diff --git a/apps/cli/package.json b/apps/cli/package.json index 4e63069..ae41076 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -1,6 +1,6 @@ { "name": "claudemesh-cli", - "version": "1.0.0-alpha.40", + "version": "1.0.0-alpha.41", "description": "Peer mesh for Claude Code sessions — CLI + MCP server.", "keywords": [ "claude-code", diff --git a/apps/cli/src/commands/join.ts b/apps/cli/src/commands/join.ts index 36edd65..cd0865e 100644 --- a/apps/cli/src/commands/join.ts +++ b/apps/cli/src/commands/join.ts @@ -111,6 +111,24 @@ export async function runJoin(args: string[]): Promise { process.exit(1); } + // Short-circuit: if the arg matches a mesh already in local config (slug + // or name), we're already joined. Don't go through the invite flow. + if (!link.includes("://")) { + const existing = readConfig().meshes.find( + (m) => m.slug === link || m.name === link, + ); + if (existing) { + console.log(`Already in "${existing.slug}" on this machine.`); + console.log(""); + console.log(`Use it in the current directory:`); + console.log(` claudemesh launch --mesh ${existing.slug}`); + console.log(""); + console.log(`Or list peers:`); + console.log(` claudemesh peers --mesh ${existing.slug}`); + return; + } + } + // Try v2 first — short code / `/i/` URL. const v2Code = parseV2InviteInput(link); if (v2Code) {