@scp-dev/cli 0.2.0 → 0.2.1

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 (30) hide show
  1. package/README.md +1 -0
  2. package/dist/{chunk-GH7AXFUL.js → chunk-25ZVL5LD.js} +8 -10
  3. package/dist/{chunk-RXKBND3T.js → chunk-HF4KP6AR.js} +229 -13
  4. package/dist/{chunk-5DYFYLAQ.js → chunk-KC5AV5NQ.js} +3 -5
  5. package/dist/{chunk-M2DCR2J4.js → chunk-MNTIEWKF.js} +13 -3
  6. package/dist/{chunk-U2RSSTNW.js → chunk-MXQ7B3CQ.js} +3 -5
  7. package/dist/{chunk-WV5FINTW.js → chunk-NJLFHBSS.js} +20 -10
  8. package/dist/chunk-ZLL5EGI2.js +805 -0
  9. package/dist/{claude-YJLGFQ2P.js → claude-WTCPUYU3.js} +21 -11
  10. package/dist/cli.js +1 -1
  11. package/dist/codex-YZZNH6IQ.js +565 -0
  12. package/dist/{daemon-SUTLTY5U.js → daemon-OMJY7T2F.js} +1 -1
  13. package/dist/{hooks-EI7M3YKY.js → hooks-4B5NOH7X.js} +19 -3
  14. package/dist/install-2ZM3IYXG.js +14 -0
  15. package/dist/join-BH5CS6SL.js +45 -0
  16. package/dist/{login-V2WT7QX5.js → login-UB72MU7W.js} +4 -7
  17. package/dist/{main-HPBTO3JK.js → main-I4F53MMA.js} +79 -31
  18. package/dist/{mcp-DGAQNFKO.js → mcp-RXAVQBMP.js} +11 -11
  19. package/dist/{peek-WLG3ZROU.js → peek-M2HQVO4O.js} +2 -3
  20. package/dist/{pi-HMESQA64.js → pi-IAVFVOOO.js} +2 -3
  21. package/dist/{relay-5Z7IEXKD.js → relay-QDX2BNZH.js} +6 -4
  22. package/dist/{remote-FYN5ZXE4.js → remote-2OWBWLJH.js} +3 -5
  23. package/dist/{setup-LXG346FJ.js → setup-HPH7HE6O.js} +5 -6
  24. package/dist/{spawn-DLPMAS5M.js → spawn-V66GYUNC.js} +6 -7
  25. package/dist/{up-GPM4LWY3.js → up-2YGEDA5J.js} +6 -9
  26. package/package.json +7 -5
  27. package/dist/chunk-3RRPUYTE.js +0 -147
  28. package/dist/chunk-3V3DRXB2.js +0 -340
  29. package/dist/chunk-E53YHYEP.js +0 -305
  30. package/dist/install-MYHVFKT4.js +0 -15
@@ -5,10 +5,14 @@ import {
5
5
  DIRECTIVE_CLOSE,
6
6
  HOOK_COMMAND,
7
7
  NO_INJECT,
8
+ OPENCODE_WAKE,
8
9
  PARENT_EXCEPTION,
9
10
  PUSH_WAIT,
10
11
  PUSH_WAIT_DEFAULT_S,
11
12
  REPLY_HOW,
13
+ TLDR,
14
+ TLDR_EVERY_DEFAULT,
15
+ WAKE,
12
16
  agyHookSet,
13
17
  claudeVersionFile,
14
18
  hasOurHooks,
@@ -21,6 +25,7 @@ import {
21
25
  musePlugin,
22
26
  nudgeText,
23
27
  opencodePlugin,
28
+ promptTitle,
24
29
  pushText,
25
30
  pushWait,
26
31
  relayHookCommand,
@@ -29,13 +34,16 @@ import {
29
34
  stopContinues,
30
35
  subagentIntro,
31
36
  summarize,
37
+ titleText,
38
+ tldrEvery,
39
+ transcriptTitle,
32
40
  unreadPointer
33
- } from "./chunk-RXKBND3T.js";
41
+ } from "./chunk-HF4KP6AR.js";
34
42
  import {
35
43
  SUBAGENT
36
44
  } from "./chunk-YYSLYVNZ.js";
37
- import "./chunk-E53YHYEP.js";
38
- import "./chunk-M2DCR2J4.js";
45
+ import "./chunk-ZLL5EGI2.js";
46
+ import "./chunk-MNTIEWKF.js";
39
47
  export {
40
48
  AGY_HOOK_SET,
41
49
  AGY_UNVERIFIED,
@@ -43,11 +51,15 @@ export {
43
51
  DIRECTIVE_CLOSE,
44
52
  HOOK_COMMAND,
45
53
  NO_INJECT,
54
+ OPENCODE_WAKE,
46
55
  PARENT_EXCEPTION,
47
56
  PUSH_WAIT,
48
57
  PUSH_WAIT_DEFAULT_S,
49
58
  REPLY_HOW,
50
59
  SUBAGENT,
60
+ TLDR,
61
+ TLDR_EVERY_DEFAULT,
62
+ WAKE,
51
63
  agyHookSet,
52
64
  claudeVersionFile,
53
65
  hasOurHooks,
@@ -60,6 +72,7 @@ export {
60
72
  musePlugin,
61
73
  nudgeText,
62
74
  opencodePlugin,
75
+ promptTitle,
63
76
  pushText,
64
77
  pushWait,
65
78
  relayHookCommand,
@@ -68,5 +81,8 @@ export {
68
81
  stopContinues,
69
82
  subagentIntro,
70
83
  summarize,
84
+ titleText,
85
+ tldrEvery,
86
+ transcriptTitle,
71
87
  unreadPointer
72
88
  };
@@ -0,0 +1,14 @@
1
+ import {
2
+ hooksTarget,
3
+ installHooks,
4
+ mcpInstall
5
+ } from "./chunk-KC5AV5NQ.js";
6
+ import "./chunk-HF4KP6AR.js";
7
+ import "./chunk-YYSLYVNZ.js";
8
+ import "./chunk-ZLL5EGI2.js";
9
+ import "./chunk-MNTIEWKF.js";
10
+ export {
11
+ hooksTarget,
12
+ installHooks,
13
+ mcpInstall
14
+ };
@@ -0,0 +1,45 @@
1
+ import {
2
+ RelayUsage,
3
+ localHandle,
4
+ relayIdentity,
5
+ sessionKey,
6
+ startDaemon,
7
+ walkNow
8
+ } from "./chunk-ZLL5EGI2.js";
9
+ import "./chunk-MNTIEWKF.js";
10
+
11
+ // src/join.ts
12
+ import { CLI_NAME } from "@scp-dev/core";
13
+ import { connectBroker, readSessionMarker, relayDir } from "@scp-dev/broker";
14
+ async function joinCommand(values, positionals, cwd, out) {
15
+ if (positionals.length > 1) throw new RelayUsage(`${CLI_NAME} join takes one handle, or none to keep the session's name`);
16
+ const handle = positionals[0] === void 0 ? void 0 : localHandle(positionals[0]);
17
+ const { keys, self } = walkNow();
18
+ const key = self.at(-1);
19
+ const match = key === void 0 ? null : /^pid:(\d+):(.+)$/.exec(key);
20
+ if (!match) throw new RelayUsage(`${CLI_NAME} join runs in an agent session's shell: no harness process runs this shell`);
21
+ const dir = relayDir();
22
+ const known = readSessionMarker(dir, sessionKey(process.env, key))?.handle;
23
+ const claim = relayIdentity({
24
+ ...known ? { as: known } : {},
25
+ ...typeof values.harness === "string" ? { harness: values.harness } : {},
26
+ fallbackHarness: "cli",
27
+ cwd,
28
+ env: process.env,
29
+ harnessPid: () => Number(match[1]),
30
+ startOf: () => match[2],
31
+ lineageOf: () => keys.slice(Math.max(0, keys.indexOf(key)))
32
+ });
33
+ const client = await connectBroker(dir, () => startDaemon(dir));
34
+ try {
35
+ const hello = await client.hello({ transient: true, claim, join: handle ? { handle } : {} });
36
+ if (values.json === true) out(JSON.stringify(hello.endpoint, null, 2));
37
+ else out(`joined as ${hello.endpoint.address}: peers can message it, and its hooks hand it new messages at turn boundaries`);
38
+ } finally {
39
+ client.close();
40
+ }
41
+ return 0;
42
+ }
43
+ export {
44
+ joinCommand
45
+ };
@@ -1,17 +1,14 @@
1
1
  import {
2
2
  machineName
3
- } from "./chunk-U2RSSTNW.js";
3
+ } from "./chunk-MXQ7B3CQ.js";
4
4
  import {
5
+ RelayUsage,
5
6
  activeRelay,
6
7
  saveCredential
7
- } from "./chunk-3RRPUYTE.js";
8
- import {
9
- RelayUsage
10
- } from "./chunk-3V3DRXB2.js";
11
- import "./chunk-E53YHYEP.js";
8
+ } from "./chunk-ZLL5EGI2.js";
12
9
  import {
13
10
  note
14
- } from "./chunk-M2DCR2J4.js";
11
+ } from "./chunk-MNTIEWKF.js";
15
12
 
16
13
  // src/login.ts
17
14
  import { spawn } from "child_process";
@@ -11,20 +11,18 @@ import {
11
11
  open,
12
12
  preset,
13
13
  selectorList,
14
+ shortHostname,
14
15
  stamp,
15
16
  startDaemon,
16
17
  time
17
- } from "./chunk-3V3DRXB2.js";
18
- import {
19
- shortHostname
20
- } from "./chunk-E53YHYEP.js";
18
+ } from "./chunk-ZLL5EGI2.js";
21
19
  import {
22
20
  FAILED,
23
21
  exitFlushed,
24
22
  note,
25
23
  parseSeconds,
26
24
  printTable
27
- } from "./chunk-M2DCR2J4.js";
25
+ } from "./chunk-MNTIEWKF.js";
28
26
 
29
27
  // src/main.ts
30
28
  import { text as readAll } from "stream/consumers";
@@ -35,7 +33,7 @@ import { parseArgs } from "util";
35
33
  // package.json
36
34
  var package_default = {
37
35
  name: "@scp-dev/cli",
38
- version: "0.2.0",
36
+ version: "0.2.1",
39
37
  description: "The swarm command line tool.",
40
38
  license: "Apache-2.0",
41
39
  homepage: "https://scp.dev",
@@ -66,6 +64,8 @@ var package_default = {
66
64
  "smol-toml": "^1.9.1"
67
65
  },
68
66
  devDependencies: {
67
+ "@openai/codex": "0.159.0",
68
+ "opencode-ai": "1.18.34",
69
69
  tsup: "^8.5.1"
70
70
  },
71
71
  publishConfig: {
@@ -98,7 +98,8 @@ results back, as with native subagents.
98
98
  ${CLI_NAME} reply <id> [text|-] answer a message in its thread: ${CLI_NAME} reply 5af1f2 "done"
99
99
  ${CLI_NAME} ask <to> [text|-] [--wait S] send a request and wait for its reply: ${CLI_NAME} ask lead "which branch?"
100
100
  ${CLI_NAME} inbox [--wait S] your unread messages, then marked read: ${CLI_NAME} inbox
101
- ${CLI_NAME} list [--all] agents on the relay: address, title, presence, status
101
+ ${CLI_NAME} list [--all] agents on the relay: address, title, presence, status; --all adds offline ones
102
+ ${CLI_NAME} join [name] put this session on the relay, named once: ${CLI_NAME} join lead (${CLI_NAME} name renames it)
102
103
  ${CLI_NAME} status [id] the fleet in short; with the id of a message you sent: who read it when
103
104
  ${CLI_NAME} peek <ep> a short, redacted view of a peekable agent's last turns: ${CLI_NAME} peek rev
104
105
  ${CLI_NAME} set-status <state> [note] working, waiting, blocked or done: ${CLI_NAME} set-status done "PR open"
@@ -123,8 +124,10 @@ usage:
123
124
  sessions nobody spawned that spawned nobody fold into one line, --roots (or --all) lists
124
125
  them; --tree nests them by parent; (you) marks your own
125
126
  ${CLI_NAME} list --contacts the endpoints of other accounts your contacts let you reach: address, harness, presence
126
- ${CLI_NAME} send <to> [text|-] send a message (- or no text reads stdin); a line per recipient says when it sees it
127
- [--reply-to ID] [--thread ID] [--private] [--attach PATH]... --thread takes a thread id or the <id> of a message in it
127
+ ${CLI_NAME} send <to> [text|-] send a message (- or no text reads stdin); a line per recipient says when it sees it,
128
+ [--reply-to ID] [--thread ID] [--private] [--attach PATH]... [--live] and "queued: no live session holds <addr>" for one
129
+ that is offline; --live refuses those (not_live) and queues nothing;
130
+ --thread takes a thread id or the <id> of a message in it
128
131
  ${CLI_NAME} reply <id> [text|-] reply to message <id>: to its sender, in its thread, marking it read; <id> may
129
132
  also be another's message in a thread you sent or got a message in
130
133
  ${CLI_NAME} inbox [--wait S] [--keep] your unread messages, then marked read (--keep leaves them unread); --wait waits up
@@ -227,6 +230,8 @@ scopes (selectors are comma-separated, e.g. tree:parent,tree:children,group:team
227
230
  -c sandbox_workspace_write.network_access=true (the relay socket counts as network)
228
231
  ${CLI_NAME} pi [--name N] [--] [pi args...] runs pi with the @scp-dev/pi extension: the relay tools, and each new
229
232
  message as a turn (steering a running one, waking an idle session)
233
+ ${CLI_NAME} codex [--name N] [--headless] [--] [codex args...]
234
+ runs codex with relay messages waking an idle thread or steering a running turn
230
235
  ${CLI_NAME} peers [--all] [--roots] who you may message: title, status and the rule that admits each; offline ones and
231
236
  sessions nobody spawned that spawned nobody only with --all (--roots: those sessions)
232
237
  ${CLI_NAME} why <from> <to> whether from may message to, and why
@@ -262,6 +267,19 @@ agent sessions:
262
267
  ${CLI_NAME} claude [--name N] [--] [claude args...] start Claude Code with the scp channel loaded, so peer messages wake
263
268
  it while idle (claude --dangerously-load-development-channels server:scp; SCP_NAME=N)
264
269
  --channels pushes messages into a Claude Code that ${CLI_NAME} claude started; setup mounts claude's shim with it.
270
+ Without --name, ${CLI_NAME} claude asks the session to pick its own name with ${CLI_NAME} name <name>.
271
+ ${CLI_NAME} join [<handle>] put the session that runs this shell on the relay (it then shows in list,
272
+ peers can message it, and its hooks hand it new messages), named <handle>
273
+ when given; on a joined session it renames it in place. Works for a session
274
+ started before the hooks were installed too. Tell any session: ${CLI_NAME} join <name>
275
+ ${CLI_NAME} name [<handle>] [--endpoint EP] print this session's address, or rename it in place: id, mail, threads, status
276
+ and title stay; a handle another endpoint holds, live or offline, is refused;
277
+ a spawned worker is named by its spawner (policy defaults.rename: self lets it);
278
+ --endpoint renames another agent, for the human at a terminal
279
+ ${CLI_NAME} leave [--endpoint EP] take this session off the relay: offline, no messages pushed, mail kept until
280
+ ${CLI_NAME} join; a spawned worker stays joined while it runs
281
+ With setup --join manual a session stays off the relay until it runs ${CLI_NAME} join; the default, auto, joins every
282
+ hooked session when it starts.
265
283
 
266
284
  relay:
267
285
  ${CLI_NAME} relay use <url> | show select a relay, or show its source and credential status
@@ -277,7 +295,8 @@ identity:
277
295
  --as HANDLE (or --as=HANDLE, anywhere on the line, or $SCP_NAME, a local handle; a leading me/ is dropped) acts as that agent, with --harness H
278
296
  ($SCP_HARNESS, default cli), $SCP_LABELS (role=impl,lane=relay) and $SCP_PARENT. An offline
279
297
  agent of the same handle and harness is taken back with its inbox; a handle a live session holds is refused, never
280
- renamed. Run from that agent's own process, it acts as the agent, narrowing only.
298
+ suffixed. Run from that agent's own process, it acts as the agent, narrowing only. A session renamed with join or
299
+ name keeps its new handle: its hooks, its shim and commands with $SCP_NAME from its shell claim that one.
281
300
  Without --as, at a terminal or with --human you are your own human inbox (me/); messages sent with --human and no
282
301
  terminal are marked tty="false" and get no scope exemption. From an agent's process, --human acts as that agent.
283
302
  Without either and without a terminal, a command acts as the agent whose harness process runs this shell (the
@@ -327,7 +346,10 @@ var VERB_OPTIONS = {
327
346
  var IDENTITY = ["as", "harness", "human", "json", "cloud", "machine"];
328
347
  var VERBS = {
329
348
  list: [...IDENTITY, "all", "tree", "roots", "contacts"],
330
- send: [...IDENTITY, "reply-to", "thread", "private", "attach"],
349
+ send: [...IDENTITY, "reply-to", "thread", "private", "attach", "live"],
350
+ join: ["harness", "json"],
351
+ leave: [...IDENTITY, "endpoint"],
352
+ name: [...IDENTITY, "endpoint"],
331
353
  inbox: [...IDENTITY, "wait", "ack", "keep"],
332
354
  reply: IDENTITY,
333
355
  ack: [...IDENTITY, "all"],
@@ -498,12 +520,13 @@ async function relayMain(argv, cwd = process.cwd()) {
498
520
  out(package_default.version);
499
521
  return 0;
500
522
  }
501
- if (verb === "hook") return (await import("./hooks-EI7M3YKY.js")).relayHookCommand(rest, startDaemon);
502
- if (verb === "setup") return (await import("./setup-LXG346FJ.js")).relaySetupCommand(rest, cwd, out);
503
- if (verb === "claude") return (await import("./claude-YJLGFQ2P.js")).claudeCommand(rest);
504
- if (verb === "pi") return (await import("./pi-HMESQA64.js")).piCommand(rest);
523
+ if (verb === "hook") return (await import("./hooks-4B5NOH7X.js")).relayHookCommand(rest, startDaemon);
524
+ if (verb === "setup") return (await import("./setup-HPH7HE6O.js")).relaySetupCommand(rest, cwd, out);
525
+ if (verb === "claude") return (await import("./claude-WTCPUYU3.js")).claudeCommand(rest);
526
+ if (verb === "pi") return (await import("./pi-IAVFVOOO.js")).piCommand(rest);
527
+ if (verb === "codex") return (await import("./codex-YZZNH6IQ.js")).codexCommand(rest);
505
528
  if (verb === "spawn") {
506
- const { splitSpawn, spawnCommand } = await import("./spawn-DLPMAS5M.js");
529
+ const { splitSpawn, spawnCommand } = await import("./spawn-V66GYUNC.js");
507
530
  const { flags } = splitSpawn(rest);
508
531
  if (flags.includes("--help") || flags.includes("-h")) {
509
532
  out(flags.includes("--all") ? RELAY_HELP : SPAWN_HELP);
@@ -530,11 +553,11 @@ async function relayMain(argv, cwd = process.cwd()) {
530
553
  return daemon(values.idle, values.policy);
531
554
  }
532
555
  if (verb === "mcp")
533
- return (await import("./mcp-DGAQNFKO.js")).relayMcpCommand(values, positionals);
556
+ return (await import("./mcp-RXAVQBMP.js")).relayMcpCommand(values, positionals);
534
557
  if (verb === "hooks") {
535
558
  if (positionals[0] !== "install" || positionals.length > 1) throw new RelayUsage(`${CLI_NAME} hooks takes install --harness claude|codex|opencode|agy|muse`);
536
559
  if (values.write && values.print) throw new RelayUsage("--print and --write: pick one");
537
- return (await import("./install-MYHVFKT4.js")).installHooks({
560
+ return (await import("./install-2ZM3IYXG.js")).installHooks({
538
561
  harness: values.harness,
539
562
  scope: values.scope,
540
563
  write: values.write === true,
@@ -545,25 +568,26 @@ async function relayMain(argv, cwd = process.cwd()) {
545
568
  out
546
569
  });
547
570
  }
548
- if (verb === "relay") return (await import("./relay-5Z7IEXKD.js")).relayVerb(positionals, values.json === true);
549
- if (verb === "up") return (await import("./up-GPM4LWY3.js")).up(positionals, values, cwd, relinkBroker);
571
+ if (verb === "relay") return (await import("./relay-QDX2BNZH.js")).relayVerb(positionals, values.json === true);
572
+ if (verb === "up") return (await import("./up-2YGEDA5J.js")).up(positionals, values, cwd, relinkBroker);
550
573
  if (verb === "login") {
551
- const code = await (await import("./relay-5Z7IEXKD.js")).loginMain(positionals, values);
574
+ const code = await (await import("./relay-QDX2BNZH.js")).loginMain(positionals, values);
552
575
  if (code === 0) await relinkRunning();
553
576
  return code;
554
577
  }
555
- if (verb === "logout") return (await import("./relay-5Z7IEXKD.js")).logoutMain(positionals, values.json === true);
578
+ if (verb === "logout") return (await import("./relay-QDX2BNZH.js")).logoutMain(positionals, values.json === true);
556
579
  if (verb === "cloud") {
557
- const code = await (await import("./remote-FYN5ZXE4.js")).cloudMain(positionals, values, cloudStatus);
580
+ const code = await (await import("./remote-2OWBWLJH.js")).cloudMain(positionals, values, cloudStatus);
558
581
  if (code === 0 && positionals[0] === "enable") await relinkRunning();
559
582
  return code;
560
583
  }
584
+ if (verb === "join") return (await import("./join-BH5CS6SL.js")).joinCommand(values, positionals, cwd, out);
561
585
  if (verb === "holds") holdsArgs(values, positionals);
562
586
  const bodyFromStdin = (verb === "send" || verb === "ask" || verb === "reply") && (positionals[1] === void 0 || positionals[1] === "-");
563
587
  const opened = await open(verb, values, cwd, bodyFromStdin);
564
588
  const { client } = opened;
565
589
  try {
566
- if (verb === "machines") return await (await import("./remote-FYN5ZXE4.js")).machinesVerb(client, positionals, values.json === true);
590
+ if (verb === "machines") return await (await import("./remote-2OWBWLJH.js")).machinesVerb(client, positionals, values.json === true);
567
591
  return await runVerb(opened, verb, values, positionals, cwd);
568
592
  } finally {
569
593
  client.close();
@@ -594,7 +618,7 @@ async function relinkBroker() {
594
618
  client.close();
595
619
  }
596
620
  if (!result.restarting) return result;
597
- await (await import("./daemon-SUTLTY5U.js")).exited(pid);
621
+ await (await import("./daemon-OMJY7T2F.js")).exited(pid);
598
622
  return cloudStatus();
599
623
  }
600
624
  async function relinkRunning() {
@@ -614,7 +638,7 @@ async function daemonControl(positionals, values) {
614
638
  if (positionals.length !== 1 || action !== "stop" && action !== "restart" || values.idle !== void 0 || values.policy !== void 0)
615
639
  throw new RelayUsage(`${CLI_NAME} daemon takes stop or restart, or --idle and --policy to run in the foreground`);
616
640
  const dir = relayDir();
617
- const pid = await (await import("./daemon-SUTLTY5U.js")).stopBroker(dir);
641
+ const pid = await (await import("./daemon-OMJY7T2F.js")).stopBroker(dir);
618
642
  if (action === "stop") {
619
643
  out(pid === null ? "no relay broker runs" : `stopped the relay broker (pid ${pid}); the next command starts a fresh one`);
620
644
  return 0;
@@ -740,9 +764,9 @@ async function runVerb({ client, me, broker, where, bound, harnessPid }, verb, v
740
764
  return 0;
741
765
  }
742
766
  case "peek":
743
- return (await import("./peek-WLG3ZROU.js")).peekCommand(localClient(client, broker, verb), values, positionals);
767
+ return (await import("./peek-M2HQVO4O.js")).peekCommand(localClient(client, broker, verb), values, positionals);
744
768
  case "set-peek":
745
- return (await import("./peek-WLG3ZROU.js")).setPeekCommand(localClient(client, broker, verb), values, positionals);
769
+ return (await import("./peek-M2HQVO4O.js")).setPeekCommand(localClient(client, broker, verb), values, positionals);
746
770
  case "why": {
747
771
  const [from, to] = positionals;
748
772
  if (!from || !to || positionals.length > 2) throw new RelayUsage(`${CLI_NAME} why takes <from> <to>`);
@@ -768,13 +792,13 @@ async function runVerb({ client, me, broker, where, bound, harnessPid }, verb, v
768
792
  ...attachments.length ? { attachments } : {}
769
793
  };
770
794
  if (verb === "send") {
771
- const result2 = await client.request("send", params);
795
+ const result2 = await client.request("send", { ...params, ...values.live ? { live: true } : {} });
772
796
  if (asJson) json(result2);
773
797
  else if (result2.held) out(heldText(result2.held));
774
798
  else {
775
799
  const lines = reachLines(result2.deliveries);
776
800
  out(`sent ${result2.id} to ${result2.deliveries.map((d) => lines.length ? d.address : deliveryText(d)).join(", ")}${redactedText(result2.redacted)}`);
777
- for (const line of lines) out(` ${line}`);
801
+ for (const line of [...lines, ...result2.warnings ?? []]) out(` ${line}`);
778
802
  if (result2.deliveries.some((d) => d.state === "running" || d.state === "starting"))
779
803
  out(` ${CLI_NAME} status ${shortId(result2.id)} shows when it is read`);
780
804
  }
@@ -943,6 +967,30 @@ async function runVerb({ client, me, broker, where, bound, harnessPid }, verb, v
943
967
  else out(`${view.address}: ${view.status ? statusText(view.status) : "-"}`);
944
968
  return 0;
945
969
  }
970
+ case "name": {
971
+ if (positionals.length > 1) throw new RelayUsage(`${CLI_NAME} name takes one handle, or none to print your address`);
972
+ const endpoint = values.endpoint;
973
+ if (!positionals.length) {
974
+ if (endpoint !== void 0) throw new RelayUsage(`${CLI_NAME} name --endpoint EP takes the new handle`);
975
+ if (me?.kind !== "agent") throw new RelayUsage(`${CLI_NAME} name: this shell is no joined session; ${CLI_NAME} join <name> joins it`);
976
+ if (asJson) json({ address: me.address });
977
+ else out(me.address);
978
+ return 0;
979
+ }
980
+ const before = endpoint ?? me?.address;
981
+ const view = await client.request("rename", { handle: positionals[0], ...endpoint !== void 0 ? { endpoint } : {} });
982
+ if (asJson) json(view);
983
+ else out(before && before !== view.address ? `${before} is now ${view.address}` : `${view.address}`);
984
+ return 0;
985
+ }
986
+ case "leave": {
987
+ if (positionals.length) throw new RelayUsage(`${CLI_NAME} leave takes no arguments (--endpoint EP for the human at a terminal)`);
988
+ const endpoint = values.endpoint;
989
+ const view = await client.request("leave", endpoint !== void 0 ? { endpoint } : {});
990
+ if (asJson) json(view);
991
+ else out(`${view.address} left the relay: offline, no messages pushed; its mail is kept until ${CLI_NAME} join`);
992
+ return 0;
993
+ }
946
994
  case "set-title": {
947
995
  if (!positionals.length) throw new RelayUsage(`${CLI_NAME} set-title takes the title text ("" clears it)`);
948
996
  const view = await client.request("title", { text: positionals.join(" ") });
@@ -1295,7 +1343,7 @@ async function daemon(idle, policyFile) {
1295
1343
  });
1296
1344
  let broker;
1297
1345
  try {
1298
- const { daemonBridge } = await import("./remote-FYN5ZXE4.js");
1346
+ const { daemonBridge } = await import("./remote-2OWBWLJH.js");
1299
1347
  const bridge = await daemonBridge();
1300
1348
  broker = await startBroker({
1301
1349
  dir: relayDir(),
@@ -1,24 +1,23 @@
1
1
  import {
2
2
  spawnDetached
3
- } from "./chunk-GH7AXFUL.js";
3
+ } from "./chunk-25ZVL5LD.js";
4
4
  import "./chunk-KN7WEIE4.js";
5
- import "./chunk-WV5FINTW.js";
5
+ import "./chunk-NJLFHBSS.js";
6
6
  import {
7
7
  mcpInstall
8
- } from "./chunk-5DYFYLAQ.js";
8
+ } from "./chunk-KC5AV5NQ.js";
9
+ import "./chunk-HF4KP6AR.js";
10
+ import "./chunk-YYSLYVNZ.js";
9
11
  import {
10
12
  CHANNELS_ENV,
11
13
  RelayUsage,
12
- startDaemon
13
- } from "./chunk-3V3DRXB2.js";
14
- import "./chunk-RXKBND3T.js";
15
- import "./chunk-YYSLYVNZ.js";
16
- import {
17
14
  harnessPid,
15
+ membership,
18
16
  psParent,
19
- relayIdentity
20
- } from "./chunk-E53YHYEP.js";
21
- import "./chunk-M2DCR2J4.js";
17
+ relayIdentity,
18
+ startDaemon
19
+ } from "./chunk-ZLL5EGI2.js";
20
+ import "./chunk-MNTIEWKF.js";
22
21
 
23
22
  // src/mcp.ts
24
23
  import { CLI_NAME, validHandle } from "@scp-dev/core";
@@ -45,6 +44,7 @@ async function relayMcpCommand(values, positionals) {
45
44
  await runRelayMcp({
46
45
  connect: () => connectBroker(dir, () => startDaemon(dir)),
47
46
  claim,
47
+ membership: () => membership(process.env, claim.session),
48
48
  input: process.stdin,
49
49
  output: (line) => void process.stdout.write(line),
50
50
  env: process.env,
@@ -2,11 +2,10 @@ import {
2
2
  RelayUsage,
3
3
  peekGrant,
4
4
  stamp
5
- } from "./chunk-3V3DRXB2.js";
6
- import "./chunk-E53YHYEP.js";
5
+ } from "./chunk-ZLL5EGI2.js";
7
6
  import {
8
7
  note
9
- } from "./chunk-M2DCR2J4.js";
8
+ } from "./chunk-MNTIEWKF.js";
10
9
 
11
10
  // src/peek.ts
12
11
  import { PREAMBLE, wrapPeek, CLI_NAME } from "@scp-dev/core";
@@ -1,8 +1,7 @@
1
1
  import {
2
2
  RelayUsage
3
- } from "./chunk-3V3DRXB2.js";
4
- import "./chunk-E53YHYEP.js";
5
- import "./chunk-M2DCR2J4.js";
3
+ } from "./chunk-ZLL5EGI2.js";
4
+ import "./chunk-MNTIEWKF.js";
6
5
 
7
6
  // src/pi.ts
8
7
  import { spawn } from "child_process";
@@ -3,6 +3,7 @@ import {
3
3
  activeRelay,
4
4
  checkRelayUrl,
5
5
  configDir,
6
+ joinMode,
6
7
  loginMain,
7
8
  logoutMain,
8
9
  readCredentials,
@@ -10,16 +11,16 @@ import {
10
11
  relayVerb,
11
12
  removeCredential,
12
13
  saveCredential,
14
+ setJoinMode,
13
15
  writePrivateJson
14
- } from "./chunk-3RRPUYTE.js";
15
- import "./chunk-3V3DRXB2.js";
16
- import "./chunk-E53YHYEP.js";
17
- import "./chunk-M2DCR2J4.js";
16
+ } from "./chunk-ZLL5EGI2.js";
17
+ import "./chunk-MNTIEWKF.js";
18
18
  export {
19
19
  DEFAULT_RELAY,
20
20
  activeRelay,
21
21
  checkRelayUrl,
22
22
  configDir,
23
+ joinMode,
23
24
  loginMain,
24
25
  logoutMain,
25
26
  readCredentials,
@@ -27,5 +28,6 @@ export {
27
28
  relayVerb,
28
29
  removeCredential,
29
30
  saveCredential,
31
+ setJoinMode,
30
32
  writePrivateJson
31
33
  };
@@ -9,11 +9,9 @@ import {
9
9
  machinesVerb,
10
10
  openCloud,
11
11
  readCloudFile
12
- } from "./chunk-U2RSSTNW.js";
13
- import "./chunk-3RRPUYTE.js";
14
- import "./chunk-3V3DRXB2.js";
15
- import "./chunk-E53YHYEP.js";
16
- import "./chunk-M2DCR2J4.js";
12
+ } from "./chunk-MXQ7B3CQ.js";
13
+ import "./chunk-ZLL5EGI2.js";
14
+ import "./chunk-MNTIEWKF.js";
17
15
  export {
18
16
  CloudRelayClient,
19
17
  CloudUsage,
@@ -15,13 +15,12 @@ import {
15
15
  verifyMount,
16
16
  verifyMusePlugin,
17
17
  whichOnPath
18
- } from "./chunk-WV5FINTW.js";
19
- import "./chunk-5DYFYLAQ.js";
20
- import "./chunk-3V3DRXB2.js";
21
- import "./chunk-RXKBND3T.js";
18
+ } from "./chunk-NJLFHBSS.js";
19
+ import "./chunk-KC5AV5NQ.js";
20
+ import "./chunk-HF4KP6AR.js";
22
21
  import "./chunk-YYSLYVNZ.js";
23
- import "./chunk-E53YHYEP.js";
24
- import "./chunk-M2DCR2J4.js";
22
+ import "./chunk-ZLL5EGI2.js";
23
+ import "./chunk-MNTIEWKF.js";
25
24
  export {
26
25
  SETUP_HARNESSES,
27
26
  SETUP_HELP,
@@ -29,17 +29,16 @@ import {
29
29
  steerArgv,
30
30
  transcriptReplies,
31
31
  workerName
32
- } from "./chunk-GH7AXFUL.js";
32
+ } from "./chunk-25ZVL5LD.js";
33
33
  import {
34
34
  SPAWN_HELP
35
35
  } from "./chunk-KN7WEIE4.js";
36
- import "./chunk-WV5FINTW.js";
37
- import "./chunk-5DYFYLAQ.js";
38
- import "./chunk-3V3DRXB2.js";
39
- import "./chunk-RXKBND3T.js";
36
+ import "./chunk-NJLFHBSS.js";
37
+ import "./chunk-KC5AV5NQ.js";
38
+ import "./chunk-HF4KP6AR.js";
40
39
  import "./chunk-YYSLYVNZ.js";
41
- import "./chunk-E53YHYEP.js";
42
- import "./chunk-M2DCR2J4.js";
40
+ import "./chunk-ZLL5EGI2.js";
41
+ import "./chunk-MNTIEWKF.js";
43
42
  export {
44
43
  MESSAGING,
45
44
  SPAWN_HELP,
@@ -1,12 +1,9 @@
1
1
  import {
2
+ RelayUsage,
2
3
  activeRelay,
3
4
  relayCredential
4
- } from "./chunk-3RRPUYTE.js";
5
- import {
6
- RelayUsage
7
- } from "./chunk-3V3DRXB2.js";
8
- import "./chunk-E53YHYEP.js";
9
- import "./chunk-M2DCR2J4.js";
5
+ } from "./chunk-ZLL5EGI2.js";
6
+ import "./chunk-MNTIEWKF.js";
10
7
 
11
8
  // src/up.ts
12
9
  import { CLI_NAME } from "@scp-dev/core";
@@ -17,16 +14,16 @@ async function up(positionals, values, cwd, brokerStatus) {
17
14
  const { url } = activeRelay(process.env);
18
15
  const headless = values.token !== void 0 || Boolean(process.env.SCP_TOKEN?.trim());
19
16
  if (headless || !relayCredential(process.env, url).token) {
20
- const code = await (await import("./login-V2WT7QX5.js")).login({
17
+ const code = await (await import("./login-UB72MU7W.js")).login({
21
18
  ...values.token !== void 0 ? { token: values.token } : {},
22
19
  ...values.label !== void 0 ? { label: values.label } : {},
23
20
  ...values["no-browser"] ? { "no-browser": true } : {}
24
21
  });
25
22
  if (code !== 0) return code;
26
23
  } else out(`already logged in to ${url}`);
27
- const enabled = await (await import("./remote-FYN5ZXE4.js")).cloudMain(["enable"], values.machine !== void 0 ? { machine: values.machine } : {}, brokerStatus);
24
+ const enabled = await (await import("./remote-2OWBWLJH.js")).cloudMain(["enable"], values.machine !== void 0 ? { machine: values.machine } : {}, brokerStatus);
28
25
  if (enabled !== 0) return enabled;
29
- const setup = (await import("./setup-LXG346FJ.js")).relaySetupCommand(["--write"], cwd, out);
26
+ const setup = (await import("./setup-HPH7HE6O.js")).relaySetupCommand(["--write"], cwd, out);
30
27
  if (setup !== 0) return setup;
31
28
  const broker = await brokerStatus();
32
29
  if (!broker.enabled) out(`the broker is still local-only; run \`${CLI_NAME} daemon restart\` to link it to ${url}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scp-dev/cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "The swarm command line tool.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://scp.dev",
@@ -24,13 +24,15 @@
24
24
  "typecheck": "tsc -p ."
25
25
  },
26
26
  "dependencies": {
27
- "@scp-dev/core": "0.1.1",
28
- "@scp-dev/broker": "0.1.2",
29
- "@scp-dev/hub": "0.1.1",
30
- "@scp-dev/mcp": "0.1.2",
27
+ "@scp-dev/core": "0.1.2",
28
+ "@scp-dev/broker": "0.1.3",
29
+ "@scp-dev/hub": "0.2.0",
30
+ "@scp-dev/mcp": "0.1.3",
31
31
  "smol-toml": "^1.9.1"
32
32
  },
33
33
  "devDependencies": {
34
+ "@openai/codex": "0.159.0",
35
+ "opencode-ai": "1.18.34",
34
36
  "tsup": "^8.5.1"
35
37
  },
36
38
  "publishConfig": {