patchcord 0.5.115 → 0.5.116

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 +38 -2
  2. package/package.json +1 -1
package/bin/patchcord.mjs CHANGED
@@ -97,6 +97,9 @@ TEAMLEAD — set up the team-lead agent (the shepherd) in this folder
97
97
  TEAM — the teamlead'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
@@ -829,7 +832,7 @@ if (cmd === "subscribe") {
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 === "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,6 +1013,39 @@ if (cmd === "login" || cmd === "teamlead" || cmd === "provision" || cmd === "tea
1010
1013
  process.exit(0);
1011
1014
  }
1012
1015
 
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
+
1013
1049
  if (cmd === "teamlead") {
1014
1050
  // Set up the TEAMLEAD agent in THIS folder. The teamlead is a distinct kind
1015
1051
  // of agent — it shepherds a team: provisions, connects, and manages the
@@ -2977,5 +3013,5 @@ if (cmd === "skill") {
2977
3013
  process.exit(0);
2978
3014
  }
2979
3015
 
2980
- console.error(`Unknown command: ${cmd}. Available: install, whoami, agents, upload, subscribe, update, login, provision, teamlead, team, schedule, --rename, --token, --agent-type, --version, --help`);
3016
+ console.error(`Unknown command: ${cmd}. Available: install, whoami, agents, upload, subscribe, update, login, provision, pull, teamlead, team, schedule, --rename, --token, --agent-type, --version, --help`);
2981
3017
  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.116",
4
4
  "description": "Cross-machine agent messaging for Claude Code and Codex",
5
5
  "author": "ppravdin",
6
6
  "license": "MIT",