@scp-dev/cli 0.3.1 → 0.5.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.
@@ -10,11 +10,11 @@ import {
10
10
  mergeHooks,
11
11
  musePlugin,
12
12
  opencodePlugin
13
- } from "./chunk-QRWQIHV6.js";
13
+ } from "./chunk-XQHPDNVG.js";
14
14
  import {
15
15
  RelayUsage,
16
16
  gitToplevel
17
- } from "./chunk-2LIJXXTL.js";
17
+ } from "./chunk-AAFHLHXG.js";
18
18
 
19
19
  // src/install.ts
20
20
  import { chmodSync, copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, realpathSync, renameSync, statSync, unlinkSync, writeFileSync } from "fs";
@@ -3,10 +3,10 @@ import {
3
3
  agySettingsFile,
4
4
  mcpFile,
5
5
  mountedEntry
6
- } from "./chunk-2OSUVJ2J.js";
6
+ } from "./chunk-UKQBH4AQ.js";
7
7
  import {
8
8
  steerPrompt
9
- } from "./chunk-QRWQIHV6.js";
9
+ } from "./chunk-XQHPDNVG.js";
10
10
  import {
11
11
  OPTIONS,
12
12
  RelayUsage,
@@ -18,7 +18,7 @@ import {
18
18
  selectorList,
19
19
  spawnerKey,
20
20
  walkNow
21
- } from "./chunk-2LIJXXTL.js";
21
+ } from "./chunk-AAFHLHXG.js";
22
22
  import {
23
23
  SELF,
24
24
  note
@@ -44,8 +44,8 @@ import {
44
44
  } from "@scp-dev/core";
45
45
  var SERVER = "scp";
46
46
  var SPAWN_RUNNER = "SCP_SPAWN_RUNNER";
47
- var SPAWNER_IDENTITY = ["SCP_NAME", "SCP_SESSION", "SCP_GRANT", "SCP_PARENT", "SCP_HARNESS", SPAWN_RUNNER];
48
- var SHIM_ENV = ["SCP_GRANT", "SCP_NAME", "SCP_LABELS", "SCP_DIR", "XDG_STATE_HOME"];
47
+ var SPAWNER_IDENTITY = ["SCP_NAME", "SCP_SESSION", "SCP_GRANT", "SCP_PARENT", "SCP_HARNESS", "SCP_SHIM_BINDING", SPAWN_RUNNER];
48
+ var SHIM_ENV = ["SCP_GRANT", "SCP_NAME", "SCP_LABELS", "SCP_DIR", "XDG_STATE_HOME", "SCP_SHIM_BINDING"];
49
49
  function spawnEnvironment(parent, grant, labels) {
50
50
  const env = {};
51
51
  for (const [key, value] of Object.entries(parent)) if (value !== void 0 && !SPAWNER_IDENTITY.includes(key)) env[key] = value;
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-MNTIEWKF.js";
7
7
 
8
8
  // src/relay.ts
9
- import { chmodSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "fs";
9
+ import { chmodSync as chmodSync2, mkdirSync, readFileSync as readFileSync2, renameSync, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
10
10
  import { join as join3, dirname as dirname2 } from "path";
11
11
  import { randomUUID } from "crypto";
12
12
  import { CLI_NAME as CLI_NAME3 } from "@scp-dev/core";
@@ -16,13 +16,13 @@ import { spawn } from "child_process";
16
16
  import { closeSync, openSync, statSync, truncateSync } from "fs";
17
17
  import { join as join2 } from "path";
18
18
  import { CLI_NAME as CLI_NAME2 } from "@scp-dev/core";
19
- import { connectBroker, privateDir, relayDir as relayDir2 } from "@scp-dev/broker";
19
+ import { connectBroker, privateDir as privateDir2, relayDir as relayDir3 } from "@scp-dev/broker";
20
20
 
21
21
  // src/identity.ts
22
- import { existsSync, realpathSync } from "fs";
22
+ import { chmodSync, existsSync, readFileSync, realpathSync, rmSync, writeFileSync } from "fs";
23
23
  import { tmpdir } from "os";
24
24
  import { basename, dirname, isAbsolute, join, resolve } from "path";
25
- import { shortHostname } from "@scp-dev/broker";
25
+ import { privateDir, relayDir, shortHostname } from "@scp-dev/broker";
26
26
  import { GENERIC_HARNESSES, LIMITS, validHandle, validHarness } from "@scp-dev/core";
27
27
  var SHORT = { "claude-code": "claude" };
28
28
  var SHELLS = /* @__PURE__ */ new Set(["sh", "bash", "zsh", "dash", "fish"]);
@@ -34,6 +34,61 @@ function detectHarness(env) {
34
34
  if (env.ANTIGRAVITY_AGENT === "1" || env.ANTIGRAVITY_CONVERSATION_ID) return "agy";
35
35
  if (env.CLAUDECODE === "1") return "claude-code";
36
36
  if (env.CODEX_THREAD_ID) return "codex";
37
+ if (inferring(env) && (env.CODEX_SANDBOX || env.CODEX_SANDBOX_NETWORK_DISABLED)) return "codex";
38
+ return void 0;
39
+ }
40
+ var BINDING_KEY = /^[0-9a-f]{1,128}$/;
41
+ var BINDING_PROCESS = /^pid:([1-9][0-9]*):[A-Za-z0-9:-]{1,64}$/;
42
+ function codexShell(env) {
43
+ return env.SCP_HARNESS === "codex" || inferring(env) && detectHarness(env) === "codex";
44
+ }
45
+ function writeShimBinding(claim, env) {
46
+ const pid = BINDING_PROCESS.exec(claim.process)?.[1];
47
+ if (claim.harness !== "codex" || !pid) return () => {
48
+ };
49
+ const text = JSON.stringify({ process: claim.process, handle: claim.handle, harness: claim.harness });
50
+ const names = [`pid-${pid}`, ...BINDING_KEY.test(env.SCP_SHIM_BINDING ?? "") ? [`key-${env.SCP_SHIM_BINDING}`] : []];
51
+ const paths = [];
52
+ for (const name of names) {
53
+ try {
54
+ const path = join(privateDir(join(relayDir(env), "bindings")), `${name}.json`);
55
+ writeFileSync(path, text, { mode: 384 });
56
+ chmodSync(path, 384);
57
+ paths.push(path);
58
+ } catch {
59
+ }
60
+ }
61
+ return () => {
62
+ for (const path of paths) {
63
+ try {
64
+ if (readFileSync(path, "utf8") === text) rmSync(path);
65
+ } catch {
66
+ }
67
+ }
68
+ };
69
+ }
70
+ function readShimBinding(env, pid, table) {
71
+ const read = (name, expectedPid) => {
72
+ try {
73
+ const binding = JSON.parse(readFileSync(join(relayDir(env), "bindings", `${name}.json`), "utf8"));
74
+ const match = typeof binding.process === "string" ? BINDING_PROCESS.exec(binding.process) : null;
75
+ if (match && Number(match[1]) > 1 && (expectedPid === void 0 || Number(match[1]) === expectedPid) && binding.harness === "codex" && typeof binding.handle === "string" && validHandle(binding.handle))
76
+ return binding;
77
+ } catch {
78
+ }
79
+ return void 0;
80
+ };
81
+ if (BINDING_KEY.test(env.SCP_SHIM_BINDING ?? "")) {
82
+ const binding = read(`key-${env.SCP_SHIM_BINDING}`);
83
+ if (binding) return binding;
84
+ }
85
+ const seen = /* @__PURE__ */ new Set();
86
+ while (pid > 1 && !seen.has(pid)) {
87
+ seen.add(pid);
88
+ const entry = table?.get(pid);
89
+ if (!entry) return read(`pid-${pid}`, pid);
90
+ pid = entry.ppid;
91
+ }
37
92
  return void 0;
38
93
  }
39
94
  function normalizeHarness(raw, fallback) {
@@ -342,9 +397,9 @@ function relayIdentity(input) {
342
397
 
343
398
  // src/session.ts
344
399
  import { CLI_NAME } from "@scp-dev/core";
345
- import { readSessionMarker, relayDir } from "@scp-dev/broker";
400
+ import { readSessionMarker, relayDir as relayDir2 } from "@scp-dev/broker";
346
401
  function membership(env, session) {
347
- const marker = readSessionMarker(relayDir(env), session);
402
+ const marker = readSessionMarker(relayDir2(env), session);
348
403
  if (marker?.joined === false) return { dark: `this session left the relay; ${CLI_NAME} join (or relay_join) joins it again` };
349
404
  if (!marker?.joined && joinMode(env) === "manual") return { dark: `this session has not joined the relay; ${CLI_NAME} join <name> (or relay_join) joins it` };
350
405
  return marker?.handle ? { handle: marker.handle } : {};
@@ -471,7 +526,7 @@ var DAEMON_ENV = [
471
526
  ];
472
527
  var LOG_MAX_BYTES = 1024 * 1024;
473
528
  function startDaemon(dir) {
474
- privateDir(dir);
529
+ privateDir2(dir);
475
530
  const logFile = join2(dir, "broker.log");
476
531
  if ((statSync(logFile, { throwIfNoEntry: false })?.size ?? 0) > LOG_MAX_BYTES) truncateSync(logFile, 0);
477
532
  const log = openSync(logFile, "a", 384);
@@ -499,11 +554,18 @@ function localHandle(raw) {
499
554
  if (handle.includes("/")) throw new RelayUsage(`--as names a local handle, not ${JSON.stringify(raw)}`);
500
555
  return handle;
501
556
  }
502
- function walkNow() {
503
- const table = readPsTable();
504
- const self = harnessLineage(process.ppid, table);
557
+ function walkNow(env = process.env, pid = process.ppid, table = readPsTable()) {
558
+ const keys = lineage(pid, table);
559
+ const self = harnessLineage(pid, table);
560
+ if (!self.length && codexShell(env)) {
561
+ const binding = readShimBinding(env, pid, table);
562
+ if (binding) {
563
+ const bound = [...keys, binding.process];
564
+ return { keys: bound, self: bound, harness: "codex" };
565
+ }
566
+ }
505
567
  const harness = self.length ? harnessAt(Number(/^pid:(\d+)/.exec(self.at(-1))?.[1]), table) : void 0;
506
- return { keys: lineage(process.ppid, table), self, ...harness ? { harness } : {} };
568
+ return { keys, self, ...harness ? { harness } : {} };
507
569
  }
508
570
  function claimHarness(values, env, walk) {
509
571
  return values.harness ?? env.SCP_HARNESS ?? (inferring(env) ? walk?.harness ?? detectHarness(env) : void 0) ?? "cli";
@@ -529,7 +591,7 @@ async function open(verb, values, cwd, bodyFromStdin, walk) {
529
591
  `${CLI_NAME2} ${verb} needs an identity: --as HANDLE (or $SCP_NAME) for an agent, or --human for your own inbox me/ (no terminal is attached, so me/ is not assumed)`
530
592
  );
531
593
  }
532
- const { machineName, openCloud } = await import("./remote-P4GFUIAP.js");
594
+ const { machineName, openCloud } = await import("./remote-UQJ5YYCC.js");
533
595
  const handle2 = named ? localHandle(named) : void 0;
534
596
  const claim = handle2 ? {
535
597
  handle: handle2,
@@ -558,7 +620,7 @@ async function open(verb, values, cwd, bodyFromStdin, walk) {
558
620
  const handle = "handle" in joined && joined.handle ? joined.handle : named ? localHandle(named) : void 0;
559
621
  const harnessPid2 = self.length ? Number(/^pid:(\d+)/.exec(self.at(-1))?.[1]) : void 0;
560
622
  const lineageClaim = keys.length ? { lineage: keys } : {};
561
- const dir = relayDir2();
623
+ const dir = relayDir3();
562
624
  const client = await connectBroker(dir, () => startDaemon(dir));
563
625
  try {
564
626
  let bound;
@@ -688,7 +750,7 @@ function checkRelayUrl(text, what = "relay URL") {
688
750
  function readObject(path) {
689
751
  let text;
690
752
  try {
691
- text = readFileSync(path, "utf8");
753
+ text = readFileSync2(path, "utf8");
692
754
  } catch (error) {
693
755
  if (error.code === "ENOENT") return void 0;
694
756
  throw new RelayUsage(`could not read ${path}`);
@@ -704,15 +766,15 @@ function readObject(path) {
704
766
  function writePrivateJson(path, value) {
705
767
  const dir = dirname2(path);
706
768
  mkdirSync(dir, { recursive: true, mode: 448 });
707
- chmodSync(dir, 448);
769
+ chmodSync2(dir, 448);
708
770
  const temp = join3(dir, `.${randomUUID()}.tmp`);
709
771
  try {
710
- writeFileSync(temp, `${JSON.stringify(value, null, 2)}
772
+ writeFileSync2(temp, `${JSON.stringify(value, null, 2)}
711
773
  `, { mode: 384, flag: "wx" });
712
- chmodSync(temp, 384);
774
+ chmodSync2(temp, 384);
713
775
  renameSync(temp, path);
714
776
  } finally {
715
- rmSync(temp, { force: true });
777
+ rmSync2(temp, { force: true });
716
778
  }
717
779
  }
718
780
  function activeRelay(env = process.env) {
@@ -787,7 +849,7 @@ function relayVerb(positionals, asJson, env = process.env) {
787
849
  }
788
850
  async function loginMain(positionals, values) {
789
851
  if (positionals.length) throw new RelayUsage(`${CLI_NAME3} login takes only flags`);
790
- return (await import("./login-AUMLI4FS.js")).login(values);
852
+ return (await import("./login-6MVD3VLC.js")).login(values);
791
853
  }
792
854
  function logoutMain(positionals, asJson, env = process.env) {
793
855
  if (positionals.length) throw new RelayUsage(`${CLI_NAME3} logout takes no arguments`);
@@ -802,6 +864,8 @@ function logoutMain(positionals, asJson, env = process.env) {
802
864
  export {
803
865
  shortHostname,
804
866
  detectHarness,
867
+ codexShell,
868
+ writeShimBinding,
805
869
  normalizeHarness,
806
870
  hookHarness,
807
871
  gitToplevel,
@@ -835,6 +899,7 @@ export {
835
899
  OPTIONS,
836
900
  SPAWN_OPTIONS,
837
901
  startDaemon,
902
+ terminalAttached,
838
903
  localHandle,
839
904
  walkNow,
840
905
  open,
@@ -5,7 +5,7 @@ import {
5
5
  configDir,
6
6
  relayCredential,
7
7
  writePrivateJson
8
- } from "./chunk-2LIJXXTL.js";
8
+ } from "./chunk-AAFHLHXG.js";
9
9
  import {
10
10
  note,
11
11
  printTable
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  hooksTarget
3
- } from "./chunk-Q5UI4Z7H.js";
3
+ } from "./chunk-2342GTME.js";
4
4
  import {
5
5
  AGY_HOOK_SET,
6
6
  BLOCK_STOP,
@@ -12,12 +12,12 @@ import {
12
12
  mergeHooks,
13
13
  musePlugin,
14
14
  opencodePlugin
15
- } from "./chunk-QRWQIHV6.js";
15
+ } from "./chunk-XQHPDNVG.js";
16
16
  import {
17
17
  RelayUsage,
18
18
  gitToplevel,
19
19
  setJoinMode
20
- } from "./chunk-2LIJXXTL.js";
20
+ } from "./chunk-AAFHLHXG.js";
21
21
 
22
22
  // src/setup.ts
23
23
  import { spawnSync } from "child_process";
@@ -13,7 +13,7 @@ import {
13
13
  psStart,
14
14
  relayIdentity,
15
15
  sessionKey
16
- } from "./chunk-2LIJXXTL.js";
16
+ } from "./chunk-AAFHLHXG.js";
17
17
 
18
18
  // src/hooks.ts
19
19
  import { Readable } from "stream";
@@ -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,16 +3,16 @@ 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-UKQBH4AQ.js";
7
+ import "./chunk-2342GTME.js";
8
+ import "./chunk-XQHPDNVG.js";
9
9
  import "./chunk-YYSLYVNZ.js";
10
10
  import {
11
11
  CHANNELS_ENV,
12
12
  RelayUsage,
13
13
  deriveHandle,
14
14
  joinMode
15
- } from "./chunk-2LIJXXTL.js";
15
+ } from "./chunk-AAFHLHXG.js";
16
16
  import "./chunk-MNTIEWKF.js";
17
17
 
18
18
  // src/claude.ts
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-F2NFQ2KC.js");
21
21
  await run(process.argv.slice(2));
22
22
  }
@@ -3,18 +3,18 @@ import {
3
3
  codexMount,
4
4
  codexOverrides,
5
5
  toml
6
- } from "./chunk-3SHVJIXP.js";
6
+ } from "./chunk-7RA7E5WR.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-UKQBH4AQ.js";
9
+ import "./chunk-2342GTME.js";
10
+ import "./chunk-XQHPDNVG.js";
11
11
  import "./chunk-YYSLYVNZ.js";
12
12
  import {
13
13
  RelayUsage,
14
14
  readPsTable,
15
15
  relayIdentity,
16
16
  startDaemon
17
- } from "./chunk-2LIJXXTL.js";
17
+ } from "./chunk-AAFHLHXG.js";
18
18
  import {
19
19
  SELF
20
20
  } from "./chunk-MNTIEWKF.js";
@@ -29,7 +29,7 @@ import { join } from "path";
29
29
  import { PassThrough } from "stream";
30
30
  import { setTimeout as sleep } from "timers/promises";
31
31
  import { connectBroker, relayDir } from "@scp-dev/broker";
32
- import { CLI_NAME, validHandle } from "@scp-dev/core";
32
+ import { CLI_NAME, RelayError, validHandle } from "@scp-dev/core";
33
33
  import { MCP_PROTOCOLS, runRelayMcp } from "@scp-dev/mcp";
34
34
  import { parse } from "smol-toml";
35
35
  var CODEX_HELP = `${CLI_NAME} codex [--name N | --as N] [--headless] [--resume THREAD] [--] [codex args...]
@@ -61,13 +61,13 @@ function codexLaunch(args, env, _self) {
61
61
  }
62
62
  name = name?.replace(/^me\//, "");
63
63
  if (name !== void 0 && !validHandle(name)) throw new RelayUsage(`${JSON.stringify(name)} is not a valid agent handle`);
64
- const { SCP_SESSION: _session, SCP_GRANT: _grant, SCP_PARENT: _parent, ...clean } = env;
64
+ const { SCP_SESSION: _session, SCP_PARENT: _parent, ...clean } = env;
65
65
  return {
66
66
  ...name !== void 0 ? { name } : {},
67
67
  headless,
68
68
  ...resume !== void 0 ? { resume } : {},
69
69
  codexArgs: resume !== void 0 && !headless ? ["resume", resume, ...codexArgs] : codexArgs,
70
- env: { ...clean, SCP_HARNESS: "codex", ...name !== void 0 ? { SCP_NAME: name } : {} }
70
+ env: { ...clean, SCP_HARNESS: "codex", SCP_SHIM_BINDING: randomBytes(16).toString("hex"), ...name !== void 0 ? { SCP_NAME: name } : {} }
71
71
  };
72
72
  }
73
73
  var CodexSocket = class {
@@ -398,6 +398,24 @@ function appServerPid(pid) {
398
398
  }
399
399
  return pid;
400
400
  }
401
+ async function connectCodexChannel(connect2, claim, cwd, stopped) {
402
+ while (!stopped()) {
403
+ const client = await connect2();
404
+ try {
405
+ const hello = await client.hello({ observe: true, self: [claim.process], ...claim.grant ? { grant: claim.grant } : {}, cwd });
406
+ if (hello.endpoint) {
407
+ client.hello = async () => hello;
408
+ return client;
409
+ }
410
+ } catch (error) {
411
+ client.close();
412
+ if (!claim.grant || !(error instanceof RelayError) || error.code !== "unauthorized") throw error;
413
+ }
414
+ client.close();
415
+ await sleep(100);
416
+ }
417
+ throw new Error("codex channel stopped");
418
+ }
401
419
  async function codexCommand(args) {
402
420
  if (args[0] === "--help" || args[0] === "-h") {
403
421
  process.stdout.write(`${CODEX_HELP}
@@ -514,24 +532,12 @@ ${stderr.toString().trim()}` : ""}`
514
532
  const broker = relayDir(launch.env);
515
533
  let lines = "";
516
534
  channel = runRelayMcp({
517
- connect: async () => {
518
- while (!input.writableEnded) {
519
- const client = await connectBroker(broker, () => startDaemon(broker));
520
- try {
521
- const hello = await client.hello({ observe: true, self: [claim.process], cwd });
522
- if (hello.endpoint) {
523
- client.hello = async () => hello;
524
- return client;
525
- }
526
- } catch (error) {
527
- client.close();
528
- throw error;
529
- }
530
- client.close();
531
- await sleep(100);
532
- }
533
- throw new Error("codex channel stopped");
534
- },
535
+ connect: () => connectCodexChannel(
536
+ () => connectBroker(broker, () => startDaemon(broker)),
537
+ claim,
538
+ cwd,
539
+ () => input.writableEnded
540
+ ),
535
541
  claim,
536
542
  channels: true,
537
543
  wake: "codex-app-server",
@@ -611,5 +617,6 @@ export {
611
617
  CodexWaker,
612
618
  codexCommand,
613
619
  codexLaunch,
620
+ connectCodexChannel,
614
621
  serverOptions
615
622
  };
@@ -40,11 +40,11 @@ import {
40
40
  tldrEvery,
41
41
  transcriptTitle,
42
42
  unreadPointer
43
- } from "./chunk-QRWQIHV6.js";
43
+ } from "./chunk-XQHPDNVG.js";
44
44
  import {
45
45
  SUBAGENT
46
46
  } from "./chunk-YYSLYVNZ.js";
47
- import "./chunk-2LIJXXTL.js";
47
+ import "./chunk-AAFHLHXG.js";
48
48
  import "./chunk-MNTIEWKF.js";
49
49
  export {
50
50
  AGY_HOOK_SET,
@@ -2,10 +2,10 @@ import {
2
2
  hooksTarget,
3
3
  installHooks,
4
4
  mcpInstall
5
- } from "./chunk-Q5UI4Z7H.js";
6
- import "./chunk-QRWQIHV6.js";
5
+ } from "./chunk-2342GTME.js";
6
+ import "./chunk-XQHPDNVG.js";
7
7
  import "./chunk-YYSLYVNZ.js";
8
- import "./chunk-2LIJXXTL.js";
8
+ import "./chunk-AAFHLHXG.js";
9
9
  import "./chunk-MNTIEWKF.js";
10
10
  export {
11
11
  hooksTarget,
@@ -1,12 +1,13 @@
1
1
  import {
2
2
  RelayUsage,
3
+ codexShell,
3
4
  harnessAt,
4
5
  localHandle,
5
6
  relayIdentity,
6
7
  sessionKey,
7
8
  startDaemon,
8
9
  walkNow
9
- } from "./chunk-2LIJXXTL.js";
10
+ } from "./chunk-AAFHLHXG.js";
10
11
  import "./chunk-MNTIEWKF.js";
11
12
 
12
13
  // src/join.ts
@@ -18,7 +19,10 @@ async function joinCommand(values, positionals, cwd, out) {
18
19
  const { keys, self } = walkNow();
19
20
  const key = self.at(-1);
20
21
  const match = key === void 0 ? null : /^pid:(\d+):(.+)$/.exec(key);
21
- if (!match) throw new RelayUsage(`${CLI_NAME} join runs in an agent session's shell: no harness process runs this shell`);
22
+ if (!match) {
23
+ if (codexShell(process.env)) throw new RelayUsage(`${CLI_NAME} join: the codex sandbox hides the harness; use relay_join (MCP) instead`);
24
+ throw new RelayUsage(`${CLI_NAME} join runs in an agent session's shell: no harness process runs this shell`);
25
+ }
22
26
  const dir = relayDir();
23
27
  const known = readSessionMarker(dir, sessionKey(process.env, key))?.handle;
24
28
  const claim = relayIdentity({
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  machineName
3
- } from "./chunk-IEFXYBX7.js";
3
+ } from "./chunk-H2XQXMZU.js";
4
4
  import {
5
5
  RelayUsage,
6
6
  activeRelay,
7
7
  saveCredential
8
- } from "./chunk-2LIJXXTL.js";
8
+ } from "./chunk-AAFHLHXG.js";
9
9
  import {
10
10
  note
11
11
  } from "./chunk-MNTIEWKF.js";
@@ -14,8 +14,9 @@ import {
14
14
  shortHostname,
15
15
  stamp,
16
16
  startDaemon,
17
+ terminalAttached,
17
18
  time
18
- } from "./chunk-2LIJXXTL.js";
19
+ } from "./chunk-AAFHLHXG.js";
19
20
  import {
20
21
  FAILED,
21
22
  exitFlushed,
@@ -34,7 +35,7 @@ import { parseArgs } from "util";
34
35
  // package.json
35
36
  var package_default = {
36
37
  name: "@scp-dev/cli",
37
- version: "0.3.1",
38
+ version: "0.5.0",
38
39
  description: "The swarm command line tool.",
39
40
  license: "Apache-2.0",
40
41
  homepage: "https://scp.dev",
@@ -105,6 +106,8 @@ results back, as with native subagents.
105
106
  ${CLI_NAME} list [--all] agents on the relay: address, title, presence, wake, status; --all adds offline ones
106
107
  ${CLI_NAME} join [name] put this session on the relay, named once: ${CLI_NAME} join lead (${CLI_NAME} name renames it)
107
108
  ${CLI_NAME} join --under <parent> link this session under an orchestrator, as a spawned worker sits: ${CLI_NAME} join --under lead
109
+ ${CLI_NAME} adopt <child> ask a local root agent to link under you; it accepts with ${CLI_NAME} link accept <id>
110
+ ${CLI_NAME} link accept <id> accept a link request and sit under its sender as a worker
108
111
  ${CLI_NAME} status [id] the fleet in short; with the id of a message you sent: who read it when
109
112
  ${CLI_NAME} peek <ep> a short, redacted view of a peekable agent's last turns: ${CLI_NAME} peek rev
110
113
  ${CLI_NAME} set-status <state> [note] working, waiting, blocked or done: ${CLI_NAME} set-status done "PR open"
@@ -286,13 +289,20 @@ agent sessions:
286
289
  and title stay; a handle another endpoint holds, live or offline, is refused;
287
290
  a spawned worker is named by its spawner (policy defaults.rename: self lets it);
288
291
  --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
292
+ ${CLI_NAME} join [<handle>] --under <parent> link the session under the agent <parent> (one it may message), as if
290
293
  <parent> had spawned it: it shows under <parent> in list --tree, the dashboard
291
294
  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
295
+ default it reaches only what <parent> reaches). Narrowing, so always allowed.
296
+ <parent> may be on another machine of the account (me/<machine>/<handle>):
297
+ the session stays a root there, takes no child scope, and the two reach
298
+ each other both ways
293
299
  ${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.
295
- An agent without a terminal is refused: the session joins with --under itself
300
+ <p> may be on another machine of the account (me/<machine>/<handle>).
301
+ With --parent and a terminal, inherited $SCP_NAME and $SCP_GRANT are ignored
302
+ unless --as is explicit. An agent without a terminal asks the child to consent,
303
+ under itself only; the child accepts with link accept or join --under
304
+ ${CLI_NAME} link accept <id> accept a link request delivered to this session and sit under its sender as a worker;
305
+ <id> is the full or short message id. Only the session itself may accept
296
306
  ${CLI_NAME} unlink [<child>] put a linked agent back at the root, its subtree along and the child scope off;
297
307
  widening, so the human at a terminal only (policy defaults.unlink: self lets
298
308
  an agent unlink itself). A link that would put a parent under its own child
@@ -383,6 +393,7 @@ var VERBS = {
383
393
  send: [...IDENTITY, "reply-to", "thread", "private", "attach", "live"],
384
394
  join: ["harness", "json", "under"],
385
395
  adopt: [...IDENTITY, "parent"],
396
+ link: IDENTITY,
386
397
  unlink: IDENTITY,
387
398
  leave: [...IDENTITY, "endpoint"],
388
399
  name: [...IDENTITY, "endpoint"],
@@ -558,14 +569,14 @@ async function relayMain(argv, cwd = process.cwd()) {
558
569
  out(cliVersion());
559
570
  return 0;
560
571
  }
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);
564
- 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);
572
+ if (verb === "hook") return (await import("./hooks-BZANUJPY.js")).relayHookCommand(rest, startDaemon);
573
+ if (verb === "setup") return (await import("./setup-UJCIMYU4.js")).relaySetupCommand(rest, cwd, out);
574
+ if (verb === "claude") return (await import("./claude-RNH2E4GU.js")).claudeCommand(rest);
575
+ if (verb === "pi") return (await import("./pi-N3DX37PD.js")).piCommand(rest);
576
+ if (verb === "codex") return (await import("./codex-OSGHQMK6.js")).codexCommand(rest);
577
+ if (verb === "opencode") return (await import("./opencode-XV33XTL5.js")).opencodeCommand(rest, process.env, void 0, cwd);
567
578
  if (verb === "spawn") {
568
- const { splitSpawn, spawnCommand } = await import("./spawn-GG7VFZA6.js");
579
+ const { splitSpawn, spawnCommand } = await import("./spawn-JYD7NCQT.js");
569
580
  const { flags } = splitSpawn(rest);
570
581
  if (flags.includes("--help") || flags.includes("-h")) {
571
582
  out(flags.includes("--all") ? RELAY_HELP : SPAWN_HELP);
@@ -573,7 +584,7 @@ async function relayMain(argv, cwd = process.cwd()) {
573
584
  }
574
585
  return spawnCommand(rest, cwd);
575
586
  }
576
- if (verb === "mesh") return (await import("./mesh-H4KL5XAR.js")).meshCommand(rest);
587
+ if (verb === "mesh") return (await import("./mesh-OZILTV5P.js")).meshCommand(rest);
577
588
  const allowed = VERBS[verb];
578
589
  if (!allowed) throw new RelayUsage(`unknown command "${verb}"`);
579
590
  let parsed;
@@ -593,11 +604,11 @@ async function relayMain(argv, cwd = process.cwd()) {
593
604
  return daemon(values.idle, values.policy);
594
605
  }
595
606
  if (verb === "mcp")
596
- return (await import("./mcp-VXBRMQB7.js")).relayMcpCommand(values, positionals);
607
+ return (await import("./mcp-BH526TOG.js")).relayMcpCommand(values, positionals);
597
608
  if (verb === "hooks") {
598
609
  if (positionals[0] !== "install" || positionals.length > 1) throw new RelayUsage(`${CLI_NAME} hooks takes install --harness claude|codex|opencode|agy|muse`);
599
610
  if (values.write && values.print) throw new RelayUsage("--print and --write: pick one");
600
- return (await import("./install-6KXJY27V.js")).installHooks({
611
+ return (await import("./install-25J5QB63.js")).installHooks({
601
612
  harness: values.harness,
602
613
  scope: values.scope,
603
614
  write: values.write === true,
@@ -608,31 +619,48 @@ async function relayMain(argv, cwd = process.cwd()) {
608
619
  out
609
620
  });
610
621
  }
611
- 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);
622
+ if (verb === "relay") return (await import("./relay-SF3UWIPM.js")).relayVerb(positionals, values.json === true);
623
+ if (verb === "up") return (await import("./up-3YJU7YX6.js")).up(positionals, values, cwd, relinkBroker);
613
624
  if (verb === "login") {
614
- const code = await (await import("./relay-QWJM372C.js")).loginMain(positionals, values);
625
+ const code = await (await import("./relay-SF3UWIPM.js")).loginMain(positionals, values);
615
626
  if (code === 0) await relinkRunning();
616
627
  return code;
617
628
  }
618
- if (verb === "logout") return (await import("./relay-QWJM372C.js")).logoutMain(positionals, values.json === true);
629
+ if (verb === "logout") return (await import("./relay-SF3UWIPM.js")).logoutMain(positionals, values.json === true);
619
630
  if (verb === "cloud") {
620
- const code = await (await import("./remote-P4GFUIAP.js")).cloudMain(positionals, values, cloudStatus);
631
+ const code = await (await import("./remote-UQJ5YYCC.js")).cloudMain(positionals, values, cloudStatus);
621
632
  if (code === 0 && positionals[0] === "enable") await relinkRunning();
622
633
  return code;
623
634
  }
624
- if (verb === "join") return (await import("./join-FITJVZCA.js")).joinCommand(values, positionals, cwd, out);
635
+ if (verb === "join") return (await import("./join-EOLHE3LJ.js")).joinCommand(values, positionals, cwd, out);
625
636
  if (verb === "holds") holdsArgs(values, positionals);
626
637
  const bodyFromStdin = (verb === "send" || verb === "ask" || verb === "reply") && (positionals[1] === void 0 || positionals[1] === "-");
627
- const opened = await open(verb, values, cwd, bodyFromStdin);
638
+ const humanAdopt = verb === "adopt" && values.parent !== void 0 && values.as === void 0 && terminalAttached(process, false);
639
+ const opened = humanAdopt ? await openAdoptHuman(cwd, values) : await open(verb, values, cwd, bodyFromStdin);
628
640
  const { client } = opened;
629
641
  try {
630
- if (verb === "machines") return await (await import("./remote-P4GFUIAP.js")).machinesVerb(client, positionals, values.json === true);
642
+ if (verb === "machines") return await (await import("./remote-UQJ5YYCC.js")).machinesVerb(client, positionals, values.json === true);
631
643
  return await runVerb(opened, verb, values, positionals, cwd);
632
644
  } finally {
633
645
  client.close();
634
646
  }
635
647
  }
648
+ async function openAdoptHuman(cwd, values) {
649
+ if (values.cloud || process.env.SCP_TRANSPORT === "cloud") {
650
+ const { openCloud } = await import("./remote-UQJ5YYCC.js");
651
+ return { ...await openCloud({ tty: true, ...values.machine !== void 0 ? { machine: values.machine } : {} }), broker: null, bound: "human" };
652
+ }
653
+ if (values.machine !== void 0) throw new RelayUsage("--machine names the machine of the cloud transport: add --cloud");
654
+ const dir = relayDir();
655
+ const client = await connectBroker(dir, () => startDaemon(dir));
656
+ try {
657
+ const hello = await client.hello({ human: true, tty: true, cwd, brief: true });
658
+ return { client, me: hello.endpoint, broker: hello.broker, where: brokerLine(hello.broker), bound: "human" };
659
+ } catch (error) {
660
+ client.close();
661
+ throw error;
662
+ }
663
+ }
636
664
  async function cloudStatus() {
637
665
  const dir = relayDir();
638
666
  const client = await connectBroker(dir, () => startDaemon(dir));
@@ -804,9 +832,9 @@ async function runVerb({ client, me, broker, where, bound, harnessPid }, verb, v
804
832
  return 0;
805
833
  }
806
834
  case "peek":
807
- return (await import("./peek-YTCWVPF7.js")).peekCommand(localClient(client, broker, verb), values, positionals);
835
+ return (await import("./peek-LFQR6TCS.js")).peekCommand(localClient(client, broker, verb), values, positionals);
808
836
  case "set-peek":
809
- return (await import("./peek-YTCWVPF7.js")).setPeekCommand(localClient(client, broker, verb), values, positionals);
837
+ return (await import("./peek-LFQR6TCS.js")).setPeekCommand(localClient(client, broker, verb), values, positionals);
810
838
  case "why": {
811
839
  const [from, to] = positionals;
812
840
  if (!from || !to || positionals.length > 2) throw new RelayUsage(`${CLI_NAME} why takes <from> <to>`);
@@ -1045,6 +1073,16 @@ async function runVerb({ client, me, broker, where, bound, harnessPid }, verb, v
1045
1073
  ...parent !== void 0 ? { parent } : {}
1046
1074
  });
1047
1075
  if (asJson) json(result);
1076
+ else if (result.held) out(heldText(result.held));
1077
+ else if (result.requested)
1078
+ out(`asked ${result.endpoint.address} to link under ${result.parent}; it accepts with ${CLI_NAME} link accept ${shortId(result.requested)}`);
1079
+ else out(`${result.endpoint.address} now sits under ${result.parent}`);
1080
+ return 0;
1081
+ }
1082
+ case "link": {
1083
+ if (positionals.length !== 2 || positionals[0] !== "accept") throw new RelayUsage(`${CLI_NAME} link takes accept <id>`);
1084
+ const result = await client.request("link_accept", { id: positionals[1] });
1085
+ if (asJson) json(result);
1048
1086
  else out(`${result.endpoint.address} now sits under ${result.parent}`);
1049
1087
  return 0;
1050
1088
  }
@@ -1416,11 +1454,11 @@ async function daemon(idle, policyFile) {
1416
1454
  });
1417
1455
  let broker;
1418
1456
  try {
1419
- const { daemonBridge } = await import("./remote-P4GFUIAP.js");
1457
+ const { daemonBridge } = await import("./remote-UQJ5YYCC.js");
1420
1458
  const bridge = await daemonBridge();
1421
1459
  broker = await startBroker({
1422
1460
  dir: relayDir(),
1423
- ...bridge ? { bridge } : await (await import("./mesh-H4KL5XAR.js")).meshBrokerOptions(),
1461
+ ...bridge ? { bridge } : await (await import("./mesh-OZILTV5P.js")).meshBrokerOptions(),
1424
1462
  bridgeConfig: () => daemonBridge(),
1425
1463
  ...idleMs !== void 0 ? { idleMs } : {},
1426
1464
  ...policyFile ? { policyPath: resolve(policyFile) } : {}
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  spawnDetached
3
- } from "./chunk-3SHVJIXP.js";
3
+ } from "./chunk-7RA7E5WR.js";
4
4
  import "./chunk-KN7WEIE4.js";
5
- import "./chunk-2OSUVJ2J.js";
5
+ import "./chunk-UKQBH4AQ.js";
6
6
  import {
7
7
  mcpInstall
8
- } from "./chunk-Q5UI4Z7H.js";
9
- import "./chunk-QRWQIHV6.js";
8
+ } from "./chunk-2342GTME.js";
9
+ import "./chunk-XQHPDNVG.js";
10
10
  import "./chunk-YYSLYVNZ.js";
11
11
  import {
12
12
  CHANNELS_ENV,
@@ -16,14 +16,15 @@ import {
16
16
  membership,
17
17
  psParent,
18
18
  relayIdentity,
19
- startDaemon
20
- } from "./chunk-2LIJXXTL.js";
19
+ startDaemon,
20
+ writeShimBinding
21
+ } from "./chunk-AAFHLHXG.js";
21
22
  import "./chunk-MNTIEWKF.js";
22
23
 
23
24
  // src/mcp.ts
24
25
  import { CLI_NAME, validHandle } from "@scp-dev/core";
25
26
  import { connectBroker, relayDir } from "@scp-dev/broker";
26
- import { runRelayMcp } from "@scp-dev/mcp";
27
+ import { runRelayMcp, sessionInboxOf } from "@scp-dev/mcp";
27
28
  var ORPHAN_CHECK_MS = 5e3;
28
29
  async function relayMcpCommand(values, positionals) {
29
30
  if (positionals[0] === "install") {
@@ -43,25 +44,35 @@ async function relayMcpCommand(values, positionals) {
43
44
  inferHarness: (pid) => harnessAt(pid)
44
45
  });
45
46
  if (!validHandle(claim.handle)) throw new RelayUsage(`${JSON.stringify(claim.handle)} is not a valid agent handle (me, user and relay are reserved)`);
46
- const dir = relayDir();
47
+ const dir = relayDir(process.env);
48
+ const unbind = writeShimBinding(claim, process.env);
49
+ process.on("exit", unbind);
47
50
  const parent = process.ppid;
48
51
  const orphaned = setInterval(() => {
49
52
  if (process.ppid !== parent) process.exit(0);
50
53
  }, ORPHAN_CHECK_MS);
51
54
  orphaned.unref();
52
- await runRelayMcp({
53
- connect: () => connectBroker(dir, () => startDaemon(dir)),
54
- claim,
55
- membership: () => membership(process.env, claim.session),
56
- input: process.stdin,
57
- output: (line) => void process.stdout.write(line),
58
- env: process.env,
59
- channels: values.channels === true,
60
- launchedWithChannels: values.channels === true && launchedWithChannels(process.env),
61
- spawn: (request) => spawnDetached(spawnWords(request), request.cwd ?? claim.cwd),
62
- log: (line) => void process.stderr.write(`${line}
55
+ const inbox = sessionInboxOf(process.env);
56
+ try {
57
+ await runRelayMcp({
58
+ connect: () => connectBroker(dir, () => startDaemon(dir)),
59
+ claim,
60
+ membership: () => membership(process.env, claim.session),
61
+ input: process.stdin,
62
+ output: (line) => void process.stdout.write(line),
63
+ env: process.env,
64
+ channels: values.channels === true,
65
+ launchedWithChannels: values.channels === true && launchedWithChannels(process.env),
66
+ ...inbox ? { sessionInbox: inbox } : {},
67
+ spawn: (request) => spawnDetached(spawnWords(request), request.cwd ?? claim.cwd),
68
+ log: (line) => void process.stderr.write(`${line}
63
69
  `)
64
- });
70
+ });
71
+ } finally {
72
+ clearInterval(orphaned);
73
+ process.off("exit", unbind);
74
+ unbind();
75
+ }
65
76
  return 0;
66
77
  }
67
78
  function spawnWords(request) {
@@ -0,0 +1,53 @@
1
+ import {
2
+ RelayUsage
3
+ } from "./chunk-AAFHLHXG.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,18 +2,18 @@ import {
2
2
  mcpFile,
3
3
  mountedEntry,
4
4
  whichOnPath
5
- } from "./chunk-2OSUVJ2J.js";
5
+ } from "./chunk-UKQBH4AQ.js";
6
6
  import {
7
7
  hooksTarget
8
- } from "./chunk-Q5UI4Z7H.js";
8
+ } from "./chunk-2342GTME.js";
9
9
  import {
10
10
  opencodePlugin
11
- } from "./chunk-QRWQIHV6.js";
11
+ } from "./chunk-XQHPDNVG.js";
12
12
  import "./chunk-YYSLYVNZ.js";
13
13
  import {
14
14
  RelayUsage,
15
15
  gitToplevel
16
- } from "./chunk-2LIJXXTL.js";
16
+ } from "./chunk-AAFHLHXG.js";
17
17
  import "./chunk-MNTIEWKF.js";
18
18
 
19
19
  // src/opencode.ts
@@ -2,7 +2,7 @@ import {
2
2
  RelayUsage,
3
3
  peekGrant,
4
4
  stamp
5
- } from "./chunk-2LIJXXTL.js";
5
+ } from "./chunk-AAFHLHXG.js";
6
6
  import {
7
7
  note
8
8
  } from "./chunk-MNTIEWKF.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  RelayUsage
3
- } from "./chunk-2LIJXXTL.js";
3
+ } from "./chunk-AAFHLHXG.js";
4
4
  import "./chunk-MNTIEWKF.js";
5
5
 
6
6
  // src/pi.ts
@@ -13,7 +13,7 @@ import {
13
13
  saveCredential,
14
14
  setJoinMode,
15
15
  writePrivateJson
16
- } from "./chunk-2LIJXXTL.js";
16
+ } from "./chunk-AAFHLHXG.js";
17
17
  import "./chunk-MNTIEWKF.js";
18
18
  export {
19
19
  DEFAULT_RELAY,
@@ -9,8 +9,8 @@ import {
9
9
  machinesVerb,
10
10
  openCloud,
11
11
  readCloudFile
12
- } from "./chunk-IEFXYBX7.js";
13
- import "./chunk-2LIJXXTL.js";
12
+ } from "./chunk-H2XQXMZU.js";
13
+ import "./chunk-AAFHLHXG.js";
14
14
  import "./chunk-MNTIEWKF.js";
15
15
  export {
16
16
  CloudRelayClient,
@@ -15,11 +15,11 @@ 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-UKQBH4AQ.js";
19
+ import "./chunk-2342GTME.js";
20
+ import "./chunk-XQHPDNVG.js";
21
21
  import "./chunk-YYSLYVNZ.js";
22
- import "./chunk-2LIJXXTL.js";
22
+ import "./chunk-AAFHLHXG.js";
23
23
  import "./chunk-MNTIEWKF.js";
24
24
  export {
25
25
  SETUP_HARNESSES,
@@ -31,15 +31,15 @@ import {
31
31
  toml,
32
32
  transcriptReplies,
33
33
  workerName
34
- } from "./chunk-3SHVJIXP.js";
34
+ } from "./chunk-7RA7E5WR.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-UKQBH4AQ.js";
39
+ import "./chunk-2342GTME.js";
40
+ import "./chunk-XQHPDNVG.js";
41
41
  import "./chunk-YYSLYVNZ.js";
42
- import "./chunk-2LIJXXTL.js";
42
+ import "./chunk-AAFHLHXG.js";
43
43
  import "./chunk-MNTIEWKF.js";
44
44
  export {
45
45
  CODEX_VALUED,
@@ -2,7 +2,7 @@ import {
2
2
  RelayUsage,
3
3
  activeRelay,
4
4
  relayCredential
5
- } from "./chunk-2LIJXXTL.js";
5
+ } from "./chunk-AAFHLHXG.js";
6
6
  import "./chunk-MNTIEWKF.js";
7
7
 
8
8
  // src/up.ts
@@ -29,21 +29,21 @@ async function up(positionals, values, cwd, brokerStatus) {
29
29
  const { url } = activeRelay(process.env);
30
30
  const headless = values.token !== void 0 || Boolean(process.env.SCP_TOKEN?.trim());
31
31
  if (headless || !relayCredential(process.env, url).token) {
32
- const code = await (await import("./login-AUMLI4FS.js")).login({
32
+ const code = await (await import("./login-6MVD3VLC.js")).login({
33
33
  ...values.token !== void 0 ? { token: values.token } : {},
34
34
  ...values.label !== void 0 ? { label: values.label } : {},
35
35
  ...values["no-browser"] ? { "no-browser": true } : {}
36
36
  });
37
37
  if (code !== 0) return code;
38
38
  } else out(`already logged in to ${url}`);
39
- const enabled = await (await import("./remote-P4GFUIAP.js")).cloudMain(["enable"], values.machine !== void 0 ? { machine: values.machine } : {}, brokerStatus);
39
+ const enabled = await (await import("./remote-UQJ5YYCC.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-UJCIMYU4.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-UJCIMYU4.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.5.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.3.0",
28
+ "@scp-dev/broker": "0.4.0",
29
+ "@scp-dev/hub": "0.6.1",
30
+ "@scp-dev/mcp": "0.2.0",
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.7",
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
- };