patchcord 0.5.115 → 0.5.117

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.
Files changed (2) hide show
  1. package/bin/patchcord.mjs +71 -26
  2. package/package.json +1 -1
package/bin/patchcord.mjs CHANGED
@@ -89,14 +89,17 @@ THIS AGENT — identity + messaging
89
89
  ACCOUNT — log in to the CLI (commands below log in on demand)
90
90
  patchcord login Authenticate the CLI (your account)
91
91
 
92
- TEAMLEAD — set up the team-lead agent (the shepherd) in this folder
93
- patchcord teamlead [--namespace <ns>] [--tool <harness>]
94
- Provision the teamlead here; launch it
92
+ ORCHESTRATOR — set up the orchestrator agent (the shepherd) in this folder
93
+ patchcord orchestrator [--namespace <ns>] [--tool <harness>]
94
+ Provision the orchestrator here; launch it
95
95
  to adopt this project or build a new team
96
96
 
97
- TEAM — the teamlead's tools (run from the project root)
97
+ TEAM — the orchestrator's tools (run from the project root)
98
98
  patchcord provision <agent> --tool <X> --role <Y> --namespace <ns> [--dir <sub/>]
99
99
  Create a worker agent (identity + config)
100
+ patchcord pull <agent> --tool <X> --namespace <ns> [--dir <sub/>]
101
+ Place an EXISTING agent into a folder
102
+ (same identity, new token; nothing overwritten)
100
103
  patchcord provision revoke <agent> --namespace <ns>
101
104
  patchcord team list [--namespace <ns>] Provisioned agents (server view, deduped)
102
105
  patchcord team status Reconcile folder ↔ identity ↔ tmux ↔ token
@@ -824,12 +827,12 @@ if (cmd === "subscribe") {
824
827
  // works the same as the space-form (--token foo). The internal flag parsing below
825
828
  // supports both. Non-flag commands (channel, init, skill, help, plugin-path) have
826
829
  // their own branches above and below.
827
- // ── CLI account auth + teamlead/team/provisioning/schedule ─────────────────
830
+ // ── CLI account auth + orchestrator/team/provisioning/schedule ─────────────
828
831
  // These commands act on the user's ACCOUNT, so they require CLI login. The
829
832
  // account token (user-level, tied to NO agent) lives at ~/.patchcord/auth.json
830
833
  // (legacy: main.json / master.json) or $PATCHCORD_TOKEN (legacy: *_MAIN/MASTER).
831
834
  // `patchcord login` authenticates; everything else logs in on demand.
832
- if (cmd === "login" || cmd === "teamlead" || cmd === "provision" || cmd === "team" || cmd === "schedule") {
835
+ if (cmd === "login" || cmd === "orchestrator" || cmd === "teamlead" || cmd === "provision" || cmd === "pull" || cmd === "team" || cmd === "schedule") {
833
836
  const M = { cyan: "\x1b[36m", green: "\x1b[32m", dim: "\x1b[2m", rst: "\x1b[0m" };
834
837
  const AUTH_CONFIG = join(HOME, ".patchcord", "auth.json");
835
838
  const LEGACY_CONFIGS = [join(HOME, ".patchcord", "main.json"), join(HOME, ".patchcord", "master.json")];
@@ -1010,27 +1013,67 @@ if (cmd === "login" || cmd === "teamlead" || cmd === "provision" || cmd === "tea
1010
1013
  process.exit(0);
1011
1014
  }
1012
1015
 
1013
- if (cmd === "teamlead") {
1014
- // Set up the TEAMLEAD agent in THIS folder. The teamlead is a distinct kind
1015
- // of agent it shepherds a team: provisions, connects, and manages the
1016
- // other agents. It is NOT a normal agent: it gets its own identity, its own
1017
- // onboarding instruction, and on launch either ADOPTS this existing project
1018
- // or CREATES a new team by interviewing the user.
1016
+ if (cmd === "pull") {
1017
+ // Inverse of provision: place an EXISTING agent identity into a folder.
1018
+ // Mints another token bound to the same agent_id@namespace (its original
1019
+ // token is hashed server-side and unrecoverable, so we can't return the
1020
+ // literal one but the identity is the same). Nothing is overwritten; the
1021
+ // agent can now run from this folder too.
1022
+ const arg = process.argv[3];
1023
+ if (!arg || arg.startsWith("-")) { console.error("Usage: patchcord pull <agent> --namespace ns --tool X [--dir sub/]"); process.exit(1); }
1024
+ const tool = flagVal("tool", "claude_code");
1025
+ const ns = flagVal("namespace");
1026
+ const subdir = flagVal("dir", arg);
1027
+ if (!ns) { console.error("--namespace <project-namespace> required"); process.exit(1); }
1028
+ const { status, json, m } = await accountCall("POST", "/api/provision", { namespace_id: ns, agent_id: arg, tool, require_existing: true, label: `pull:${tool}` });
1029
+ if (status === "404") { console.error(`no agent ${M.green}${ns}:${arg}${M.rst} to pull — create it with: patchcord provision ${arg} --tool ${tool} --namespace ${ns}`); process.exit(1); }
1030
+ if (status !== "200" || !json?.token) { console.error(`pull failed (HTTP ${status}): ${json?.error || ""}`); process.exit(1); }
1031
+ const base = String(json.url || `${m.baseUrl}/mcp`).replace(/\/mcp$/, "");
1032
+ const dir = join(process.cwd(), subdir);
1033
+ const hostname = run("hostname -s") || run("hostname") || "unknown";
1034
+ writeWorkerConfig(tool, dir, base, json.token, hostname);
1035
+ // Record in the local team manifest so `team launch` / `team status` see it.
1036
+ try {
1037
+ const tj = join(process.cwd(), ".patchcord", "team.json");
1038
+ if (existsSync(tj)) {
1039
+ const man = JSON.parse(readFileSync(tj, "utf-8"));
1040
+ man.agents = (man.agents || []).filter((a) => a.agent !== arg);
1041
+ man.agents.push({ agent: arg, tool, dir: subdir, namespace: ns });
1042
+ writeFileSync(tj, JSON.stringify(man, null, 2) + "\n");
1043
+ }
1044
+ } catch {}
1045
+ console.log(`✓ pulled ${M.green}${ns}:${arg}${M.rst} [${tool}] → ${dir}`);
1046
+ process.exit(0);
1047
+ }
1048
+
1049
+ if (cmd === "orchestrator" || cmd === "teamlead") {
1050
+ // Set up the ORCHESTRATOR agent in THIS folder. The orchestrator is a
1051
+ // distinct kind of agent — it shepherds a team: provisions, connects, and
1052
+ // manages the other agents. It is NOT a normal agent: it gets its own
1053
+ // identity, its own onboarding instruction, and on launch either ADOPTS
1054
+ // this existing project or CREATES a new team by interviewing the user.
1055
+ // (`teamlead` is kept as a back-compat alias for the command name.)
1019
1056
  const root = process.cwd();
1020
1057
  const ns = (flagVal("namespace", basename(root)) || "team").replace(/[^a-z0-9-]/gi, "-").toLowerCase();
1021
1058
  const tool = flagVal("tool", "claude_code");
1022
1059
  const hostname = run("hostname -s") || run("hostname") || "unknown";
1023
- const { status, json, m } = await accountCall("POST", "/api/provision", { namespace_id: ns, agent_id: "teamlead", tool, role: "teamlead", label: "teamlead:self" });
1024
- if (status !== "200" || !json?.token) { console.error(`could not set up teamlead (HTTP ${status}): ${json?.error || ""}`); process.exit(1); }
1060
+ const { status, json, m } = await accountCall("POST", "/api/provision", { namespace_id: ns, agent_id: "orchestrator", tool, role: "orchestrator", label: "orchestrator:self" });
1061
+ if (status !== "200" || !json?.token) { console.error(`could not set up orchestrator (HTTP ${status}): ${json?.error || ""}`); process.exit(1); }
1025
1062
  const base = String(json.url || `${m.baseUrl}/mcp`).replace(/\/mcp$/, "");
1026
1063
  writeWorkerConfig(tool, root, base, json.token, hostname);
1027
1064
  mkdirSync(join(root, ".patchcord"), { recursive: true });
1028
1065
  const tj = join(root, ".patchcord", "team.json");
1029
- let manifest = { project: basename(root), namespace: ns, teamlead: { agent: "teamlead", tool }, agents: [] };
1030
- try { if (existsSync(tj)) manifest = { ...JSON.parse(readFileSync(tj, "utf-8")), namespace: ns, teamlead: { agent: "teamlead", tool } }; } catch {}
1066
+ let manifest = { project: basename(root), namespace: ns, orchestrator: { agent: "orchestrator", tool }, agents: [] };
1067
+ try {
1068
+ if (existsSync(tj)) {
1069
+ const prev = JSON.parse(readFileSync(tj, "utf-8"));
1070
+ delete prev.teamlead; delete prev.main; delete prev.master; // drop pre-rename keys
1071
+ manifest = { ...prev, namespace: ns, orchestrator: { agent: "orchestrator", tool } };
1072
+ }
1073
+ } catch {}
1031
1074
  writeFileSync(tj, JSON.stringify(manifest, null, 2) + "\n");
1032
- // The teamlead's onboarding instruction (read on launch).
1033
- writeFileSync(join(root, "TEAMLEAD.md"), `# You are the TEAMLEAD (${ns}:teamlead)
1075
+ // The orchestrator's onboarding instruction (read on launch).
1076
+ writeFileSync(join(root, "ORCHESTRATOR.md"), `# You are the ORCHESTRATOR (${ns}:orchestrator)
1034
1077
 
1035
1078
  You shepherd a team of patchcord agents in this folder. You are NOT a worker —
1036
1079
  you design the team, provision its agents, launch them, and manage them.
@@ -1043,14 +1086,16 @@ you design the team, provision its agents, launch them, and manage them.
1043
1086
  which roles/harnesses, how many — confirm the plan, then build it.
1044
1087
 
1045
1088
  ## Build / run
1046
- - Provision each worker: \`patchcord provision <agent> --tool <claude_code|codex|opencode|kimi> --role <role> --namespace ${ns} --dir <agent>/\`
1089
+ - Provision each worker: \`patchcord provision <agent> --tool <claude_code|codex|opencode|kimi|agy> --role <role> --namespace ${ns} --dir <agent>/\`
1090
+ - Pull an existing agent into a folder: \`patchcord pull <agent> --tool <X> --namespace ${ns} --dir <agent>/\`
1047
1091
  - Launch: \`patchcord team launch\` (mux), verify with \`patchcord team status\`.
1048
1092
  - Coordinate over patchcord (inbox / send_message); manage at the meta level.
1049
- - Your own identity here is ${ns}:teamlead — \`patchcord whoami\` confirms it.
1093
+ - Your own identity here is ${ns}:orchestrator — \`patchcord whoami\` confirms it.
1050
1094
  `);
1051
- console.log(`\n ${M.green}✓${M.rst} Teamlead ready: ${M.green}${ns}:teamlead${M.rst} [${tool}] in ${root}`);
1095
+ try { if (existsSync(join(root, "TEAMLEAD.md"))) unlinkSync(join(root, "TEAMLEAD.md")); } catch {} // remove pre-rename onboarding file
1096
+ console.log(`\n ${M.green}✓${M.rst} Orchestrator ready: ${M.green}${ns}:orchestrator${M.rst} [${tool}] in ${root}`);
1052
1097
  console.log(` ${M.dim}Launch it here — it adopts this project or creates a new team, asking you:${M.rst}`);
1053
- console.log(` mux new ${tool === "claude_code" ? "claude" : (tool === "kimi-code" ? "kimi" : tool)} --dir .`);
1098
+ console.log(` mux new ${tool === "claude_code" ? "claude" : (tool === "kimi-code" ? "kimi" : (tool === "antigravity" || tool === "agy") ? "agy" : tool)} --dir .`);
1054
1099
  process.exit(0);
1055
1100
  }
1056
1101
 
@@ -1124,10 +1169,10 @@ you design the team, provision its agents, launch them, and manage them.
1124
1169
  panes.push({ session, window, path: real(path), cmd, claimed: false });
1125
1170
  }
1126
1171
 
1127
- // Build the roster: teamlead first, then workers.
1172
+ // Build the roster: orchestrator first, then workers.
1128
1173
  const roster = [];
1129
- const leadEntry = manifest.teamlead || manifest.main || manifest.master; // pre-rename names
1130
- if (leadEntry) roster.push({ ...leadEntry, role: "teamlead", dir: ".", _lead: true });
1174
+ const leadEntry = manifest.orchestrator || manifest.teamlead || manifest.main || manifest.master; // pre-rename names
1175
+ if (leadEntry) roster.push({ ...leadEntry, role: "orchestrator", dir: ".", _lead: true });
1131
1176
  for (const a of (manifest.agents || [])) roster.push(a);
1132
1177
 
1133
1178
  const rows = [];
@@ -2977,5 +3022,5 @@ if (cmd === "skill") {
2977
3022
  process.exit(0);
2978
3023
  }
2979
3024
 
2980
- console.error(`Unknown command: ${cmd}. Available: install, whoami, agents, upload, subscribe, update, login, provision, teamlead, team, schedule, --rename, --token, --agent-type, --version, --help`);
3025
+ console.error(`Unknown command: ${cmd}. Available: install, whoami, agents, upload, subscribe, update, login, provision, pull, orchestrator, team, schedule, --rename, --token, --agent-type, --version, --help`);
2981
3026
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "patchcord",
3
- "version": "0.5.115",
3
+ "version": "0.5.117",
4
4
  "description": "Cross-machine agent messaging for Claude Code and Codex",
5
5
  "author": "ppravdin",
6
6
  "license": "MIT",