@scp-dev/cli 0.1.3 → 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-ABP5AKFH.js → chunk-25ZVL5LD.js} +8 -10
  3. package/dist/{chunk-ABR5UABL.js → chunk-HF4KP6AR.js} +229 -13
  4. package/dist/{chunk-QQZF5TQD.js → chunk-KC5AV5NQ.js} +3 -5
  5. package/dist/{chunk-M2DCR2J4.js → chunk-MNTIEWKF.js} +13 -3
  6. package/dist/{chunk-5UWLTO2Y.js → chunk-MXQ7B3CQ.js} +3 -5
  7. package/dist/{chunk-IH2RJRIW.js → chunk-NJLFHBSS.js} +20 -10
  8. package/dist/chunk-ZLL5EGI2.js +805 -0
  9. package/dist/{claude-5WTICOYS.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-4YVIPZKE.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-5Y3HPSVC.js → login-UB72MU7W.js} +4 -7
  17. package/dist/{main-PZQAJGHQ.js → main-I4F53MMA.js} +81 -30
  18. package/dist/{mcp-GI5OMTUT.js → mcp-RXAVQBMP.js} +11 -11
  19. package/dist/{peek-X4SEGEUB.js → peek-M2HQVO4O.js} +2 -3
  20. package/dist/pi-IAVFVOOO.js +71 -0
  21. package/dist/{relay-W2NFUE2U.js → relay-QDX2BNZH.js} +6 -4
  22. package/dist/{remote-GC4XN44U.js → remote-2OWBWLJH.js} +3 -5
  23. package/dist/{setup-UF4AA6RO.js → setup-HPH7HE6O.js} +5 -6
  24. package/dist/{spawn-KT5235WX.js → spawn-V66GYUNC.js} +6 -7
  25. package/dist/{up-VA54QWA6.js → up-2YGEDA5J.js} +6 -9
  26. package/package.json +7 -5
  27. package/dist/chunk-3PGDKPRN.js +0 -304
  28. package/dist/chunk-BUC5G5PY.js +0 -147
  29. package/dist/chunk-URSBFDR6.js +0 -340
  30. package/dist/install-4KQQWGGB.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-ABR5UABL.js";
41
+ } from "./chunk-HF4KP6AR.js";
34
42
  import {
35
43
  SUBAGENT
36
44
  } from "./chunk-YYSLYVNZ.js";
37
- import "./chunk-3PGDKPRN.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-5UWLTO2Y.js";
3
+ } from "./chunk-MXQ7B3CQ.js";
4
4
  import {
5
+ RelayUsage,
5
6
  activeRelay,
6
7
  saveCredential
7
- } from "./chunk-BUC5G5PY.js";
8
- import {
9
- RelayUsage
10
- } from "./chunk-URSBFDR6.js";
11
- import "./chunk-3PGDKPRN.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-URSBFDR6.js";
18
- import {
19
- shortHostname
20
- } from "./chunk-3PGDKPRN.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.1.3",
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
@@ -225,6 +228,10 @@ scopes (selectors are comma-separated, e.g. tree:parent,tree:children,group:team
225
228
  messages with the relay MCP tools (relay_send, relay_inbox, relay_reply). A
226
229
  ${CLI_NAME} command from codex's workspace-write sandbox also needs
227
230
  -c sandbox_workspace_write.network_access=true (the relay socket counts as network)
231
+ ${CLI_NAME} pi [--name N] [--] [pi args...] runs pi with the @scp-dev/pi extension: the relay tools, and each new
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
228
235
  ${CLI_NAME} peers [--all] [--roots] who you may message: title, status and the rule that admits each; offline ones and
229
236
  sessions nobody spawned that spawned nobody only with --all (--roots: those sessions)
230
237
  ${CLI_NAME} why <from> <to> whether from may message to, and why
@@ -260,6 +267,19 @@ agent sessions:
260
267
  ${CLI_NAME} claude [--name N] [--] [claude args...] start Claude Code with the scp channel loaded, so peer messages wake
261
268
  it while idle (claude --dangerously-load-development-channels server:scp; SCP_NAME=N)
262
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.
263
283
 
264
284
  relay:
265
285
  ${CLI_NAME} relay use <url> | show select a relay, or show its source and credential status
@@ -275,7 +295,8 @@ identity:
275
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
276
296
  ($SCP_HARNESS, default cli), $SCP_LABELS (role=impl,lane=relay) and $SCP_PARENT. An offline
277
297
  agent of the same handle and harness is taken back with its inbox; a handle a live session holds is refused, never
278
- 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.
279
300
  Without --as, at a terminal or with --human you are your own human inbox (me/); messages sent with --human and no
280
301
  terminal are marked tty="false" and get no scope exemption. From an agent's process, --human acts as that agent.
281
302
  Without either and without a terminal, a command acts as the agent whose harness process runs this shell (the
@@ -325,7 +346,10 @@ var VERB_OPTIONS = {
325
346
  var IDENTITY = ["as", "harness", "human", "json", "cloud", "machine"];
326
347
  var VERBS = {
327
348
  list: [...IDENTITY, "all", "tree", "roots", "contacts"],
328
- 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"],
329
353
  inbox: [...IDENTITY, "wait", "ack", "keep"],
330
354
  reply: IDENTITY,
331
355
  ack: [...IDENTITY, "all"],
@@ -496,11 +520,13 @@ async function relayMain(argv, cwd = process.cwd()) {
496
520
  out(package_default.version);
497
521
  return 0;
498
522
  }
499
- if (verb === "hook") return (await import("./hooks-4YVIPZKE.js")).relayHookCommand(rest, startDaemon);
500
- if (verb === "setup") return (await import("./setup-UF4AA6RO.js")).relaySetupCommand(rest, cwd, out);
501
- if (verb === "claude") return (await import("./claude-5WTICOYS.js")).claudeCommand(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);
502
528
  if (verb === "spawn") {
503
- const { splitSpawn, spawnCommand } = await import("./spawn-KT5235WX.js");
529
+ const { splitSpawn, spawnCommand } = await import("./spawn-V66GYUNC.js");
504
530
  const { flags } = splitSpawn(rest);
505
531
  if (flags.includes("--help") || flags.includes("-h")) {
506
532
  out(flags.includes("--all") ? RELAY_HELP : SPAWN_HELP);
@@ -527,11 +553,11 @@ async function relayMain(argv, cwd = process.cwd()) {
527
553
  return daemon(values.idle, values.policy);
528
554
  }
529
555
  if (verb === "mcp")
530
- return (await import("./mcp-GI5OMTUT.js")).relayMcpCommand(values, positionals);
556
+ return (await import("./mcp-RXAVQBMP.js")).relayMcpCommand(values, positionals);
531
557
  if (verb === "hooks") {
532
558
  if (positionals[0] !== "install" || positionals.length > 1) throw new RelayUsage(`${CLI_NAME} hooks takes install --harness claude|codex|opencode|agy|muse`);
533
559
  if (values.write && values.print) throw new RelayUsage("--print and --write: pick one");
534
- return (await import("./install-4KQQWGGB.js")).installHooks({
560
+ return (await import("./install-2ZM3IYXG.js")).installHooks({
535
561
  harness: values.harness,
536
562
  scope: values.scope,
537
563
  write: values.write === true,
@@ -542,25 +568,26 @@ async function relayMain(argv, cwd = process.cwd()) {
542
568
  out
543
569
  });
544
570
  }
545
- if (verb === "relay") return (await import("./relay-W2NFUE2U.js")).relayVerb(positionals, values.json === true);
546
- if (verb === "up") return (await import("./up-VA54QWA6.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);
547
573
  if (verb === "login") {
548
- const code = await (await import("./relay-W2NFUE2U.js")).loginMain(positionals, values);
574
+ const code = await (await import("./relay-QDX2BNZH.js")).loginMain(positionals, values);
549
575
  if (code === 0) await relinkRunning();
550
576
  return code;
551
577
  }
552
- if (verb === "logout") return (await import("./relay-W2NFUE2U.js")).logoutMain(positionals, values.json === true);
578
+ if (verb === "logout") return (await import("./relay-QDX2BNZH.js")).logoutMain(positionals, values.json === true);
553
579
  if (verb === "cloud") {
554
- const code = await (await import("./remote-GC4XN44U.js")).cloudMain(positionals, values, cloudStatus);
580
+ const code = await (await import("./remote-2OWBWLJH.js")).cloudMain(positionals, values, cloudStatus);
555
581
  if (code === 0 && positionals[0] === "enable") await relinkRunning();
556
582
  return code;
557
583
  }
584
+ if (verb === "join") return (await import("./join-BH5CS6SL.js")).joinCommand(values, positionals, cwd, out);
558
585
  if (verb === "holds") holdsArgs(values, positionals);
559
586
  const bodyFromStdin = (verb === "send" || verb === "ask" || verb === "reply") && (positionals[1] === void 0 || positionals[1] === "-");
560
587
  const opened = await open(verb, values, cwd, bodyFromStdin);
561
588
  const { client } = opened;
562
589
  try {
563
- if (verb === "machines") return await (await import("./remote-GC4XN44U.js")).machinesVerb(client, positionals, values.json === true);
590
+ if (verb === "machines") return await (await import("./remote-2OWBWLJH.js")).machinesVerb(client, positionals, values.json === true);
564
591
  return await runVerb(opened, verb, values, positionals, cwd);
565
592
  } finally {
566
593
  client.close();
@@ -591,7 +618,7 @@ async function relinkBroker() {
591
618
  client.close();
592
619
  }
593
620
  if (!result.restarting) return result;
594
- await (await import("./daemon-SUTLTY5U.js")).exited(pid);
621
+ await (await import("./daemon-OMJY7T2F.js")).exited(pid);
595
622
  return cloudStatus();
596
623
  }
597
624
  async function relinkRunning() {
@@ -611,7 +638,7 @@ async function daemonControl(positionals, values) {
611
638
  if (positionals.length !== 1 || action !== "stop" && action !== "restart" || values.idle !== void 0 || values.policy !== void 0)
612
639
  throw new RelayUsage(`${CLI_NAME} daemon takes stop or restart, or --idle and --policy to run in the foreground`);
613
640
  const dir = relayDir();
614
- const pid = await (await import("./daemon-SUTLTY5U.js")).stopBroker(dir);
641
+ const pid = await (await import("./daemon-OMJY7T2F.js")).stopBroker(dir);
615
642
  if (action === "stop") {
616
643
  out(pid === null ? "no relay broker runs" : `stopped the relay broker (pid ${pid}); the next command starts a fresh one`);
617
644
  return 0;
@@ -737,9 +764,9 @@ async function runVerb({ client, me, broker, where, bound, harnessPid }, verb, v
737
764
  return 0;
738
765
  }
739
766
  case "peek":
740
- return (await import("./peek-X4SEGEUB.js")).peekCommand(localClient(client, broker, verb), values, positionals);
767
+ return (await import("./peek-M2HQVO4O.js")).peekCommand(localClient(client, broker, verb), values, positionals);
741
768
  case "set-peek":
742
- return (await import("./peek-X4SEGEUB.js")).setPeekCommand(localClient(client, broker, verb), values, positionals);
769
+ return (await import("./peek-M2HQVO4O.js")).setPeekCommand(localClient(client, broker, verb), values, positionals);
743
770
  case "why": {
744
771
  const [from, to] = positionals;
745
772
  if (!from || !to || positionals.length > 2) throw new RelayUsage(`${CLI_NAME} why takes <from> <to>`);
@@ -765,13 +792,13 @@ async function runVerb({ client, me, broker, where, bound, harnessPid }, verb, v
765
792
  ...attachments.length ? { attachments } : {}
766
793
  };
767
794
  if (verb === "send") {
768
- const result2 = await client.request("send", params);
795
+ const result2 = await client.request("send", { ...params, ...values.live ? { live: true } : {} });
769
796
  if (asJson) json(result2);
770
797
  else if (result2.held) out(heldText(result2.held));
771
798
  else {
772
799
  const lines = reachLines(result2.deliveries);
773
800
  out(`sent ${result2.id} to ${result2.deliveries.map((d) => lines.length ? d.address : deliveryText(d)).join(", ")}${redactedText(result2.redacted)}`);
774
- for (const line of lines) out(` ${line}`);
801
+ for (const line of [...lines, ...result2.warnings ?? []]) out(` ${line}`);
775
802
  if (result2.deliveries.some((d) => d.state === "running" || d.state === "starting"))
776
803
  out(` ${CLI_NAME} status ${shortId(result2.id)} shows when it is read`);
777
804
  }
@@ -940,6 +967,30 @@ async function runVerb({ client, me, broker, where, bound, harnessPid }, verb, v
940
967
  else out(`${view.address}: ${view.status ? statusText(view.status) : "-"}`);
941
968
  return 0;
942
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
+ }
943
994
  case "set-title": {
944
995
  if (!positionals.length) throw new RelayUsage(`${CLI_NAME} set-title takes the title text ("" clears it)`);
945
996
  const view = await client.request("title", { text: positionals.join(" ") });
@@ -1292,7 +1343,7 @@ async function daemon(idle, policyFile) {
1292
1343
  });
1293
1344
  let broker;
1294
1345
  try {
1295
- const { daemonBridge } = await import("./remote-GC4XN44U.js");
1346
+ const { daemonBridge } = await import("./remote-2OWBWLJH.js");
1296
1347
  const bridge = await daemonBridge();
1297
1348
  broker = await startBroker({
1298
1349
  dir: relayDir(),
@@ -1,24 +1,23 @@
1
1
  import {
2
2
  spawnDetached
3
- } from "./chunk-ABP5AKFH.js";
3
+ } from "./chunk-25ZVL5LD.js";
4
4
  import "./chunk-KN7WEIE4.js";
5
- import "./chunk-IH2RJRIW.js";
5
+ import "./chunk-NJLFHBSS.js";
6
6
  import {
7
7
  mcpInstall
8
- } from "./chunk-QQZF5TQD.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-URSBFDR6.js";
14
- import "./chunk-ABR5UABL.js";
15
- import "./chunk-YYSLYVNZ.js";
16
- import {
17
14
  harnessPid,
15
+ membership,
18
16
  psParent,
19
- relayIdentity
20
- } from "./chunk-3PGDKPRN.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-URSBFDR6.js";
6
- import "./chunk-3PGDKPRN.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";
@@ -0,0 +1,71 @@
1
+ import {
2
+ RelayUsage
3
+ } from "./chunk-ZLL5EGI2.js";
4
+ import "./chunk-MNTIEWKF.js";
5
+
6
+ // src/pi.ts
7
+ import { spawn } from "child_process";
8
+ import { fileURLToPath } from "url";
9
+ import { CLI_NAME, validHandle } from "@scp-dev/core";
10
+ var PI_HELP = `${CLI_NAME} pi [--name NAME | --as NAME] [--] [pi args...]
11
+ runs pi with the @scp-dev/pi extension: the relay tools, and each new message as a turn, waking the session when idle.
12
+ $SCP_PI_BIN picks the pi binary (default pi on PATH), $SCP_PI_EXTENSION the extension file.`;
13
+ function piLaunch(args, env, extension) {
14
+ let name;
15
+ const rest = [];
16
+ for (let i = 0; i < args.length; i++) {
17
+ const arg = args[i];
18
+ if (arg === "--") {
19
+ rest.push(...args.slice(i + 1));
20
+ break;
21
+ }
22
+ if (arg === "--name" || arg === "--as") {
23
+ name = args[++i];
24
+ if (name === void 0) throw new RelayUsage(`${CLI_NAME} pi ${arg} takes a name`);
25
+ } else if (arg.startsWith("--name=") || arg.startsWith("--as=")) name = arg.slice(arg.indexOf("=") + 1);
26
+ else rest.push(arg);
27
+ }
28
+ name = name?.replace(/^me\//, "");
29
+ if (name !== void 0 && !validHandle(name)) throw new RelayUsage(`${JSON.stringify(name)} is not a valid agent handle`);
30
+ return {
31
+ argv: [env.SCP_PI_BIN || "pi", "--extension", extension, ...rest],
32
+ env: { ...env, SCP_HARNESS: "pi", ...name !== void 0 ? { SCP_NAME: name } : {} }
33
+ };
34
+ }
35
+ function extensionPath(env) {
36
+ if (env.SCP_PI_EXTENSION) return env.SCP_PI_EXTENSION;
37
+ try {
38
+ return fileURLToPath(import.meta.resolve("@scp-dev/pi"));
39
+ } catch {
40
+ throw new RelayUsage(`${CLI_NAME} pi needs the @scp-dev/pi extension: install it next to ${CLI_NAME}, or set $SCP_PI_EXTENSION to its file`);
41
+ }
42
+ }
43
+ async function piCommand(args) {
44
+ const own = args.includes("--") ? args.slice(0, args.indexOf("--")) : args;
45
+ if (own.includes("--help") || own.includes("-h")) {
46
+ process.stdout.write(`${PI_HELP}
47
+ `);
48
+ return 0;
49
+ }
50
+ const launch = piLaunch(args, process.env, extensionPath(process.env));
51
+ return await new Promise((resolve, reject) => {
52
+ const child = spawn(launch.argv[0], launch.argv.slice(1), { env: launch.env, stdio: "inherit" });
53
+ const forward = (signal) => child.kill(signal);
54
+ const signals = ["SIGTERM", "SIGHUP"];
55
+ const ignore = () => {
56
+ };
57
+ for (const signal of signals) process.on(signal, forward);
58
+ process.on("SIGINT", ignore);
59
+ child.once("error", (error) => reject(new RelayUsage(`could not start ${launch.argv[0]}: ${error.message}`)));
60
+ child.once("exit", (code, signal) => {
61
+ for (const each of signals) process.off(each, forward);
62
+ process.off("SIGINT", ignore);
63
+ resolve(code ?? (signal ? 1 : 0));
64
+ });
65
+ });
66
+ }
67
+ export {
68
+ PI_HELP,
69
+ piCommand,
70
+ piLaunch
71
+ };
@@ -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-BUC5G5PY.js";
15
- import "./chunk-URSBFDR6.js";
16
- import "./chunk-3PGDKPRN.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-5UWLTO2Y.js";
13
- import "./chunk-BUC5G5PY.js";
14
- import "./chunk-URSBFDR6.js";
15
- import "./chunk-3PGDKPRN.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-IH2RJRIW.js";
19
- import "./chunk-QQZF5TQD.js";
20
- import "./chunk-URSBFDR6.js";
21
- import "./chunk-ABR5UABL.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-3PGDKPRN.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-ABP5AKFH.js";
32
+ } from "./chunk-25ZVL5LD.js";
33
33
  import {
34
34
  SPAWN_HELP
35
35
  } from "./chunk-KN7WEIE4.js";
36
- import "./chunk-IH2RJRIW.js";
37
- import "./chunk-QQZF5TQD.js";
38
- import "./chunk-URSBFDR6.js";
39
- import "./chunk-ABR5UABL.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-3PGDKPRN.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,