@agentmemory/agentmemory 0.9.29 → 0.9.30
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/.env.example +83 -22
- package/AGENTS.md +17 -24
- package/README.md +447 -170
- package/dist/.env.example +83 -22
- package/dist/cli.d.mts.map +1 -1
- package/dist/cli.mjs +1221 -335
- package/dist/cli.mjs.map +1 -1
- package/dist/{connect-Qaeq15TQ.mjs → connect-B4_ca6BD.mjs} +30 -39
- package/dist/connect-B4_ca6BD.mjs.map +1 -0
- package/dist/docker-compose.yml +40 -14
- package/dist/hooks/_capture.d.mts +22 -0
- package/dist/hooks/_capture.d.mts.map +1 -0
- package/dist/hooks/_capture.mjs +908 -0
- package/dist/hooks/_capture.mjs.map +1 -0
- package/dist/hooks/antigravity-bridge.d.mts +1 -1
- package/dist/hooks/antigravity-bridge.d.mts.map +1 -1
- package/dist/hooks/antigravity-bridge.mjs +24 -15
- package/dist/hooks/antigravity-bridge.mjs.map +1 -1
- package/dist/hooks/notification.mjs +17 -25
- package/dist/hooks/notification.mjs.map +1 -1
- package/dist/hooks/post-commit.mjs +71 -1
- package/dist/hooks/post-commit.mjs.map +1 -1
- package/dist/hooks/post-tool-failure.mjs +59 -25
- package/dist/hooks/post-tool-failure.mjs.map +1 -1
- package/dist/hooks/post-tool-use.mjs +87 -35
- package/dist/hooks/post-tool-use.mjs.map +1 -1
- package/dist/hooks/pre-compact.mjs +83 -3
- package/dist/hooks/pre-compact.mjs.map +1 -1
- package/dist/hooks/pre-tool-use.mjs +71 -1
- package/dist/hooks/pre-tool-use.mjs.map +1 -1
- package/dist/hooks/prompt-submit.mjs +13 -21
- package/dist/hooks/prompt-submit.mjs.map +1 -1
- package/dist/hooks/session-end.mjs +25 -20
- package/dist/hooks/session-end.mjs.map +1 -1
- package/dist/hooks/session-start.mjs +80 -3
- package/dist/hooks/session-start.mjs.map +1 -1
- package/dist/hooks/stop.mjs +71 -1
- package/dist/hooks/stop.mjs.map +1 -1
- package/dist/hooks/subagent-start.mjs +16 -25
- package/dist/hooks/subagent-start.mjs.map +1 -1
- package/dist/hooks/subagent-stop.mjs +17 -25
- package/dist/hooks/subagent-stop.mjs.map +1 -1
- package/dist/hooks/task-completed.mjs +19 -27
- package/dist/hooks/task-completed.mjs.map +1 -1
- package/dist/iii-config.docker.yaml +10 -10
- package/dist/iii-config.yaml +3 -1
- package/dist/{image-refs-BKLmp_sD.mjs → image-refs-BaT-9oMU.mjs} +2 -2
- package/dist/image-refs-BaT-9oMU.mjs.map +1 -0
- package/dist/{image-refs-CJgZmb9X.mjs → image-refs-T_urbwHM.mjs} +3 -3
- package/dist/image-refs-T_urbwHM.mjs.map +1 -0
- package/dist/{keyed-mutex-DTHtcZrt.mjs → image-store-BsN4vyjr.mjs} +2 -14
- package/dist/image-store-BsN4vyjr.mjs.map +1 -0
- package/dist/index.mjs +12943 -6218
- package/dist/index.mjs.map +1 -1
- package/dist/{schema-BFZhNTF7.mjs → keyed-mutex-DchXsyfP.mjs} +28 -4
- package/dist/keyed-mutex-DchXsyfP.mjs.map +1 -0
- package/dist/secret-store-BnY3A50C.mjs +2348 -0
- package/dist/secret-store-BnY3A50C.mjs.map +1 -0
- package/dist/{src-G7yt8gGm.mjs → src-Jsq9LCeH.mjs} +5941 -2180
- package/dist/src-Jsq9LCeH.mjs.map +1 -0
- package/dist/{standalone-BqNJDJ04.mjs → standalone-DKCdrf1d.mjs} +39 -12
- package/dist/standalone-DKCdrf1d.mjs.map +1 -0
- package/dist/standalone.d.mts.map +1 -1
- package/dist/standalone.mjs +249 -14
- package/dist/standalone.mjs.map +1 -1
- package/dist/status-IRz7ta8-.mjs +2344 -0
- package/dist/status-IRz7ta8-.mjs.map +1 -0
- package/dist/viewer/index.html +7224 -2794
- package/docker-compose.yml +40 -14
- package/iii-config.docker.yaml +10 -10
- package/iii-config.yaml +3 -1
- package/integrations/pi/index.ts +2 -3
- package/integrations/pi/security.ts +52 -0
- package/package.json +13 -4
- package/plugin/.claude-plugin/plugin.json +2 -2
- package/plugin/.codex-plugin/plugin.json +26 -4
- package/plugin/.devin-plugin/plugin.json +1 -1
- package/plugin/.mcp.codex.json +12 -0
- package/plugin/.mcp.copilot.json +2 -7
- package/plugin/.mcp.json +2 -7
- package/plugin/assets/icon.svg +35 -0
- package/plugin/hooks/hooks.copilot.json +11 -11
- package/plugin/opencode/README.md +266 -30
- package/plugin/opencode/agentmemory-capture.ts +572 -3
- package/plugin/opencode/plugin.json +1 -1
- package/plugin/plugin.json +1 -1
- package/plugin/scripts/_capture.d.mts +22 -0
- package/plugin/scripts/_capture.d.mts.map +1 -0
- package/plugin/scripts/_capture.mjs +908 -0
- package/plugin/scripts/_capture.mjs.map +1 -0
- package/plugin/scripts/antigravity-bridge.d.mts +1 -1
- package/plugin/scripts/antigravity-bridge.d.mts.map +1 -1
- package/plugin/scripts/antigravity-bridge.mjs +24 -15
- package/plugin/scripts/antigravity-bridge.mjs.map +1 -1
- package/plugin/scripts/notification.mjs +17 -25
- package/plugin/scripts/notification.mjs.map +1 -1
- package/plugin/scripts/plugin-bridge.mjs +378 -0
- package/plugin/scripts/post-commit.mjs +71 -1
- package/plugin/scripts/post-commit.mjs.map +1 -1
- package/plugin/scripts/post-tool-failure.mjs +59 -25
- package/plugin/scripts/post-tool-failure.mjs.map +1 -1
- package/plugin/scripts/post-tool-use.mjs +87 -35
- package/plugin/scripts/post-tool-use.mjs.map +1 -1
- package/plugin/scripts/pre-compact.mjs +83 -3
- package/plugin/scripts/pre-compact.mjs.map +1 -1
- package/plugin/scripts/pre-tool-use.mjs +71 -1
- package/plugin/scripts/pre-tool-use.mjs.map +1 -1
- package/plugin/scripts/prompt-submit.mjs +13 -21
- package/plugin/scripts/prompt-submit.mjs.map +1 -1
- package/plugin/scripts/session-end.mjs +25 -20
- package/plugin/scripts/session-end.mjs.map +1 -1
- package/plugin/scripts/session-start.mjs +80 -3
- package/plugin/scripts/session-start.mjs.map +1 -1
- package/plugin/scripts/stop.mjs +71 -1
- package/plugin/scripts/stop.mjs.map +1 -1
- package/plugin/scripts/subagent-start.mjs +16 -25
- package/plugin/scripts/subagent-start.mjs.map +1 -1
- package/plugin/scripts/subagent-stop.mjs +17 -25
- package/plugin/scripts/subagent-stop.mjs.map +1 -1
- package/plugin/scripts/task-completed.mjs +19 -27
- package/plugin/scripts/task-completed.mjs.map +1 -1
- package/plugin/skills/_shared/TROUBLESHOOTING.md +22 -6
- package/plugin/skills/agentmemory-agents/REFERENCE.md +3 -3
- package/plugin/skills/agentmemory-config/REFERENCE.md +49 -1
- package/plugin/skills/agentmemory-config/SKILL.md +44 -7
- package/plugin/skills/agentmemory-mcp-tools/REFERENCE.md +1 -1
- package/plugin/skills/agentmemory-rest-api/REFERENCE.md +10 -2
- package/plugin/skills/handoff/SKILL.md +4 -2
- package/plugin/skills/memory-discipline/SKILL.md +13 -5
- package/dist/connect-Qaeq15TQ.mjs.map +0 -1
- package/dist/image-refs-BKLmp_sD.mjs.map +0 -1
- package/dist/image-refs-CJgZmb9X.mjs.map +0 -1
- package/dist/keyed-mutex-DTHtcZrt.mjs.map +0 -1
- package/dist/logger-BEB7pCI9.mjs +0 -43
- package/dist/logger-BEB7pCI9.mjs.map +0 -1
- package/dist/schema-BFZhNTF7.mjs.map +0 -1
- package/dist/src-G7yt8gGm.mjs.map +0 -1
- package/dist/standalone-BqNJDJ04.mjs.map +0 -1
- package/dist/tools-registry-BV_2bu7z.mjs +0 -1405
- package/dist/tools-registry-BV_2bu7z.mjs.map +0 -1
package/dist/cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.mjs","names":["__dirname","findEnvExample","fsConstants","PATH_DELIMITER"],"sources":["../src/cli/doctor-diagnostics.ts","../src/cli/remove-plan.ts","../src/cli/splash.ts","../src/cli/preferences.ts","../src/cli/onboarding.ts","../src/cli-data-dir.ts","../src/cli.ts"],"sourcesContent":["// Doctor v2 diagnostic catalog.\n//\n// Each entry is a self-describing diagnostic: a check function that returns\n// `{ ok, detail? }`, a human-readable message, an inline fix preview, and\n// an `apply` function that runs the fix. The list is exported as a pure\n// data structure so unit tests can assert on shape without bringing\n// @clack/prompts into the test harness.\n//\n// The runtime (src/cli.ts -> runDoctor) iterates the list, prompts the user\n// per check, and only re-runs the SAME diagnostic after a fix — never the\n// whole suite. Each fix returns `{ ok, message? }` so we can show a one-line\n// outcome before moving on.\n//\n// Doctor v2 surface:\n// agentmemory doctor # interactive: Fix/Skip/More/Quit per failed check\n// agentmemory doctor --all # apply every available fix without prompting (CI)\n// agentmemory doctor --dry-run # show what each fix WOULD do; execute nothing\n\nexport type DiagnosticStatus = {\n ok: boolean;\n /** Short status detail (one line). Shown alongside the check name. */\n detail?: string;\n};\n\nexport type DiagnosticFixResult = {\n ok: boolean;\n message?: string;\n};\n\nexport type DoctorContext = {\n /** Base URL for the running engine, e.g. http://localhost:3111 */\n baseUrl: string;\n /** Viewer URL, e.g. http://localhost:3113 */\n viewerUrl: string;\n /** Path to ~/.agentmemory/.env */\n envPath: string;\n /** Path to ~/.agentmemory/iii.pid */\n pidfilePath: string;\n /** Path to ~/.agentmemory/engine-state.json */\n enginePath: string;\n /** Pinned engine version (e.g. \"0.11.2\"). */\n pinnedVersion: string;\n};\n\nexport type Diagnostic = {\n /** Stable id. Used in --json and tests. */\n id: string;\n /** One-line problem statement shown to the user. */\n message: string;\n /** One-line description of WHAT the fix will do. Shown before the prompt. */\n fixPreview: string;\n /** Longer explanation shown when the user picks [?] More info. */\n moreInfo: string;\n /** Run the check; return ok=true if everything's fine, ok=false otherwise. */\n check: (ctx: DoctorContext) => Promise<DiagnosticStatus>;\n /** Apply the fix. Returns ok=true on success. */\n fix: (ctx: DoctorContext) => Promise<DiagnosticFixResult>;\n /** True when there's nothing to auto-fix (we only suggest). */\n manualOnly?: boolean;\n};\n\n// Diagnostic ids are stable for testing and machine-readable doctor output.\nexport const DIAGNOSTIC_IDS = [\n \"env-missing\",\n \"no-llm-provider-key\",\n \"engine-version-mismatch\",\n \"viewer-unreachable\",\n \"stale-pidfile\",\n \"env-placeholder-keys\",\n \"iii-on-path-not-local-bin\",\n] as const;\n\nexport type DiagnosticId = (typeof DIAGNOSTIC_IDS)[number];\n\n// Pure helpers (no I/O) — exported for direct unit testing.\n// ---------------------------------------------------------------------------\n\n/** Common placeholder values shipped in .env.example. */\nconst PLACEHOLDER_VALUES = new Set([\n \"\",\n \"your-key-here\",\n \"sk-ant-...\",\n \"sk-...\",\n \"changeme\",\n \"todo\",\n \"xxx\",\n]);\n\nconst PROVIDER_KEY_NAMES = [\n \"ANTHROPIC_API_KEY\",\n \"OPENAI_API_KEY\",\n \"GEMINI_API_KEY\",\n \"GOOGLE_API_KEY\",\n \"OPENROUTER_API_KEY\",\n \"MINIMAX_API_KEY\",\n] as const;\n\nexport function parseEnvFile(content: string): Record<string, string> {\n const out: Record<string, string> = {};\n for (const rawLine of content.split(/\\r?\\n/)) {\n const line = rawLine.trim();\n if (!line || line.startsWith(\"#\")) continue;\n const eq = line.indexOf(\"=\");\n if (eq < 0) continue;\n const key = line.slice(0, eq).trim();\n let value = line.slice(eq + 1).trim();\n // Strip surrounding quotes.\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n out[key] = value;\n }\n return out;\n}\n\n/** Returns the list of provider keys that look real (non-placeholder). */\nexport function realProviderKeys(env: Record<string, string>): string[] {\n return PROVIDER_KEY_NAMES.filter((k) => {\n const v = (env[k] ?? \"\").trim();\n if (!v) return false;\n if (PLACEHOLDER_VALUES.has(v.toLowerCase())) return false;\n // Reject values that are just dots/placeholders like \"xxxx-xxxx\".\n if (/^x+$/i.test(v.replace(/[-_]/g, \"\"))) return false;\n return true;\n });\n}\n\n/** Returns the list of provider key NAMES that exist but are placeholders. */\nexport function placeholderProviderKeys(env: Record<string, string>): string[] {\n return PROVIDER_KEY_NAMES.filter((k) => {\n const v = (env[k] ?? \"\").trim();\n if (!v) return false;\n if (PLACEHOLDER_VALUES.has(v.toLowerCase())) return true;\n if (/^x+$/i.test(v.replace(/[-_]/g, \"\"))) return true;\n return false;\n });\n}\n\n/**\n * Build the canonical diagnostic catalog.\n *\n * The factory takes the side-effect helpers as injected functions so tests\n * can swap them with stubs. Production callers pass real implementations\n * from src/cli.ts.\n */\nexport type DoctorEffects = {\n /** Does ~/.agentmemory/.env exist? */\n envFileExists: () => boolean;\n /** Read ~/.agentmemory/.env and return parsed key=value pairs. */\n readEnvFile: () => Record<string, string>;\n /** Is the iii engine PID in the pidfile still alive? */\n pidfilePidIsAlive: () => boolean | null;\n /** Does the pidfile exist on disk? */\n pidfileExists: () => boolean;\n /** Resolve the iii binary on PATH; return null if not found. */\n findIiiBinary: () => string | null;\n /** Path to ~/.agentmemory/bin/iii (the private install location). */\n localBinIiiPath: () => string;\n /** Run `iii --version`; null if it fails. */\n iiiBinaryVersion: (binPath: string) => string | null;\n /** Probe the viewer URL; true if it returns OK within timeoutMs. */\n viewerReachable: (timeoutMs?: number) => Promise<boolean>;\n /** Run init logic (copies .env.example). */\n runInit: () => Promise<DiagnosticFixResult>;\n /** Open a file in $EDITOR (or fallback). Resolves when editor exits. */\n openEditor: (path: string) => Promise<DiagnosticFixResult>;\n /** Run the iii installer. */\n runIiiInstaller: () => Promise<DiagnosticFixResult>;\n /** Stop the running engine cleanly. */\n runStop: () => Promise<DiagnosticFixResult>;\n /** Start the engine (waits for /livez). */\n runStart: () => Promise<DiagnosticFixResult>;\n /** Clear pidfile + engine-state. */\n clearEnginePidAndState: () => void;\n};\n\nexport function buildDiagnostics(effects: DoctorEffects): Diagnostic[] {\n return [\n {\n id: \"env-missing\",\n message: \"~/.agentmemory/.env is missing.\",\n fixPreview: \"Copy .env.example into ~/.agentmemory/.env (your keys file).\",\n moreInfo:\n \"agentmemory reads provider API keys (Anthropic, OpenAI, Gemini, …) from ~/.agentmemory/.env. \" +\n \"Without this file the daemon falls back to BM25-only search and no LLM-backed enrichment runs.\",\n check: async () => ({\n ok: effects.envFileExists(),\n detail: effects.envFileExists() ? undefined : \"no env file\",\n }),\n fix: () => effects.runInit(),\n },\n {\n id: \"no-llm-provider-key\",\n message: \"No LLM provider API key found in ~/.agentmemory/.env.\",\n fixPreview: \"Open ~/.agentmemory/.env in $EDITOR and paste your key, then re-check.\",\n moreInfo:\n \"Set at least one of: ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, \" +\n \"OPENROUTER_API_KEY, MINIMAX_API_KEY. The daemon picks the first that resolves \" +\n \"to a real (non-placeholder) value at startup.\",\n check: async () => {\n if (!effects.envFileExists()) {\n return { ok: false, detail: \"env file missing (run env-missing fix first)\" };\n }\n const env = effects.readEnvFile();\n const real = realProviderKeys(env);\n return {\n ok: real.length > 0,\n detail: real.length > 0 ? `found: ${real.join(\", \")}` : \"no provider key set\",\n };\n },\n fix: (ctx) => effects.openEditor(ctx.envPath),\n },\n {\n id: \"engine-version-mismatch\",\n message: \"iii binary on PATH doesn't match the version agentmemory pins to.\",\n fixPreview:\n \"Re-run the iii installer for the pinned version and restart the engine.\",\n moreInfo:\n \"agentmemory pins the iii engine to a specific release because newer engines \" +\n \"use a different worker model. Running a mismatched binary surfaces as EPIPE \" +\n \"reconnect loops and empty search results.\",\n check: async (ctx) => {\n const bin = effects.findIiiBinary();\n if (!bin) return { ok: false, detail: \"iii not on PATH\" };\n const v = effects.iiiBinaryVersion(bin);\n if (!v) return { ok: false, detail: \"iii on PATH but --version failed\" };\n return {\n ok: v === ctx.pinnedVersion,\n detail: `${v} (pinned ${ctx.pinnedVersion})`,\n };\n },\n fix: async () => {\n const r = await effects.runIiiInstaller();\n if (!r.ok) return r;\n // Best-effort restart: stop then start.\n await effects.runStop();\n return effects.runStart();\n },\n },\n {\n id: \"viewer-unreachable\",\n message: \"Viewer port not reachable.\",\n fixPreview: \"Stop the engine, restart it, and retry the viewer probe.\",\n moreInfo:\n \"The viewer is served on REST port + 2 (default 3113). If it never came up \" +\n \"the most common cause is port collision; a sibling PR ships auto-bump for \" +\n \"this case. If that lands first this check just verifies; otherwise restart \" +\n \"the engine to retry binding.\",\n check: async () => ({\n ok: await effects.viewerReachable(),\n detail: undefined,\n }),\n fix: async () => {\n const stopped = await effects.runStop();\n if (!stopped.ok) return stopped;\n return effects.runStart();\n },\n },\n {\n id: \"stale-pidfile\",\n message: \"Stale pidfile: pid recorded but the process is gone.\",\n fixPreview: \"Clear ~/.agentmemory/iii.pid + engine-state.json, then restart.\",\n moreInfo:\n \"When the engine crashes hard (kill -9, OOM, host reboot) the pidfile sticks \" +\n \"around. agentmemory refuses to start a second engine on top of a stale pid, \" +\n \"so this state must be cleared explicitly.\",\n check: async () => {\n if (!effects.pidfileExists()) return { ok: true, detail: \"no pidfile\" };\n const alive = effects.pidfilePidIsAlive();\n if (alive === null) return { ok: true, detail: \"pidfile unreadable\" };\n return {\n ok: alive,\n detail: alive ? \"pid is alive\" : \"pid is gone\",\n };\n },\n fix: async () => {\n effects.clearEnginePidAndState();\n return effects.runStart();\n },\n },\n {\n id: \"env-placeholder-keys\",\n message: \"~/.agentmemory/.env contains placeholder/empty API keys.\",\n fixPreview: \"Open ~/.agentmemory/.env in $EDITOR to paste real values.\",\n moreInfo:\n \"Lines like ANTHROPIC_API_KEY=sk-ant-... or =your-key-here are treated as \" +\n \"absent. The daemon will fall back to BM25-only search. Replace placeholders \" +\n \"with real keys or comment the line out.\",\n check: async () => {\n if (!effects.envFileExists()) {\n return { ok: true, detail: \"env file missing (handled by env-missing)\" };\n }\n const env = effects.readEnvFile();\n const placeholders = placeholderProviderKeys(env);\n return {\n ok: placeholders.length === 0,\n detail:\n placeholders.length === 0\n ? undefined\n : `placeholder: ${placeholders.join(\", \")}`,\n };\n },\n fix: (ctx) => effects.openEditor(ctx.envPath),\n },\n {\n id: \"iii-on-path-not-local-bin\",\n message:\n \"iii is on PATH but not at agentmemory's private install path.\",\n fixPreview:\n \"Install the pinned version to ~/.agentmemory/bin — won't touch your PATH.\",\n moreInfo:\n \"agentmemory installs its pinned engine to ~/.agentmemory/bin/iii so a \" +\n \"user-managed iii on PATH (homebrew, cargo, manual install) stays untouched. \" +\n \"When agentmemory needs the pin and PATH doesn't have it, it falls back to the \" +\n \"private install. If neither exists, run the installer.\",\n manualOnly: true,\n check: async () => {\n const bin = effects.findIiiBinary();\n if (!bin) return { ok: true, detail: \"iii not on PATH (handled elsewhere)\" };\n const localBin = effects.localBinIiiPath();\n return {\n ok: bin === localBin,\n detail: bin === localBin ? undefined : `iii at: ${bin}`,\n };\n },\n fix: async () =>\n effects.runIiiInstaller().then((r) => ({\n ok: r.ok,\n message:\n r.message ??\n \"Installer wrote to ~/.agentmemory/bin/iii. Your PATH wasn't modified.\",\n })),\n },\n ];\n}\n\nexport type DoctorRunMode = \"interactive\" | \"all\" | \"dry-run\";\n\n/**\n * Run all diagnostics and return their initial status (no fixes applied).\n * Useful for tests and for `--dry-run` mode.\n */\nexport async function runAllChecks(\n ctx: DoctorContext,\n diagnostics: Diagnostic[],\n): Promise<Array<{ diagnostic: Diagnostic; status: DiagnosticStatus }>> {\n const results: Array<{ diagnostic: Diagnostic; status: DiagnosticStatus }> = [];\n for (const d of diagnostics) {\n const status = await d.check(ctx);\n results.push({ diagnostic: d, status });\n }\n return results;\n}\n\n/**\n * Dry-run output: each failing check's fix preview, prefixed by the diagnostic\n * message. Pure function so we can snapshot-test the format.\n */\nexport function dryRunPlan(\n ctx: DoctorContext,\n results: Array<{ diagnostic: Diagnostic; status: DiagnosticStatus }>,\n): string[] {\n const lines: string[] = [];\n let n = 0;\n for (const { diagnostic, status } of results) {\n if (status.ok) continue;\n n++;\n lines.push(`${n}. [${diagnostic.id}] ${diagnostic.message}`);\n lines.push(` would fix: ${diagnostic.fixPreview}`);\n if (status.detail) lines.push(` detail: ${status.detail}`);\n }\n if (lines.length === 0) {\n lines.push(`All checks passing for ${ctx.baseUrl} — no fixes to run.`);\n }\n return lines;\n}\n","// `agentmemory remove` — destruction plan.\n//\n// Generating the plan is a pure function of the on-disk state (which files\n// exist, whether ~/.local/bin/iii matches the version we installed, the\n// connect-manifest contents). All side effects live in src/cli.ts; this\n// module owns only the planning logic so it's unit-testable without\n// touching $HOME.\n//\n// CLI surface:\n// agentmemory remove # interactive, double-confirms\n// agentmemory remove --force # skip confirmations\n// agentmemory remove --keep-data # remove binaries+symlinks, keep memory data\n\nimport { existsSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport type RemovePlanItem = {\n /** Stable id, used in tests and CLI output. */\n id: string;\n /** Human-readable description of the action. */\n description: string;\n /** Absolute path being acted on (or null for non-fs actions). */\n path: string | null;\n /** Whether this item is `ask-again` even with --force (e.g. memory data). */\n alwaysAsk: boolean;\n /** Whether the file actually exists / action is meaningful. Plan-time hint. */\n applicable: boolean;\n /** Bytes (for files) or -1 (unknown / dir). Pure metadata. */\n sizeBytes: number;\n};\n\nexport type RemoveOptions = {\n /** Skip confirmations (still asks separately about always-ask items). */\n force: boolean;\n /** Keep ~/.agentmemory/* user data; only remove binaries/symlinks. */\n keepData: boolean;\n};\n\nexport type RemoveContext = {\n /** $HOME (so tests can sandbox). */\n home: string;\n /** Pinned engine version we expect ~/.local/bin/iii to match. */\n pinnedVersion: string;\n /**\n * `iii --version` result for ~/.local/bin/iii, or null if it's missing /\n * unreadable / not executable. Passed in so the plan module stays pure.\n */\n localBinIiiVersion: string | null;\n /** Loaded connect manifest, or null if missing. */\n connectManifest: ConnectManifest | null;\n};\n\n/**\n * The `agentmemory connect` PR writes this manifest at\n * ~/.agentmemory/backups/connect-manifest.json. We tolerate it being absent\n * (older versions, fresh installs) by treating it as `{ installed: [] }`.\n */\nexport type ConnectManifest = {\n installed: Array<{\n /** Target path the connect command wrote (symlink or file). */\n target: string;\n /** Agent label, e.g. \"claude-code\", \"cursor\". */\n agent?: string;\n /** Whether this was a symlink (true) or copy (false). */\n symlink?: boolean;\n }>;\n};\n\nexport function pidfilePath(home: string): string {\n return join(home, \".agentmemory\", \"iii.pid\");\n}\n\nexport function enginePath(home: string): string {\n return join(home, \".agentmemory\", \"engine-state.json\");\n}\n\nexport function envPath(home: string): string {\n return join(home, \".agentmemory\", \".env\");\n}\n\nexport function preferencesPath(home: string): string {\n return join(home, \".agentmemory\", \"preferences.json\");\n}\n\nexport function backupsDir(home: string): string {\n return join(home, \".agentmemory\", \"backups\");\n}\n\nexport function dataDir(home: string): string {\n return join(home, \".agentmemory\", \"data\");\n}\n\n// Platform-aware binary name. Windows requires the .exe suffix or the\n// existsSync probe misses the installed binary.\nfunction iiiBinFile(): string {\n return process.platform === \"win32\" ? \"iii.exe\" : \"iii\";\n}\n\n// Legacy install location. Older agentmemory versions wrote the pinned iii\n// engine here. Kept so `agentmemory remove` can still clean up after them.\nexport function legacyLocalBinIii(home: string): string {\n return join(home, \".local\", \"bin\", iiiBinFile());\n}\n\n// Current private install location. Lives under ~/.agentmemory/ so it\n// stays isolated from any user-managed iii on PATH.\nexport function privateIiiBin(home: string): string {\n return join(home, \".agentmemory\", \"bin\", iiiBinFile());\n}\n\n// Back-compat shim for any caller still importing the old name.\nexport const localBinIii = privateIiiBin;\n\nfunction safeSize(path: string): number {\n try {\n return statSync(path).size;\n } catch {\n return -1;\n }\n}\n\nfunction pathExists(path: string): boolean {\n try {\n return existsSync(path);\n } catch {\n return false;\n }\n}\n\n/**\n * Build the destruction plan for `agentmemory remove`.\n *\n * Plan items are returned regardless of whether `applicable` is true — the\n * caller can decide whether to skip-and-log or hide entirely. This keeps\n * the structure stable for tests.\n */\nexport function buildRemovePlan(\n ctx: RemoveContext,\n options: RemoveOptions,\n): RemovePlanItem[] {\n const { home, pinnedVersion, localBinIiiVersion, connectManifest } = ctx;\n const plan: RemovePlanItem[] = [];\n\n plan.push({\n id: \"stop-engine\",\n description: \"Stop running iii-engine (if any) cleanly\",\n path: null,\n alwaysAsk: false,\n applicable: pathExists(pidfilePath(home)) || pathExists(enginePath(home)),\n sizeBytes: -1,\n });\n\n plan.push({\n id: \"pidfile\",\n description: \"Delete pidfile\",\n path: pidfilePath(home),\n alwaysAsk: false,\n applicable: pathExists(pidfilePath(home)),\n sizeBytes: safeSize(pidfilePath(home)),\n });\n\n plan.push({\n id: \"engine-state\",\n description: \"Delete engine-state.json\",\n path: enginePath(home),\n alwaysAsk: false,\n applicable: pathExists(enginePath(home)),\n sizeBytes: safeSize(enginePath(home)),\n });\n\n // .env holds the user's API keys. Always ask before deleting, even on\n // --force. --keep-data keeps it as part of \"user data\".\n plan.push({\n id: \"env\",\n description: \"Delete .env (your API keys) — will ask separately\",\n path: envPath(home),\n alwaysAsk: true,\n applicable: !options.keepData && pathExists(envPath(home)),\n sizeBytes: safeSize(envPath(home)),\n });\n\n plan.push({\n id: \"preferences\",\n description: \"Delete preferences.json\",\n path: preferencesPath(home),\n alwaysAsk: false,\n applicable: !options.keepData && pathExists(preferencesPath(home)),\n sizeBytes: safeSize(preferencesPath(home)),\n });\n\n plan.push({\n id: \"backups\",\n description: \"Delete backups/ directory (connect manifest + backups)\",\n path: backupsDir(home),\n alwaysAsk: false,\n applicable: !options.keepData && pathExists(backupsDir(home)),\n sizeBytes: -1,\n });\n\n // Iterate over connect-installed agent symlinks. We always honor these\n // (even with --keep-data, since they're outside ~/.agentmemory/).\n if (connectManifest?.installed?.length) {\n for (const entry of connectManifest.installed) {\n plan.push({\n id: `connect:${entry.target}`,\n description: `Remove agent connection (${entry.agent ?? \"unknown\"})`,\n path: entry.target,\n alwaysAsk: false,\n applicable: pathExists(entry.target),\n sizeBytes: safeSize(entry.target),\n });\n }\n }\n\n // Private install (~/.agentmemory/bin/iii) — agentmemory owns this path,\n // so it's always safe to remove. The version check still gates the\n // legacy ~/.local/bin/iii path which may be a user-managed install we\n // don't own.\n const privIii = privateIiiBin(home);\n if (pathExists(privIii)) {\n plan.push({\n id: \"private-bin-iii\",\n description: `Delete ~/.agentmemory/bin/iii (agentmemory's private install)`,\n path: privIii,\n alwaysAsk: false,\n applicable: true,\n sizeBytes: safeSize(privIii),\n });\n }\n\n // Legacy ~/.local/bin/iii — only remove if it matches the version we\n // installed. Older agentmemory wrote here; newer versions don't but the\n // file may still be a leftover from a previous install.\n // Heuristic: spawn `iii --version`; if it returns pinnedVersion, safe to\n // remove. Otherwise mark `alwaysAsk` so the operator confirms explicitly.\n const legacyIii = legacyLocalBinIii(home);\n if (pathExists(legacyIii)) {\n const matches = localBinIiiVersion === pinnedVersion;\n plan.push({\n id: \"legacy-local-bin-iii\",\n description: matches\n ? `Delete ~/.local/bin/iii (legacy install location, matches pinned v${pinnedVersion})`\n : `Delete ~/.local/bin/iii (legacy install location, version ${localBinIiiVersion ?? \"unknown\"} != pinned v${pinnedVersion}) — will ask`,\n path: legacyIii,\n alwaysAsk: !matches,\n applicable: true,\n sizeBytes: safeSize(legacyIii),\n });\n }\n\n // Memory data dir — ALWAYS asks separately, even with --force. Default\n // behavior is keep.\n plan.push({\n id: \"data-dir\",\n description:\n \"Delete memory data directory (~/.agentmemory/data/) — will ask separately\",\n path: dataDir(home),\n alwaysAsk: true,\n applicable: !options.keepData && pathExists(dataDir(home)),\n sizeBytes: -1,\n });\n\n return plan;\n}\n\n/** Format a plan for the user — one line per item. */\nexport function formatPlan(plan: RemovePlanItem[]): string {\n return plan\n .filter((p) => p.applicable)\n .map((p, i) => {\n const tag = p.alwaysAsk ? \" [asks]\" : \"\";\n const sz =\n p.sizeBytes > 0 ? ` (${humanBytes(p.sizeBytes)})` : \"\";\n return ` ${i + 1}. ${p.description}${tag}${sz}${p.path ? `\\n ${p.path}` : \"\"}`;\n })\n .join(\"\\n\");\n}\n\nfunction humanBytes(n: number): string {\n if (n < 1024) return `${n} B`;\n if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;\n return `${(n / (1024 * 1024)).toFixed(1)} MB`;\n}\n","// Terminal-width-aware splash banner for the agentmemory CLI.\n//\n// Three render tiers, picked from `process.stdout.columns`:\n//\n// >= 120 cols: full block-art logo + tagline.\n// 80–119 cols: compact monospace title + tagline.\n// < 80 cols: single-line `agentmemory v<VERSION>`.\n//\n// The brand accent is the orange `#FF6B35` we already use in the README\n// and viewer; we render it through ANSI 38;5;208 (the closest xterm-256\n// match) when stdout is a TTY, and fall back to plain text otherwise.\n// No colour bytes are hard-coded into the strings themselves so that\n// piping the banner to a file (`agentmemory > log`) stays clean.\n//\n// We don't pull in chalk/picocolors — picocolors is a transitive dep but\n// we never want to depend on transitives directly. The two ANSI escape\n// helpers below are the entire colour surface and they degrade to\n// no-ops automatically.\n\nconst IS_COLOR_TTY = !!process.stdout.isTTY && !process.env[\"NO_COLOR\"];\n\nfunction accent(s: string): string {\n // 256-colour orange that visually matches #FF6B35 in most modern\n // terminal palettes. We pick 208 (a true orange) over the closer-but-\n // pinker 209 because it reads as the brand colour on both dark and\n // light backgrounds.\n return IS_COLOR_TTY ? `\\x1b[38;5;208m${s}\\x1b[0m` : s;\n}\n\nfunction dim(s: string): string {\n return IS_COLOR_TTY ? `\\x1b[2m${s}\\x1b[22m` : s;\n}\n\nfunction bold(s: string): string {\n return IS_COLOR_TTY ? `\\x1b[1m${s}\\x1b[22m` : s;\n}\n\nfunction getTerminalWidth(): number {\n const w = process.stdout.columns;\n return typeof w === \"number\" && w > 0 ? w : 80;\n}\n\nconst TAGLINE = \"Persistent memory for AI coding agents\";\n\n// \"agentmemory\" rendered in figlet's standard font (verified output —\n// regenerate via `figlet agentmemory` if you change the wordmark). Each\n// row is exactly 70 columns wide so the banner aligns cleanly inside\n// the 2-col left margin we add below.\nfunction fullBanner(version: string): string {\n const logo = [\n \" _ \",\n \" __ _ __ _ ___ _ __ | |_ _ __ ___ ___ _ __ ___ ___ _ __ _ _ \",\n \" / _` |/ _` |/ _ \\\\ '_ \\\\| __| '_ ` _ \\\\ / _ \\\\ '_ ` _ \\\\ / _ \\\\| '__| | | |\",\n \"| (_| | (_| | __/ | | | |_| | | | | | __/ | | | | | (_) | | | |_| |\",\n \" \\\\__,_|\\\\__, |\\\\___|_| |_|\\\\__|_| |_| |_|\\\\___|_| |_| |_|\\\\___/|_| \\\\__, |\",\n \" |___/ |___/ \",\n ];\n const lines: string[] = [\"\", ...logo.map((line) => \" \" + accent(line))];\n lines.push(\"\");\n lines.push(\" \" + bold(TAGLINE) + \" \" + dim(`v${version}`));\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n\nfunction compactBanner(version: string): string {\n const title = \" \" + bold(accent(\"agentmemory\"));\n const meta = \" \" + dim(`v${version} · ${TAGLINE}`);\n return [\"\", title, meta, \"\"].join(\"\\n\");\n}\n\nfunction minimalBanner(version: string): string {\n return `${accent(\"agentmemory\")} ${dim(`v${version}`)}`;\n}\n\nexport function renderSplash(version: string): void {\n const width = getTerminalWidth();\n let out: string;\n if (width >= 120) {\n out = fullBanner(version);\n } else if (width >= 80) {\n out = compactBanner(version);\n } else {\n out = minimalBanner(version);\n }\n process.stdout.write(out + \"\\n\");\n}\n","// JSON-backed CLI preferences.\n//\n// Lives at `~/.agentmemory/preferences.json`. The agentmemory daemon\n// already owns `~/.agentmemory/.env`, `iii.pid`, `engine-state.json` —\n// adding one more sibling here keeps the install-state surface in one\n// place.\n//\n// All functions are synchronous, mirroring the pidfile / engine-state\n// helpers in src/cli.ts. We never throw: read failures collapse to\n// defaults; write failures swallow silently. Preferences are a UX\n// nicety, not data — corrupting `iii.pid` matters, corrupting this\n// file does not.\n//\n// Writes are atomic via tmp + rename so a Ctrl+C between the open and\n// the final write can't leave a half-written JSON blob on disk that\n// the next read would refuse to parse.\n\nimport {\n closeSync,\n existsSync,\n fsyncSync,\n mkdirSync,\n openSync,\n readFileSync,\n renameSync,\n unlinkSync,\n writeSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport interface Prefs {\n schemaVersion: 1;\n // Most recently picked single agent (for \"use last agent\" style flows).\n lastAgent: string | null;\n // The full multi-select set from the last onboarding run.\n lastAgents: string[];\n // Most recently picked LLM provider; `null` means BM25-only mode.\n lastProvider: string | null;\n // Once true, splash is rendered only on first run / explicit --reset.\n // The first onboarding sets this to true so the second invocation\n // skips the banner.\n skipSplash: boolean;\n // Reserved for a later \"do not nag me about the npx vs install\n // tradeoff\" toggle. Kept on the schema so we don't have to bump\n // schemaVersion when we ship the flag.\n skipNpxHint: boolean;\n // Set to true when the user declines the \"install agentmemory\n // globally?\" prompt on first npx run. We never ask again on this\n // machine so the prompt stays a one-time DX nudge, not a nag.\n skipGlobalInstall: boolean;\n // Set to true when the user declines the \"install iii console?\"\n // prompt. iii console is first-class engine UI but optional at the\n // install step — once the user says no, we stop asking.\n skipConsoleInstall: boolean;\n // ISO timestamp of the first time onboarding completed. Set once,\n // never updated, so we can show \"you joined agentmemory N days ago\"\n // copy in /status later without keeping a separate file.\n firstRunAt: string | null;\n // Set to true once the user has answered the context-injection prompt\n // (either way). We never re-ask after this so the prompt stays a\n // one-time choice, matching the skipGlobalInstall / skipConsoleInstall\n // never-nag pattern.\n injectContextChosen: boolean;\n}\n\nconst DEFAULTS: Prefs = {\n schemaVersion: 1,\n lastAgent: null,\n lastAgents: [],\n lastProvider: null,\n skipSplash: false,\n skipNpxHint: false,\n skipGlobalInstall: false,\n skipConsoleInstall: false,\n firstRunAt: null,\n injectContextChosen: false,\n};\n\nexport function prefsDir(): string {\n return join(homedir(), \".agentmemory\");\n}\n\nexport function prefsPath(): string {\n return join(prefsDir(), \"preferences.json\");\n}\n\nexport function readPrefs(): Prefs {\n try {\n if (!existsSync(prefsPath())) return { ...DEFAULTS };\n const raw = readFileSync(prefsPath(), \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<Prefs>;\n return { ...DEFAULTS, ...parsed, schemaVersion: 1 };\n } catch {\n return { ...DEFAULTS };\n }\n}\n\nexport function writePrefs(p: Partial<Prefs>): void {\n try {\n const dir = prefsDir();\n mkdirSync(dir, { recursive: true });\n const current = readPrefs();\n const next: Prefs = { ...current, ...p, schemaVersion: 1 };\n const target = prefsPath();\n const tmp = target + \".tmp\";\n // Open + write + fsync + rename ensures a Ctrl+C between any two\n // syscalls either leaves the old file intact (rename is atomic on\n // POSIX) or leaves only a .tmp behind that the next writePrefs\n // overwrites. We never end up with a truncated `preferences.json`\n // that readPrefs would have to discard.\n const fd = openSync(tmp, \"w\", 0o600);\n try {\n writeSync(fd, JSON.stringify(next, null, 2) + \"\\n\");\n try {\n fsyncSync(fd);\n } catch {\n // fsync isn't available on every filesystem (e.g. some Docker\n // overlays). The rename below is still atomic; we just can't\n // guarantee durability against a power loss.\n }\n } finally {\n closeSync(fd);\n }\n renameSync(tmp, target);\n } catch {\n // Preferences are best-effort. Don't crash the CLI for them.\n }\n}\n\nexport function resetPrefs(): void {\n try {\n unlinkSync(prefsPath());\n } catch {\n // Already gone — that's exactly the state we wanted.\n }\n}\n\nexport function isFirstRun(): boolean {\n // \"First run\" means: the preferences file doesn't exist OR exists\n // but `firstRunAt` was never recorded. The latter handles users who\n // had `.agentmemory/preferences.json` from a much older agentmemory\n // build that wrote a different schema — we treat them as new.\n if (!existsSync(prefsPath())) return true;\n return readPrefs().firstRunAt === null;\n}\n","// First-run interactive onboarding flow.\n//\n// Wakes up only when `isFirstRun()` is true (preferences are missing or\n// have never recorded a `firstRunAt`) or when the user passes\n// `--reset`. The flow asks for:\n//\n// 1. Which agents will be wired to agentmemory (multi-select). Each\n// option carries a small glyph that we reuse in /status output so\n// the user recognises them later. The label mirrors README row 1\n// (native plugins) and row 2 (MCP-only).\n// 2. Which LLM provider to use for compress / consolidate / graph.\n// \"skip — BM25-only mode\" is a real first-class option; lots of\n// users want agentmemory purely as a hybrid keyword + vector\n// memory layer without granting LLM API keys.\n//\n// We then write `~/.agentmemory/preferences.json` and seed\n// `~/.agentmemory/.env` with a commented-out `*_API_KEY=` line for the\n// chosen provider. This matches the existing `agentmemory init` flow\n// closely so users who skip onboarding still get the same file via\n// `agentmemory init`.\n\nimport { copyFile, mkdir } from \"node:fs/promises\";\nimport { constants as fsConstants, existsSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport * as p from \"@clack/prompts\";\nimport { appendFileSync, readFileSync } from \"node:fs\";\nimport { readPrefs, writePrefs } from \"./preferences.js\";\nimport { ADAPTERS, resolveAdapter, runAdapter } from \"./connect/index.js\";\nimport type { ConnectResult } from \"./connect/types.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n// Native plugin row — these agents ship an agentmemory plugin or\n// first-party integration. Glyphs match SkillKit's published set\n// where they overlap; the rest fall back to the generic `◇`.\n// Display glyph per agent; the agent set itself comes from connect's\n// ADAPTERS (single source of truth) so the picker can never drift from\n// what `agentmemory connect` can actually wire (#872). Unknown adapters\n// fall back to a neutral glyph.\nconst AGENT_GLYPH: Record<string, string> = {\n \"claude-code\": \"⟁\",\n \"copilot-cli\": \"◈\",\n codex: \"◎\",\n cursor: \"◫\",\n \"gemini-cli\": \"✦\",\n opencode: \"⬡\",\n};\n\nconst PROVIDERS: { value: string; label: string; envKey: string | null }[] = [\n { value: \"anthropic\", label: \"Anthropic — claude\", envKey: \"ANTHROPIC_API_KEY\" },\n { value: \"openai\", label: \"OpenAI — gpt\", envKey: \"OPENAI_API_KEY\" },\n { value: \"gemini\", label: \"Google — gemini\", envKey: \"GEMINI_API_KEY\" },\n { value: \"openrouter\", label: \"OpenRouter — multi-model\", envKey: \"OPENROUTER_API_KEY\" },\n { value: \"minimax\", label: \"MiniMax — MiniMax-M3\", envKey: \"MINIMAX_API_KEY\" },\n { value: \"skip\", label: \"Skip — BM25-only mode (no LLM key)\", envKey: null },\n];\n\nconst PROVIDER_COST_HINTS: Record<string, string> = {\n anthropic: \"rough cost: a fast Haiku-class model keeps compress/consolidate at fractions of a cent per session.\",\n openai: \"rough cost: a mini-class model keeps compress/consolidate at fractions of a cent per session.\",\n gemini: \"rough cost: a Flash-class model keeps compress/consolidate at fractions of a cent per session.\",\n openrouter: \"rough cost: pick a small model; spend tracks your chosen model's per-token price.\",\n minimax: \"rough cost: scales with the MiniMax model price per token.\",\n};\n\nexport function buildAgentOptions(): { value: string; label: string; hint?: string }[] {\n const options = ADAPTERS.map((a) => ({\n value: a.name,\n label: `${AGENT_GLYPH[a.name] ?? \"◇\"} ${a.displayName}`,\n hint: a.category === \"native\" ? \"native plugin\" : \"MCP server\",\n }));\n return [\n ...options.filter((o) => o.hint === \"native plugin\"),\n ...options.filter((o) => o.hint === \"MCP server\"),\n ];\n}\n\nexport function getInitialAgentValues(\n env: Record<string, string | undefined> = process.env,\n): string[] {\n if (env[\"COPILOT_CLI\"] === \"1\" || env[\"COPILOT_AGENT_SESSION_ID\"]) {\n return [\"copilot-cli\"];\n }\n return [\"claude-code\"];\n}\n\n// Mirror src/cli.ts findEnvExample so onboarding ships the same .env\n// skeleton whether called directly or via `agentmemory init`. We\n// duplicate (rather than import) so the onboarding module doesn't\n// pull cli.ts's top-level side effects into the test runner.\nfunction findEnvExample(): string | null {\n const candidates = [\n join(__dirname, \"..\", \"..\", \".env.example\"),\n join(__dirname, \"..\", \".env.example\"),\n join(__dirname, \".env.example\"),\n join(process.cwd(), \".env.example\"),\n ];\n for (const c of candidates) {\n if (existsSync(c)) return c;\n }\n return null;\n}\n\nasync function seedEnvFile(provider: string | null): Promise<string | null> {\n const target = join(homedir(), \".agentmemory\", \".env\");\n const dir = dirname(target);\n await mkdir(dir, { recursive: true });\n\n const template = findEnvExample();\n if (template && !existsSync(target)) {\n try {\n await copyFile(template, target, fsConstants.COPYFILE_EXCL);\n } catch (err) {\n if ((err as NodeJS.ErrnoException)?.code !== \"EEXIST\") {\n return null;\n }\n }\n } else if (!template && !existsSync(target)) {\n // Fall back to a minimal skeleton so users always get a `.env` to\n // edit. This matches the shape of the bundled `.env.example`\n // without forcing us to keep two copies in sync.\n const lines = [\n \"# agentmemory environment — uncomment what you need\",\n \"# AGENTMEMORY_URL=http://localhost:3111\",\n \"\",\n ];\n const envKey = PROVIDERS.find((x) => x.value === provider)?.envKey;\n if (envKey) {\n lines.push(`# ${envKey}=`);\n }\n writeFileSync(target, lines.join(\"\\n\"), { mode: 0o600 });\n }\n\n return target;\n}\n\nexport interface OnboardingResult {\n agents: string[];\n provider: string | null;\n}\n\nfunction shouldSkipInteractiveOnboarding(): boolean {\n const ci = process.env[\"CI\"];\n return (\n process.stdin.isTTY !== true ||\n process.stdout.isTTY !== true ||\n (ci !== undefined && ci !== \"\" && ci !== \"0\" && ci.toLowerCase() !== \"false\")\n );\n}\n\nfunction writeDefaultOnboardingPrefs(): OnboardingResult {\n writePrefs({\n lastAgent: null,\n lastAgents: [],\n lastProvider: null,\n skipSplash: true,\n firstRunAt: new Date().toISOString(),\n });\n return { agents: [], provider: null };\n}\n\nexport async function runOnboarding(): Promise<OnboardingResult> {\n if (shouldSkipInteractiveOnboarding()) {\n return writeDefaultOnboardingPrefs();\n }\n\n p.note(\n [\n \"Welcome to agentmemory.\",\n \"\",\n \"Persistent memory for your AI coding agents. We'll pick which\",\n \"agents to wire up and which provider (if any) handles compression\",\n \"and consolidation. Either step can be changed later in ~/.agentmemory/.env.\",\n ].join(\"\\n\"),\n \"first-run setup\",\n );\n\n const agentsPicked = await p.multiselect<string>({\n message: \"Which agents will use agentmemory? (space to toggle, enter to confirm)\",\n options: buildAgentOptions(),\n required: false,\n initialValues: getInitialAgentValues(),\n });\n if (p.isCancel(agentsPicked)) {\n p.cancel(\"Setup cancelled. Re-run any time with: agentmemory --reset\");\n process.exit(0);\n }\n\n const pickedAgentsList = (agentsPicked as string[]) ?? [];\n if (pickedAgentsList.length > 0) {\n p.note(\n [\n \"━ how this works ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\",\n \"All selected agents share the same memory at :3111.\",\n \"A memory saved by Claude Code is visible to Copilot + Codex + Cursor instantly.\",\n \"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\",\n ].join(\"\\n\"),\n );\n }\n\n const providerPicked = await p.select<string>({\n message: \"Which LLM provider should agentmemory use for compress/consolidate?\",\n options: PROVIDERS.map(({ value, label }) => ({ value, label })),\n initialValue: \"anthropic\",\n });\n if (p.isCancel(providerPicked)) {\n p.cancel(\"Setup cancelled. Re-run any time with: agentmemory --reset\");\n process.exit(0);\n }\n\n const provider = providerPicked === \"skip\" ? null : providerPicked;\n const agents = (agentsPicked as string[]) ?? [];\n\n if (provider) {\n const hint = PROVIDER_COST_HINTS[provider];\n if (hint) {\n p.log.info(hint);\n }\n }\n\n const envPath = await seedEnvFile(provider);\n\n await maybePromptContextInjection(envPath);\n\n writePrefs({\n lastAgent: agents[0] ?? null,\n lastAgents: agents,\n lastProvider: provider,\n skipSplash: true,\n firstRunAt: new Date().toISOString(),\n });\n\n const prefsLocation = join(homedir(), \".agentmemory\", \"preferences.json\");\n const lines = [`✓ Saved preferences to ${prefsLocation}`];\n if (envPath) {\n lines.push(`✓ Wrote ${envPath} (edit to add your API key)`);\n } else {\n lines.push(`! Could not write ~/.agentmemory/.env — run \\`agentmemory init\\` after this completes.`);\n }\n if (provider) {\n const envKey = PROVIDERS.find((x) => x.value === provider)?.envKey;\n if (envKey) {\n lines.push(` Uncomment ${envKey}= in that file to enable ${provider}.`);\n }\n } else {\n lines.push(\" No provider chosen — agentmemory will run in BM25-only mode.\");\n }\n p.note(lines.join(\"\\n\"), \"ready\");\n\n if (agents.length > 0) {\n await wireSelectedAgents(agents);\n }\n\n return { agents, provider };\n}\n\nfunction enableInjectContextInEnv(envPath: string | null): boolean {\n if (!envPath || !existsSync(envPath)) return false;\n try {\n const current = readFileSync(envPath, \"utf-8\");\n if (/^\\s*AGENTMEMORY_INJECT_CONTEXT\\s*=\\s*true\\b/m.test(current)) {\n return true;\n }\n const prefix = current.length > 0 && !current.endsWith(\"\\n\") ? \"\\n\" : \"\";\n appendFileSync(envPath, `${prefix}AGENTMEMORY_INJECT_CONTEXT=true\\n`, { mode: 0o600 });\n return true;\n } catch {\n return false;\n }\n}\n\nasync function maybePromptContextInjection(envPath: string | null): Promise<void> {\n if (readPrefs().injectContextChosen) return;\n\n const enable = await p.confirm({\n message: \"Enable automatic context injection so the agent recalls past sessions without being asked? [y/N]\",\n initialValue: false,\n });\n\n if (p.isCancel(enable)) {\n p.cancel(\"Setup cancelled. Re-run any time with: agentmemory --reset\");\n process.exit(0);\n }\n\n p.log.info(\n \"Cost note: injection spends session tokens proportional to tool-call frequency. Default is off.\",\n );\n\n writePrefs({ injectContextChosen: true });\n\n if (enable === true) {\n const wrote = enableInjectContextInEnv(envPath);\n if (wrote) {\n p.log.success(\"Context injection enabled (AGENTMEMORY_INJECT_CONTEXT=true).\");\n } else {\n p.log.warn(\n \"Could not update ~/.agentmemory/.env. Set AGENTMEMORY_INJECT_CONTEXT=true there to enable it.\",\n );\n }\n } else {\n p.log.info(\"Context injection left off. Set AGENTMEMORY_INJECT_CONTEXT=true later to enable.\");\n }\n}\n\nasync function wireSelectedAgents(agents: string[]): Promise<void> {\n p.note(\"Wire selected agents now?\", \"next step\");\n const confirmed = await p.confirm({\n message: \"Run `agentmemory connect <agent>` for each selected agent now? [Y/n]\",\n initialValue: true,\n });\n\n if (p.isCancel(confirmed) || confirmed === false) {\n const cmds = agents.map((a) => ` agentmemory connect ${a}`);\n p.note([\"Wire later with:\", ...cmds].join(\"\\n\"), \"later\");\n return;\n }\n\n const wired: string[] = [];\n const manual: { name: string; docs?: string }[] = [];\n const failed: { name: string; reason: string }[] = [];\n\n for (const name of agents) {\n const adapter = resolveAdapter(name);\n if (!adapter) {\n failed.push({ name, reason: \"no adapter available\" });\n p.log.warn(`Wiring ${name}… no adapter available (skipped).`);\n continue;\n }\n p.log.step(`Wiring ${name}...`);\n let result: ConnectResult;\n try {\n result = await runAdapter(adapter, { dryRun: false, force: false });\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n failed.push({ name, reason });\n p.log.error(`${name}: ${reason}`);\n continue;\n }\n switch (result.kind) {\n case \"installed\":\n case \"already-wired\":\n wired.push(name);\n break;\n case \"stub\":\n manual.push({ name, docs: adapter.docs });\n break;\n case \"skipped\":\n failed.push({ name, reason: result.reason });\n break;\n }\n }\n\n const summary: string[] = [];\n if (wired.length > 0) {\n summary.push(`Wired: ${wired.join(\", \")}.`);\n }\n if (manual.length > 0 || failed.length > 0) {\n const parts: string[] = [];\n for (const m of manual) {\n parts.push(`${m.name} (manual install required${m.docs ? ` — see ${m.docs}` : \"\"})`);\n }\n for (const f of failed) {\n parts.push(`${f.name} (${f.reason})`);\n }\n summary.push(`Skipped/failed: ${parts.join(\", \")}.`);\n }\n if (summary.length === 0) {\n summary.push(\"No agents were wired.\");\n }\n p.note(summary.join(\"\\n\"), \"wire summary\");\n}\n","import { existsSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport { homedir, platform } from \"node:os\";\n\nexport type DataDirSource = \"flag\" | \"env\" | \"default\";\n\nexport type ResolvedDataDir = {\n dataDir: string;\n source: DataDirSource;\n relocatedFrom?: string;\n};\n\ntype ResolveDataDirOptions = {\n args?: string[];\n env?: NodeJS.ProcessEnv;\n cwd?: string;\n home?: string;\n platform?: NodeJS.Platform;\n};\n\nfunction argValue(args: string[], name: string): string | undefined {\n const equals = `${name}=`;\n const inline = args.find((arg) => arg.startsWith(equals));\n if (inline) return inline.slice(equals.length);\n\n const idx = args.indexOf(name);\n if (idx !== -1) return args[idx + 1];\n return undefined;\n}\n\nfunction expandHome(pathValue: string, home: string): string {\n if (pathValue === \"~\") return home;\n if (pathValue.startsWith(\"~/\") || pathValue.startsWith(\"~\\\\\")) {\n return join(home, pathValue.slice(2));\n }\n return pathValue;\n}\n\nfunction absoluteDataDir(pathValue: string, cwd: string, home: string): string {\n const expanded = expandHome(pathValue, home);\n return isAbsolute(expanded) ? expanded : resolve(cwd, expanded);\n}\n\nfunction platformDefaultDataDir(\n env: NodeJS.ProcessEnv,\n home: string,\n nodePlatform: NodeJS.Platform,\n useXdg = true,\n): string {\n if (nodePlatform === \"darwin\") {\n return join(home, \"Library\", \"Application Support\", \"agentmemory\");\n }\n if (nodePlatform === \"win32\") {\n const appData = env[\"APPDATA\"];\n return appData\n ? join(appData, \"agentmemory\")\n : join(home, \".agentmemory\");\n }\n const xdgDataHome = env[\"XDG_DATA_HOME\"];\n if (useXdg && xdgDataHome && isAbsolute(xdgDataHome)) {\n return join(xdgDataHome, \"agentmemory\");\n }\n return join(home, \".local\", \"share\", \"agentmemory\");\n}\n\nfunction nearestGitParent(pathValue: string): string | undefined {\n let current = pathValue;\n while (true) {\n if (existsSync(join(current, \".git\"))) return current;\n const parent = dirname(current);\n if (parent === current) return undefined;\n current = parent;\n }\n}\n\nfunction isWithin(parent: string, child: string): boolean {\n const pathFromParent = relative(parent, child);\n return (\n pathFromParent === \"\" ||\n (pathFromParent !== \"..\" &&\n !pathFromParent.startsWith(`..${sep}`) &&\n !isAbsolute(pathFromParent))\n );\n}\n\nexport function resolveDataDir(options: ResolveDataDirOptions = {}): ResolvedDataDir {\n const args = options.args ?? process.argv.slice(2);\n const env = options.env ?? process.env;\n const cwd = options.cwd ?? process.cwd();\n const home = options.home ?? homedir();\n const nodePlatform = options.platform ?? platform();\n const parsedInstance = parseInt(argValue(args, \"--instance\") ?? \"0\", 10);\n const instance =\n parsedInstance > 0 && parsedInstance <= 50 ? parsedInstance : 0;\n const forInstance = (dataDir: string) =>\n instance ? join(dataDir, `instance-${instance}`) : dataDir;\n\n const flagValue = argValue(args, \"--data-dir\");\n if (flagValue) {\n return {\n dataDir: forInstance(absoluteDataDir(flagValue, cwd, home)),\n source: \"flag\",\n };\n }\n\n const envValue = env[\"AGENTMEMORY_DATA_DIR\"];\n if (envValue) {\n return {\n dataDir: forInstance(absoluteDataDir(envValue, cwd, home)),\n source: \"env\",\n };\n }\n\n const legacyDir = resolve(cwd, \"data\");\n const hasLegacyStore =\n existsSync(join(legacyDir, \"state_store.db\")) ||\n existsSync(join(legacyDir, \"iii-config.yaml\"));\n if (instance === 0 && hasLegacyStore) {\n return { dataDir: legacyDir, source: \"default\" };\n }\n\n const defaultDir = platformDefaultDataDir(env, home, nodePlatform);\n const gitParent = nearestGitParent(cwd);\n if (gitParent && isWithin(gitParent, defaultDir)) {\n const relocated = platformDefaultDataDir(env, home, nodePlatform, false);\n if (relocated !== defaultDir) {\n return {\n dataDir: forInstance(relocated),\n source: \"default\",\n relocatedFrom: defaultDir,\n };\n }\n }\n\n return {\n dataDir: forInstance(defaultDir),\n source: \"default\",\n };\n}\n","#!/usr/bin/env node\n\nimport {\n spawn,\n execFileSync,\n spawnSync,\n type ChildProcess,\n} from \"node:child_process\";\nimport {\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n readlinkSync,\n rmSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { join, dirname, delimiter as PATH_DELIMITER } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { homedir, platform } from \"node:os\";\nimport * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\n\n// Semantic color helpers. clack strips ANSI for box-width math\n// (stripVTControlCharacters + string-width), so coloring inside p.note\n// keeps borders aligned. Centralized here so the palette stays consistent\n// across every command's output.\nconst c = {\n url: pc.cyan,\n ok: pc.green,\n warn: pc.yellow,\n err: pc.red,\n cmd: (s: string) => pc.bold(pc.cyan(s)),\n label: pc.bold,\n dim: pc.dim,\n accent: (s: string) => pc.bold(pc.yellow(s)),\n};\nimport { generateId } from \"./state/schema.js\";\nimport {\n buildDiagnostics,\n dryRunPlan,\n parseEnvFile,\n type Diagnostic,\n type DiagnosticFixResult,\n type DoctorContext,\n type DoctorEffects,\n} from \"./cli/doctor-diagnostics.js\";\nimport {\n buildRemovePlan,\n formatPlan,\n legacyLocalBinIii,\n type ConnectManifest,\n type RemoveOptions,\n} from \"./cli/remove-plan.js\";\nimport { renderSplash } from \"./cli/splash.js\";\nimport { isFirstRun, readPrefs, resetPrefs, writePrefs } from \"./cli/preferences.js\";\nimport { runOnboarding } from \"./cli/onboarding.js\";\nimport { setBootVerbose } from \"./logger.js\";\nimport { hydrateProcessEnvFromFile } from \"./config.js\";\nimport { VERSION } from \"./version.js\";\nimport { getAllTools, ESSENTIAL_TOOLS } from \"./mcp/tools-registry.js\";\nimport { knownAgents } from \"./cli/connect/index.js\";\n\nconst ALL_TOOLS_COUNT = getAllTools().length;\nconst CORE_TOOLS_COUNT = getAllTools().filter((t) => ESSENTIAL_TOOLS.has(t.name)).length;\nimport { resolveDataDir } from \"./cli-data-dir.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst args = process.argv.slice(2);\nconst IS_WINDOWS = platform() === \"win32\";\nconst IS_VERBOSE =\n args.includes(\"--verbose\") ||\n args.includes(\"-v\") ||\n process.env[\"AGENTMEMORY_VERBOSE\"] === \"1\" ||\n process.env[\"AGENTMEMORY_VERBOSE\"] === \"true\";\n\n// Propagate the resolved verbosity to the worker's boot logger so the\n// 25-line `[agentmemory] X registered` stream is either dropped or\n// printed verbatim. Without this the worker's default (env-only) would\n// disagree with the CLI flag.\nsetBootVerbose(IS_VERBOSE);\n\nconst IS_RESET = args.includes(\"--reset\");\n\n// Fold ~/.agentmemory/.env into process.env before any port/URL read\n// (getRestPort/getBaseUrl/getStreamPort/getEnginePort) or the --port /\n// --instance / --tools handlers below. Only-if-unset, so a real\n// process.env value — including one just set by a CLI flag — still wins.\nhydrateProcessEnvFromFile();\n\n// --version / -V early exit. Print VERSION + exit before any side effects\n// (engine boot, env load, dir mkdir). `-v` is taken by --verbose so we\n// reserve `-V` (capital) for version per POSIX convention.\nif (args.includes(\"--version\") || args.includes(\"-V\")) {\n process.stdout.write(`${VERSION}\\n`);\n process.exit(0);\n}\n\n// Pinned iii-engine version. The unpinned `install.iii.dev/iii/main/install.sh`\n// script tracks `latest`, which made every fresh agentmemory install pull\n// engine 0.11.6 — and 0.11.6 introduces a new sandbox-everything-via-\n// `iii worker add` worker model that agentmemory hasn't been refactored\n// for yet (we still use the old `iii-exec watch` config-file model). The\n// architectural mismatch surfaces as EPIPE reconnect loops and empty\n// search results after save. Pin to v0.11.2 — the last engine that runs\n// agentmemory's current worker model cleanly — until the refactor lands.\n// Override env var AGENTMEMORY_III_VERSION lets users on the sandbox\n// model already point at a newer engine without us cutting a release.\nconst IIPINNED_VERSION =\n process.env[\"AGENTMEMORY_III_VERSION\"] || \"0.11.2\";\n\n// Map Node platform/arch → the asset name iii-hq/iii ships under\n// https://github.com/iii-hq/iii/releases/download/iii/v<version>/<asset>\nfunction iiiReleaseAsset(): string | null {\n const p = platform();\n const a = process.arch;\n if (p === \"darwin\" && a === \"arm64\")\n return \"iii-aarch64-apple-darwin.tar.gz\";\n if (p === \"darwin\" && a === \"x64\")\n return \"iii-x86_64-apple-darwin.tar.gz\";\n if (p === \"linux\" && a === \"x64\")\n return \"iii-x86_64-unknown-linux-gnu.tar.gz\";\n if (p === \"linux\" && a === \"arm64\")\n return \"iii-aarch64-unknown-linux-gnu.tar.gz\";\n if (p === \"linux\" && a === \"arm\")\n return \"iii-armv7-unknown-linux-gnueabihf.tar.gz\";\n if (p === \"win32\" && a === \"x64\")\n return \"iii-x86_64-pc-windows-msvc.zip\";\n if (p === \"win32\" && a === \"arm64\")\n return \"iii-aarch64-pc-windows-msvc.zip\";\n return null;\n}\n\nfunction iiiReleaseUrl(): string | null {\n const asset = iiiReleaseAsset();\n if (!asset) return null;\n // Tag name is monorepo-prefixed: `iii/v0.11.2`. Slash is URL-encoded\n // by GitHub when serving the download path, hence `iii/v...` not `iii%2Fv...`.\n return `https://github.com/iii-hq/iii/releases/download/iii/v${IIPINNED_VERSION}/${asset}`;\n}\n\nfunction vlog(msg: string): void {\n if (IS_VERBOSE) p.log.info(`[verbose] ${msg}`);\n}\n\nfunction wrapList(items: readonly string[], indent: number, width = 78): string {\n const lines: string[] = [];\n let line = \"\";\n for (const item of items) {\n const joined = line ? `${line}, ${item}` : item;\n if (line && indent + joined.length > width) {\n lines.push(`${line},`);\n line = item;\n } else {\n line = joined;\n }\n }\n lines.push(line);\n return lines.join(`\\n${\" \".repeat(indent)}`);\n}\n\nif (args.includes(\"--help\") || args.includes(\"-h\")) {\n console.log(`\nagentmemory — persistent memory for AI coding agents\n\nUsage: agentmemory [command] [options]\n\nCommands:\n (default) Start agentmemory worker\n init Copy bundled .env.example to ~/.agentmemory/.env if absent\n connect [agent] Wire agentmemory into an installed agent\n (${wrapList(knownAgents(), 21)}).\n No arg = interactive picker. --all wires every detected agent.\n --dry-run shows what would change. --force re-installs.\n status Show connection status, memory count, flags, and health\n doctor Interactive diagnostic + fixer. [F]ix · [S]kip · [?]more · [Q]uit\n --all: apply every fix without prompting (CI)\n --dry-run: show what each fix would do, don't execute\n remove Cleanly uninstall agentmemory (pidfile, state, .env, binaries).\n --force: skip confirmations · --keep-data: keep memory data\n demo [--serve] Seed sample sessions and show recall in action.\n --serve boots the server, runs the demo, and stops it\n in one command (no second terminal).\n upgrade Upgrade local deps + iii runtime (best effort)\n stop [--force] Stop the running iii-engine started by this CLI.\n --force bypasses the Docker-heuristic guard and signals\n whatever pidfile+lsof report on the REST port (use when\n the engine was started natively but state file is missing).\n mcp Start standalone MCP shim — opt-in surface for MCP-only clients\n (Cursor, Gemini CLI, etc). REST always available at :3111.\n import-jsonl [p] Import Claude Code JSONL transcripts (default: ~/.claude/projects)\n --max-files <N> | --max-files=<N>: override scan cap (default 200, max 1000;\n out-of-range is rejected; for trees >1000 files, batch by subdirectory)\n\nOptions:\n --help, -h Show this help\n --verbose, -v Show engine stderr, boot log, and diagnostic info\n --reset Wipe ~/.agentmemory/preferences.json and re-run onboarding\n --tools all|core Tool visibility (default: all = ${ALL_TOOLS_COUNT} tools; core = ${CORE_TOOLS_COUNT} essentials)\n --no-engine Skip auto-starting iii-engine\n --port <N> Override REST port (default: 3111). Streams (N+1), viewer\n (N+2), and iii engine (N+46023) auto-derive from N so a\n single flag relocates the whole quartet.\n --instance <N> Shortcut for --port (3111 + N*100) to run multiple\n daemons side-by-side without env gymnastics.\n --instance 1 -> 3211/3212/3213/49234, etc. (max N=50)\n --data-dir <path> Store iii-engine state outside the current repo\n\nEnvironment:\n AGENTMEMORY_URL Full REST base URL (e.g. http://localhost:3111).\n Honored by status, doctor, and MCP shim commands.\n AGENTMEMORY_DATA_DIR State directory fallback when --data-dir is not set.\n AGENTMEMORY_USE_DOCKER=1 Prefer the bundled docker-compose path over the\n native iii-engine binary on first run.\n AGENTMEMORY_III_VERSION Override pinned iii-engine version (default ${IIPINNED_VERSION}).\n AGENTMEMORY_FOLLOWUP_WINDOW_SECONDS\n Window (seconds) for the smart-search follow-up diagnostic\n (default 30). Long values overcount, short values undercount.\n\nQuick start:\n npx @agentmemory/agentmemory # start with local iii-engine or Docker\n npx @agentmemory/agentmemory demo # see semantic recall in 30 seconds\n npx @agentmemory/agentmemory doctor # diagnose config + feature flags\n npx @agentmemory/agentmemory status # health + memory count + flags\n npx @agentmemory/agentmemory upgrade # upgrade agentmemory + iii runtime\n npx @agentmemory/agentmemory mcp # standalone MCP server (no engine)\n npx @agentmemory/mcp # same as above (shim package)\n`);\n process.exit(0);\n}\n\nconst toolsIdx = args.indexOf(\"--tools\");\nif (toolsIdx !== -1 && args[toolsIdx + 1]) {\n const toolsMode = args[toolsIdx + 1]!;\n if (toolsMode !== \"all\" && toolsMode !== \"core\") {\n p.log.warn(\n `Unknown --tools value \"${toolsMode}\" (valid: all, core); falling back to all.`,\n );\n }\n process.env[\"AGENTMEMORY_TOOLS\"] = toolsMode;\n}\n\nconst portIdx = args.indexOf(\"--port\");\nif (portIdx !== -1 && args[portIdx + 1]) {\n process.env[\"III_REST_PORT\"] = args[portIdx + 1];\n}\n\n// `--instance N` picks a 100-port block off the 3111 base so multiple\n// agentmemory daemons can coexist on one host without env-var\n// gymnastics. `--instance 0` keeps the canonical 3111/3112/3113/49134\n// quartet; `--instance 1` → 3211/3212/3213/49234; etc. REST acts as the\n// anchor — streams/viewer/engine derive from it via fixed offsets below\n// unless an env explicitly pins each one.\nconst instanceIdx = args.indexOf(\"--instance\");\nif (instanceIdx !== -1 && args[instanceIdx + 1]) {\n const n = parseInt(args[instanceIdx + 1] || \"\", 10);\n if (Number.isFinite(n) && n >= 0 && n <= 50) {\n const base = 3111 + n * 100;\n if (!process.env[\"III_REST_PORT\"]) {\n process.env[\"III_REST_PORT\"] = String(base);\n }\n }\n}\n\nconst dataDirResolution = resolveDataDir({ args });\nif (dataDirResolution.source !== \"default\") {\n process.env[\"AGENTMEMORY_DATA_DIR\"] = dataDirResolution.dataDir;\n}\n\nconst skipEngine = args.includes(\"--no-engine\");\n\nfunction getRestPort(): number {\n const url = process.env[\"AGENTMEMORY_URL\"];\n if (url) {\n try {\n const parsed = new URL(url).port;\n if (parsed) return parseInt(parsed, 10);\n } catch {}\n }\n return parseInt(process.env[\"III_REST_PORT\"] || \"3111\", 10) || 3111;\n}\n\nfunction getBaseUrl(): string {\n const url = process.env[\"AGENTMEMORY_URL\"];\n if (url) return url.replace(/\\/+$/, \"\");\n return `http://localhost:${getRestPort()}`;\n}\n\nlet discoveredViewerPort: number | null = null;\n\nexport async function discoverViewerPort(): Promise<void> {\n if (discoveredViewerPort !== null) return;\n try {\n const res = await fetch(`${getBaseUrl()}/agentmemory/livez`, {\n signal: AbortSignal.timeout(1000),\n });\n if (res.ok) {\n const data = await res.json() as { viewerPort?: number | null };\n if (typeof data.viewerPort === \"number\") {\n discoveredViewerPort = data.viewerPort;\n }\n }\n } catch {}\n}\n\nfunction getViewerUrl(): string {\n const envUrl = process.env[\"AGENTMEMORY_VIEWER_URL\"];\n if (envUrl) return envUrl.replace(/\\/+$/, \"\");\n \n if (discoveredViewerPort !== null) {\n try {\n const u = new URL(getBaseUrl());\n return `${u.protocol}//${u.hostname}:${discoveredViewerPort}`;\n } catch {\n return `http://localhost:${discoveredViewerPort}`;\n }\n }\n \n try {\n const u = new URL(getBaseUrl());\n const vPort =\n parseInt(process.env[\"III_VIEWER_PORT\"] || \"\", 10) ||\n (parseInt(u.port || \"3111\", 10) || 3111) + 2;\n return `${u.protocol}//${u.hostname}:${vPort}`;\n } catch {\n const vPort =\n parseInt(process.env[\"III_VIEWER_PORT\"] || \"\", 10) ||\n getRestPort() + 2;\n return `http://localhost:${vPort}`;\n }\n}\n\n// WebSocket streams port. Engine writes here; the SDK and viewer\n// subscribe. Honors both `III_STREAM_PORT` (the singular name the\n// engine docs use post-0.11) and `III_STREAMS_PORT` (the name our\n// own config.ts has used since 0.7) so a single source of truth in\n// either form lights up the ready panel. Falls back to REST+1 so\n// `--port 3211` auto-picks 3212 instead of colliding on 3112.\nfunction getStreamPort(): number {\n return (\n parseInt(process.env[\"III_STREAM_PORT\"] || \"\", 10) ||\n parseInt(process.env[\"III_STREAMS_PORT\"] || \"\", 10) ||\n getRestPort() + 1\n );\n}\n\n// Bridge WebSocket port — the iii engine's internal worker bus.\n// Defaults derived from REST as REST+46023 so the canonical 3111\n// anchor yields 49134 and `--port 3211` auto-picks 49234 without a\n// second-instance collision. Overridable via\n// `III_ENGINE_PORT` or the legacy `III_ENGINE_URL=ws://host:port`.\nfunction getEnginePort(): number {\n const explicit = parseInt(process.env[\"III_ENGINE_PORT\"] || \"\", 10);\n if (explicit) return explicit;\n const url = process.env[\"III_ENGINE_URL\"];\n if (url) {\n try {\n const parsed = new URL(url).port;\n if (parsed) return parseInt(parsed, 10);\n } catch {}\n }\n return getRestPort() + 46023;\n}\n\nasync function isEngineRunning(): Promise<boolean> {\n try {\n await fetch(`${getBaseUrl()}/`, {\n signal: AbortSignal.timeout(2000),\n });\n return true;\n } catch {\n return false;\n }\n}\n\nasync function isAgentmemoryReady(): Promise<boolean> {\n try {\n const res = await fetch(`${getBaseUrl()}/agentmemory/livez`, {\n signal: AbortSignal.timeout(2000),\n });\n if (!res.ok) return false;\n try {\n const data = await res.json() as { viewerPort?: number | null; viewerSkipped?: boolean };\n if (typeof data.viewerPort === \"number\") {\n discoveredViewerPort = data.viewerPort;\n return true;\n }\n if (data.viewerSkipped) return true;\n return false;\n } catch {\n return false;\n }\n } catch {\n return false;\n }\n}\n\nfunction findIiiConfig(): string {\n // Precedence (user-overridable wins): explicit env > project cwd >\n // ~/.agentmemory/ > bundled. The bundled config used to win\n // unconditionally, so users hitting the observability log-feedback\n // loop had no way to drop a tamer config in place without\n // editing node_modules.\n const envPath = process.env[\"AGENTMEMORY_III_CONFIG\"];\n const candidates = [\n ...(envPath ? [envPath] : []),\n join(process.cwd(), \"iii-config.yaml\"),\n join(homedir(), \".agentmemory\", \"iii-config.yaml\"),\n join(__dirname, \"iii-config.yaml\"),\n join(__dirname, \"..\", \"iii-config.yaml\"),\n ];\n for (const c of candidates) {\n if (existsSync(c)) return c;\n }\n return \"\";\n}\n\nfunction yamlSingleQuoted(value: string): string {\n return `'${value.replace(/'/g, \"''\")}'`;\n}\n\nfunction renderIiiConfig(template: string, dataDir: string): string {\n return template\n .replace(\n \"file_path: ./data/state_store.db\",\n `file_path: ${yamlSingleQuoted(join(dataDir, \"state_store.db\"))}`,\n )\n .replace(\n \"file_path: ./data/stream_store\",\n `file_path: ${yamlSingleQuoted(join(dataDir, \"stream_store\"))}`,\n );\n}\n\nfunction writeRuntimeIiiConfig(configPath: string, dataDir: string): string {\n mkdirSync(dataDir, { recursive: true });\n const runtimeConfigPath = join(dataDir, \"iii-config.yaml\");\n writeFileSync(\n runtimeConfigPath,\n renderIiiConfig(readFileSync(configPath, \"utf8\"), dataDir),\n );\n return runtimeConfigPath;\n}\n\nfunction warnIfRelocatedDataDir(): void {\n if (!dataDirResolution.relocatedFrom) return;\n\n try {\n mkdirSync(dataDirResolution.dataDir, { recursive: true });\n const marker = join(dataDirResolution.dataDir, \".cwd-relocation-warning\");\n if (existsSync(marker)) return;\n p.log.warn(\n `Default data dir ${dataDirResolution.relocatedFrom} is inside a git worktree; using ${dataDirResolution.dataDir} instead.`,\n );\n writeFileSync(marker, new Date().toISOString());\n } catch {\n p.log.warn(\n `Default data dir ${dataDirResolution.relocatedFrom} is inside a git worktree; using ${dataDirResolution.dataDir} instead.`,\n );\n }\n}\n\nfunction whichBinary(name: string): string | null {\n const cmd = IS_WINDOWS ? \"where\" : \"which\";\n try {\n const out = execFileSync(cmd, [name], {\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n const first = out\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .find((line) => line.length > 0);\n return first ?? null;\n } catch {\n return null;\n }\n}\n\n// Private install location agentmemory manages itself. Sits under the\n// agentmemory state dir (~/.agentmemory/bin) so the pinned engine stays\n// isolated from a user-managed iii on PATH or in ~/.local/bin. A\n// fresh box with iii 0.16.1 already on PATH refused to boot because the\n// hard-pin enforcer told users to overwrite their global install with\n// v0.11.2. Private install resolves the conflict without touching their\n// existing iii.\nfunction agentmemoryBinDir(): string {\n if (IS_WINDOWS) {\n const userProfile = process.env[\"USERPROFILE\"];\n if (!userProfile) return join(homedir(), \".agentmemory\", \"bin\");\n return join(userProfile, \".agentmemory\", \"bin\");\n }\n return join(homedir(), \".agentmemory\", \"bin\");\n}\n\nfunction privateIiiPath(): string {\n return join(agentmemoryBinDir(), IS_WINDOWS ? \"iii.exe\" : \"iii\");\n}\n\nfunction fallbackIiiPaths(): string[] {\n if (IS_WINDOWS) {\n const userProfile = process.env[\"USERPROFILE\"];\n const paths = [privateIiiPath()];\n if (userProfile) {\n paths.push(\n join(userProfile, \".local\", \"bin\", \"iii.exe\"),\n join(userProfile, \"bin\", \"iii.exe\"),\n );\n }\n return paths;\n }\n const home = process.env[\"HOME\"];\n const paths = [privateIiiPath()];\n if (home) {\n paths.push(join(home, \".local\", \"bin\", \"iii\"));\n }\n paths.push(\"/usr/local/bin/iii\");\n return paths;\n}\n\nfunction iiiBinVersion(binPath: string): string | null {\n try {\n const out = execFileSync(binPath, [\"--version\"], {\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n timeout: 3000,\n });\n const match = out.match(/(\\d+\\.\\d+\\.\\d+(?:[-+][\\w.]+)?)/);\n return match ? match[1]! : null;\n } catch {\n return null;\n }\n}\n\n// Resolve a compatible iii binary for the pinned engine version.\n//\n// Soft-warn lets the worker boot against a mismatched engine and crash at\n// runtime (state::list-not-found on v0.13.0+, sandbox-everything trap on\n// v0.11.6+). Hard-pin without a fallback leaves the user stuck — they\n// either downgrade their global iii (breaking other consumers) or set\n// AGENTMEMORY_III_VERSION and hope it works.\n//\n// Instead: when the candidate iii on PATH is the wrong version, prefer\n// the private install under ~/.agentmemory/bin/iii. If the private copy\n// is missing or also mismatched, the caller installs the pinned version\n// there before retrying. AGENTMEMORY_III_VERSION still overrides\n// IIPINNED_VERSION upstream so users who knowingly want a different\n// engine can opt in.\nfunction resolveCompatibleIii(iiiBinPath: string | null | undefined): string | null {\n if (!iiiBinPath) return null;\n const detected = iiiBinVersion(iiiBinPath);\n if (detected && detected === IIPINNED_VERSION) return iiiBinPath;\n\n const privatePath = privateIiiPath();\n if (iiiBinPath !== privatePath && existsSync(privatePath)) {\n const privateVersion = iiiBinVersion(privatePath);\n if (privateVersion === IIPINNED_VERSION) {\n const reason = detected ? `v${detected} mismatches pin` : \"probe failed\";\n vlog(\n `iii at ${iiiBinPath} ${reason} v${IIPINNED_VERSION}; using private install at ${privatePath}.`,\n );\n return privatePath;\n }\n }\n\n return null;\n}\n\nfunction enginePidfilePath(): string {\n return join(homedir(), \".agentmemory\", \"iii.pid\");\n}\n\nfunction engineStatePath(): string {\n return join(homedir(), \".agentmemory\", \"engine-state.json\");\n}\n\ntype EngineState =\n | { kind: \"native\"; configPath: string; attached?: boolean; binPath?: string }\n | { kind: \"docker\"; composeFile: string };\n\nfunction writeEnginePidfile(pid: number): void {\n try {\n const pidPath = enginePidfilePath();\n mkdirSync(dirname(pidPath), { recursive: true });\n writeFileSync(pidPath, `${pid}\\n`, { encoding: \"utf-8\" });\n } catch (err) {\n vlog(`writeEnginePidfile: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n\nfunction readEnginePidfile(): number | null {\n try {\n const pidStr = readFileSync(enginePidfilePath(), \"utf-8\").trim();\n const pid = parseInt(pidStr, 10);\n return Number.isFinite(pid) && pid > 0 ? pid : null;\n } catch {\n return null;\n }\n}\n\nfunction clearEnginePidfile(): void {\n try {\n unlinkSync(enginePidfilePath());\n } catch {}\n}\n\n// Worker pidfile: the agentmemory worker process\n// (`node dist/index.mjs`) is spawned by iii-exec inside the engine. When\n// `agentmemory stop` kills only the engine pid, the worker can survive\n// (detached spawn, signal not propagated, or kept alive by a wrapper\n// script). On the next start, the orphaned worker reconnects to the new\n// engine and shows up as a duplicate registration. We write the worker\n// pid from src/index.ts on boot so stop can find and reap it.\nfunction workerPidfilePath(): string {\n return join(homedir(), \".agentmemory\", \"worker.pid\");\n}\n\nfunction readWorkerPidfile(): number | null {\n try {\n const pidStr = readFileSync(workerPidfilePath(), \"utf-8\").trim();\n const pid = parseInt(pidStr, 10);\n return Number.isFinite(pid) && pid > 0 ? pid : null;\n } catch {\n return null;\n }\n}\n\nfunction clearWorkerPidfile(): void {\n try {\n unlinkSync(workerPidfilePath());\n } catch {}\n}\n\nfunction writeEngineState(state: EngineState): void {\n try {\n const statePath = engineStatePath();\n mkdirSync(dirname(statePath), { recursive: true });\n writeFileSync(statePath, `${JSON.stringify(state)}\\n`, { encoding: \"utf-8\" });\n } catch (err) {\n vlog(`writeEngineState: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n\nfunction readEngineState(): EngineState | null {\n try {\n const raw = readFileSync(engineStatePath(), \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<EngineState>;\n if (parsed && (parsed.kind === \"native\" || parsed.kind === \"docker\")) {\n return parsed as EngineState;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nfunction clearEngineState(): void {\n try {\n unlinkSync(engineStatePath());\n } catch {}\n}\n\nfunction discoverComposeFile(): string | null {\n const candidates = [\n join(__dirname, \"..\", \"docker-compose.yml\"),\n join(__dirname, \"docker-compose.yml\"),\n join(process.cwd(), \"docker-compose.yml\"),\n ];\n return candidates.find((c) => existsSync(c)) ?? null;\n}\n\nfunction isInvokedViaNpx(): boolean {\n if (process.env[\"npm_lifecycle_event\"] === \"npx\") return true;\n const argv1 = process.argv[1] ?? \"\";\n if (argv1.includes(\"_npx\")) return true;\n const ua = process.env[\"npm_config_user_agent\"] ?? \"\";\n if (ua.startsWith(\"npm/\") || ua.includes(\" npm/\")) return true;\n return false;\n}\n\n// First-run global-install prompt. Replaces the previous passive\n// `p.log.info` hint that users ignored — typing `agentmemory stop`\n// in a new shell would then 404 with `command not found`. We now\n// ask once, persist the answer in preferences, and never ask again.\nasync function maybeOfferGlobalInstall(): Promise<void> {\n if (!isInvokedViaNpx()) return;\n if (!process.stdin.isTTY) return;\n if (process.env[\"CI\"]) return;\n const prefs = readPrefs();\n if (prefs.skipGlobalInstall || prefs.skipNpxHint) return;\n\n const answer = await p.confirm({\n message:\n \"Install agentmemory globally so the bare `agentmemory` command works in any shell? [Y/n]\",\n initialValue: true,\n });\n if (p.isCancel(answer)) {\n // Treat Ctrl+C as \"not now\" rather than \"never\". Don't persist.\n return;\n }\n if (answer === false) {\n writePrefs({ skipGlobalInstall: true });\n p.log.info(\n \"Skipped. Re-run via `npx @agentmemory/agentmemory` or install later with: npm install -g @agentmemory/agentmemory\",\n );\n return;\n }\n\n const npmBin = whichBinary(\"npm\");\n if (!npmBin) {\n p.log.warn(\n \"npm not found on PATH. Install manually: npm install -g @agentmemory/agentmemory\",\n );\n return;\n }\n const ok = runCommand(\n npmBin,\n [\"install\", \"-g\", `@agentmemory/agentmemory@${VERSION}`],\n { label: `Installing @agentmemory/agentmemory@${VERSION} globally` },\n );\n if (ok) {\n p.log.success(\n \"Installed globally. `agentmemory stop` etc. will now work in new shells.\",\n );\n // Persist so we never re-prompt even if the user happens to npx\n // again from a CI-less TTY.\n writePrefs({ skipGlobalInstall: true });\n } else {\n p.log.warn(\n \"Global install failed. Try manually: npm install -g @agentmemory/agentmemory\",\n );\n }\n}\n\n// iii-console install state.\n// \"installed\" — `iii-console` is on PATH or at `~/.local/bin/iii-console`\n// \"missing\" — binary not found anywhere we look\n// We deliberately do NOT probe the console's HTTP port: the binary\n// being on disk is the signal we care about (it's not auto-started by\n// agentmemory and its default port 3113 collides with our viewer, so\n// \"is it listening?\" is the wrong question at boot time).\ntype IiiConsoleState =\n | { kind: \"installed\"; binPath: string }\n | { kind: \"missing\" };\n\nfunction detectIiiConsole(): IiiConsoleState {\n const onPath = whichBinary(\"iii-console\");\n if (onPath) return { kind: \"installed\", binPath: onPath };\n const fallback = IS_WINDOWS\n ? join(process.env[\"USERPROFILE\"] ?? \"\", \".local\", \"bin\", \"iii-console.exe\")\n : join(homedir(), \".local\", \"bin\", \"iii-console\");\n if (fallback && existsSync(fallback)) {\n return { kind: \"installed\", binPath: fallback };\n }\n return { kind: \"missing\" };\n}\n\n// The upstream install script reads `VERSION` as an env var (see\n// install.iii.dev/iii/main/install.sh: `engine_version=\"${VERSION:-}\"`).\n// Pin to IIPINNED_VERSION so a fresh boot can never pull a newer iii\n// console that talks a different protocol than our pinned engine\n// (root cause of protocol drift).\nconst III_CONSOLE_INSTALL_CMD =\n `curl -fsSL https://install.iii.dev/iii/main/install.sh | VERSION=${IIPINNED_VERSION} sh`;\n\n// Display-only renderer. The internal `runCommand(shBin, [\"-c\", ...])`\n// path uses III_CONSOLE_INSTALL_CMD verbatim (POSIX shell). Anywhere\n// that PRINTS the command to a user has to handle Windows separately\n// since `VERSION=X sh` and the pipe-to-sh idiom aren't valid in\n// cmd.exe / PowerShell.\nfunction iiiConsoleInstallHint(): string {\n if (!IS_WINDOWS) return III_CONSOLE_INSTALL_CMD;\n return (\n `# PowerShell:\\n` +\n ` $env:VERSION = \"${IIPINNED_VERSION}\"\\n` +\n ` iwr -useb https://install.iii.dev/iii/main/install.sh -OutFile install.sh\\n` +\n ` bash install.sh # WSL or Git Bash required\\n` +\n `# Or grab the pinned release directly:\\n` +\n ` https://github.com/iii-hq/iii/releases/tag/iii%2Fv${IIPINNED_VERSION}`\n );\n}\n\nasync function ensureIiiConsole(): Promise<IiiConsoleState> {\n const state = detectIiiConsole();\n if (state.kind === \"installed\") return state;\n\n // Non-interactive contexts get the panel hint but no prompt.\n if (!process.stdin.isTTY || process.env[\"CI\"]) return state;\n const prefs = readPrefs();\n if (prefs.skipConsoleInstall) return state;\n\n const answer = await p.confirm({\n message:\n \"iii console gives engine-level visibility (workers, functions, queues, traces). Install now?\",\n initialValue: true,\n });\n if (p.isCancel(answer)) return state;\n if (answer === false) {\n writePrefs({ skipConsoleInstall: true });\n return state;\n }\n\n const shBin = whichBinary(\"sh\");\n const curlBin = whichBinary(\"curl\");\n if (!shBin || !curlBin) {\n p.log.warn(\n `curl or sh not found. Install manually:\\n ${iiiConsoleInstallHint()}`,\n );\n return state;\n }\n const ok = runCommand(shBin, [\"-c\", III_CONSOLE_INSTALL_CMD], {\n label: \"Installing iii console\",\n });\n if (!ok) {\n p.log.warn(\n `iii console install failed. Re-run manually:\\n ${iiiConsoleInstallHint()}`,\n );\n return state;\n }\n // Re-detect rather than trust install-script output paths.\n return detectIiiConsole();\n}\n\nfunction adoptRunningEngine(): void {\n try {\n const existingState = readEngineState();\n const existingPid = readEnginePidfile();\n if (existingState && existingPid) return;\n\n const pids = findEnginePidsByPort(getRestPort());\n const enginePid = pids[0];\n if (enginePid) {\n // A Docker-forwarded port is held by the VM/proxy process\n // (com.docker.backend, vpnkit, ...), not the engine. Adopting it\n // as kind:\"native\" would make a later `stop` SIGTERM that process.\n const comm = pidCommand(enginePid);\n if (isForeignPortHolder(comm)) {\n vlog(\n `adoptRunningEngine: refusing to adopt pid ${enginePid} (${comm}) — not the iii engine binary`,\n );\n return;\n }\n }\n if (enginePid && !existingPid) {\n writeEnginePidfile(enginePid);\n }\n if (!existingState) {\n writeEngineState({\n kind: \"native\",\n configPath: findIiiConfig() || \"\",\n attached: true,\n });\n }\n if (enginePid && !existingPid) {\n p.log.info(c.ok(`Attached to existing iii-engine (pid ${enginePid})`));\n }\n } catch (err) {\n vlog(`adoptRunningEngine: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n\nasync function runIiiInstaller(): Promise<{ ok: boolean; binPath: string | null }> {\n const releaseUrl = iiiReleaseUrl();\n const asset = iiiReleaseAsset();\n const isZipAsset = asset?.endsWith(\".zip\") === true;\n\n if (!releaseUrl) {\n p.log.warn(\n `iii-engine binary not available for ${platform()}/${process.arch}. Use Docker (\\`docker pull iiidev/iii:${IIPINNED_VERSION}\\`) or download manually from https://github.com/iii-hq/iii/releases/tag/iii%2Fv${IIPINNED_VERSION}.`,\n );\n return { ok: false, binPath: null };\n }\n\n if (IS_WINDOWS || isZipAsset) {\n p.log.info(\n `Auto-install unavailable on ${platform()} — ${asset} isn't tar-compatible. Install manually:\\n` +\n ` 1. Download ${releaseUrl}\\n` +\n ` 2. Extract iii.exe and place it on PATH (e.g. %USERPROFILE%\\\\.local\\\\bin)\\n` +\n `Or use Docker: docker pull iiidev/iii:${IIPINNED_VERSION}`,\n );\n return { ok: false, binPath: null };\n }\n\n const shBin = whichBinary(\"sh\");\n const curlBin = whichBinary(\"curl\");\n if (!shBin || !curlBin) {\n p.log.warn(\"curl or sh not found. Cannot auto-install iii-engine.\");\n return { ok: false, binPath: null };\n }\n\n const binDir = agentmemoryBinDir();\n const binPath = privateIiiPath();\n const installCmd = [\n `mkdir -p \"${binDir}\"`,\n `curl -fsSL \"${releaseUrl}\" | tar -xz -C \"${binDir}\"`,\n `chmod +x \"${binPath}\"`,\n ].join(\" && \");\n const installerOk = runCommand(shBin, [\"-c\", installCmd], {\n label: `Installing iii-engine v${IIPINNED_VERSION} (pinned)`,\n optional: true,\n });\n if (!installerOk) {\n p.log.warn(\n `iii-engine installer failed. Fallbacks: Docker (\\`docker pull iiidev/iii:${IIPINNED_VERSION}\\`) or download manually from https://github.com/iii-hq/iii/releases/tag/iii%2Fv${IIPINNED_VERSION}.`,\n );\n return { ok: false, binPath: null };\n }\n return { ok: true, binPath };\n}\n\ntype StartupFailure = {\n kind: \"no-engine\" | \"no-docker-compose\" | \"engine-crashed\" | \"docker-crashed\";\n stderr?: string;\n binary?: string;\n};\n\nlet startupFailure: StartupFailure | null = null;\n\n// Spawn a background engine and collect any startup stderr for a short\n// window. The process is unref'd so the CLI parent can exit cleanly; we\n// only care about stderr that shows up BEFORE the health check succeeds,\n// which is what surfaces early crash/config-parse errors on all platforms.\nfunction spawnEngineBackground(\n bin: string,\n spawnArgs: string[],\n label: string,\n): ChildProcess {\n vlog(`spawn: ${bin} ${spawnArgs.join(\" \")}`);\n const child = spawn(bin, spawnArgs, {\n detached: true,\n stdio: [\"ignore\", \"ignore\", \"pipe\"],\n windowsHide: true,\n });\n const isDocker = label.includes(\"Docker\");\n if (!isDocker && typeof child.pid === \"number\") {\n writeEnginePidfile(child.pid);\n }\n const stderrChunks: Buffer[] = [];\n let stderrBytes = 0;\n const MAX_STDERR_CAPTURE = 16 * 1024;\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n if (stderrBytes >= MAX_STDERR_CAPTURE) return;\n const slice = chunk.subarray(0, MAX_STDERR_CAPTURE - stderrBytes);\n stderrChunks.push(slice);\n stderrBytes += slice.length;\n });\n child.on(\"exit\", (code, signal) => {\n const abnormal =\n (code !== null && code !== 0) || (code === null && signal !== null);\n if (abnormal) {\n const stderr = Buffer.concat(stderrChunks).toString(\"utf-8\");\n startupFailure = {\n kind: isDocker ? \"docker-crashed\" : \"engine-crashed\",\n stderr:\n stderr.trim() ||\n (signal\n ? `process killed by signal ${signal}`\n : `process exited with code ${code}`),\n binary: bin,\n };\n vlog(`engine exited early: code=${code} signal=${signal}`);\n if (IS_VERBOSE && stderr.trim()) {\n p.log.error(`engine stderr:\\n${stderr}`);\n }\n if (!isDocker) clearEnginePidfile();\n clearEngineState();\n }\n });\n child.unref();\n return child;\n}\n\nfunction startIiiBin(iiiBin: string, configPath: string): boolean {\n const s = p.spinner();\n s.start(`Starting iii-engine: ${iiiBin}`);\n writeEngineState({ kind: \"native\", configPath, binPath: iiiBin });\n spawnEngineBackground(iiiBin, [\"--config\", configPath], \"iii-engine\");\n s.stop(c.ok(\"iii-engine process started\"));\n return true;\n}\n\n// Find a pinned-compatible iii path from a list of candidates. Returns\n// the first candidate whose --version matches the pin, OR returns the\n// private install path if it exists and matches, OR null if no candidate\n// is compatible. Caller (startEngine) auto-installs the pin to the\n// private path when this returns null.\nfunction pickCompatibleIii(candidates: Array<string | null | undefined>): string | null {\n for (const c of candidates) {\n if (!c) continue;\n const resolved = resolveCompatibleIii(c);\n if (resolved) return resolved;\n }\n return null;\n}\n\nasync function startEngine(): Promise<boolean> {\n const configPath = findIiiConfig();\n warnIfRelocatedDataDir();\n const runtimeConfigPath = configPath\n ? writeRuntimeIiiConfig(configPath, dataDirResolution.dataDir)\n : \"\";\n const pathIii = whichBinary(\"iii\");\n vlog(`iii binary: ${pathIii ?? \"(not on PATH)\"}, config: ${runtimeConfigPath || \"(not found)\"}`);\n\n const fallbacks = fallbackIiiPaths().filter((p) => existsSync(p));\n for (const f of fallbacks) {\n const v = iiiBinVersion(f);\n vlog(`fallback iii at ${f} reports version: ${v ?? \"unknown\"}`);\n }\n\n let iiiBin = pickCompatibleIii([pathIii, ...fallbacks]);\n\n if (iiiBin && runtimeConfigPath) {\n if (iiiBin !== pathIii) {\n p.log.info(`Using iii at: ${c.dim(iiiBin)} (v${c.accent(IIPINNED_VERSION)})`);\n process.env[\"PATH\"] = `${dirname(iiiBin)}${PATH_DELIMITER}${process.env[\"PATH\"] ?? \"\"}`;\n }\n return startIiiBin(iiiBin, runtimeConfigPath);\n }\n\n if (pathIii && !iiiBin) {\n const detected = iiiBinVersion(pathIii);\n vlog(\n `iii on PATH is v${detected ?? \"unknown\"}, pin is v${IIPINNED_VERSION}. ` +\n `Will install pinned engine to ${privateIiiPath()}.`,\n );\n }\n\n if (!configPath) {\n startupFailure = { kind: \"no-engine\" };\n return false;\n }\n\n const dockerBin = whichBinary(\"docker\");\n vlog(`docker binary: ${dockerBin ?? \"(not on PATH)\"}`);\n mkdirSync(dataDirResolution.dataDir, { recursive: true });\n const dockerComposeCandidates = [\n join(__dirname, \"..\", \"docker-compose.yml\"),\n join(__dirname, \"docker-compose.yml\"),\n join(process.cwd(), \"docker-compose.yml\"),\n ];\n const composeFile = dockerComposeCandidates.find((c) => existsSync(c));\n vlog(`docker-compose.yml: ${composeFile ?? \"(not found)\"}`);\n\n const dockerOptIn =\n process.env[\"AGENTMEMORY_USE_DOCKER\"] === \"1\" ||\n process.env[\"AGENTMEMORY_USE_DOCKER\"] === \"true\";\n const interactive = !!process.stdin.isTTY && !process.env[\"CI\"];\n\n type Choice = \"install\" | \"docker\" | \"manual\";\n let choice: Choice;\n\n // Wrong-version iii on PATH is a configuration trap: any prompt would\n // confuse the user since they already \"have iii installed\". Skip the\n // prompt and auto-install pinned engine to the private location.\n const pathIiiMismatch = pathIii !== null && resolveCompatibleIii(pathIii) === null;\n\n if (dockerOptIn && dockerBin && composeFile) {\n choice = \"docker\";\n } else if (pathIiiMismatch) {\n choice = \"install\";\n const detected = iiiBinVersion(pathIii!);\n p.log.info(\n `iii on PATH is v${detected ?? \"unknown\"} but agentmemory pins v${IIPINNED_VERSION}. ` +\n `Installing pinned engine to ~/.agentmemory/bin (leaves your existing iii untouched).`,\n );\n } else if (!interactive) {\n choice = \"install\";\n p.log.info(\"Non-interactive environment detected — auto-installing iii-engine.\");\n } else {\n p.log.warn(`iii-engine binary not found locally.`);\n const options: { value: Choice; label: string; hint?: string }[] = [\n {\n value: \"install\",\n label: `Install iii v${IIPINNED_VERSION} to ~/.agentmemory/bin (~6MB, ~5s)`,\n hint: \"recommended\",\n },\n ];\n if (dockerBin && composeFile) {\n options.push({ value: \"docker\", label: \"Use Docker compose\", hint: \"advanced\" });\n }\n options.push({ value: \"manual\", label: \"Show manual install steps and exit\" });\n\n const picked = await p.select<Choice>({\n message: \"How would you like to start iii-engine?\",\n options,\n initialValue: \"install\",\n });\n if (p.isCancel(picked)) {\n startupFailure = { kind: \"no-engine\" };\n return false;\n }\n choice = picked;\n }\n\n if (choice === \"manual\") {\n startupFailure = { kind: \"no-engine\" };\n return false;\n }\n\n if (choice === \"install\") {\n const result = await runIiiInstaller();\n if (result.ok && result.binPath) {\n process.env[\"PATH\"] = `${dirname(result.binPath)}${PATH_DELIMITER}${process.env[\"PATH\"] ?? \"\"}`;\n iiiBin = result.binPath;\n return startIiiBin(iiiBin, configPath);\n }\n if (dockerBin && composeFile && interactive) {\n const fallback = await p.confirm({\n message: \"Auto-install failed. Try Docker compose instead?\",\n initialValue: true,\n });\n if (p.isCancel(fallback) || fallback !== true) {\n startupFailure = { kind: \"no-engine\" };\n return false;\n }\n choice = \"docker\";\n } else {\n startupFailure = { kind: \"no-engine\" };\n return false;\n }\n }\n\n if (choice === \"docker\" && dockerBin && composeFile) {\n const s = p.spinner();\n s.start(\"Starting iii-engine via Docker...\");\n writeEngineState({ kind: \"docker\", composeFile });\n spawnEngineBackground(\n dockerBin,\n [\"compose\", \"-f\", composeFile, \"up\", \"-d\"],\n \"iii-engine via Docker\",\n );\n s.stop(\"Docker compose started\");\n return true;\n }\n\n if (!composeFile && dockerBin) {\n startupFailure = { kind: \"no-docker-compose\" };\n } else {\n startupFailure = { kind: \"no-engine\" };\n }\n return false;\n}\n\nasync function waitForEngine(timeoutMs: number): Promise<boolean> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n if (await isEngineRunning()) return true;\n await new Promise((r) => setTimeout(r, 500));\n }\n return false;\n}\n\nfunction installInstructions(): string[] {\n const releaseUrl = iiiReleaseUrl();\n if (IS_WINDOWS) {\n return [\n `agentmemory needs iii-engine v${IIPINNED_VERSION}. Pick one:`,\n \"\",\n \" A) Download the prebuilt Windows binary:\",\n ` 1. Open https://github.com/iii-hq/iii/releases/tag/iii%2Fv${IIPINNED_VERSION}`,\n ` 2. Download iii-x86_64-pc-windows-msvc.zip (or iii-aarch64-pc-windows-msvc.zip on ARM)`,\n \" 3. Extract iii.exe to %USERPROFILE%\\\\.local\\\\bin\\\\iii.exe (or add to PATH)\",\n \" 4. Re-run: npx @agentmemory/agentmemory\",\n \"\",\n ` B) Docker: docker pull iiidev/iii:${IIPINNED_VERSION}`,\n \" Re-run with AGENTMEMORY_USE_DOCKER=1 npx @agentmemory/agentmemory\",\n \"\",\n \"Or skip the engine entirely (standalone MCP): npx @agentmemory/agentmemory mcp\",\n \"\",\n \"Docs: https://iii.dev/docs\",\n ];\n }\n const linuxInstall = releaseUrl\n ? ` A) mkdir -p ~/.agentmemory/bin && curl -fsSL \"${releaseUrl}\" | tar -xz -C ~/.agentmemory/bin && chmod +x ~/.agentmemory/bin/iii`\n : ` A) Manual download: https://github.com/iii-hq/iii/releases/tag/iii%2Fv${IIPINNED_VERSION}`;\n return [\n `agentmemory needs iii-engine v${IIPINNED_VERSION}. Pick one:`,\n \"\",\n linuxInstall,\n \" Then re-run: npx @agentmemory/agentmemory\",\n \"\",\n ` B) Docker: docker pull iiidev/iii:${IIPINNED_VERSION}`,\n \" Re-run with AGENTMEMORY_USE_DOCKER=1 npx @agentmemory/agentmemory\",\n \"\",\n \"Or skip the engine entirely (standalone MCP): npx @agentmemory/agentmemory mcp\",\n \"\",\n \"Docs: https://iii.dev/docs\",\n ];\n}\n\nfunction portInUseDiagnostic(port: number): string {\n return IS_WINDOWS\n ? ` netstat -ano | findstr :${port}`\n : ` lsof -i :${port} # or: ss -tlnp | grep :${port}`;\n}\n\nasync function waitForAgentmemoryReady(timeoutMs: number): Promise<boolean> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n if (await isAgentmemoryReady()) return true;\n await new Promise((r) => setTimeout(r, 250));\n }\n return false;\n}\n\n// Derive a host string for the streams/engine WebSocket lines from\n// the configured engine URL (`III_ENGINE_URL`) or REST base\n// (`AGENTMEMORY_URL`) so a remote-bind setup like\n// `III_ENGINE_URL=ws://my-host:49134` doesn't print misleading\n// localhost addresses. Falls back to localhost.\nfunction getEngineHost(): string {\n for (const envKey of [\"III_ENGINE_URL\", \"AGENTMEMORY_URL\"]) {\n const raw = process.env[envKey];\n if (!raw) continue;\n try {\n const parsed = new URL(raw);\n if (parsed.hostname) return parsed.hostname;\n } catch {}\n }\n return \"localhost\";\n}\n\nfunction printReadyHint(consoleState: IiiConsoleState): void {\n // REST goes through getBaseUrl which already honors AGENTMEMORY_URL\n // for full host+protocol overrides. Streams/Engine are derived from\n // III_ENGINE_URL so a remote bind reads correctly in the panel.\n const restUrl = getBaseUrl();\n const viewerUrl = getViewerUrl();\n const engineHost = getEngineHost();\n const streamUrl = `ws://${engineHost}:${getStreamPort()}`;\n const engineUrl = `ws://${engineHost}:${getEnginePort()}`;\n\n const consoleLine =\n consoleState.kind === \"installed\"\n ? // We can't safely probe iii-console's port (default 3113\n // collides with our viewer) so we surface the binary location\n // and let the user start it on a port of their choice. Use\n // the detected binary path so `(run: ...)` is executable as-\n // is, even when the binary isn't on PATH under the bare\n // name `iii-console`.\n `${c.label(\"iii console\")} ${c.dim(consoleState.binPath)} ${c.dim(`(run: ${consoleState.binPath} -p <port>)`)}`\n : `${c.label(\"iii console\")} ${c.dim(`(install: ${iiiConsoleInstallHint()})`)}`;\n\n const lines = [\n `${c.label(\"REST API\")} ${c.url(restUrl)}`,\n `${c.label(\"Viewer\")} ${c.url(viewerUrl)}`,\n `${c.label(\"Streams\")} ${c.url(streamUrl)}`,\n `${c.label(\"Engine\")} ${c.url(engineUrl)}`,\n consoleLine,\n ];\n // p.note renders a bordered panel with a title — same affordance\n // used elsewhere in this CLI for \"Troubleshooting\" / \"Setup\n // required\" blocks, so the visual language stays consistent.\n p.note(lines.join(\"\\n\"), `agentmemory v${c.accent(VERSION)}`);\n\n // Pick a runnable form for the suggested next-step. Users invoked\n // via `npx` don't have the bare `agentmemory` command on PATH yet\n // (unless they accepted the global-install prompt and the npm bin\n // dir was already on PATH in this shell), so we suggest the npx\n // form for them; everyone else gets the global form.\n const demoCommand = isInvokedViaNpx()\n ? \"npx @agentmemory/agentmemory demo\"\n : \"agentmemory demo\";\n process.stdout.write(`\\n${c.dim(\"Try:\")} ${c.cmd(demoCommand)}\\n`);\n}\n\nasync function main() {\n // Booting a second instance next to a live daemon registers a duplicate\n // worker on the running engine, and on iii 0.11.2 the second instance's\n // shutdown tears down the daemon's HTTP trigger routing (every\n // /agentmemory/* route 404s until a full engine restart). Refuse instead.\n // A different --instance resolves to a different port, so multi-instance\n // setups are unaffected.\n try {\n const probe = await fetch(`${getBaseUrl()}/agentmemory/livez`, {\n signal: AbortSignal.timeout(1500),\n });\n if (probe.ok) {\n p.log.error(\n `agentmemory is already running on port ${getRestPort()}. Starting a second instance here would corrupt the running daemon's REST routing. Use the REST API (or the MCP tools) against the running instance, run a different --instance, or stop it first with \\`agentmemory stop\\`.`,\n );\n process.exit(1);\n }\n } catch {\n // no live daemon on this port; boot normally\n }\n\n // `--reset` wipes preferences before anything else so the onboarding\n // flow below always runs fresh.\n if (IS_RESET) {\n resetPrefs();\n }\n\n const firstRun = isFirstRun();\n const prefs = readPrefs();\n // Show the splash on the first run, on --reset, or whenever the user\n // hasn't yet opted out via the schema (we set `skipSplash: true`\n // after onboarding completes). Verbose runs always splash since the\n // user explicitly asked for the chatty experience.\n if (firstRun || IS_RESET || IS_VERBOSE || !prefs.skipSplash) {\n renderSplash(VERSION);\n }\n\n if (firstRun || IS_RESET) {\n await runOnboarding();\n }\n\n if (skipEngine) {\n if (IS_VERBOSE) p.log.info(\"Skipping engine check (--no-engine)\");\n await import(\"./index.js\");\n if (await waitForAgentmemoryReady(15000)) {\n const consoleState = await ensureIiiConsole();\n await maybeOfferGlobalInstall();\n printReadyHint(consoleState);\n }\n return;\n }\n\n if (await isEngineRunning()) {\n if (IS_VERBOSE) p.log.success(\"iii-engine is running\");\n // Prefer the binary path persisted at launch time over whatever's on\n // PATH now. PATH lookups misfire when a global iii install gets added\n // after agentmemory started (or when the running engine was launched\n // from a path that's no longer first on PATH).\n const persisted = readEngineState();\n const persistedBin =\n persisted?.kind === \"native\" && persisted.binPath && existsSync(persisted.binPath)\n ? persisted.binPath\n : null;\n const attachedBin =\n persistedBin ??\n whichBinary(\"iii\") ??\n fallbackIiiPaths().find((p) => existsSync(p)) ??\n null;\n const detected = attachedBin ? iiiBinVersion(attachedBin) : null;\n\n // Fail closed: only adopt the running engine when we can positively\n // confirm it is the pinned version. An unknown version (detected === null,\n // e.g. the binary can't be version-probed) is treated as incompatible —\n // adopting a foreign or unverifiable engine hangs the worker in a\n // WebSocket reconnect loop. Worst case here is a re-run that reinstalls\n // the pinned engine, never a silent loop.\n if (detected === IIPINNED_VERSION) {\n adoptRunningEngine();\n await import(\"./index.js\");\n if (await waitForAgentmemoryReady(15000)) {\n const consoleState = await ensureIiiConsole();\n await maybeOfferGlobalInstall();\n printReadyHint(consoleState);\n }\n return;\n }\n\n const detectedLabel = detected ? `v${detected}` : \"an unverified version\";\n\n // An incompatible engine owns the port. Adopting it hangs the worker in a\n // WebSocket reconnect loop (it can't speak that engine's protocol), so stop\n // with the simplest honest remedy. A normal user has no other engine and\n // never sees this; only someone running their own iii does, and for them\n // \"stop it, then run normally\" is the fix. We do not suggest a different\n // engine version: agentmemory only supports v${IIPINNED_VERSION}.\n const base = isInvokedViaNpx() ? \"npx @agentmemory/agentmemory\" : \"agentmemory\";\n p.log.error(\n `Another iii-engine (${detectedLabel}) is running on port ${getEnginePort()}, and agentmemory needs its own pinned v${IIPINNED_VERSION}.`,\n );\n p.note(\n [\n `agentmemory only supports iii-engine v${IIPINNED_VERSION}. It will not adopt or change the running engine (${detectedLabel}).`,\n \"\",\n c.label(\"Switch to the pinned engine in two steps:\"),\n \"\",\n ` 1. Stop the running engine:`,\n ` ${c.cmd(`${base} stop --force`)}`,\n ` ${c.dim(`(or stop your own iii however you started it — agentmemory leaves your global iii untouched)`)}`,\n \"\",\n ` 2. Start agentmemory. It downloads and runs the pinned`,\n ` v${IIPINNED_VERSION} into ~/.agentmemory/bin automatically:`,\n ` ${c.cmd(base)}`,\n \"\",\n c.dim(`Step 2 needs no manual install. To install iii v${IIPINNED_VERSION} yourself (replaces your global iii), curl:`),\n ` ${c.cmd(III_CONSOLE_INSTALL_CMD)}`,\n ` ${c.dim(\"or download the release:\")} ${c.url(`https://github.com/iii-hq/iii/releases/tag/iii%2Fv${IIPINNED_VERSION}`)}`,\n ].join(\"\\n\"),\n \"engine conflict\",\n );\n process.exit(1);\n }\n\n const started = await startEngine();\n if (!started) {\n p.log.error(\"Could not start iii-engine.\");\n const lines = installInstructions();\n if (startupFailure?.kind === \"no-docker-compose\") {\n lines.unshift(\n \"Docker is installed but docker-compose.yml is missing from this\",\n \"install. Re-install with: npm install -g @agentmemory/agentmemory\",\n \"\",\n );\n }\n p.note(lines.join(\"\\n\"), \"Setup required\");\n process.exit(1);\n }\n\n const s = p.spinner();\n s.start(\"Waiting for iii-engine to be ready...\");\n\n const ready = await waitForEngine(15000);\n if (!ready) {\n const port = getRestPort();\n s.stop(\"iii-engine did not become ready within 15s\");\n\n if (startupFailure?.kind === \"engine-crashed\" || startupFailure?.kind === \"docker-crashed\") {\n p.log.error(\"The iii-engine process crashed on startup.\");\n if (startupFailure.binary) {\n p.log.info(`Binary: ${startupFailure.binary}`);\n }\n if (startupFailure.stderr) {\n p.note(startupFailure.stderr, \"engine stderr\");\n } else {\n p.log.info(\"No stderr was captured. Re-run with --verbose for more detail.\");\n }\n p.note(\n [\n \"Common causes:\",\n ` - iii-engine version mismatch — reinstall the pinned v${IIPINNED_VERSION} binary`,\n \" (sh script on macOS/Linux, GitHub release zip on Windows)\",\n \" - Docker Desktop not running (if you're using the Docker path)\",\n \" - Port already in use (see below)\",\n \"\",\n \"See https://iii.dev/docs for current install instructions.\",\n ].join(\"\\n\"),\n \"Troubleshooting\",\n );\n } else {\n p.log.error(\"The engine process started but the REST API never responded.\");\n p.note(\n [\n `Check whether port ${port} is already bound by another process:`,\n portInUseDiagnostic(port),\n \"\",\n \"If it is, free the port or override: agentmemory --port <N>\",\n \"\",\n \"If it isn't, a firewall may be blocking 127.0.0.1:\" + port + \".\",\n \"Re-run with --verbose to see engine stderr.\",\n ].join(\"\\n\"),\n \"Troubleshooting\",\n );\n }\n process.exit(1);\n }\n\n s.stop(c.ok(\"iii-engine is ready\"));\n await import(\"./index.js\");\n if (await waitForAgentmemoryReady(15000)) {\n const consoleState = await ensureIiiConsole();\n await maybeOfferGlobalInstall();\n printReadyHint(consoleState);\n }\n // Mark splash as something to skip on subsequent runs. This is a\n // no-op if onboarding already flipped the flag (idempotent merge).\n writePrefs({ skipSplash: true });\n}\n\nasync function apiFetch<T = unknown>(base: string, path: string, timeoutMs = 5000): Promise<T | null> {\n try {\n const headers: Record<string, string> = {};\n const secret = process.env[\"AGENTMEMORY_SECRET\"];\n if (secret) headers[\"Authorization\"] = `Bearer ${secret}`;\n const res = await fetch(`${base}/agentmemory/${path}`, {\n signal: AbortSignal.timeout(timeoutMs),\n headers,\n });\n return (await res.json()) as T;\n } catch {\n return null;\n }\n}\n\nasync function runStatus() {\n const port = getRestPort();\n const base = getBaseUrl();\n p.intro(\"agentmemory status\");\n\n const up = await isEngineRunning();\n if (!up) {\n p.log.error(`Not running — no response at ${base}`);\n p.log.info(\"Start with: npx @agentmemory/agentmemory\");\n process.exit(1);\n }\n\n try {\n const [healthRes, sessionsRes, graphRes, memoriesRes, flagsRes, followupRes] = await Promise.all([\n apiFetch<any>(base, \"health\"),\n apiFetch<any>(base, \"sessions\"),\n apiFetch<any>(base, \"graph/stats\"),\n apiFetch<any>(base, \"memories?count=true\"),\n apiFetch<any>(base, \"config/flags\"),\n apiFetch<any>(base, \"diagnostics/followup\"),\n ]);\n\n if (typeof healthRes?.viewerPort === \"number\") {\n discoveredViewerPort = healthRes.viewerPort;\n }\n const h = healthRes?.health;\n const status = healthRes?.status || \"unknown\";\n const version = healthRes?.version || \"?\";\n const sessionList = Array.isArray(sessionsRes?.sessions) ? sessionsRes.sessions : [];\n const sessions = sessionList.length;\n const nodes = Number(graphRes?.totalNodes ?? graphRes?.nodes ?? graphRes?.nodeCount ?? 0);\n const edges = Number(graphRes?.totalEdges ?? graphRes?.edges ?? graphRes?.edgeCount ?? 0);\n const cb = healthRes?.circuitBreaker?.state || \"closed\";\n const heapMB = h?.memory ? Math.round(h.memory.heapUsed / 1048576) : 0;\n const uptime = h?.uptimeSeconds ? Math.round(h.uptimeSeconds) : 0;\n\n const obsCount = sessionList.reduce(\n (sum: number, s: any) => sum + (Number(s?.observationCount) || 0),\n 0,\n );\n const memCount = Number(memoriesRes?.latestCount ?? memoriesRes?.total ?? 0) || 0;\n const estFullTokens = obsCount * 80;\n const estInjectedTokens = Math.min(obsCount, 50) * 38;\n const tokensSaved = estFullTokens - estInjectedTokens;\n const pctSaved = estFullTokens > 0 ? Math.round((tokensSaved / estFullTokens) * 100) : 0;\n\n p.log.success(`Connected — v${version} at ${base}`);\n\n const lines = [\n `Health: ${status === \"healthy\" ? pc.green(\"✓ healthy\") : pc.yellow(status)}`,\n `Sessions: ${sessions}`,\n `Observations: ${obsCount}`,\n `Memories: ${memCount}`,\n `Graph: ${nodes} nodes, ${edges} edges`,\n `Circuit: ${cb}`,\n `Heap: ${heapMB} MB`,\n `Uptime: ${uptime}s`,\n `Viewer: ${c.url(getViewerUrl())}`,\n ];\n\n if (obsCount > 0) {\n lines.push(\"\");\n lines.push(`Token savings: ~${tokensSaved.toLocaleString()} tokens saved (${pctSaved}% reduction)`);\n lines.push(` Full context: ~${estFullTokens.toLocaleString()} tokens`);\n lines.push(` Injected: ~${estInjectedTokens.toLocaleString()} tokens`);\n }\n\n if (flagsRes) {\n const provider = flagsRes.provider === \"llm\" ? pc.green(\"✓ llm\") : pc.yellow(\"✗ noop (no key)\");\n const embed = flagsRes.embeddingProvider === \"embeddings\" ? pc.green(\"✓ embeddings\") : pc.dim(\"bm25-only\");\n const flagRows = (flagsRes.flags || []).map((f: { key: string; enabled: boolean; label: string }) =>\n ` ${f.enabled ? pc.green(\"✓\") : pc.dim(\"✗\")} ${pc.bold(f.key.padEnd(32))} ${f.label}`\n );\n lines.push(\"\");\n lines.push(`Provider: ${provider}`);\n lines.push(`Embeddings: ${embed}`);\n lines.push(`Flags:`);\n flagRows.forEach((r: string) => lines.push(r));\n }\n\n if (followupRes && Number.isFinite(followupRes.agentInitiatedSearches)) {\n const total = Number(followupRes.agentInitiatedSearches) || 0;\n const hits = Number(followupRes.followupWithinWindow) || 0;\n const pct = total > 0 ? Math.round((hits / total) * 100) : 0;\n lines.push(\"\");\n lines.push(\n `Followup rate: ${hits}/${total} (${pct}%) within ${followupRes.windowSeconds}s — directional, may overcount on refinement`,\n );\n }\n\n p.note(lines.join(\"\\n\"), \"agentmemory\");\n } catch (err) {\n p.log.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n}\n\ntype DoctorCheck = { name: string; ok: boolean; hint?: string };\n\nfunction formatChecks(checks: DoctorCheck[]): string {\n return checks\n .map((c) => `${c.ok ? pc.green(\"✓\") : pc.red(\"✗\")} ${c.name}${c.hint ? `\\n ${c.hint}` : \"\"}`)\n .join(\"\\n\");\n}\n\ntype CCHooksCheck =\n | { state: \"loaded\"; manifestPath?: string }\n | { state: \"not-loaded\" }\n | { state: \"no-debug-log\" }\n | { state: \"no-cc-dir\" };\n\nfunction findLatestDebugLog(debugDir: string): string | undefined {\n const latestLink = join(debugDir, \"latest\");\n try {\n if (existsSync(latestLink)) {\n const target = readlinkSync(latestLink);\n const resolved = target.startsWith(\"/\") ? target : join(debugDir, target);\n if (existsSync(resolved)) return resolved;\n }\n } catch {}\n\n try {\n const newest = readdirSync(debugDir)\n .filter((f) => f.endsWith(\".txt\"))\n .map((f) => ({ f, m: statSync(join(debugDir, f)).mtimeMs }))\n .sort((a, b) => b.m - a.m)[0];\n if (newest) return join(debugDir, newest.f);\n } catch {}\n\n return undefined;\n}\n\nfunction checkClaudeCodeHooks(): CCHooksCheck {\n const debugDir = join(homedir(), \".claude\", \"debug\");\n if (!existsSync(debugDir)) return { state: \"no-cc-dir\" };\n\n const logPath = findLatestDebugLog(debugDir);\n if (!logPath) return { state: \"no-debug-log\" };\n\n let content: string;\n try {\n content = readFileSync(logPath, \"utf8\");\n } catch {\n return { state: \"no-debug-log\" };\n }\n\n const match = content.match(\n /Loaded hooks from standard location for plugin agentmemory:\\s*(\\S+)/\n );\n if (match) return { state: \"loaded\", manifestPath: match[1] };\n if (content.includes(\"Loading hooks from plugin: agentmemory\")) return { state: \"loaded\" };\n return { state: \"not-loaded\" };\n}\n\n// ---------------------------------------------------------------------------\n// Doctor v2 — interactive fixer.\n//\n// The legacy passive check-list (server reachable, flags, knowledge-graph,\n// Claude Code hooks) still runs first as an informational summary because\n// those checks need a live engine and don't have a one-shot inline fix.\n// Then we drive the new diagnostic catalog (see src/cli/doctor-diagnostics.ts)\n// which prompts Fix/Skip/More/Quit per failing check, applies the fix\n// inline, and re-checks only the affected diagnostic.\n\nfunction buildDoctorContext(): DoctorContext {\n return {\n baseUrl: getBaseUrl(),\n viewerUrl: getViewerUrl(),\n envPath: join(homedir(), \".agentmemory\", \".env\"),\n pidfilePath: enginePidfilePath(),\n enginePath: engineStatePath(),\n pinnedVersion: IIPINNED_VERSION,\n };\n}\n\nfunction buildDoctorEffects(): DoctorEffects {\n return {\n envFileExists: () => existsSync(join(homedir(), \".agentmemory\", \".env\")),\n readEnvFile: () => {\n try {\n return parseEnvFile(\n readFileSync(join(homedir(), \".agentmemory\", \".env\"), \"utf-8\"),\n );\n } catch {\n return {};\n }\n },\n pidfileExists: () => existsSync(enginePidfilePath()),\n pidfilePidIsAlive: () => {\n const pid = readEnginePidfile();\n if (pid === null) return null;\n return pidAlive(pid);\n },\n findIiiBinary: () => whichBinary(\"iii\"),\n localBinIiiPath: () => privateIiiPath(),\n iiiBinaryVersion: (binPath: string) => iiiBinVersion(binPath),\n viewerReachable: async (timeoutMs = 2000) => {\n try {\n await discoverViewerPort();\n const res = await fetch(getViewerUrl(), {\n signal: AbortSignal.timeout(timeoutMs),\n });\n return res.ok;\n } catch {\n return false;\n }\n },\n runInit: async () => {\n try {\n await runInit();\n return { ok: true, message: \"Wrote ~/.agentmemory/.env\" };\n } catch (err) {\n return {\n ok: false,\n message: err instanceof Error ? err.message : String(err),\n };\n }\n },\n openEditor: async (path: string) => {\n const editor = process.env[\"EDITOR\"] || process.env[\"VISUAL\"] || \"nano\";\n p.log.info(`Opening ${path} in ${editor}…`);\n try {\n // Inherit stdio so the user actually sees the editor.\n const result = spawnSync(editor, [path], { stdio: \"inherit\" });\n if (result.error) {\n return {\n ok: false,\n message: `Failed to launch ${editor}: ${result.error.message}`,\n };\n }\n if ((result.status ?? 0) !== 0) {\n return {\n ok: false,\n message: `${editor} exited with code ${result.status}`,\n };\n }\n return { ok: true, message: `Saved ${path}` };\n } catch (err) {\n return {\n ok: false,\n message: err instanceof Error ? err.message : String(err),\n };\n }\n },\n runIiiInstaller: async () => {\n const r = await runIiiInstaller();\n return {\n ok: r.ok,\n message: r.ok\n ? `Installed iii v${IIPINNED_VERSION} to ${r.binPath}`\n : \"iii installer failed (see warnings above)\",\n };\n },\n runStop: async () => {\n try {\n // runStop calls process.exit on its own — guard against that here\n // by short-circuiting when there's nothing to stop.\n const port = getRestPort();\n const portPids = findEnginePidsByPort(port);\n const pidfilePid = readEnginePidfile();\n if (portPids.length === 0 && pidfilePid === null) {\n clearEnginePidfile();\n clearEngineState();\n return { ok: true, message: \"Nothing to stop.\" };\n }\n const candidates = new Set<number>();\n if (pidfilePid) candidates.add(pidfilePid);\n for (const pid of portPids) candidates.add(pid);\n let allStopped = true;\n for (const pid of candidates) {\n const ok = await signalAndWait(pid, \"SIGTERM\", 3000);\n if (!ok) allStopped = false;\n }\n clearEnginePidfile();\n clearEngineState();\n return {\n ok: allStopped,\n message: allStopped ? \"Engine stopped.\" : \"Some engine pids survived.\",\n };\n } catch (err) {\n return {\n ok: false,\n message: err instanceof Error ? err.message : String(err),\n };\n }\n },\n runStart: async () => {\n try {\n const started = await startEngine();\n if (!started) return { ok: false, message: \"startEngine() returned false\" };\n const ready = await waitForEngine(15000);\n return {\n ok: ready,\n message: ready ? \"Engine ready\" : \"Engine did not become ready within 15s\",\n };\n } catch (err) {\n return {\n ok: false,\n message: err instanceof Error ? err.message : String(err),\n };\n }\n },\n clearEnginePidAndState: () => {\n clearEnginePidfile();\n clearEngineState();\n },\n };\n}\n\nasync function passiveServerChecks(): Promise<DoctorCheck[]> {\n const base = getBaseUrl();\n const checks: DoctorCheck[] = [];\n\n const serverUp = await isEngineRunning();\n checks.push({\n name: \"Server reachable\",\n ok: serverUp,\n hint: serverUp\n ? undefined\n : `Start with: npx @agentmemory/agentmemory (tried ${base})`,\n });\n if (!serverUp) return checks;\n\n const [health, flags, graph] = await Promise.all([\n apiFetch<any>(base, \"health\", 3000),\n apiFetch<any>(base, \"config/flags\", 3000),\n apiFetch<any>(base, \"graph/stats\", 3000),\n ]);\n\n const hasLlm = flags?.provider === \"llm\";\n const hasEmbed = flags?.embeddingProvider === \"embeddings\";\n const graphNodeCount = Number(\n graph?.totalNodes ?? graph?.nodes ?? graph?.nodeCount ?? 0,\n );\n const graphHas = graphNodeCount > 0;\n\n checks.push(\n {\n name: \"Health status\",\n ok: health?.status === \"healthy\",\n hint:\n health?.status === \"healthy\"\n ? undefined\n : `Status: ${health?.status || \"unknown\"}`,\n },\n {\n name: \"LLM provider\",\n ok: hasLlm,\n hint: hasLlm ? undefined : \"set ANTHROPIC_API_KEY (or GEMINI/OPENROUTER/MINIMAX) in ~/.agentmemory/.env\",\n },\n {\n name: \"Embedding provider\",\n ok: hasEmbed,\n hint: hasEmbed\n ? undefined\n : \"Running BM25-only. Add OPENAI_API_KEY / VOYAGE_API_KEY / COHERE_API_KEY / OLLAMA_HOST\",\n },\n );\n\n for (const f of (flags?.flags || []) as {\n label: string;\n enabled: boolean;\n enableHow: string;\n }[]) {\n checks.push({\n name: f.label,\n ok: f.enabled,\n hint: f.enabled ? undefined : f.enableHow,\n });\n }\n\n const cc = checkClaudeCodeHooks();\n const ccCheck = (() => {\n switch (cc.state) {\n case \"loaded\":\n return {\n ok: true,\n hint: cc.manifestPath ? `manifest: ${cc.manifestPath}` : undefined,\n };\n case \"not-loaded\":\n return {\n ok: false,\n hint:\n \"Plugin enabled but hooks not loaded by Claude Code. Try: /plugin uninstall agentmemory@agentmemory && /plugin install agentmemory@agentmemory, then restart the session.\",\n };\n case \"no-debug-log\":\n return {\n ok: false,\n hint:\n 'Cannot verify — no Claude Code debug log found. Run once with `claude --debug -p \"x\"`, then re-run doctor.',\n };\n case \"no-cc-dir\":\n return undefined;\n }\n })();\n if (ccCheck) checks.push({ name: \"Claude Code plugin hooks registered\", ...ccCheck });\n\n checks.push({\n name: \"Knowledge graph populated\",\n ok: graphHas,\n hint: graphHas\n ? undefined\n : \"Graph is empty. Run a session with GRAPH_EXTRACTION_ENABLED=true.\",\n });\n\n return checks;\n}\n\ntype DoctorAction = \"fix\" | \"skip\" | \"more\" | \"quit\";\n\nasync function askFixAction(d: Diagnostic): Promise<DoctorAction> {\n const choice = await p.select<DoctorAction>({\n message: `[${d.id}] ${d.message}`,\n options: [\n { value: \"fix\", label: \"F Fix\", hint: d.fixPreview },\n { value: \"skip\", label: \"S Skip\" },\n { value: \"more\", label: \"? More info\" },\n { value: \"quit\", label: \"Q Quit doctor\" },\n ],\n initialValue: \"fix\",\n });\n if (p.isCancel(choice)) return \"quit\";\n return choice;\n}\n\nasync function applyFixWithReport(\n d: Diagnostic,\n ctx: DoctorContext,\n dryRun: boolean,\n): Promise<DiagnosticFixResult> {\n if (dryRun) {\n p.log.info(`[dry-run] would: ${d.fixPreview}`);\n return { ok: true, message: \"(dry-run)\" };\n }\n const result = await d.fix(ctx);\n if (result.ok) {\n p.log.success(result.message ?? `${d.id} fixed.`);\n } else {\n p.log.error(result.message ?? `${d.id} fix failed.`);\n }\n return result;\n}\n\nasync function runDoctor() {\n p.intro(\"agentmemory doctor\");\n const applyAll = args.includes(\"--all\");\n const dryRun = args.includes(\"--dry-run\");\n if (applyAll && dryRun) {\n p.log.error(\"Cannot combine --all and --dry-run.\");\n process.exit(2);\n }\n\n // Passive server checks (informational).\n const passive = await passiveServerChecks();\n const passivePassed = passive.filter((c) => c.ok).length;\n p.note(formatChecks(passive), `server: ${passivePassed}/${passive.length} passing`);\n\n // Doctor v2 interactive catalog.\n const ctx = buildDoctorContext();\n const effects = buildDoctorEffects();\n const diagnostics = buildDiagnostics(effects);\n\n if (dryRun) {\n const results: Array<{ diagnostic: Diagnostic; status: { ok: boolean; detail?: string } }> = [];\n for (const d of diagnostics) results.push({ diagnostic: d, status: await d.check(ctx) });\n const lines = dryRunPlan(ctx, results);\n p.note(lines.join(\"\\n\"), \"dry-run plan\");\n p.outro(\"Dry-run complete. Re-run without --dry-run to apply.\");\n return;\n }\n\n let failed = 0;\n let fixed = 0;\n let skipped = 0;\n let quit = false;\n\n for (const d of diagnostics) {\n if (quit) {\n skipped++;\n continue;\n }\n const status = await d.check(ctx);\n if (status.ok) {\n p.log.success(`${d.id} ✓${status.detail ? ` (${status.detail})` : \"\"}`);\n continue;\n }\n failed++;\n p.log.warn(`${d.id} ✗ ${status.detail ?? \"\"}`.trim());\n p.log.info(`why: ${d.fixPreview}`);\n\n if (d.manualOnly) {\n p.log.info(`(manual fix only — see \"${d.id}\" docs)`);\n }\n\n if (applyAll) {\n const r = await applyFixWithReport(d, ctx, false);\n if (r.ok) fixed++;\n // Re-check only this diagnostic.\n const after = await d.check(ctx);\n if (!after.ok) p.log.warn(`${d.id} still failing after fix.`);\n continue;\n }\n\n // Interactive prompt loop — allow [?] More info without leaving the check.\n while (true) {\n const action = await askFixAction(d);\n if (action === \"fix\") {\n const r = await applyFixWithReport(d, ctx, false);\n if (r.ok) {\n const after = await d.check(ctx);\n if (after.ok) {\n fixed++;\n } else {\n p.log.warn(`${d.id} still failing after fix: ${after.detail ?? \"\"}`);\n }\n }\n break;\n }\n if (action === \"skip\") {\n skipped++;\n break;\n }\n if (action === \"more\") {\n p.note(d.moreInfo, `[${d.id}] more info`);\n continue;\n }\n if (action === \"quit\") {\n quit = true;\n break;\n }\n }\n }\n\n const summary = `${diagnostics.length} checks · ${failed} failing · ${fixed} fixed · ${skipped} skipped`;\n if (quit) {\n p.outro(`Quit early. ${summary}`);\n process.exit(1);\n }\n if (failed === 0) {\n p.outro(\"All diagnostics passing. agentmemory is healthy.\");\n return;\n }\n if (failed - fixed === 0) {\n p.outro(`All fixes applied. ${summary}`);\n return;\n }\n p.outro(summary);\n process.exit(1);\n}\n\ntype DemoObservation = {\n toolName: string;\n toolInput: Record<string, string>;\n toolOutput: string;\n};\n\ntype DemoSession = {\n id: string;\n title: string;\n observations: DemoObservation[];\n};\n\ntype SearchResult = { query: string; hits: number; topTitle: string };\n\nfunction buildDemoSessions(): DemoSession[] {\n return [\n {\n id: generateId(\"demo\"),\n title: \"Session 1: JWT auth setup\",\n observations: [\n {\n toolName: \"Write\",\n toolInput: { file_path: \"src/middleware/auth.ts\" },\n toolOutput:\n \"Created JWT middleware using jose library. Tokens expire after 30 days. Chose jose over jsonwebtoken for Edge compatibility.\",\n },\n {\n toolName: \"Write\",\n toolInput: { file_path: \"test/auth.test.ts\" },\n toolOutput:\n \"Added token validation tests covering expired, malformed, and valid cases.\",\n },\n {\n toolName: \"Bash\",\n toolInput: { command: \"npm test\" },\n toolOutput: \"All 12 auth tests passing.\",\n },\n ],\n },\n {\n id: generateId(\"demo\"),\n title: \"Session 2: Database migration debugging\",\n observations: [\n {\n toolName: \"Read\",\n toolInput: { file_path: \"prisma/schema.prisma\" },\n toolOutput:\n \"Found N+1 query issue in user relations. Need to add include on posts query.\",\n },\n {\n toolName: \"Edit\",\n toolInput: { file_path: \"src/api/users.ts\" },\n toolOutput:\n \"Fixed N+1 by adding Prisma include. Query time dropped from 450ms to 28ms.\",\n },\n ],\n },\n {\n id: generateId(\"demo\"),\n title: \"Session 3: Rate limiting\",\n observations: [\n {\n toolName: \"Write\",\n toolInput: { file_path: \"src/middleware/ratelimit.ts\" },\n toolOutput:\n \"Added rate limiting middleware with 100 req/min default. Uses in-memory store for dev, Redis for prod.\",\n },\n ],\n },\n ];\n}\n\nasync function postJson<T = unknown>(\n url: string,\n body: unknown,\n timeoutMs = 5000,\n): Promise<T | null> {\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(timeoutMs),\n });\n if (!res.ok) return null;\n return (await res.json().catch(() => null)) as T | null;\n } catch {\n return null;\n }\n}\n\nasync function postJsonStrict<T = unknown>(\n url: string,\n body: unknown,\n timeoutMs = 5000,\n): Promise<T | null> {\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(timeoutMs),\n });\n if (!res.ok) {\n const errBody = await res.text().catch(() => \"\");\n const suffix = errBody ? ` — ${errBody.slice(0, 200)}` : \"\";\n throw new Error(`POST ${url} failed: ${res.status} ${res.statusText}${suffix}`);\n }\n return (await res.json().catch(() => null)) as T | null;\n}\n\nasync function seedDemoSession(\n base: string,\n project: string,\n session: DemoSession,\n): Promise<number> {\n await postJsonStrict(`${base}/agentmemory/session/start`, {\n sessionId: session.id,\n project,\n cwd: project,\n });\n\n let stored = 0;\n for (const obs of session.observations) {\n const url = `${base}/agentmemory/observe`;\n const payload = {\n hookType: \"post_tool_use\",\n sessionId: session.id,\n project,\n cwd: project,\n timestamp: new Date().toISOString(),\n data: {\n tool_name: obs.toolName,\n tool_input: obs.toolInput,\n tool_output: obs.toolOutput,\n },\n };\n\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n signal: AbortSignal.timeout(5000),\n });\n if (res.ok) {\n stored++;\n } else {\n const body = await res.text().catch(() => \"\");\n p.log.warn(\n `observe failed for ${obs.toolName}: ${res.status} ${res.statusText}${body ? ` — ${body.slice(0, 160)}` : \"\"}`,\n );\n }\n } catch (err) {\n p.log.warn(\n `observe request failed for ${obs.toolName}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n await postJsonStrict(`${base}/agentmemory/session/end`, { sessionId: session.id });\n return stored;\n}\n\nasync function runDemoSearch(base: string, query: string): Promise<SearchResult> {\n const data = await postJson<{ results?: Array<{ title?: string }> }>(\n `${base}/agentmemory/smart-search`,\n { query, limit: 5 },\n 10000,\n );\n const items = data?.results ?? [];\n return {\n query,\n hits: items.length,\n topTitle: items[0]?.title ?? \"(no results)\",\n };\n}\n\n// Prefer the packaged `.env.example` (next to `dist/cli.mjs`); fall back to\n// the repo root when running from a source checkout.\nfunction findEnvExample(): string | null {\n const candidates = [\n join(__dirname, \"..\", \".env.example\"),\n join(__dirname, \".env.example\"),\n join(process.cwd(), \".env.example\"),\n ];\n for (const c of candidates) {\n if (existsSync(c)) return c;\n }\n return null;\n}\n\nasync function runInit() {\n p.intro(\"agentmemory init\");\n const target = join(homedir(), \".agentmemory\", \".env\");\n const template = findEnvExample();\n if (!template) {\n p.log.error(\n \"Could not locate .env.example in the package. Re-install with: npm i -g @agentmemory/agentmemory\",\n );\n process.exit(1);\n }\n const dir = dirname(target);\n const { mkdir, copyFile } = await import(\"node:fs/promises\");\n const { constants: fsConstants } = await import(\"node:fs\");\n try {\n await mkdir(dir, { recursive: true });\n // COPYFILE_EXCL collapses the exists-check + copy into one syscall —\n // an existsSync(target) + copyFile() pair races with a parallel init\n // (or any other process touching ~/.agentmemory/.env between the two\n // calls) and would silently overwrite a config the operator just\n // wrote. EEXIST out of copyFile is the only \"already configured\"\n // signal we trust.\n await copyFile(template, target, fsConstants.COPYFILE_EXCL);\n } catch (err) {\n if ((err as NodeJS.ErrnoException)?.code === \"EEXIST\") {\n p.log.warn(`${target} already exists — leaving it untouched.`);\n p.log.info(\n `Compare against the latest template: diff ${target} ${template}`,\n );\n p.outro(\"Nothing changed.\");\n return;\n }\n p.log.error(\n `Failed to copy template: ${err instanceof Error ? err.message : String(err)}`,\n );\n process.exit(1);\n }\n p.log.success(`Wrote ${target}`);\n p.note(\n [\n \"All keys are commented out by default. Uncomment the ones you want.\",\n \"\",\n \"Common next steps:\",\n \" 1. Pick an LLM provider key (ANTHROPIC_API_KEY / OPENAI_API_KEY / GEMINI_API_KEY / etc.)\",\n \" 2. Run `npx @agentmemory/agentmemory doctor` to verify the daemon sees them\",\n \" 3. Run `npx @agentmemory/agentmemory` to start the worker\",\n ].join(\"\\n\"),\n \"Next steps\",\n );\n p.outro(`Edit ${target} and you're set.`);\n}\n\nasync function startServerForDemo(): Promise<() => Promise<void>> {\n if (await isAgentmemoryReady()) {\n return async () => {};\n }\n\n const startedEngine = !(await isEngineRunning());\n if (startedEngine) {\n const ok = await startEngine();\n if (!ok) {\n p.log.error(\"Could not start iii-engine for the demo.\");\n p.note(installInstructions().join(\"\\n\"), \"Setup required\");\n process.exit(1);\n }\n if (!(await waitForEngine(15000))) {\n p.log.error(\"iii-engine did not become ready within 15s.\");\n process.exit(1);\n }\n }\n\n await import(\"./index.js\");\n if (!(await waitForAgentmemoryReady(15000))) {\n p.log.error(\"agentmemory worker did not become ready within 15s.\");\n process.exit(1);\n }\n\n return async () => {\n if (!startedEngine) return;\n const port = getRestPort();\n const state = readEngineState();\n if (state?.kind === \"docker\") {\n await stopDockerEngine(state.composeFile, port).catch(() => {});\n return;\n }\n const pids = new Set<number>(findEnginePidsByPort(port));\n const pidfilePid = readEnginePidfile();\n if (pidfilePid) pids.add(pidfilePid);\n for (const pid of pids) {\n await signalAndWait(pid, \"SIGTERM\", 3000).catch(() => {});\n }\n clearEnginePidfile();\n clearEngineState();\n clearWorkerPidfile();\n };\n}\n\nasync function runDemo() {\n const port = getRestPort();\n const base = `http://localhost:${port}`;\n p.intro(\"agentmemory demo\");\n\n const serve = args.includes(\"--serve\");\n let teardown: () => Promise<void> = async () => {};\n\n if (serve) {\n teardown = await startServerForDemo();\n } else if (!(await isAgentmemoryReady())) {\n p.log.error(\n `agentmemory worker not reachable on port ${port} (livez probe failed). Something may be on the port but it isn't serving /agentmemory/*.`,\n );\n p.log.info(\"Start it with: npx @agentmemory/agentmemory\");\n p.log.info(\"Or run a one-command demo with: npx @agentmemory/agentmemory demo --serve\");\n process.exit(1);\n }\n\n try {\n await runDemoBody(base);\n } finally {\n await teardown();\n }\n\n if (serve) {\n process.exit(0);\n }\n}\n\nasync function runDemoBody(base: string) {\n const demoProject = \"/tmp/agentmemory-demo\";\n const sessions = buildDemoSessions();\n\n const sSeed = p.spinner();\n sSeed.start(\"Seeding 3 demo sessions with realistic observations...\");\n\n let totalObs = 0;\n for (const session of sessions) {\n totalObs += await seedDemoSession(base, demoProject, session);\n }\n\n sSeed.stop(`Seeded ${totalObs} observations across ${sessions.length} sessions`);\n\n const queries = [\n \"jwt auth middleware\",\n \"database performance optimization\",\n \"rate limiting\",\n ];\n\n const sQuery = p.spinner();\n sQuery.start(`Running ${queries.length} smart-search queries...`);\n\n const results: SearchResult[] = [];\n for (const query of queries) {\n results.push(await runDemoSearch(base, query));\n }\n\n sQuery.stop(\"Search complete\");\n\n // Only claim the semantic-recall win when the search actually hit.\n // Without an embedding key this query returns 0 hits, and asserting\n // success over a visibly failed search reads as a lie.\n const semanticHits =\n results.find((r) => r.query === \"database performance optimization\")\n ?.hits ?? 0;\n const lines = [\n `Project: ${demoProject}`,\n `Sessions: ${sessions.length} seeded (${totalObs} observations)`,\n \"\",\n c.label(\"Search results:\"),\n ...results.flatMap((r) => [\n ` ${c.label(`\"${r.query}\"`)}`,\n ` ${c.dim(\"→\")} ${c.ok(`${r.hits} hit(s)`)}, top: ${r.topTitle.slice(0, 60)}`,\n ]),\n \"\",\n ...(semanticHits > 0\n ? [\n c.accent(`Notice: searching \"database performance optimization\"`),\n c.accent(`found the N+1 query fix — keyword matching can't do that.`),\n ]\n : [\n c.dim(`Note: \"database performance optimization\" found nothing —`),\n c.dim(`semantic recall needs an embedding provider key (e.g.`),\n c.dim(`OPENAI_API_KEY or GEMINI_API_KEY in ~/.agentmemory/.env).`),\n ]),\n \"\",\n `Viewer: ${c.url(getViewerUrl())}`,\n `Clean up with: ${c.dim(`curl -X DELETE \"${base}/agentmemory/sessions?project=${demoProject}\"`)}`,\n ];\n\n p.note(lines.join(\"\\n\"), \"demo complete\");\n p.log.success(\"agentmemory is working. Point your agent at it and get back to coding.\");\n}\n\nfunction runCommand(\n command: string,\n commandArgs: string[],\n options: { cwd?: string; label: string; optional?: boolean } = { label: \"command\" },\n): boolean {\n const spinner = p.spinner();\n spinner.start(options.label);\n const result = spawnSync(command, commandArgs, {\n cwd: options.cwd || process.cwd(),\n stdio: \"pipe\",\n encoding: \"utf-8\",\n });\n\n if (result.status === 0) {\n spinner.stop(`${options.label} ${pc.green(\"✓\")}`);\n return true;\n }\n\n const stderr = (result.stderr || \"\").toString().trim();\n const stdout = (result.stdout || \"\").toString().trim();\n const msg = stderr || stdout || \"unknown error\";\n\n if (options.optional) {\n spinner.stop(`${options.label} (skipped)`);\n p.log.warn(msg.slice(0, 300));\n return false;\n }\n\n spinner.stop(`${options.label} ${pc.red(\"✗\")}`);\n p.log.error(msg.slice(0, 300));\n return false;\n}\n\nasync function runUpgrade() {\n p.intro(\"agentmemory upgrade\");\n\n const cwd = process.cwd();\n const hasPackageJson = existsSync(join(cwd, \"package.json\"));\n const hasPnpmLock = existsSync(join(cwd, \"pnpm-lock.yaml\"));\n\n const pnpmBin = whichBinary(\"pnpm\");\n const npmBin = whichBinary(\"npm\");\n const dockerBin = whichBinary(\"docker\");\n\n p.log.info(`Working directory: ${cwd}`);\n const requireSuccess = (ok: boolean, label: string): void => {\n if (!ok) {\n p.log.error(`Upgrade aborted: ${label} failed.`);\n process.exit(1);\n }\n };\n\n if (hasPackageJson) {\n const usePnpm = !!pnpmBin && hasPnpmLock;\n if (usePnpm && pnpmBin) {\n const installOk = runCommand(pnpmBin, [\"install\"], {\n label: \"Refreshing dependencies (pnpm install)\",\n });\n requireSuccess(installOk, \"pnpm install\");\n runCommand(pnpmBin, [\"up\", \"iii-sdk@0.11.2\"], {\n label: \"Pinning iii-sdk@0.11.2\",\n optional: true,\n });\n } else if (npmBin) {\n const installOk = runCommand(npmBin, [\"install\"], {\n label: \"Refreshing dependencies (npm install)\",\n });\n requireSuccess(installOk, \"npm install\");\n runCommand(npmBin, [\"install\", \"iii-sdk@0.11.2\"], {\n label: \"Pinning iii-sdk@0.11.2\",\n optional: true,\n });\n } else {\n p.log.warn(\"No package manager found (pnpm/npm). Skipping JS dependency upgrade.\");\n }\n } else {\n p.log.warn(\"No package.json in current directory. Skipping JS dependency upgrade.\");\n }\n\n const upgradeEngine = await p.confirm({\n message: \"Re-run the iii-engine install script (curl | sh)?\",\n initialValue: true,\n });\n if (p.isCancel(upgradeEngine)) {\n p.cancel(\"Cancelled.\");\n return process.exit(0);\n }\n if (upgradeEngine === true) {\n await runIiiInstaller();\n } else {\n p.log.info(\"Skipped iii-engine installer.\");\n }\n\n if (dockerBin) {\n runCommand(dockerBin, [\"pull\", `iiidev/iii:${IIPINNED_VERSION}`], {\n label: `Pulling iii Docker image v${IIPINNED_VERSION} (pinned)`,\n optional: true,\n });\n } else {\n p.log.info(\"Docker not found. Skipping Docker image refresh.\");\n }\n\n p.note(\n [\n \"Upgrade flow completed.\",\n \"\",\n \"Recommended next steps:\",\n \" 1) agentmemory status\",\n \" 2) npm/pnpm test\",\n \" 3) restart agentmemory process\",\n ].join(\"\\n\"),\n \"agentmemory upgrade\",\n );\n}\n\nfunction pidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (err) {\n return (err as NodeJS.ErrnoException)?.code === \"EPERM\";\n }\n}\n\nasync function signalAndWait(\n pid: number,\n initialSignal: NodeJS.Signals,\n timeoutMs: number,\n): Promise<boolean> {\n try {\n process.kill(pid, initialSignal);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException)?.code;\n if (code === \"ESRCH\") return true;\n if (code === \"EPERM\") {\n p.log.warn(`No permission to signal pid ${pid}. Try: kill ${pid}`);\n return false;\n }\n vlog(`${initialSignal} ${pid}: ${err instanceof Error ? err.message : String(err)}`);\n return false;\n }\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n if (!pidAlive(pid)) return true;\n await new Promise((r) => setTimeout(r, 200));\n }\n if (!pidAlive(pid)) return true;\n try {\n process.kill(pid, \"SIGKILL\");\n } catch (err) {\n if ((err as NodeJS.ErrnoException)?.code === \"ESRCH\") return true;\n vlog(`SIGKILL ${pid}: ${err instanceof Error ? err.message : String(err)}`);\n return false;\n }\n await new Promise((r) => setTimeout(r, 200));\n return !pidAlive(pid);\n}\n\n// Shared worker-reap: SIGTERM with a grace window sized for the worker's\n// shutdown flush (index snapshots land via the engine, so the worker must\n// die before the engine does, with time to commit).\nasync function stopWorkerPid(pid: number, graceMs: number): Promise<boolean> {\n const s = p.spinner();\n s.start(`Stopping agentmemory worker (pid ${pid})... [flushing state]`);\n const ok = await signalAndWait(pid, \"SIGTERM\", graceMs);\n s.stop(ok ? `Stopped worker pid ${pid}` : `Failed to stop worker pid ${pid}`);\n return ok;\n}\n\nfunction pidCommand(pid: number): string {\n if (IS_WINDOWS) return \"\";\n try {\n return execFileSync(\"ps\", [\"-p\", String(pid), \"-o\", \"comm=\"], {\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim();\n } catch {\n return \"\";\n }\n}\n\n// Positive identity beats a denylist: the engine is always the `iii`\n// binary (spawned from PATH or ~/.agentmemory/bin), so anything else\n// holding the port — Docker's proxy, an ssh forward, a stray dev\n// server — must not be adopted or signaled. A denylist of known VM\n// stacks failed open for every name it didn't know.\nfunction isForeignPortHolder(comm: string): boolean {\n if (!comm) return false;\n const base = comm.split(\"/\").pop() || comm;\n return base !== \"iii\" && !base.startsWith(\"iii-\");\n}\n\nfunction findEnginePidsByPort(port: number): number[] {\n if (IS_WINDOWS) return [];\n const lsof = whichBinary(\"lsof\");\n if (!lsof) return [];\n // -sTCP:LISTEN restricts to listening server sockets only. Without\n // this, lsof also returns client-side PIDs (any process with an\n // active TCP connection to :port), which includes the agentmemory\n // CLI itself thanks to the keep-alive fetch in isEngineRunning().\n // signalAndWait would then SIGKILL its own parent — exit code 137.\n const selfPid = process.pid;\n try {\n const out = execFileSync(lsof, [\"-i\", `:${port}`, \"-sTCP:LISTEN\", \"-t\"], {\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n return out\n .split(/\\s+/)\n .map((s) => parseInt(s, 10))\n .filter((n) => Number.isFinite(n) && n > 0 && n !== selfPid);\n } catch (err) {\n vlog(`lsof :${port}: ${err instanceof Error ? err.message : String(err)}`);\n return [];\n }\n}\n\nasync function stopDockerEngine(composeFile: string, port: number): Promise<void> {\n const dockerBin = whichBinary(\"docker\");\n if (!dockerBin) {\n p.log.error(\n `Engine was started via Docker compose, but \\`docker\\` is no longer on PATH. Stop it manually:\\n docker compose -f ${composeFile} down`,\n );\n process.exit(1);\n }\n if (!existsSync(composeFile)) {\n p.log.error(\n `Engine state references ${composeFile}, but the file is gone. Stop it manually:\\n docker compose down (from the dir holding the original docker-compose.yml)`,\n );\n process.exit(1);\n }\n\n // Reap the native worker first so its shutdown flush (BM25/vector\n // snapshots via iii state::set) lands while the engine is still up —\n // same ordering as the native stop path. Previously the worker pidfile\n // was cleared without ever signaling the process, leaking a worker on\n // every Docker-mode stop.\n const workerPid = readWorkerPidfile();\n let workerStopped = true;\n if (workerPid) {\n workerStopped = await stopWorkerPid(workerPid, 5000);\n }\n\n // Scope teardown to agentmemory's own services. A bare `down` against a\n // user-owned compose file tears down every service in it. `rm -s -f`\n // stops and removes only the named containers.\n let composeText = \"\";\n try {\n composeText = readFileSync(composeFile, \"utf-8\");\n } catch {\n composeText = \"\";\n }\n const ownServices = [\"iii-engine\", \"iii-init\"].filter((svc) =>\n new RegExp(`^\\\\s+${svc}:`, \"m\").test(composeText),\n );\n if (ownServices.length === 0) {\n p.log.error(\n `${composeFile} does not define the agentmemory services (iii-engine/iii-init). Refusing to run an unscoped \\`docker compose down\\` against it — that would tear down every service in the file.\\n\\nStop the engine service manually:\\n docker compose -f ${composeFile} stop <service>`,\n );\n process.exit(1);\n }\n const ok = runCommand(\n dockerBin,\n [\"compose\", \"-f\", composeFile, \"rm\", \"-s\", \"-f\", ...ownServices],\n {\n label: `docker compose -f ${composeFile} rm -s -f ${ownServices.join(\" \")}`,\n },\n );\n // Clear each piece of state only after its shutdown succeeded, so a\n // failed stop stays retryable.\n if (workerStopped) clearWorkerPidfile();\n if (ok) {\n clearEnginePidfile();\n clearEngineState();\n } else {\n p.log.error(\n `docker compose rm failed. The engine may still be running on :${port}. Inspect with:\\n docker compose -f ${composeFile} ps`,\n );\n process.exit(1);\n }\n p.outro(\"Stopped. Memories persisted to disk; restart anytime with: npx @agentmemory/agentmemory\");\n}\n\nasync function runStop(): Promise<void> {\n p.intro(\"agentmemory stop\");\n const port = getRestPort();\n const state = readEngineState();\n const running = await isEngineRunning();\n const force = args.includes(\"--force\");\n\n if (state?.kind === \"docker\") {\n if (!running) {\n p.log.info(`No engine responding on port ${port}.`);\n clearEnginePidfile();\n clearEngineState();\n clearWorkerPidfile();\n p.outro(\"Nothing to stop.\");\n return;\n }\n await stopDockerEngine(state.composeFile, port);\n return;\n }\n\n const portPids = findEnginePidsByPort(port);\n const pidfilePid = readEnginePidfile();\n // read the worker pid up front so the engine-down branch\n // can still reap an orphaned worker process (the common failure mode\n // where a wrapper script kept the worker alive across engine restarts).\n const workerPid = readWorkerPidfile();\n\n if (!running) {\n if (portPids.length === 0 && pidfilePid === null && workerPid === null) {\n clearEnginePidfile();\n clearEngineState();\n clearWorkerPidfile();\n p.outro(\"Nothing to stop.\");\n return;\n }\n if (workerPid !== null && portPids.length === 0 && pidfilePid === null) {\n // Engine already gone but worker is lingering — reap it directly\n // instead of preserving for manual cleanup.\n const s = p.spinner();\n s.start(`Stopping orphaned agentmemory worker (pid ${workerPid})...`);\n const ok = await signalAndWait(workerPid, \"SIGTERM\", 3000);\n s.stop(ok ? `Stopped worker pid ${workerPid}` : `Failed to stop worker pid ${workerPid}`);\n clearEnginePidfile();\n clearEngineState();\n clearWorkerPidfile();\n if (!ok) {\n p.log.error(`Worker pid ${workerPid} survived SIGKILL. Investigate with \\`ps\\`.`);\n process.exit(1);\n }\n p.outro(\"Stopped orphaned worker. Memories persisted to disk.\");\n return;\n }\n const survivors = new Set<number>(portPids);\n if (pidfilePid) survivors.add(pidfilePid);\n if (workerPid) survivors.add(workerPid);\n p.log.warn(\n `Engine not responding on :${port}, but ${survivors.size} process(es) still hold the port or pidfile: ${[...survivors].join(\", \")}`,\n );\n p.log.info(\n `Preserving ~/.agentmemory/iii.pid + worker.pid. Investigate before manual cleanup:\\n ps -p ${[...survivors].join(\",\")} -o pid,ppid,comm,etime\\n ${IS_WINDOWS ? \"netstat -ano | findstr :\" + port : \"lsof -i :\" + port}`,\n );\n process.exit(1);\n }\n\n if (!state) {\n const compose = discoverComposeFile();\n if (compose && pidfilePid === null) {\n if (force) {\n p.log.warn(\n `--force: bypassing Docker-heuristic guard. Falling back to native pidfile + lsof on :${port}.`,\n );\n } else {\n p.log.error(\n `Engine is running on :${port} but no pidfile or state file is present. It may have been started via Docker compose by a different shell. Refusing to signal host PIDs.\\n\\nStop it with:\\n docker compose -f ${compose} down\\n\\nOr re-run with --force to signal whatever lsof finds on :${port}, or AGENTMEMORY_USE_DOCKER=1 to record state next time.`,\n );\n process.exit(1);\n }\n }\n }\n\n const candidates = new Set<number>();\n if (pidfilePid) candidates.add(pidfilePid);\n for (const pid of portPids) candidates.add(pid);\n\n // stop must also reap the agentmemory worker process\n // (`node dist/index.mjs`). If only the engine is killed, the worker can\n // survive (detached spawn / signal not propagated) and reconnect to the\n // next engine as a duplicate registration. workerPid was read above so\n // the engine-down branch could also reap orphans.\n const workerCandidates = new Set<number>();\n if (workerPid) workerCandidates.add(workerPid);\n\n if (candidates.size === 0 && workerCandidates.size === 0) {\n p.log.error(\n `Could not locate engine process. Try:\\n ${IS_WINDOWS ? \"netstat -ano | findstr :\" + port : \"lsof -i :\" + port + \" -t | xargs kill -9\"}`,\n );\n process.exit(1);\n }\n\n let allStopped = true;\n // stop worker first, then engine. The worker's shutdown\n // handler calls indexPersistence.save() -> kv.set() -> iii state::set\n // to flush BM25/vector snapshots + audit rows. Killing iii first\n // leaves those writes with no engine to land on, and the index +\n // observations end up as in-memory state the iii process never\n // persists. Worker SIGTERM grace bumped 3s -> 5s to give a large\n // index a real chance to commit before the engine goes away.\n for (const pid of workerCandidates) {\n if (!(await stopWorkerPid(pid, 5000))) allStopped = false;\n }\n const skippedForeign: Array<{ pid: number; comm: string }> = [];\n for (const pid of candidates) {\n if (workerCandidates.has(pid)) continue;\n // Last-line guard against a stale/poisoned pidfile or a Docker\n // port-forward holding :port — signaling com.docker.backend kills\n // Docker Desktop's whole backend.\n const comm = pidCommand(pid);\n if (!force && isForeignPortHolder(comm)) {\n skippedForeign.push({ pid, comm });\n continue;\n }\n const s = p.spinner();\n s.start(`Stopping iii-engine (pid ${pid})...`);\n const ok = await signalAndWait(pid, \"SIGTERM\", 3000);\n s.stop(ok ? `Stopped pid ${pid}` : `Failed to stop pid ${pid}`);\n if (!ok) allStopped = false;\n }\n\n clearEnginePidfile();\n clearEngineState();\n clearWorkerPidfile();\n if (skippedForeign.length > 0) {\n const list = skippedForeign\n .map((sf) => ` pid ${sf.pid} ${sf.comm}`)\n .join(\"\\n\");\n p.log.error(\n `Refused to signal process(es) holding :${port} that are not the iii engine:\\n${list}\\n\\nIf the engine runs in Docker, stop it there:\\n docker compose ps && docker compose rm -s -f <service>\\n\\nOr re-run with --force to signal them anyway.`,\n );\n process.exit(1);\n }\n if (!allStopped) {\n p.log.error(\"One or more processes survived SIGKILL. Investigate with `ps`.\");\n process.exit(1);\n }\n p.outro(\"Stopped. Memories persisted to disk; restart anytime with: npx @agentmemory/agentmemory\");\n}\n\nasync function runMcp(): Promise<void> {\n await import(\"./mcp/standalone.js\");\n}\n\nasync function runConnectCmd(): Promise<void> {\n const { runConnect } = await import(\"./cli/connect/index.js\");\n await runConnect(args.slice(1));\n}\n\nasync function runImportJsonl(): Promise<void> {\n // Long-form flags that take a value. Their value tokens must be\n // consumed alongside the flag so they don't leak into positional\n // args (e.g. `--port 3112 import-jsonl` would otherwise turn\n // 3112 into pathArg).\n const VALUE_FLAGS = new Set([\"--port\", \"--tools\", \"--data-dir\"]);\n let maxFiles: number | undefined;\n const tail = args.slice(1);\n const positional: string[] = [];\n for (let i = 0; i < tail.length; i++) {\n const a = tail[i]!;\n if (a === \"--max-files\") {\n const raw = tail[i + 1];\n const parsed = raw !== undefined ? parseInt(raw, 10) : NaN;\n if (Number.isInteger(parsed) && parsed > 0) {\n maxFiles = parsed;\n } else if (raw !== undefined) {\n p.log.warn(`Ignoring --max-files ${raw}: expected a positive integer.`);\n }\n i++;\n continue;\n }\n if (a.startsWith(\"--max-files=\")) {\n const raw = a.slice(\"--max-files=\".length);\n const parsed = parseInt(raw, 10);\n if (Number.isInteger(parsed) && parsed > 0) {\n maxFiles = parsed;\n } else {\n p.log.warn(`Ignoring --max-files=${raw}: expected a positive integer.`);\n }\n continue;\n }\n if (VALUE_FLAGS.has(a)) {\n i++;\n continue;\n }\n if (a.startsWith(\"-\")) continue;\n positional.push(a);\n }\n const pathArg = positional[0];\n\n const port = getRestPort();\n const base = `http://localhost:${port}`;\n\n let probeOk = false;\n let probeDetail = \"\";\n try {\n const probe = await fetch(`${base}/agentmemory/livez`, {\n signal: AbortSignal.timeout(2000),\n });\n probeOk = probe.ok;\n if (!probeOk) {\n const probeBody = await probe.text().catch(() => \"\");\n probeDetail = `reachable but unhealthy (HTTP ${probe.status}${probeBody ? `: ${probeBody.slice(0, 200)}` : \"\"})`;\n }\n } catch (err) {\n probeOk = false;\n const msg = err instanceof Error ? err.message : String(err);\n probeDetail = `unreachable (${msg})`;\n }\n if (!probeOk) {\n p.log.error(\n `agentmemory livez probe failed on port ${port}: ${probeDetail}. Start it with \\`npx @agentmemory/agentmemory\\` in another terminal, then re-run this command.`,\n );\n process.exit(1);\n }\n\n const body: Record<string, unknown> = {};\n if (pathArg) body[\"path\"] = pathArg;\n if (maxFiles !== undefined) body[\"maxFiles\"] = maxFiles;\n\n const headers: Record<string, string> = { \"content-type\": \"application/json\" };\n const secret = process.env[\"AGENTMEMORY_SECRET\"];\n if (secret) headers[\"authorization\"] = `Bearer ${secret}`;\n\n p.log.info(`Importing JSONL from ${pathArg || \"~/.claude/projects\"}…`);\n const spinner = p.spinner();\n spinner.start(\"scanning files\");\n\n try {\n const res = await fetch(`${base}/agentmemory/replay/import-jsonl`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(120_000),\n });\n const text = await res.text();\n let json: {\n success?: boolean;\n error?: string;\n imported?: number;\n sessionIds?: string[];\n observations?: number;\n discovered?: number;\n truncated?: boolean;\n traversalCapped?: boolean;\n maxFiles?: number;\n maxFilesUpperBound?: number;\n } = {};\n if (text.length > 0) {\n try {\n json = JSON.parse(text);\n } catch {\n spinner.stop(\"failed\");\n p.log.error(\n `server returned non-JSON response (HTTP ${res.status}): ${text.slice(0, 200)}`,\n );\n process.exit(1);\n }\n }\n if (!res.ok || json.success !== true) {\n spinner.stop(\"failed\");\n const detail =\n json.error ||\n (text.length === 0\n ? \"empty response body\"\n : json.success === undefined\n ? `HTTP ${res.status} (response missing success field)`\n : `HTTP ${res.status}`);\n if (res.status === 401) {\n p.log.error(\n `${detail}. Set AGENTMEMORY_SECRET to match the server's secret and re-run.`,\n );\n } else if (res.status === 404) {\n p.log.error(\n `${detail}. The running agentmemory server does not expose /agentmemory/replay/import-jsonl — upgrade to v0.8.13 or later.`,\n );\n } else {\n p.log.error(detail);\n }\n process.exit(1);\n }\n spinner.stop(\n `imported ${json.imported ?? 0} file(s), ${json.observations ?? 0} observation(s) across ${json.sessionIds?.length || 0} session(s)`,\n );\n if (json.truncated) {\n const cap = json.maxFiles ?? 200;\n const upper = json.maxFilesUpperBound ?? 1000;\n const discovered = json.discovered ?? 0;\n const skipped = discovered - (json.imported ?? 0);\n const discoveredLabel = json.traversalCapped\n ? `${discovered}+ (traversal halted at safety cap)`\n : String(discovered);\n const baseMsg = `Hit the ${cap}-file scan cap; ${skipped} of ${discoveredLabel} discovered file(s) were skipped.`;\n // If we already saw more than the server's hard cap (or the\n // walker stopped early), bumping --max-files won't help on its\n // own — recommend batching by subdirectory.\n if (discovered > upper || json.traversalCapped) {\n p.log.warn(\n `${baseMsg} Tree exceeds the server's --max-files limit of ${upper}; ` +\n `batch by subdirectory (run import-jsonl once per project under ~/.claude/projects).`,\n );\n } else {\n const suggested = Math.min(\n Math.max((discovered || cap) + 100, cap * 2),\n upper,\n );\n p.log.warn(\n `${baseMsg} Re-run with --max-files=${suggested} (max ${upper}) or batch by subdirectory.`,\n );\n }\n }\n if (json.sessionIds && json.sessionIds.length > 0) {\n p.log.info(`View at ${getViewerUrl()} → Replay tab`);\n }\n } catch (err) {\n spinner.stop(\"failed\");\n if (err instanceof Error && err.name === \"TimeoutError\") {\n p.log.error(\"import timed out after 2 minutes\");\n } else {\n p.log.error(err instanceof Error ? err.message : String(err));\n }\n process.exit(1);\n }\n}\n\n// ---------------------------------------------------------------------------\n// `agentmemory remove` — clean uninstall.\n//\n// Planning logic lives in src/cli/remove-plan.ts so it's testable without\n// touching $HOME. This function loads the manifest, builds the plan,\n// double-confirms, then executes step by step.\n\nfunction loadConnectManifest(home: string): ConnectManifest | null {\n const path = join(home, \".agentmemory\", \"backups\", \"connect-manifest.json\");\n try {\n const raw = readFileSync(path, \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<ConnectManifest>;\n if (Array.isArray(parsed?.installed)) {\n return { installed: parsed.installed };\n }\n return null;\n } catch {\n return null;\n }\n}\n\nfunction probeLocalBinIiiVersion(home: string): string | null {\n const path = legacyLocalBinIii(home);\n if (!existsSync(path)) return null;\n return iiiBinVersion(path);\n}\n\nfunction safeDelete(path: string): { ok: boolean; message: string } {\n try {\n if (!existsSync(path)) return { ok: true, message: `not present (${path})` };\n const st = statSync(path);\n if (st.isDirectory()) {\n rmSync(path, { recursive: true, force: true });\n } else {\n unlinkSync(path);\n }\n return { ok: true, message: `deleted ${path}` };\n } catch (err) {\n return {\n ok: false,\n message: `failed ${path}: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n}\n\nasync function runRemove(): Promise<void> {\n p.intro(\"agentmemory remove\");\n const force = args.includes(\"--force\");\n const keepData = args.includes(\"--keep-data\");\n\n const home = homedir();\n const connectManifest = loadConnectManifest(home);\n const localBinIiiVersion = probeLocalBinIiiVersion(home);\n\n const options: RemoveOptions = { force, keepData };\n const plan = buildRemovePlan(\n {\n home,\n pinnedVersion: IIPINNED_VERSION,\n localBinIiiVersion,\n connectManifest,\n },\n options,\n );\n\n const applicable = plan.filter((it) => it.applicable);\n if (applicable.length === 0) {\n p.outro(\"Nothing to remove. agentmemory is already gone.\");\n return;\n }\n\n p.note(formatPlan(plan), \"destruction plan\");\n\n if (!force) {\n const proceed = await p.confirm({\n message: \"Proceed with these deletions?\",\n initialValue: false,\n });\n if (p.isCancel(proceed) || proceed !== true) {\n p.cancel(\"Cancelled. Nothing was deleted.\");\n return;\n }\n const sure = await p.confirm({\n message: \"This is irreversible. Continue?\",\n initialValue: false,\n });\n if (p.isCancel(sure) || sure !== true) {\n p.cancel(\"Cancelled. Nothing was deleted.\");\n return;\n }\n }\n\n for (const item of plan) {\n if (!item.applicable) continue;\n\n // alwaysAsk items get a per-item confirmation even with --force.\n if (item.alwaysAsk) {\n const ok = await p.confirm({\n message: `${item.description} — really delete${item.path ? ` ${item.path}` : \"\"}?`,\n initialValue: false,\n });\n if (p.isCancel(ok) || ok !== true) {\n p.log.info(`skipped: ${item.id}`);\n continue;\n }\n }\n\n if (item.id === \"stop-engine\") {\n try {\n const port = getRestPort();\n const portPids = findEnginePidsByPort(port);\n const pidfilePid = readEnginePidfile();\n const cands = new Set<number>();\n if (pidfilePid) cands.add(pidfilePid);\n for (const pid of portPids) cands.add(pid);\n for (const pid of cands) await signalAndWait(pid, \"SIGTERM\", 3000);\n clearEnginePidfile();\n clearEngineState();\n p.log.success(\n cands.size > 0\n ? `stopped engine (${cands.size} pid${cands.size === 1 ? \"\" : \"s\"})`\n : \"no engine running\",\n );\n } catch (err) {\n p.log.warn(\n `engine stop best-effort: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n continue;\n }\n\n if (!item.path) continue;\n const r = safeDelete(item.path);\n if (r.ok) p.log.success(r.message);\n else p.log.error(r.message);\n }\n\n p.outro(\n \"Done. agentmemory cleanly removed. The npm package itself: npm uninstall -g @agentmemory/agentmemory\",\n );\n}\n\nconst commands: Record<string, () => Promise<void>> = {\n init: runInit,\n connect: runConnectCmd,\n status: runStatus,\n doctor: runDoctor,\n demo: runDemo,\n upgrade: runUpgrade,\n stop: runStop,\n remove: runRemove,\n mcp: runMcp,\n \"import-jsonl\": runImportJsonl,\n};\n\nconst first = args[0] ?? \"\";\nasync function unknownCommand(): Promise<void> {\n p.log.error(\n `Unknown command: ${first}. Supported: ${Object.keys(commands).join(\", \")}. Run \\`agentmemory\\` with no arguments to start the memory server, or \\`agentmemory --help\\` for usage.`,\n );\n process.exit(1);\n}\n// Only a bare invocation or flag-style args boot the server; an unrecognized\n// word is an error. Previously any typo (or a guessed subcommand like\n// `agentmemory consolidate`) fell through to the full server boot and could\n// break a running daemon.\nconst handler = commands[first] ?? (first && !first.startsWith(\"-\") ? unknownCommand : main);\nhandler().catch((err) => {\n p.log.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.mjs","names":["workerPidfilePath","__dirname","findEnvExample","fsConstants","PATH_DELIMITER"],"sources":["../src/cli/doctor-diagnostics.ts","../src/cli/remove-plan.ts","../src/cli/ready-hint.ts","../src/cli/engine-install.ts","../src/cli/startup-stderr.ts","../src/cli/console.ts","../src/cli/process-state.ts","../src/cli/splash.ts","../src/cli/preferences.ts","../src/cli/onboarding.ts","../src/cli/capture.ts","../src/cli.ts"],"sourcesContent":["// Doctor v2 diagnostic catalog.\n//\n// Each entry is a self-describing diagnostic: a check function that returns\n// `{ ok, detail? }`, a human-readable message, an inline fix preview, and\n// an `apply` function that runs the fix. The list is exported as a pure\n// data structure so unit tests can assert on shape without bringing\n// @clack/prompts into the test harness.\n//\n// The runtime (src/cli.ts -> runDoctor) iterates the list, prompts the user\n// per check, and only re-runs the SAME diagnostic after a fix — never the\n// whole suite. Each fix returns `{ ok, message? }` so we can show a one-line\n// outcome before moving on.\n//\n// Doctor v2 surface:\n// agentmemory doctor # interactive: Fix/Skip/More/Quit per failed check\n// agentmemory doctor --all # apply every available fix without prompting (CI)\n// agentmemory doctor --dry-run # show what each fix WOULD do; execute nothing\n\nexport type DiagnosticStatus = {\n ok: boolean;\n /** Short status detail (one line). Shown alongside the check name. */\n detail?: string;\n};\n\nexport type DiagnosticFixResult = {\n ok: boolean;\n message?: string;\n};\n\nexport type DoctorContext = {\n /** Base URL for the running engine, e.g. http://localhost:3111 */\n baseUrl: string;\n /** Viewer URL, e.g. http://localhost:3113 */\n viewerUrl: string;\n /** Path to ~/.agentmemory/.env */\n envPath: string;\n /** Path to ~/.agentmemory/iii.pid */\n pidfilePath: string;\n /** Path to ~/.agentmemory/engine-state.json */\n enginePath: string;\n /** Pinned engine version (e.g. \"0.22.1\"). */\n pinnedVersion: string;\n};\n\nexport type Diagnostic = {\n /** Stable id. Used in --json and tests. */\n id: string;\n /** One-line problem statement shown to the user. */\n message: string;\n /** One-line description of WHAT the fix will do. Shown before the prompt. */\n fixPreview: string;\n /** Longer explanation shown when the user picks [?] More info. */\n moreInfo: string;\n /** Run the check; return ok=true if everything's fine, ok=false otherwise. */\n check: (ctx: DoctorContext) => Promise<DiagnosticStatus>;\n /** Apply the fix. Returns ok=true on success. */\n fix: (ctx: DoctorContext) => Promise<DiagnosticFixResult>;\n /** True when there's nothing to auto-fix (we only suggest). */\n manualOnly?: boolean;\n};\n\n// Diagnostic ids are stable for testing and machine-readable doctor output.\nexport const DIAGNOSTIC_IDS = [\n \"env-missing\",\n \"no-llm-provider-key\",\n \"engine-version-mismatch\",\n \"viewer-unreachable\",\n \"stale-pidfile\",\n \"env-placeholder-keys\",\n \"iii-on-path-not-local-bin\",\n] as const;\n\nexport type DiagnosticId = (typeof DIAGNOSTIC_IDS)[number];\n\n// Pure helpers (no I/O) — exported for direct unit testing.\n// ---------------------------------------------------------------------------\n\n/** Common placeholder values shipped in .env.example. */\nconst PLACEHOLDER_VALUES = new Set([\n \"\",\n \"your-key-here\",\n \"sk-ant-...\",\n \"sk-...\",\n \"changeme\",\n \"todo\",\n \"xxx\",\n]);\n\nconst PROVIDER_KEY_NAMES = [\n \"ANTHROPIC_API_KEY\",\n \"OPENAI_API_KEY\",\n \"GEMINI_API_KEY\",\n \"GOOGLE_API_KEY\",\n \"OPENROUTER_API_KEY\",\n \"MINIMAX_API_KEY\",\n] as const;\n\nexport function parseEnvFile(content: string): Record<string, string> {\n const out: Record<string, string> = {};\n for (const rawLine of content.split(/\\r?\\n/)) {\n const line = rawLine.trim();\n if (!line || line.startsWith(\"#\")) continue;\n const eq = line.indexOf(\"=\");\n if (eq < 0) continue;\n const key = line.slice(0, eq).trim();\n let value = line.slice(eq + 1).trim();\n // Strip surrounding quotes.\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n out[key] = value;\n }\n return out;\n}\n\n/** Returns the list of provider keys that look real (non-placeholder). */\nexport function realProviderKeys(env: Record<string, string>): string[] {\n return PROVIDER_KEY_NAMES.filter((k) => {\n const v = (env[k] ?? \"\").trim();\n if (!v) return false;\n if (PLACEHOLDER_VALUES.has(v.toLowerCase())) return false;\n // Reject values that are just dots/placeholders like \"xxxx-xxxx\".\n if (/^x+$/i.test(v.replace(/[-_]/g, \"\"))) return false;\n return true;\n });\n}\n\n/** Returns the list of provider key NAMES that exist but are placeholders. */\nexport function placeholderProviderKeys(env: Record<string, string>): string[] {\n return PROVIDER_KEY_NAMES.filter((k) => {\n const v = (env[k] ?? \"\").trim();\n if (!v) return false;\n if (PLACEHOLDER_VALUES.has(v.toLowerCase())) return true;\n if (/^x+$/i.test(v.replace(/[-_]/g, \"\"))) return true;\n return false;\n });\n}\n\n/**\n * Build the canonical diagnostic catalog.\n *\n * The factory takes the side-effect helpers as injected functions so tests\n * can swap them with stubs. Production callers pass real implementations\n * from src/cli.ts.\n */\nexport type DoctorEffects = {\n /** Does ~/.agentmemory/.env exist? */\n envFileExists: () => boolean;\n /** Read ~/.agentmemory/.env and return parsed key=value pairs. */\n readEnvFile: () => Record<string, string>;\n /** Is the iii engine PID in the pidfile still alive? */\n pidfilePidIsAlive: () => boolean | null;\n /** Does the pidfile exist on disk? */\n pidfileExists: () => boolean;\n /** Resolve the iii binary on PATH; return null if not found. */\n findIiiBinary: () => string | null;\n /** Path to ~/.agentmemory/bin/iii (the private install location). */\n localBinIiiPath: () => string;\n /** Run `iii --version`; null if it fails. */\n iiiBinaryVersion: (binPath: string) => string | null;\n /** Probe the viewer URL; true if it returns OK within timeoutMs. */\n viewerReachable: (timeoutMs?: number) => Promise<boolean>;\n /** Run init logic (copies .env.example). */\n runInit: () => Promise<DiagnosticFixResult>;\n /** Open a file in $EDITOR (or fallback). Resolves when editor exits. */\n openEditor: (path: string) => Promise<DiagnosticFixResult>;\n /** Run the iii installer. */\n runIiiInstaller: () => Promise<DiagnosticFixResult>;\n /** Stop the running engine cleanly. */\n runStop: () => Promise<DiagnosticFixResult>;\n /** Start the engine (waits for /livez). */\n runStart: () => Promise<DiagnosticFixResult>;\n /** Clear pidfile + engine-state. */\n clearEnginePidAndState: () => void;\n};\n\nexport function buildDiagnostics(effects: DoctorEffects): Diagnostic[] {\n return [\n {\n id: \"env-missing\",\n message: \"~/.agentmemory/.env is missing.\",\n fixPreview: \"Copy .env.example into ~/.agentmemory/.env (your keys file).\",\n moreInfo:\n \"agentmemory reads provider API keys (Anthropic, OpenAI, Gemini, …) from ~/.agentmemory/.env. \" +\n \"Without this file the daemon falls back to BM25-only search and no LLM-backed enrichment runs.\",\n check: async () => ({\n ok: effects.envFileExists(),\n detail: effects.envFileExists() ? undefined : \"no env file\",\n }),\n fix: () => effects.runInit(),\n },\n {\n id: \"no-llm-provider-key\",\n message: \"No LLM provider API key found in ~/.agentmemory/.env.\",\n fixPreview: \"Open ~/.agentmemory/.env in $EDITOR and paste your key, then re-check.\",\n moreInfo:\n \"Set at least one of: ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, \" +\n \"OPENROUTER_API_KEY, MINIMAX_API_KEY. The daemon picks the first that resolves \" +\n \"to a real (non-placeholder) value at startup.\",\n check: async () => {\n if (!effects.envFileExists()) {\n return { ok: false, detail: \"env file missing (run env-missing fix first)\" };\n }\n const env = effects.readEnvFile();\n const real = realProviderKeys(env);\n return {\n ok: real.length > 0,\n detail: real.length > 0 ? `found: ${real.join(\", \")}` : \"no provider key set\",\n };\n },\n fix: (ctx) => effects.openEditor(ctx.envPath),\n },\n {\n id: \"engine-version-mismatch\",\n message: \"iii binary on PATH doesn't match the version agentmemory pins to.\",\n fixPreview:\n \"Re-run the iii installer for the pinned version and restart the engine.\",\n moreInfo:\n \"agentmemory pins the iii engine to a specific release because newer engines \" +\n \"use a different worker model. Running a mismatched binary surfaces as EPIPE \" +\n \"reconnect loops and empty search results.\",\n check: async (ctx) => {\n const bin = effects.findIiiBinary();\n if (!bin) return { ok: false, detail: \"iii not on PATH\" };\n const v = effects.iiiBinaryVersion(bin);\n if (!v) return { ok: false, detail: \"iii on PATH but --version failed\" };\n return {\n ok: v === ctx.pinnedVersion,\n detail: `${v} (pinned ${ctx.pinnedVersion})`,\n };\n },\n fix: async () => {\n const r = await effects.runIiiInstaller();\n if (!r.ok) return r;\n // Best-effort restart: stop then start.\n await effects.runStop();\n return effects.runStart();\n },\n },\n {\n id: \"viewer-unreachable\",\n message: \"Viewer port not reachable.\",\n fixPreview: \"Stop the engine, restart it, and retry the viewer probe.\",\n moreInfo:\n \"The viewer is served on REST port + 2 (default 3113). If it never came up \" +\n \"the most common cause is port collision; a sibling PR ships auto-bump for \" +\n \"this case. If that lands first this check just verifies; otherwise restart \" +\n \"the engine to retry binding.\",\n check: async () => ({\n ok: await effects.viewerReachable(),\n detail: undefined,\n }),\n fix: async () => {\n const stopped = await effects.runStop();\n if (!stopped.ok) return stopped;\n return effects.runStart();\n },\n },\n {\n id: \"stale-pidfile\",\n message: \"Stale pidfile: pid recorded but the process is gone.\",\n fixPreview: \"Clear ~/.agentmemory/iii.pid + engine-state.json, then restart.\",\n moreInfo:\n \"When the engine crashes hard (kill -9, OOM, host reboot) the pidfile sticks \" +\n \"around. agentmemory refuses to start a second engine on top of a stale pid, \" +\n \"so this state must be cleared explicitly.\",\n check: async () => {\n if (!effects.pidfileExists()) return { ok: true, detail: \"no pidfile\" };\n const alive = effects.pidfilePidIsAlive();\n if (alive === null) return { ok: true, detail: \"pidfile unreadable\" };\n return {\n ok: alive,\n detail: alive ? \"pid is alive\" : \"pid is gone\",\n };\n },\n fix: async () => {\n effects.clearEnginePidAndState();\n return effects.runStart();\n },\n },\n {\n id: \"env-placeholder-keys\",\n message: \"~/.agentmemory/.env contains placeholder/empty API keys.\",\n fixPreview: \"Open ~/.agentmemory/.env in $EDITOR to paste real values.\",\n moreInfo:\n \"Lines like ANTHROPIC_API_KEY=sk-ant-... or =your-key-here are treated as \" +\n \"absent. The daemon will fall back to BM25-only search. Replace placeholders \" +\n \"with real keys or comment the line out.\",\n check: async () => {\n if (!effects.envFileExists()) {\n return { ok: true, detail: \"env file missing (handled by env-missing)\" };\n }\n const env = effects.readEnvFile();\n const placeholders = placeholderProviderKeys(env);\n return {\n ok: placeholders.length === 0,\n detail:\n placeholders.length === 0\n ? undefined\n : `placeholder: ${placeholders.join(\", \")}`,\n };\n },\n fix: (ctx) => effects.openEditor(ctx.envPath),\n },\n {\n id: \"iii-on-path-not-local-bin\",\n message:\n \"iii is on PATH but not at agentmemory's private install path.\",\n fixPreview:\n \"Install the pinned version to ~/.agentmemory/bin — won't touch your PATH.\",\n moreInfo:\n \"agentmemory installs its pinned engine to ~/.agentmemory/bin/iii so a \" +\n \"user-managed iii on PATH (homebrew, cargo, manual install) stays untouched. \" +\n \"When agentmemory needs the pin and PATH doesn't have it, it falls back to the \" +\n \"private install. If neither exists, run the installer.\",\n manualOnly: true,\n check: async () => {\n const bin = effects.findIiiBinary();\n if (!bin) return { ok: true, detail: \"iii not on PATH (handled elsewhere)\" };\n const localBin = effects.localBinIiiPath();\n return {\n ok: bin === localBin,\n detail: bin === localBin ? undefined : `iii at: ${bin}`,\n };\n },\n fix: async () =>\n effects.runIiiInstaller().then((r) => ({\n ok: r.ok,\n message:\n r.message ??\n \"Installer wrote to ~/.agentmemory/bin/iii. Your PATH wasn't modified.\",\n })),\n },\n ];\n}\n\nexport type DoctorRunMode = \"interactive\" | \"all\" | \"dry-run\";\n\n/**\n * Run all diagnostics and return their initial status (no fixes applied).\n * Useful for tests and for `--dry-run` mode.\n */\nexport async function runAllChecks(\n ctx: DoctorContext,\n diagnostics: Diagnostic[],\n): Promise<Array<{ diagnostic: Diagnostic; status: DiagnosticStatus }>> {\n const results: Array<{ diagnostic: Diagnostic; status: DiagnosticStatus }> = [];\n for (const d of diagnostics) {\n const status = await d.check(ctx);\n results.push({ diagnostic: d, status });\n }\n return results;\n}\n\n/**\n * Dry-run output: each failing check's fix preview, prefixed by the diagnostic\n * message. Pure function so we can snapshot-test the format.\n */\nexport function dryRunPlan(\n ctx: DoctorContext,\n results: Array<{ diagnostic: Diagnostic; status: DiagnosticStatus }>,\n): string[] {\n const lines: string[] = [];\n let n = 0;\n for (const { diagnostic, status } of results) {\n if (status.ok) continue;\n n++;\n lines.push(`${n}. [${diagnostic.id}] ${diagnostic.message}`);\n lines.push(` would fix: ${diagnostic.fixPreview}`);\n if (status.detail) lines.push(` detail: ${status.detail}`);\n }\n if (lines.length === 0) {\n lines.push(`All checks passing for ${ctx.baseUrl} — no fixes to run.`);\n }\n return lines;\n}\n","// `agentmemory remove` — destruction plan.\n//\n// Generating the plan is a pure function of the on-disk state (which files\n// exist, whether ~/.local/bin/iii matches the version we installed, the\n// connect-manifest contents). All side effects live in src/cli.ts; this\n// module owns only the planning logic so it's unit-testable without\n// touching $HOME.\n//\n// CLI surface:\n// agentmemory remove # interactive, double-confirms\n// agentmemory remove --force # skip confirmations\n// agentmemory remove --keep-data # remove binaries+symlinks, keep memory data\n\nimport { existsSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { runtimeConfigPath } from \"./engine-launch.js\";\n\nexport type RemovePlanItem = {\n /** Stable id, used in tests and CLI output. */\n id: string;\n /** Human-readable description of the action. */\n description: string;\n /** Absolute path being acted on (or null for non-fs actions). */\n path: string | null;\n /** Whether this item is `ask-again` even with --force (e.g. memory data). */\n alwaysAsk: boolean;\n /** Whether the file actually exists / action is meaningful. Plan-time hint. */\n applicable: boolean;\n /** Bytes (for files) or -1 (unknown / dir). Pure metadata. */\n sizeBytes: number;\n};\n\nexport type RemoveOptions = {\n /** Skip confirmations (still asks separately about always-ask items). */\n force: boolean;\n /** Keep ~/.agentmemory/* user data; only remove binaries/symlinks. */\n keepData: boolean;\n /** Keep engine ownership metadata needed to recover retained Docker data. */\n preserveRuntimeState?: boolean;\n};\n\nexport type RemoveContext = {\n /** $HOME (so tests can sandbox). */\n home: string;\n /** Resolved directory containing pidfiles and engine ownership state. */\n runtimeDir: string;\n /** Resolved iii-engine data directory selected for this invocation. */\n dataDir: string;\n /** Pinned engine version we expect ~/.local/bin/iii to match. */\n pinnedVersion: string;\n /**\n * `iii --version` result for ~/.local/bin/iii, or null if it's missing /\n * unreadable / not executable. Passed in so the plan module stays pure.\n */\n localBinIiiVersion: string | null;\n /** Loaded connect manifest, or null if missing. */\n connectManifest: ConnectManifest | null;\n};\n\n/**\n * The `agentmemory connect` PR writes this manifest at\n * ~/.agentmemory/backups/connect-manifest.json. We tolerate it being absent\n * (older versions, fresh installs) by treating it as `{ installed: [] }`.\n */\nexport type ConnectManifest = {\n installed: Array<{\n /** Target path the connect command wrote (symlink or file). */\n target: string;\n /** Agent label, e.g. \"claude-code\", \"cursor\". */\n agent?: string;\n /** Whether this was a symlink (true) or copy (false). */\n symlink?: boolean;\n }>;\n};\n\nexport function pidfilePath(runtimeDir: string): string {\n return join(runtimeDir, \"iii.pid\");\n}\n\nexport function workerPidfilePath(runtimeDir: string): string {\n return join(runtimeDir, \"worker.pid\");\n}\n\nexport function enginePath(runtimeDir: string): string {\n return join(runtimeDir, \"engine-state.json\");\n}\n\nexport function envPath(home: string): string {\n return join(home, \".agentmemory\", \".env\");\n}\n\nexport function preferencesPath(home: string): string {\n return join(home, \".agentmemory\", \"preferences.json\");\n}\n\nexport function backupsDir(home: string): string {\n return join(home, \".agentmemory\", \"backups\");\n}\n\n// Platform-aware binary name. Windows requires the .exe suffix or the\n// existsSync probe misses the installed binary.\nfunction iiiBinFile(): string {\n return process.platform === \"win32\" ? \"iii.exe\" : \"iii\";\n}\n\n// Legacy install location. Older agentmemory versions wrote the pinned iii\n// engine here. Kept so `agentmemory remove` can still clean up after them.\nexport function legacyLocalBinIii(home: string): string {\n return join(home, \".local\", \"bin\", iiiBinFile());\n}\n\n// Current private install location. Lives under ~/.agentmemory/ so it\n// stays isolated from any user-managed iii on PATH.\nexport function privateIiiBin(home: string): string {\n return join(home, \".agentmemory\", \"bin\", iiiBinFile());\n}\n\n// Back-compat shim for any caller still importing the old name.\nexport const localBinIii = privateIiiBin;\n\nfunction safeSize(path: string): number {\n try {\n return statSync(path).size;\n } catch {\n return -1;\n }\n}\n\nfunction pathExists(path: string): boolean {\n try {\n return existsSync(path);\n } catch {\n return false;\n }\n}\n\n/**\n * Build the destruction plan for `agentmemory remove`.\n *\n * Plan items are returned regardless of whether `applicable` is true — the\n * caller can decide whether to skip-and-log or hide entirely. This keeps\n * the structure stable for tests.\n */\nexport function buildRemovePlan(\n ctx: RemoveContext,\n options: RemoveOptions,\n): RemovePlanItem[] {\n const {\n home,\n runtimeDir,\n dataDir,\n pinnedVersion,\n localBinIiiVersion,\n connectManifest,\n } = ctx;\n const plan: RemovePlanItem[] = [];\n\n plan.push({\n id: \"stop-engine\",\n description: \"Stop running iii-engine (if any) cleanly\",\n path: null,\n alwaysAsk: false,\n applicable:\n pathExists(pidfilePath(runtimeDir)) ||\n pathExists(workerPidfilePath(runtimeDir)) ||\n pathExists(enginePath(runtimeDir)),\n sizeBytes: -1,\n });\n\n plan.push({\n id: \"pidfile\",\n description: \"Delete pidfile\",\n path: pidfilePath(runtimeDir),\n alwaysAsk: false,\n applicable: pathExists(pidfilePath(runtimeDir)),\n sizeBytes: safeSize(pidfilePath(runtimeDir)),\n });\n\n plan.push({\n id: \"worker-pidfile\",\n description: \"Delete worker pidfile\",\n path: workerPidfilePath(runtimeDir),\n alwaysAsk: false,\n applicable: pathExists(workerPidfilePath(runtimeDir)),\n sizeBytes: safeSize(workerPidfilePath(runtimeDir)),\n });\n\n plan.push({\n id: \"engine-state\",\n description: \"Delete engine-state.json\",\n path: enginePath(runtimeDir),\n alwaysAsk: false,\n applicable:\n !options.preserveRuntimeState && pathExists(enginePath(runtimeDir)),\n sizeBytes: safeSize(enginePath(runtimeDir)),\n });\n\n // .env holds the user's API keys. Always ask before deleting, even on\n // --force. --keep-data keeps it as part of \"user data\".\n plan.push({\n id: \"env\",\n description: \"Delete .env (your API keys) — will ask separately\",\n path: envPath(home),\n alwaysAsk: true,\n applicable: !options.keepData && pathExists(envPath(home)),\n sizeBytes: safeSize(envPath(home)),\n });\n\n plan.push({\n id: \"preferences\",\n description: \"Delete preferences.json\",\n path: preferencesPath(home),\n alwaysAsk: false,\n applicable: !options.keepData && pathExists(preferencesPath(home)),\n sizeBytes: safeSize(preferencesPath(home)),\n });\n\n plan.push({\n id: \"backups\",\n description: \"Delete backups/ directory (connect manifest + backups)\",\n path: backupsDir(home),\n alwaysAsk: false,\n applicable: !options.keepData && pathExists(backupsDir(home)),\n sizeBytes: -1,\n });\n\n plan.push({\n id: \"runtime-config\",\n description: \"Delete generated iii-config.runtime.yaml\",\n path: runtimeConfigPath(dataDir),\n alwaysAsk: false,\n applicable: pathExists(runtimeConfigPath(dataDir)),\n sizeBytes: safeSize(runtimeConfigPath(dataDir)),\n });\n\n // Iterate over connect-installed agent symlinks. We always honor these\n // (even with --keep-data, since they're outside ~/.agentmemory/).\n if (connectManifest?.installed?.length) {\n for (const entry of connectManifest.installed) {\n plan.push({\n id: `connect:${entry.target}`,\n description: `Remove agent connection (${entry.agent ?? \"unknown\"})`,\n path: entry.target,\n alwaysAsk: false,\n applicable: pathExists(entry.target),\n sizeBytes: safeSize(entry.target),\n });\n }\n }\n\n // Private install (~/.agentmemory/bin/iii) — agentmemory owns this path,\n // so it's always safe to remove. The version check still gates the\n // legacy ~/.local/bin/iii path which may be a user-managed install we\n // don't own.\n const privIii = privateIiiBin(home);\n if (pathExists(privIii)) {\n plan.push({\n id: \"private-bin-iii\",\n description: `Delete ~/.agentmemory/bin/iii (agentmemory's private install)`,\n path: privIii,\n alwaysAsk: false,\n applicable: true,\n sizeBytes: safeSize(privIii),\n });\n }\n\n // Legacy ~/.local/bin/iii — only remove if it matches the version we\n // installed. Older agentmemory wrote here; newer versions don't but the\n // file may still be a leftover from a previous install.\n // Heuristic: spawn `iii --version`; if it returns pinnedVersion, safe to\n // remove. Otherwise mark `alwaysAsk` so the operator confirms explicitly.\n const legacyIii = legacyLocalBinIii(home);\n if (pathExists(legacyIii)) {\n const matches = localBinIiiVersion === pinnedVersion;\n plan.push({\n id: \"legacy-local-bin-iii\",\n description: matches\n ? `Delete ~/.local/bin/iii (legacy install location, matches pinned v${pinnedVersion})`\n : `Delete ~/.local/bin/iii (legacy install location, version ${localBinIiiVersion ?? \"unknown\"} != pinned v${pinnedVersion}) — will ask`,\n path: legacyIii,\n alwaysAsk: !matches,\n applicable: true,\n sizeBytes: safeSize(legacyIii),\n });\n }\n\n // Memory data dir — ALWAYS asks separately, even with --force. Default\n // behavior is keep.\n plan.push({\n id: \"data-dir\",\n description: `Delete memory data directory (${dataDir}) — will ask separately`,\n path: dataDir,\n alwaysAsk: true,\n applicable: !options.keepData && pathExists(dataDir),\n sizeBytes: -1,\n });\n\n return plan;\n}\n\n/** Format a plan for the user — one line per item. */\nexport function formatPlan(plan: RemovePlanItem[]): string {\n return plan\n .filter((p) => p.applicable)\n .map((p, i) => {\n const tag = p.alwaysAsk ? \" [asks]\" : \"\";\n const sz =\n p.sizeBytes > 0 ? ` (${humanBytes(p.sizeBytes)})` : \"\";\n return ` ${i + 1}. ${p.description}${tag}${sz}${p.path ? `\\n ${p.path}` : \"\"}`;\n })\n .join(\"\\n\");\n}\n\nfunction humanBytes(n: number): string {\n if (n < 1024) return `${n} B`;\n if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;\n return `${(n / (1024 * 1024)).toFixed(1)} MB`;\n}\n","const DEFAULT_REST_PORT = 3111;\n\nexport function portFlagSuffix(restPort: number, instance: number): string {\n if (instance > 0 && restPort === DEFAULT_REST_PORT + instance * 100) {\n return ` --instance ${instance}`;\n }\n return restPort === DEFAULT_REST_PORT ? \"\" : ` --port ${restPort}`;\n}\n","import { spawnSync } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { readFileSync, rmSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport const III_INSTALL_CONNECT_TIMEOUT_S = 15;\nexport const III_INSTALL_MAX_TIME_S = 300;\nexport const III_INSTALL_SPAWN_TIMEOUT_MS =\n (III_INSTALL_CONNECT_TIMEOUT_S + III_INSTALL_MAX_TIME_S + 30) * 1000;\n\ntype ChecksumTable = Readonly<Record<string, Readonly<Record<string, string>>>>;\n\nexport const III_RELEASE_SHA256: ChecksumTable = {\n \"0.22.1\": {\n \"iii-aarch64-apple-darwin.tar.gz\": \"2b309019b909a896cae874dc947e2cdf877b4f3c51dd026b79850af858517fa4\",\n \"iii-x86_64-apple-darwin.tar.gz\": \"6d33940db2d3ad6a9aef9837aa5b89bf5c5e4acd0679e8178fec258af229d7e1\",\n \"iii-x86_64-unknown-linux-gnu.tar.gz\": \"34d4bd2ec1873e6114bb836be7db9cb3f410d0d63353d240917f0bc9c30df13b\",\n \"iii-aarch64-unknown-linux-gnu.tar.gz\": \"87efc60210c1580ef2e11b13c679a4dad91917a9d80f737c5ba7e3475b3ca413\",\n \"iii-armv7-unknown-linux-gnueabihf.tar.gz\": \"af5dfc45149678c647e5adaca55c055428eebfa73d65884b052c30c98abcfd19\",\n \"iii-x86_64-pc-windows-msvc.zip\": \"d862bf7cf1e864f3290c8a6fc17c308c6ecac097cb2666e4a739efc0040aae96\",\n \"iii-aarch64-pc-windows-msvc.zip\": \"4777a48cee3fc1a742daee929e3d943df09e4ddd3357d27a33d31c9dc9e520ac\",\n },\n};\n\nexport function expectedIiiSha256(\n version: string,\n asset: string,\n checksums: ChecksumTable = III_RELEASE_SHA256,\n): string | null {\n return checksums[version]?.[asset] ?? null;\n}\n\nexport function sha256File(path: string): string {\n return createHash(\"sha256\").update(readFileSync(path)).digest(\"hex\");\n}\n\nfunction curlTimeoutFlags(): string {\n return `--connect-timeout ${III_INSTALL_CONNECT_TIMEOUT_S} --max-time ${III_INSTALL_MAX_TIME_S}`;\n}\n\nexport function iiiArchivePath(binDir: string): string {\n return join(binDir, \".iii-download.tar.gz\");\n}\n\nexport function iiiDownloadShellCommand(): string {\n return `mkdir -p \"$2\" && rm -f \"$3\" && if curl -fsSL ${curlTimeoutFlags()} -o \"$3\" \"$1\"; then :; else code=$?; rm -f \"$3\"; exit $code; fi`;\n}\n\nexport function iiiExtractShellCommand(): string {\n return 'if tar -xzf \"$1\" -C \"$2\"; then rm -f \"$1\"; else code=$?; rm -f \"$1\"; exit $code; fi && chmod +x \"$3\"';\n}\n\nexport function iiiManualInstallCommand(\n releaseUrl: string,\n binDir: string,\n binPath: string,\n sha256: string | null,\n): string {\n const verify = sha256\n ? ` && printf '%s %s\\\\n' \"${sha256}\" \"$archive\" | { sha256sum -c - 2>/dev/null || shasum -a 256 -c -; }`\n : \"\";\n return `mkdir -p \"${binDir}\" && archive=\"$(mktemp \"${binDir}/.iii-download.XXXXXX\")\" && { curl -fL --connect-timeout ${III_INSTALL_CONNECT_TIMEOUT_S} -o \"$archive\" \"${releaseUrl}\"${verify} && tar -xzf \"$archive\" -C \"${binDir}\"; code=$?; rm -f \"$archive\"; (exit $code); } && chmod +x \"${binPath}\"`;\n}\n\nexport function describeInstallFailure(result: {\n error?: Error & { code?: string };\n signal?: NodeJS.Signals | null;\n status?: number | null;\n stderr?: string | null;\n stdout?: string | null;\n}): string {\n if (result.error?.code === \"ETIMEDOUT\") {\n return `timed out after ${Math.round(III_INSTALL_SPAWN_TIMEOUT_MS / 1000)} s`;\n }\n const output = (result.stderr || result.stdout || \"\").toString().trim();\n if (output) return output;\n if (result.status === 28) {\n return `download timed out (no connection within ${III_INSTALL_CONNECT_TIMEOUT_S} s or not finished within ${III_INSTALL_MAX_TIME_S} s)`;\n }\n if (result.signal) return `installer stopped by ${result.signal}`;\n if (result.error) return result.error.message;\n return `installer exited with status ${result.status ?? \"unknown\"}`;\n}\n\nexport type IiiInstallOutcome =\n | { ok: true }\n | { ok: false; reason: \"no-checksum\" | \"download\" | \"checksum\" | \"extract\"; detail: string };\n\nexport function installIiiArchive(opts: {\n sh: string;\n releaseUrl: string;\n version: string;\n asset: string;\n binDir: string;\n binPath: string;\n env?: NodeJS.ProcessEnv;\n checksums?: ChecksumTable;\n}): IiiInstallOutcome {\n const expected = expectedIiiSha256(opts.version, opts.asset, opts.checksums);\n if (!expected) {\n return {\n ok: false,\n reason: \"no-checksum\",\n detail: `no pinned SHA-256 for ${opts.asset} in iii v${opts.version}, so the download cannot be verified`,\n };\n }\n const run = (script: string, args: string[]) =>\n spawnSync(opts.sh, [\"-c\", script, \"sh\", ...args], {\n stdio: \"pipe\",\n encoding: \"utf-8\",\n timeout: III_INSTALL_SPAWN_TIMEOUT_MS,\n env: opts.env ?? process.env,\n });\n\n const archive = iiiArchivePath(opts.binDir);\n const download = run(iiiDownloadShellCommand(), [opts.releaseUrl, opts.binDir, archive]);\n if (download.status !== 0) {\n return { ok: false, reason: \"download\", detail: describeInstallFailure(download) };\n }\n\n let actual: string;\n try {\n actual = sha256File(archive);\n } catch (err) {\n rmSync(archive, { force: true });\n return { ok: false, reason: \"download\", detail: err instanceof Error ? err.message : String(err) };\n }\n if (actual !== expected) {\n rmSync(archive, { force: true });\n return {\n ok: false,\n reason: \"checksum\",\n detail: `SHA-256 mismatch for ${opts.asset}: expected ${expected}, got ${actual}. The download was deleted and nothing was installed`,\n };\n }\n\n const extract = run(iiiExtractShellCommand(), [archive, opts.binDir, opts.binPath]);\n if (extract.status !== 0) {\n return { ok: false, reason: \"extract\", detail: describeInstallFailure(extract) };\n }\n return { ok: true };\n}\n","export interface StartupStderrCapture {\n append(chunk: Buffer): void;\n text(): string;\n}\n\nexport function createStartupStderrCapture(\n maxBytes = 16 * 1024,\n): StartupStderrCapture {\n const chunks: Buffer[] = [];\n let capturedBytes = 0;\n\n return {\n append(chunk: Buffer): void {\n if (capturedBytes >= maxBytes) return;\n const slice = chunk.subarray(0, maxBytes - capturedBytes);\n chunks.push(slice);\n capturedBytes += slice.length;\n },\n text(): string {\n return Buffer.concat(chunks).toString(\"utf8\");\n },\n };\n}\n","export interface ConsoleLaunch {\n iiiBin: string;\n consolePort: number;\n restPort: number;\n streamPort: number;\n enginePort: number;\n extraArgs: string[];\n}\n\nconst GLOBAL_VALUE_FLAGS = new Set([\"--port\", \"--instance\", \"--data-dir\", \"--tools\"]);\nconst GLOBAL_BOOLEAN_FLAGS = new Set([\"--verbose\", \"-v\", \"--no-engine\"]);\n\nexport function defaultConsolePort(viewerPort: number): number {\n return viewerPort + 1;\n}\n\nfunction readPort(raw: string | undefined, flag: string): number {\n const port = raw === undefined ? Number.NaN : Number(raw);\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new Error(`${flag} needs a port between 1 and 65535`);\n }\n return port;\n}\n\nexport function parseConsoleArgs(\n tail: string[],\n fallbackPort: number,\n): { consolePort: number; extraArgs: string[] } {\n let consolePort = fallbackPort;\n const extraArgs: string[] = [];\n for (let i = 0; i < tail.length; i++) {\n const arg = tail[i]!;\n if (arg === \"--console-port\") {\n consolePort = readPort(tail[i + 1], arg);\n i++;\n continue;\n }\n if (arg.startsWith(\"--console-port=\")) {\n consolePort = readPort(arg.slice(\"--console-port=\".length), \"--console-port\");\n continue;\n }\n if (GLOBAL_VALUE_FLAGS.has(arg)) {\n i++;\n continue;\n }\n if ([...GLOBAL_VALUE_FLAGS].some((flag) => arg.startsWith(`${flag}=`))) continue;\n if (GLOBAL_BOOLEAN_FLAGS.has(arg)) continue;\n extraArgs.push(arg);\n }\n return { consolePort, extraArgs };\n}\n\nexport function consoleArgs(launch: ConsoleLaunch): string[] {\n return [\n \"console\",\n \"--port\",\n String(launch.consolePort),\n \"--engine-port\",\n String(launch.restPort),\n \"--ws-port\",\n String(launch.streamPort),\n \"--bridge-port\",\n String(launch.enginePort),\n ...launch.extraArgs,\n ];\n}\n","export function processStatIsRunning(stat: string): boolean {\n return !stat.trimStart().startsWith(\"Z\");\n}\n","// Terminal-width-aware splash banner for the agentmemory CLI.\n//\n// Three render tiers, picked from `process.stdout.columns`:\n//\n// >= 120 cols: full block-art logo + tagline.\n// 80–119 cols: compact monospace title + tagline.\n// < 80 cols: single-line `agentmemory v<VERSION>`.\n//\n// The brand accent is the orange `#FF6B35` we already use in the README\n// and viewer; we render it through ANSI 38;5;208 (the closest xterm-256\n// match) when stdout is a TTY, and fall back to plain text otherwise.\n// No colour bytes are hard-coded into the strings themselves so that\n// piping the banner to a file (`agentmemory > log`) stays clean.\n//\n// We don't pull in chalk/picocolors — picocolors is a transitive dep but\n// we never want to depend on transitives directly. The two ANSI escape\n// helpers below are the entire colour surface and they degrade to\n// no-ops automatically.\n\nconst IS_COLOR_TTY = !!process.stdout.isTTY && !process.env[\"NO_COLOR\"];\n\nfunction accent(s: string): string {\n // 256-colour orange that visually matches #FF6B35 in most modern\n // terminal palettes. We pick 208 (a true orange) over the closer-but-\n // pinker 209 because it reads as the brand colour on both dark and\n // light backgrounds.\n return IS_COLOR_TTY ? `\\x1b[38;5;208m${s}\\x1b[0m` : s;\n}\n\nfunction dim(s: string): string {\n return IS_COLOR_TTY ? `\\x1b[2m${s}\\x1b[22m` : s;\n}\n\nfunction bold(s: string): string {\n return IS_COLOR_TTY ? `\\x1b[1m${s}\\x1b[22m` : s;\n}\n\nfunction getTerminalWidth(): number {\n const w = process.stdout.columns;\n return typeof w === \"number\" && w > 0 ? w : 80;\n}\n\nconst TAGLINE = \"Persistent memory for AI coding agents\";\n\n// \"agentmemory\" rendered in figlet's standard font (verified output —\n// regenerate via `figlet agentmemory` if you change the wordmark). Each\n// row is exactly 70 columns wide so the banner aligns cleanly inside\n// the 2-col left margin we add below.\nfunction fullBanner(version: string): string {\n const logo = [\n \" _ \",\n \" __ _ __ _ ___ _ __ | |_ _ __ ___ ___ _ __ ___ ___ _ __ _ _ \",\n \" / _` |/ _` |/ _ \\\\ '_ \\\\| __| '_ ` _ \\\\ / _ \\\\ '_ ` _ \\\\ / _ \\\\| '__| | | |\",\n \"| (_| | (_| | __/ | | | |_| | | | | | __/ | | | | | (_) | | | |_| |\",\n \" \\\\__,_|\\\\__, |\\\\___|_| |_|\\\\__|_| |_| |_|\\\\___|_| |_| |_|\\\\___/|_| \\\\__, |\",\n \" |___/ |___/ \",\n ];\n const lines: string[] = [\"\", ...logo.map((line) => \" \" + accent(line))];\n lines.push(\"\");\n lines.push(\" \" + bold(TAGLINE) + \" \" + dim(`v${version}`));\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n\nfunction compactBanner(version: string): string {\n const title = \" \" + bold(accent(\"agentmemory\"));\n const meta = \" \" + dim(`v${version} · ${TAGLINE}`);\n return [\"\", title, meta, \"\"].join(\"\\n\");\n}\n\nfunction minimalBanner(version: string): string {\n return `${accent(\"agentmemory\")} ${dim(`v${version}`)}`;\n}\n\nexport function renderSplash(version: string): void {\n const width = getTerminalWidth();\n let out: string;\n if (width >= 120) {\n out = fullBanner(version);\n } else if (width >= 80) {\n out = compactBanner(version);\n } else {\n out = minimalBanner(version);\n }\n process.stdout.write(out + \"\\n\");\n}\n","// JSON-backed CLI preferences.\n//\n// Lives at `~/.agentmemory/preferences.json`. The agentmemory daemon\n// already owns `~/.agentmemory/.env`, `iii.pid`, `engine-state.json` —\n// adding one more sibling here keeps the install-state surface in one\n// place.\n//\n// All functions are synchronous, mirroring the pidfile / engine-state\n// helpers in src/cli.ts. We never throw: read failures collapse to\n// defaults; write failures swallow silently. Preferences are a UX\n// nicety, not data — corrupting `iii.pid` matters, corrupting this\n// file does not.\n//\n// Writes are atomic via tmp + rename so a Ctrl+C between the open and\n// the final write can't leave a half-written JSON blob on disk that\n// the next read would refuse to parse.\n\nimport {\n closeSync,\n existsSync,\n fsyncSync,\n mkdirSync,\n openSync,\n readFileSync,\n renameSync,\n unlinkSync,\n writeSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport interface Prefs {\n schemaVersion: 1;\n // Most recently picked single agent (for \"use last agent\" style flows).\n lastAgent: string | null;\n // The full multi-select set from the last onboarding run.\n lastAgents: string[];\n // Most recently picked LLM provider; `null` means BM25-only mode.\n lastProvider: string | null;\n // Once true, splash is rendered only on first run / explicit --reset.\n // The first onboarding sets this to true so the second invocation\n // skips the banner.\n skipSplash: boolean;\n // Reserved for a later \"do not nag me about the npx vs install\n // tradeoff\" toggle. Kept on the schema so we don't have to bump\n // schemaVersion when we ship the flag.\n skipNpxHint: boolean;\n // Set to true when the user declines the \"install agentmemory\n // globally?\" prompt on first npx run. We never ask again on this\n // machine so the prompt stays a one-time DX nudge, not a nag.\n skipGlobalInstall: boolean;\n // ISO timestamp of the first time onboarding completed. Set once,\n // never updated, so we can show \"you joined agentmemory N days ago\"\n // copy in /status later without keeping a separate file.\n firstRunAt: string | null;\n // Set to true once the user has answered the context-injection prompt\n // (either way). We never re-ask after this so the prompt stays a\n // one-time choice, matching the skipGlobalInstall\n // never-nag pattern.\n injectContextChosen: boolean;\n}\n\nconst DEFAULTS: Prefs = {\n schemaVersion: 1,\n lastAgent: null,\n lastAgents: [],\n lastProvider: null,\n skipSplash: false,\n skipNpxHint: false,\n skipGlobalInstall: false,\n firstRunAt: null,\n injectContextChosen: false,\n};\n\nexport function prefsDir(): string {\n return join(homedir(), \".agentmemory\");\n}\n\nexport function prefsPath(): string {\n return join(prefsDir(), \"preferences.json\");\n}\n\nexport function readPrefs(): Prefs {\n try {\n if (!existsSync(prefsPath())) return { ...DEFAULTS };\n const raw = readFileSync(prefsPath(), \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<Prefs>;\n return { ...DEFAULTS, ...parsed, schemaVersion: 1 };\n } catch {\n return { ...DEFAULTS };\n }\n}\n\nexport function writePrefs(p: Partial<Prefs>): void {\n try {\n const dir = prefsDir();\n mkdirSync(dir, { recursive: true });\n const current = readPrefs();\n const next: Prefs = { ...current, ...p, schemaVersion: 1 };\n const target = prefsPath();\n const tmp = target + \".tmp\";\n // Open + write + fsync + rename ensures a Ctrl+C between any two\n // syscalls either leaves the old file intact (rename is atomic on\n // POSIX) or leaves only a .tmp behind that the next writePrefs\n // overwrites. We never end up with a truncated `preferences.json`\n // that readPrefs would have to discard.\n const fd = openSync(tmp, \"w\", 0o600);\n try {\n writeSync(fd, JSON.stringify(next, null, 2) + \"\\n\");\n try {\n fsyncSync(fd);\n } catch {\n // fsync isn't available on every filesystem (e.g. some Docker\n // overlays). The rename below is still atomic; we just can't\n // guarantee durability against a power loss.\n }\n } finally {\n closeSync(fd);\n }\n renameSync(tmp, target);\n } catch {\n // Preferences are best-effort. Don't crash the CLI for them.\n }\n}\n\nexport function resetPrefs(): void {\n try {\n unlinkSync(prefsPath());\n } catch {\n // Already gone — that's exactly the state we wanted.\n }\n}\n\nexport function isFirstRun(): boolean {\n // \"First run\" means: the preferences file doesn't exist OR exists\n // but `firstRunAt` was never recorded. The latter handles users who\n // had `.agentmemory/preferences.json` from a much older agentmemory\n // build that wrote a different schema — we treat them as new.\n if (!existsSync(prefsPath())) return true;\n return readPrefs().firstRunAt === null;\n}\n","// First-run interactive onboarding flow.\n//\n// Wakes up only when `isFirstRun()` is true (preferences are missing or\n// have never recorded a `firstRunAt`) or when the user passes\n// `--reset`. The flow asks for:\n//\n// 1. Which agents will be wired to agentmemory (multi-select). Each\n// option carries a small glyph that we reuse in /status output so\n// the user recognises them later. The label mirrors README row 1\n// (native plugins) and row 2 (MCP-only).\n// 2. Which LLM provider to use for compress / consolidate / graph.\n// \"skip — BM25-only mode\" is a real first-class option; lots of\n// users want agentmemory purely as a hybrid keyword + vector\n// memory layer without granting LLM API keys.\n//\n// We then write `~/.agentmemory/preferences.json` and seed\n// `~/.agentmemory/.env` with a commented-out `*_API_KEY=` line for the\n// chosen provider. This matches the existing `agentmemory init` flow\n// closely so users who skip onboarding still get the same file via\n// `agentmemory init`.\n\nimport { copyFile, mkdir } from \"node:fs/promises\";\nimport { constants as fsConstants, existsSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport * as p from \"@clack/prompts\";\nimport { appendFileSync, readFileSync } from \"node:fs\";\nimport { readPrefs, writePrefs } from \"./preferences.js\";\nimport { ADAPTERS, resolveAdapter, runAdapter } from \"./connect/index.js\";\nimport type { ConnectResult } from \"./connect/types.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nconst AGENT_GLYPH: Record<string, string> = {\n \"claude-code\": \"⟁\",\n \"copilot-cli\": \"◈\",\n codex: \"◎\",\n cursor: \"◫\",\n \"gemini-cli\": \"✦\",\n opencode: \"⬡\",\n};\n\nconst PROVIDERS: { value: string; label: string; envKey: string | null }[] = [\n { value: \"anthropic\", label: \"Anthropic — claude\", envKey: \"ANTHROPIC_API_KEY\" },\n { value: \"openai\", label: \"OpenAI — gpt\", envKey: \"OPENAI_API_KEY\" },\n { value: \"gemini\", label: \"Google — gemini\", envKey: \"GEMINI_API_KEY\" },\n { value: \"openrouter\", label: \"OpenRouter — multi-model\", envKey: \"OPENROUTER_API_KEY\" },\n { value: \"minimax\", label: \"MiniMax — MiniMax-M3\", envKey: \"MINIMAX_API_KEY\" },\n { value: \"skip\", label: \"Skip — BM25-only mode (no LLM key)\", envKey: null },\n];\n\nconst PROVIDER_COST_HINTS: Record<string, string> = {\n anthropic: \"rough cost: a fast Haiku-class model keeps compress/consolidate at fractions of a cent per session.\",\n openai: \"rough cost: a mini-class model keeps compress/consolidate at fractions of a cent per session.\",\n gemini: \"rough cost: a Flash-class model keeps compress/consolidate at fractions of a cent per session.\",\n openrouter: \"rough cost: pick a small model; spend tracks your chosen model's per-token price.\",\n minimax: \"rough cost: scales with the MiniMax model price per token.\",\n};\n\nexport function buildAgentOptions(): { value: string; label: string; hint?: string }[] {\n const options = ADAPTERS.map((a) => ({\n value: a.name,\n label: `${AGENT_GLYPH[a.name] ?? \"◇\"} ${a.displayName}`,\n hint: a.category === \"native\" ? \"native plugin\" : \"MCP server\",\n }));\n return [\n ...options.filter((o) => o.hint === \"native plugin\"),\n ...options.filter((o) => o.hint === \"MCP server\"),\n ];\n}\n\nexport function getInitialAgentValues(\n env: Record<string, string | undefined> = process.env,\n): string[] {\n if (env[\"COPILOT_CLI\"] === \"1\" || env[\"COPILOT_AGENT_SESSION_ID\"]) {\n return [\"copilot-cli\"];\n }\n return [\"claude-code\"];\n}\n\n// Mirror src/cli.ts findEnvExample so onboarding ships the same .env\n// skeleton whether called directly or via `agentmemory init`. We\n// duplicate (rather than import) so the onboarding module doesn't\n// pull cli.ts's top-level side effects into the test runner.\nfunction findEnvExample(): string | null {\n const candidates = [\n join(__dirname, \"..\", \"..\", \".env.example\"),\n join(__dirname, \"..\", \".env.example\"),\n join(__dirname, \".env.example\"),\n join(process.cwd(), \".env.example\"),\n ];\n for (const c of candidates) {\n if (existsSync(c)) return c;\n }\n return null;\n}\n\nasync function seedEnvFile(provider: string | null): Promise<string | null> {\n const target = join(homedir(), \".agentmemory\", \".env\");\n const dir = dirname(target);\n await mkdir(dir, { recursive: true });\n\n const template = findEnvExample();\n if (template && !existsSync(target)) {\n try {\n await copyFile(template, target, fsConstants.COPYFILE_EXCL);\n } catch (err) {\n if ((err as NodeJS.ErrnoException)?.code !== \"EEXIST\") {\n return null;\n }\n }\n } else if (!template && !existsSync(target)) {\n // Fall back to a minimal skeleton so users always get a `.env` to\n // edit. This matches the shape of the bundled `.env.example`\n // without forcing us to keep two copies in sync.\n const lines = [\n \"# agentmemory environment — uncomment what you need\",\n \"# AGENTMEMORY_URL=http://localhost:3111\",\n \"\",\n ];\n const envKey = PROVIDERS.find((x) => x.value === provider)?.envKey;\n if (envKey) {\n lines.push(`# ${envKey}=`);\n }\n writeFileSync(target, lines.join(\"\\n\"), { mode: 0o600 });\n }\n\n return target;\n}\n\nexport interface OnboardingResult {\n agents: string[];\n provider: string | null;\n}\n\nfunction shouldSkipInteractiveOnboarding(): boolean {\n const ci = process.env[\"CI\"];\n return (\n process.stdin.isTTY !== true ||\n process.stdout.isTTY !== true ||\n (ci !== undefined && ci !== \"\" && ci !== \"0\" && ci.toLowerCase() !== \"false\")\n );\n}\n\nfunction writeDefaultOnboardingPrefs(): OnboardingResult {\n writePrefs({\n lastAgent: null,\n lastAgents: [],\n lastProvider: null,\n skipSplash: true,\n firstRunAt: new Date().toISOString(),\n });\n return { agents: [], provider: null };\n}\n\nexport async function runOnboarding(): Promise<OnboardingResult> {\n if (shouldSkipInteractiveOnboarding()) {\n return writeDefaultOnboardingPrefs();\n }\n\n p.note(\n [\n \"Welcome to agentmemory.\",\n \"\",\n \"Persistent memory for your AI coding agents. We'll pick which\",\n \"agents to wire up and which provider (if any) handles compression\",\n \"and consolidation. Either step can be changed later in ~/.agentmemory/.env.\",\n ].join(\"\\n\"),\n \"first-run setup\",\n );\n\n const agentsPicked = await p.multiselect<string>({\n message: \"Which agents will use agentmemory? (space to toggle, enter to confirm)\",\n options: buildAgentOptions(),\n required: false,\n initialValues: getInitialAgentValues(),\n });\n if (p.isCancel(agentsPicked)) {\n p.cancel(\"Setup cancelled. Re-run any time with: agentmemory --reset\");\n process.exit(0);\n }\n\n const pickedAgentsList = (agentsPicked as string[]) ?? [];\n if (pickedAgentsList.length > 0) {\n p.note(\n [\n \"━ how this works ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\",\n \"All selected agents share the same memory at :3111.\",\n \"A memory saved by Claude Code is visible to Copilot + Codex + Cursor instantly.\",\n \"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\",\n ].join(\"\\n\"),\n );\n }\n\n const providerPicked = await p.select<string>({\n message: \"Which LLM provider should agentmemory use for compress/consolidate?\",\n options: PROVIDERS.map(({ value, label }) => ({ value, label })),\n initialValue: \"anthropic\",\n });\n if (p.isCancel(providerPicked)) {\n p.cancel(\"Setup cancelled. Re-run any time with: agentmemory --reset\");\n process.exit(0);\n }\n\n const provider = providerPicked === \"skip\" ? null : providerPicked;\n const agents = (agentsPicked as string[]) ?? [];\n\n if (provider) {\n const hint = PROVIDER_COST_HINTS[provider];\n if (hint) {\n p.log.info(hint);\n }\n }\n\n const envPath = await seedEnvFile(provider);\n\n await maybePromptContextInjection(envPath);\n\n writePrefs({\n lastAgent: agents[0] ?? null,\n lastAgents: agents,\n lastProvider: provider,\n skipSplash: true,\n firstRunAt: new Date().toISOString(),\n });\n\n const prefsLocation = join(homedir(), \".agentmemory\", \"preferences.json\");\n const lines = [`✓ Saved preferences to ${prefsLocation}`];\n if (envPath) {\n lines.push(`✓ Wrote ${envPath} (edit to add your API key)`);\n } else {\n lines.push(`! Could not write ~/.agentmemory/.env — run \\`agentmemory init\\` after this completes.`);\n }\n if (provider) {\n const envKey = PROVIDERS.find((x) => x.value === provider)?.envKey;\n if (envKey) {\n lines.push(` Uncomment ${envKey}= in that file to enable ${provider}.`);\n }\n } else {\n lines.push(\" No provider chosen — agentmemory will run in BM25-only mode.\");\n }\n p.note(lines.join(\"\\n\"), \"ready\");\n\n if (agents.length > 0) {\n await wireSelectedAgents(agents);\n }\n\n return { agents, provider };\n}\n\nfunction enableInjectContextInEnv(envPath: string | null): boolean {\n if (!envPath || !existsSync(envPath)) return false;\n try {\n const current = readFileSync(envPath, \"utf-8\");\n if (/^\\s*AGENTMEMORY_INJECT_CONTEXT\\s*=\\s*true\\b/m.test(current)) {\n return true;\n }\n const prefix = current.length > 0 && !current.endsWith(\"\\n\") ? \"\\n\" : \"\";\n appendFileSync(envPath, `${prefix}AGENTMEMORY_INJECT_CONTEXT=true\\n`, { mode: 0o600 });\n return true;\n } catch {\n return false;\n }\n}\n\nasync function maybePromptContextInjection(envPath: string | null): Promise<void> {\n if (readPrefs().injectContextChosen) return;\n\n const enable = await p.confirm({\n message: \"Enable automatic context injection so the agent recalls past sessions without being asked? [y/N]\",\n initialValue: false,\n });\n\n if (p.isCancel(enable)) {\n p.cancel(\"Setup cancelled. Re-run any time with: agentmemory --reset\");\n process.exit(0);\n }\n\n p.log.info(\n \"Cost note: injection spends session tokens proportional to tool-call frequency. Default is off.\",\n );\n\n writePrefs({ injectContextChosen: true });\n\n if (enable === true) {\n const wrote = enableInjectContextInEnv(envPath);\n if (wrote) {\n p.log.success(\"Context injection enabled (AGENTMEMORY_INJECT_CONTEXT=true).\");\n } else {\n p.log.warn(\n \"Could not update ~/.agentmemory/.env. Set AGENTMEMORY_INJECT_CONTEXT=true there to enable it.\",\n );\n }\n } else {\n p.log.info(\"Context injection left off. Set AGENTMEMORY_INJECT_CONTEXT=true later to enable.\");\n }\n}\n\nasync function wireSelectedAgents(agents: string[]): Promise<void> {\n p.note(\"Wire selected agents now?\", \"next step\");\n const confirmed = await p.confirm({\n message: \"Run `agentmemory connect <agent>` for each selected agent now? [Y/n]\",\n initialValue: true,\n });\n\n if (p.isCancel(confirmed) || confirmed === false) {\n const cmds = agents.map((a) => ` agentmemory connect ${a}`);\n p.note([\"Wire later with:\", ...cmds].join(\"\\n\"), \"later\");\n return;\n }\n\n const wired: string[] = [];\n const manual: { name: string; docs?: string }[] = [];\n const failed: { name: string; reason: string }[] = [];\n\n for (const name of agents) {\n const adapter = resolveAdapter(name);\n if (!adapter) {\n failed.push({ name, reason: \"no adapter available\" });\n p.log.warn(`Wiring ${name}… no adapter available (skipped).`);\n continue;\n }\n p.log.step(`Wiring ${name}...`);\n let result: ConnectResult;\n try {\n result = await runAdapter(adapter, { dryRun: false, force: false });\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n failed.push({ name, reason });\n p.log.error(`${name}: ${reason}`);\n continue;\n }\n switch (result.kind) {\n case \"installed\":\n case \"already-wired\":\n wired.push(name);\n break;\n case \"stub\":\n manual.push({ name, docs: adapter.docs });\n break;\n case \"skipped\":\n failed.push({ name, reason: result.reason });\n break;\n }\n }\n\n const summary: string[] = [];\n if (wired.length > 0) {\n summary.push(`Wired: ${wired.join(\", \")}.`);\n }\n if (manual.length > 0 || failed.length > 0) {\n const parts: string[] = [];\n for (const m of manual) {\n parts.push(`${m.name} (manual install required${m.docs ? ` — see ${m.docs}` : \"\"})`);\n }\n for (const f of failed) {\n parts.push(`${f.name} (${f.reason})`);\n }\n summary.push(`Skipped/failed: ${parts.join(\", \")}.`);\n }\n if (summary.length === 0) {\n summary.push(\"No agents were wired.\");\n }\n p.note(summary.join(\"\\n\"), \"wire summary\");\n}\n","import { drainSpool, parseSentMark, retainSent, spoolSummary, type SendOutcome, type SpoolRecord } from \"../capture/spool.js\";\nimport { CURL_AUTH_HEADER } from \"../functions/status.js\";\n\ninterface CaptureCommandOptions {\n base: string;\n args: string[];\n secret?: string;\n log?: (line: string) => void;\n}\n\nfunction headers(secret?: string): Record<string, string> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (secret) h[\"Authorization\"] = `Bearer ${secret}`;\n return h;\n}\n\nfunction classify(status: number): SendOutcome {\n if (status === 200) return \"duplicate\";\n if (status >= 200 && status < 300) return \"delivered\";\n if (status === 408 || status === 429 || status >= 500) return \"retry\";\n return \"rejected\";\n}\n\nasync function serverCapture(base: string, secret?: string): Promise<unknown> {\n try {\n const res = await fetch(`${base}/agentmemory/capture?limit=20`, {\n headers: headers(secret),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return { error: `HTTP ${res.status}` };\n return await res.json();\n } catch (err) {\n return { error: err instanceof Error ? err.message : String(err) };\n }\n}\n\nexport async function runCaptureCommand(options: CaptureCommandOptions): Promise<number> {\n const log = options.log ?? ((line: string) => console.log(line));\n const json = options.args.includes(\"--json\");\n const drain = options.args.includes(\"--drain\");\n const output: Record<string, unknown> = {};\n\n if (drain) {\n output[\"drain\"] = await drainSpool(options.base, async (record: SpoolRecord) => {\n const res = await fetch(`${options.base}/agentmemory/observe`, {\n method: \"POST\",\n headers: headers(options.secret),\n body: JSON.stringify({ ...record.body, eventId: record.eventId }),\n signal: AbortSignal.timeout(10_000),\n });\n const text = await res.text().catch(() => \"\");\n const outcome = classify(res.status);\n if (outcome === \"delivered\" || outcome === \"duplicate\") {\n let mark = null;\n try {\n mark = parseSentMark(JSON.parse(text));\n } catch {}\n if (mark) retainSent(options.base, record.eventId, record.body, mark);\n }\n return outcome;\n });\n }\n output[\"spool\"] = spoolSummary(options.base);\n output[\"server\"] = await serverCapture(options.base, options.secret);\n\n if (json) {\n log(JSON.stringify(output, null, 2));\n return 0;\n }\n\n const spool = output[\"spool\"] as ReturnType<typeof spoolSummary>;\n if (drain) {\n const d = output[\"drain\"] as Awaited<ReturnType<typeof drainSpool>>;\n log(\n d.skipped\n ? `Drain skipped: ${d.skipped === \"locked\" ? \"another drain is running\" : \"nothing to send\"}`\n : `Drained ${d.claimed}: ${d.delivered} stored, ${d.duplicates} already stored, ${d.rejected} rejected, ${d.expired} expired, ${d.remaining} still waiting${d.error ? ` (${d.error})` : \"\"}`,\n );\n }\n log(`Local spool: ${spool.enabled ? `${spool.records} waiting, ${spool.bytes} bytes` : \"off (AGENTMEMORY_CAPTURE_SPOOL=false)\"}`);\n log(` file: ${spool.path}`);\n log(` limits: ${spool.maxBytes} bytes, ${spool.maxAgeHours} h`);\n log(` totals: ${spool.stats.spooled} spooled, ${spool.stats.delivered} delivered, ${spool.stats.duplicates} duplicates, ${spool.stats.dropped} dropped, ${spool.stats.expired} expired`);\n if (spool.stats.lastDrainAt) log(` last drain: ${spool.stats.lastDrainAt}`);\n if (spool.stats.lastDropAt) log(` last drop: ${spool.stats.lastDropAt} (${spool.stats.lastDropReason ?? \"unknown\"})`);\n\n const server = output[\"server\"] as {\n error?: string;\n capture?: { inbox?: { pending: number; retrying: number; dead: number; lastError: string | null } | null; sinceStart?: Record<string, number> } | null;\n items?: Array<{ eventId: string; status: string; attempts: number; lastError?: string; preview?: string }>;\n };\n if (server.error) {\n log(`Server: unreachable at ${options.base} (${server.error})`);\n return 0;\n }\n const inbox = server.capture?.inbox;\n log(`Server inbox: ${inbox ? `${inbox.pending} pending, ${inbox.retrying} retrying, ${inbox.dead} dead letters` : \"unknown\"}`);\n if (inbox?.lastError) log(` last error: ${inbox.lastError}`);\n for (const item of server.items ?? []) {\n log(` ${item.status.padEnd(8)} ${item.eventId} attempts=${item.attempts} ${item.preview ?? \"\"}`);\n }\n if (inbox && inbox.dead > 0) {\n log(`Retry dead letters: curl -X POST ${options.base}/agentmemory/capture/retry ${CURL_AUTH_HEADER} -H \"Content-Type: application/json\" -d '{\"all\":true}'`);\n }\n return 0;\n}\n","#!/usr/bin/env node\n\nimport {\n spawn,\n execFileSync,\n spawnSync,\n type ChildProcess,\n} from \"node:child_process\";\nimport {\n cpSync,\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n readlinkSync,\n rmSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { join, dirname, resolve, delimiter as PATH_DELIMITER } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { homedir, platform } from \"node:os\";\nimport * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\n\n// Semantic color helpers. clack strips ANSI for box-width math\n// (stripVTControlCharacters + string-width), so coloring inside p.note\n// keeps borders aligned. Centralized here so the palette stays consistent\n// across every command's output.\nconst c = {\n url: pc.cyan,\n ok: pc.green,\n warn: pc.yellow,\n err: pc.red,\n cmd: (s: string) => pc.bold(pc.cyan(s)),\n label: pc.bold,\n dim: pc.dim,\n accent: (s: string) => pc.bold(pc.yellow(s)),\n};\nimport { generateId } from \"./state/schema.js\";\nimport {\n buildDiagnostics,\n dryRunPlan,\n parseEnvFile,\n type Diagnostic,\n type DiagnosticFixResult,\n type DoctorContext,\n type DoctorEffects,\n} from \"./cli/doctor-diagnostics.js\";\nimport {\n buildRemovePlan,\n formatPlan,\n legacyLocalBinIii,\n type ConnectManifest,\n type RemoveOptions,\n} from \"./cli/remove-plan.js\";\nimport { portFlagSuffix } from \"./cli/ready-hint.js\";\nimport { expectedIiiSha256, iiiManualInstallCommand, installIiiArchive } from \"./cli/engine-install.js\";\nimport {\n dockerComposeArgs,\n dockerProjectName,\n isBundledConfig,\n legacyDataMigrations,\n resolveEngineCwd,\n rewriteBundledConfig,\n runtimeConfigPath,\n engineChildEnv,\n resolveLaunchRenderFailure,\n redactCredentialUrls,\n} from \"./cli/engine-launch.js\";\nimport { runtimeMetadataPath } from \"./runtime-paths.js\";\nimport { createStartupStderrCapture } from \"./cli/startup-stderr.js\";\nimport {\n clearPersistedBuiltinConfig,\n engineFlushWaitMs,\n engineStateConfigPaths,\n renderEngineConfig,\n} from \"./cli/engine-config.js\";\nimport { SHUTDOWN_HARD_EXIT_MS } from \"./shutdown.js\";\nimport { consoleArgs, defaultConsolePort, parseConsoleArgs } from \"./cli/console.js\";\nimport { processStatIsRunning } from \"./cli/process-state.js\";\nimport { renderSplash } from \"./cli/splash.js\";\nimport { isFirstRun, readPrefs, resetPrefs, writePrefs } from \"./cli/preferences.js\";\nimport { runOnboarding } from \"./cli/onboarding.js\";\nimport { setBootVerbose } from \"./logger.js\";\nimport { getRedisUrl, getStateBackend, getStateSaveIntervalMs, hydrateProcessEnvFromFile } from \"./config.js\";\nimport { III_PINNED_VERSION, VERSION } from \"./version.js\";\nimport { getAllTools, ESSENTIAL_TOOLS } from \"./mcp/tools-registry.js\";\nimport { knownAgents } from \"./cli/connect/index.js\";\n\nconst ALL_TOOLS_COUNT = getAllTools().length;\nconst CORE_TOOLS_COUNT = getAllTools().filter((t) => ESSENTIAL_TOOLS.has(t.name)).length;\nimport { resolveDataDir } from \"./cli-data-dir.js\";\nimport { runCaptureCommand } from \"./cli/capture.js\";\nimport { bearerHeaders, resolveClientSecret } from \"./secret-store.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst args = process.argv.slice(2);\nconst IS_WINDOWS = platform() === \"win32\";\nconst IS_VERBOSE =\n args.includes(\"--verbose\") ||\n args.includes(\"-v\") ||\n process.env[\"AGENTMEMORY_VERBOSE\"] === \"1\" ||\n process.env[\"AGENTMEMORY_VERBOSE\"] === \"true\";\n\n// Propagate the resolved verbosity to the worker's boot logger so the\n// 25-line `[agentmemory] X registered` stream is either dropped or\n// printed verbatim. Without this the worker's default (env-only) would\n// disagree with the CLI flag.\nsetBootVerbose(IS_VERBOSE);\n\nconst IS_RESET = args.includes(\"--reset\");\n\n// Fold ~/.agentmemory/.env into process.env before any port/URL read\n// (getRestPort/getBaseUrl/getStreamPort/getEnginePort) or the --port /\n// --instance / --tools handlers below. Only-if-unset, so a real\n// process.env value — including one just set by a CLI flag — still wins.\nhydrateProcessEnvFromFile();\n\n// --version / -V early exit. Print VERSION + exit before any side effects\n// (engine boot, env load, dir mkdir). `-v` is taken by --verbose so we\n// reserve `-V` (capital) for version per POSIX convention.\nif (args.includes(\"--version\") || args.includes(\"-V\")) {\n process.stdout.write(`${VERSION}\\n`);\n process.exit(0);\n}\n\n// Pinned iii-engine version. The engine, the iii-sdk and the @iii-dev/helpers\n// packages in package.json must stay on the same release: the worker speaks\n// that engine's wire protocol and the unpinned installer tracks `latest`.\n// 0.22.x is the last line before 0.23 removes the config.yaml worker\n// lifecycle this CLI relies on; it keeps HTTP routes owned by the\n// reconnecting worker (no REST 404s after an engine reconnect). The engine\n// still boots its iii- prefixed builtins from config.yaml (the unprefixed\n// http/state/queue/pubsub/cron names resolve to the standalone registry\n// workers, which is the 0.23 migration, not this one). Bump this\n// constant and the two package.json dependencies together.\n// AGENTMEMORY_III_VERSION overrides the pin for anyone running a\n// self-managed engine.\nconst IIPINNED_DEFAULT_VERSION = III_PINNED_VERSION;\nconst IIPINNED_VERSION =\n process.env[\"AGENTMEMORY_III_VERSION\"] || IIPINNED_DEFAULT_VERSION;\nconst IIIENGINE_INSTALL_CMD = `curl -fsSL https://install.iii.dev/iii/main/install.sh | VERSION=${IIPINNED_VERSION} sh`;\n\n// Map Node platform/arch → the asset name iii-hq/iii ships under\n// https://github.com/iii-hq/iii/releases/download/iii/v<version>/<asset>\nfunction iiiReleaseAsset(): string | null {\n const p = platform();\n const a = process.arch;\n if (p === \"darwin\" && a === \"arm64\")\n return \"iii-aarch64-apple-darwin.tar.gz\";\n if (p === \"darwin\" && a === \"x64\")\n return \"iii-x86_64-apple-darwin.tar.gz\";\n if (p === \"linux\" && a === \"x64\")\n return \"iii-x86_64-unknown-linux-gnu.tar.gz\";\n if (p === \"linux\" && a === \"arm64\")\n return \"iii-aarch64-unknown-linux-gnu.tar.gz\";\n if (p === \"linux\" && a === \"arm\")\n return \"iii-armv7-unknown-linux-gnueabihf.tar.gz\";\n if (p === \"win32\" && a === \"x64\")\n return \"iii-x86_64-pc-windows-msvc.zip\";\n if (p === \"win32\" && a === \"arm64\")\n return \"iii-aarch64-pc-windows-msvc.zip\";\n return null;\n}\n\nfunction iiiReleaseUrl(): string | null {\n const asset = iiiReleaseAsset();\n if (!asset) return null;\n // Tag name is monorepo-prefixed: `iii/v0.22.1`. Slash is URL-encoded\n // by GitHub when serving the download path, hence `iii/v...` not `iii%2Fv...`.\n return `https://github.com/iii-hq/iii/releases/download/iii/v${IIPINNED_VERSION}/${asset}`;\n}\n\nfunction vlog(msg: string): void {\n if (IS_VERBOSE) p.log.info(`[verbose] ${msg}`);\n}\n\nfunction wrapList(items: readonly string[], indent: number, width = 78): string {\n const lines: string[] = [];\n let line = \"\";\n for (const item of items) {\n const joined = line ? `${line}, ${item}` : item;\n if (line && indent + joined.length > width) {\n lines.push(`${line},`);\n line = item;\n } else {\n line = joined;\n }\n }\n lines.push(line);\n return lines.join(`\\n${\" \".repeat(indent)}`);\n}\n\nif (args.includes(\"--help\") || args.includes(\"-h\")) {\n console.log(`\nagentmemory — persistent memory for AI coding agents\n\nUsage: agentmemory [command] [options]\n\nCommands:\n (default) Start agentmemory worker\n init Copy bundled .env.example to ~/.agentmemory/.env if absent\n connect [agent] Wire agentmemory into an installed agent\n (${wrapList(knownAgents(), 21)}).\n No arg = interactive picker. --all wires every detected agent.\n --dry-run shows what would change. --force re-installs.\n status Show connection status, memory count, flags, and health\n console Launch the iii web console for this engine (workers, functions,\n triggers, queues, traces). --console-port N, default viewer+1\n doctor Interactive diagnostic + fixer. [F]ix · [S]kip · [?]more · [Q]uit\n --all: apply every fix without prompting (CI)\n --dry-run: show what each fix would do, don't execute\n remove Cleanly uninstall agentmemory (pidfile, state, .env, binaries).\n --force: skip confirmations · --keep-data: keep memory data\n demo [--serve] Seed sample sessions and show recall in action.\n --serve boots the server, runs the demo, and stops it\n in one command (no second terminal).\n upgrade Upgrade local deps + iii runtime (best effort)\n stop [--force] Stop the running iii-engine started by this CLI.\n --force bypasses the Docker-heuristic guard and signals\n whatever pidfile+lsof report on the REST port (use when\n the engine was started natively but state file is missing).\n mcp Start standalone MCP shim — opt-in surface for MCP-only clients\n (Cursor, Gemini CLI, etc). REST always available at :3111.\n capture [--drain] Show capture health: the local offline spool and the server\n inbox (pending, retrying, dead letters). --drain sends\n spooled observations now. --json for machine output.\n import-jsonl [p] Import Claude Code JSONL transcripts (default: ~/.claude/projects)\n --max-files <N> | --max-files=<N>: override scan cap (default 200, max 1000;\n out-of-range is rejected; for trees >1000 files, batch by subdirectory)\n\nOptions:\n --help, -h Show this help\n --verbose, -v Show engine stderr, boot log, and diagnostic info\n --reset Wipe ~/.agentmemory/preferences.json and re-run onboarding\n --tools all|core Tool visibility (default: all = ${ALL_TOOLS_COUNT} tools; core = ${CORE_TOOLS_COUNT} essentials)\n --no-engine Skip auto-starting iii-engine\n --port <N> Override REST port (default: 3111). Streams (N+1), viewer\n (N+2), and iii engine (N+46023) auto-derive from N so a\n single flag relocates the whole quartet.\n --instance <N> Shortcut for --port (3111 + N*100) to run multiple\n daemons side-by-side without env gymnastics.\n --instance 1 -> 3211/3212/3213/49234, etc. (max N=50)\n --data-dir <path> Store iii-engine state outside the current repo\n\nEnvironment:\n AGENTMEMORY_URL Full REST base URL (e.g. http://localhost:3111).\n Honored by status, doctor, and MCP shim commands.\n AGENTMEMORY_DATA_DIR State directory fallback when --data-dir is not set.\n AGENTMEMORY_USE_DOCKER=1 Prefer the bundled docker-compose path over the\n native iii-engine binary on first run.\n AGENTMEMORY_III_VERSION Override pinned iii-engine version (default ${IIPINNED_VERSION}).\n AGENTMEMORY_III_CONFIG Engine config to start from (default: ./iii-config.yaml,\n then ~/.agentmemory/iii-config.yaml, then the bundled\n loopback-only config).\n AGENTMEMORY_FOLLOWUP_WINDOW_SECONDS\n Window (seconds) for the smart-search follow-up diagnostic\n (default 30). Long values overcount, short values undercount.\n\nQuick start:\n npx @agentmemory/agentmemory # start with local iii-engine or Docker\n npx @agentmemory/agentmemory demo # see semantic recall in 30 seconds\n npx @agentmemory/agentmemory doctor # diagnose config + feature flags\n npx @agentmemory/agentmemory status # health + memory count + flags\n npx @agentmemory/agentmemory upgrade # upgrade agentmemory + iii runtime\n npx @agentmemory/agentmemory mcp # standalone MCP server (no engine)\n npx @agentmemory/mcp # same as above (shim package)\n`);\n process.exit(0);\n}\n\nconst toolsIdx = args.indexOf(\"--tools\");\nif (toolsIdx !== -1 && args[toolsIdx + 1]) {\n const toolsMode = args[toolsIdx + 1]!;\n if (toolsMode !== \"all\" && toolsMode !== \"core\") {\n p.log.warn(\n `Unknown --tools value \"${toolsMode}\" (valid: all, core); falling back to all.`,\n );\n }\n process.env[\"AGENTMEMORY_TOOLS\"] = toolsMode;\n}\n\nconst URL_CLIENT_COMMANDS = new Set([\"status\", \"doctor\", \"mcp\", \"capture\"]);\nlet hasExplicitLocalPortOverride = false;\nlet selectedInstance = 0;\n\nfunction cliArgValue(name: string): string | undefined {\n const inline = args.find((arg) => arg.startsWith(`${name}=`));\n if (inline) return inline.slice(name.length + 1);\n const index = args.indexOf(name);\n return index === -1 ? undefined : args[index + 1];\n}\n\nconst portValue = cliArgValue(\"--port\");\nif (portValue) {\n process.env[\"III_REST_PORT\"] = portValue;\n hasExplicitLocalPortOverride = true;\n}\n\n// `--instance N` picks a 100-port block off the 3111 base so multiple\n// agentmemory daemons can coexist on one host without env-var\n// gymnastics. `--instance 0` keeps the canonical 3111/3112/3113/49134\n// quartet; `--instance 1` → 3211/3212/3213/49234; etc. REST acts as the\n// anchor — streams/viewer/engine derive from it via fixed offsets below\n// unless an env explicitly pins each one.\nconst instanceValue = cliArgValue(\"--instance\");\nconst hasInstanceArgument = args.some(\n (arg) => arg === \"--instance\" || arg.startsWith(\"--instance=\"),\n);\nif (hasInstanceArgument) {\n if (instanceValue === undefined || !/^\\d+$/.test(instanceValue)) {\n p.log.error(\"--instance must be an integer between 0 and 50.\");\n process.exit(1);\n }\n const n = Number(instanceValue);\n if (!Number.isInteger(n) || n > 50) {\n p.log.error(\"--instance must be an integer between 0 and 50.\");\n process.exit(1);\n }\n selectedInstance = n;\n const base = 3111 + n * 100;\n if (!hasExplicitLocalPortOverride) {\n process.env[\"III_REST_PORT\"] = String(base);\n }\n hasExplicitLocalPortOverride = true;\n}\n\nconst restPort = parseInt(process.env[\"III_REST_PORT\"] || \"3111\", 10);\nif (Number.isFinite(restPort) && restPort > 0) {\n process.env[\"III_STREAM_PORT\"] ??=\n process.env[\"III_STREAMS_PORT\"] ?? String(restPort + 1);\n process.env[\"III_VIEWER_PORT\"] ??= String(restPort + 2);\n const configuredEngineUrl = process.env[\"III_ENGINE_URL\"];\n if (configuredEngineUrl) {\n try {\n const parsedEnginePort = new URL(configuredEngineUrl).port;\n if (parsedEnginePort) {\n process.env[\"III_ENGINE_PORT\"] = parsedEnginePort;\n }\n } catch {}\n } else {\n process.env[\"III_ENGINE_PORT\"] ??= String(restPort + 46023);\n }\n process.env[\"AGENTMEMORY_METRICS_PORT\"] ??= String(restPort + 6353);\n}\n\nconst dataDirResolution = resolveDataDir({ args });\nprocess.env[\"AGENTMEMORY_DATA_DIR\"] = dataDirResolution.dataDir;\nprocess.env[\"AGENTMEMORY_RUNTIME_DIR\"] = selectedInstance > 0\n ? dataDirResolution.dataDir\n : join(homedir(), \".agentmemory\");\n\nconst skipEngine = args.includes(\"--no-engine\");\n\nfunction shouldUseAgentmemoryUrl(): boolean {\n return !hasExplicitLocalPortOverride && URL_CLIENT_COMMANDS.has(args[0] ?? \"\");\n}\n\nfunction getRestPort(): number {\n const url = shouldUseAgentmemoryUrl()\n ? process.env[\"AGENTMEMORY_URL\"]\n : undefined;\n if (url) {\n try {\n const parsed = new URL(url).port;\n if (parsed) return parseInt(parsed, 10);\n } catch {}\n }\n return parseInt(process.env[\"III_REST_PORT\"] || \"3111\", 10) || 3111;\n}\n\nfunction getBaseUrl(): string {\n const url = shouldUseAgentmemoryUrl()\n ? process.env[\"AGENTMEMORY_URL\"]\n : undefined;\n if (url) return url.replace(/\\/+$/, \"\");\n return `http://localhost:${getRestPort()}`;\n}\n\nfunction getConfiguredViewerPort(): number {\n return (\n parseInt(process.env[\"III_VIEWER_PORT\"] || \"\", 10) ||\n getRestPort() + 2\n );\n}\n\nlet discoveredViewerPort: number | null = null;\n\nexport async function discoverViewerPort(): Promise<void> {\n if (discoveredViewerPort !== null) return;\n try {\n const res = await fetch(`${getBaseUrl()}/agentmemory/livez`, {\n signal: AbortSignal.timeout(1000),\n });\n if (res.ok) {\n const data = await res.json() as { viewerPort?: number | null };\n if (typeof data.viewerPort === \"number\") {\n discoveredViewerPort = data.viewerPort;\n }\n }\n } catch {}\n}\n\nfunction getViewerUrl(): string {\n const envUrl = process.env[\"AGENTMEMORY_VIEWER_URL\"];\n if (envUrl) return envUrl.replace(/\\/+$/, \"\");\n \n if (discoveredViewerPort !== null) {\n try {\n const u = new URL(getBaseUrl());\n return `${u.protocol}//${u.hostname}:${discoveredViewerPort}`;\n } catch {\n return `http://localhost:${discoveredViewerPort}`;\n }\n }\n \n try {\n const u = new URL(getBaseUrl());\n const vPort = getConfiguredViewerPort();\n return `${u.protocol}//${u.hostname}:${vPort}`;\n } catch {\n const vPort = getConfiguredViewerPort();\n return `http://localhost:${vPort}`;\n }\n}\n\n// WebSocket streams port. Engine writes here; the SDK and viewer\n// subscribe. Honors both `III_STREAM_PORT` (the singular name the\n// engine docs use post-0.11) and `III_STREAMS_PORT` (the name our\n// own config.ts has used since 0.7) so a single source of truth in\n// either form lights up the ready panel. Falls back to REST+1 so\n// `--port 3211` auto-picks 3212 instead of colliding on 3112.\nfunction getStreamPort(): number {\n return (\n parseInt(process.env[\"III_STREAM_PORT\"] || \"\", 10) ||\n parseInt(process.env[\"III_STREAMS_PORT\"] || \"\", 10) ||\n getRestPort() + 1\n );\n}\n\n// Bridge WebSocket port — the iii engine's internal worker bus.\n// Defaults derived from REST as REST+46023 so the canonical 3111\n// anchor yields 49134 and `--port 3211` auto-picks 49234 without a\n// second-instance collision. Overridable via\n// `III_ENGINE_PORT` or the legacy `III_ENGINE_URL=ws://host:port`.\nfunction getEnginePort(): number {\n const url = process.env[\"III_ENGINE_URL\"];\n if (url) {\n try {\n const parsed = new URL(url).port;\n if (parsed) return parseInt(parsed, 10);\n } catch {}\n }\n const explicit = parseInt(process.env[\"III_ENGINE_PORT\"] || \"\", 10);\n if (explicit) return explicit;\n return getRestPort() + 46023;\n}\n\nasync function isEngineRunning(): Promise<boolean> {\n try {\n await fetch(`${getBaseUrl()}/`, {\n signal: AbortSignal.timeout(2000),\n });\n return true;\n } catch {\n return false;\n }\n}\n\nasync function isAgentmemoryReady(): Promise<boolean> {\n try {\n const res = await fetch(`${getBaseUrl()}/agentmemory/livez`, {\n signal: AbortSignal.timeout(2000),\n });\n if (!res.ok) return false;\n try {\n const data = await res.json() as { viewerPort?: number | null; viewerSkipped?: boolean };\n if (typeof data.viewerPort === \"number\") {\n discoveredViewerPort = data.viewerPort;\n return true;\n }\n if (data.viewerSkipped) return true;\n return false;\n } catch {\n return false;\n }\n } catch {\n return false;\n }\n}\n\nfunction findIiiConfig(): string {\n // Precedence (user-overridable wins): explicit env > project cwd >\n // ~/.agentmemory/ > bundled. The bundled config used to win\n // unconditionally, so users hitting the observability log-feedback\n // loop had no way to drop a tamer config in place without\n // editing node_modules.\n const envPath = process.env[\"AGENTMEMORY_III_CONFIG\"];\n const candidates = [\n ...(envPath ? [envPath] : []),\n join(process.cwd(), \"iii-config.yaml\"),\n join(homedir(), \".agentmemory\", \"iii-config.yaml\"),\n join(__dirname, \"iii-config.yaml\"),\n join(__dirname, \"..\", \"iii-config.yaml\"),\n ];\n for (const c of candidates) {\n if (existsSync(c)) return resolve(c);\n }\n return \"\";\n}\n\nfunction warnIfRelocatedDataDir(): void {\n if (!dataDirResolution.relocatedFrom) return;\n\n try {\n mkdirSync(dataDirResolution.dataDir, { recursive: true });\n const marker = join(dataDirResolution.dataDir, \".cwd-relocation-warning\");\n if (existsSync(marker)) return;\n p.log.warn(\n `Default data dir ${dataDirResolution.relocatedFrom} is inside a git worktree; using ${dataDirResolution.dataDir} instead.`,\n );\n writeFileSync(marker, new Date().toISOString());\n } catch {\n p.log.warn(\n `Default data dir ${dataDirResolution.relocatedFrom} is inside a git worktree; using ${dataDirResolution.dataDir} instead.`,\n );\n }\n}\n\nfunction whichBinary(name: string): string | null {\n const cmd = IS_WINDOWS ? \"where\" : \"which\";\n try {\n const out = execFileSync(cmd, [name], {\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n const first = out\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .find((line) => line.length > 0);\n return first ?? null;\n } catch {\n return null;\n }\n}\n\n// Private install location agentmemory manages itself. Sits under the\n// agentmemory state dir (~/.agentmemory/bin) so the pinned engine stays\n// isolated from a user-managed iii on PATH or in ~/.local/bin. A\n// fresh box with iii 0.16.1 already on PATH refused to boot because the\n// hard-pin enforcer told users to overwrite their global install with\n// the pinned version. Private install resolves the conflict without touching their\n// existing iii.\nfunction agentmemoryBinDir(): string {\n if (IS_WINDOWS) {\n const userProfile = process.env[\"USERPROFILE\"];\n if (!userProfile) return join(homedir(), \".agentmemory\", \"bin\");\n return join(userProfile, \".agentmemory\", \"bin\");\n }\n return join(homedir(), \".agentmemory\", \"bin\");\n}\n\nfunction privateIiiPath(): string {\n return join(agentmemoryBinDir(), IS_WINDOWS ? \"iii.exe\" : \"iii\");\n}\n\nfunction fallbackIiiPaths(): string[] {\n if (IS_WINDOWS) {\n const userProfile = process.env[\"USERPROFILE\"];\n const paths = [privateIiiPath()];\n if (userProfile) {\n paths.push(\n join(userProfile, \".local\", \"bin\", \"iii.exe\"),\n join(userProfile, \"bin\", \"iii.exe\"),\n );\n }\n return paths;\n }\n const home = process.env[\"HOME\"];\n const paths = [privateIiiPath()];\n if (home) {\n paths.push(join(home, \".local\", \"bin\", \"iii\"));\n }\n paths.push(\"/usr/local/bin/iii\");\n return paths;\n}\n\nfunction iiiBinVersion(binPath: string): string | null {\n try {\n const out = execFileSync(binPath, [\"--version\"], {\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n timeout: 3000,\n });\n const match = out.match(/(\\d+\\.\\d+\\.\\d+(?:[-+][\\w.]+)?)/);\n return match ? match[1]! : null;\n } catch {\n return null;\n }\n}\n\n// Resolve a compatible iii binary for the pinned engine version.\n//\n// Soft-warn lets the worker boot against a mismatched engine and crash at\n// runtime (the SDK and engine wire protocol move together; 0.20+ renamed the\n// SDK surface entirely). Hard-pin without a fallback leaves the user stuck — they\n// either downgrade their global iii (breaking other consumers) or set\n// AGENTMEMORY_III_VERSION and hope it works.\n//\n// Instead: when the candidate iii on PATH is the wrong version, prefer\n// the private install under ~/.agentmemory/bin/iii. If the private copy\n// is missing or also mismatched, the caller installs the pinned version\n// there before retrying. AGENTMEMORY_III_VERSION still overrides\n// IIPINNED_VERSION upstream so users who knowingly want a different\n// engine can opt in.\nfunction resolveCompatibleIii(iiiBinPath: string | null | undefined): string | null {\n if (!iiiBinPath) return null;\n const detected = iiiBinVersion(iiiBinPath);\n if (detected && detected === IIPINNED_VERSION) return iiiBinPath;\n\n const privatePath = privateIiiPath();\n if (iiiBinPath !== privatePath && existsSync(privatePath)) {\n const privateVersion = iiiBinVersion(privatePath);\n if (privateVersion === IIPINNED_VERSION) {\n const reason = detected ? `v${detected} mismatches pin` : \"probe failed\";\n vlog(\n `iii at ${iiiBinPath} ${reason} v${IIPINNED_VERSION}; using private install at ${privatePath}.`,\n );\n return privatePath;\n }\n }\n\n return null;\n}\n\nfunction enginePidfilePath(): string {\n return runtimeMetadataPath(\"iii.pid\");\n}\n\nfunction engineStatePath(): string {\n return runtimeMetadataPath(\"engine-state.json\");\n}\n\ntype NativeEngineState = {\n kind: \"native\";\n configPath: string;\n attached?: boolean;\n binPath?: string;\n restPort?: number;\n};\n\ntype DockerEngineState = {\n kind: \"docker\";\n schemaVersion?: 2;\n composeFile: string;\n projectName?: string;\n engineVersion?: string;\n restPort?: number;\n dataDir?: string;\n containerId?: string;\n dataMountType?: \"bind\" | \"volume\";\n dataMountSource?: string;\n preserveContainer?: boolean;\n};\n\ntype EngineState = NativeEngineState | DockerEngineState;\n\nfunction writeEnginePidfile(pid: number): void {\n try {\n const pidPath = enginePidfilePath();\n mkdirSync(dirname(pidPath), { recursive: true });\n writeFileSync(pidPath, `${pid}\\n`, { encoding: \"utf-8\" });\n } catch (err) {\n vlog(`writeEnginePidfile: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n\nfunction readEnginePidfile(): number | null {\n try {\n const pidStr = readFileSync(enginePidfilePath(), \"utf-8\").trim();\n const pid = parseInt(pidStr, 10);\n return Number.isFinite(pid) && pid > 0 ? pid : null;\n } catch {\n return null;\n }\n}\n\nfunction clearEnginePidfile(): void {\n try {\n unlinkSync(enginePidfilePath());\n } catch {}\n}\n\nfunction workerPidfilePath(): string {\n return runtimeMetadataPath(\"worker.pid\");\n}\n\nfunction readWorkerPidfile(): number | null {\n try {\n const pidStr = readFileSync(workerPidfilePath(), \"utf-8\").trim();\n const pid = parseInt(pidStr, 10);\n return Number.isFinite(pid) && pid > 0 ? pid : null;\n } catch {\n return null;\n }\n}\n\nfunction clearWorkerPidfile(): void {\n try {\n unlinkSync(workerPidfilePath());\n } catch {}\n}\n\nfunction writeEngineState(state: EngineState): void {\n try {\n const statePath = engineStatePath();\n mkdirSync(dirname(statePath), { recursive: true });\n const normalized = state.kind === \"docker\" && state.schemaVersion === 2\n ? {\n ...state,\n restPort: state.restPort ?? getRestPort(),\n dataDir: state.dataDir ?? dataDirResolution.dataDir,\n }\n : { ...state, restPort: state.restPort ?? getRestPort() };\n writeFileSync(statePath, `${JSON.stringify(normalized)}\\n`, { encoding: \"utf-8\" });\n } catch (err) {\n vlog(`writeEngineState: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n\nfunction readEngineState(): EngineState | null {\n try {\n const raw = readFileSync(engineStatePath(), \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<EngineState>;\n if (parsed && (parsed.kind === \"native\" || parsed.kind === \"docker\")) {\n return parsed as EngineState;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nfunction clearEngineState(): void {\n try {\n unlinkSync(engineStatePath());\n } catch {}\n}\n\nfunction engineStateRestPort(state: EngineState): number {\n if (state.restPort && Number.isFinite(state.restPort)) return state.restPort;\n if (state.kind === \"docker\") {\n const projectPort = state.projectName?.match(/^agentmemory-(\\d+)$/)?.[1];\n if (projectPort) return parseInt(projectPort, 10);\n return 3111;\n }\n try {\n const raw = readFileSync(state.configPath, \"utf-8\");\n const httpBlock = raw.match(\n /- name:\\s*(?:iii-)?http([\\s\\S]*?)(?=\\n\\s*- name:|$)/,\n )?.[1];\n const configuredPort = httpBlock?.match(/\\n\\s*port:\\s*(\\d+)/)?.[1];\n if (configuredPort) return parseInt(configuredPort, 10);\n } catch {}\n return 3111;\n}\n\nasync function startWorkerForEngineState(): Promise<void> {\n const workerPid = readWorkerPidfile();\n if (workerPid && pidAlive(workerPid)) return;\n if (configuredEngineMayStartWorker() && await waitForConfiguredWorker(5000)) {\n return;\n }\n await import(\"./index.js\");\n}\n\nfunction configuredEngineMayStartWorker(): boolean {\n const state = readEngineState();\n if (state?.kind !== \"native\") return false;\n try {\n const raw = readFileSync(state.configPath, \"utf-8\");\n return raw.includes(\"- name: iii-exec\");\n } catch {\n return false;\n }\n}\n\nasync function waitForConfiguredWorker(timeoutMs: number): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n const workerPid = readWorkerPidfile();\n if (workerPid && pidAlive(workerPid)) return true;\n if (await isAgentmemoryReady()) return true;\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n return false;\n}\n\nfunction discoverComposeFile(): string | null {\n const candidates = [\n join(__dirname, \"..\", \"docker-compose.yml\"),\n join(__dirname, \"docker-compose.yml\"),\n join(process.cwd(), \"docker-compose.yml\"),\n ];\n return candidates.find((c) => existsSync(c)) ?? null;\n}\n\ntype DockerEngineInspection =\n | {\n status: \"running\" | \"stopped\";\n composeFile: string;\n projectName: string;\n containerId: string;\n dataMountType: \"bind\" | \"volume\";\n dataMountSource: string;\n preserveContainer: boolean;\n }\n | { status: \"missing\"; composeFile: string; projectName?: string }\n | { status: \"unavailable\"; reason: string };\n\ntype DockerInspectRecord = {\n Id?: string;\n State?: { Running?: boolean };\n Config?: { Image?: string; Labels?: Record<string, string> };\n HostConfig?: {\n PortBindings?: Record<\n string,\n Array<{ HostIp?: string; HostPort?: string }> | null\n >;\n };\n Mounts?: Array<{\n Type?: string;\n Name?: string;\n Source?: string;\n Destination?: string;\n }>;\n};\n\nfunction sameDockerMountSource(\n type: \"bind\" | \"volume\",\n left: string,\n right: string,\n): boolean {\n return type === \"bind\" ? resolve(left) === resolve(right) : left === right;\n}\n\nfunction inspectDockerContainer(\n dockerBin: string,\n containerId: string,\n state: DockerEngineState,\n ownerPort: number,\n): DockerEngineInspection {\n const result = spawnSync(dockerBin, [\"inspect\", containerId], {\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n maxBuffer: 1024 * 1024,\n });\n if (result.status !== 0) {\n return { status: \"unavailable\", reason: `docker inspect failed for ${containerId}` };\n }\n let record: DockerInspectRecord;\n try {\n record = (JSON.parse(result.stdout) as DockerInspectRecord[])[0] ?? {};\n } catch {\n return { status: \"unavailable\", reason: `docker inspect returned invalid JSON for ${containerId}` };\n }\n\n const image = record.Config?.Image ?? \"\";\n const expectedImage = `iiidev/iii:${state.engineVersion ?? IIPINNED_VERSION}`;\n if (image !== expectedImage) {\n return {\n status: \"unavailable\",\n reason: `saved container uses ${image || \"an unknown image\"}, expected ${expectedImage}`,\n };\n }\n\n const labels = record.Config?.Labels ?? {};\n const projectName = labels[\"com.docker.compose.project\"] ?? \"\";\n if (labels[\"com.docker.compose.service\"] !== \"iii-engine\" || !projectName) {\n return {\n status: \"unavailable\",\n reason: \"saved container is not the iii-engine service of a Compose project\",\n };\n }\n if (state.projectName && state.projectName !== projectName) {\n return {\n status: \"unavailable\",\n reason: `saved Docker project ${state.projectName} does not match container project ${projectName}`,\n };\n }\n if (state.schemaVersion === 2 && projectName !== dockerProjectName(ownerPort)) {\n return {\n status: \"unavailable\",\n reason: `Docker project ${projectName} does not match REST port ${ownerPort}`,\n };\n }\n\n const restBindings = record.HostConfig?.PortBindings?.[`${ownerPort}/tcp`] ?? [];\n if (!restBindings.some((binding) => binding.HostPort === String(ownerPort))) {\n return {\n status: \"unavailable\",\n reason: `saved container does not publish REST port ${ownerPort}`,\n };\n }\n\n const dataMount = record.Mounts?.find((mount) => mount.Destination === \"/data\");\n const dataMountType = dataMount?.Type;\n const dataMountSource = dataMountType === \"volume\"\n ? dataMount?.Name ?? dataMount?.Source ?? \"\"\n : dataMount?.Source ?? \"\";\n if (\n (dataMountType !== \"bind\" && dataMountType !== \"volume\") ||\n !dataMountSource\n ) {\n return {\n status: \"unavailable\",\n reason: \"saved container has no verifiable /data bind or volume mount\",\n };\n }\n if (\n state.dataMountType &&\n state.dataMountType !== dataMountType\n ) {\n return {\n status: \"unavailable\",\n reason: `saved /data mount type ${state.dataMountType} changed to ${dataMountType}`,\n };\n }\n if (\n state.dataMountSource &&\n !sameDockerMountSource(dataMountType, state.dataMountSource, dataMountSource)\n ) {\n return {\n status: \"unavailable\",\n reason: \"saved container /data mount source changed\",\n };\n }\n if (!state.dataMountSource) {\n if (\n dataMountType === \"bind\" &&\n resolve(dataMountSource) !== resolve(dataDirResolution.dataDir)\n ) {\n return {\n status: \"unavailable\",\n reason: `container /data bind ${dataMountSource} does not match ${dataDirResolution.dataDir}`,\n };\n }\n if (dataMountType === \"volume\" && dataDirResolution.source !== \"default\") {\n return {\n status: \"unavailable\",\n reason: \"legacy container uses a named volume but this invocation selects an explicit data directory\",\n };\n }\n }\n if (\n state.dataDir &&\n resolve(state.dataDir) !== resolve(dataDirResolution.dataDir)\n ) {\n return {\n status: \"unavailable\",\n reason: `saved data directory ${state.dataDir} does not match ${dataDirResolution.dataDir}`,\n };\n }\n\n return {\n status: record.State?.Running ? \"running\" : \"stopped\",\n composeFile: existsSync(state.composeFile)\n ? state.composeFile\n : discoverComposeFile() ?? state.composeFile,\n projectName,\n containerId: record.Id ?? containerId,\n dataMountType,\n dataMountSource,\n preserveContainer:\n state.preserveContainer === true ||\n (state.schemaVersion !== 2 && dataMountType === \"volume\"),\n };\n}\n\nfunction inspectOwnedDockerEngine(state: EngineState): DockerEngineInspection {\n if (state.kind !== \"docker\") {\n return { status: \"unavailable\", reason: \"engine state is not Docker\" };\n }\n const ownerPort = engineStateRestPort(state);\n if (state.schemaVersion === 2 && state.projectName !== dockerProjectName(ownerPort)) {\n return {\n status: \"unavailable\",\n reason: `saved Docker project ${state.projectName} does not match REST port ${ownerPort}`,\n };\n }\n\n const dockerBin = whichBinary(\"docker\");\n if (!dockerBin) {\n return { status: \"unavailable\", reason: \"docker is not on PATH\" };\n }\n\n const discoveryFailures: string[] = [];\n if (state.containerId) {\n const direct = inspectDockerContainer(dockerBin, state.containerId, state, ownerPort);\n if (direct.status !== \"unavailable\") return direct;\n if (state.preserveContainer) return direct;\n discoveryFailures.push(direct.reason);\n }\n\n const composeFile = existsSync(state.composeFile)\n ? state.composeFile\n : discoverComposeFile() ?? state.composeFile;\n const candidateIds = new Set<string>();\n try {\n if (existsSync(composeFile)) {\n const composeText = readFileSync(composeFile, \"utf-8\");\n if (!/^\\s+iii-engine:/m.test(composeText)) {\n return {\n status: \"unavailable\",\n reason: `${composeFile} does not define iii-engine`,\n };\n }\n const psResult = spawnSync(\n dockerBin,\n dockerComposeArgs(composeFile, state.projectName, [\n \"ps\",\n \"-q\",\n \"--all\",\n \"iii-engine\",\n ]),\n { encoding: \"utf-8\", stdio: [\"ignore\", \"pipe\", \"ignore\"] },\n );\n if (psResult.status === 0) {\n for (const id of (psResult.stdout ?? \"\").trim().split(/\\s+/)) {\n if (id) candidateIds.add(id);\n }\n } else {\n discoveryFailures.push(\n `docker compose ps failed for project ${state.projectName ?? \"<default>\"}`,\n );\n }\n }\n\n const scanArgs = [\n \"ps\",\n \"-aq\",\n \"--filter\",\n \"label=com.docker.compose.service=iii-engine\",\n \"--filter\",\n `ancestor=iiidev/iii:${state.engineVersion ?? IIPINNED_VERSION}`,\n ...(state.projectName\n ? [\"--filter\", `label=com.docker.compose.project=${state.projectName}`]\n : []),\n ];\n const scanResult = spawnSync(\n dockerBin,\n scanArgs,\n { encoding: \"utf-8\", stdio: [\"ignore\", \"pipe\", \"ignore\"] },\n );\n if (scanResult.status === 0) {\n for (const id of (scanResult.stdout ?? \"\").trim().split(/\\s+/)) {\n if (id) candidateIds.add(id);\n }\n } else {\n discoveryFailures.push(\"docker container scan failed\");\n }\n\n const matches: DockerEngineInspection[] = [];\n for (const containerId of candidateIds) {\n const inspected = inspectDockerContainer(dockerBin, containerId, state, ownerPort);\n if (inspected.status === \"running\" || inspected.status === \"stopped\") {\n if (\n !matches.some(\n (match) =>\n (match.status === \"running\" || match.status === \"stopped\") &&\n match.containerId === inspected.containerId,\n )\n ) {\n matches.push(inspected);\n }\n } else if (inspected.status === \"unavailable\") {\n discoveryFailures.push(inspected.reason);\n }\n }\n if (matches.length === 1) return matches[0]!;\n if (matches.length > 1) {\n return {\n status: \"unavailable\",\n reason: `multiple Docker iii-engine containers match REST port ${ownerPort}`,\n };\n }\n if (discoveryFailures.length > 0) {\n return {\n status: \"unavailable\",\n reason: [...new Set(discoveryFailures)].join(\"; \"),\n };\n }\n if (state.schemaVersion !== 2 || state.preserveContainer) {\n return {\n status: \"unavailable\",\n reason: `legacy Docker ownership exists for REST port ${ownerPort}, but no unique container can be verified`,\n };\n }\n return {\n status: \"missing\",\n composeFile,\n projectName: state.projectName,\n };\n } catch (err) {\n return {\n status: \"unavailable\",\n reason: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\nfunction persistDockerInspection(\n state: DockerEngineState,\n inspection: DockerEngineInspection,\n): DockerEngineState {\n if (inspection.status !== \"running\" && inspection.status !== \"stopped\") {\n return state;\n }\n const resolved: DockerEngineState = {\n ...state,\n composeFile: inspection.composeFile,\n projectName: inspection.projectName,\n containerId: inspection.containerId,\n dataMountType: inspection.dataMountType,\n dataMountSource: inspection.dataMountSource,\n preserveContainer: inspection.preserveContainer,\n };\n writeEngineState(resolved);\n return resolved;\n}\n\nasync function assertRuntimePortOwnership(): Promise<void> {\n const state = readEngineState();\n if (!state) return;\n const ownerPort = engineStateRestPort(state);\n const requestedPort = getRestPort();\n if (ownerPort === requestedPort) return;\n\n if (state.kind === \"docker\") {\n const inspection = inspectOwnedDockerEngine(state);\n if (inspection.status === \"unavailable\") {\n p.log.error(\n `The data directory contains Docker ownership for REST port ${ownerPort}, but it cannot be verified: ${inspection.reason}. Refusing to overwrite its lifecycle state.`,\n );\n process.exit(1);\n }\n if (inspection.status === \"running\" || inspection.status === \"stopped\") {\n persistDockerInspection(state, inspection);\n p.log.error(\n `The canonical lifecycle state is owned by a ${inspection.status} Docker engine on REST port ${ownerPort}. Refusing to reuse it for port ${requestedPort}. Use the original port, or use --instance <N> for an isolated daemon.`,\n );\n process.exit(1);\n }\n p.log.error(\n `The canonical lifecycle state still records a Docker engine for REST port ${ownerPort}, but its container is missing. Refusing to overwrite that ownership from port ${requestedPort}. Re-run \\`agentmemory stop\\` with the original port to reconcile it.`,\n );\n process.exit(1);\n }\n\n const enginePid = readEnginePidfile();\n const workerPid = readWorkerPidfile();\n let active = Boolean(\n (enginePid &&\n pidAlive(enginePid) &&\n !isForeignPortHolder(pidCommand(enginePid))) ||\n (workerPid && pidAlive(workerPid)),\n );\n if (!active) {\n try {\n await fetch(`http://127.0.0.1:${ownerPort}/`, {\n signal: AbortSignal.timeout(750),\n });\n active = true;\n } catch {}\n }\n if (active) {\n p.log.error(\n `The canonical lifecycle state is owned by a live agentmemory engine on REST port ${ownerPort}. Refusing to reuse it for port ${requestedPort}. Use the original port, or use --instance <N> for an isolated daemon.`,\n );\n process.exit(1);\n }\n clearEnginePidfile();\n clearWorkerPidfile();\n clearEngineState();\n}\n\nfunction configureDockerHostUser(): void {\n if (typeof process.getuid !== \"function\" || typeof process.getgid !== \"function\") {\n return;\n }\n const hostUid = String(process.getuid());\n const hostGid = String(process.getgid());\n process.env[\"AGENTMEMORY_DOCKER_UID\"] ??= hostUid;\n process.env[\"AGENTMEMORY_DOCKER_GID\"] ??= hostGid;\n if (\n process.env[\"AGENTMEMORY_DOCKER_UID\"] === hostUid &&\n process.env[\"AGENTMEMORY_DOCKER_GID\"] === hostGid\n ) {\n process.env[\"AGENTMEMORY_DOCKER_SKIP_CHOWN\"] ??= \"1\";\n }\n}\n\nfunction isInvokedViaNpx(): boolean {\n if (process.env[\"npm_lifecycle_event\"] === \"npx\") return true;\n const argv1 = process.argv[1] ?? \"\";\n if (argv1.includes(\"_npx\")) return true;\n const ua = process.env[\"npm_config_user_agent\"] ?? \"\";\n if (ua.startsWith(\"npm/\") || ua.includes(\" npm/\")) return true;\n return false;\n}\n\n// First-run global-install prompt. Replaces the previous passive\n// `p.log.info` hint that users ignored — typing `agentmemory stop`\n// in a new shell would then 404 with `command not found`. We now\n// ask once, persist the answer in preferences, and never ask again.\nasync function maybeOfferGlobalInstall(): Promise<void> {\n if (!isInvokedViaNpx()) return;\n if (!process.stdin.isTTY) return;\n if (process.env[\"CI\"]) return;\n const prefs = readPrefs();\n if (prefs.skipGlobalInstall || prefs.skipNpxHint) return;\n\n const answer = await p.confirm({\n message:\n \"Install agentmemory globally so the bare `agentmemory` command works in any shell? [Y/n]\",\n initialValue: true,\n });\n if (p.isCancel(answer)) {\n // Treat Ctrl+C as \"not now\" rather than \"never\". Don't persist.\n return;\n }\n if (answer === false) {\n writePrefs({ skipGlobalInstall: true });\n p.log.info(\n \"Skipped. Re-run via `npx @agentmemory/agentmemory` or install later with: npm install -g @agentmemory/agentmemory\",\n );\n return;\n }\n\n const npmBin = whichBinary(\"npm\");\n if (!npmBin) {\n p.log.warn(\n \"npm not found on PATH. Install manually: npm install -g @agentmemory/agentmemory\",\n );\n return;\n }\n const ok = runCommand(\n npmBin,\n [\"install\", \"-g\", `@agentmemory/agentmemory@${VERSION}`],\n { label: `Installing @agentmemory/agentmemory@${VERSION} globally` },\n );\n if (ok) {\n p.log.success(\n \"Installed globally. `agentmemory stop` etc. will now work in new shells.\",\n );\n // Persist so we never re-prompt even if the user happens to npx\n // again from a CI-less TTY.\n writePrefs({ skipGlobalInstall: true });\n } else {\n p.log.warn(\n \"Global install failed. Try manually: npm install -g @agentmemory/agentmemory\",\n );\n }\n}\n\nfunction adoptRunningEngine(): void {\n try {\n const existingState = readEngineState();\n const existingPid = readEnginePidfile();\n if (existingState && existingPid) return;\n\n const pids = findEnginePidsByPort(getRestPort());\n const enginePid = pids[0];\n if (enginePid) {\n // A Docker-forwarded port is held by the VM/proxy process\n // (com.docker.backend, vpnkit, ...), not the engine. Adopting it\n // as kind:\"native\" would make a later `stop` SIGTERM that process.\n const comm = pidCommand(enginePid);\n if (isForeignPortHolder(comm)) {\n vlog(\n `adoptRunningEngine: refusing to adopt pid ${enginePid} (${comm}) — not the iii engine binary`,\n );\n return;\n }\n }\n if (enginePid && !existingPid) {\n writeEnginePidfile(enginePid);\n }\n if (!existingState) {\n writeEngineState({\n kind: \"native\",\n configPath: findIiiConfig() || \"\",\n attached: true,\n });\n }\n if (enginePid && !existingPid) {\n p.log.info(c.ok(`Attached to existing iii-engine (pid ${enginePid})`));\n }\n } catch (err) {\n vlog(`adoptRunningEngine: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n\nasync function runIiiInstaller(): Promise<{ ok: boolean; binPath: string | null }> {\n const releaseUrl = iiiReleaseUrl();\n const asset = iiiReleaseAsset();\n const isZipAsset = asset?.endsWith(\".zip\") === true;\n\n if (!releaseUrl) {\n p.log.warn(\n `iii-engine binary not available for ${platform()}/${process.arch}. Use Docker (\\`docker pull iiidev/iii:${IIPINNED_VERSION}\\`) or download manually from https://github.com/iii-hq/iii/releases/tag/iii%2Fv${IIPINNED_VERSION}.`,\n );\n return { ok: false, binPath: null };\n }\n\n if (IS_WINDOWS || isZipAsset) {\n p.log.info(\n `Auto-install unavailable on ${platform()} — ${asset} isn't tar-compatible. Install manually:\\n` +\n ` 1. Download ${releaseUrl}\\n` +\n ` Its SHA-256 must be ${expectedIiiSha256(IIPINNED_VERSION, asset ?? \"\") ?? `the value in ${releaseUrl.replace(/\\.zip$/, \".sha256\")}`}\\n` +\n ` 2. Extract iii.exe and place it on PATH (e.g. %USERPROFILE%\\\\.local\\\\bin)\\n` +\n `Or use Docker: docker pull iiidev/iii:${IIPINNED_VERSION}`,\n );\n return { ok: false, binPath: null };\n }\n\n const shBin = whichBinary(\"sh\");\n const curlBin = whichBinary(\"curl\");\n const tarBin = whichBinary(\"tar\");\n if (!shBin || !curlBin || !tarBin) {\n const missing = [!shBin && \"sh\", !curlBin && \"curl\", !tarBin && \"tar\"]\n .filter(Boolean)\n .join(\", \");\n p.log.warn(`${missing} not found. Cannot auto-install iii-engine.`);\n return { ok: false, binPath: null };\n }\n\n const binDir = agentmemoryBinDir();\n const binPath = privateIiiPath();\n const label = `Installing iii-engine v${IIPINNED_VERSION} (pinned)`;\n const spinner = p.spinner();\n spinner.start(label);\n const outcome = installIiiArchive({\n sh: shBin,\n releaseUrl,\n version: IIPINNED_VERSION,\n asset: asset ?? \"\",\n binDir,\n binPath,\n });\n if (!outcome.ok) {\n spinner.stop(`${label} ${pc.red(\"✗\")}`);\n const sha256 = expectedIiiSha256(IIPINNED_VERSION, asset ?? \"\");\n const heading =\n outcome.reason === \"checksum\"\n ? \"iii-engine download failed verification\"\n : outcome.reason === \"no-checksum\"\n ? \"iii-engine auto-install skipped\"\n : \"iii-engine download failed\";\n const checksumHint = sha256\n ? \"\"\n : `Compare the archive against ${releaseUrl.replace(/\\.(tar\\.gz|zip)$/, \".sha256\")} before extracting.\\n`;\n p.log.warn(\n `${heading}: ${outcome.detail.slice(0, 300)}\\n` +\n `Install it manually, then re-run agentmemory:\\n` +\n ` ${iiiManualInstallCommand(releaseUrl, binDir, binPath, sha256)}\\n` +\n checksumHint +\n `Or use Docker: docker pull iiidev/iii:${IIPINNED_VERSION}`,\n );\n return { ok: false, binPath: null };\n }\n spinner.stop(`${label} ${pc.green(\"✓\")}`);\n return { ok: true, binPath };\n}\n\ntype StartupFailure = {\n kind: \"no-engine\" | \"no-docker-compose\" | \"engine-crashed\" | \"docker-crashed\";\n stderr?: string;\n binary?: string;\n};\n\nlet startupFailure: StartupFailure | null = null;\nlet activeStartupStderr = createStartupStderrCapture();\n\nfunction printCapturedStartupStderr(): void {\n const stderr = redactCredentialUrls(activeStartupStderr.text().trim());\n if (IS_VERBOSE && stderr) {\n p.note(stderr, \"engine stderr\");\n }\n}\n\nfunction printDockerStartupLogs(): void {\n const state = readEngineState();\n if (state?.kind !== \"docker\") return;\n const inspection = inspectOwnedDockerEngine(state);\n if (inspection.status !== \"running\" && inspection.status !== \"stopped\") return;\n const dockerBin = whichBinary(\"docker\");\n if (!dockerBin) return;\n const result = spawnSync(\n dockerBin,\n [\n \"logs\",\n \"--tail\",\n \"80\",\n inspection.containerId,\n ],\n {\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n timeout: 5000,\n maxBuffer: 64 * 1024,\n },\n );\n const output = redactCredentialUrls(`${result.stdout ?? \"\"}${result.stderr ?? \"\"}`.trim());\n if (output) p.note(output.slice(-16 * 1024), \"docker engine logs\");\n}\n\n// Spawn a background engine and collect any startup stderr for a short\n// window. The process is unref'd so the CLI parent can exit cleanly; we\n// only care about stderr that shows up BEFORE the health check succeeds,\n// which is what surfaces early crash/config-parse errors on all platforms.\nfunction spawnEngineBackground(\n bin: string,\n spawnArgs: string[],\n label: string,\n cwd?: string,\n): ChildProcess {\n vlog(`spawn: ${bin} ${spawnArgs.join(\" \")}${cwd ? ` (cwd: ${cwd})` : \"\"}`);\n activeStartupStderr = createStartupStderrCapture();\n const child = spawn(bin, spawnArgs, {\n detached: true,\n stdio: [\"ignore\", \"ignore\", \"pipe\"],\n windowsHide: true,\n env: engineChildEnv(process.env),\n ...(cwd ? { cwd } : {}),\n });\n const isDocker = label.includes(\"Docker\");\n if (!isDocker && typeof child.pid === \"number\") {\n writeEnginePidfile(child.pid);\n }\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n activeStartupStderr.append(chunk);\n });\n child.on(\"exit\", (code, signal) => {\n const abnormal =\n (code !== null && code !== 0) || (code === null && signal !== null);\n if (abnormal) {\n const stderr = redactCredentialUrls(activeStartupStderr.text());\n startupFailure = {\n kind: isDocker ? \"docker-crashed\" : \"engine-crashed\",\n stderr:\n stderr.trim() ||\n (signal\n ? `process killed by signal ${signal}`\n : `process exited with code ${code}`),\n binary: bin,\n };\n vlog(`engine exited early: code=${code} signal=${signal}`);\n if (IS_VERBOSE && stderr.trim()) {\n p.log.error(`engine stderr:\\n${stderr}`);\n }\n if (!isDocker) {\n clearEnginePidfile();\n clearEngineState();\n }\n }\n });\n child.unref();\n return child;\n}\n\nfunction prepareEngineLaunch(configPath: string): {\n configPath: string;\n cwd: string;\n} {\n const home = homedir();\n const bundledConfig = isBundledConfig(configPath, __dirname);\n const cwd = resolveEngineCwd(\n configPath,\n process.cwd(),\n home,\n bundledConfig,\n );\n const stateBackendKind = getStateBackend();\n try {\n mkdirSync(cwd, { recursive: true });\n } catch (err) {\n const failure = resolveLaunchRenderFailure(stateBackendKind, err);\n if (failure.fatal) {\n p.log.error(failure.message);\n process.exit(1);\n }\n return { configPath, cwd: process.cwd() };\n }\n try {\n const rawConfig = readFileSync(configPath, \"utf-8\");\n const options = {\n dataDir: dataDirResolution.dataDir,\n ports: {\n restPort: getRestPort(),\n streamPort: getStreamPort(),\n viewerPort: getConfiguredViewerPort(),\n enginePort: getEnginePort(),\n },\n stateBackend: { kind: stateBackendKind, redisUrl: getRedisUrl() },\n saveIntervalMs: getStateSaveIntervalMs(),\n };\n const rewritten = bundledConfig\n ? rewriteBundledConfig(\n rawConfig,\n home,\n process.execPath,\n join(__dirname, \"index.mjs\"),\n options,\n )\n : renderEngineConfig(rawConfig, options);\n const runtimePath = runtimeConfigPath(dataDirResolution.dataDir);\n mkdirSync(dirname(runtimePath), { recursive: true });\n writeFileSync(runtimePath, rewritten, \"utf-8\");\n try {\n const cleared = clearPersistedBuiltinConfig(cwd, runtimePath, rewritten);\n if (cleared.length > 0) {\n vlog(\n `cleared ${cleared.length} persisted builtin config entries so the rendered runtime config seeds the engine again`,\n );\n }\n } catch (err) {\n p.log.error(\n `${String(err instanceof Error ? err.message : err)}. The engine would ignore the rendered runtime config and keep its previously persisted ports and timeouts. Fix the permissions on that file and run agentmemory start again.`,\n );\n process.exit(1);\n }\n if (selectedInstance === 0 && dataDirResolution.source === \"default\") {\n for (const m of legacyDataMigrations(\n process.cwd(),\n home,\n dataDirResolution.dataDir,\n )) {\n if (existsSync(m.from) && !existsSync(m.to)) {\n try {\n mkdirSync(dirname(m.to), { recursive: true });\n cpSync(m.from, m.to, { recursive: true });\n p.log.info(`Copied existing data: ${m.from} -> ${m.to}`);\n } catch (err) {\n vlog(`data copy failed for ${m.from}: ${String(err)}`);\n }\n }\n }\n }\n return {\n configPath: runtimePath,\n cwd,\n };\n } catch (err) {\n const failure = resolveLaunchRenderFailure(stateBackendKind, err);\n if (failure.fatal) {\n p.log.error(failure.message);\n process.exit(1);\n }\n vlog(`runtime config generation failed, using bundled config verbatim: ${String(err)}`);\n return { configPath, cwd };\n }\n}\n\nfunction startIiiBin(iiiBin: string, configPath: string): boolean {\n const s = p.spinner();\n s.start(`Starting iii-engine: ${iiiBin}`);\n const launch = prepareEngineLaunch(configPath);\n writeEngineState({\n kind: \"native\",\n configPath: launch.configPath,\n binPath: iiiBin,\n });\n spawnEngineBackground(\n iiiBin,\n [\"--config\", launch.configPath, \"--no-update-check\"],\n \"iii-engine\",\n launch.cwd,\n );\n s.stop(c.ok(\"iii-engine process started\"));\n return true;\n}\n\n// Find a pinned-compatible iii path from a list of candidates. Returns\n// the first candidate whose --version matches the pin, OR returns the\n// private install path if it exists and matches, OR null if no candidate\n// is compatible. Caller (startEngine) auto-installs the pin to the\n// private path when this returns null.\nfunction pickCompatibleIii(candidates: Array<string | null | undefined>): string | null {\n for (const c of candidates) {\n if (!c) continue;\n const resolved = resolveCompatibleIii(c);\n if (resolved) return resolved;\n }\n return null;\n}\n\nfunction warnIfDockerIgnoresStateBackend(stateBackendKind: \"file\" | \"redis\"): void {\n if (stateBackendKind !== \"redis\") return;\n p.log.warn(\n \"AGENTMEMORY_STATE_BACKEND=redis is not applied on the Docker path: docker-compose.yml mounts iii-config.docker.yaml read-only, so this start will not render it. \" +\n \"Edit iii-config.docker.yaml by hand to point iii-state/iii-stream at redis (see README \\\"Storage backend\\\"), or it keeps using the file store. \" +\n \"docker-compose.yml passes AGENTMEMORY_REDIS_URL into the engine container, so redis_url: '${AGENTMEMORY_REDIS_URL}' works in that file.\",\n );\n}\n\nasync function startEngine(): Promise<boolean> {\n let stateBackendKind: \"file\" | \"redis\";\n try {\n stateBackendKind = getStateBackend();\n } catch (err) {\n p.log.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n if (stateBackendKind === \"redis\" && !getRedisUrl()) {\n p.log.error(\n \"AGENTMEMORY_STATE_BACKEND=redis requires AGENTMEMORY_REDIS_URL to be set (e.g. redis://localhost:6379). \" +\n \"Set both in ~/.agentmemory/.env, or unset AGENTMEMORY_STATE_BACKEND to keep the default file store.\",\n );\n process.exit(1);\n }\n await assertRuntimePortOwnership();\n const persistedState = readEngineState();\n if (persistedState?.kind === \"docker\") {\n warnIfDockerIgnoresStateBackend(stateBackendKind);\n const inspection = inspectOwnedDockerEngine(persistedState);\n if (inspection.status === \"unavailable\" || inspection.status === \"missing\") {\n const detail = inspection.status === \"unavailable\"\n ? inspection.reason\n : \"container is missing\";\n p.log.error(\n `A saved Docker engine owns this lifecycle state, but it cannot be resumed safely (${detail}). Run \\`agentmemory stop\\` to reconcile that project before starting another engine.`,\n );\n return false;\n }\n persistDockerInspection(persistedState, inspection);\n if (inspection.status === \"running\") return true;\n const dockerBin = whichBinary(\"docker\");\n return Boolean(\n dockerBin &&\n runCommand(dockerBin, [\"start\", inspection.containerId], {\n label: `Restarting owned Docker container ${inspection.containerId}`,\n }),\n );\n }\n const configPath = findIiiConfig();\n warnIfRelocatedDataDir();\n const pathIii = whichBinary(\"iii\");\n vlog(`iii binary: ${pathIii ?? \"(not on PATH)\"}, config: ${configPath || \"(not found)\"}`);\n\n const dockerBin = whichBinary(\"docker\");\n const dockerComposeCandidates = [\n join(__dirname, \"..\", \"docker-compose.yml\"),\n join(__dirname, \"docker-compose.yml\"),\n join(process.cwd(), \"docker-compose.yml\"),\n ];\n const composeFile = dockerComposeCandidates.find((c) => existsSync(c));\n const dockerOptIn =\n process.env[\"AGENTMEMORY_USE_DOCKER\"] === \"1\" ||\n process.env[\"AGENTMEMORY_USE_DOCKER\"] === \"true\";\n\n const fallbacks = fallbackIiiPaths().filter((p) => existsSync(p));\n for (const f of fallbacks) {\n const v = iiiBinVersion(f);\n vlog(`fallback iii at ${f} reports version: ${v ?? \"unknown\"}`);\n }\n\n let iiiBin = pickCompatibleIii([pathIii, ...fallbacks]);\n\n if (iiiBin && configPath && !(dockerOptIn && dockerBin && composeFile)) {\n if (iiiBin !== pathIii) {\n p.log.info(`Using iii at: ${c.dim(iiiBin)} (v${c.accent(IIPINNED_VERSION)})`);\n process.env[\"PATH\"] = `${dirname(iiiBin)}${PATH_DELIMITER}${process.env[\"PATH\"] ?? \"\"}`;\n }\n return startIiiBin(iiiBin, configPath);\n }\n\n if (pathIii && !iiiBin) {\n const detected = iiiBinVersion(pathIii);\n vlog(\n `iii on PATH is v${detected ?? \"unknown\"}, pin is v${IIPINNED_VERSION}. ` +\n `Will install pinned engine to ${privateIiiPath()}.`,\n );\n }\n\n if (!configPath) {\n startupFailure = { kind: \"no-engine\" };\n return false;\n }\n\n vlog(`docker binary: ${dockerBin ?? \"(not on PATH)\"}`);\n mkdirSync(dataDirResolution.dataDir, { recursive: true });\n vlog(`docker-compose.yml: ${composeFile ?? \"(not found)\"}`);\n const interactive = !!process.stdin.isTTY && !process.env[\"CI\"];\n\n type Choice = \"install\" | \"docker\" | \"manual\";\n let choice: Choice;\n\n // Wrong-version iii on PATH is a configuration trap: any prompt would\n // confuse the user since they already \"have iii installed\". Skip the\n // prompt and auto-install pinned engine to the private location.\n const pathIiiMismatch = pathIii !== null && resolveCompatibleIii(pathIii) === null;\n\n if (dockerOptIn && dockerBin && composeFile) {\n choice = \"docker\";\n } else if (pathIiiMismatch) {\n choice = \"install\";\n const detected = iiiBinVersion(pathIii!);\n p.log.info(\n `iii on PATH is v${detected ?? \"unknown\"} but agentmemory pins v${IIPINNED_VERSION}. ` +\n `Installing pinned engine to ~/.agentmemory/bin (leaves your existing iii untouched).`,\n );\n } else if (!interactive) {\n choice = \"install\";\n p.log.info(\"Non-interactive environment detected — auto-installing iii-engine.\");\n } else {\n p.log.warn(`iii-engine binary not found locally.`);\n const options: { value: Choice; label: string; hint?: string }[] = [\n {\n value: \"install\",\n label: `Install iii v${IIPINNED_VERSION} to ~/.agentmemory/bin (~6MB, ~5s)`,\n hint: \"recommended\",\n },\n ];\n if (dockerBin && composeFile) {\n options.push({ value: \"docker\", label: \"Use Docker compose\", hint: \"advanced\" });\n }\n options.push({ value: \"manual\", label: \"Show manual install steps and exit\" });\n\n const picked = await p.select<Choice>({\n message: \"How would you like to start iii-engine?\",\n options,\n initialValue: \"install\",\n });\n if (p.isCancel(picked)) {\n startupFailure = { kind: \"no-engine\" };\n return false;\n }\n choice = picked;\n }\n\n if (choice === \"manual\") {\n startupFailure = { kind: \"no-engine\" };\n return false;\n }\n\n if (choice === \"install\") {\n const result = await runIiiInstaller();\n if (result.ok && result.binPath) {\n process.env[\"PATH\"] = `${dirname(result.binPath)}${PATH_DELIMITER}${process.env[\"PATH\"] ?? \"\"}`;\n iiiBin = result.binPath;\n return startIiiBin(iiiBin, configPath);\n }\n if (dockerBin && composeFile && interactive) {\n const fallback = await p.confirm({\n message: \"Auto-install failed. Try Docker compose instead?\",\n initialValue: true,\n });\n if (p.isCancel(fallback) || fallback !== true) {\n startupFailure = { kind: \"no-engine\" };\n return false;\n }\n choice = \"docker\";\n } else {\n startupFailure = { kind: \"no-engine\" };\n return false;\n }\n }\n\n if (choice === \"docker\" && dockerBin && composeFile) {\n warnIfDockerIgnoresStateBackend(stateBackendKind);\n const s = p.spinner();\n s.start(\"Starting iii-engine via Docker...\");\n configureDockerHostUser();\n const projectName = dockerProjectName(getRestPort());\n writeEngineState({\n kind: \"docker\",\n schemaVersion: 2,\n composeFile,\n projectName,\n engineVersion: IIPINNED_VERSION,\n dataMountType: \"bind\",\n dataMountSource: dataDirResolution.dataDir,\n preserveContainer: false,\n });\n spawnEngineBackground(\n dockerBin,\n dockerComposeArgs(composeFile, projectName, [\"up\", \"-d\"]),\n \"iii-engine via Docker\",\n );\n s.stop(\"Docker compose started\");\n return true;\n }\n\n if (!composeFile && dockerBin) {\n startupFailure = { kind: \"no-docker-compose\" };\n } else {\n startupFailure = { kind: \"no-engine\" };\n }\n return false;\n}\n\nasync function waitForEngine(timeoutMs: number): Promise<boolean> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n if (await isEngineRunning()) return true;\n await new Promise((r) => setTimeout(r, 500));\n }\n return false;\n}\n\nasync function reconcilePersistedDockerEngine(): Promise<boolean> {\n const state = readEngineState();\n if (state?.kind !== \"docker\") return false;\n const inspection = inspectOwnedDockerEngine(state);\n if (inspection.status === \"unavailable\") {\n p.log.error(\n `The saved Docker engine cannot be verified: ${inspection.reason}. Refusing to overwrite its lifecycle state. Run \\`agentmemory stop\\` after restoring Docker/compose access.`,\n );\n process.exit(1);\n }\n if (inspection.status === \"missing\") {\n p.log.error(\n \"The saved Docker project no longer has an iii-engine container. Run `agentmemory stop` to remove its stale project state, then start agentmemory again.\",\n );\n process.exit(1);\n }\n persistDockerInspection(state, inspection);\n if (inspection.status === \"stopped\") {\n const dockerBin = whichBinary(\"docker\");\n if (\n !dockerBin ||\n !runCommand(dockerBin, [\"start\", inspection.containerId], {\n label: `Restarting owned Docker container ${inspection.containerId}`,\n })\n ) {\n p.log.error(\"The owned Docker container could not be restarted; lifecycle state was preserved.\");\n process.exit(1);\n }\n }\n if (!(await waitForEngine(5000))) {\n printDockerStartupLogs();\n p.log.error(\n `The owned Docker container is running, but its REST API on port ${getRestPort()} is unhealthy. The saved project was preserved; inspect the Docker logs above or run \\`agentmemory stop\\`.`,\n );\n process.exit(1);\n }\n await startWorkerForEngineState();\n if (!(await waitForAgentmemoryReady(15000))) {\n p.log.error(\"agentmemory worker did not become ready within 15s.\");\n process.exit(1);\n }\n await maybeOfferGlobalInstall();\n printReadyHint();\n return true;\n}\n\nfunction installInstructions(): string[] {\n const releaseUrl = iiiReleaseUrl();\n if (IS_WINDOWS) {\n const asset = iiiReleaseAsset() ?? \"\";\n const sha256 = expectedIiiSha256(IIPINNED_VERSION, asset);\n const verify = sha256\n ? ` Verify before extracting: (Get-FileHash .\\\\${asset}).Hash must be ${sha256.toUpperCase()}`\n : ` Verify before extracting against the matching .sha256 file on the release page`;\n return [\n `agentmemory needs iii-engine v${IIPINNED_VERSION}. Pick one:`,\n \"\",\n \" A) Download the prebuilt Windows binary:\",\n ` 1. Open https://github.com/iii-hq/iii/releases/tag/iii%2Fv${IIPINNED_VERSION}`,\n ` 2. Download iii-x86_64-pc-windows-msvc.zip (or iii-aarch64-pc-windows-msvc.zip on ARM)`,\n verify,\n \" 3. Extract iii.exe to %USERPROFILE%\\\\.local\\\\bin\\\\iii.exe (or add to PATH)\",\n \" 4. Re-run: npx @agentmemory/agentmemory\",\n \"\",\n ` B) Docker: docker pull iiidev/iii:${IIPINNED_VERSION}`,\n \" Re-run with AGENTMEMORY_USE_DOCKER=1 npx @agentmemory/agentmemory\",\n \"\",\n \"Or skip the engine entirely (standalone MCP): npx @agentmemory/agentmemory mcp\",\n \"\",\n \"Docs: https://iii.dev/docs\",\n ];\n }\n const linuxInstall = releaseUrl\n ? ` A) ${iiiManualInstallCommand(releaseUrl, agentmemoryBinDir(), privateIiiPath(), expectedIiiSha256(IIPINNED_VERSION, iiiReleaseAsset() ?? \"\"))}`\n : ` A) Manual download: https://github.com/iii-hq/iii/releases/tag/iii%2Fv${IIPINNED_VERSION}`;\n return [\n `agentmemory needs iii-engine v${IIPINNED_VERSION}. Pick one:`,\n \"\",\n linuxInstall,\n \" Then re-run: npx @agentmemory/agentmemory\",\n \"\",\n ` B) Docker: docker pull iiidev/iii:${IIPINNED_VERSION}`,\n \" Re-run with AGENTMEMORY_USE_DOCKER=1 npx @agentmemory/agentmemory\",\n \"\",\n \"Or skip the engine entirely (standalone MCP): npx @agentmemory/agentmemory mcp\",\n \"\",\n \"Docs: https://iii.dev/docs\",\n ];\n}\n\nfunction portInUseDiagnostic(port: number): string {\n return IS_WINDOWS\n ? ` netstat -ano | findstr :${port}`\n : ` lsof -i :${port} # or: ss -tlnp | grep :${port}`;\n}\n\nasync function waitForAgentmemoryReady(timeoutMs: number): Promise<boolean> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n if (await isAgentmemoryReady()) return true;\n await new Promise((r) => setTimeout(r, 250));\n }\n return false;\n}\n\n// Derive a host string for the streams/engine WebSocket lines from\n// the configured engine URL (`III_ENGINE_URL`) or REST base\n// (`AGENTMEMORY_URL`) so a remote-bind setup like\n// `III_ENGINE_URL=ws://my-host:49134` doesn't print misleading\n// localhost addresses. Falls back to localhost.\nfunction getEngineHost(): string {\n const envKeys = shouldUseAgentmemoryUrl()\n ? [\"III_ENGINE_URL\", \"AGENTMEMORY_URL\"]\n : [\"III_ENGINE_URL\"];\n for (const envKey of envKeys) {\n const raw = process.env[envKey];\n if (!raw) continue;\n try {\n const parsed = new URL(raw);\n if (parsed.hostname) return parsed.hostname;\n } catch {}\n }\n return \"localhost\";\n}\n\nfunction printReadyHint(): void {\n const restUrl = getBaseUrl();\n const viewerUrl = getViewerUrl();\n const engineHost = getEngineHost();\n const streamUrl = `ws://${engineHost}:${getStreamPort()}`;\n const engineUrl = `ws://${engineHost}:${getEnginePort()}`;\n const invocation = isInvokedViaNpx() ? \"npx @agentmemory/agentmemory\" : \"agentmemory\";\n const consolePort = defaultConsolePort(getConfiguredViewerPort());\n const portFlags = portFlagSuffix(getRestPort(), selectedInstance);\n\n const consoleLine = `${c.label(\"iii console\")} ${c.cmd(`${invocation} console${portFlags}`)} ${c.dim(`(serves on :${consolePort}; first run downloads the console next to the pinned iii)`)}`;\n\n const lines = [\n `${c.label(\"REST API\")} ${c.url(restUrl)}`,\n `${c.label(\"Viewer\")} ${c.url(viewerUrl)}`,\n `${c.label(\"Streams\")} ${c.url(streamUrl)}`,\n `${c.label(\"Engine\")} ${c.url(engineUrl)}`,\n consoleLine,\n ];\n // p.note renders a bordered panel with a title — same affordance\n // used elsewhere in this CLI for \"Troubleshooting\" / \"Setup\n // required\" blocks, so the visual language stays consistent.\n p.note(lines.join(\"\\n\"), `agentmemory v${c.accent(VERSION)}`);\n\n // Pick a runnable form for the suggested next-step. Users invoked\n // via `npx` don't have the bare `agentmemory` command on PATH yet\n // (unless they accepted the global-install prompt and the npm bin\n // dir was already on PATH in this shell), so we suggest the npx\n // form for them; everyone else gets the global form.\n const demoCommand = `${invocation} demo${portFlags}`;\n process.stdout.write(`\\n${c.dim(\"Try:\")} ${c.cmd(demoCommand)}\\n`);\n}\n\nasync function main() {\n await assertRuntimePortOwnership();\n // Booting a second instance next to a live daemon registers a duplicate\n // worker on the running engine, and before iii 0.19.2 the second instance's\n // shutdown tore down the daemon's HTTP trigger routing (every\n // /agentmemory/* route 404s until a full engine restart). Refuse instead.\n // A different --instance resolves to a different port, so multi-instance\n // setups are unaffected.\n try {\n const probe = await fetch(`${getBaseUrl()}/agentmemory/livez`, {\n signal: AbortSignal.timeout(1500),\n });\n if (probe.ok) {\n p.log.error(\n `agentmemory is already running on port ${getRestPort()}. Starting a second instance here would corrupt the running daemon's REST routing. Use the REST API (or the MCP tools) against the running instance, run a different --instance, or stop it first with \\`agentmemory stop\\`.`,\n );\n process.exit(1);\n }\n } catch {\n // no live daemon on this port; boot normally\n }\n\n // `--reset` wipes preferences before anything else so the onboarding\n // flow below always runs fresh.\n if (IS_RESET) {\n resetPrefs();\n }\n\n const firstRun = isFirstRun();\n const prefs = readPrefs();\n // Show the splash on the first run, on --reset, or whenever the user\n // hasn't yet opted out via the schema (we set `skipSplash: true`\n // after onboarding completes). Verbose runs always splash since the\n // user explicitly asked for the chatty experience.\n if (firstRun || IS_RESET || IS_VERBOSE || !prefs.skipSplash) {\n renderSplash(VERSION);\n }\n\n if (firstRun || IS_RESET) {\n await runOnboarding();\n }\n\n if (skipEngine) {\n if (IS_VERBOSE) p.log.info(\"Skipping engine check (--no-engine)\");\n await import(\"./index.js\");\n if (await waitForAgentmemoryReady(15000)) {\n await maybeOfferGlobalInstall();\n printReadyHint();\n }\n return;\n }\n\n if (await reconcilePersistedDockerEngine()) return;\n\n if (await isEngineRunning()) {\n if (IS_VERBOSE) p.log.success(\"iii-engine is running\");\n // Prefer the binary path persisted at launch time over whatever's on\n // PATH now. PATH lookups misfire when a global iii install gets added\n // after agentmemory started (or when the running engine was launched\n // from a path that's no longer first on PATH).\n const persisted = readEngineState();\n const persistedBin =\n persisted?.kind === \"native\" && persisted.binPath && existsSync(persisted.binPath)\n ? persisted.binPath\n : null;\n const attachedBin =\n persistedBin ??\n whichBinary(\"iii\") ??\n fallbackIiiPaths().find((p) => existsSync(p)) ??\n null;\n const detected = attachedBin ? iiiBinVersion(attachedBin) : null;\n\n // Fail closed: only adopt the running engine when we can positively\n // confirm it is the pinned version. An unknown version (detected === null,\n // e.g. the binary can't be version-probed) is treated as incompatible —\n // adopting a foreign or unverifiable engine hangs the worker in a\n // WebSocket reconnect loop. Worst case here is a re-run that reinstalls\n // the pinned engine, never a silent loop.\n if (detected === IIPINNED_VERSION) {\n adoptRunningEngine();\n await startWorkerForEngineState();\n if (!(await waitForAgentmemoryReady(15000))) {\n p.log.error(\"agentmemory worker did not become ready within 15s.\");\n process.exit(1);\n }\n await maybeOfferGlobalInstall();\n printReadyHint();\n return;\n }\n\n const detectedLabel = detected ? `v${detected}` : \"an unverified version\";\n\n // An incompatible engine owns the port. Adopting it hangs the worker in a\n // WebSocket reconnect loop (it can't speak that engine's protocol), so stop\n // with the simplest honest remedy. A normal user has no other engine and\n // never sees this; only someone running their own iii does, and for them\n // \"stop it, then run normally\" is the fix. We do not suggest a different\n // engine version: agentmemory only supports v${IIPINNED_VERSION}.\n const base = isInvokedViaNpx() ? \"npx @agentmemory/agentmemory\" : \"agentmemory\";\n p.log.error(\n `Another iii-engine (${detectedLabel}) is running on port ${getEnginePort()}, and agentmemory needs its own pinned v${IIPINNED_VERSION}.`,\n );\n p.note(\n [\n `agentmemory only supports iii-engine v${IIPINNED_VERSION}. It will not adopt or change the running engine (${detectedLabel}).`,\n \"\",\n c.label(\"Switch to the pinned engine in two steps:\"),\n \"\",\n ` 1. Stop the running engine:`,\n ` ${c.cmd(`${base} stop --force`)}`,\n ` ${c.dim(`(or stop your own iii however you started it — agentmemory leaves your global iii untouched)`)}`,\n \"\",\n ` 2. Start agentmemory. It downloads and runs the pinned`,\n ` v${IIPINNED_VERSION} into ~/.agentmemory/bin automatically:`,\n ` ${c.cmd(base)}`,\n \"\",\n c.dim(`Step 2 needs no manual install. To install iii v${IIPINNED_VERSION} yourself (replaces your global iii), curl:`),\n ` ${c.cmd(IIIENGINE_INSTALL_CMD)}`,\n ` ${c.dim(\"or download the release:\")} ${c.url(`https://github.com/iii-hq/iii/releases/tag/iii%2Fv${IIPINNED_VERSION}`)}`,\n ].join(\"\\n\"),\n \"engine conflict\",\n );\n process.exit(1);\n }\n\n const started = await startEngine();\n if (!started) {\n p.log.error(\"Could not start iii-engine.\");\n const lines = installInstructions();\n if (startupFailure?.kind === \"no-docker-compose\") {\n lines.unshift(\n \"Docker is installed but docker-compose.yml is missing from this\",\n \"install. Re-install with: npm install -g @agentmemory/agentmemory\",\n \"\",\n );\n }\n p.note(lines.join(\"\\n\"), \"Setup required\");\n process.exit(1);\n }\n\n const s = p.spinner();\n s.start(\"Waiting for iii-engine to be ready...\");\n\n const ready = await waitForEngine(15000);\n if (!ready) {\n const port = getRestPort();\n s.stop(\"iii-engine did not become ready within 15s\");\n printDockerStartupLogs();\n\n if (startupFailure?.kind === \"engine-crashed\" || startupFailure?.kind === \"docker-crashed\") {\n p.log.error(\"The iii-engine process crashed on startup.\");\n if (startupFailure.binary) {\n p.log.info(`Binary: ${startupFailure.binary}`);\n }\n if (startupFailure.stderr) {\n p.note(startupFailure.stderr, \"engine stderr\");\n } else {\n p.log.info(\"No stderr was captured. Re-run with --verbose for more detail.\");\n }\n p.note(\n [\n \"Common causes:\",\n ` - iii-engine version mismatch — reinstall the pinned v${IIPINNED_VERSION} binary`,\n \" (sh script on macOS/Linux, GitHub release zip on Windows)\",\n \" - Docker Desktop not running (if you're using the Docker path)\",\n \" - Port already in use (see below)\",\n \"\",\n \"See https://iii.dev/docs for current install instructions.\",\n ].join(\"\\n\"),\n \"Troubleshooting\",\n );\n } else {\n p.log.error(\"The engine process started but the REST API never responded.\");\n printCapturedStartupStderr();\n p.note(\n [\n `Check whether port ${port} is already bound by another process:`,\n portInUseDiagnostic(port),\n \"\",\n \"If it is, free the port or override: agentmemory --port <N>\",\n \"\",\n \"If it isn't, a firewall may be blocking 127.0.0.1:\" + port + \".\",\n \"Re-run with --verbose to see engine stderr.\",\n ].join(\"\\n\"),\n \"Troubleshooting\",\n );\n }\n process.exit(1);\n }\n\n s.stop(c.ok(\"iii-engine is ready\"));\n await startWorkerForEngineState();\n if (!(await waitForAgentmemoryReady(15000))) {\n p.log.error(\"agentmemory worker did not become ready within 15s.\");\n process.exit(1);\n }\n await maybeOfferGlobalInstall();\n printReadyHint();\n // Mark splash as something to skip on subsequent runs. This is a\n // no-op if onboarding already flipped the flag (idempotent merge).\n writePrefs({ skipSplash: true });\n}\n\nasync function apiFetch<T = unknown>(base: string, path: string, timeoutMs = 5000): Promise<T | null> {\n try {\n const headers: Record<string, string> = bearerHeaders(base);\n const res = await fetch(`${base}/agentmemory/${path}`, {\n signal: AbortSignal.timeout(timeoutMs),\n headers,\n });\n return (await res.json()) as T;\n } catch {\n return null;\n }\n}\n\nasync function runStatus() {\n const port = getRestPort();\n const base = getBaseUrl();\n p.intro(\"agentmemory status\");\n\n const up = await isEngineRunning();\n if (!up) {\n p.log.error(`Not running — no response at ${base}`);\n p.log.info(\"Start with: npx @agentmemory/agentmemory\");\n process.exit(1);\n }\n\n try {\n const [healthRes, sessionsRes, graphRes, memoriesRes, flagsRes, followupRes] = await Promise.all([\n apiFetch<any>(base, \"health\"),\n apiFetch<any>(base, \"sessions\"),\n apiFetch<any>(base, \"graph/stats\"),\n apiFetch<any>(base, \"memories?count=true\"),\n apiFetch<any>(base, \"config/flags\"),\n apiFetch<any>(base, \"diagnostics/followup\"),\n ]);\n\n if (typeof healthRes?.viewerPort === \"number\") {\n discoveredViewerPort = healthRes.viewerPort;\n }\n const h = healthRes?.health;\n const status = healthRes?.status || \"unknown\";\n const version = healthRes?.version || \"?\";\n const sessionList = Array.isArray(sessionsRes?.sessions) ? sessionsRes.sessions : [];\n const sessions = sessionList.length;\n const nodes = Number(graphRes?.totalNodes ?? graphRes?.nodes ?? graphRes?.nodeCount ?? 0);\n const edges = Number(graphRes?.totalEdges ?? graphRes?.edges ?? graphRes?.edgeCount ?? 0);\n const cb = healthRes?.circuitBreaker?.state || \"closed\";\n const heapMB = h?.memory ? Math.round(h.memory.heapUsed / 1048576) : 0;\n const uptime = h?.uptimeSeconds ? Math.round(h.uptimeSeconds) : 0;\n\n const obsCount = sessionList.reduce(\n (sum: number, s: any) => sum + (Number(s?.observationCount) || 0),\n 0,\n );\n const memCount = Number(memoriesRes?.latestCount ?? memoriesRes?.total ?? 0) || 0;\n const estFullTokens = obsCount * 80;\n const estInjectedTokens = Math.min(obsCount, 50) * 38;\n const tokensSaved = estFullTokens - estInjectedTokens;\n const pctSaved = estFullTokens > 0 ? Math.round((tokensSaved / estFullTokens) * 100) : 0;\n\n p.log.success(`Connected — v${version} at ${base}`);\n\n const lines = [\n `Health: ${status === \"healthy\" ? pc.green(\"✓ healthy\") : pc.yellow(status)}`,\n `Sessions: ${sessions}`,\n `Observations: ${obsCount}`,\n `Memories: ${memCount}`,\n `Graph: ${nodes} nodes, ${edges} edges`,\n `Circuit: ${cb}`,\n `Heap: ${heapMB} MB`,\n `Uptime: ${uptime}s`,\n `Viewer: ${c.url(getViewerUrl())}`,\n ];\n\n if (obsCount > 0) {\n lines.push(\"\");\n lines.push(`Token savings: ~${tokensSaved.toLocaleString()} tokens saved (${pctSaved}% reduction)`);\n lines.push(` Full context: ~${estFullTokens.toLocaleString()} tokens`);\n lines.push(` Injected: ~${estInjectedTokens.toLocaleString()} tokens`);\n }\n\n if (flagsRes) {\n const provider = flagsRes.provider === \"llm\" ? pc.green(\"✓ llm\") : pc.yellow(\"✗ noop (no key)\");\n const embed = flagsRes.embeddingProvider === \"embeddings\" ? pc.green(\"✓ embeddings\") : pc.dim(\"bm25-only\");\n const flagRows = (flagsRes.flags || []).map((f: { key: string; enabled: boolean; label: string }) =>\n ` ${f.enabled ? pc.green(\"✓\") : pc.dim(\"✗\")} ${pc.bold(f.key.padEnd(32))} ${f.label}`\n );\n lines.push(\"\");\n lines.push(`Provider: ${provider}`);\n lines.push(`Embeddings: ${embed}`);\n lines.push(`Flags:`);\n flagRows.forEach((r: string) => lines.push(r));\n }\n\n if (followupRes && Number.isFinite(followupRes.agentInitiatedSearches)) {\n const total = Number(followupRes.agentInitiatedSearches) || 0;\n const hits = Number(followupRes.followupWithinWindow) || 0;\n const pct = total > 0 ? Math.round((hits / total) * 100) : 0;\n lines.push(\"\");\n lines.push(\n `Followup rate: ${hits}/${total} (${pct}%) within ${followupRes.windowSeconds}s — directional, may overcount on refinement`,\n );\n }\n\n p.note(lines.join(\"\\n\"), \"agentmemory\");\n } catch (err) {\n p.log.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n}\n\ntype DoctorCheck = { name: string; ok: boolean; hint?: string };\n\nfunction formatChecks(checks: DoctorCheck[]): string {\n return checks\n .map((c) => `${c.ok ? pc.green(\"✓\") : pc.red(\"✗\")} ${c.name}${c.hint ? `\\n ${c.hint}` : \"\"}`)\n .join(\"\\n\");\n}\n\ntype CCHooksCheck =\n | { state: \"loaded\"; manifestPath?: string }\n | { state: \"not-loaded\" }\n | { state: \"no-debug-log\" }\n | { state: \"no-cc-dir\" };\n\nfunction findLatestDebugLog(debugDir: string): string | undefined {\n const latestLink = join(debugDir, \"latest\");\n try {\n if (existsSync(latestLink)) {\n const target = readlinkSync(latestLink);\n const resolved = target.startsWith(\"/\") ? target : join(debugDir, target);\n if (existsSync(resolved)) return resolved;\n }\n } catch {}\n\n try {\n const newest = readdirSync(debugDir)\n .filter((f) => f.endsWith(\".txt\"))\n .map((f) => ({ f, m: statSync(join(debugDir, f)).mtimeMs }))\n .sort((a, b) => b.m - a.m)[0];\n if (newest) return join(debugDir, newest.f);\n } catch {}\n\n return undefined;\n}\n\nfunction checkClaudeCodeHooks(): CCHooksCheck {\n const debugDir = join(homedir(), \".claude\", \"debug\");\n if (!existsSync(debugDir)) return { state: \"no-cc-dir\" };\n\n const logPath = findLatestDebugLog(debugDir);\n if (!logPath) return { state: \"no-debug-log\" };\n\n let content: string;\n try {\n content = readFileSync(logPath, \"utf8\");\n } catch {\n return { state: \"no-debug-log\" };\n }\n\n const match = content.match(\n /Loaded hooks from standard location for plugin agentmemory:\\s*(\\S+)/\n );\n if (match) return { state: \"loaded\", manifestPath: match[1] };\n if (content.includes(\"Loading hooks from plugin: agentmemory\")) return { state: \"loaded\" };\n return { state: \"not-loaded\" };\n}\n\n// ---------------------------------------------------------------------------\n// Doctor v2 — interactive fixer.\n//\n// The legacy passive check-list (server reachable, flags, knowledge-graph,\n// Claude Code hooks) still runs first as an informational summary because\n// those checks need a live engine and don't have a one-shot inline fix.\n// Then we drive the new diagnostic catalog (see src/cli/doctor-diagnostics.ts)\n// which prompts Fix/Skip/More/Quit per failing check, applies the fix\n// inline, and re-checks only the affected diagnostic.\n\nfunction buildDoctorContext(): DoctorContext {\n return {\n baseUrl: getBaseUrl(),\n viewerUrl: getViewerUrl(),\n envPath: join(homedir(), \".agentmemory\", \".env\"),\n pidfilePath: enginePidfilePath(),\n enginePath: engineStatePath(),\n pinnedVersion: IIPINNED_VERSION,\n };\n}\n\nfunction buildDoctorEffects(): DoctorEffects {\n return {\n envFileExists: () => existsSync(join(homedir(), \".agentmemory\", \".env\")),\n readEnvFile: () => {\n try {\n return parseEnvFile(\n readFileSync(join(homedir(), \".agentmemory\", \".env\"), \"utf-8\"),\n );\n } catch {\n return {};\n }\n },\n pidfileExists: () => existsSync(enginePidfilePath()),\n pidfilePidIsAlive: () => {\n const pid = readEnginePidfile();\n if (pid === null) return null;\n return pidAlive(pid);\n },\n findIiiBinary: () => whichBinary(\"iii\"),\n localBinIiiPath: () => privateIiiPath(),\n iiiBinaryVersion: (binPath: string) => iiiBinVersion(binPath),\n viewerReachable: async (timeoutMs = 2000) => {\n try {\n await discoverViewerPort();\n const res = await fetch(getViewerUrl(), {\n signal: AbortSignal.timeout(timeoutMs),\n });\n return res.ok;\n } catch {\n return false;\n }\n },\n runInit: async () => {\n try {\n await runInit();\n return { ok: true, message: \"Wrote ~/.agentmemory/.env\" };\n } catch (err) {\n return {\n ok: false,\n message: err instanceof Error ? err.message : String(err),\n };\n }\n },\n openEditor: async (path: string) => {\n const editor = process.env[\"EDITOR\"] || process.env[\"VISUAL\"] || \"nano\";\n p.log.info(`Opening ${path} in ${editor}…`);\n try {\n // Inherit stdio so the user actually sees the editor.\n const result = spawnSync(editor, [path], { stdio: \"inherit\" });\n if (result.error) {\n return {\n ok: false,\n message: `Failed to launch ${editor}: ${result.error.message}`,\n };\n }\n if ((result.status ?? 0) !== 0) {\n return {\n ok: false,\n message: `${editor} exited with code ${result.status}`,\n };\n }\n return { ok: true, message: `Saved ${path}` };\n } catch (err) {\n return {\n ok: false,\n message: err instanceof Error ? err.message : String(err),\n };\n }\n },\n runIiiInstaller: async () => {\n const r = await runIiiInstaller();\n return {\n ok: r.ok,\n message: r.ok\n ? `Installed iii v${IIPINNED_VERSION} to ${r.binPath}`\n : \"iii installer failed (see warnings above)\",\n };\n },\n runStop: async () => {\n try {\n // runStop calls process.exit on its own — guard against that here\n // by short-circuiting when there's nothing to stop.\n const port = getRestPort();\n const portPids = findEnginePidsByPort(port);\n const pidfilePid = readEnginePidfile();\n if (portPids.length === 0 && pidfilePid === null) {\n clearEnginePidfile();\n clearEngineState();\n return { ok: true, message: \"Nothing to stop.\" };\n }\n const candidates = new Set<number>();\n if (pidfilePid) candidates.add(pidfilePid);\n for (const pid of portPids) candidates.add(pid);\n let allStopped = true;\n for (const pid of candidates) {\n const ok = await signalAndWait(pid, \"SIGTERM\", 3000);\n if (!ok) allStopped = false;\n }\n clearEnginePidfile();\n clearEngineState();\n return {\n ok: allStopped,\n message: allStopped ? \"Engine stopped.\" : \"Some engine pids survived.\",\n };\n } catch (err) {\n return {\n ok: false,\n message: err instanceof Error ? err.message : String(err),\n };\n }\n },\n runStart: async () => {\n try {\n const started = await startEngine();\n if (!started) return { ok: false, message: \"startEngine() returned false\" };\n const ready = await waitForEngine(15000);\n return {\n ok: ready,\n message: ready ? \"Engine ready\" : \"Engine did not become ready within 15s\",\n };\n } catch (err) {\n return {\n ok: false,\n message: err instanceof Error ? err.message : String(err),\n };\n }\n },\n clearEnginePidAndState: () => {\n clearEnginePidfile();\n clearEngineState();\n },\n };\n}\n\nasync function passiveServerChecks(): Promise<DoctorCheck[]> {\n const base = getBaseUrl();\n const checks: DoctorCheck[] = [];\n\n const serverUp = await isEngineRunning();\n checks.push({\n name: \"Server reachable\",\n ok: serverUp,\n hint: serverUp\n ? undefined\n : `Start with: npx @agentmemory/agentmemory (tried ${base})`,\n });\n if (!serverUp) return checks;\n\n const [health, flags, graph] = await Promise.all([\n apiFetch<any>(base, \"health\", 3000),\n apiFetch<any>(base, \"config/flags\", 3000),\n apiFetch<any>(base, \"graph/stats\", 3000),\n ]);\n\n const hasLlm = flags?.provider === \"llm\";\n const hasEmbed = flags?.embeddingProvider === \"embeddings\";\n const graphNodeCount = Number(\n graph?.totalNodes ?? graph?.nodes ?? graph?.nodeCount ?? 0,\n );\n const graphHas = graphNodeCount > 0;\n\n checks.push(\n {\n name: \"Health status\",\n ok: health?.status === \"healthy\",\n hint:\n health?.status === \"healthy\"\n ? undefined\n : `Status: ${health?.status || \"unknown\"}`,\n },\n {\n name: \"LLM provider\",\n ok: hasLlm,\n hint: hasLlm ? undefined : \"set ANTHROPIC_API_KEY (or GEMINI/OPENROUTER/MINIMAX) in ~/.agentmemory/.env\",\n },\n {\n name: \"Embedding provider\",\n ok: hasEmbed,\n hint: hasEmbed\n ? undefined\n : \"Running BM25-only. Set EMBEDDING_PROVIDER=local for on-device semantic search, or add OPENAI_API_KEY / VOYAGE_API_KEY / COHERE_API_KEY / OLLAMA_HOST\",\n },\n );\n\n for (const f of (flags?.flags || []) as {\n label: string;\n enabled: boolean;\n enableHow: string;\n }[]) {\n checks.push({\n name: f.label,\n ok: f.enabled,\n hint: f.enabled ? undefined : f.enableHow,\n });\n }\n\n const cc = checkClaudeCodeHooks();\n const ccCheck = (() => {\n switch (cc.state) {\n case \"loaded\":\n return {\n ok: true,\n hint: cc.manifestPath ? `manifest: ${cc.manifestPath}` : undefined,\n };\n case \"not-loaded\":\n return {\n ok: false,\n hint:\n \"Plugin enabled but hooks not loaded by Claude Code. Try: /plugin uninstall agentmemory@agentmemory && /plugin install agentmemory@agentmemory, then restart the session.\",\n };\n case \"no-debug-log\":\n return {\n ok: false,\n hint:\n 'Cannot verify — no Claude Code debug log found. Run once with `claude --debug -p \"x\"`, then re-run doctor.',\n };\n case \"no-cc-dir\":\n return undefined;\n }\n })();\n if (ccCheck) checks.push({ name: \"Claude Code plugin hooks registered\", ...ccCheck });\n\n checks.push({\n name: \"Knowledge graph populated\",\n ok: graphHas,\n hint: graphHas\n ? undefined\n : \"Graph is empty. Run a session with GRAPH_EXTRACTION_ENABLED=true.\",\n });\n\n return checks;\n}\n\ntype DoctorAction = \"fix\" | \"skip\" | \"more\" | \"quit\";\n\nasync function askFixAction(d: Diagnostic): Promise<DoctorAction> {\n const choice = await p.select<DoctorAction>({\n message: `[${d.id}] ${d.message}`,\n options: [\n { value: \"fix\", label: \"F Fix\", hint: d.fixPreview },\n { value: \"skip\", label: \"S Skip\" },\n { value: \"more\", label: \"? More info\" },\n { value: \"quit\", label: \"Q Quit doctor\" },\n ],\n initialValue: \"fix\",\n });\n if (p.isCancel(choice)) return \"quit\";\n return choice;\n}\n\nasync function applyFixWithReport(\n d: Diagnostic,\n ctx: DoctorContext,\n dryRun: boolean,\n): Promise<DiagnosticFixResult> {\n if (dryRun) {\n p.log.info(`[dry-run] would: ${d.fixPreview}`);\n return { ok: true, message: \"(dry-run)\" };\n }\n const result = await d.fix(ctx);\n if (result.ok) {\n p.log.success(result.message ?? `${d.id} fixed.`);\n } else {\n p.log.error(result.message ?? `${d.id} fix failed.`);\n }\n return result;\n}\n\nasync function runDoctor() {\n p.intro(\"agentmemory doctor\");\n const applyAll = args.includes(\"--all\");\n const dryRun = args.includes(\"--dry-run\");\n if (applyAll && dryRun) {\n p.log.error(\"Cannot combine --all and --dry-run.\");\n process.exit(2);\n }\n\n // Passive server checks (informational).\n const passive = await passiveServerChecks();\n const passivePassed = passive.filter((c) => c.ok).length;\n p.note(formatChecks(passive), `server: ${passivePassed}/${passive.length} passing`);\n\n // Doctor v2 interactive catalog.\n const ctx = buildDoctorContext();\n const effects = buildDoctorEffects();\n const diagnostics = buildDiagnostics(effects);\n\n if (dryRun) {\n const results: Array<{ diagnostic: Diagnostic; status: { ok: boolean; detail?: string } }> = [];\n for (const d of diagnostics) results.push({ diagnostic: d, status: await d.check(ctx) });\n const lines = dryRunPlan(ctx, results);\n p.note(lines.join(\"\\n\"), \"dry-run plan\");\n p.outro(\"Dry-run complete. Re-run without --dry-run to apply.\");\n return;\n }\n\n let failed = 0;\n let fixed = 0;\n let skipped = 0;\n let quit = false;\n\n for (const d of diagnostics) {\n if (quit) {\n skipped++;\n continue;\n }\n const status = await d.check(ctx);\n if (status.ok) {\n p.log.success(`${d.id} ✓${status.detail ? ` (${status.detail})` : \"\"}`);\n continue;\n }\n failed++;\n p.log.warn(`${d.id} ✗ ${status.detail ?? \"\"}`.trim());\n p.log.info(`why: ${d.fixPreview}`);\n\n if (d.manualOnly) {\n p.log.info(`(manual fix only — see \"${d.id}\" docs)`);\n }\n\n if (applyAll) {\n const r = await applyFixWithReport(d, ctx, false);\n if (r.ok) fixed++;\n // Re-check only this diagnostic.\n const after = await d.check(ctx);\n if (!after.ok) p.log.warn(`${d.id} still failing after fix.`);\n continue;\n }\n\n // Interactive prompt loop — allow [?] More info without leaving the check.\n while (true) {\n const action = await askFixAction(d);\n if (action === \"fix\") {\n const r = await applyFixWithReport(d, ctx, false);\n if (r.ok) {\n const after = await d.check(ctx);\n if (after.ok) {\n fixed++;\n } else {\n p.log.warn(`${d.id} still failing after fix: ${after.detail ?? \"\"}`);\n }\n }\n break;\n }\n if (action === \"skip\") {\n skipped++;\n break;\n }\n if (action === \"more\") {\n p.note(d.moreInfo, `[${d.id}] more info`);\n continue;\n }\n if (action === \"quit\") {\n quit = true;\n break;\n }\n }\n }\n\n const summary = `${diagnostics.length} checks · ${failed} failing · ${fixed} fixed · ${skipped} skipped`;\n if (quit) {\n p.outro(`Quit early. ${summary}`);\n process.exit(1);\n }\n if (failed === 0) {\n p.outro(\"All diagnostics passing. agentmemory is healthy.\");\n return;\n }\n if (failed - fixed === 0) {\n p.outro(`All fixes applied. ${summary}`);\n return;\n }\n p.outro(summary);\n process.exit(1);\n}\n\ntype DemoObservation = {\n toolName: string;\n toolInput: Record<string, string>;\n toolOutput: string;\n};\n\ntype DemoSession = {\n id: string;\n title: string;\n observations: DemoObservation[];\n};\n\ntype SearchResult = { query: string; hits: number; topTitle: string };\n\nfunction buildDemoSessions(): DemoSession[] {\n return [\n {\n id: generateId(\"demo\"),\n title: \"Session 1: JWT auth setup\",\n observations: [\n {\n toolName: \"Write\",\n toolInput: { file_path: \"src/middleware/auth.ts\" },\n toolOutput:\n \"Created JWT middleware using jose library. Tokens expire after 30 days. Chose jose over jsonwebtoken for Edge compatibility.\",\n },\n {\n toolName: \"Write\",\n toolInput: { file_path: \"test/auth.test.ts\" },\n toolOutput:\n \"Added token validation tests covering expired, malformed, and valid cases.\",\n },\n {\n toolName: \"Bash\",\n toolInput: { command: \"npm test\" },\n toolOutput: \"All 12 auth tests passing.\",\n },\n ],\n },\n {\n id: generateId(\"demo\"),\n title: \"Session 2: Database migration debugging\",\n observations: [\n {\n toolName: \"Read\",\n toolInput: { file_path: \"prisma/schema.prisma\" },\n toolOutput:\n \"Found N+1 query issue in user relations. Need to add include on posts query.\",\n },\n {\n toolName: \"Edit\",\n toolInput: { file_path: \"src/api/users.ts\" },\n toolOutput:\n \"Fixed N+1 by adding Prisma include. Query time dropped from 450ms to 28ms.\",\n },\n ],\n },\n {\n id: generateId(\"demo\"),\n title: \"Session 3: Rate limiting\",\n observations: [\n {\n toolName: \"Write\",\n toolInput: { file_path: \"src/middleware/ratelimit.ts\" },\n toolOutput:\n \"Added rate limiting middleware with 100 req/min default. Uses in-memory store for dev, Redis for prod.\",\n },\n ],\n },\n ];\n}\n\nasync function postJson<T = unknown>(\n url: string,\n body: unknown,\n timeoutMs = 5000,\n): Promise<T | null> {\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...bearerHeaders(url) },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(timeoutMs),\n });\n if (!res.ok) return null;\n return (await res.json().catch(() => null)) as T | null;\n } catch {\n return null;\n }\n}\n\nasync function postJsonStrict<T = unknown>(\n url: string,\n body: unknown,\n timeoutMs = 5000,\n): Promise<T | null> {\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...bearerHeaders(url) },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(timeoutMs),\n });\n if (!res.ok) {\n const errBody = await res.text().catch(() => \"\");\n const suffix = errBody ? ` — ${errBody.slice(0, 200)}` : \"\";\n throw new Error(`POST ${url} failed: ${res.status} ${res.statusText}${suffix}`);\n }\n return (await res.json().catch(() => null)) as T | null;\n}\n\nasync function seedDemoSession(\n base: string,\n project: string,\n session: DemoSession,\n): Promise<number> {\n await postJsonStrict(`${base}/agentmemory/session/start`, {\n sessionId: session.id,\n project,\n cwd: project,\n });\n\n let stored = 0;\n for (const obs of session.observations) {\n const url = `${base}/agentmemory/observe`;\n const payload = {\n hookType: \"post_tool_use\",\n sessionId: session.id,\n project,\n cwd: project,\n timestamp: new Date().toISOString(),\n data: {\n tool_name: obs.toolName,\n tool_input: obs.toolInput,\n tool_output: obs.toolOutput,\n },\n };\n\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...bearerHeaders(url) },\n body: JSON.stringify(payload),\n signal: AbortSignal.timeout(5000),\n });\n if (res.ok) {\n stored++;\n } else {\n const body = await res.text().catch(() => \"\");\n p.log.warn(\n `observe failed for ${obs.toolName}: ${res.status} ${res.statusText}${body ? ` — ${body.slice(0, 160)}` : \"\"}`,\n );\n }\n } catch (err) {\n p.log.warn(\n `observe request failed for ${obs.toolName}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n await postJsonStrict(`${base}/agentmemory/session/end`, { sessionId: session.id });\n return stored;\n}\n\nasync function runDemoSearch(base: string, query: string): Promise<SearchResult> {\n const data = await postJson<{ results?: Array<{ title?: string }> }>(\n `${base}/agentmemory/smart-search`,\n { query, limit: 5 },\n 10000,\n );\n const items = data?.results ?? [];\n return {\n query,\n hits: items.length,\n topTitle: items[0]?.title ?? \"(no results)\",\n };\n}\n\n// Prefer the packaged `.env.example` (next to `dist/cli.mjs`); fall back to\n// the repo root when running from a source checkout.\nfunction findEnvExample(): string | null {\n const candidates = [\n join(__dirname, \"..\", \".env.example\"),\n join(__dirname, \".env.example\"),\n join(process.cwd(), \".env.example\"),\n ];\n for (const c of candidates) {\n if (existsSync(c)) return c;\n }\n return null;\n}\n\nasync function runInit() {\n p.intro(\"agentmemory init\");\n const target = join(homedir(), \".agentmemory\", \".env\");\n const template = findEnvExample();\n if (!template) {\n p.log.error(\n \"Could not locate .env.example in the package. Re-install with: npm i -g @agentmemory/agentmemory\",\n );\n process.exit(1);\n }\n const dir = dirname(target);\n const { mkdir, copyFile } = await import(\"node:fs/promises\");\n const { constants: fsConstants } = await import(\"node:fs\");\n try {\n await mkdir(dir, { recursive: true });\n // COPYFILE_EXCL collapses the exists-check + copy into one syscall —\n // an existsSync(target) + copyFile() pair races with a parallel init\n // (or any other process touching ~/.agentmemory/.env between the two\n // calls) and would silently overwrite a config the operator just\n // wrote. EEXIST out of copyFile is the only \"already configured\"\n // signal we trust.\n await copyFile(template, target, fsConstants.COPYFILE_EXCL);\n } catch (err) {\n if ((err as NodeJS.ErrnoException)?.code === \"EEXIST\") {\n p.log.warn(`${target} already exists — leaving it untouched.`);\n p.log.info(\n `Compare against the latest template: diff ${target} ${template}`,\n );\n p.outro(\"Nothing changed.\");\n return;\n }\n p.log.error(\n `Failed to copy template: ${err instanceof Error ? err.message : String(err)}`,\n );\n process.exit(1);\n }\n p.log.success(`Wrote ${target}`);\n p.note(\n [\n \"All keys are commented out by default. Uncomment the ones you want.\",\n \"\",\n \"Common next steps:\",\n \" 1. Pick an LLM provider key (ANTHROPIC_API_KEY / OPENAI_API_KEY / GEMINI_API_KEY / etc.)\",\n \" 2. Run `npx @agentmemory/agentmemory doctor` to verify the daemon sees them\",\n \" 3. Run `npx @agentmemory/agentmemory` to start the worker\",\n ].join(\"\\n\"),\n \"Next steps\",\n );\n p.outro(`Edit ${target} and you're set.`);\n}\n\nasync function startServerForDemo(): Promise<() => Promise<void>> {\n await assertRuntimePortOwnership();\n if (await isAgentmemoryReady()) {\n return async () => {};\n }\n\n const startedEngine = !(await isEngineRunning());\n if (startedEngine) {\n const ok = await startEngine();\n if (!ok) {\n p.log.error(\"Could not start iii-engine for the demo.\");\n p.note(installInstructions().join(\"\\n\"), \"Setup required\");\n process.exit(1);\n }\n if (!(await waitForEngine(15000))) {\n printCapturedStartupStderr();\n printDockerStartupLogs();\n p.log.error(\"iii-engine did not become ready within 15s.\");\n process.exit(1);\n }\n }\n\n await startWorkerForEngineState();\n if (!(await waitForAgentmemoryReady(15000))) {\n p.log.error(\"agentmemory worker did not become ready within 15s.\");\n process.exit(1);\n }\n\n return async () => {\n if (!startedEngine) return;\n const port = getRestPort();\n const state = readEngineState();\n if (state?.kind === \"docker\") {\n await stopDockerEngine(state, port).catch(() => {});\n return;\n }\n const pids = new Set<number>(findEnginePidsByPort(port));\n const pidfilePid = readEnginePidfile();\n if (pidfilePid) pids.add(pidfilePid);\n for (const pid of pids) {\n await signalAndWait(pid, \"SIGTERM\", 3000).catch(() => {});\n }\n clearEnginePidfile();\n clearEngineState();\n clearWorkerPidfile();\n };\n}\n\nasync function runDemo() {\n const port = getRestPort();\n const base = `http://localhost:${port}`;\n p.intro(\"agentmemory demo\");\n\n const serve = args.includes(\"--serve\");\n let teardown: () => Promise<void> = async () => {};\n\n if (serve) {\n teardown = await startServerForDemo();\n } else if (!(await isAgentmemoryReady())) {\n p.log.error(\n `agentmemory worker not reachable on port ${port} (livez probe failed). Something may be on the port but it isn't serving /agentmemory/*.`,\n );\n p.log.info(\"Start it with: npx @agentmemory/agentmemory\");\n p.log.info(\"Or run a one-command demo with: npx @agentmemory/agentmemory demo --serve\");\n process.exit(1);\n }\n\n try {\n await runDemoBody(base);\n } finally {\n await teardown();\n }\n\n if (serve) {\n process.exit(0);\n }\n}\n\nasync function runDemoBody(base: string) {\n const demoProject = \"/tmp/agentmemory-demo\";\n const sessions = buildDemoSessions();\n\n const sSeed = p.spinner();\n sSeed.start(\"Seeding 3 demo sessions with realistic observations...\");\n\n let totalObs = 0;\n for (const session of sessions) {\n totalObs += await seedDemoSession(base, demoProject, session);\n }\n\n sSeed.stop(`Seeded ${totalObs} observations across ${sessions.length} sessions`);\n\n const queries = [\n \"jwt auth middleware\",\n \"database performance optimization\",\n \"rate limiting\",\n ];\n\n const sQuery = p.spinner();\n sQuery.start(`Running ${queries.length} smart-search queries...`);\n\n const results: SearchResult[] = [];\n for (const query of queries) {\n results.push(await runDemoSearch(base, query));\n }\n\n sQuery.stop(\"Search complete\");\n\n // Only claim the semantic-recall win when the search actually hit.\n // Without an embedding key this query returns 0 hits, and asserting\n // success over a visibly failed search reads as a lie.\n const semanticHits =\n results.find((r) => r.query === \"database performance optimization\")\n ?.hits ?? 0;\n const lines = [\n `Project: ${demoProject}`,\n `Sessions: ${sessions.length} seeded (${totalObs} observations)`,\n \"\",\n c.label(\"Search results:\"),\n ...results.flatMap((r) => [\n ` ${c.label(`\"${r.query}\"`)}`,\n ` ${c.dim(\"→\")} ${c.ok(`${r.hits} hit(s)`)}, top: ${r.topTitle.slice(0, 60)}`,\n ]),\n \"\",\n ...(semanticHits > 0\n ? [\n c.accent(`Notice: searching \"database performance optimization\"`),\n c.accent(`found the N+1 query fix — keyword matching can't do that.`),\n ]\n : [\n c.dim(`Note: \"database performance optimization\" found nothing —`),\n c.dim(`set EMBEDDING_PROVIDER=local for on-device semantic recall,`),\n c.dim(`or add an embedding API key in ~/.agentmemory/.env.`),\n ]),\n \"\",\n `Viewer: ${c.url(getViewerUrl())}`,\n `Clean up with: ${c.dim(`curl -X DELETE \"${base}/agentmemory/sessions?project=${demoProject}\"`)}`,\n ];\n\n p.note(lines.join(\"\\n\"), \"demo complete\");\n p.log.success(\"agentmemory is working. Point your agent at it and get back to coding.\");\n}\n\nfunction runCommand(\n command: string,\n commandArgs: string[],\n options: { cwd?: string; label: string; optional?: boolean } = { label: \"command\" },\n): boolean {\n const spinner = p.spinner();\n spinner.start(options.label);\n const result = spawnSync(command, commandArgs, {\n cwd: options.cwd || process.cwd(),\n stdio: \"pipe\",\n encoding: \"utf-8\",\n });\n\n if (result.status === 0) {\n spinner.stop(`${options.label} ${pc.green(\"✓\")}`);\n return true;\n }\n\n const stderr = (result.stderr || \"\").toString().trim();\n const stdout = (result.stdout || \"\").toString().trim();\n const msg = stderr || stdout || \"unknown error\";\n\n if (options.optional) {\n spinner.stop(`${options.label} (skipped)`);\n p.log.warn(msg.slice(0, 300));\n return false;\n }\n\n spinner.stop(`${options.label} ${pc.red(\"✗\")}`);\n p.log.error(msg.slice(0, 300));\n return false;\n}\n\nasync function runUpgrade() {\n p.intro(\"agentmemory upgrade\");\n\n const cwd = process.cwd();\n const hasPackageJson = existsSync(join(cwd, \"package.json\"));\n const hasPnpmLock = existsSync(join(cwd, \"pnpm-lock.yaml\"));\n\n const pnpmBin = whichBinary(\"pnpm\");\n const npmBin = whichBinary(\"npm\");\n const dockerBin = whichBinary(\"docker\");\n\n p.log.info(`Working directory: ${cwd}`);\n const requireSuccess = (ok: boolean, label: string): void => {\n if (!ok) {\n p.log.error(`Upgrade aborted: ${label} failed.`);\n process.exit(1);\n }\n };\n\n if (hasPackageJson) {\n const usePnpm = !!pnpmBin && hasPnpmLock;\n if (usePnpm && pnpmBin) {\n const installOk = runCommand(pnpmBin, [\"install\"], {\n label: \"Refreshing dependencies (pnpm install)\",\n });\n requireSuccess(installOk, \"pnpm install\");\n runCommand(\n pnpmBin,\n [\n \"up\",\n `iii-sdk@${IIPINNED_DEFAULT_VERSION}`,\n `@iii-dev/helpers@${IIPINNED_DEFAULT_VERSION}`,\n ],\n {\n label: `Pinning iii-sdk and @iii-dev/helpers at ${IIPINNED_DEFAULT_VERSION}`,\n optional: true,\n },\n );\n } else if (npmBin) {\n const installOk = runCommand(npmBin, [\"install\"], {\n label: \"Refreshing dependencies (npm install)\",\n });\n requireSuccess(installOk, \"npm install\");\n runCommand(\n npmBin,\n [\n \"install\",\n `iii-sdk@${IIPINNED_DEFAULT_VERSION}`,\n `@iii-dev/helpers@${IIPINNED_DEFAULT_VERSION}`,\n ],\n {\n label: `Pinning iii-sdk and @iii-dev/helpers at ${IIPINNED_DEFAULT_VERSION}`,\n optional: true,\n },\n );\n } else {\n p.log.warn(\"No package manager found (pnpm/npm). Skipping JS dependency upgrade.\");\n }\n } else {\n p.log.warn(\"No package.json in current directory. Skipping JS dependency upgrade.\");\n }\n\n const upgradeEngine = await p.confirm({\n message: \"Re-run the iii-engine install script (curl | sh)?\",\n initialValue: true,\n });\n if (p.isCancel(upgradeEngine)) {\n p.cancel(\"Cancelled.\");\n return process.exit(0);\n }\n if (upgradeEngine === true) {\n await runIiiInstaller();\n } else {\n p.log.info(\"Skipped iii-engine installer.\");\n }\n\n if (dockerBin) {\n runCommand(dockerBin, [\"pull\", `iiidev/iii:${IIPINNED_VERSION}`], {\n label: `Pulling iii Docker image v${IIPINNED_VERSION} (pinned)`,\n optional: true,\n });\n } else {\n p.log.info(\"Docker not found. Skipping Docker image refresh.\");\n }\n\n p.note(\n [\n \"Upgrade flow completed.\",\n \"\",\n \"Recommended next steps:\",\n \" 1) agentmemory status\",\n \" 2) npm/pnpm test\",\n \" 3) restart agentmemory process\",\n ].join(\"\\n\"),\n \"agentmemory upgrade\",\n );\n}\n\nfunction pidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n if (!IS_WINDOWS) {\n try {\n const stat = execFileSync(\"ps\", [\"-p\", String(pid), \"-o\", \"stat=\"], {\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n if (stat.trim() && !processStatIsRunning(stat)) return false;\n } catch {}\n }\n return true;\n } catch (err) {\n return (err as NodeJS.ErrnoException)?.code === \"EPERM\";\n }\n}\n\nasync function signalAndWait(\n pid: number,\n initialSignal: NodeJS.Signals,\n timeoutMs: number,\n): Promise<boolean> {\n try {\n process.kill(pid, initialSignal);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException)?.code;\n if (code === \"ESRCH\") return true;\n if (code === \"EPERM\") {\n p.log.warn(`No permission to signal pid ${pid}. Try: kill ${pid}`);\n return false;\n }\n vlog(`${initialSignal} ${pid}: ${err instanceof Error ? err.message : String(err)}`);\n return false;\n }\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n if (!pidAlive(pid)) return true;\n await new Promise((r) => setTimeout(r, 200));\n }\n if (!pidAlive(pid)) return true;\n try {\n process.kill(pid, \"SIGKILL\");\n } catch (err) {\n if ((err as NodeJS.ErrnoException)?.code === \"ESRCH\") return true;\n vlog(`SIGKILL ${pid}: ${err instanceof Error ? err.message : String(err)}`);\n return false;\n }\n await new Promise((r) => setTimeout(r, 200));\n return !pidAlive(pid);\n}\n\n// Shared worker-reap: SIGTERM with a grace window sized for the worker's\n// shutdown flush (index snapshots land via the engine, so the worker must\n// die before the engine does, with time to commit).\nasync function waitForEngineFlush(): Promise<void> {\n let stateBackend: \"file\" | \"redis\" = \"file\";\n try {\n stateBackend = getStateBackend();\n } catch {}\n const runtimePath = runtimeConfigPath(dataDirResolution.dataDir);\n const configTexts: string[] = [];\n for (const path of engineStateConfigPaths(join(homedir(), \".agentmemory\"), runtimePath)) {\n try {\n configTexts.push(readFileSync(path, \"utf-8\"));\n } catch {}\n }\n const waitMs = engineFlushWaitMs(stateBackend, configTexts);\n if (waitMs <= 0) return;\n const s = p.spinner();\n s.start(`Waiting ${(waitMs / 1000).toFixed(1)}s for iii-engine to write state to disk...`);\n await new Promise((r) => setTimeout(r, waitMs));\n s.stop(\"iii-engine state flush window passed\");\n}\n\nasync function stopWorkerPid(pid: number, graceMs: number): Promise<boolean> {\n const s = p.spinner();\n s.start(`Stopping agentmemory worker (pid ${pid})... [flushing state]`);\n const ok = await signalAndWait(pid, \"SIGTERM\", graceMs);\n s.stop(ok ? `Stopped worker pid ${pid}` : `Failed to stop worker pid ${pid}`);\n return ok;\n}\n\ntype NativeRemovalStopResult =\n | { ok: true; stoppedEnginePids: number }\n | { ok: false; reason: string };\n\nasync function stopNativeEngineForRemoval(): Promise<NativeRemovalStopResult> {\n const port = getRestPort();\n const workerPid = readWorkerPidfile();\n const enginePids = new Set<number>(findEnginePidsByPort(port));\n const pidfilePid = readEnginePidfile();\n if (pidfilePid) enginePids.add(pidfilePid);\n if (workerPid) enginePids.delete(workerPid);\n\n const foreign = [...enginePids]\n .map((pid) => ({ pid, comm: pidCommand(pid) }))\n .filter(({ comm }) => isForeignPortHolder(comm));\n if (foreign.length > 0) {\n return {\n ok: false,\n reason: `refusing to signal non-iii process(es): ${foreign.map(({ pid, comm }) => `${pid} (${comm})`).join(\", \")}`,\n };\n }\n\n if (workerPid) {\n if (!(await stopWorkerPid(workerPid, 5000))) {\n return {\n ok: false,\n reason: `worker pid ${workerPid} could not be stopped; no engine or files were removed`,\n };\n }\n clearWorkerPidfile();\n }\n\n for (const pid of enginePids) {\n const s = p.spinner();\n s.start(`Stopping iii-engine (pid ${pid})...`);\n const ok = await signalAndWait(pid, \"SIGTERM\", 3000);\n s.stop(ok ? `Stopped pid ${pid}` : `Failed to stop pid ${pid}`);\n if (!ok) {\n return {\n ok: false,\n reason: `engine pid ${pid} survived shutdown; lifecycle state and files were preserved`,\n };\n }\n }\n\n clearEnginePidfile();\n clearEngineState();\n clearWorkerPidfile();\n return { ok: true, stoppedEnginePids: enginePids.size };\n}\n\nfunction pidCommand(pid: number): string {\n if (IS_WINDOWS) return \"\";\n try {\n return execFileSync(\"ps\", [\"-p\", String(pid), \"-o\", \"comm=\"], {\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim();\n } catch {\n return \"\";\n }\n}\n\n// Positive identity beats a denylist: the engine is always the `iii`\n// binary (spawned from PATH or ~/.agentmemory/bin), so anything else\n// holding the port — Docker's proxy, an ssh forward, a stray dev\n// server — must not be adopted or signaled. A denylist of known VM\n// stacks failed open for every name it didn't know.\nfunction isForeignPortHolder(comm: string): boolean {\n if (!comm) return false;\n const base = comm.split(\"/\").pop() || comm;\n return base !== \"iii\" && !base.startsWith(\"iii-\");\n}\n\nfunction findEnginePidsByPort(port: number): number[] {\n if (IS_WINDOWS) return [];\n const lsof = whichBinary(\"lsof\");\n if (!lsof) return [];\n // -sTCP:LISTEN restricts to listening server sockets only. Without\n // this, lsof also returns client-side PIDs (any process with an\n // active TCP connection to :port), which includes the agentmemory\n // CLI itself thanks to the keep-alive fetch in isEngineRunning().\n // signalAndWait would then SIGKILL its own parent — exit code 137.\n const selfPid = process.pid;\n try {\n const out = execFileSync(lsof, [\"-i\", `:${port}`, \"-sTCP:LISTEN\", \"-t\"], {\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n return out\n .split(/\\s+/)\n .map((s) => parseInt(s, 10))\n .filter((n) => Number.isFinite(n) && n > 0 && n !== selfPid);\n } catch (err) {\n vlog(`lsof :${port}: ${err instanceof Error ? err.message : String(err)}`);\n return [];\n }\n}\n\nasync function stopDockerEngine(\n state: DockerEngineState,\n port: number,\n suppressOutro = false,\n): Promise<void> {\n const dockerBin = whichBinary(\"docker\");\n if (!dockerBin) {\n p.log.error(\n \"Engine was started via Docker, but `docker` is no longer on PATH. Lifecycle state was preserved.\",\n );\n process.exit(1);\n }\n\n const inspection = inspectOwnedDockerEngine(state);\n if (inspection.status === \"unavailable\") {\n p.log.error(\n `The saved Docker engine cannot be verified: ${inspection.reason}. Refusing to stop or clear ownership state.`,\n );\n process.exit(1);\n }\n const resolvedState = persistDockerInspection(state, inspection);\n\n const workerPid = readWorkerPidfile();\n if (workerPid && !(await stopWorkerPid(workerPid, 5000))) {\n p.log.error(\"The agentmemory worker could not be stopped; Docker ownership state was preserved.\");\n process.exit(1);\n }\n clearWorkerPidfile();\n\n if (inspection.status === \"running\" || inspection.status === \"stopped\") {\n if (\n inspection.status === \"running\" &&\n !runCommand(\n dockerBin,\n [\"stop\", \"--time\", \"10\", inspection.containerId],\n { label: `Stopping preserved Docker container ${inspection.containerId}` },\n )\n ) {\n p.log.error(\"The Docker container could not be stopped; ownership state was preserved.\");\n process.exit(1);\n }\n clearEnginePidfile();\n writeEngineState(resolvedState);\n if (!suppressOutro) {\n p.outro(\n \"Stopped. The validated Docker container and data mount were preserved for a lossless restart.\",\n );\n }\n return;\n }\n\n const projectName = inspection.projectName ?? resolvedState.projectName;\n if (!projectName) {\n p.log.error(\"No verified Docker Compose project name is available. Refusing an unscoped stop.\");\n process.exit(1);\n }\n const effectiveComposeFile = existsSync(inspection.composeFile)\n ? inspection.composeFile\n : discoverComposeFile();\n if (!effectiveComposeFile) {\n p.log.error(\"No agentmemory compose file is available. Docker ownership state was preserved.\");\n process.exit(1);\n }\n const composeText = readFileSync(effectiveComposeFile, \"utf-8\");\n const ownServices = [\"iii-engine\", \"iii-init\"].filter((service) =>\n new RegExp(`^\\\\s+${service}:`, \"m\").test(composeText),\n );\n if (ownServices.length === 0) {\n p.log.error(`${effectiveComposeFile} does not define iii-engine or iii-init. Refusing an unscoped stop.`);\n process.exit(1);\n }\n\n const composeCommand = [\n \"docker\",\n ...dockerComposeArgs(effectiveComposeFile, projectName, []),\n ].join(\" \");\n\n const ok = runCommand(\n dockerBin,\n dockerComposeArgs(effectiveComposeFile, projectName, [\n \"rm\",\n \"-s\",\n \"-f\",\n ...ownServices,\n ]),\n {\n label: `${composeCommand} rm -s -f ${ownServices.join(\" \")}`,\n },\n );\n // Clear each piece of state only after its shutdown succeeded, so a\n // failed stop stays retryable.\n if (ok) {\n clearEnginePidfile();\n clearEngineState();\n } else {\n p.log.error(\n `docker compose rm failed. The engine may still be running on :${port}. Inspect with:\\n ${composeCommand} ps`,\n );\n process.exit(1);\n }\n if (!suppressOutro) {\n p.outro(\"Stopped. Memories persisted to disk; restart anytime with: npx @agentmemory/agentmemory\");\n }\n}\n\nasync function runStop(): Promise<void> {\n await assertRuntimePortOwnership();\n p.intro(\"agentmemory stop\");\n const port = getRestPort();\n const state = readEngineState();\n const running = await isEngineRunning();\n const force = args.includes(\"--force\");\n\n if (state?.kind === \"docker\") {\n if (!running) {\n p.log.info(`No engine responding on port ${port}.`);\n }\n await stopDockerEngine(state, port);\n return;\n }\n\n const portPids = findEnginePidsByPort(port);\n const pidfilePid = readEnginePidfile();\n // read the worker pid up front so the engine-down branch\n // can still reap an orphaned worker process (the common failure mode\n // where a wrapper script kept the worker alive across engine restarts).\n const workerPid = readWorkerPidfile();\n\n if (!running) {\n if (portPids.length === 0 && pidfilePid === null && workerPid === null) {\n clearEnginePidfile();\n clearEngineState();\n clearWorkerPidfile();\n p.outro(\"Nothing to stop.\");\n return;\n }\n if (workerPid !== null && portPids.length === 0 && pidfilePid === null) {\n // Engine already gone but worker is lingering — reap it directly\n // instead of preserving for manual cleanup.\n const s = p.spinner();\n s.start(`Stopping orphaned agentmemory worker (pid ${workerPid})...`);\n const ok = await signalAndWait(workerPid, \"SIGTERM\", SHUTDOWN_HARD_EXIT_MS + 1000);\n s.stop(ok ? `Stopped worker pid ${workerPid}` : `Failed to stop worker pid ${workerPid}`);\n clearEnginePidfile();\n clearEngineState();\n clearWorkerPidfile();\n if (!ok) {\n p.log.error(`Worker pid ${workerPid} survived SIGKILL. Investigate with \\`ps\\`.`);\n process.exit(1);\n }\n p.outro(\"Stopped orphaned worker. Memories persisted to disk.\");\n return;\n }\n const survivors = new Set<number>(portPids);\n if (pidfilePid) survivors.add(pidfilePid);\n if (workerPid) survivors.add(workerPid);\n p.log.warn(\n `Engine not responding on :${port}, but ${survivors.size} process(es) still hold the port or pidfile: ${[...survivors].join(\", \")}`,\n );\n p.log.info(\n `Preserving ~/.agentmemory/iii.pid + worker.pid. Investigate before manual cleanup:\\n ps -p ${[...survivors].join(\",\")} -o pid,ppid,comm,etime\\n ${IS_WINDOWS ? \"netstat -ano | findstr :\" + port : \"lsof -i :\" + port}`,\n );\n process.exit(1);\n }\n\n if (!state) {\n const compose = discoverComposeFile();\n if (compose && pidfilePid === null) {\n if (force) {\n p.log.warn(\n `--force: bypassing Docker-heuristic guard. Falling back to native pidfile + lsof on :${port}.`,\n );\n } else {\n p.log.error(\n `Engine is running on :${port} but no pidfile or state file is present. It may have been started via Docker compose by a different shell. Refusing to signal host PIDs.\\n\\nStop it with:\\n docker compose -f ${compose} down\\n\\nOr re-run with --force to signal whatever lsof finds on :${port}, or AGENTMEMORY_USE_DOCKER=1 to record state next time.`,\n );\n process.exit(1);\n }\n }\n }\n\n const candidates = new Set<number>();\n if (pidfilePid) candidates.add(pidfilePid);\n for (const pid of portPids) candidates.add(pid);\n\n // stop must also reap the agentmemory worker process\n // (`node dist/index.mjs`). If only the engine is killed, the worker can\n // survive (detached spawn / signal not propagated) and reconnect to the\n // next engine as a duplicate registration. workerPid was read above so\n // the engine-down branch could also reap orphans.\n const workerCandidates = new Set<number>();\n if (workerPid) workerCandidates.add(workerPid);\n\n if (candidates.size === 0 && workerCandidates.size === 0) {\n p.log.error(\n `Could not locate engine process. Try:\\n ${IS_WINDOWS ? \"netstat -ano | findstr :\" + port : \"lsof -i :\" + port + \" -t | xargs kill -9\"}`,\n );\n process.exit(1);\n }\n\n let allStopped = true;\n // stop worker first, then engine. The worker's shutdown\n // handler calls indexPersistence.save() -> kv.set() -> iii state::set\n // to flush BM25/vector snapshots + audit rows. Killing iii first\n // leaves those writes with no engine to land on, and the index +\n // observations end up as in-memory state the iii process never\n // persists. Worker SIGTERM grace bumped 3s -> 5s to give a large\n // index a real chance to commit before the engine goes away.\n for (const pid of workerCandidates) {\n if (!(await stopWorkerPid(pid, SHUTDOWN_HARD_EXIT_MS + 1000))) allStopped = false;\n }\n if (workerCandidates.size > 0 && [...candidates].some((pid) => !workerCandidates.has(pid))) {\n await waitForEngineFlush();\n }\n const skippedForeign: Array<{ pid: number; comm: string }> = [];\n for (const pid of candidates) {\n if (workerCandidates.has(pid)) continue;\n // Last-line guard against a stale/poisoned pidfile or a Docker\n // port-forward holding :port — signaling com.docker.backend kills\n // Docker Desktop's whole backend.\n const comm = pidCommand(pid);\n if (!force && isForeignPortHolder(comm)) {\n skippedForeign.push({ pid, comm });\n continue;\n }\n const s = p.spinner();\n s.start(`Stopping iii-engine (pid ${pid})...`);\n const ok = await signalAndWait(pid, \"SIGTERM\", 3000);\n s.stop(ok ? `Stopped pid ${pid}` : `Failed to stop pid ${pid}`);\n if (!ok) allStopped = false;\n }\n\n clearEnginePidfile();\n clearEngineState();\n clearWorkerPidfile();\n if (skippedForeign.length > 0) {\n const list = skippedForeign\n .map((sf) => ` pid ${sf.pid} ${sf.comm}`)\n .join(\"\\n\");\n p.log.error(\n `Refused to signal process(es) holding :${port} that are not the iii engine:\\n${list}\\n\\nIf the engine runs in Docker, stop it there:\\n docker compose ps && docker compose rm -s -f <service>\\n\\nOr re-run with --force to signal them anyway.`,\n );\n process.exit(1);\n }\n if (!allStopped) {\n p.log.error(\"One or more processes survived SIGKILL. Investigate with `ps`.\");\n process.exit(1);\n }\n p.outro(\"Stopped. Memories persisted to disk; restart anytime with: npx @agentmemory/agentmemory\");\n}\n\nasync function runMcp(): Promise<void> {\n await import(\"./mcp/standalone.js\");\n}\n\nasync function runConnectCmd(): Promise<void> {\n const { runConnect } = await import(\"./cli/connect/index.js\");\n await runConnect(args.slice(1));\n}\n\nasync function runImportJsonl(): Promise<void> {\n // Long-form flags that take a value. Their value tokens must be\n // consumed alongside the flag so they don't leak into positional\n // args (e.g. `--port 3112 import-jsonl` would otherwise turn\n // 3112 into pathArg).\n const VALUE_FLAGS = new Set([\"--port\", \"--tools\", \"--data-dir\"]);\n let maxFiles: number | undefined;\n const tail = args.slice(1);\n const positional: string[] = [];\n for (let i = 0; i < tail.length; i++) {\n const a = tail[i]!;\n if (a === \"--max-files\") {\n const raw = tail[i + 1];\n const parsed = raw !== undefined ? parseInt(raw, 10) : NaN;\n if (Number.isInteger(parsed) && parsed > 0) {\n maxFiles = parsed;\n } else if (raw !== undefined) {\n p.log.warn(`Ignoring --max-files ${raw}: expected a positive integer.`);\n }\n i++;\n continue;\n }\n if (a.startsWith(\"--max-files=\")) {\n const raw = a.slice(\"--max-files=\".length);\n const parsed = parseInt(raw, 10);\n if (Number.isInteger(parsed) && parsed > 0) {\n maxFiles = parsed;\n } else {\n p.log.warn(`Ignoring --max-files=${raw}: expected a positive integer.`);\n }\n continue;\n }\n if (VALUE_FLAGS.has(a)) {\n i++;\n continue;\n }\n if (a.startsWith(\"-\")) continue;\n positional.push(a);\n }\n const pathArg = positional[0];\n\n const port = getRestPort();\n const base = `http://localhost:${port}`;\n\n let probeOk = false;\n let probeDetail = \"\";\n try {\n const probe = await fetch(`${base}/agentmemory/livez`, {\n signal: AbortSignal.timeout(2000),\n });\n probeOk = probe.ok;\n if (!probeOk) {\n const probeBody = await probe.text().catch(() => \"\");\n probeDetail = `reachable but unhealthy (HTTP ${probe.status}${probeBody ? `: ${probeBody.slice(0, 200)}` : \"\"})`;\n }\n } catch (err) {\n probeOk = false;\n const msg = err instanceof Error ? err.message : String(err);\n probeDetail = `unreachable (${msg})`;\n }\n if (!probeOk) {\n p.log.error(\n `agentmemory livez probe failed on port ${port}: ${probeDetail}. Start it with \\`npx @agentmemory/agentmemory\\` in another terminal, then re-run this command.`,\n );\n process.exit(1);\n }\n\n const body: Record<string, unknown> = {};\n if (pathArg) body[\"path\"] = resolve(pathArg.startsWith(\"~\") ? join(homedir(), pathArg.slice(1)) : pathArg);\n if (maxFiles !== undefined) body[\"maxFiles\"] = maxFiles;\n\n const headers: Record<string, string> = { \"content-type\": \"application/json\", ...bearerHeaders(base) };\n\n p.log.info(`Importing JSONL from ${pathArg || \"~/.claude/projects\"}…`);\n const spinner = p.spinner();\n spinner.start(\"scanning files\");\n\n try {\n const res = await fetch(`${base}/agentmemory/replay/import-jsonl`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(120_000),\n });\n const text = await res.text();\n let json: {\n success?: boolean;\n error?: string;\n imported?: number;\n sessionIds?: string[];\n observations?: number;\n discovered?: number;\n truncated?: boolean;\n traversalCapped?: boolean;\n maxFiles?: number;\n maxFilesUpperBound?: number;\n } = {};\n if (text.length > 0) {\n try {\n json = JSON.parse(text);\n } catch {\n spinner.stop(\"failed\");\n p.log.error(\n `server returned non-JSON response (HTTP ${res.status}): ${text.slice(0, 200)}`,\n );\n process.exit(1);\n }\n }\n if (!res.ok || json.success !== true) {\n spinner.stop(\"failed\");\n const detail =\n json.error ||\n (text.length === 0\n ? \"empty response body\"\n : json.success === undefined\n ? `HTTP ${res.status} (response missing success field)`\n : `HTTP ${res.status}`);\n if (res.status === 401) {\n p.log.error(\n `${detail}. Set AGENTMEMORY_SECRET to match the server's secret and re-run.`,\n );\n } else if (res.status === 404) {\n p.log.error(\n `${detail}. The running agentmemory server does not expose /agentmemory/replay/import-jsonl — upgrade to v0.8.13 or later.`,\n );\n } else {\n p.log.error(detail);\n }\n process.exit(1);\n }\n spinner.stop(\n `imported ${json.imported ?? 0} file(s), ${json.observations ?? 0} observation(s) across ${json.sessionIds?.length || 0} session(s)`,\n );\n if (json.truncated) {\n const cap = json.maxFiles ?? 200;\n const upper = json.maxFilesUpperBound ?? 1000;\n const discovered = json.discovered ?? 0;\n const skipped = discovered - (json.imported ?? 0);\n const discoveredLabel = json.traversalCapped\n ? `${discovered}+ (traversal halted at safety cap)`\n : String(discovered);\n const baseMsg = `Hit the ${cap}-file scan cap; ${skipped} of ${discoveredLabel} discovered file(s) were skipped.`;\n // If we already saw more than the server's hard cap (or the\n // walker stopped early), bumping --max-files won't help on its\n // own — recommend batching by subdirectory.\n if (discovered > upper || json.traversalCapped) {\n p.log.warn(\n `${baseMsg} Tree exceeds the server's --max-files limit of ${upper}; ` +\n `batch by subdirectory (run import-jsonl once per project under ~/.claude/projects).`,\n );\n } else {\n const suggested = Math.min(\n Math.max((discovered || cap) + 100, cap * 2),\n upper,\n );\n p.log.warn(\n `${baseMsg} Re-run with --max-files=${suggested} (max ${upper}) or batch by subdirectory.`,\n );\n }\n }\n if (json.sessionIds && json.sessionIds.length > 0) {\n p.log.info(`View at ${getViewerUrl()} → Replay tab`);\n }\n } catch (err) {\n spinner.stop(\"failed\");\n if (err instanceof Error && err.name === \"TimeoutError\") {\n p.log.error(\"import timed out after 2 minutes\");\n } else {\n p.log.error(err instanceof Error ? err.message : String(err));\n }\n process.exit(1);\n }\n}\n\n// ---------------------------------------------------------------------------\n// `agentmemory remove` — clean uninstall.\n//\n// Planning logic lives in src/cli/remove-plan.ts so it's testable without\n// touching $HOME. This function loads the manifest, builds the plan,\n// double-confirms, then executes step by step.\n\nfunction loadConnectManifest(home: string): ConnectManifest | null {\n const path = join(home, \".agentmemory\", \"backups\", \"connect-manifest.json\");\n try {\n const raw = readFileSync(path, \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<ConnectManifest>;\n if (Array.isArray(parsed?.installed)) {\n return { installed: parsed.installed };\n }\n return null;\n } catch {\n return null;\n }\n}\n\nfunction probeLocalBinIiiVersion(home: string): string | null {\n const path = legacyLocalBinIii(home);\n if (!existsSync(path)) return null;\n return iiiBinVersion(path);\n}\n\nfunction safeDelete(path: string): { ok: boolean; message: string } {\n try {\n if (!existsSync(path)) return { ok: true, message: `not present (${path})` };\n const st = statSync(path);\n if (st.isDirectory()) {\n rmSync(path, { recursive: true, force: true });\n } else {\n unlinkSync(path);\n }\n return { ok: true, message: `deleted ${path}` };\n } catch (err) {\n return {\n ok: false,\n message: `failed ${path}: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n}\n\nasync function runRemove(): Promise<void> {\n if (selectedInstance !== 0) {\n p.intro(\"agentmemory remove\");\n p.log.error(\n `remove is a global uninstall and cannot target instance ${selectedInstance}. Stop that daemon with \\`agentmemory stop --instance ${selectedInstance}\\`, then run \\`agentmemory remove\\` without --instance when you intend to uninstall shared assets.`,\n );\n process.exit(1);\n }\n await assertRuntimePortOwnership();\n p.intro(\"agentmemory remove\");\n const force = args.includes(\"--force\");\n const keepData = args.includes(\"--keep-data\");\n const ownedState = readEngineState();\n if (ownedState?.kind === \"docker\") {\n const inspection = inspectOwnedDockerEngine(ownedState);\n if (inspection.status === \"running\" || inspection.status === \"stopped\") {\n persistDockerInspection(ownedState, inspection);\n if (!keepData) {\n p.log.error(\n `Docker-backed removal requires --keep-data so the validated ${inspection.dataMountType} data mount (${inspection.dataMountSource}) and its recovery metadata remain usable. Re-run \\`agentmemory remove --keep-data\\`; destructive Docker data deletion is intentionally not automated.`,\n );\n process.exit(1);\n }\n } else {\n const detail = inspection.status === \"unavailable\"\n ? inspection.reason\n : \"the owned container is missing\";\n p.log.error(\n `remove cannot safely reconcile the saved Docker ownership (${detail}). Lifecycle state was preserved for manual recovery.`,\n );\n process.exit(1);\n }\n }\n\n const home = homedir();\n const connectManifest = loadConnectManifest(home);\n const localBinIiiVersion = probeLocalBinIiiVersion(home);\n\n const options: RemoveOptions = {\n force,\n keepData,\n preserveRuntimeState: ownedState?.kind === \"docker\",\n };\n const plan = buildRemovePlan(\n {\n home,\n runtimeDir: dirname(engineStatePath()),\n dataDir: dataDirResolution.dataDir,\n pinnedVersion: IIPINNED_VERSION,\n localBinIiiVersion,\n connectManifest,\n },\n options,\n );\n\n const applicable = plan.filter((it) => it.applicable);\n if (applicable.length === 0) {\n p.outro(\"Nothing to remove. agentmemory is already gone.\");\n return;\n }\n\n p.note(formatPlan(plan), \"destruction plan\");\n\n if (!force) {\n const proceed = await p.confirm({\n message: \"Proceed with these deletions?\",\n initialValue: false,\n });\n if (p.isCancel(proceed) || proceed !== true) {\n p.cancel(\"Cancelled. Nothing was deleted.\");\n return;\n }\n const sure = await p.confirm({\n message: \"This is irreversible. Continue?\",\n initialValue: false,\n });\n if (p.isCancel(sure) || sure !== true) {\n p.cancel(\"Cancelled. Nothing was deleted.\");\n return;\n }\n }\n\n for (const item of plan) {\n if (!item.applicable) continue;\n\n // alwaysAsk items get a per-item confirmation even with --force.\n if (item.alwaysAsk) {\n const ok = await p.confirm({\n message: `${item.description} — really delete${item.path ? ` ${item.path}` : \"\"}?`,\n initialValue: false,\n });\n if (p.isCancel(ok) || ok !== true) {\n p.log.info(`skipped: ${item.id}`);\n continue;\n }\n }\n\n if (item.id === \"stop-engine\") {\n if (ownedState?.kind === \"docker\") {\n await stopDockerEngine(ownedState, getRestPort(), true);\n p.log.success(\"stopped Docker engine; container, data mount, and recovery state preserved\");\n continue;\n }\n const stopped = await stopNativeEngineForRemoval();\n if (!stopped.ok) {\n p.log.error(`Removal aborted: ${stopped.reason}.`);\n process.exit(1);\n }\n p.log.success(\n stopped.stoppedEnginePids > 0\n ? `stopped engine (${stopped.stoppedEnginePids} pid${stopped.stoppedEnginePids === 1 ? \"\" : \"s\"})`\n : \"no engine running\",\n );\n continue;\n }\n\n if (!item.path) continue;\n const r = safeDelete(item.path);\n if (r.ok) p.log.success(r.message);\n else p.log.error(r.message);\n }\n\n p.outro(\n \"Done. agentmemory cleanly removed. The npm package itself: npm uninstall -g @agentmemory/agentmemory\",\n );\n}\n\nasync function runConsole(): Promise<void> {\n const iiiBin = pickCompatibleIii([\n whichBinary(\"iii\"),\n ...fallbackIiiPaths().filter((candidate) => existsSync(candidate)),\n ]);\n if (!iiiBin) {\n p.log.error(\n `No iii v${IIPINNED_VERSION} found. Start agentmemory once so it installs the pinned engine into ${privateIiiPath()}, then run this again.`,\n );\n process.exit(1);\n }\n let parsed: ReturnType<typeof parseConsoleArgs>;\n try {\n parsed = parseConsoleArgs(\n args.slice(1),\n defaultConsolePort(getConfiguredViewerPort()),\n );\n } catch (err) {\n p.log.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n const launch = {\n iiiBin,\n consolePort: parsed.consolePort,\n restPort: getRestPort(),\n streamPort: getStreamPort(),\n enginePort: getEnginePort(),\n extraArgs: parsed.extraArgs,\n };\n if (!(await isEngineRunning())) {\n p.log.warn(\n `No engine responding on port ${launch.restPort}. The console starts anyway and connects once agentmemory is up.`,\n );\n }\n p.log.info(\n `iii console: http://127.0.0.1:${launch.consolePort} (engine REST ${launch.restPort}, streams ${launch.streamPort}, bridge ${launch.enginePort}). The first run downloads the console binary next to the pinned iii.`,\n );\n const child = spawn(iiiBin, consoleArgs(launch), {\n stdio: \"inherit\",\n detached: true,\n });\n const forward = (signal: NodeJS.Signals): void => {\n try {\n process.kill(-child.pid!, signal);\n } catch {\n child.kill(signal);\n }\n };\n for (const signal of [\"SIGINT\", \"SIGTERM\", \"SIGHUP\"] as const) {\n process.on(signal, () => forward(signal));\n }\n const code = await new Promise<number>((resolve) => {\n child.on(\"exit\", (status, signal) => resolve(status ?? (signal ? 1 : 0)));\n child.on(\"error\", (err) => {\n p.log.error(err.message);\n resolve(1);\n });\n });\n process.exit(code);\n}\n\nasync function runCapture(): Promise<void> {\n const code = await runCaptureCommand({\n base: getBaseUrl(),\n args: args.slice(1),\n secret: resolveClientSecret(getBaseUrl()),\n });\n process.exit(code);\n}\n\nconst commands: Record<string, () => Promise<void>> = {\n init: runInit,\n connect: runConnectCmd,\n status: runStatus,\n console: runConsole,\n doctor: runDoctor,\n demo: runDemo,\n upgrade: runUpgrade,\n stop: runStop,\n remove: runRemove,\n mcp: runMcp,\n \"import-jsonl\": runImportJsonl,\n capture: runCapture,\n};\n\nconst first = args[0] ?? \"\";\nasync function unknownCommand(): Promise<void> {\n p.log.error(\n `Unknown command: ${first}. Supported: ${Object.keys(commands).join(\", \")}. Run \\`agentmemory\\` with no arguments to start the memory server, or \\`agentmemory --help\\` for usage.`,\n );\n process.exit(1);\n}\n// Only a bare invocation or flag-style args boot the server; an unrecognized\n// word is an error. Previously any typo (or a guessed subcommand like\n// `agentmemory consolidate`) fell through to the full server boot and could\n// break a running daemon.\nconst handler = commands[first] ?? (first && !first.startsWith(\"-\") ? unknownCommand : main);\nhandler().catch((err) => {\n p.log.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n});\n"],"mappings":"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"}
|