svamp-cli 0.1.64 → 0.1.66

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.
package/dist/cli.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { b as stopDaemon, s as startDaemon, d as daemonStatus } from './run-BImPgXHd.mjs';
1
+ import { b as stopDaemon, s as startDaemon, d as daemonStatus } from './run-BDmLH9T8.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import 'fs';
@@ -109,7 +109,7 @@ async function main() {
109
109
  const { handleServiceCommand } = await import('./commands-CF32XIau.mjs');
110
110
  await handleServiceCommand();
111
111
  } else if (subcommand === "process" || subcommand === "proc") {
112
- const { processCommand } = await import('./commands-BfMlD9o4.mjs');
112
+ const { processCommand } = await import('./commands-CdQ8qr6l.mjs');
113
113
  let machineId;
114
114
  const processArgs = args.slice(1);
115
115
  const mIdx = processArgs.findIndex((a) => a === "--machine" || a === "-m");
@@ -127,7 +127,7 @@ async function main() {
127
127
  } else if (!subcommand || subcommand === "start") {
128
128
  await handleInteractiveCommand();
129
129
  } else if (subcommand === "--version" || subcommand === "-v") {
130
- const pkg = await import('./package-Dg0hQJRC.mjs').catch(() => ({ default: { version: "unknown" } }));
130
+ const pkg = await import('./package-CSFQKq7F.mjs').catch(() => ({ default: { version: "unknown" } }));
131
131
  console.log(`svamp version: ${pkg.default.version}`);
132
132
  } else {
133
133
  console.error(`Unknown command: ${subcommand}`);
@@ -136,7 +136,7 @@ async function main() {
136
136
  }
137
137
  }
138
138
  async function handleInteractiveCommand() {
139
- const { runInteractive } = await import('./run-C7VxH4X8.mjs');
139
+ const { runInteractive } = await import('./run-ez-QlRKy.mjs');
140
140
  const interactiveArgs = subcommand === "start" ? args.slice(1) : args;
141
141
  let directory = process.cwd();
142
142
  let resumeSessionId;
@@ -181,7 +181,7 @@ async function handleAgentCommand() {
181
181
  return;
182
182
  }
183
183
  if (agentArgs[0] === "list") {
184
- const { KNOWN_ACP_AGENTS, KNOWN_MCP_AGENTS: KNOWN_MCP_AGENTS2 } = await import('./run-BImPgXHd.mjs').then(function (n) { return n.i; });
184
+ const { KNOWN_ACP_AGENTS, KNOWN_MCP_AGENTS: KNOWN_MCP_AGENTS2 } = await import('./run-BDmLH9T8.mjs').then(function (n) { return n.i; });
185
185
  console.log("Known agents:");
186
186
  for (const [name, config2] of Object.entries(KNOWN_ACP_AGENTS)) {
187
187
  console.log(` ${name.padEnd(12)} ${config2.command} ${config2.args.join(" ")} (ACP)`);
@@ -193,7 +193,7 @@ async function handleAgentCommand() {
193
193
  console.log('Use "svamp agent -- <command> [args]" for a custom ACP agent.');
194
194
  return;
195
195
  }
196
- const { resolveAcpAgentConfig, KNOWN_MCP_AGENTS } = await import('./run-BImPgXHd.mjs').then(function (n) { return n.i; });
196
+ const { resolveAcpAgentConfig, KNOWN_MCP_AGENTS } = await import('./run-BDmLH9T8.mjs').then(function (n) { return n.i; });
197
197
  let cwd = process.cwd();
198
198
  const filteredArgs = [];
199
199
  for (let i = 0; i < agentArgs.length; i++) {
@@ -217,12 +217,12 @@ async function handleAgentCommand() {
217
217
  console.log(`Starting ${config.agentName} agent in ${cwd}...`);
218
218
  let backend;
219
219
  if (KNOWN_MCP_AGENTS[config.agentName]) {
220
- const { CodexMcpBackend } = await import('./run-BImPgXHd.mjs').then(function (n) { return n.j; });
220
+ const { CodexMcpBackend } = await import('./run-BDmLH9T8.mjs').then(function (n) { return n.j; });
221
221
  backend = new CodexMcpBackend({ cwd, log: logFn });
222
222
  } else {
223
- const { AcpBackend } = await import('./run-BImPgXHd.mjs').then(function (n) { return n.h; });
224
- const { GeminiTransport } = await import('./run-BImPgXHd.mjs').then(function (n) { return n.G; });
225
- const { DefaultTransport } = await import('./run-BImPgXHd.mjs').then(function (n) { return n.D; });
223
+ const { AcpBackend } = await import('./run-BDmLH9T8.mjs').then(function (n) { return n.h; });
224
+ const { GeminiTransport } = await import('./run-BDmLH9T8.mjs').then(function (n) { return n.G; });
225
+ const { DefaultTransport } = await import('./run-BDmLH9T8.mjs').then(function (n) { return n.D; });
226
226
  const transportHandler = config.agentName === "gemini" ? new GeminiTransport() : new DefaultTransport(config.agentName);
227
227
  backend = new AcpBackend({
228
228
  agentName: config.agentName,
@@ -340,7 +340,7 @@ async function handleSessionCommand() {
340
340
  printSessionHelp();
341
341
  return;
342
342
  }
343
- const { sessionList, sessionSpawn, sessionStop, sessionInfo, sessionMessages, sessionAttach, sessionMachines, sessionSend, sessionWait, sessionShare, sessionRalphStart, sessionRalphCancel, sessionRalphStatus, sessionQueueAdd, sessionQueueList, sessionQueueClear } = await import('./commands-Brx7D-77.mjs');
343
+ const { sessionList, sessionSpawn, sessionStop, sessionInfo, sessionMessages, sessionAttach, sessionMachines, sessionSend, sessionWait, sessionShare, sessionRalphStart, sessionRalphCancel, sessionRalphStatus, sessionQueueAdd, sessionQueueList, sessionQueueClear } = await import('./commands-Dpc6QK0m.mjs');
344
344
  const parseFlagStr = (flag, shortFlag) => {
345
345
  for (let i = 1; i < sessionArgs.length; i++) {
346
346
  if ((sessionArgs[i] === flag || shortFlag) && i + 1 < sessionArgs.length) {
@@ -400,7 +400,7 @@ async function handleSessionCommand() {
400
400
  allowDomain.push(sessionArgs[++i]);
401
401
  }
402
402
  }
403
- const { parseShareArg } = await import('./commands-Brx7D-77.mjs');
403
+ const { parseShareArg } = await import('./commands-Dpc6QK0m.mjs');
404
404
  const shareEntries = share.map((s) => parseShareArg(s));
405
405
  await sessionSpawn(agent, dir, targetMachineId, {
406
406
  message,
@@ -484,7 +484,7 @@ async function handleSessionCommand() {
484
484
  console.error("Usage: svamp session approve <session-id> [request-id] [--json]");
485
485
  process.exit(1);
486
486
  }
487
- const { sessionApprove } = await import('./commands-Brx7D-77.mjs');
487
+ const { sessionApprove } = await import('./commands-Dpc6QK0m.mjs');
488
488
  const approveReqId = sessionArgs[2] && !sessionArgs[2].startsWith("--") ? sessionArgs[2] : void 0;
489
489
  await sessionApprove(sessionArgs[1], approveReqId, targetMachineId, {
490
490
  json: hasFlag("--json")
@@ -494,7 +494,7 @@ async function handleSessionCommand() {
494
494
  console.error("Usage: svamp session deny <session-id> [request-id] [--json]");
495
495
  process.exit(1);
496
496
  }
497
- const { sessionDeny } = await import('./commands-Brx7D-77.mjs');
497
+ const { sessionDeny } = await import('./commands-Dpc6QK0m.mjs');
498
498
  const denyReqId = sessionArgs[2] && !sessionArgs[2].startsWith("--") ? sessionArgs[2] : void 0;
499
499
  await sessionDeny(sessionArgs[1], denyReqId, targetMachineId, {
500
500
  json: hasFlag("--json")
@@ -524,6 +524,40 @@ async function handleSessionCommand() {
524
524
  process.exit(1);
525
525
  }
526
526
  await sessionRalphStatus(sessionArgs[1], targetMachineId);
527
+ } else if (sessionSubcommand === "set-title") {
528
+ const title = sessionArgs[1];
529
+ if (!title) {
530
+ console.error("Usage: svamp session set-title <title>");
531
+ process.exit(1);
532
+ }
533
+ const { sessionSetTitle } = await import('./agentCommands-C6iGblcL.mjs');
534
+ await sessionSetTitle(title);
535
+ } else if (sessionSubcommand === "set-link") {
536
+ const url = sessionArgs[1];
537
+ if (!url) {
538
+ console.error("Usage: svamp session set-link <url> [label]");
539
+ process.exit(1);
540
+ }
541
+ const label = sessionArgs[2] && !sessionArgs[2].startsWith("--") ? sessionArgs[2] : void 0;
542
+ const { sessionSetLink } = await import('./agentCommands-C6iGblcL.mjs');
543
+ await sessionSetLink(url, label);
544
+ } else if (sessionSubcommand === "notify") {
545
+ const message = sessionArgs[1];
546
+ if (!message) {
547
+ console.error("Usage: svamp session notify <message> [--level info|warning|error]");
548
+ process.exit(1);
549
+ }
550
+ const level = parseFlagStr("--level") || "info";
551
+ const { sessionNotify } = await import('./agentCommands-C6iGblcL.mjs');
552
+ await sessionNotify(message, level);
553
+ } else if (sessionSubcommand === "broadcast") {
554
+ const action = sessionArgs[1];
555
+ if (!action) {
556
+ console.error("Usage: svamp session broadcast <action> [args...]\nActions: open-canvas <url> [label], close-canvas, toast <message>");
557
+ process.exit(1);
558
+ }
559
+ const { sessionBroadcast } = await import('./agentCommands-C6iGblcL.mjs');
560
+ await sessionBroadcast(action, sessionArgs.slice(2).filter((a) => !a.startsWith("--")));
527
561
  } else if (sessionSubcommand === "queue") {
528
562
  const queueSubcmd = sessionArgs[1];
529
563
  if (queueSubcmd === "add") {
@@ -563,7 +597,7 @@ async function handleMachineCommand() {
563
597
  return;
564
598
  }
565
599
  if (machineSubcommand === "share") {
566
- const { machineShare } = await import('./commands-Brx7D-77.mjs');
600
+ const { machineShare } = await import('./commands-Dpc6QK0m.mjs');
567
601
  let machineId;
568
602
  const shareArgs = [];
569
603
  for (let i = 1; i < machineArgs.length; i++) {
@@ -593,7 +627,7 @@ async function handleMachineCommand() {
593
627
  }
594
628
  await machineShare(machineId, { add, remove, list, configPath, showConfig });
595
629
  } else if (machineSubcommand === "exec") {
596
- const { machineExec } = await import('./commands-Brx7D-77.mjs');
630
+ const { machineExec } = await import('./commands-Dpc6QK0m.mjs');
597
631
  let machineId;
598
632
  let cwd;
599
633
  const cmdParts = [];
@@ -613,7 +647,7 @@ async function handleMachineCommand() {
613
647
  }
614
648
  await machineExec(machineId, command, cwd);
615
649
  } else if (machineSubcommand === "info") {
616
- const { machineInfo } = await import('./commands-Brx7D-77.mjs');
650
+ const { machineInfo } = await import('./commands-Dpc6QK0m.mjs');
617
651
  let machineId;
618
652
  for (let i = 1; i < machineArgs.length; i++) {
619
653
  if ((machineArgs[i] === "--machine" || machineArgs[i] === "-m") && i + 1 < machineArgs.length) {
@@ -621,8 +655,22 @@ async function handleMachineCommand() {
621
655
  }
622
656
  }
623
657
  await machineInfo(machineId);
658
+ } else if (machineSubcommand === "notify") {
659
+ const message = machineArgs[1];
660
+ if (!message) {
661
+ console.error("Usage: svamp machine notify <message> [--level info|warning|error]");
662
+ process.exit(1);
663
+ }
664
+ let level = "info";
665
+ for (let i = 2; i < machineArgs.length; i++) {
666
+ if (machineArgs[i] === "--level" && i + 1 < machineArgs.length) {
667
+ level = machineArgs[++i];
668
+ }
669
+ }
670
+ const { machineNotify } = await import('./agentCommands-C6iGblcL.mjs');
671
+ await machineNotify(message, level);
624
672
  } else if (machineSubcommand === "ls") {
625
- const { machineLs } = await import('./commands-Brx7D-77.mjs');
673
+ const { machineLs } = await import('./commands-Dpc6QK0m.mjs');
626
674
  let machineId;
627
675
  let showHidden = false;
628
676
  let path;
@@ -636,6 +684,43 @@ async function handleMachineCommand() {
636
684
  }
637
685
  }
638
686
  await machineLs(machineId, path, showHidden);
687
+ } else if (machineSubcommand === "storage") {
688
+ const { storageList, storageOrphans, storageMarkOrphan, storageUnmarkOrphan, storageDelete, printStorageHelp } = await import('./storageCommands-CKhntx1P.mjs');
689
+ const storageArgs = machineArgs.slice(1);
690
+ const storageSubcmd = storageArgs[0];
691
+ if (!storageSubcmd || storageSubcmd === "--help" || storageSubcmd === "-h") {
692
+ printStorageHelp();
693
+ } else if (storageSubcmd === "list") {
694
+ await storageList();
695
+ } else if (storageSubcmd === "orphans") {
696
+ const mark = storageArgs.includes("--mark");
697
+ await storageOrphans(mark);
698
+ } else if (storageSubcmd === "mark-orphan") {
699
+ const ns = storageArgs[1];
700
+ if (!ns) {
701
+ console.error("Usage: svamp machine storage mark-orphan <namespace>");
702
+ process.exit(1);
703
+ }
704
+ await storageMarkOrphan(ns);
705
+ } else if (storageSubcmd === "unmark-orphan") {
706
+ const ns = storageArgs[1];
707
+ if (!ns) {
708
+ console.error("Usage: svamp machine storage unmark-orphan <namespace>");
709
+ process.exit(1);
710
+ }
711
+ await storageUnmarkOrphan(ns);
712
+ } else if (storageSubcmd === "delete") {
713
+ const ns = storageArgs[1];
714
+ if (!ns) {
715
+ console.error("Usage: svamp machine storage delete <namespace>");
716
+ process.exit(1);
717
+ }
718
+ await storageDelete(ns);
719
+ } else {
720
+ console.error(`Unknown storage command: ${storageSubcmd}`);
721
+ printStorageHelp();
722
+ process.exit(1);
723
+ }
639
724
  } else {
640
725
  console.error(`Unknown machine command: ${machineSubcommand}`);
641
726
  printMachineHelp();
@@ -996,50 +1081,38 @@ function printHelp() {
996
1081
  console.log(`
997
1082
  svamp \u2014 AI workspace on Hypha Cloud
998
1083
 
999
- Usage:
1000
- svamp Start interactive Claude session (synced to cloud)
1001
- svamp start [-d <path>] Same as above, with explicit directory
1002
- svamp login [url] Login to Hypha (opens browser, stores token)
1003
- svamp daemon start Start the daemon (detached)
1004
- svamp daemon stop Stop the daemon (sessions preserved for restart)
1005
- svamp daemon restart Restart the daemon (sessions resume seamlessly)
1006
- svamp daemon status Show daemon status
1007
- svamp daemon install Install as system service (launchd/systemd/wrapper)
1008
- svamp session list List active sessions
1009
- svamp session spawn Spawn a new session on the daemon
1010
- svamp session send <id> <m> Send message to a session
1011
- svamp session wait <id> Wait for agent to become idle
1012
- svamp session info <id> Show session status & pending permissions
1013
- svamp session messages <id> Show message history
1014
- svamp session approve <id> Approve pending permission request
1015
- svamp session deny <id> Deny pending permission request
1016
- svamp session attach <id> Attach to a session (interactive terminal)
1017
- svamp session share <id> Manage session sharing
1018
- svamp session --help Show all session commands
1019
- svamp machine share Manage machine sharing & security contexts
1020
- svamp machine --help Show all machine commands
1021
- svamp skills find <query> Search the skills marketplace
1022
- svamp skills install <n> Install a skill from the marketplace
1023
- svamp skills --help Show all skill commands
1024
- svamp process apply <f.yaml> Create/update a supervised process (idempotent)
1025
- svamp process list List supervised processes
1026
- svamp process start <name> Start or create a process
1027
- svamp process logs <name> Show process log output
1028
- svamp process --help Show all process commands
1029
- svamp service expose <name> Expose a service from this sandbox
1030
- svamp service list List service groups
1031
- svamp service --help Show all service commands
1032
- svamp agent list List known agents
1033
- svamp agent <name> Start local agent session (gemini, codex)
1034
- svamp --version Show version
1035
- svamp --help Show this help
1084
+ Quick start \u2014 spawn an agent to do a task:
1085
+ svamp session spawn claude -d ./project -p bypassPermissions --message "fix tests" --wait
1086
+
1087
+ Commands:
1088
+ svamp Start interactive Claude session (synced to cloud)
1089
+ svamp login [url] Login to Hypha (opens browser, stores token)
1090
+ svamp daemon start Start the background daemon (required for sessions)
1091
+ svamp daemon status Show daemon status
1092
+ svamp daemon --help Show all daemon commands
1093
+
1094
+ Session management (requires daemon running):
1095
+ svamp session spawn <agent> [opts] Spawn a new agent session (agents: claude, gemini, codex)
1096
+ svamp session send <id> <message> Send message to a session (--wait to block until done)
1097
+ svamp session wait <id> Wait for agent to become idle
1098
+ svamp session messages <id> Show message history (--last N, --json, --raw)
1099
+ svamp session info <id> Show session status & pending permissions
1100
+ svamp session list List sessions
1101
+ svamp session stop <id> Stop a session
1102
+ svamp session attach <id> Attach interactive terminal (stdin/stdout)
1103
+ svamp session approve/deny <id> Approve or deny pending permission requests
1104
+ svamp session --help Show ALL session commands and detailed options
1105
+
1106
+ Other:
1107
+ svamp machine --help Machine sharing & security contexts
1108
+ svamp skills --help Skills marketplace (find, install, publish)
1109
+ svamp service --help Service exposure (HTTP services from sandboxes)
1110
+ svamp agent <name> Start local agent session (no daemon needed)
1111
+ svamp --version Show version
1036
1112
 
1037
1113
  Interactive mode:
1038
- When you run 'svamp' with no arguments, Claude starts in your terminal
1039
- with full interactive access. Your session is synced to Hypha Cloud so
1040
- it's visible in the web app. When a message arrives from the web app,
1041
- svamp switches to remote mode to process it, then you can press
1042
- Space-Space to return to local mode.
1114
+ Run 'svamp' with no arguments to start Claude in your terminal with cloud sync.
1115
+ Messages from the web app auto-switch to remote mode. Space-Space returns to local.
1043
1116
 
1044
1117
  Environment variables:
1045
1118
  HYPHA_SERVER_URL Hypha server URL (required for cloud sync)
@@ -1065,149 +1138,169 @@ Usage:
1065
1138
  }
1066
1139
  function printSessionHelp() {
1067
1140
  console.log(`
1068
- svamp session \u2014 Manage daemon sessions (Claude, Gemini, Codex)
1141
+ svamp session \u2014 Spawn and manage AI agent sessions
1069
1142
 
1070
- Commands:
1071
- svamp session list [--active] [--json] List sessions (alias: ls)
1072
- svamp session machines List discoverable machines
1073
- svamp session spawn <agent> [-d <path>] [options] Spawn a new session
1074
- svamp session stop <id> Stop a session
1075
- svamp session info <id> [--json] Show status, activity & pending permissions
1076
- svamp session send <id> <message> [--wait] [--timeout N] [--json]
1077
- Send a message to a session
1078
- svamp session wait <id> [--timeout N] [--json] Wait for agent to become idle
1079
- svamp session messages <id> [--last N] [--json] [--raw] [--after N] [--limit N]
1080
- Show messages (alias: msgs)
1081
- svamp session attach <id> Attach to session (interactive terminal)
1082
- svamp session approve <id> [request-id] [--json] Approve pending permission(s)
1083
- svamp session deny <id> [request-id] [--json] Deny pending permission(s)
1143
+ QUICK START \u2014 Spawn a session, give it a task, get results:
1084
1144
 
1085
- Spawn options:
1086
- -d, --directory <path> Working directory (default: cwd)
1087
- -p, --permission-mode <mode> Agent permission mode (see "Permission modes" below)
1088
- --message <msg> Send initial message after spawn
1089
- --wait Wait for agent to become idle before returning
1090
- --worktree Create a git worktree branch (at .dev/worktree/<name>)
1091
- --isolate Force OS-level sandbox isolation
1092
- --security-context <path> Apply security context config (JSON file)
1093
- --share <email>[:<role>] Share with user (repeatable). Role: view, interact, admin
1094
- --deny-network Block all network access
1095
- --deny-read <path> Deny reading path (repeatable)
1096
- --allow-write <path> Allow writing path (repeatable)
1097
- --allow-domain <domain> Allow network domain (repeatable)
1145
+ # One-liner: spawn agent, send task, wait for completion
1146
+ svamp session spawn claude -d ./my-project -p bypassPermissions \\
1147
+ --message "fix the failing tests" --wait
1098
1148
 
1099
- Permission modes (-p, --permission-mode):
1100
- default Prompt for each tool use (default)
1101
- acceptEdits Auto-approve file edits, prompt for bash/dangerous tools
1102
- bypassPermissions Auto-approve all tools (no prompts)
1149
+ # The command prints the session ID (e.g., "abc12345-..."). Use it to:
1150
+ svamp session messages abc1 --last 10 # read output (prefix match on ID)
1151
+ svamp session send abc1 "now run lint" --wait # send follow-up, wait for done
1152
+ svamp session stop abc1 # stop when finished
1103
1153
 
1104
- Permission workflow:
1105
- When an agent runs with 'default' or 'acceptEdits' permission mode, it pauses
1106
- when it needs to use a tool that requires approval. Use these commands to manage:
1154
+ # Spawn on a remote/cloud machine:
1155
+ svamp session spawn claude -d /workspace -m cloud-box --message "deploy" --wait
1107
1156
 
1108
- 1. Check status: svamp session info <id> --json
1109
- \u2192 shows pendingPermissions array when agent is blocked
1110
- 2. Wait & detect: svamp session wait <id> --json
1111
- \u2192 exits with code 2 if permission pending (see exit codes)
1112
- 3. Approve: svamp session approve <id> (approve all pending)
1113
- svamp session approve <id> <rid> (approve specific request)
1114
- 4. Deny: svamp session deny <id> (deny all pending)
1115
- svamp session deny <id> <rid> (deny specific request)
1157
+ AGENTS:
1158
+ claude Claude Code \u2014 full coding agent (default)
1159
+ gemini Google Gemini via ACP protocol
1160
+ codex OpenAI Codex via MCP protocol
1116
1161
 
1117
- Request IDs support prefix matching (e.g., "abc1" matches "abc12345-...").
1162
+ Usage: svamp session spawn <agent> [options]
1163
+ The <agent> argument is required. Use "claude" if unsure.
1118
1164
 
1119
- Messages options:
1120
- --last N Show only the last N messages
1121
- --after N Start after sequence number N
1122
- --limit N Max messages to fetch from server (default: 1000, cap: 500 per page)
1123
- --json Output as JSON (FormattedMessage: id, seq, role, text, createdAt)
1124
- --raw With --json: output full raw message objects (includes tool_use args,
1125
- tool_result content, thinking blocks \u2014 use for programmatic parsing)
1165
+ COMMANDS:
1126
1166
 
1127
- Exit codes (wait, send --wait, spawn --wait):
1128
- 0 Agent is idle (task completed)
1129
- 1 Error (timeout, connection failure, session not found)
1130
- 2 Agent is waiting for permission approval \u2014 use approve/deny to continue
1167
+ Lifecycle:
1168
+ spawn <agent> [-d <path>] [options] Spawn a new agent session
1169
+ stop <id> Stop a running session
1170
+ list [--active] [--json] List sessions (alias: ls)
1171
+ machines List discoverable machines
1172
+ info <id> [--json] Show status & pending permissions
1131
1173
 
1132
- Global options:
1133
- --machine <id>, -m <id> Target a specific machine (prefix match supported)
1174
+ Communicate:
1175
+ send <id> <message> [--wait] [--timeout N] [--json]
1176
+ Send a message to a running session
1177
+ messages <id> [--last N] [--json] Read message history (alias: msgs)
1178
+ wait <id> [--timeout N] [--json] Wait for agent to become idle
1179
+ attach <id> Attach interactive terminal (stdin/stdout)
1134
1180
 
1135
- Agents: claude (default), gemini, codex
1136
- Session and machine IDs support prefix matching (e.g., "abc1" matches "abc12345-...").
1181
+ Permissions (when agent pauses for approval):
1182
+ approve <id> [request-id] [--json] Approve pending tool permission(s)
1183
+ deny <id> [request-id] [--json] Deny pending tool permission(s)
1137
1184
 
1138
- Sharing:
1139
- svamp session share <id> --list List shared users
1140
- svamp session share <id> --add <email>[:<role>] Share with user
1141
- svamp session share <id> --remove <email> Remove shared user
1142
- svamp session share <id> --public <view|interact|off> Set public link access
1185
+ Sharing:
1186
+ share <id> --list List shared users
1187
+ share <id> --add <email>[:<role>] Share with user (role: view|interact|admin)
1188
+ share <id> --remove <email> Remove shared user
1189
+ share <id> --public <view|interact|off> Set public link access
1143
1190
 
1144
- Options:
1145
- --machine <id>, -m <id> Target a specific machine (prefix match supported)
1191
+ Ralph Loop (iterative automation):
1192
+ ralph-start <id> "<task>" [options] Start iterative loop
1193
+ ralph-cancel <id> Cancel loop
1194
+ ralph-status <id> Show loop status
1195
+
1196
+ Message Queue:
1197
+ queue add <id> "<message>" Queue a message for later
1198
+ queue list <id> List queued messages
1199
+ queue clear <id> Clear queue
1146
1200
 
1147
- Spawn options:
1148
- -p, --permission-mode <mode> Agent permission mode: default, acceptEdits, bypassPermissions
1149
- --worktree Create a git worktree branch as working directory
1201
+ SPAWN OPTIONS:
1202
+ -d, --directory <path> Working directory (REQUIRED for meaningful work)
1203
+ -p, --permission-mode <mode> Permission mode (see below). Default: "default"
1204
+ --message <msg> Send this message to the agent immediately after spawn
1205
+ --wait Block until agent finishes (idle). Combine with --message
1206
+ for fire-and-forget: spawn \u2192 task \u2192 wait \u2192 done.
1207
+ --timeout <sec> Timeout for --wait (default: no timeout)
1208
+ --worktree Create isolated git worktree branch (.dev/worktree/<name>)
1209
+ --tags <tag1,tag2> Comma-separated tags for session grouping
1210
+ --parent <sessionId> Set parent session (auto-set from SVAMP_SESSION_ID env)
1150
1211
 
1151
- Spawn isolation options:
1152
- --share <email>[:<role>] Share session (repeatable). Role: view, interact, admin
1153
- --security-context <path> Path to security context JSON config file
1154
- --isolate Force OS-level isolation even without sharing
1155
- --deny-read <path> Deny read access to path (repeatable)
1156
- --allow-write <path> Allow write access to path (repeatable)
1157
- --deny-network Deny all network access
1158
- --allow-domain <domain> Allow network access to domain (repeatable)
1212
+ PERMISSION MODES:
1213
+ default Agent pauses and asks for approval before each tool use.
1214
+ You must use "approve" / "deny" commands to unblock it.
1215
+ acceptEdits Auto-approve file edits. Pauses for bash & dangerous tools.
1216
+ bypassPermissions Auto-approve everything. No prompts, no pauses.
1217
+ \u26A0 Use this for automation / when you trust the agent fully.
1159
1218
 
1160
- Spawn grouping options:
1161
- --tags <tag1,tag2> Comma-separated tags
1162
- --parent <sessionId> Set parent session (auto-detected from SVAMP_SESSION_ID)
1219
+ Tip: For programmatic use (spawning from another agent or script), use
1220
+ -p bypassPermissions to avoid the agent getting stuck waiting for approval.
1163
1221
 
1164
- Agents: claude (default), gemini, codex
1222
+ PERMISSION WORKFLOW (only relevant for "default" and "acceptEdits" modes):
1223
+ 1. svamp session wait <id> --json \u2192 exit code 2 means permission pending
1224
+ 2. svamp session info <id> --json \u2192 shows pendingPermissions array
1225
+ 3. svamp session approve <id> \u2192 approve all pending (or approve <id> <rid>)
1226
+ 4. svamp session deny <id> \u2192 deny all pending (or deny <id> <rid>)
1165
1227
 
1166
- Session and machine IDs can be abbreviated (prefix match, like Docker).
1228
+ ISOLATION & SHARING OPTIONS (for spawn):
1229
+ --isolate Force OS-level sandbox (even without sharing)
1230
+ --security-context <path> Apply security context config (JSON file)
1231
+ --share <email>[:<role>] Share session (repeatable). Role: view|interact|admin
1232
+ --deny-network Block all network access
1233
+ --deny-read <path> Deny reading path (repeatable)
1234
+ --allow-write <path> Allow writing path (repeatable)
1235
+ --allow-domain <domain> Allow network domain (repeatable)
1236
+
1237
+ MESSAGES OPTIONS:
1238
+ --last N Show last N messages only
1239
+ --after N Start after sequence number N (for pagination)
1240
+ --limit N Max messages to fetch (default: 1000)
1241
+ --json Output as JSON array of {id, seq, role, text, createdAt}
1242
+ --raw With --json: include full raw objects (tool_use, tool_result, thinking)
1167
1243
 
1168
- NOTE: By default, spawned agents run with 'default' permission mode, which means
1169
- the agent may pause to request permission for tool use (file edits, bash, etc.).
1170
- Use -p bypassPermissions to run without approval prompts.
1244
+ RALPH LOOP OPTIONS (for ralph-start):
1245
+ --context-mode <mode> fresh (new process each iteration) or continue (same process)
1246
+ --completion-promise <text> Completion signal text (default: DONE)
1247
+ --max-iterations <n> Max iterations (default: 10)
1248
+ --cooldown <sec> Delay between iterations (default: 1)
1171
1249
 
1172
- Attach commands:
1250
+ EXIT CODES (for wait, send --wait, spawn --wait):
1251
+ 0 Agent is idle (task completed successfully)
1252
+ 1 Error (timeout, connection failure, session not found)
1253
+ 2 Agent is waiting for permission approval \u2014 use approve/deny to unblock
1254
+
1255
+ ATTACH COMMANDS (inside an attached session):
1173
1256
  /quit, /detach Detach (session keeps running)
1174
1257
  /abort, /cancel Cancel current agent turn
1175
- /kill Stop the session
1258
+ /kill Stop the session entirely
1176
1259
  /info Show session status
1177
1260
 
1178
- Ralph Loop (iterative task automation):
1179
- svamp session ralph-start <id> "<task>" [--context-mode fresh|continue] [--completion-promise TEXT] [--max-iterations N] [--cooldown N]
1180
- svamp session ralph-cancel <id>
1181
- svamp session ralph-status <id>
1182
- (alias: svamp session ralph <id> "<task>" ...)
1261
+ GLOBAL OPTIONS:
1262
+ --machine <id>, -m <id> Target a specific machine (prefix match supported)
1183
1263
 
1184
- Message Queue:
1185
- svamp session queue add <id> "<message>"
1186
- svamp session queue list <id>
1187
- svamp session queue clear <id>
1264
+ ID MATCHING:
1265
+ Session and machine IDs support prefix matching.
1266
+ "abc1" matches "abc12345-6789-..." \u2014 you only need enough characters to be unique.
1188
1267
 
1189
- Examples:
1190
- # Spawn with bypassed permissions (no prompts)
1191
- svamp session spawn claude -d ./proj -p bypassPermissions --message "fix tests" --wait
1268
+ EXAMPLES:
1192
1269
 
1193
- # Spawn with default permissions, handle approval via CLI
1194
- svamp session spawn claude -d ./proj --message "refactor auth"
1195
- svamp session wait abc1 --json # exits with code 2 if permission pending
1196
- svamp session approve abc1 # approve all pending permissions
1197
- svamp session wait abc1 # wait for completion
1270
+ # === Common: Spawn agent to do a task and wait ===
1271
+ svamp session spawn claude -d ./my-project -p bypassPermissions \\
1272
+ --message "fix all TypeScript errors, run tsc to verify" --wait
1198
1273
 
1199
- # Monitor session messages (raw for full tool details)
1200
- svamp session messages abc1 --last 10 --json --raw
1274
+ # === Multi-step: Spawn, then send messages interactively ===
1275
+ ID=$(svamp session spawn claude -d ./proj -p bypassPermissions)
1276
+ svamp session send $ID "first, read the README" --wait
1277
+ svamp session send $ID "now implement the feature described there" --wait
1278
+ svamp session messages $ID --last 20
1201
1279
 
1202
- # Send message and wait for completion
1203
- svamp session send abc1 "run the tests" --wait --json
1280
+ # === Spawn child session from another agent (e.g., in a bash tool) ===
1281
+ # Use -p bypassPermissions so the child doesn't get stuck on approvals.
1282
+ # Use --wait so your script blocks until the child finishes.
1283
+ svamp session spawn claude -d /tmp/test-project -p bypassPermissions \\
1284
+ --message "run the test suite and report results" --wait
1285
+ # Then read the child's output:
1286
+ svamp session messages <child-id> --last 5
1204
1287
 
1205
- # Isolation & sharing
1288
+ # === Monitor with permissions (default mode) ===
1289
+ svamp session spawn claude -d ./proj --message "refactor auth module"
1290
+ svamp session wait abc1 --json # exit code 2 = permission pending
1291
+ svamp session approve abc1 # approve all pending
1292
+ svamp session wait abc1 # wait for completion
1293
+
1294
+ # === Spawn on a remote machine ===
1295
+ svamp session spawn claude -d /workspace -m my-cloud-box \\
1296
+ -p bypassPermissions --message "deploy to staging" --wait
1297
+
1298
+ # === Isolated session with network restrictions ===
1206
1299
  svamp session spawn claude -d /tmp/sandbox --isolate --deny-network
1207
- svamp session spawn claude -d /tmp/proj --share alice@example.com:admin
1208
1300
 
1209
- # Ralph Loop
1210
- svamp session ralph-start abc1 "Fix all linting errors" --context-mode fresh --max-iterations 10
1301
+ # === Ralph Loop: iterative task automation ===
1302
+ svamp session ralph-start abc1 "Fix all linting errors" \\
1303
+ --context-mode fresh --max-iterations 10
1211
1304
  `);
1212
1305
  }
1213
1306
  function printMachineHelp() {
@@ -1224,6 +1317,13 @@ Usage:
1224
1317
  svamp machine share --config <path> Apply security context config
1225
1318
  svamp machine share --show-config Show current security context config
1226
1319
 
1320
+ Storage (admin):
1321
+ svamp machine storage list List all user PVCs with status
1322
+ svamp machine storage orphans [--mark] Show PVCs with no active namespace
1323
+ svamp machine storage mark-orphan <namespace> Flag a PVC as orphaned
1324
+ svamp machine storage unmark-orphan <namespace> Remove orphan flag
1325
+ svamp machine storage delete <namespace> Permanently delete a PVC (double confirm)
1326
+
1227
1327
  Options:
1228
1328
  --machine <id>, -m <id> Target a specific machine (prefix match supported)
1229
1329
  --cwd <path> Working directory for exec (default: home dir)
@@ -1,11 +1,11 @@
1
1
  import { writeFileSync, readFileSync } from 'fs';
2
2
  import { resolve } from 'path';
3
- import { connectAndGetMachine } from './commands-Brx7D-77.mjs';
3
+ import { connectAndGetMachine } from './commands-Dpc6QK0m.mjs';
4
4
  import 'node:fs';
5
5
  import 'node:child_process';
6
6
  import 'node:path';
7
7
  import 'node:os';
8
- import './run-BImPgXHd.mjs';
8
+ import './run-BDmLH9T8.mjs';
9
9
  import 'os';
10
10
  import 'fs/promises';
11
11
  import 'url';