@mutagent/cli 0.1.282 → 0.1.284

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/bin/cli.js CHANGED
@@ -884,7 +884,7 @@ var init_sdk_client = __esm(() => {
884
884
 
885
885
  // src/bin/cli.ts
886
886
  import { Command as Command15 } from "commander";
887
- import chalk28 from "chalk";
887
+ import chalk29 from "chalk";
888
888
  import { readFileSync as readFileSync12 } from "fs";
889
889
  import { join as join14, dirname as dirname4 } from "path";
890
890
  import { fileURLToPath as fileURLToPath2 } from "url";
@@ -6122,7 +6122,7 @@ If mutagent-cli is not installed: mutagent install helix`), isJson);
6122
6122
 
6123
6123
  // src/commands/helix/index.ts
6124
6124
  import { Command as Command14 } from "commander";
6125
- import chalk27 from "chalk";
6125
+ import chalk28 from "chalk";
6126
6126
 
6127
6127
  // src/commands/helix/spawn.ts
6128
6128
  import chalk21 from "chalk";
@@ -6415,6 +6415,13 @@ async function postInput(id, body) {
6415
6415
  sandboxId: id
6416
6416
  });
6417
6417
  }
6418
+ async function postSignal(id, body) {
6419
+ return requestJson(`/api/sandbox/${encodeURIComponent(id)}/signal`, {
6420
+ method: "POST",
6421
+ body: JSON.stringify(body),
6422
+ sandboxId: id
6423
+ });
6424
+ }
6418
6425
  async function startSession(id, body) {
6419
6426
  return requestJson(`/api/sandbox/${encodeURIComponent(id)}/session`, {
6420
6427
  method: "POST",
@@ -7582,22 +7589,112 @@ function readType(raw) {
7582
7589
  return "raw";
7583
7590
  }
7584
7591
 
7592
+ // src/commands/helix/signal.ts
7593
+ import chalk24 from "chalk";
7594
+ init_errors();
7595
+ var SIGNAL_TYPES = ["SIGINT", "SIGTERM"];
7596
+ var DEFAULT_SIGNAL = "SIGINT";
7597
+ function registerSignalCommand(parent) {
7598
+ parent.command("signal").description("Stop a running session, leaving its sandbox up").argument("<id>", "Sandbox ID").requiredOption("--session <id>", "Session ID inside the sandbox").option("--type <signal>", `${SIGNAL_TYPES.join(" | ")} (default: ${DEFAULT_SIGNAL})`).addHelpText("after", `
7599
+ Examples:
7600
+ ${chalk24.dim("$")} mutagent helix signal sbx_123 --session s1 ${chalk24.dim("SIGINT — like Ctrl-C")}
7601
+ ${chalk24.dim("$")} mutagent helix signal sbx_123 --session s1 --type SIGTERM ${chalk24.dim("Ask it to shut down")}
7602
+ ${chalk24.dim("$")} mutagent helix signal sbx_123 --session s1 --json
7603
+
7604
+ THE SANDBOX SURVIVES. This stops the SESSION — the agent process — and leaves
7605
+ the box, its filesystem and its event log exactly where they are, so you can
7606
+ attach, exec against it, or read what the agent did before you stopped it.
7607
+ 'mutagent helix rm <id>' is still the only thing that destroys a sandbox.
7608
+
7609
+ THREE WAYS TO STOP AN AGENT, WEAKEST FIRST:
7610
+ ${chalk24.bold("send --type abort")} Asks the agent to end the turn. Needs a cooperating agent
7611
+ that is still reading its stdin. Try this first.
7612
+ ${chalk24.bold("signal")} Does not ask. Reaches a wedged or looping process.
7613
+ The session ends; the box stays.
7614
+ ${chalk24.bold("rm")} Destroys the sandbox and everything in it.
7615
+
7616
+ THE SIGNALS:
7617
+ SIGINT Interrupts the current turn, the way Ctrl-C does in a local terminal.
7618
+ SIGTERM Asks the process to shut down.
7619
+ SIGKILL is not accepted: it would end the session before it could flush the
7620
+ output you came back to read.
7621
+
7622
+ A 200 here means a LIVE process was signalled — not just that the request was
7623
+ understood. A session that had already finished is reported as such rather than
7624
+ being counted as a success, so this never tells you that you stopped an agent
7625
+ that had in fact been done for a while.
7626
+
7627
+ 'mutagent helix ls' shows which sandboxes are up; 'mutagent helix attach <id>'
7628
+ shows what the session was doing.
7629
+
7630
+ AI Agent Directive:
7631
+ --json returns ONE object: { success, sandboxId, sessionId, signal, signalled,
7632
+ _links }. 'signalled' is an EFFECT, not an acknowledgement — it is true only
7633
+ when a running process was actually stopped.
7634
+ A session that has already ended exits non-zero rather than reporting success.
7635
+ Treat that as information, not as a failure to retry: the agent is already
7636
+ stopped, which is what you wanted.
7637
+ This does NOT destroy the sandbox. It stays billable until 'mutagent helix rm
7638
+ <id>'. Confirm with the user before that.
7639
+ `).action(async (id, options) => {
7640
+ const isJson = getJsonFlag(parent);
7641
+ const output = new OutputFormatter(isJson ? "json" : "table");
7642
+ try {
7643
+ const sessionId = options.session?.trim() ?? "";
7644
+ if (sessionId === "") {
7645
+ throw new MutagentError("MISSING_ARGUMENTS", "--session is required — a sandbox can hold more than one session.", `Run: mutagent helix signal ${id} --session <session-id>`);
7646
+ }
7647
+ const signal = resolveSignal(options.type);
7648
+ const result = await postSignal(id, { sessionId, signal });
7649
+ if (isJson) {
7650
+ output.output({
7651
+ success: true,
7652
+ sandboxId: id,
7653
+ sessionId,
7654
+ signal,
7655
+ signalled: result.signalled,
7656
+ _links: sandboxLinks(id),
7657
+ _directive: {
7658
+ instruction: "The session was stopped. The SANDBOX is still running and still billable — remove it explicitly when you are done with it.",
7659
+ next: [`mutagent helix attach ${id} --json`, `mutagent helix rm ${id}`]
7660
+ }
7661
+ });
7662
+ return;
7663
+ }
7664
+ output.success(`Sent ${signal} to session ${sessionId}`);
7665
+ console.error(chalk24.dim(` The sandbox is still up: mutagent helix attach ${id}`));
7666
+ console.error(chalk24.dim(` Destroy it with: mutagent helix rm ${id}`));
7667
+ } catch (error) {
7668
+ handleError(error, isJson);
7669
+ }
7670
+ });
7671
+ }
7672
+ function resolveSignal(raw) {
7673
+ if (raw === undefined)
7674
+ return DEFAULT_SIGNAL;
7675
+ const normalised = raw.trim().toUpperCase();
7676
+ if (!SIGNAL_TYPES.includes(normalised)) {
7677
+ throw new MutagentError("INVALID_ARGUMENTS", `Unknown signal "${raw}".`, `Use one of: ${SIGNAL_TYPES.join(", ")}. SIGKILL is not accepted — it would end the session before it could flush its output.`);
7678
+ }
7679
+ return normalised;
7680
+ }
7681
+
7585
7682
  // src/commands/helix/session-start.ts
7586
7683
  import { Command as Command13 } from "commander";
7587
- import chalk24 from "chalk";
7684
+ import chalk25 from "chalk";
7588
7685
  init_errors();
7589
7686
  function registerSessionCommand(parent) {
7590
7687
  const session = new Command13("session").description("Start and inspect Helix sessions inside a sandbox").addHelpText("after", `
7591
7688
  Examples:
7592
- ${chalk24.dim("$")} mutagent helix session start sbx_123 --rpc
7593
- ${chalk24.dim("$")} mutagent helix session start sbx_123
7594
- ${chalk24.dim("$")} mutagent helix session start sbx_123 --rpc --json
7689
+ ${chalk25.dim("$")} mutagent helix session start sbx_123 --rpc
7690
+ ${chalk25.dim("$")} mutagent helix session start sbx_123
7691
+ ${chalk25.dim("$")} mutagent helix session start sbx_123 --rpc --json
7595
7692
 
7596
7693
  A sandbox and a session are not the same thing:
7597
- ${chalk24.bold("spawn")} gives you a BOX — a machine with nothing running in it.
7598
- ${chalk24.bold("session start")} gives you an AGENT inside that box.
7599
- ${chalk24.bold("attach")} WATCHES that agent.
7600
- ${chalk24.bold("send")} TYPES INTO it.
7694
+ ${chalk25.bold("spawn")} gives you a BOX — a machine with nothing running in it.
7695
+ ${chalk25.bold("session start")} gives you an AGENT inside that box.
7696
+ ${chalk25.bold("attach")} WATCHES that agent.
7697
+ ${chalk25.bold("send")} TYPES INTO it.
7601
7698
  A box with no session is a normal state — that is what 'exec' runs against.
7602
7699
 
7603
7700
  AI Agent Directive:
@@ -7610,15 +7707,15 @@ AI Agent Directive:
7610
7707
  function registerStart(session, root) {
7611
7708
  session.command("start").description("Start a Helix session inside an existing sandbox").argument("<id>", "Sandbox ID").option("--rpc", "Long-lived session you can send into (default: one-shot)").addHelpText("after", `
7612
7709
  Examples:
7613
- ${chalk24.dim("$")} mutagent helix session start sbx_123 --rpc
7614
- ${chalk24.dim("$")} mutagent helix session start sbx_123
7615
- ${chalk24.dim("$")} mutagent helix session start sbx_123 --rpc --json
7710
+ ${chalk25.dim("$")} mutagent helix session start sbx_123 --rpc
7711
+ ${chalk25.dim("$")} mutagent helix session start sbx_123
7712
+ ${chalk25.dim("$")} mutagent helix session start sbx_123 --rpc --json
7616
7713
 
7617
7714
  TWO MODES, AND ONLY ONE OF THEM LISTENS:
7618
- ${chalk24.bold("--rpc")} A long-lived agent reading commands on its stdin. This is
7715
+ ${chalk25.bold("--rpc")} A long-lived agent reading commands on its stdin. This is
7619
7716
  the mode 'mutagent helix send' writes into; without it there
7620
7717
  is nothing to write to and every send is refused.
7621
- ${chalk24.dim("(default)")} One-shot. The session takes its turn and ends. Watchable
7718
+ ${chalk25.dim("(default)")} One-shot. The session takes its turn and ends. Watchable
7622
7719
  with 'attach', not steerable.
7623
7720
 
7624
7721
  The box must already exist — 'mutagent helix spawn --image <ref>' makes one, and
@@ -7660,9 +7757,9 @@ AI Agent Directive:
7660
7757
  return;
7661
7758
  }
7662
7759
  output.success(`Session ${sessionId} started in ${id} (${mode})`);
7663
- console.error(chalk24.dim(` Watch it: mutagent helix attach ${id}`));
7760
+ console.error(chalk25.dim(` Watch it: mutagent helix attach ${id}`));
7664
7761
  if (mode === "rpc") {
7665
- console.error(chalk24.dim(` Talk to it: mutagent helix send ${id} --session ${sessionId} "<message>"`));
7762
+ console.error(chalk25.dim(` Talk to it: mutagent helix send ${id} --session ${sessionId} "<message>"`));
7666
7763
  }
7667
7764
  } catch (error) {
7668
7765
  handleError(error, isJson);
@@ -7676,15 +7773,32 @@ function requireSessionId(result, sandboxId) {
7676
7773
  }
7677
7774
 
7678
7775
  // src/commands/helix/run.ts
7679
- import chalk25 from "chalk";
7776
+ import chalk26 from "chalk";
7680
7777
  init_errors();
7681
7778
  function registerRunCommand(parent) {
7682
- parent.command("run").description("Run one Helix agent turn in a fresh sandbox").argument("<task...>", "WHAT to do this turn").requiredOption("--prompt <definition>", "WHO the agent is — the agent definition").option("--preset <name>", "Preset to run on (default: the backend default)").option("--keep", "Keep the sandbox afterwards instead of tearing it down").option("--timeout-ms <n>", "Per-command timeout in milliseconds").option("--no-stream", "Wait for the whole turn instead of watching it happen").addHelpText("after", `
7779
+ parent.command("run").alias("agent").description("Run one Helix agent turn in a fresh sandbox (alias: agent)").argument("<task...>", "WHAT to do this turn").requiredOption("--prompt <definition>", "WHO the agent is — the agent definition").option("--preset <name>", "Preset to run on (default: the backend default)").option("--keep", "Keep the sandbox afterwards instead of tearing it down").option("--timeout-ms <n>", "Per-command timeout in milliseconds").option("--no-stream", "Wait for the whole turn instead of watching it happen").option("--prime", "Run on the leaner ASPS-Prime scaffold (the binary's --prime)").addHelpText("after", `
7683
7780
  Examples:
7684
- ${chalk25.dim("$")} mutagent helix run "summarise the failing tests" --prompt "You are a test triage agent."
7685
- ${chalk25.dim("$")} mutagent helix run fix the flaky login spec --prompt "$(cat agent.md)"
7686
- ${chalk25.dim("$")} mutagent helix run "list open PRs" --prompt "You are a release assistant." --json
7687
- ${chalk25.dim("$")} mutagent helix run "explore the repo" --prompt "$(cat agent.md)" --keep
7781
+ ${chalk26.dim("$")} mutagent helix run "summarise the failing tests" --prompt "You are a test triage agent."
7782
+ ${chalk26.dim("$")} mutagent helix run fix the flaky login spec --prompt "$(cat agent.md)"
7783
+ ${chalk26.dim("$")} mutagent helix run "list open PRs" --prompt "You are a release assistant." --json
7784
+ ${chalk26.dim("$")} mutagent helix run "explore the repo" --prompt "$(cat agent.md)" --keep
7785
+
7786
+ --prime — THE SAME FLAG THE LOCAL BINARY TAKES:
7787
+ 'helix agent --prime' locally and 'mutagent helix run --prime' in the cloud
7788
+ select the same thing: the ASPS-Prime scaffold, a leaner code-first arm with
7789
+ no orchestrator persona, no skills and no sub-agent crew. It is forwarded to
7790
+ the binary as argv rather than interpreted by the server, so it means exactly
7791
+ what the binary's own --help says it means. This is NOT a speed setting — it
7792
+ changes which agent takes the turn.
7793
+
7794
+ SAME COMMAND, TWO NAMES:
7795
+ 'mutagent helix agent' is an ALIAS of 'mutagent helix run'. Not a variant, not
7796
+ a shorthand with different defaults — the same command, the same flags, the
7797
+ same behaviour. It exists so the verb that works against the local binary
7798
+ ('helix agent --prompt "..." "task"') also works against the cloud.
7799
+ RUN is the canonical name: it is what the docs, the JSON output and the error
7800
+ messages use. 'agent' is there so a caller who learned the local CLI does not
7801
+ have to learn a second word for the same operation.
7688
7802
 
7689
7803
  TWO PROMPTS, AND THEY ARE NOT THE SAME THING:
7690
7804
  --prompt WHO the agent is — its definition, its standing instructions.
@@ -7719,6 +7833,11 @@ AI Agent Directive:
7719
7833
  is a complete summary object, so '| tail -1' still yields one object. Same
7720
7834
  convention as 'mutagent helix exec'.
7721
7835
  Both --prompt and the task are required; do not fold one into the other.
7836
+ 'mutagent helix agent' and 'mutagent helix run' are THE SAME COMMAND. Prefer
7837
+ 'run' in anything you write down; 'agent' exists for parity with the local
7838
+ 'helix agent' verb.
7839
+ --prime selects the binary's leaner scaffold. Omit it unless the user asked
7840
+ for it; it is not a performance flag, it changes which agent runs.
7722
7841
  `).action(async (taskParts, options) => {
7723
7842
  const isJson = getJsonFlag(parent);
7724
7843
  const output = new OutputFormatter(isJson ? "json" : "table");
@@ -7735,6 +7854,7 @@ AI Agent Directive:
7735
7854
  const body = {
7736
7855
  prompt,
7737
7856
  task,
7857
+ ...options.prime === true ? { prime: true } : {},
7738
7858
  ...oneShotFields(options.preset, options.keep, options.timeoutMs)
7739
7859
  };
7740
7860
  if (options.stream === false) {
@@ -7791,17 +7911,17 @@ async function streamAgentTurn(body, isJson, keep) {
7791
7911
  function registerExecCommand(parent) {
7792
7912
  parent.command("exec").description("Run a command in a sandbox — an existing one, or a fresh one").argument("<argv...>", "Command and arguments (argv, not a shell string)").option("--sandbox <id>", "Run in this existing sandbox instead of a fresh one").option("--preset <name>", "Preset for the fresh sandbox (ignored with --sandbox)").option("--keep", "Keep the fresh sandbox afterwards (ignored with --sandbox)").option("--cwd <dir>", "Working directory inside the sandbox").option("--timeout-ms <n>", "Command timeout in milliseconds").option("--no-stream", "Wait for the full result instead of streaming it").addHelpText("after", `
7793
7913
  Examples:
7794
- ${chalk25.dim("$")} mutagent helix exec -- ls -la /workspace
7795
- ${chalk25.dim("$")} mutagent helix exec --sandbox sbx_123 -- bun test
7796
- ${chalk25.dim("$")} mutagent helix exec --sandbox sbx_123 --cwd /src -- git status
7797
- ${chalk25.dim("$")} mutagent helix exec --preset default -- uname -m --json
7914
+ ${chalk26.dim("$")} mutagent helix exec -- ls -la /workspace
7915
+ ${chalk26.dim("$")} mutagent helix exec --sandbox sbx_123 -- bun test
7916
+ ${chalk26.dim("$")} mutagent helix exec --sandbox sbx_123 --cwd /src -- git status
7917
+ ${chalk26.dim("$")} mutagent helix exec --preset default -- uname -m --json
7798
7918
 
7799
- Put ${chalk25.bold("--")} before the command. Everything after it is argv and is passed through
7919
+ Put ${chalk26.bold("--")} before the command. Everything after it is argv and is passed through
7800
7920
  untouched, so flags meant for your command are not read as flags for this one.
7801
7921
 
7802
7922
  ARGV, NOT A SHELL STRING. There is no shell in the sandbox unless you name one:
7803
- ${chalk25.dim("$")} mutagent helix exec -- sh -c 'ls | wc -l' ${chalk25.dim("a shell, explicitly")}
7804
- ${chalk25.dim("$")} mutagent helix exec -- 'ls | wc -l' ${chalk25.dim("looks for a file called 'ls | wc -l'")}
7923
+ ${chalk26.dim("$")} mutagent helix exec -- sh -c 'ls | wc -l' ${chalk26.dim("a shell, explicitly")}
7924
+ ${chalk26.dim("$")} mutagent helix exec -- 'ls | wc -l' ${chalk26.dim("looks for a file called 'ls | wc -l'")}
7805
7925
 
7806
7926
  WITH --sandbox runs in that box and streams as output is produced.
7807
7927
  WITHOUT --sandbox spawns a fresh box from a preset, runs, tears it down. That
@@ -7933,17 +8053,17 @@ function reportResult(result, output, isJson, context) {
7933
8053
  }
7934
8054
 
7935
8055
  // src/commands/helix/inventory.ts
7936
- import chalk26 from "chalk";
8056
+ import chalk27 from "chalk";
7937
8057
  init_errors();
7938
8058
  function registerLsCommand(parent) {
7939
8059
  parent.command("ls").description("List your sandboxes").addHelpText("after", `
7940
8060
  Examples:
7941
- ${chalk26.dim("$")} mutagent helix ls
7942
- ${chalk26.dim("$")} mutagent helix ls --json
8061
+ ${chalk27.dim("$")} mutagent helix ls
8062
+ ${chalk27.dim("$")} mutagent helix ls --json
7943
8063
 
7944
8064
  Listing is always workspace-scoped — these are the sandboxes in the workspace
7945
8065
  you are configured for, not every sandbox on the account. Change it with:
7946
- ${chalk26.dim("$")} mutagent config set workspace <workspace-id>
8066
+ ${chalk27.dim("$")} mutagent config set workspace <workspace-id>
7947
8067
 
7948
8068
  An empty list is a normal result, not an error: it means no sandbox is running.
7949
8069
 
@@ -7963,7 +8083,7 @@ AI Agent Directive:
7963
8083
  return;
7964
8084
  }
7965
8085
  if (sandboxes.length === 0) {
7966
- console.log(chalk26.gray("No sandboxes running."));
8086
+ console.log(chalk27.gray("No sandboxes running."));
7967
8087
  console.log("");
7968
8088
  console.log(" Start one: mutagent helix spawn --image <ref>");
7969
8089
  return;
@@ -7987,8 +8107,8 @@ function toRow(sandbox) {
7987
8107
  function registerPresetsCommand(parent) {
7988
8108
  parent.command("presets").description("List the presets a one-shot run can name").addHelpText("after", `
7989
8109
  Examples:
7990
- ${chalk26.dim("$")} mutagent helix presets
7991
- ${chalk26.dim("$")} mutagent helix presets --json
8110
+ ${chalk27.dim("$")} mutagent helix presets
8111
+ ${chalk27.dim("$")} mutagent helix presets --json
7992
8112
 
7993
8113
  A preset is a named definition on the backend. It is what lets 'helix run' and
7994
8114
  'helix exec' start something without you knowing an image reference, a registry
@@ -8009,7 +8129,7 @@ AI Agent Directive:
8009
8129
  return;
8010
8130
  }
8011
8131
  if (presets.length === 0) {
8012
- console.log(chalk26.gray("No presets configured on this backend."));
8132
+ console.log(chalk27.gray("No presets configured on this backend."));
8013
8133
  console.log("");
8014
8134
  console.log(" Spawn with an explicit image: mutagent helix spawn --image <ref>");
8015
8135
  return;
@@ -8029,15 +8149,15 @@ AI Agent Directive:
8029
8149
  function registerRmCommand(parent) {
8030
8150
  parent.command("rm").description("Destroy a sandbox").argument("<id>", "Sandbox ID").option("-f, --force", "Skip confirmation").addHelpText("after", `
8031
8151
  Examples:
8032
- ${chalk26.dim("$")} mutagent helix rm sbx_123 --force
8033
- ${chalk26.dim("$")} mutagent helix rm sbx_123 --json
8152
+ ${chalk27.dim("$")} mutagent helix rm sbx_123 --force
8153
+ ${chalk27.dim("$")} mutagent helix rm sbx_123 --json
8034
8154
 
8035
8155
  This is the ONLY command that destroys a sandbox — detaching, Ctrl-C and a
8036
8156
  closed terminal all leave it running. Removing a sandbox that is already gone
8037
8157
  succeeds, so a retried teardown is safe.
8038
8158
 
8039
- ${chalk26.dim("Note: --force is required. The CLI is non-interactive — confirm with the user via your native flow, then pass --force. --json auto-confirms.")}
8040
- ${chalk26.dim("Warning: any session running in the sandbox ends immediately and cannot be recovered.")}
8159
+ ${chalk27.dim("Note: --force is required. The CLI is non-interactive — confirm with the user via your native flow, then pass --force. --json auto-confirms.")}
8160
+ ${chalk27.dim("Warning: any session running in the sandbox ends immediately and cannot be recovered.")}
8041
8161
 
8042
8162
  AI Agent Directive:
8043
8163
  Destroying a sandbox ends any session running in it and cannot be undone.
@@ -8072,8 +8192,8 @@ Use --force to confirm: mutagent helix rm ${id} --force`);
8072
8192
  function registerTracesCommand(parent) {
8073
8193
  parent.command("traces").description("Show the spans captured for a sandbox").argument("<id>", "Sandbox ID").addHelpText("after", `
8074
8194
  Examples:
8075
- ${chalk26.dim("$")} mutagent helix traces sbx_123
8076
- ${chalk26.dim("$")} mutagent helix traces sbx_123 --json
8195
+ ${chalk27.dim("$")} mutagent helix traces sbx_123
8196
+ ${chalk27.dim("$")} mutagent helix traces sbx_123 --json
8077
8197
 
8078
8198
  Spans are what the session actually did — the record to read when the output
8079
8199
  alone does not explain the result. They are called spans, not traces, because
@@ -8097,7 +8217,7 @@ AI Agent Directive:
8097
8217
  return;
8098
8218
  }
8099
8219
  if (spans.length === 0) {
8100
- console.log(chalk26.gray(`No spans captured for sandbox ${id}.`));
8220
+ console.log(chalk27.gray(`No spans captured for sandbox ${id}.`));
8101
8221
  return;
8102
8222
  }
8103
8223
  output.output(spans.map((span) => {
@@ -8119,43 +8239,49 @@ AI Agent Directive:
8119
8239
  function createHelixCommand() {
8120
8240
  const helix = new Command14("helix").description("Run Helix sessions in a cloud sandbox").addHelpText("after", `
8121
8241
  Examples:
8122
- ${chalk27.dim("$")} mutagent helix run "fix the failing test" --prompt "$(cat agent.md)"
8123
- ${chalk27.dim("$")} mutagent helix exec -- uname -m ${chalk27.dim("One command, fresh box")}
8124
- ${chalk27.dim("$")} mutagent helix presets ${chalk27.dim("What a one-shot can run on")}
8125
- ${chalk27.dim("$")} mutagent helix spawn --image alpine:3.20 ${chalk27.dim("Persistent box, then attach")}
8126
- ${chalk27.dim("$")} mutagent helix session start sbx_1 --rpc ${chalk27.dim("Start an agent inside that box")}
8127
- ${chalk27.dim("$")} mutagent helix ls ${chalk27.dim("What is running")}
8128
- ${chalk27.dim("$")} mutagent helix exec --sandbox sbx_1 -- bun test ${chalk27.dim("Command in that box")}
8129
- ${chalk27.dim("$")} mutagent helix attach sbx_1 --since 412 ${chalk27.dim("Resume after a sequence number")}
8130
- ${chalk27.dim("$")} mutagent helix send sbx_1 --session s1 "and now" ${chalk27.dim("Talk to a running session")}
8131
- ${chalk27.dim("$")} mutagent helix traces sbx_1 --json ${chalk27.dim("What the session actually did")}
8132
- ${chalk27.dim("$")} mutagent helix rm sbx_1 --force ${chalk27.dim("Destroy it")}
8242
+ ${chalk28.dim("$")} mutagent helix run "fix the failing test" --prompt "$(cat agent.md)"
8243
+ ${chalk28.dim("$")} mutagent helix exec -- uname -m ${chalk28.dim("One command, fresh box")}
8244
+ ${chalk28.dim("$")} mutagent helix presets ${chalk28.dim("What a one-shot can run on")}
8245
+ ${chalk28.dim("$")} mutagent helix spawn --image alpine:3.20 ${chalk28.dim("Persistent box, then attach")}
8246
+ ${chalk28.dim("$")} mutagent helix session start sbx_1 --rpc ${chalk28.dim("Start an agent inside that box")}
8247
+ ${chalk28.dim("$")} mutagent helix ls ${chalk28.dim("What is running")}
8248
+ ${chalk28.dim("$")} mutagent helix exec --sandbox sbx_1 -- bun test ${chalk28.dim("Command in that box")}
8249
+ ${chalk28.dim("$")} mutagent helix attach sbx_1 --since 412 ${chalk28.dim("Resume after a sequence number")}
8250
+ ${chalk28.dim("$")} mutagent helix send sbx_1 --session s1 "and now" ${chalk28.dim("Talk to a running session")}
8251
+ ${chalk28.dim("$")} mutagent helix signal sbx_1 --session s1 ${chalk28.dim("Stop the agent, keep the box")}
8252
+ ${chalk28.dim("$")} mutagent helix traces sbx_1 --json ${chalk28.dim("What the session actually did")}
8253
+ ${chalk28.dim("$")} mutagent helix rm sbx_1 --force ${chalk28.dim("Destroy it")}
8133
8254
 
8134
8255
  Subcommands:
8135
- run, exec, spawn, session, ls, presets, attach, send, traces, rm
8256
+ run (alias: agent), exec, spawn, session, ls, presets, attach, send, signal,
8257
+ traces, rm
8136
8258
 
8137
8259
  One-shot vs persistent:
8138
- ${chalk27.bold("run")} and ${chalk27.bold("exec")} (without --sandbox) start from a named PRESET, do one
8260
+ ${chalk28.bold("run")} and ${chalk28.bold("exec")} (without --sandbox) start from a named PRESET, do one
8139
8261
  thing and tear the sandbox down. Nothing to clean up, no image to know.
8140
- ${chalk27.bold("spawn")} takes an explicit --image and leaves a box running for you to
8141
- ${chalk27.bold("attach")} and ${chalk27.bold("exec --sandbox")} against until you ${chalk27.bold("rm")} it.
8262
+ ${chalk28.bold("spawn")} takes an explicit --image and leaves a box running for you to
8263
+ ${chalk28.bold("attach")} and ${chalk28.bold("exec --sandbox")} against until you ${chalk28.bold("rm")} it.
8142
8264
 
8143
8265
  Boxes vs sessions vs watching vs steering:
8144
- ${chalk27.bold("spawn")} gives you a BOX. ${chalk27.bold("session start")} gives you an AGENT inside that box.
8145
- ${chalk27.bold("attach")} WATCHES that agent; it does not type into one. ${chalk27.bold("send")} TYPES INTO it,
8266
+ ${chalk28.bold("spawn")} gives you a BOX. ${chalk28.bold("session start")} gives you an AGENT inside that box.
8267
+ ${chalk28.bold("attach")} WATCHES that agent; it does not type into one. ${chalk28.bold("send")} TYPES INTO it,
8146
8268
  from any terminal holding the id — so a session can be redirected without the
8147
8269
  terminal that started it. A box with no session is normal: that is what
8148
- ${chalk27.bold("exec")} runs against.
8270
+ ${chalk28.bold("exec")} runs against.
8271
+ ${chalk28.bold("signal")} STOPS that agent and leaves the box standing — the remote Ctrl-C.
8272
+ Only ${chalk28.bold("rm")} destroys a sandbox.
8149
8273
 
8150
8274
  Lifecycle:
8151
8275
  A spawned sandbox outlives your terminal. Ctrl-C, a dropped connection and a
8152
8276
  closed terminal all DETACH — the session keeps running and can be re-attached.
8277
+ Stopping the AGENT is a different thing from destroying the BOX: 'signal' does
8278
+ the first, 'rm' does the second.
8153
8279
  Only 'mutagent helix rm <id>' destroys a sandbox, so remember to run it when
8154
8280
  you are finished.
8155
8281
 
8156
8282
  Access:
8157
8283
  Sandbox access is minted per WORKSPACE, so a workspace must be configured:
8158
- ${chalk27.dim("$")} mutagent config set workspace <workspace-id>
8284
+ ${chalk28.dim("$")} mutagent config set workspace <workspace-id>
8159
8285
 
8160
8286
  Output:
8161
8287
  Sandbox stdout goes to stdout, sandbox stderr goes to stderr, and anything
@@ -8175,6 +8301,9 @@ AI Agent Directive:
8175
8301
  single JSON document until it ends. Everything else returns one JSON object.
8176
8302
  'run' is always blocking: it takes TWO strings, --prompt (WHO the agent is)
8177
8303
  and the task (WHAT to do). Never fold one into the other.
8304
+ 'run' and 'agent' are the same command; 'run' is the canonical name.
8305
+ To stop a running agent, prefer 'send --type abort' (asks it to stop), then
8306
+ 'signal' (does not ask). Neither destroys the sandbox — only 'rm' does.
8178
8307
  Spawning consumes resources until removed — confirm with the user before
8179
8308
  'spawn' and before 'rm'.
8180
8309
  `);
@@ -8185,6 +8314,7 @@ AI Agent Directive:
8185
8314
  registerPresetsCommand(helix);
8186
8315
  registerAttachCommand(helix);
8187
8316
  registerSendCommand(helix);
8317
+ registerSignalCommand(helix);
8188
8318
  registerSessionCommand(helix);
8189
8319
  registerTracesCommand(helix);
8190
8320
  registerRmCommand(helix);
@@ -8309,61 +8439,61 @@ program.name("mutagent").description(`Mutagent CLI - command-line client for the
8309
8439
  });
8310
8440
  program.addHelpText("beforeAll", () => renderBanner());
8311
8441
  program.addHelpText("after", `
8312
- ${chalk28.bold.cyan("WORKFLOWS:")}
8313
- ${chalk28.bold("Setup")} mutagent login → mutagent init
8314
- ${chalk28.bold("Lifecycle Tools")} mutagent install helix ${chalk28.dim("(login-gated)")}
8315
- ${chalk28.bold("Feedback")} mutagent feedback send "<what happened>" --category <cli|helix|stage:<x>> ${chalk28.dim("[--session <id>] [--attach-transcript]")}
8442
+ ${chalk29.bold.cyan("WORKFLOWS:")}
8443
+ ${chalk29.bold("Setup")} mutagent login → mutagent init
8444
+ ${chalk29.bold("Lifecycle Tools")} mutagent install helix ${chalk29.dim("(login-gated)")}
8445
+ ${chalk29.bold("Feedback")} mutagent feedback send "<what happened>" --category <cli|helix|stage:<x>> ${chalk29.dim("[--session <id>] [--attach-transcript]")}
8316
8446
 
8317
- ${chalk28.dim("For CLI usage guidance for AI agents, see the Skill at")}
8318
- ${chalk28.cyan(".claude/skills/mutagent-cli/SKILL.md")}
8447
+ ${chalk29.dim("For CLI usage guidance for AI agents, see the Skill at")}
8448
+ ${chalk29.cyan(".claude/skills/mutagent-cli/SKILL.md")}
8319
8449
 
8320
- ${chalk28.yellow("Global flags:")}
8321
- -v, --version ${chalk28.dim("Print the CLI version")} ${chalk28.dim("(before a subcommand; after one it is the subcommand's)")}
8450
+ ${chalk29.yellow("Global flags:")}
8451
+ -v, --version ${chalk29.dim("Print the CLI version")} ${chalk29.dim("(before a subcommand; after one it is the subcommand's)")}
8322
8452
  --json --api-key <k> --endpoint <url> --non-interactive
8323
8453
 
8324
- ${chalk28.yellow("Non-Interactive Mode (CI/CD & Coding Agents):")}
8325
- export MUTAGENT_API_KEY=mt_... ${chalk28.dim("or")} --api-key mt_...
8326
- --json ${chalk28.dim("for structured output")} --non-interactive ${chalk28.dim("to disable prompts")}
8454
+ ${chalk29.yellow("Non-Interactive Mode (CI/CD & Coding Agents):")}
8455
+ export MUTAGENT_API_KEY=mt_... ${chalk29.dim("or")} --api-key mt_...
8456
+ --json ${chalk29.dim("for structured output")} --non-interactive ${chalk29.dim("to disable prompts")}
8327
8457
 
8328
- ${chalk28.yellow("Command Navigation:")}
8329
- mutagent login ${chalk28.dim("Login (browser OAuth — recommended)")}
8330
- mutagent auth status ${chalk28.dim("Check auth + workspace")}
8331
- mutagent init ${chalk28.dim("Initialize project (.mutagentrc.json)")}
8332
- mutagent workspaces list --json ${chalk28.dim("List workspaces (verify ID)")}
8333
- mutagent config set workspace <id> ${chalk28.dim("Set active workspace")}
8334
- mutagent usage --json ${chalk28.dim("Show account usage + provider status")}
8458
+ ${chalk29.yellow("Command Navigation:")}
8459
+ mutagent login ${chalk29.dim("Login (browser OAuth — recommended)")}
8460
+ mutagent auth status ${chalk29.dim("Check auth + workspace")}
8461
+ mutagent init ${chalk29.dim("Initialize project (.mutagentrc.json)")}
8462
+ mutagent workspaces list --json ${chalk29.dim("List workspaces (verify ID)")}
8463
+ mutagent config set workspace <id> ${chalk29.dim("Set active workspace")}
8464
+ mutagent usage --json ${chalk29.dim("Show account usage + provider status")}
8335
8465
 
8336
- mutagent providers list --json ${chalk28.dim("List configured BYOK providers")}
8337
- mutagent providers list --models ${chalk28.dim("See available models per provider")}
8466
+ mutagent providers list --json ${chalk29.dim("List configured BYOK providers")}
8467
+ mutagent providers list --models ${chalk29.dim("See available models per provider")}
8338
8468
 
8339
- mutagent helix run "<task>" --prompt "<who>" ${chalk28.dim("One Helix agent turn in a cloud sandbox")}
8340
- mutagent helix ls --json ${chalk28.dim("List running sandboxes")}
8341
- mutagent helix spawn --image <ref> ${chalk28.dim("Persistent sandbox you attach to")}
8342
- mutagent helix rm <id> --force ${chalk28.dim("Destroy a sandbox (the only thing that does)")}
8469
+ mutagent helix run "<task>" --prompt "<who>" ${chalk29.dim("One Helix agent turn in a cloud sandbox")}
8470
+ mutagent helix ls --json ${chalk29.dim("List running sandboxes")}
8471
+ mutagent helix spawn --image <ref> ${chalk29.dim("Persistent sandbox you attach to")}
8472
+ mutagent helix rm <id> --force ${chalk29.dim("Destroy a sandbox (the only thing that does)")}
8343
8473
 
8344
- mutagent install helix ${chalk28.dim("Install the ADL lifecycle conductor locally (login-gated)")}
8345
- mutagent install helix --version 1.2.3 ${chalk28.dim("Pin a version")}
8346
- mutagent install --help ${chalk28.dim("helix")}
8474
+ mutagent install helix ${chalk29.dim("Install the ADL lifecycle conductor locally (login-gated)")}
8475
+ mutagent install helix --version 1.2.3 ${chalk29.dim("Pin a version")}
8476
+ mutagent install --help ${chalk29.dim("helix")}
8347
8477
 
8348
- mutagent hooks --help ${chalk28.dim("Hook setup for Claude Code session telemetry upload")}
8478
+ mutagent hooks --help ${chalk29.dim("Hook setup for Claude Code session telemetry upload")}
8349
8479
 
8350
- ${chalk28.bold.red("Report Issues:")}
8351
- Hit a bug? Run: ${chalk28.cyan('mutagent feedback send "describe what went wrong" --category cli')}
8352
- Lifecycle-stage feedback: ${chalk28.cyan('mutagent feedback send "eval gate unclear" --category stage:evaluate')}
8353
- Link to a session: ${chalk28.cyan('mutagent feedback send "..." --session <session-id>')}
8354
- Attach your coding-agent session transcript: ${chalk28.cyan('mutagent feedback send "..." --attach-transcript')}
8355
- ${chalk28.dim("--category accepts: cli | helix | stage:<spec|build|evaluate|diagnose|optimize>")}
8480
+ ${chalk29.bold.red("Report Issues:")}
8481
+ Hit a bug? Run: ${chalk29.cyan('mutagent feedback send "describe what went wrong" --category cli')}
8482
+ Lifecycle-stage feedback: ${chalk29.cyan('mutagent feedback send "eval gate unclear" --category stage:evaluate')}
8483
+ Link to a session: ${chalk29.cyan('mutagent feedback send "..." --session <session-id>')}
8484
+ Attach your coding-agent session transcript: ${chalk29.cyan('mutagent feedback send "..." --attach-transcript')}
8485
+ ${chalk29.dim("--category accepts: cli | helix | stage:<spec|build|evaluate|diagnose|optimize>")}
8356
8486
 
8357
- ${chalk28.yellow("Directive System:")}
8487
+ ${chalk29.yellow("Directive System:")}
8358
8488
  Every --json response may include:
8359
- ${chalk28.bold("_directive.display")} Type tag — 'status_card' for card-kind directives (drives test/docs guards)
8360
- ${chalk28.bold("_directive.renderedCard")} Pre-formatted card ${chalk28.red("(MUST echo verbatim in chat whenever this field exists — see SKILL.md Verbatim Card Display Protocol)")}
8361
- ${chalk28.bold("_directive.instruction")} Next step for the agent (self-sufficient, no Skill required)
8362
- ${chalk28.bold("_directive.next")} Array of suggested follow-up commands
8363
- ${chalk28.bold("_links")} Dashboard/API URLs (format as markdown links)
8364
- ${chalk28.bold("_compat")} Compat metadata: cliVersion, skillVersion, skillMinCliVersion
8365
-
8366
- ${chalk28.yellow("AI Agent Rules (MANDATORY for coding agents):")}
8489
+ ${chalk29.bold("_directive.display")} Type tag — 'status_card' for card-kind directives (drives test/docs guards)
8490
+ ${chalk29.bold("_directive.renderedCard")} Pre-formatted card ${chalk29.red("(MUST echo verbatim in chat whenever this field exists — see SKILL.md Verbatim Card Display Protocol)")}
8491
+ ${chalk29.bold("_directive.instruction")} Next step for the agent (self-sufficient, no Skill required)
8492
+ ${chalk29.bold("_directive.next")} Array of suggested follow-up commands
8493
+ ${chalk29.bold("_links")} Dashboard/API URLs (format as markdown links)
8494
+ ${chalk29.bold("_compat")} Compat metadata: cliVersion, skillVersion, skillMinCliVersion
8495
+
8496
+ ${chalk29.yellow("AI Agent Rules (MANDATORY for coding agents):")}
8367
8497
  1. Login (two paths):
8368
8498
  - CI / fully automated: export MUTAGENT_API_KEY=mt_... then mutagent login --json
8369
8499
  - Helping a user onboard: mutagent login --browser --json
@@ -8373,13 +8503,13 @@ ${chalk28.yellow("AI Agent Rules (MANDATORY for coding agents):")}
8373
8503
  2. EVERY command MUST include --json (no exceptions)
8374
8504
  3. Run <command> --help BEFORE first use of any command
8375
8505
  4. Parse _directive.renderedCard and copy it into your CHAT RESPONSE verbatim
8376
- ${chalk28.red("HARD STOP")}: do NOT run further commands until the card is rendered in chat
8506
+ ${chalk29.red("HARD STOP")}: do NOT run further commands until the card is rendered in chat
8377
8507
  5. After mutagent init, verify workspace: mutagent workspaces list --json
8378
8508
  6. ALL user interaction via AskUserQuestion — CLI is non-interactive
8379
8509
  ${!hasCredentials() ? `
8380
- ` + chalk28.yellow(" Warning: Not authenticated. Run: mutagent login") + `
8510
+ ` + chalk29.yellow(" Warning: Not authenticated. Run: mutagent login") + `
8381
8511
  ` : ""}${!hasRcConfig() ? `
8382
- ` + chalk28.green(" Get started: mutagent init") + `
8512
+ ` + chalk29.green(" Get started: mutagent init") + `
8383
8513
  ` : ""}`);
8384
8514
  var rawArgs = process.argv.slice(2);
8385
8515
  if (isGlobalVersionFlag(rawArgs)) {
@@ -8420,5 +8550,5 @@ program.addCommand(createFeedbackCommand());
8420
8550
  program.addCommand(createTraceCommand());
8421
8551
  program.parse();
8422
8552
 
8423
- //# debugId=9CA63CD3787CB08B64756E2164756E21
8553
+ //# debugId=B28A5231DE264E0C64756E2164756E21
8424
8554
  //# sourceMappingURL=cli.js.map