claude-team-join 1.2.0 → 2.0.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/README.md +14 -20
- package/dist/cli.d.ts +2 -2
- package/dist/cli.js +22 -48
- package/dist/cli.js.map +1 -1
- package/dist/index.js +6 -31
- package/dist/index.js.map +1 -1
- package/dist/skills.d.ts +5 -0
- package/dist/skills.js +192 -0
- package/dist/skills.js.map +1 -0
- package/package.json +4 -7
- package/dist/helpers.d.ts +0 -35
- package/dist/helpers.js +0 -133
- package/dist/helpers.js.map +0 -1
- package/dist/tools.d.ts +0 -39
- package/dist/tools.js +0 -164
- package/dist/tools.js.map +0 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ The team files stay on disk (`~/.claude/teams/`), but no session can lead them a
|
|
|
10
10
|
|
|
11
11
|
You lose your team setup, prompts, and member configs.
|
|
12
12
|
|
|
13
|
-
**claude-team-join**
|
|
13
|
+
**claude-team-join** installs skills that let Claude Code discover those orphaned teams, take over as lead, and re-spawn the teammates exactly as they were.
|
|
14
14
|
|
|
15
15
|
## Requirements
|
|
16
16
|
|
|
@@ -27,7 +27,7 @@ npx claude-team-join --install
|
|
|
27
27
|
|
|
28
28
|
Then restart Claude Code (close and reopen, or run `claude` again).
|
|
29
29
|
|
|
30
|
-
That's it. The
|
|
30
|
+
That's it. The skills are now available in every Claude Code session.
|
|
31
31
|
|
|
32
32
|
To uninstall:
|
|
33
33
|
|
|
@@ -37,25 +37,25 @@ npx claude-team-join --uninstall
|
|
|
37
37
|
|
|
38
38
|
## What you get
|
|
39
39
|
|
|
40
|
-
Three
|
|
40
|
+
Three skills are installed to `~/.claude/skills/`:
|
|
41
41
|
|
|
42
|
-
- **`
|
|
42
|
+
- **`team-join`** - Rejoins an orphaned team by making your current session the new lead.
|
|
43
43
|
|
|
44
|
-
- **`
|
|
44
|
+
- **`team-list`** - Shows all teams, their members, and whether the lead session is alive or stale.
|
|
45
45
|
|
|
46
|
-
- **`
|
|
46
|
+
- **`team-members`** - Returns the full config (name, role, prompt, model) for each teammate so they can be re-spawned identically.
|
|
47
47
|
|
|
48
48
|
## Usage
|
|
49
49
|
|
|
50
50
|
Once installed, just tell Claude Code what you need in plain English:
|
|
51
51
|
|
|
52
52
|
```
|
|
53
|
-
"Show me my orphaned teams"
|
|
54
53
|
"Rejoin the my-project team"
|
|
54
|
+
"Show me my orphaned teams"
|
|
55
55
|
"Re-spawn all the teammates from my-project"
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
Claude Code will
|
|
58
|
+
Claude Code will match the appropriate skill automatically.
|
|
59
59
|
|
|
60
60
|
## Contributing
|
|
61
61
|
|
|
@@ -72,20 +72,14 @@ Run tests:
|
|
|
72
72
|
npm test
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
To test locally
|
|
76
|
-
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
"mcpServers": {
|
|
80
|
-
"claude-team-join": {
|
|
81
|
-
"type": "stdio",
|
|
82
|
-
"command": "node",
|
|
83
|
-
"args": ["/absolute/path/to/claude-code-agent-teams-join/dist/index.js"]
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
75
|
+
To test locally:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
node dist/index.js --install
|
|
87
79
|
```
|
|
88
80
|
|
|
81
|
+
Then restart Claude Code and try commands like "rejoin the my-team team".
|
|
82
|
+
|
|
89
83
|
## License
|
|
90
84
|
|
|
91
85
|
MIT - see [LICENSE](LICENSE) for details.
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export declare function handleInstall(
|
|
1
|
+
export declare function handleInstall(skillsDir: string): {
|
|
2
2
|
success: boolean;
|
|
3
3
|
message: string;
|
|
4
4
|
};
|
|
5
|
-
export declare function handleUninstall(
|
|
5
|
+
export declare function handleUninstall(skillsDir: string): {
|
|
6
6
|
success: boolean;
|
|
7
7
|
message: string;
|
|
8
8
|
};
|
package/dist/cli.js
CHANGED
|
@@ -36,62 +36,36 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.handleInstall = handleInstall;
|
|
37
37
|
exports.handleUninstall = handleUninstall;
|
|
38
38
|
const fs = __importStar(require("fs"));
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
|
|
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 = {};
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const skills_js_1 = require("./skills.js");
|
|
41
|
+
function handleInstall(skillsDir) {
|
|
42
|
+
fs.mkdirSync(skillsDir, { recursive: true });
|
|
43
|
+
const installed = [];
|
|
44
|
+
for (const skill of skills_js_1.SKILLS) {
|
|
45
|
+
const dir = path.join(skillsDir, skill.dirName);
|
|
46
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
47
|
+
fs.writeFileSync(path.join(dir, "SKILL.md"), skill.content, "utf-8");
|
|
48
|
+
installed.push(skill.dirName);
|
|
58
49
|
}
|
|
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
50
|
return {
|
|
68
51
|
success: true,
|
|
69
|
-
message: `
|
|
52
|
+
message: `Installed skills to ${skillsDir}: ${installed.join(", ")}\n Restart Claude Code to pick up the new skills.`,
|
|
70
53
|
};
|
|
71
54
|
}
|
|
72
|
-
function handleUninstall(
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
-
};
|
|
55
|
+
function handleUninstall(skillsDir) {
|
|
56
|
+
const removed = [];
|
|
57
|
+
for (const skill of skills_js_1.SKILLS) {
|
|
58
|
+
const dir = path.join(skillsDir, skill.dirName);
|
|
59
|
+
if (fs.existsSync(dir)) {
|
|
60
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
61
|
+
removed.push(skill.dirName);
|
|
62
|
+
}
|
|
91
63
|
}
|
|
92
64
|
return {
|
|
93
65
|
success: true,
|
|
94
|
-
message:
|
|
66
|
+
message: removed.length > 0
|
|
67
|
+
? `Removed skills from ${skillsDir}: ${removed.join(", ")}`
|
|
68
|
+
: `No claude-team-join skills found in ${skillsDir}`,
|
|
95
69
|
};
|
|
96
70
|
}
|
|
97
71
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,sCAgBC;AAED,0CAiBC;AAvCD,uCAAyB;AACzB,2CAA6B;AAC7B,2CAAqC;AAErC,SAAgB,aAAa,CAAC,SAAiB;IAC7C,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE7C,MAAM,SAAS,GAAa,EAAE,CAAC;IAE/B,KAAK,MAAM,KAAK,IAAI,kBAAM,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAChD,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvC,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACrE,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAED,OAAO;QACL,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,uBAAuB,SAAS,KAAK,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,oDAAoD;KACvH,CAAC;AACJ,CAAC;AAED,SAAgB,eAAe,CAAC,SAAiB;IAC/C,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,MAAM,KAAK,IAAI,kBAAM,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAChD,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACjD,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC;YACzB,CAAC,CAAC,uBAAuB,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YAC3D,CAAC,CAAC,uCAAuC,SAAS,EAAE;KACvD,CAAC;AACJ,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -34,46 +34,21 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
};
|
|
35
35
|
})();
|
|
36
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
-
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
38
|
-
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
39
|
-
const zod_1 = require("zod");
|
|
40
37
|
const os = __importStar(require("os"));
|
|
41
|
-
const
|
|
38
|
+
const path = __importStar(require("path"));
|
|
42
39
|
const cli_js_1 = require("./cli.js");
|
|
43
|
-
const
|
|
44
|
-
// --- CLI: --install / --uninstall ---
|
|
45
|
-
const helpers = (0, helpers_js_1.createHelpers)(os.homedir());
|
|
40
|
+
const skillsDir = path.join(os.homedir(), ".claude", "skills");
|
|
46
41
|
const arg = process.argv[2];
|
|
47
42
|
if (arg === "--install" || arg === "install") {
|
|
48
|
-
const result = (0, cli_js_1.handleInstall)(
|
|
43
|
+
const result = (0, cli_js_1.handleInstall)(skillsDir);
|
|
49
44
|
console.log(result.success ? `\u2713 ${result.message}` : result.message);
|
|
50
45
|
process.exit(result.success ? 0 : 1);
|
|
51
46
|
}
|
|
52
47
|
if (arg === "--uninstall" || arg === "uninstall") {
|
|
53
|
-
const result = (0, cli_js_1.handleUninstall)(
|
|
48
|
+
const result = (0, cli_js_1.handleUninstall)(skillsDir);
|
|
54
49
|
console.log(result.success ? `\u2713 ${result.message}` : result.message);
|
|
55
50
|
process.exit(result.success ? 0 : 1);
|
|
56
51
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
name: "claude-team-join",
|
|
60
|
-
version: "1.2.0",
|
|
61
|
-
});
|
|
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);
|
|
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.", {
|
|
65
|
-
team_name: zod_1.z.string().regex(/^[a-zA-Z0-9_\- ]+$/).describe("Name of the team to rejoin"),
|
|
66
|
-
}, toolHandlers.teamJoin);
|
|
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", {
|
|
68
|
-
team_name: zod_1.z.string().regex(/^[a-zA-Z0-9_\- ]+$/).describe("Name of the team to get members from"),
|
|
69
|
-
}, toolHandlers.getTeamMembers);
|
|
70
|
-
// --- Start Server ---
|
|
71
|
-
async function main() {
|
|
72
|
-
const transport = new stdio_js_1.StdioServerTransport();
|
|
73
|
-
await server.connect(transport);
|
|
74
|
-
}
|
|
75
|
-
main().catch((err) => {
|
|
76
|
-
console.error("Fatal error:", err);
|
|
77
|
-
process.exit(1);
|
|
78
|
-
});
|
|
52
|
+
console.log("Usage: claude-team-join --install | --uninstall");
|
|
53
|
+
process.exit(0);
|
|
79
54
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,uCAAyB;AACzB,2CAA6B;AAC7B,qCAA0D;AAE1D,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AAC/D,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAE5B,IAAI,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;IAC7C,MAAM,MAAM,GAAG,IAAA,sBAAa,EAAC,SAAS,CAAC,CAAC;IACxC,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,IAAI,GAAG,KAAK,aAAa,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;IACjD,MAAM,MAAM,GAAG,IAAA,wBAAe,EAAC,SAAS,CAAC,CAAC;IAC1C,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,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;AAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC"}
|
package/dist/skills.d.ts
ADDED
package/dist/skills.js
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SKILLS = void 0;
|
|
4
|
+
exports.SKILLS = [
|
|
5
|
+
{
|
|
6
|
+
dirName: "team-join",
|
|
7
|
+
content: `---
|
|
8
|
+
name: team-join
|
|
9
|
+
description: Rejoin an orphaned Claude Code agent team. Use when user says "rejoin team", "join team", "reconnect team", "resume team", "rejoin the <name> team", or wants to become the lead of an existing team.
|
|
10
|
+
allowed-tools: Read, Write, Bash, Glob
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Rejoin an Orphaned Claude Code Team
|
|
14
|
+
|
|
15
|
+
You are helping the user rejoin an orphaned Claude Code agent team. Follow these steps precisely.
|
|
16
|
+
|
|
17
|
+
## Step 1: Identify the team
|
|
18
|
+
|
|
19
|
+
If the user specified a team name, use that. Otherwise, list available teams:
|
|
20
|
+
|
|
21
|
+
\`\`\`bash
|
|
22
|
+
ls ~/.claude/teams/
|
|
23
|
+
\`\`\`
|
|
24
|
+
|
|
25
|
+
If multiple teams exist and none was specified, show the list and ask the user which team to rejoin.
|
|
26
|
+
|
|
27
|
+
If no teams exist, tell the user there are no teams to rejoin and stop.
|
|
28
|
+
|
|
29
|
+
## Step 2: Read the team config
|
|
30
|
+
|
|
31
|
+
Read the file \`~/.claude/teams/{team_name}/config.json\`.
|
|
32
|
+
|
|
33
|
+
If it doesn't exist or is unreadable, tell the user and stop.
|
|
34
|
+
|
|
35
|
+
## Step 3: Get the current session ID
|
|
36
|
+
|
|
37
|
+
Run:
|
|
38
|
+
|
|
39
|
+
\`\`\`bash
|
|
40
|
+
ls -t ~/.claude/session-env/ | head -1
|
|
41
|
+
\`\`\`
|
|
42
|
+
|
|
43
|
+
This returns the most recently modified session directory name, which is the current session ID.
|
|
44
|
+
|
|
45
|
+
If no session is found, tell the user the session could not be detected and stop.
|
|
46
|
+
|
|
47
|
+
## Step 4: Update the team config
|
|
48
|
+
|
|
49
|
+
Modify the config JSON:
|
|
50
|
+
1. Set \`leadSessionId\` to the current session ID from step 3
|
|
51
|
+
2. Set \`leadAgentId\` to \`team-lead@{team_name}\`
|
|
52
|
+
3. For every entry in the \`members\` array, set \`isActive\` to \`false\`
|
|
53
|
+
|
|
54
|
+
Write the updated JSON back to \`~/.claude/teams/{team_name}/config.json\` (pretty-printed with 4-space indent).
|
|
55
|
+
|
|
56
|
+
## Step 5: Report the result
|
|
57
|
+
|
|
58
|
+
Tell the user:
|
|
59
|
+
- The team has been rejoined
|
|
60
|
+
- How many teammates were reset to inactive
|
|
61
|
+
- List each non-"team-lead" member by name and role (agentType)
|
|
62
|
+
- Offer to re-spawn the teammates using the Task tool
|
|
63
|
+
|
|
64
|
+
Use the get_team_members skill or read the config directly to get teammate details for re-spawning.
|
|
65
|
+
`,
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
dirName: "team-list",
|
|
69
|
+
content: `---
|
|
70
|
+
name: team-list
|
|
71
|
+
description: List all Claude Code agent teams and their status. Use when user says "list teams", "show teams", "my teams", "orphaned teams", "team status".
|
|
72
|
+
allowed-tools: Read, Bash, Glob
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
# List Claude Code Agent Teams
|
|
76
|
+
|
|
77
|
+
You are listing all Claude Code agent teams and their status. Follow these steps.
|
|
78
|
+
|
|
79
|
+
## Step 1: Find all teams
|
|
80
|
+
|
|
81
|
+
List directories in \`~/.claude/teams/\`:
|
|
82
|
+
|
|
83
|
+
\`\`\`bash
|
|
84
|
+
ls ~/.claude/teams/
|
|
85
|
+
\`\`\`
|
|
86
|
+
|
|
87
|
+
If the directory doesn't exist or is empty, tell the user there are no teams and stop.
|
|
88
|
+
|
|
89
|
+
## Step 2: Read each team's config
|
|
90
|
+
|
|
91
|
+
For each team directory, read \`~/.claude/teams/{team_name}/config.json\`.
|
|
92
|
+
|
|
93
|
+
Skip any team whose config is missing or unreadable.
|
|
94
|
+
|
|
95
|
+
## Step 3: Check session staleness
|
|
96
|
+
|
|
97
|
+
For each team, determine the lead session status:
|
|
98
|
+
|
|
99
|
+
1. Get the team's \`leadSessionId\` from the config
|
|
100
|
+
2. Check if that session directory exists and its modification time:
|
|
101
|
+
|
|
102
|
+
\`\`\`bash
|
|
103
|
+
stat -f "%m" ~/.claude/session-env/{leadSessionId}/ 2>/dev/null
|
|
104
|
+
\`\`\`
|
|
105
|
+
|
|
106
|
+
3. Get the current time:
|
|
107
|
+
|
|
108
|
+
\`\`\`bash
|
|
109
|
+
date +%s
|
|
110
|
+
\`\`\`
|
|
111
|
+
|
|
112
|
+
4. If the session was modified less than 5 minutes ago (300 seconds), it is **active**. Otherwise it is **stale**.
|
|
113
|
+
|
|
114
|
+
Also determine the current session:
|
|
115
|
+
|
|
116
|
+
\`\`\`bash
|
|
117
|
+
ls -t ~/.claude/session-env/ | head -1
|
|
118
|
+
\`\`\`
|
|
119
|
+
|
|
120
|
+
If the team's \`leadSessionId\` matches the current session, status is **current**. If active but not current, status is **active-other**. Otherwise **stale**.
|
|
121
|
+
|
|
122
|
+
## Step 4: Present the results
|
|
123
|
+
|
|
124
|
+
For each team, show:
|
|
125
|
+
- **Team name**
|
|
126
|
+
- **Description** (or "no description" if missing)
|
|
127
|
+
- **Created at** (formatted from the \`createdAt\` timestamp)
|
|
128
|
+
- **Member count** and member names with roles
|
|
129
|
+
- **Lead session status**: current, active-other, or stale
|
|
130
|
+
|
|
131
|
+
Format as a clear, readable list. Highlight stale teams as candidates for rejoining.
|
|
132
|
+
`,
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
dirName: "team-members",
|
|
136
|
+
content: `---
|
|
137
|
+
name: team-members
|
|
138
|
+
description: Get teammate definitions from a Claude Code team for re-spawning. Use when user says "team members", "show teammates", "re-spawn teammates", "respawn agents".
|
|
139
|
+
allowed-tools: Read, Bash, Glob
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
# Get Team Member Definitions
|
|
143
|
+
|
|
144
|
+
You are retrieving teammate definitions from a Claude Code team so they can be re-spawned. Follow these steps.
|
|
145
|
+
|
|
146
|
+
## Step 1: Identify the team
|
|
147
|
+
|
|
148
|
+
If the user specified a team name, use that. Otherwise, list available teams:
|
|
149
|
+
|
|
150
|
+
\`\`\`bash
|
|
151
|
+
ls ~/.claude/teams/
|
|
152
|
+
\`\`\`
|
|
153
|
+
|
|
154
|
+
If multiple teams exist and none was specified, show the list and ask the user which team to inspect.
|
|
155
|
+
|
|
156
|
+
## Step 2: Read the team config
|
|
157
|
+
|
|
158
|
+
Read \`~/.claude/teams/{team_name}/config.json\`.
|
|
159
|
+
|
|
160
|
+
If it doesn't exist or is unreadable, tell the user and stop.
|
|
161
|
+
|
|
162
|
+
## Step 3: Extract teammate definitions
|
|
163
|
+
|
|
164
|
+
From the \`members\` array, filter out the entry with \`name\` equal to \`"team-lead"\` (that's the lead agent, not a spawnable teammate).
|
|
165
|
+
|
|
166
|
+
For each remaining member, present:
|
|
167
|
+
- **name**: The teammate's name
|
|
168
|
+
- **agentType**: Their role/subagent type (e.g., "general-purpose", "Explore")
|
|
169
|
+
- **model**: The model they were using (e.g., "sonnet", "opus")
|
|
170
|
+
- **prompt**: Whether they have a prompt defined (show the prompt content)
|
|
171
|
+
- **cwd**: Their working directory
|
|
172
|
+
- **planModeRequired**: Whether they require plan mode (default false)
|
|
173
|
+
|
|
174
|
+
## Step 4: Offer to re-spawn
|
|
175
|
+
|
|
176
|
+
Ask the user if they'd like to re-spawn these teammates. If yes, use the Task tool to spawn each one with their original configuration:
|
|
177
|
+
|
|
178
|
+
\`\`\`
|
|
179
|
+
Task tool parameters:
|
|
180
|
+
- name: {member.name}
|
|
181
|
+
- subagent_type: {member.agentType}
|
|
182
|
+
- model: {member.model}
|
|
183
|
+
- prompt: {member.prompt}
|
|
184
|
+
- team_name: {team_name}
|
|
185
|
+
- mode: "plan" (if planModeRequired is true)
|
|
186
|
+
\`\`\`
|
|
187
|
+
|
|
188
|
+
Spawn teammates in parallel when possible by making multiple Task tool calls in a single message.
|
|
189
|
+
`,
|
|
190
|
+
},
|
|
191
|
+
];
|
|
192
|
+
//# sourceMappingURL=skills.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../src/skills.ts"],"names":[],"mappings":";;;AAKa,QAAA,MAAM,GAAsB;IACvC;QACE,OAAO,EAAE,WAAW;QACpB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0DZ;KACE;IACD;QACE,OAAO,EAAE,WAAW;QACpB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+DZ;KACE;IACD;QACE,OAAO,EAAE,cAAc;QACvB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqDZ;KACE;CACF,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-team-join",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Skill package 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"
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"keywords": [
|
|
18
18
|
"claude-code",
|
|
19
|
-
"
|
|
19
|
+
"skill",
|
|
20
20
|
"team",
|
|
21
21
|
"agent"
|
|
22
22
|
],
|
|
@@ -30,10 +30,7 @@
|
|
|
30
30
|
"bugs": {
|
|
31
31
|
"url": "https://github.com/shim52/claude-code-agent-teams-join/issues"
|
|
32
32
|
},
|
|
33
|
-
"dependencies": {
|
|
34
|
-
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
35
|
-
"zod": "^3.23.0"
|
|
36
|
-
},
|
|
33
|
+
"dependencies": {},
|
|
37
34
|
"devDependencies": {
|
|
38
35
|
"typescript": "^5.7.0",
|
|
39
36
|
"@types/node": "^22.0.0",
|
package/dist/helpers.d.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
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>;
|
package/dist/helpers.js
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
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
|
package/dist/helpers.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"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"}
|
package/dist/tools.d.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
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
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
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
|
package/dist/tools.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
|