claude-team-join 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 shim52
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -4,10 +4,19 @@ Rejoin orphaned Claude Code agent teams from a new session.
4
4
 
5
5
  ## The problem
6
6
 
7
- When your Claude Code session ends terminal closed, crash, timeout any agent teams it created become orphaned. The team files stay on disk (`~/.claude/teams/`), but no session can lead them anymore. You lose your team setup, prompts, and member configs.
7
+ When your Claude Code session ends - terminal closed, crash, timeout - any agent teams it created become orphaned.
8
+
9
+ The team files stay on disk (`~/.claude/teams/`), but no session can lead them anymore.
10
+
11
+ You lose your team setup, prompts, and member configs.
8
12
 
9
13
  **claude-team-join** is an MCP server that lets Claude Code discover those orphaned teams, take over as lead, and re-spawn the teammates exactly as they were.
10
14
 
15
+ ## Requirements
16
+
17
+ - Node.js >= 18
18
+ - [Claude Code](https://docs.anthropic.com/en/docs/claude-code) CLI
19
+
11
20
  ## Install
12
21
 
13
22
  Run this in your terminal:
@@ -20,19 +29,23 @@ Then restart Claude Code (close and reopen, or run `claude` again).
20
29
 
21
30
  That's it. The tools are now available in every Claude Code session.
22
31
 
23
- > To uninstall: `npx claude-team-join --uninstall`
32
+ To uninstall:
33
+
34
+ ```bash
35
+ npx claude-team-join --uninstall
36
+ ```
24
37
 
25
38
  ## What you get
26
39
 
27
40
  Three tools become available to Claude Code:
28
41
 
29
- | Tool | What it does |
30
- |---|---|
31
- | **list_teams** | Shows all teams, their members, and whether the lead session is alive or stale |
32
- | **team_join** | Makes your current session the new lead of an orphaned team |
33
- | **get_team_members** | Returns the full config (name, role, prompt, model) for each teammate so they can be re-spawned identically |
42
+ - **`list_teams`** - Shows all teams, their members, and whether the lead session is alive or stale.
34
43
 
35
- ## How to use
44
+ - **`team_join`** - Makes your current session the new lead of an orphaned team.
45
+
46
+ - **`get_team_members`** - Returns the full config (name, role, prompt, model) for each teammate so they can be re-spawned identically.
47
+
48
+ ## Usage
36
49
 
37
50
  Once installed, just tell Claude Code what you need in plain English:
38
51
 
@@ -53,7 +66,13 @@ npm install
53
66
  npm run build
54
67
  ```
55
68
 
56
- To test locally, point your `~/.claude.json` at the local build:
69
+ Run tests:
70
+
71
+ ```bash
72
+ npm test
73
+ ```
74
+
75
+ To test locally, point your Claude Code config at the local build:
57
76
 
58
77
  ```json
59
78
  {
@@ -69,4 +88,4 @@ To test locally, point your `~/.claude.json` at the local build:
69
88
 
70
89
  ## License
71
90
 
72
- MIT
91
+ MIT - see [LICENSE](LICENSE) for details.
package/dist/cli.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ export declare function handleInstall(configPath: string): {
2
+ success: boolean;
3
+ message: string;
4
+ };
5
+ export declare function handleUninstall(configPath: string): {
6
+ success: boolean;
7
+ message: string;
8
+ };
package/dist/cli.js ADDED
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.handleInstall = handleInstall;
37
+ exports.handleUninstall = handleUninstall;
38
+ const fs = __importStar(require("fs"));
39
+ const MCP_SERVER_KEY = "claude-team-join";
40
+ function handleInstall(configPath) {
41
+ let config;
42
+ try {
43
+ const raw = fs.readFileSync(configPath, "utf-8");
44
+ try {
45
+ config = JSON.parse(raw);
46
+ }
47
+ catch {
48
+ // File exists but contains malformed JSON — do NOT overwrite
49
+ return {
50
+ success: false,
51
+ message: `Error: ${configPath} contains malformed JSON. Fix it manually before running --install.`,
52
+ };
53
+ }
54
+ }
55
+ catch {
56
+ // File doesn't exist — start fresh
57
+ config = {};
58
+ }
59
+ if (!config.mcpServers)
60
+ config.mcpServers = {};
61
+ config.mcpServers[MCP_SERVER_KEY] = {
62
+ type: "stdio",
63
+ command: "npx",
64
+ args: ["-y", "claude-team-join"],
65
+ };
66
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
67
+ return {
68
+ success: true,
69
+ message: `Added claude-team-join to ${configPath}\n Restart Claude Code to pick up the new MCP server.`,
70
+ };
71
+ }
72
+ function handleUninstall(configPath) {
73
+ let config;
74
+ try {
75
+ const raw = fs.readFileSync(configPath, "utf-8");
76
+ config = JSON.parse(raw);
77
+ }
78
+ catch {
79
+ return {
80
+ success: true,
81
+ message: `claude-team-join is not configured in ${configPath}`,
82
+ };
83
+ }
84
+ if (config.mcpServers?.[MCP_SERVER_KEY]) {
85
+ delete config.mcpServers[MCP_SERVER_KEY];
86
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
87
+ return {
88
+ success: true,
89
+ message: `Removed claude-team-join from ${configPath}`,
90
+ };
91
+ }
92
+ return {
93
+ success: true,
94
+ message: `claude-team-join is not configured in ${configPath}`,
95
+ };
96
+ }
97
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,sCAiCC;AAED,0CA0BC;AAjED,uCAAyB;AAEzB,MAAM,cAAc,GAAG,kBAAkB,CAAC;AAE1C,SAAgB,aAAa,CAAC,UAAkB;IAC9C,IAAI,MAA2B,CAAC;IAEhC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACjD,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,6DAA6D;YAC7D,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,UAAU,UAAU,qEAAqE;aACnG,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,mCAAmC;QACnC,MAAM,GAAG,EAAE,CAAC;IACd,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,UAAU;QAAE,MAAM,CAAC,UAAU,GAAG,EAAE,CAAC;IAE/C,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG;QAClC,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,KAAK;QACd,IAAI,EAAE,CAAC,IAAI,EAAE,kBAAkB,CAAC;KACjC,CAAC;IAEF,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;IAE9E,OAAO;QACL,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,6BAA6B,UAAU,wDAAwD;KACzG,CAAC;AACJ,CAAC;AAED,SAAgB,eAAe,CAAC,UAAkB;IAChD,IAAI,MAA2B,CAAC;IAEhC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACjD,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,yCAAyC,UAAU,EAAE;SAC/D,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC,cAAc,CAAC,EAAE,CAAC;QACxC,OAAO,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;QACzC,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;QAC9E,OAAO;YACL,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,iCAAiC,UAAU,EAAE;SACvD,CAAC;IACJ,CAAC;IAED,OAAO;QACL,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,yCAAyC,UAAU,EAAE;KAC/D,CAAC;AACJ,CAAC"}
@@ -0,0 +1,35 @@
1
+ export interface TeamMember {
2
+ agentId: string;
3
+ name: string;
4
+ agentType: string;
5
+ model?: string;
6
+ prompt?: string;
7
+ color?: string;
8
+ planModeRequired?: boolean;
9
+ joinedAt: number;
10
+ tmuxPaneId?: string;
11
+ cwd?: string;
12
+ subscriptions?: string[];
13
+ backendType?: string;
14
+ isActive?: boolean;
15
+ }
16
+ export interface TeamConfig {
17
+ name: string;
18
+ description?: string;
19
+ createdAt: number;
20
+ leadAgentId: string;
21
+ leadSessionId: string;
22
+ members: TeamMember[];
23
+ }
24
+ export declare function createHelpers(homeDir: string): {
25
+ getTeamNames: () => string[];
26
+ readTeamConfig: (teamName: string) => TeamConfig | null;
27
+ writeTeamConfig: (teamName: string, config: TeamConfig) => void;
28
+ getCurrentSessionId: () => string | null;
29
+ isSessionActive: (sessionId: string) => boolean;
30
+ formatTimestamp: (ts: number) => string;
31
+ CLAUDE_CONFIG_PATH: string;
32
+ TEAMS_DIR: string;
33
+ SESSION_ENV_DIR: string;
34
+ };
35
+ export type Helpers = ReturnType<typeof createHelpers>;
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.createHelpers = createHelpers;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ function isValidTeamName(name) {
40
+ return name.length > 0 && !/[\/\\]|\.\./.test(name);
41
+ }
42
+ function createHelpers(homeDir) {
43
+ const CLAUDE_DIR = path.join(homeDir, ".claude");
44
+ const TEAMS_DIR = path.join(CLAUDE_DIR, "teams");
45
+ const SESSION_ENV_DIR = path.join(CLAUDE_DIR, "session-env");
46
+ const CLAUDE_CONFIG_PATH = path.join(homeDir, ".claude.json");
47
+ function getTeamNames() {
48
+ try {
49
+ return fs
50
+ .readdirSync(TEAMS_DIR, { withFileTypes: true })
51
+ .filter((d) => d.isDirectory())
52
+ .map((d) => d.name);
53
+ }
54
+ catch {
55
+ return [];
56
+ }
57
+ }
58
+ function readTeamConfig(teamName) {
59
+ if (!isValidTeamName(teamName)) {
60
+ return null;
61
+ }
62
+ const configPath = path.join(TEAMS_DIR, teamName, "config.json");
63
+ try {
64
+ const raw = fs.readFileSync(configPath, "utf-8");
65
+ const parsed = JSON.parse(raw);
66
+ // Validate required fields
67
+ if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.members)) {
68
+ return null;
69
+ }
70
+ return parsed;
71
+ }
72
+ catch (err) {
73
+ if (err instanceof Error && "code" in err && err.code === "ENOENT") {
74
+ return null;
75
+ }
76
+ // Log non-ENOENT errors (e.g. permission denied) so they aren't silently lost
77
+ process.stderr.write(`Warning: failed to read team config for "${teamName}": ${err instanceof Error ? err.message : String(err)}\n`);
78
+ return null;
79
+ }
80
+ }
81
+ function writeTeamConfig(teamName, config) {
82
+ if (!isValidTeamName(teamName)) {
83
+ throw new Error(`Invalid team name: "${teamName}"`);
84
+ }
85
+ const configPath = path.join(TEAMS_DIR, teamName, "config.json");
86
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 4), "utf-8");
87
+ }
88
+ function getCurrentSessionId() {
89
+ try {
90
+ const entries = fs.readdirSync(SESSION_ENV_DIR, { withFileTypes: true });
91
+ let newest = null;
92
+ for (const entry of entries) {
93
+ if (!entry.isDirectory())
94
+ continue;
95
+ const stat = fs.statSync(path.join(SESSION_ENV_DIR, entry.name));
96
+ if (!newest || stat.mtimeMs > newest.mtimeMs) {
97
+ newest = { name: entry.name, mtimeMs: stat.mtimeMs };
98
+ }
99
+ }
100
+ return newest?.name ?? null;
101
+ }
102
+ catch {
103
+ return null;
104
+ }
105
+ }
106
+ function isSessionActive(sessionId) {
107
+ const sessionDir = path.join(SESSION_ENV_DIR, sessionId);
108
+ try {
109
+ const stat = fs.statSync(sessionDir);
110
+ const ageMs = Date.now() - stat.mtimeMs;
111
+ // Consider a session "active" if modified in the last 5 minutes
112
+ return ageMs < 5 * 60 * 1000;
113
+ }
114
+ catch {
115
+ return false;
116
+ }
117
+ }
118
+ function formatTimestamp(ts) {
119
+ return new Date(ts).toISOString().replace("T", " ").replace(/\.\d+Z$/, " UTC");
120
+ }
121
+ return {
122
+ getTeamNames,
123
+ readTeamConfig,
124
+ writeTeamConfig,
125
+ getCurrentSessionId,
126
+ isSessionActive,
127
+ formatTimestamp,
128
+ CLAUDE_CONFIG_PATH,
129
+ TEAMS_DIR,
130
+ SESSION_ENV_DIR,
131
+ };
132
+ }
133
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -37,271 +37,36 @@ Object.defineProperty(exports, "__esModule", { value: true });
37
37
  const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
38
38
  const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
39
39
  const zod_1 = require("zod");
40
- const fs = __importStar(require("fs"));
41
- const path = __importStar(require("path"));
42
40
  const os = __importStar(require("os"));
43
- // --- Helpers ---
44
- const CLAUDE_DIR = path.join(os.homedir(), ".claude");
45
- const TEAMS_DIR = path.join(CLAUDE_DIR, "teams");
46
- const SESSION_ENV_DIR = path.join(CLAUDE_DIR, "session-env");
47
- function getTeamNames() {
48
- try {
49
- return fs
50
- .readdirSync(TEAMS_DIR, { withFileTypes: true })
51
- .filter((d) => d.isDirectory())
52
- .map((d) => d.name);
53
- }
54
- catch {
55
- return [];
56
- }
57
- }
58
- function readTeamConfig(teamName) {
59
- const configPath = path.join(TEAMS_DIR, teamName, "config.json");
60
- try {
61
- const raw = fs.readFileSync(configPath, "utf-8");
62
- return JSON.parse(raw);
63
- }
64
- catch {
65
- return null;
66
- }
67
- }
68
- function writeTeamConfig(teamName, config) {
69
- const configPath = path.join(TEAMS_DIR, teamName, "config.json");
70
- fs.writeFileSync(configPath, JSON.stringify(config, null, 4), "utf-8");
71
- }
72
- function getCurrentSessionId() {
73
- try {
74
- const entries = fs.readdirSync(SESSION_ENV_DIR, { withFileTypes: true });
75
- let newest = null;
76
- for (const entry of entries) {
77
- if (!entry.isDirectory())
78
- continue;
79
- const stat = fs.statSync(path.join(SESSION_ENV_DIR, entry.name));
80
- if (!newest || stat.mtimeMs > newest.mtimeMs) {
81
- newest = { name: entry.name, mtimeMs: stat.mtimeMs };
82
- }
83
- }
84
- return newest?.name ?? null;
85
- }
86
- catch {
87
- return null;
88
- }
89
- }
90
- function isSessionActive(sessionId) {
91
- const sessionDir = path.join(SESSION_ENV_DIR, sessionId);
92
- try {
93
- const stat = fs.statSync(sessionDir);
94
- const ageMs = Date.now() - stat.mtimeMs;
95
- // Consider a session "active" if modified in the last 5 minutes
96
- return ageMs < 5 * 60 * 1000;
97
- }
98
- catch {
99
- return false;
100
- }
101
- }
102
- function formatTimestamp(ts) {
103
- return new Date(ts).toISOString().replace("T", " ").replace(/\.\d+Z$/, " UTC");
104
- }
41
+ const helpers_js_1 = require("./helpers.js");
42
+ const cli_js_1 = require("./cli.js");
43
+ const tools_js_1 = require("./tools.js");
105
44
  // --- CLI: --install / --uninstall ---
106
- const CLAUDE_CONFIG_PATH = path.join(os.homedir(), ".claude.json");
107
- const MCP_SERVER_KEY = "claude-team-join";
108
- function readClaudeConfig() {
109
- try {
110
- return JSON.parse(fs.readFileSync(CLAUDE_CONFIG_PATH, "utf-8"));
111
- }
112
- catch {
113
- return {};
114
- }
45
+ const helpers = (0, helpers_js_1.createHelpers)(os.homedir());
46
+ const arg = process.argv[2];
47
+ if (arg === "--install" || arg === "install") {
48
+ const result = (0, cli_js_1.handleInstall)(helpers.CLAUDE_CONFIG_PATH);
49
+ console.log(result.success ? `\u2713 ${result.message}` : result.message);
50
+ process.exit(result.success ? 0 : 1);
115
51
  }
116
- function writeClaudeConfig(config) {
117
- fs.writeFileSync(CLAUDE_CONFIG_PATH, JSON.stringify(config, null, 2) + "\n", "utf-8");
52
+ if (arg === "--uninstall" || arg === "uninstall") {
53
+ const result = (0, cli_js_1.handleUninstall)(helpers.CLAUDE_CONFIG_PATH);
54
+ console.log(result.success ? `\u2713 ${result.message}` : result.message);
55
+ process.exit(result.success ? 0 : 1);
118
56
  }
119
- function handleInstall() {
120
- const config = readClaudeConfig();
121
- if (!config.mcpServers)
122
- config.mcpServers = {};
123
- config.mcpServers[MCP_SERVER_KEY] = {
124
- type: "stdio",
125
- command: "npx",
126
- args: ["-y", "claude-team-join"],
127
- };
128
- writeClaudeConfig(config);
129
- console.log("✓ Added claude-team-join to ~/.claude.json");
130
- console.log(" Restart Claude Code to pick up the new MCP server.");
131
- process.exit(0);
132
- }
133
- function handleUninstall() {
134
- const config = readClaudeConfig();
135
- if (config.mcpServers?.[MCP_SERVER_KEY]) {
136
- delete config.mcpServers[MCP_SERVER_KEY];
137
- writeClaudeConfig(config);
138
- console.log("✓ Removed claude-team-join from ~/.claude.json");
139
- }
140
- else {
141
- console.log("claude-team-join is not configured in ~/.claude.json");
142
- }
143
- process.exit(0);
144
- }
145
- const arg = process.argv[2];
146
- if (arg === "--install" || arg === "install")
147
- handleInstall();
148
- if (arg === "--uninstall" || arg === "uninstall")
149
- handleUninstall();
150
57
  // --- MCP Server ---
151
58
  const server = new mcp_js_1.McpServer({
152
59
  name: "claude-team-join",
153
- version: "1.0.0",
154
- });
155
- // Tool 1: list_teams
156
- server.tool("list_teams", "List all Claude Code teams with their status, members, and whether the lead session is stale or current", {}, async () => {
157
- const teamNames = getTeamNames();
158
- if (teamNames.length === 0) {
159
- return {
160
- content: [
161
- {
162
- type: "text",
163
- text: "No teams found in ~/.claude/teams/",
164
- },
165
- ],
166
- };
167
- }
168
- const currentSessionId = getCurrentSessionId();
169
- const teams = [];
170
- for (const name of teamNames) {
171
- const config = readTeamConfig(name);
172
- if (!config)
173
- continue;
174
- const isCurrentSession = config.leadSessionId === currentSessionId;
175
- const isActive = isSessionActive(config.leadSessionId);
176
- const members = config.members.map((m) => ({
177
- name: m.name,
178
- role: m.agentType,
179
- isActive: m.isActive ?? false,
180
- }));
181
- teams.push({
182
- teamName: name,
183
- description: config.description ?? "(no description)",
184
- createdAt: formatTimestamp(config.createdAt),
185
- memberCount: config.members.length,
186
- members,
187
- leadSessionId: config.leadSessionId,
188
- leadSessionStatus: isCurrentSession
189
- ? "current"
190
- : isActive
191
- ? "active-other"
192
- : "stale",
193
- });
194
- }
195
- return {
196
- content: [
197
- {
198
- type: "text",
199
- text: JSON.stringify(teams, null, 2),
200
- },
201
- ],
202
- };
60
+ version: "1.2.0",
203
61
  });
204
- // Tool 2: team_join
62
+ const toolHandlers = (0, tools_js_1.createToolHandlers)(helpers);
63
+ server.tool("list_teams", "List all Claude Code teams with their status, members, and whether the lead session is stale or current", {}, toolHandlers.listTeams);
205
64
  server.tool("team_join", "Rejoin an existing team by updating its config to point to the current session. This makes you the new team lead.", {
206
- team_name: zod_1.z.string().describe("Name of the team to rejoin"),
207
- }, async ({ team_name }) => {
208
- const config = readTeamConfig(team_name);
209
- if (!config) {
210
- return {
211
- content: [
212
- {
213
- type: "text",
214
- text: `Error: Team "${team_name}" not found. Use list_teams to see available teams.`,
215
- },
216
- ],
217
- isError: true,
218
- };
219
- }
220
- const currentSessionId = getCurrentSessionId();
221
- if (!currentSessionId) {
222
- return {
223
- content: [
224
- {
225
- type: "text",
226
- text: "Error: Could not detect current session ID from ~/.claude/session-env/",
227
- },
228
- ],
229
- isError: true,
230
- };
231
- }
232
- const previousSessionId = config.leadSessionId;
233
- // Update the lead session to current
234
- config.leadSessionId = currentSessionId;
235
- config.leadAgentId = `team-lead@${team_name}`;
236
- // Reset all members' isActive to false (they need to be re-spawned)
237
- for (const member of config.members) {
238
- member.isActive = false;
239
- }
240
- writeTeamConfig(team_name, config);
241
- const nonLeadMembers = config.members.filter((m) => m.name !== "team-lead");
242
- return {
243
- content: [
244
- {
245
- type: "text",
246
- text: JSON.stringify({
247
- status: "joined",
248
- teamName: team_name,
249
- description: config.description,
250
- previousSessionId,
251
- newSessionId: currentSessionId,
252
- membersResetToInactive: config.members.length,
253
- teammatesReadyToRespawn: nonLeadMembers.map((m) => ({
254
- name: m.name,
255
- role: m.agentType,
256
- hasPrompt: !!m.prompt,
257
- })),
258
- }, null, 2),
259
- },
260
- ],
261
- };
262
- });
263
- // Tool 3: get_team_members
65
+ team_name: zod_1.z.string().regex(/^[a-zA-Z0-9_\- ]+$/).describe("Name of the team to rejoin"),
66
+ }, toolHandlers.teamJoin);
264
67
  server.tool("get_team_members", "Get full teammate definitions (name, role, prompt, model) so they can be re-spawned with the Task tool using identical configurations", {
265
- team_name: zod_1.z.string().describe("Name of the team to get members from"),
266
- }, async ({ team_name }) => {
267
- const config = readTeamConfig(team_name);
268
- if (!config) {
269
- return {
270
- content: [
271
- {
272
- type: "text",
273
- text: `Error: Team "${team_name}" not found. Use list_teams to see available teams.`,
274
- },
275
- ],
276
- isError: true,
277
- };
278
- }
279
- // Return non-lead members with their full spawn configurations
280
- const teammates = config.members
281
- .filter((m) => m.name !== "team-lead")
282
- .map((m) => ({
283
- name: m.name,
284
- agentType: m.agentType,
285
- model: m.model,
286
- prompt: m.prompt,
287
- color: m.color,
288
- planModeRequired: m.planModeRequired ?? false,
289
- cwd: m.cwd,
290
- previousAgentId: m.agentId,
291
- }));
292
- return {
293
- content: [
294
- {
295
- type: "text",
296
- text: JSON.stringify({
297
- teamName: team_name,
298
- description: config.description,
299
- teammates,
300
- }, null, 2),
301
- },
302
- ],
303
- };
304
- });
68
+ team_name: zod_1.z.string().regex(/^[a-zA-Z0-9_\- ]+$/).describe("Name of the team to get members from"),
69
+ }, toolHandlers.getTeamMembers);
305
70
  // --- Start Server ---
306
71
  async function main() {
307
72
  const transport = new stdio_js_1.StdioServerTransport();
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,oEAAoE;AACpE,wEAAiF;AACjF,6BAAwB;AACxB,uCAAyB;AAEzB,6CAA6C;AAC7C,qCAA0D;AAC1D,yCAAgD;AAEhD,uCAAuC;AAEvC,MAAM,OAAO,GAAG,IAAA,0BAAa,EAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;AAE5C,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC5B,IAAI,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;IAC7C,MAAM,MAAM,GAAG,IAAA,sBAAa,EAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACzD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC1E,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvC,CAAC;AACD,IAAI,GAAG,KAAK,aAAa,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;IACjD,MAAM,MAAM,GAAG,IAAA,wBAAe,EAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC3D,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC1E,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,qBAAqB;AAErB,MAAM,MAAM,GAAG,IAAI,kBAAS,CAAC;IAC3B,IAAI,EAAE,kBAAkB;IACxB,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,IAAA,6BAAkB,EAAC,OAAO,CAAC,CAAC;AAEjD,MAAM,CAAC,IAAI,CACT,YAAY,EACZ,yGAAyG,EACzG,EAAE,EACF,YAAY,CAAC,SAAS,CACvB,CAAC;AAEF,MAAM,CAAC,IAAI,CACT,WAAW,EACX,mHAAmH,EACnH;IACE,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,QAAQ,CAAC,4BAA4B,CAAC;CACzF,EACD,YAAY,CAAC,QAAQ,CACtB,CAAC;AAEF,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,uIAAuI,EACvI;IACE,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,QAAQ,CAAC,sCAAsC,CAAC;CACnG,EACD,YAAY,CAAC,cAAc,CAC5B,CAAC;AAEF,uBAAuB;AAEvB,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,+BAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;IACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,39 @@
1
+ import type { Helpers } from "./helpers.js";
2
+ export declare function createToolHandlers(helpers: Helpers): {
3
+ listTeams: () => Promise<{
4
+ content: {
5
+ type: "text";
6
+ text: string;
7
+ }[];
8
+ }>;
9
+ teamJoin: ({ team_name }: {
10
+ team_name: string;
11
+ }) => Promise<{
12
+ content: {
13
+ type: "text";
14
+ text: string;
15
+ }[];
16
+ isError: boolean;
17
+ } | {
18
+ content: {
19
+ type: "text";
20
+ text: string;
21
+ }[];
22
+ isError?: undefined;
23
+ }>;
24
+ getTeamMembers: ({ team_name }: {
25
+ team_name: string;
26
+ }) => Promise<{
27
+ content: {
28
+ type: "text";
29
+ text: string;
30
+ }[];
31
+ isError: boolean;
32
+ } | {
33
+ content: {
34
+ type: "text";
35
+ text: string;
36
+ }[];
37
+ isError?: undefined;
38
+ }>;
39
+ };
package/dist/tools.js ADDED
@@ -0,0 +1,164 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createToolHandlers = createToolHandlers;
4
+ function createToolHandlers(helpers) {
5
+ return {
6
+ listTeams: async () => {
7
+ const teamNames = helpers.getTeamNames();
8
+ if (teamNames.length === 0) {
9
+ return {
10
+ content: [
11
+ {
12
+ type: "text",
13
+ text: `No teams found in ${helpers.TEAMS_DIR}`,
14
+ },
15
+ ],
16
+ };
17
+ }
18
+ const currentSessionId = helpers.getCurrentSessionId();
19
+ const teams = [];
20
+ for (const name of teamNames) {
21
+ const config = helpers.readTeamConfig(name);
22
+ if (!config)
23
+ continue;
24
+ const isCurrentSession = config.leadSessionId === currentSessionId;
25
+ const isActive = helpers.isSessionActive(config.leadSessionId);
26
+ const members = config.members.map((m) => ({
27
+ name: m.name,
28
+ role: m.agentType,
29
+ isActive: m.isActive ?? false,
30
+ }));
31
+ teams.push({
32
+ teamName: name,
33
+ description: config.description ?? "(no description)",
34
+ createdAt: helpers.formatTimestamp(config.createdAt),
35
+ memberCount: config.members.length,
36
+ members,
37
+ leadSessionId: config.leadSessionId,
38
+ leadSessionStatus: isCurrentSession
39
+ ? "current"
40
+ : isActive
41
+ ? "active-other"
42
+ : "stale",
43
+ });
44
+ }
45
+ return {
46
+ content: [
47
+ {
48
+ type: "text",
49
+ text: JSON.stringify(teams, null, 2),
50
+ },
51
+ ],
52
+ };
53
+ },
54
+ teamJoin: async ({ team_name }) => {
55
+ const config = helpers.readTeamConfig(team_name);
56
+ if (!config) {
57
+ return {
58
+ content: [
59
+ {
60
+ type: "text",
61
+ text: `Error: Team "${team_name}" not found. Use list_teams to see available teams.`,
62
+ },
63
+ ],
64
+ isError: true,
65
+ };
66
+ }
67
+ const currentSessionId = helpers.getCurrentSessionId();
68
+ if (!currentSessionId) {
69
+ return {
70
+ content: [
71
+ {
72
+ type: "text",
73
+ text: `Error: Could not detect current session ID from ${helpers.SESSION_ENV_DIR}`,
74
+ },
75
+ ],
76
+ isError: true,
77
+ };
78
+ }
79
+ const previousSessionId = config.leadSessionId;
80
+ // Update the lead session to current
81
+ config.leadSessionId = currentSessionId;
82
+ config.leadAgentId = `team-lead@${team_name}`;
83
+ // Reset all members' isActive to false (they need to be re-spawned)
84
+ for (const member of config.members) {
85
+ member.isActive = false;
86
+ }
87
+ try {
88
+ helpers.writeTeamConfig(team_name, config);
89
+ }
90
+ catch (err) {
91
+ return {
92
+ content: [
93
+ {
94
+ type: "text",
95
+ text: `Error: Failed to write team config: ${err instanceof Error ? err.message : String(err)}`,
96
+ },
97
+ ],
98
+ isError: true,
99
+ };
100
+ }
101
+ const nonLeadMembers = config.members.filter((m) => m.name !== "team-lead");
102
+ return {
103
+ content: [
104
+ {
105
+ type: "text",
106
+ text: JSON.stringify({
107
+ status: "joined",
108
+ teamName: team_name,
109
+ description: config.description,
110
+ previousSessionId,
111
+ newSessionId: currentSessionId,
112
+ membersResetToInactive: config.members.length,
113
+ teammatesReadyToRespawn: nonLeadMembers.map((m) => ({
114
+ name: m.name,
115
+ role: m.agentType,
116
+ hasPrompt: !!m.prompt,
117
+ })),
118
+ }, null, 2),
119
+ },
120
+ ],
121
+ };
122
+ },
123
+ getTeamMembers: async ({ team_name }) => {
124
+ const config = helpers.readTeamConfig(team_name);
125
+ if (!config) {
126
+ return {
127
+ content: [
128
+ {
129
+ type: "text",
130
+ text: `Error: Team "${team_name}" not found. Use list_teams to see available teams.`,
131
+ },
132
+ ],
133
+ isError: true,
134
+ };
135
+ }
136
+ // Return non-lead members with their full spawn configurations
137
+ const teammates = config.members
138
+ .filter((m) => m.name !== "team-lead")
139
+ .map((m) => ({
140
+ name: m.name,
141
+ agentType: m.agentType,
142
+ model: m.model,
143
+ prompt: m.prompt,
144
+ color: m.color,
145
+ planModeRequired: m.planModeRequired ?? false,
146
+ cwd: m.cwd,
147
+ previousAgentId: m.agentId,
148
+ }));
149
+ return {
150
+ content: [
151
+ {
152
+ type: "text",
153
+ text: JSON.stringify({
154
+ teamName: team_name,
155
+ description: config.description,
156
+ teammates,
157
+ }, null, 2),
158
+ },
159
+ ],
160
+ };
161
+ },
162
+ };
163
+ }
164
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,16 +1,18 @@
1
1
  {
2
2
  "name": "claude-team-join",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "MCP server for listing, inspecting, and rejoining orphaned Claude Code teams",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
7
7
  "claude-team-join": "dist/index.js"
8
8
  },
9
9
  "scripts": {
10
- "build": "tsc",
10
+ "build": "tsc && chmod +x dist/index.js",
11
11
  "prepublishOnly": "npm run build",
12
12
  "start": "node dist/index.js",
13
- "dev": "tsx src/index.ts"
13
+ "dev": "tsx src/index.ts",
14
+ "test": "vitest run",
15
+ "test:watch": "vitest"
14
16
  },
15
17
  "keywords": [
16
18
  "claude-code",
@@ -29,12 +31,14 @@
29
31
  "url": "https://github.com/shim52/claude-code-agent-teams-join/issues"
30
32
  },
31
33
  "dependencies": {
32
- "@modelcontextprotocol/sdk": "^1.12.1"
34
+ "@modelcontextprotocol/sdk": "^1.12.1",
35
+ "zod": "^3.23.0"
33
36
  },
34
37
  "devDependencies": {
35
38
  "typescript": "^5.7.0",
36
39
  "@types/node": "^22.0.0",
37
- "tsx": "^4.19.0"
40
+ "tsx": "^4.19.0",
41
+ "vitest": "^2.0.0"
38
42
  },
39
43
  "engines": {
40
44
  "node": ">=18"