@scp-dev/cli 0.3.1 → 0.4.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.
@@ -545,13 +545,26 @@ async function runHook(args, options) {
545
545
  }
546
546
  async function wakeHook(harnessArg, payload, waitS, options) {
547
547
  if (options.env.SCP_TRANSPORT === "cloud" || field(payload, "agent_id", "agentId", "agent_type", "agentType", "subagentType")) return;
548
+ const harness = normalizeHarness(hookHarness(harnessArg, options.env), "hook");
549
+ const pid = (options.harnessPid ?? ((h) => hookHarnessPid(options.env, h)))(harness);
550
+ const started = psStart(pid);
551
+ const joined = membership(
552
+ options.env,
553
+ sessionKey(
554
+ options.env,
555
+ processKey(pid, () => started)
556
+ )
557
+ );
558
+ if ("dark" in joined) return;
548
559
  const claim = relayIdentity({
549
- harness: hookHarness(harnessArg, options.env),
560
+ ...joined.handle ? { as: joined.handle } : {},
561
+ harness,
550
562
  fallbackHarness: "hook",
551
563
  cwd: asString(payload.cwd) ?? options.cwd,
552
564
  env: options.env,
553
- harnessPid: options.harnessPid ?? ((harness) => hookHarnessPid(options.env, harness)),
554
- ...options.harnessPid ? {} : { inferHarness: (at) => harnessAt(at) }
565
+ harnessPid: () => pid,
566
+ ...options.harnessPid ? {} : { inferHarness: (at) => harnessAt(at) },
567
+ startOf: () => started
555
568
  });
556
569
  if (!validHandle(claim.handle)) return;
557
570
  const waitMs = Math.min(waitS, LIMITS.waitMaxS) * 1e3;
@@ -3,10 +3,10 @@ import {
3
3
  agySettingsFile,
4
4
  mcpFile,
5
5
  mountedEntry
6
- } from "./chunk-2OSUVJ2J.js";
6
+ } from "./chunk-VW7DYSGM.js";
7
7
  import {
8
8
  steerPrompt
9
- } from "./chunk-QRWQIHV6.js";
9
+ } from "./chunk-B2G3XTW7.js";
10
10
  import {
11
11
  OPTIONS,
12
12
  RelayUsage,
@@ -10,7 +10,7 @@ import {
10
10
  mergeHooks,
11
11
  musePlugin,
12
12
  opencodePlugin
13
- } from "./chunk-QRWQIHV6.js";
13
+ } from "./chunk-B2G3XTW7.js";
14
14
  import {
15
15
  RelayUsage,
16
16
  gitToplevel
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  hooksTarget
3
- } from "./chunk-Q5UI4Z7H.js";
3
+ } from "./chunk-VQU5CPE4.js";
4
4
  import {
5
5
  AGY_HOOK_SET,
6
6
  BLOCK_STOP,
@@ -12,7 +12,7 @@ import {
12
12
  mergeHooks,
13
13
  musePlugin,
14
14
  opencodePlugin
15
- } from "./chunk-QRWQIHV6.js";
15
+ } from "./chunk-B2G3XTW7.js";
16
16
  import {
17
17
  RelayUsage,
18
18
  gitToplevel,
@@ -3,9 +3,9 @@ import {
3
3
  mcpFile,
4
4
  mountedEntry,
5
5
  whichOnPath
6
- } from "./chunk-2OSUVJ2J.js";
7
- import "./chunk-Q5UI4Z7H.js";
8
- import "./chunk-QRWQIHV6.js";
6
+ } from "./chunk-VW7DYSGM.js";
7
+ import "./chunk-VQU5CPE4.js";
8
+ import "./chunk-B2G3XTW7.js";
9
9
  import "./chunk-YYSLYVNZ.js";
10
10
  import {
11
11
  CHANNELS_ENV,
package/dist/cli.js CHANGED
@@ -17,6 +17,6 @@ function quietSqliteWarning() {
17
17
  // src/cli.ts
18
18
  if (!await subagentFastPath(process.argv.slice(2))) {
19
19
  quietSqliteWarning();
20
- const { run } = await import("./main-ZAYVXFAG.js");
20
+ const { run } = await import("./main-STUKDZ5L.js");
21
21
  await run(process.argv.slice(2));
22
22
  }
@@ -3,11 +3,11 @@ import {
3
3
  codexMount,
4
4
  codexOverrides,
5
5
  toml
6
- } from "./chunk-3SHVJIXP.js";
6
+ } from "./chunk-HHVNSHGB.js";
7
7
  import "./chunk-KN7WEIE4.js";
8
- import "./chunk-2OSUVJ2J.js";
9
- import "./chunk-Q5UI4Z7H.js";
10
- import "./chunk-QRWQIHV6.js";
8
+ import "./chunk-VW7DYSGM.js";
9
+ import "./chunk-VQU5CPE4.js";
10
+ import "./chunk-B2G3XTW7.js";
11
11
  import "./chunk-YYSLYVNZ.js";
12
12
  import {
13
13
  RelayUsage,
@@ -40,7 +40,7 @@ import {
40
40
  tldrEvery,
41
41
  transcriptTitle,
42
42
  unreadPointer
43
- } from "./chunk-QRWQIHV6.js";
43
+ } from "./chunk-B2G3XTW7.js";
44
44
  import {
45
45
  SUBAGENT
46
46
  } from "./chunk-YYSLYVNZ.js";
@@ -2,8 +2,8 @@ import {
2
2
  hooksTarget,
3
3
  installHooks,
4
4
  mcpInstall
5
- } from "./chunk-Q5UI4Z7H.js";
6
- import "./chunk-QRWQIHV6.js";
5
+ } from "./chunk-VQU5CPE4.js";
6
+ import "./chunk-B2G3XTW7.js";
7
7
  import "./chunk-YYSLYVNZ.js";
8
8
  import "./chunk-2LIJXXTL.js";
9
9
  import "./chunk-MNTIEWKF.js";
@@ -34,7 +34,7 @@ import { parseArgs } from "util";
34
34
  // package.json
35
35
  var package_default = {
36
36
  name: "@scp-dev/cli",
37
- version: "0.3.1",
37
+ version: "0.4.0",
38
38
  description: "The swarm command line tool.",
39
39
  license: "Apache-2.0",
40
40
  homepage: "https://scp.dev",
@@ -286,12 +286,16 @@ agent sessions:
286
286
  and title stay; a handle another endpoint holds, live or offline, is refused;
287
287
  a spawned worker is named by its spawner (policy defaults.rename: self lets it);
288
288
  --endpoint renames another agent, for the human at a terminal
289
- ${CLI_NAME} join [<handle>] --under <parent> link the session under the agent <parent> (local, one it may message), as if
289
+ ${CLI_NAME} join [<handle>] --under <parent> link the session under the agent <parent> (one it may message), as if
290
290
  <parent> had spawned it: it shows under <parent> in list --tree, the dashboard
291
291
  and the graph, and takes on a worker's scope (the policy's child_default: by
292
- default it reaches only what <parent> reaches). Narrowing, so always allowed
292
+ default it reaches only what <parent> reaches). Narrowing, so always allowed.
293
+ <parent> may be on another machine of the account (me/<machine>/<handle>):
294
+ the session stays a root there, takes no child scope, and the two reach
295
+ each other both ways
293
296
  ${CLI_NAME} adopt <child> [--parent <p>] link a local root agent and its subtree under <p>, for the human at a terminal;
294
- from an agent's shell with a terminal attached <p> defaults to that agent.
297
+ <p> may be on another machine of the account (me/<machine>/<handle>).
298
+ From an agent's shell with a terminal attached <p> defaults to that agent.
295
299
  An agent without a terminal is refused: the session joins with --under itself
296
300
  ${CLI_NAME} unlink [<child>] put a linked agent back at the root, its subtree along and the child scope off;
297
301
  widening, so the human at a terminal only (policy defaults.unlink: self lets
@@ -558,14 +562,14 @@ async function relayMain(argv, cwd = process.cwd()) {
558
562
  out(cliVersion());
559
563
  return 0;
560
564
  }
561
- if (verb === "hook") return (await import("./hooks-B34E2HIP.js")).relayHookCommand(rest, startDaemon);
562
- if (verb === "setup") return (await import("./setup-MGDWKCNU.js")).relaySetupCommand(rest, cwd, out);
563
- if (verb === "claude") return (await import("./claude-EQVLST73.js")).claudeCommand(rest);
565
+ if (verb === "hook") return (await import("./hooks-ISZTCOLZ.js")).relayHookCommand(rest, startDaemon);
566
+ if (verb === "setup") return (await import("./setup-R5SNWVVF.js")).relaySetupCommand(rest, cwd, out);
567
+ if (verb === "claude") return (await import("./claude-L2I5ZM2B.js")).claudeCommand(rest);
564
568
  if (verb === "pi") return (await import("./pi-QEZVFDNR.js")).piCommand(rest);
565
- if (verb === "codex") return (await import("./codex-5GZ7YPES.js")).codexCommand(rest);
566
- if (verb === "opencode") return (await import("./opencode-ORLGNHWR.js")).opencodeCommand(rest, process.env, void 0, cwd);
569
+ if (verb === "codex") return (await import("./codex-4WPBAFAT.js")).codexCommand(rest);
570
+ if (verb === "opencode") return (await import("./opencode-WFP57BZD.js")).opencodeCommand(rest, process.env, void 0, cwd);
567
571
  if (verb === "spawn") {
568
- const { splitSpawn, spawnCommand } = await import("./spawn-GG7VFZA6.js");
572
+ const { splitSpawn, spawnCommand } = await import("./spawn-WJYOTAKI.js");
569
573
  const { flags } = splitSpawn(rest);
570
574
  if (flags.includes("--help") || flags.includes("-h")) {
571
575
  out(flags.includes("--all") ? RELAY_HELP : SPAWN_HELP);
@@ -573,7 +577,7 @@ async function relayMain(argv, cwd = process.cwd()) {
573
577
  }
574
578
  return spawnCommand(rest, cwd);
575
579
  }
576
- if (verb === "mesh") return (await import("./mesh-H4KL5XAR.js")).meshCommand(rest);
580
+ if (verb === "mesh") return (await import("./mesh-UG6VO7ZO.js")).meshCommand(rest);
577
581
  const allowed = VERBS[verb];
578
582
  if (!allowed) throw new RelayUsage(`unknown command "${verb}"`);
579
583
  let parsed;
@@ -593,11 +597,11 @@ async function relayMain(argv, cwd = process.cwd()) {
593
597
  return daemon(values.idle, values.policy);
594
598
  }
595
599
  if (verb === "mcp")
596
- return (await import("./mcp-VXBRMQB7.js")).relayMcpCommand(values, positionals);
600
+ return (await import("./mcp-J2CL6A4R.js")).relayMcpCommand(values, positionals);
597
601
  if (verb === "hooks") {
598
602
  if (positionals[0] !== "install" || positionals.length > 1) throw new RelayUsage(`${CLI_NAME} hooks takes install --harness claude|codex|opencode|agy|muse`);
599
603
  if (values.write && values.print) throw new RelayUsage("--print and --write: pick one");
600
- return (await import("./install-6KXJY27V.js")).installHooks({
604
+ return (await import("./install-SDLWXW32.js")).installHooks({
601
605
  harness: values.harness,
602
606
  scope: values.scope,
603
607
  write: values.write === true,
@@ -609,7 +613,7 @@ async function relayMain(argv, cwd = process.cwd()) {
609
613
  });
610
614
  }
611
615
  if (verb === "relay") return (await import("./relay-QWJM372C.js")).relayVerb(positionals, values.json === true);
612
- if (verb === "up") return (await import("./up-B2NEOOC6.js")).up(positionals, values, cwd, relinkBroker);
616
+ if (verb === "up") return (await import("./up-UWV5BQUH.js")).up(positionals, values, cwd, relinkBroker);
613
617
  if (verb === "login") {
614
618
  const code = await (await import("./relay-QWJM372C.js")).loginMain(positionals, values);
615
619
  if (code === 0) await relinkRunning();
@@ -1420,7 +1424,7 @@ async function daemon(idle, policyFile) {
1420
1424
  const bridge = await daemonBridge();
1421
1425
  broker = await startBroker({
1422
1426
  dir: relayDir(),
1423
- ...bridge ? { bridge } : await (await import("./mesh-H4KL5XAR.js")).meshBrokerOptions(),
1427
+ ...bridge ? { bridge } : await (await import("./mesh-UG6VO7ZO.js")).meshBrokerOptions(),
1424
1428
  bridgeConfig: () => daemonBridge(),
1425
1429
  ...idleMs !== void 0 ? { idleMs } : {},
1426
1430
  ...policyFile ? { policyPath: resolve(policyFile) } : {}
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  spawnDetached
3
- } from "./chunk-3SHVJIXP.js";
3
+ } from "./chunk-HHVNSHGB.js";
4
4
  import "./chunk-KN7WEIE4.js";
5
- import "./chunk-2OSUVJ2J.js";
5
+ import "./chunk-VW7DYSGM.js";
6
6
  import {
7
7
  mcpInstall
8
- } from "./chunk-Q5UI4Z7H.js";
9
- import "./chunk-QRWQIHV6.js";
8
+ } from "./chunk-VQU5CPE4.js";
9
+ import "./chunk-B2G3XTW7.js";
10
10
  import "./chunk-YYSLYVNZ.js";
11
11
  import {
12
12
  CHANNELS_ENV,
@@ -0,0 +1,53 @@
1
+ import {
2
+ RelayUsage
3
+ } from "./chunk-2LIJXXTL.js";
4
+ import "./chunk-MNTIEWKF.js";
5
+
6
+ // src/mesh.ts
7
+ import { readFileSync } from "fs";
8
+ import { join } from "path";
9
+ import { relayDir } from "@scp-dev/broker";
10
+ var MESH_MODULE = "@scp-dev/mesh";
11
+ async function importMesh() {
12
+ return await import(MESH_MODULE);
13
+ }
14
+ async function load() {
15
+ try {
16
+ return await importMesh();
17
+ } catch {
18
+ throw new RelayUsage("swarm mesh is experimental and runs only from a source checkout of the swarm CLI");
19
+ }
20
+ }
21
+ async function meshCommand(argv) {
22
+ return (await load()).meshCommand(argv);
23
+ }
24
+ function meshEnabled(path) {
25
+ let text;
26
+ try {
27
+ text = readFileSync(path, "utf8");
28
+ } catch {
29
+ return false;
30
+ }
31
+ try {
32
+ return JSON.parse(text)?.enabled === true;
33
+ } catch {
34
+ return true;
35
+ }
36
+ }
37
+ async function meshBrokerOptions(dir = join(relayDir(), "mesh"), options = {}) {
38
+ const path = join(dir, "mesh.json");
39
+ if (!meshEnabled(path)) return {};
40
+ let mesh;
41
+ try {
42
+ mesh = await (options.importMesh ?? importMesh)();
43
+ } catch {
44
+ const warn = options.warn ?? console.error;
45
+ warn(`mesh is enabled in ${path} but this CLI has no mesh module; running without it`);
46
+ return {};
47
+ }
48
+ return mesh.meshBrokerOptions(dir);
49
+ }
50
+ export {
51
+ meshBrokerOptions,
52
+ meshCommand
53
+ };
@@ -2,13 +2,13 @@ import {
2
2
  mcpFile,
3
3
  mountedEntry,
4
4
  whichOnPath
5
- } from "./chunk-2OSUVJ2J.js";
5
+ } from "./chunk-VW7DYSGM.js";
6
6
  import {
7
7
  hooksTarget
8
- } from "./chunk-Q5UI4Z7H.js";
8
+ } from "./chunk-VQU5CPE4.js";
9
9
  import {
10
10
  opencodePlugin
11
- } from "./chunk-QRWQIHV6.js";
11
+ } from "./chunk-B2G3XTW7.js";
12
12
  import "./chunk-YYSLYVNZ.js";
13
13
  import {
14
14
  RelayUsage,
@@ -15,9 +15,9 @@ import {
15
15
  verifyMount,
16
16
  verifyMusePlugin,
17
17
  whichOnPath
18
- } from "./chunk-2OSUVJ2J.js";
19
- import "./chunk-Q5UI4Z7H.js";
20
- import "./chunk-QRWQIHV6.js";
18
+ } from "./chunk-VW7DYSGM.js";
19
+ import "./chunk-VQU5CPE4.js";
20
+ import "./chunk-B2G3XTW7.js";
21
21
  import "./chunk-YYSLYVNZ.js";
22
22
  import "./chunk-2LIJXXTL.js";
23
23
  import "./chunk-MNTIEWKF.js";
@@ -31,13 +31,13 @@ import {
31
31
  toml,
32
32
  transcriptReplies,
33
33
  workerName
34
- } from "./chunk-3SHVJIXP.js";
34
+ } from "./chunk-HHVNSHGB.js";
35
35
  import {
36
36
  SPAWN_HELP
37
37
  } from "./chunk-KN7WEIE4.js";
38
- import "./chunk-2OSUVJ2J.js";
39
- import "./chunk-Q5UI4Z7H.js";
40
- import "./chunk-QRWQIHV6.js";
38
+ import "./chunk-VW7DYSGM.js";
39
+ import "./chunk-VQU5CPE4.js";
40
+ import "./chunk-B2G3XTW7.js";
41
41
  import "./chunk-YYSLYVNZ.js";
42
42
  import "./chunk-2LIJXXTL.js";
43
43
  import "./chunk-MNTIEWKF.js";
@@ -38,12 +38,12 @@ async function up(positionals, values, cwd, brokerStatus) {
38
38
  } else out(`already logged in to ${url}`);
39
39
  const enabled = await (await import("./remote-P4GFUIAP.js")).cloudMain(["enable"], values.machine !== void 0 ? { machine: values.machine } : {}, brokerStatus);
40
40
  if (enabled !== 0) return enabled;
41
- const setup = (await import("./setup-MGDWKCNU.js")).relaySetupCommand(["--write"], cwd, out);
41
+ const setup = (await import("./setup-R5SNWVVF.js")).relaySetupCommand(["--write"], cwd, out);
42
42
  if (setup !== 0) return setup;
43
43
  const broker = await brokerStatus();
44
44
  if (!broker.enabled) out(`the broker is still local-only; run \`${CLI_NAME} daemon restart\` to link it to ${url}`);
45
45
  else out(`broker linked to ${broker.url ?? url}${broker.connected ? "" : " (connecting)"}`);
46
- const { detectHarnesses, whichOnPath } = await import("./setup-MGDWKCNU.js");
46
+ const { detectHarnesses, whichOnPath } = await import("./setup-R5SNWVVF.js");
47
47
  const which = (name) => whichOnPath(name, process.env);
48
48
  const installed = new Set(detectHarnesses(process.env, which).keys());
49
49
  if (which("pi")) installed.add("pi");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scp-dev/cli",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "The swarm command line tool.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://scp.dev",
@@ -24,15 +24,15 @@
24
24
  "typecheck": "tsc -p ."
25
25
  },
26
26
  "dependencies": {
27
- "@scp-dev/core": "0.1.6",
28
- "@scp-dev/broker": "0.2.1",
29
- "@scp-dev/hub": "0.5.1",
30
- "@scp-dev/mcp": "0.1.8",
27
+ "@scp-dev/core": "0.2.0",
28
+ "@scp-dev/broker": "0.3.0",
29
+ "@scp-dev/hub": "0.6.0",
30
+ "@scp-dev/mcp": "0.1.9",
31
31
  "smol-toml": "^1.9.1"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@openai/codex": "0.159.0",
35
- "@scp-dev/mesh": "0.0.5",
35
+ "@scp-dev/mesh": "0.0.6",
36
36
  "opencode-ai": "1.18.34",
37
37
  "tsup": "^8.5.1"
38
38
  },
@@ -1,28 +0,0 @@
1
- import {
2
- RelayUsage
3
- } from "./chunk-2LIJXXTL.js";
4
- import "./chunk-MNTIEWKF.js";
5
-
6
- // src/mesh.ts
7
- import { existsSync } from "fs";
8
- import { join } from "path";
9
- import { relayDir } from "@scp-dev/broker";
10
- var MESH_MODULE = "@scp-dev/mesh";
11
- async function load() {
12
- try {
13
- return await import(MESH_MODULE);
14
- } catch {
15
- throw new RelayUsage("swarm mesh is experimental and runs only from a source checkout of the swarm CLI");
16
- }
17
- }
18
- async function meshCommand(argv) {
19
- return (await load()).meshCommand(argv);
20
- }
21
- async function meshBrokerOptions() {
22
- if (!existsSync(join(relayDir(), "mesh", "mesh.json"))) return {};
23
- return (await load()).meshBrokerOptions();
24
- }
25
- export {
26
- meshBrokerOptions,
27
- meshCommand
28
- };