@mnemom/mnemom 0.17.0-next.6 → 0.17.0-next.7

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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * `mnemom code <scenario>` — the CLI's first-class governed-coding-agent launcher.
2
+ * `mnemom agent <scenario>` — the CLI's first-class governed-coding-agent launcher.
3
3
  *
4
4
  * Launches your coding-agent CLI (Claude Code in v1) with its dev-time model
5
5
  * traffic routed through the Mnemom gateway's /anthropic door for observability +
@@ -11,7 +11,7 @@
11
11
  * no router door / Mnemom key). `--cli` selects the executable to run (name or
12
12
  * full path) so codex/cursor/github adapters can be added later.
13
13
  * - The us-2/PROD gateway is the DEFAULT door (https://gateway.mnemom.ai); an
14
- * explicit MNEMOM_CODE_GATEWAY / --gateway still wins, never silently prod.
14
+ * explicit MNEMOM_AGENT_GATEWAY / --gateway still wins, never silently prod.
15
15
  * - Three launch shapes: `terminal` (DEFAULT), `remote-control` (interactive RC
16
16
  * in this terminal), `server` (headless RC dispatcher). RC runs the CLI
17
17
  * UNTOUCHED behind a bundled local TLS proxy (rc-proxy.mjs) — Claude Code
@@ -20,7 +20,7 @@
20
20
  * - yolo (`--dangerously-skip-permissions`) is ON by default; `--no-yolo` opts out.
21
21
  *
22
22
  * The Anthropic key is resolved from a credential source with ZERO 1Password
23
- * dependency (env → the CLI's own ~/.mnemom/code.json store → interactive
23
+ * dependency (env → the CLI's own ~/.mnemom/launcher.json store → interactive
24
24
  * prompt) and placed ONLY in the launched process (an `ANTHROPIC_CUSTOM_HEADERS`
25
25
  * line, or the proxy's stdin under RC). It is never logged, printed, or passed as
26
26
  * an argv value.
@@ -31,31 +31,31 @@ import { tmpdir, homedir } from "node:os";
31
31
  import { basename, join, dirname } from "node:path";
32
32
  import { fileURLToPath } from "node:url";
33
33
  import { MNEMOM_DIR } from "../lib/config.js";
34
- import { configKeySpec, loadCodeConfig, writeCodeConfig } from "../lib/code-config.js";
34
+ import { configKeySpec, loadLauncherConfig, writeLauncherConfig } from "../lib/launcher-config.js";
35
35
  import { fmt } from "../lib/format.js";
36
36
  import { askInput, askYesNo, isInteractive } from "../lib/prompt.js";
37
- import { goalAlignmentLine, resolveSessionSetup } from "./code-session.js";
38
- import { defaultAgentSlug, ensureGovernedAgent, ensureSessionAndBalance, isQuietPreambleExit, resolveDefaultSlug, } from "./code-setup.js";
39
- import { assembleContract, buildCustomHeaders, isProdGateway, launchPreferenceExplicit, resolveAnthropicDoor, resolveConversationId, resolveGatewayHost, resolveLaunchShape, sanitizeAgentName, } from "../lib/code.js";
40
- /** The CLI's own provider-key store (zero 1Password): ~/.mnemom/code.json, 0600. */
41
- const CODE_STORE = join(MNEMOM_DIR, "code.json");
37
+ import { goalAlignmentLine, resolveSessionSetup } from "./agent-session.js";
38
+ import { defaultAgentSlug, ensureGovernedAgent, ensureSessionAndBalance, isQuietPreambleExit, resolveDefaultSlug, } from "./agent-setup.js";
39
+ import { assembleContract, buildCustomHeaders, isProdGateway, launchPreferenceExplicit, resolveAnthropicDoor, resolveConversationId, resolveGatewayHost, resolveLaunchShape, sanitizeAgentName, } from "../lib/agent.js";
40
+ /** The CLI's own provider-key store (zero 1Password): ~/.mnemom/launcher.json, 0600. */
41
+ const CODE_STORE = join(MNEMOM_DIR, "launcher.json");
42
42
  const say = (line = "") => console.error(line);
43
- /** Entry point for `mnemom code [scenario]`. Throws on fatal misconfig. */
44
- export async function codeCommand(scenarioArg, options = {}) {
45
- // ── session name + goal ── (a bare `mnemom code` in a terminal asks for both,
43
+ /** Entry point for `mnemom agent [scenario]`. Throws on fatal misconfig. */
44
+ export async function agentCommand(scenarioArg, options = {}) {
45
+ // ── session name + goal ── (a bare `mnemom agent` in a terminal asks for both,
46
46
  // explaining goal alignment; no goal ⇒ no contract header ⇒ goal alignment off)
47
47
  const session = await resolveSessionSetup({ scenario: scenarioArg, goal: options.goal, interactive: isInteractive() }, { askInput: (q) => askInput(q), askYesNo: (q, d) => askYesNo(q, d) });
48
48
  const scenario = session.scenario;
49
49
  const env = process.env;
50
50
  let shape = resolveLaunchShape({ remoteControl: options.remoteControl, server: options.server }, env);
51
51
  const shapeExplicit = launchPreferenceExplicit({ remoteControl: options.remoteControl, server: options.server }, env);
52
- // ── governed identity ── (default: per-customer `code-<handle>`, not a shared
52
+ // ── governed identity ── (default: per-customer `agent-<handle>`, not a shared
53
53
  // "code-agent" — see defaultAgentSlug; provisioning claims exactly this slug.
54
54
  // `let` because a brand-new user who signs in during the pre-launch gate below
55
55
  // gets their real handle re-derived once the session exists.)
56
56
  let agent = sanitizeAgentName(options.agent?.trim() || defaultAgentSlug());
57
57
  if (!agent) {
58
- throw new Error("mnemom code: --agent sanitised to an empty string — pick a value with at least one letter or digit.");
58
+ throw new Error("mnemom agent: --agent sanitised to an empty string — pick a value with at least one letter or digit.");
59
59
  }
60
60
  const conversationId = resolveConversationId(options.conversationId);
61
61
  // ── contract (built only if a contract flag was given; --goal then required) ──
@@ -98,16 +98,16 @@ export async function codeCommand(scenarioArg, options = {}) {
98
98
  shape = "remote-control";
99
99
  }
100
100
  else {
101
- say(`mnemom code: launching terminal-only (Remote Control unavailable: ${rc.missing.join("; ")}).`);
102
- say("mnemom code: once those are in place, `mnemom code <scenario> --remote-control` (or `config set launch remote-control`) gives you a session steerable from claude.ai and the Claude app too.");
101
+ say(`mnemom agent: launching terminal-only (Remote Control unavailable: ${rc.missing.join("; ")}).`);
102
+ say("mnemom agent: once those are in place, `mnemom agent <scenario> --remote-control` (or `config set launch remote-control`) gives you a session steerable from claude.ai and the Claude app too.");
103
103
  }
104
104
  };
105
105
  if (cli)
106
106
  applyAutoShape(cli);
107
107
  if (options.dryRun) {
108
108
  const planCli = cli ?? {
109
- bin: "(not found — pass --cli <path> or `mnemom code config set cli <path>`)",
110
- name: basename((options.cli || env.MNEMOM_CODE_CLI || "claude").trim()),
109
+ bin: "(not found — pass --cli <path> or `mnemom agent config set cli <path>`)",
110
+ name: basename((options.cli || env.MNEMOM_AGENT_CLI || "claude").trim()),
111
111
  };
112
112
  printPlan({
113
113
  scenario,
@@ -135,7 +135,7 @@ export async function codeCommand(scenarioArg, options = {}) {
135
135
  keySource: options.keySource,
136
136
  });
137
137
  // ── account + µ-balance gate (no free tier) ─────────────────────────────────
138
- // mnemom code runs governed and on µ, so before we seal a contract or launch we
138
+ // mnemom agent runs governed and on µ, so before we seal a contract or launch we
139
139
  // (1) ensure a Mnemom session — offering the try-me-style sign-in / sign-up when
140
140
  // there isn't one — and (2) enforce a positive µ balance on the org the agent
141
141
  // lives in (default: the user's personal org). No µ ⇒ blocked with a
@@ -150,7 +150,7 @@ export async function codeCommand(scenarioArg, options = {}) {
150
150
  }
151
151
  // Now that a session exists, a defaulted slug uses the real login handle from
152
152
  // /v1/auth/me (the stored token has no email, so the pre-sign-in value was the
153
- // "code-user" fallback). Only when the caller didn't name an agent.
153
+ // "agent-user" fallback). Only when the caller didn't name an agent.
154
154
  if (!options.agent?.trim()) {
155
155
  const refreshed = sanitizeAgentName(await resolveDefaultSlug());
156
156
  if (refreshed)
@@ -172,7 +172,7 @@ export async function codeCommand(scenarioArg, options = {}) {
172
172
  }
173
173
  catch (err) {
174
174
  const msg = err instanceof Error ? err.message : String(err);
175
- say(fmt.warn(`mnemom code: agent setup did not complete (${msg}) — launching with the unclaimed identity.`));
175
+ say(fmt.warn(`mnemom agent: agent setup did not complete (${msg}) — launching with the unclaimed identity.`));
176
176
  }
177
177
  }
178
178
  logLaunch({ shape, door, agent, conversationId, cellNote, envelope, cli });
@@ -210,8 +210,8 @@ export async function codeCommand(scenarioArg, options = {}) {
210
210
  /**
211
211
  * Resolve the Anthropic key with NO 1Password dependency (built for external
212
212
  * customer adoption), in order:
213
- * 1. env: MNEMOM_CODE_ANTHROPIC_KEY, else ANTHROPIC_API_KEY
214
- * 2. the CLI's own store: ~/.mnemom/code.json (`anthropic_key`)
213
+ * 1. env: MNEMOM_AGENT_ANTHROPIC_KEY, else ANTHROPIC_API_KEY
214
+ * 2. the CLI's own store: ~/.mnemom/launcher.json (`anthropic_key`)
215
215
  * 3. interactive prompt (masked), offering to save it to the store
216
216
  * Never logged / printed. Throws with guidance when nothing resolves — we refuse
217
217
  * to launch un-routed.
@@ -220,13 +220,13 @@ export async function resolveAnthropicKey(env, opts) {
220
220
  const source = opts.keySource;
221
221
  // "prompt" forces the interactive prompt (skips env + store).
222
222
  if (source !== "prompt") {
223
- const fromEnv = (env.MNEMOM_CODE_ANTHROPIC_KEY || env.ANTHROPIC_API_KEY || "").trim();
223
+ const fromEnv = (env.MNEMOM_AGENT_ANTHROPIC_KEY || env.ANTHROPIC_API_KEY || "").trim();
224
224
  if (fromEnv)
225
225
  return fromEnv;
226
226
  // "env" restricts to env only — no store, no prompt.
227
227
  if (source === "env") {
228
- throw new Error("mnemom code: key_source is 'env' but no Anthropic key is set.\n" +
229
- " Set one: export MNEMOM_CODE_ANTHROPIC_KEY=sk-ant-... (or ANTHROPIC_API_KEY)");
228
+ throw new Error("mnemom agent: key_source is 'env' but no Anthropic key is set.\n" +
229
+ " Set one: export MNEMOM_AGENT_ANTHROPIC_KEY=sk-ant-... (or ANTHROPIC_API_KEY)");
230
230
  }
231
231
  const stored = readStoredKey();
232
232
  if (stored)
@@ -234,28 +234,28 @@ export async function resolveAnthropicKey(env, opts) {
234
234
  }
235
235
  // (source can only be "store", "prompt", or undefined here — "env" threw above.)
236
236
  if (opts.allowPrompt && isInteractive()) {
237
- say("mnemom code: no Anthropic key in env (MNEMOM_CODE_ANTHROPIC_KEY / ANTHROPIC_API_KEY) or ~/.mnemom/code.json.");
237
+ say("mnemom agent: no Anthropic key in env (MNEMOM_AGENT_ANTHROPIC_KEY / ANTHROPIC_API_KEY) or ~/.mnemom/launcher.json.");
238
238
  const entered = (await askInput("Enter your Anthropic API key (sk-ant-…):", true)).trim();
239
239
  if (entered) {
240
- if (await askYesNo("Save it to ~/.mnemom/code.json (0600) for next time?", true)) {
240
+ if (await askYesNo("Save it to ~/.mnemom/launcher.json (0600) for next time?", true)) {
241
241
  storeKey(entered);
242
- say("mnemom code: saved to ~/.mnemom/code.json.");
242
+ say("mnemom agent: saved to ~/.mnemom/launcher.json.");
243
243
  }
244
244
  return entered;
245
245
  }
246
246
  }
247
- throw new Error("mnemom code: no Anthropic key found — refusing to launch un-routed.\n" +
248
- " Set one: export MNEMOM_CODE_ANTHROPIC_KEY=sk-ant-... (or ANTHROPIC_API_KEY)\n" +
249
- " Or save it: run `mnemom code` interactively and accept the save prompt\n" +
250
- " (stored 0600 at ~/.mnemom/code.json).");
247
+ throw new Error("mnemom agent: no Anthropic key found — refusing to launch un-routed.\n" +
248
+ " Set one: export MNEMOM_AGENT_ANTHROPIC_KEY=sk-ant-... (or ANTHROPIC_API_KEY)\n" +
249
+ " Or save it: run `mnemom agent` interactively and accept the save prompt\n" +
250
+ " (stored 0600 at ~/.mnemom/launcher.json).");
251
251
  }
252
252
  /**
253
253
  * Where an Anthropic key would resolve from RIGHT NOW, without reading its value:
254
- * "env" (MNEMOM_CODE_ANTHROPIC_KEY / ANTHROPIC_API_KEY), "store" (~/.mnemom/code.json),
255
- * or null (would fall to the interactive prompt). For `mnemom code doctor`.
254
+ * "env" (MNEMOM_AGENT_ANTHROPIC_KEY / ANTHROPIC_API_KEY), "store" (~/.mnemom/launcher.json),
255
+ * or null (would fall to the interactive prompt). For `mnemom agent doctor`.
256
256
  */
257
257
  export function anthropicKeySource(env = process.env) {
258
- if ((env.MNEMOM_CODE_ANTHROPIC_KEY || env.ANTHROPIC_API_KEY || "").trim())
258
+ if ((env.MNEMOM_AGENT_ANTHROPIC_KEY || env.ANTHROPIC_API_KEY || "").trim())
259
259
  return "env";
260
260
  if (readStoredKey())
261
261
  return "store";
@@ -272,7 +272,7 @@ function readStoredKey() {
272
272
  return undefined;
273
273
  }
274
274
  }
275
- /** Persist the provider key to ~/.mnemom/code.json at 0600 (atomic). Best-effort. */
275
+ /** Persist the provider key to ~/.mnemom/launcher.json at 0600 (atomic). Best-effort. */
276
276
  function storeKey(key) {
277
277
  try {
278
278
  mkdirSync(MNEMOM_DIR, { recursive: true });
@@ -285,7 +285,7 @@ function storeKey(key) {
285
285
  }
286
286
  }
287
287
  /**
288
- * Resolve which coding-agent CLI to launch. `--cli` (or MNEMOM_CODE_CLI) is a
288
+ * Resolve which coding-agent CLI to launch. `--cli` (or MNEMOM_AGENT_CLI) is a
289
289
  * name or a full path; default "claude". A value with a path separator is used
290
290
  * verbatim (must exist); a bare name is resolved on PATH, then — for claude — the
291
291
  * fnm/nvm/asdf install dirs (a version-manager shim / shell function is absent in
@@ -293,12 +293,12 @@ function storeKey(key) {
293
293
  * a non-claude executable is launched through it with a warning.
294
294
  */
295
295
  export function resolveCliBin(cliOpt, env) {
296
- const requested = (cliOpt || env.MNEMOM_CODE_CLI || "claude").trim();
296
+ const requested = (cliOpt || env.MNEMOM_AGENT_CLI || "claude").trim();
297
297
  const name = basename(requested);
298
298
  if (requested.includes("/")) {
299
299
  if (existsSync(requested))
300
300
  return { bin: requested, name };
301
- throw new Error(`mnemom code: --cli path '${requested}' not found.`);
301
+ throw new Error(`mnemom agent: --cli path '${requested}' not found.`);
302
302
  }
303
303
  for (const dir of (env.PATH || "").split(":")) {
304
304
  // Skip ephemeral cmux CLI shims: they only work inside a cmux session and,
@@ -334,10 +334,10 @@ export function resolveCliBin(cliOpt, env) {
334
334
  }
335
335
  }
336
336
  }
337
- throw new Error(`mnemom code: coding-agent CLI '${requested}' not found.\n` +
337
+ throw new Error(`mnemom agent: coding-agent CLI '${requested}' not found.\n` +
338
338
  " Looked on $PATH" +
339
339
  (name === "claude" ? " and in the fnm/nvm/asdf node dirs" : "") +
340
- ".\n Pass --cli <name|/full/path> or set MNEMOM_CODE_CLI.");
340
+ ".\n Pass --cli <name|/full/path> or set MNEMOM_AGENT_CLI.");
341
341
  }
342
342
  export /**
343
343
  * Recover when the coding-agent CLI can't be found — a good experience beats a
@@ -346,11 +346,11 @@ export /**
346
346
  * so they never retype it). A non-interactive session re-throws the clear,
347
347
  * actionable error rather than hanging on a prompt.
348
348
  */ async function promptForCliPath(cliOpt, env, origErr) {
349
- const requested = (cliOpt || env.MNEMOM_CODE_CLI || "claude").trim();
349
+ const requested = (cliOpt || env.MNEMOM_AGENT_CLI || "claude").trim();
350
350
  if (!isInteractive()) {
351
- throw origErr ?? new Error(`mnemom code: coding-agent CLI '${requested}' not found.`);
351
+ throw origErr ?? new Error(`mnemom agent: coding-agent CLI '${requested}' not found.`);
352
352
  }
353
- say(`mnemom code: couldn't find the '${requested}' CLI on your PATH.`);
353
+ say(`mnemom agent: couldn't find the '${requested}' CLI on your PATH.`);
354
354
  if (requested === "claude") {
355
355
  say(" If Claude Code is installed, paste its full path (find it with: which claude).");
356
356
  say(" Not installed yet? Get it at https://claude.com/claude-code, then re-run.");
@@ -361,9 +361,9 @@ export /**
361
361
  for (let attempt = 0; attempt < 3; attempt++) {
362
362
  const entered = (await askInput("Path to your coding-agent CLI (Enter to cancel):")).trim();
363
363
  if (!entered) {
364
- throw new Error("mnemom code: no coding-agent CLI available.\n" +
364
+ throw new Error("mnemom agent: no coding-agent CLI available.\n" +
365
365
  " Install Claude Code (https://claude.com/claude-code), or pass --cli <path> " +
366
- "(or save it: mnemom code config set cli <path>).");
366
+ "(or save it: mnemom agent config set cli <path>).");
367
367
  }
368
368
  if (!existsSync(entered)) {
369
369
  say(` '${entered}' doesn't exist — try again.`);
@@ -371,9 +371,9 @@ export /**
371
371
  }
372
372
  if (await askYesNo("Save this as your default CLI so you don't retype it?", true)) {
373
373
  try {
374
- const cfg = loadCodeConfig();
374
+ const cfg = loadLauncherConfig();
375
375
  configKeySpec("cli").set(cfg, entered);
376
- writeCodeConfig(cfg);
376
+ writeLauncherConfig(cfg);
377
377
  say(" Saved — future launches will use it.");
378
378
  }
379
379
  catch {
@@ -382,7 +382,7 @@ export /**
382
382
  }
383
383
  return { bin: entered, name: basename(entered) };
384
384
  }
385
- throw new Error("mnemom code: couldn't resolve a coding-agent CLI path — pass --cli <path>.");
385
+ throw new Error("mnemom agent: couldn't resolve a coding-agent CLI path — pass --cli <path>.");
386
386
  }
387
387
  function commandExists(cmd) {
388
388
  const res = spawnSync("sh", ["-c", `command -v "$1" >/dev/null 2>&1`, "sh", cmd], {
@@ -408,7 +408,7 @@ export function cliSupportsRemoteControl(bin) {
408
408
  /**
409
409
  * Can we launch the DEFAULT Remote-Control-in-terminal shape on this machine?
410
410
  * Needs node + openssl (the local proxy mints an ephemeral CA) and a claude
411
- * adapter that advertises `--remote-control`. Used both by `mnemom code doctor`
411
+ * adapter that advertises `--remote-control`. Used both by `mnemom agent doctor`
412
412
  * and by the auto-default selection (a bare launch prefers RC when capable).
413
413
  */
414
414
  export function checkRcCapability(cli) {
@@ -429,7 +429,7 @@ export function checkRcCapability(cli) {
429
429
  /** Warn once when a non-claude executable rides the v1 Claude Code adapter. */
430
430
  function warnAdapter(cli) {
431
431
  if (cli.name !== "claude") {
432
- say(`mnemom code: only the Claude Code adapter is wired in v1 — launching '${cli.name}' with the Anthropic gateway env. codex/cursor/github adapters are coming.`);
432
+ say(`mnemom agent: only the Claude Code adapter is wired in v1 — launching '${cli.name}' with the Anthropic gateway env. codex/cursor/github adapters are coming.`);
433
433
  }
434
434
  }
435
435
  // ───────────────────────────────────────────────────────────────────────────
@@ -459,7 +459,7 @@ function launchTerminal(ctx) {
459
459
  }
460
460
  const child = spawn(ctx.cli.bin, args, { stdio: "inherit", env: childEnv });
461
461
  child.on("error", (err) => {
462
- say(`mnemom code: failed to launch ${ctx.cli.name}: ${err.message}`);
462
+ say(`mnemom agent: failed to launch ${ctx.cli.name}: ${err.message}`);
463
463
  process.exit(1);
464
464
  });
465
465
  child.on("exit", (code, signal) => {
@@ -476,21 +476,21 @@ function launchRemoteControl(ctx) {
476
476
  warnAdapter(ctx.cli);
477
477
  for (const tool of ["node", "openssl"]) {
478
478
  if (!commandExists(tool)) {
479
- throw new Error(`mnemom code: --remote-control needs '${tool}' on PATH (the local proxy is a Node script that mints an ephemeral CA with openssl).`);
479
+ throw new Error(`mnemom agent: --remote-control needs '${tool}' on PATH (the local proxy is a Node script that mints an ephemeral CA with openssl).`);
480
480
  }
481
481
  }
482
482
  const proxyScript = resolveProxyScript();
483
483
  const rcDir = mkdtempSync(join(tmpdir(), "mnemom-code-rc."));
484
- const proxyLog = process.env.MNEMOM_CODE_RC_PROXY_LOG || join(rcDir, "proxy.log");
484
+ const proxyLog = process.env.MNEMOM_AGENT_RC_PROXY_LOG || join(rcDir, "proxy.log");
485
485
  const proxy = spawn("node", [proxyScript], {
486
486
  env: {
487
487
  ...process.env,
488
- MNEMOM_CODE_RC_DOOR: ctx.door,
489
- MNEMOM_CODE_RC_AGENT: ctx.agent,
490
- MNEMOM_CODE_RC_CONVERSATION_ID: ctx.conversationId,
491
- MNEMOM_CODE_RC_CONTRACT_B64: ctx.envelope?.base64 ?? "",
492
- MNEMOM_CODE_RC_PROXY_LOG: proxyLog,
493
- MNEMOM_CODE_RC_PARENT_PID: String(process.pid),
488
+ MNEMOM_AGENT_RC_DOOR: ctx.door,
489
+ MNEMOM_AGENT_RC_AGENT: ctx.agent,
490
+ MNEMOM_AGENT_RC_CONVERSATION_ID: ctx.conversationId,
491
+ MNEMOM_AGENT_RC_CONTRACT_B64: ctx.envelope?.base64 ?? "",
492
+ MNEMOM_AGENT_RC_PROXY_LOG: proxyLog,
493
+ MNEMOM_AGENT_RC_PARENT_PID: String(process.pid),
494
494
  },
495
495
  stdio: ["pipe", "pipe", "inherit"],
496
496
  });
@@ -526,7 +526,7 @@ function launchRemoteControl(ctx) {
526
526
  const port = m[1];
527
527
  const ca = m[2].trim();
528
528
  if (!existsSync(ca)) {
529
- say("mnemom code: malformed READY line from the Remote Control proxy.");
529
+ say("mnemom agent: malformed READY line from the Remote Control proxy.");
530
530
  onExit();
531
531
  process.exit(1);
532
532
  }
@@ -534,13 +534,13 @@ function launchRemoteControl(ctx) {
534
534
  return;
535
535
  }
536
536
  if (proxy.exitCode !== null) {
537
- say("mnemom code: the Remote Control proxy exited before it was ready — refusing to launch un-routed.");
537
+ say("mnemom agent: the Remote Control proxy exited before it was ready — refusing to launch un-routed.");
538
538
  redactedProxyLog(proxyLog);
539
539
  onExit();
540
540
  process.exit(1);
541
541
  }
542
542
  if (Date.now() - start > 15_000) {
543
- say("mnemom code: the Remote Control proxy did not report READY within 15s.");
543
+ say("mnemom agent: the Remote Control proxy did not report READY within 15s.");
544
544
  onExit();
545
545
  process.exit(1);
546
546
  }
@@ -550,7 +550,7 @@ function launchRemoteControl(ctx) {
550
550
  stdoutBuf += chunk.toString("utf8");
551
551
  });
552
552
  proxy.on("error", (err) => {
553
- say(`mnemom code: failed to launch the Remote Control proxy: ${err.message}`);
553
+ say(`mnemom agent: failed to launch the Remote Control proxy: ${err.message}`);
554
554
  onExit();
555
555
  process.exit(1);
556
556
  });
@@ -602,7 +602,7 @@ function spawnRcCli(ctx) {
602
602
  if (ctx.options.model)
603
603
  childEnv.ANTHROPIC_MODEL = ctx.options.model;
604
604
  args = ["remote-control", "--name", rcName, ...passthrough];
605
- say(`mnemom code: remote-control: headless server (session name '${rcName}'); drive the sessions it spawns from claude.ai/code or the Claude app. Stop this command to stop the server.`);
605
+ say(`mnemom agent: remote-control: headless server (session name '${rcName}'); drive the sessions it spawns from claude.ai/code or the Claude app. Stop this command to stop the server.`);
606
606
  }
607
607
  else {
608
608
  // Interactive RC in THIS terminal: the CLI's own `--remote-control <name>`
@@ -610,11 +610,11 @@ function spawnRcCli(ctx) {
610
610
  // buildCliArgs already includes the (name-stripped) passthrough.
611
611
  const flagArgs = buildCliArgs(scopedOptions, { yolo: ctx.yolo, allowCliFlags: true });
612
612
  args = ["--remote-control", rcName, ...flagArgs];
613
- say(`mnemom code: remote-control: interactive session in THIS terminal with Remote Control on (session name '${rcName}'); it also appears under Remote Control at claude.ai/code and in the Claude app. Exit the CLI to stop everything.`);
613
+ say(`mnemom agent: remote-control: interactive session in THIS terminal with Remote Control on (session name '${rcName}'); it also appears under Remote Control at claude.ai/code and in the Claude app. Exit the CLI to stop everything.`);
614
614
  }
615
615
  const child = spawn(ctx.cli.bin, args, { stdio: "inherit", env: childEnv });
616
616
  child.on("error", (err) => {
617
- say(`mnemom code: failed to launch ${ctx.cli.name} under Remote Control: ${err.message}`);
617
+ say(`mnemom agent: failed to launch ${ctx.cli.name} under Remote Control: ${err.message}`);
618
618
  ctx.onExit();
619
619
  process.exit(1);
620
620
  });
@@ -628,20 +628,20 @@ function spawnRcCli(ctx) {
628
628
  }
629
629
  function warnServerDrops(options, yolo) {
630
630
  if (options.effort) {
631
- say("mnemom code: --effort is not applied under --server (set it from the session instead).");
631
+ say("mnemom agent: --effort is not applied under --server (set it from the session instead).");
632
632
  }
633
633
  if (options.trimMcp) {
634
- say("mnemom code: --trim-mcp is not applied under --server (sessions load the full MCP set).");
634
+ say("mnemom agent: --trim-mcp is not applied under --server (sessions load the full MCP set).");
635
635
  }
636
636
  if (yolo) {
637
- say("mnemom code: yolo (--dangerously-skip-permissions) is not applied under --server; set permissions from the driven sessions.");
637
+ say("mnemom agent: yolo (--dangerously-skip-permissions) is not applied under --server; set permissions from the driven sessions.");
638
638
  }
639
639
  }
640
640
  function resolveProxyScript() {
641
641
  const here = dirname(fileURLToPath(import.meta.url));
642
642
  const cand = join(here, "..", "rc-proxy.mjs");
643
643
  if (!existsSync(cand)) {
644
- throw new Error(`mnemom code: the Remote Control proxy is missing (expected ${cand}). Reinstall the CLI.`);
644
+ throw new Error(`mnemom agent: the Remote Control proxy is missing (expected ${cand}). Reinstall the CLI.`);
645
645
  }
646
646
  return cand;
647
647
  }
@@ -721,15 +721,15 @@ function seedContextHintFlag(childEnv) {
721
721
  // Human-facing logging (never prints the key)
722
722
  // ───────────────────────────────────────────────────────────────────────────
723
723
  function logLaunch(ctx) {
724
- say(`mnemom code: routing ${ctx.cli.name} through ${ctx.door} [${ctx.cellNote}] as '${ctx.agent}' (conversation ${ctx.conversationId}).`);
724
+ say(`mnemom agent: routing ${ctx.cli.name} through ${ctx.door} [${ctx.cellNote}] as '${ctx.agent}' (conversation ${ctx.conversationId}).`);
725
725
  if (ctx.envelope) {
726
- say(`mnemom code: contract statement: ${ctx.envelope.contract.statement}`);
727
- say(`mnemom code: contract sha256[0:16]: ${ctx.envelope.sha}`);
726
+ say(`mnemom agent: contract statement: ${ctx.envelope.contract.statement}`);
727
+ say(`mnemom agent: contract sha256[0:16]: ${ctx.envelope.sha}`);
728
728
  }
729
729
  }
730
730
  function printPlan(ctx) {
731
731
  const L = [];
732
- L.push("mnemom code — launch plan (dry run)");
732
+ L.push("mnemom agent — launch plan (dry run)");
733
733
  L.push(` scenario: ${ctx.scenario}`);
734
734
  L.push(` cli: ${ctx.cli.name} (${ctx.cli.bin})`);
735
735
  L.push(` shape: ${ctx.shape}`);
@@ -26,7 +26,7 @@ export interface AgentsClaimOptions {
26
26
  */
27
27
  export declare function deriveHashProof(apiKey: string, agentName?: string): string;
28
28
  /**
29
- * `mnemom agents claim <id-or-name> [--org <slug>] (--key <k> | --hash-proof <h>)`
29
+ * `mnemom agent claim <id-or-name> [--org <slug>] (--key <k> | --hash-proof <h>)`
30
30
  *
31
31
  * Claims an agent into an org (ADR-062). Possession of the agent's key (via
32
32
  * `--key`, from which the CLI derives the proof) or a pre-computed
@@ -42,7 +42,7 @@ export interface AgentsMoveOptions {
42
42
  json?: boolean;
43
43
  }
44
44
  /**
45
- * `mnemom agents move <id-or-name> --to <slug|id>`
45
+ * `mnemom agent move <id-or-name> --to <slug|id>`
46
46
  *
47
47
  * Role-based relocation between orgs (the counterpart to re-claim, which is
48
48
  * possession-based). The server requires the caller to be an owner/admin of
@@ -121,7 +121,7 @@ function extractClaimableOrgs(details) {
121
121
  return list.filter((o) => !!o && typeof o === "object" && typeof o.org_id === "string");
122
122
  }
123
123
  /**
124
- * `mnemom agents claim <id-or-name> [--org <slug>] (--key <k> | --hash-proof <h>)`
124
+ * `mnemom agent claim <id-or-name> [--org <slug>] (--key <k> | --hash-proof <h>)`
125
125
  *
126
126
  * Claims an agent into an org (ADR-062). Possession of the agent's key (via
127
127
  * `--key`, from which the CLI derives the proof) or a pre-computed
@@ -148,7 +148,7 @@ export async function agentsClaimCommand(idOrName, options = {}) {
148
148
  // The arg names an agent we can't see yet (unclaimed agents aren't in
149
149
  // your fleet), so we have no id to address the claim — guide to the id.
150
150
  console.log(fmt.error(`Could not resolve '${idOrName}' to an agent id you can see yet — unclaimed agents are not in your fleet.`));
151
- console.log(fmt.dim(` Pass the agent id directly: mnemom agents claim mnm-... --key <key> [--name ${idOrName}]`) + "\n");
151
+ console.log(fmt.dim(` Pass the agent id directly: mnemom agent claim mnm-... --key <key> [--name ${idOrName}]`) + "\n");
152
152
  process.exit(1);
153
153
  return;
154
154
  }
@@ -286,7 +286,7 @@ export async function agentsClaimCommand(idOrName, options = {}) {
286
286
  console.log(fmt.error("Failed to claim agent: the --key (and agent name) didn't match the agent's stored proof (invalid hash proof)."));
287
287
  console.log(fmt.dim(` Confirm --key is the exact provider key the agent runs with.\n` +
288
288
  ` If the name couldn't be auto-resolved from the id, pass it explicitly:\n` +
289
- ` mnemom agents claim ${agentId} --key <key> --name <provisioned-name>`) + "\n");
289
+ ` mnemom agent claim ${agentId} --key <key> --name <provisioned-name>`) + "\n");
290
290
  process.exit(1);
291
291
  return;
292
292
  }
@@ -335,7 +335,7 @@ export async function agentsClaimCommand(idOrName, options = {}) {
335
335
  console.log();
336
336
  }
337
337
  /**
338
- * `mnemom agents move <id-or-name> --to <slug|id>`
338
+ * `mnemom agent move <id-or-name> --to <slug|id>`
339
339
  *
340
340
  * Role-based relocation between orgs (the counterpart to re-claim, which is
341
341
  * possession-based). The server requires the caller to be an owner/admin of
@@ -400,7 +400,7 @@ export async function agentsMoveCommand(idOrName, options = {}) {
400
400
  catch (err) {
401
401
  if (err instanceof MnemomApiError && err.effectiveStatus === 403) {
402
402
  console.log(fmt.error("Move denied: you must be an owner/admin of BOTH the agent's current org and the destination org.") + "\n");
403
- console.log(fmt.dim(" Check your roles with `mnemom org list`. If you hold the agent's key instead, re-claim can move it: mnemom agents claim <id> --org <slug> --key <key>.") + "\n");
403
+ console.log(fmt.dim(" Check your roles with `mnemom org list`. If you hold the agent's key instead, re-claim can move it: mnemom agent claim <id> --org <slug> --key <key>.") + "\n");
404
404
  process.exit(1);
405
405
  return;
406
406
  }
@@ -262,7 +262,7 @@ async function claimIdentity(agentId, scannedName, options, result, json, steps,
262
262
  if (status === 403 &&
263
263
  (err.code === "invalid_hash_proof" || /hash[ _]?proof/i.test(err.message))) {
264
264
  throw teachingClaimError(agentId, "the --key (and agent name) didn't match the agent's stored proof (invalid hash proof).", "Confirm --key is the exact provider key the agent runs with. If the name couldn't be " +
265
- `auto-resolved, pass it via \`mnemom agents claim ${agentId} --key <key> --name <name>\`.`, json, result, steps);
265
+ `auto-resolved, pass it via \`mnemom agent claim ${agentId} --key <key> --name <name>\`.`, json, result, steps);
266
266
  }
267
267
  if (status === 403 && err.code === "agent_cross_tenant") {
268
268
  throw teachingClaimError(agentId, "this agent is already claimed by a different owner.", "Onboard an agent you own, or provision a fresh one with `mnemom wrap`.", json, result, steps);
@@ -323,7 +323,7 @@ function renderClaimInstructions(agentId) {
323
323
  "",
324
324
  fmt.dim(" Claim this agent so you own its identity on the platform:"),
325
325
  "",
326
- ` mnemom agents claim ${agentId}`,
326
+ ` mnemom agent claim ${agentId}`,
327
327
  "",
328
328
  fmt.dim(" After claiming, traces appear in `mnemom logs`."),
329
329
  ];