@agentmemory/agentmemory 0.9.13 → 0.9.15
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/README.md +23 -21
- package/dist/cli.mjs +1612 -113
- package/dist/cli.mjs.map +1 -1
- package/dist/connect-hRTF7E2c.mjs +525 -0
- package/dist/connect-hRTF7E2c.mjs.map +1 -0
- package/dist/{image-refs-HVu22rfu.mjs → image-refs-R3tin9MR.mjs} +2 -2
- package/dist/{image-refs-HVu22rfu.mjs.map → image-refs-R3tin9MR.mjs.map} +1 -1
- package/dist/{image-store-BfN1vDbj.mjs → image-store-DyrKZKqZ.mjs} +1 -1
- package/dist/index.mjs +63 -35
- package/dist/index.mjs.map +1 -1
- package/dist/{src-Ca9oX6Hq.mjs → src-BGcqJR1a.mjs} +62 -72
- package/dist/src-BGcqJR1a.mjs.map +1 -0
- package/dist/{standalone-BpbiNqr9.mjs → standalone-BQOaGF4z.mjs} +3 -3
- package/dist/{standalone-BpbiNqr9.mjs.map → standalone-BQOaGF4z.mjs.map} +1 -1
- package/dist/standalone.mjs +1 -1
- package/dist/standalone.mjs.map +1 -1
- package/dist/{tools-registry-D5l632PP.mjs → tools-registry-BF0pgZmI.mjs} +2 -6
- package/dist/tools-registry-BF0pgZmI.mjs.map +1 -0
- package/package.json +6 -6
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/dist/src-Ca9oX6Hq.mjs.map +0 -1
- package/dist/tools-registry-D5l632PP.mjs.map +0 -1
package/dist/cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.mjs","names":["PATH_DELIMITER"],"sources":["../src/state/schema.ts","../src/cli.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\n\nexport const KV = {\n sessions: \"mem:sessions\",\n observations: (sessionId: string) => `mem:obs:${sessionId}`,\n memories: \"mem:memories\",\n summaries: \"mem:summaries\",\n config: \"mem:config\",\n metrics: \"mem:metrics\",\n health: \"mem:health\",\n embeddings: (obsId: string) => `mem:emb:${obsId}`,\n bm25Index: \"mem:index:bm25\",\n relations: \"mem:relations\",\n profiles: \"mem:profiles\",\n claudeBridge: \"mem:claude-bridge\",\n graphNodes: \"mem:graph:nodes\",\n graphEdges: \"mem:graph:edges\",\n semantic: \"mem:semantic\",\n procedural: \"mem:procedural\",\n teamShared: (teamId: string) => `mem:team:${teamId}:shared`,\n teamUsers: (teamId: string, userId: string) =>\n `mem:team:${teamId}:users:${userId}`,\n teamProfile: (teamId: string) => `mem:team:${teamId}:profile`,\n audit: \"mem:audit\",\n actions: \"mem:actions\",\n actionEdges: \"mem:action-edges\",\n leases: \"mem:leases\",\n routines: \"mem:routines\",\n routineRuns: \"mem:routine-runs\",\n signals: \"mem:signals\",\n checkpoints: \"mem:checkpoints\",\n mesh: \"mem:mesh\",\n sketches: \"mem:sketches\",\n facets: \"mem:facets\",\n sentinels: \"mem:sentinels\",\n crystals: \"mem:crystals\",\n lessons: \"mem:lessons\",\n insights: \"mem:insights\",\n graphEdgeHistory: \"mem:graph:edge-history\",\n enrichedChunks: (sessionId: string) => `mem:enriched:${sessionId}`,\n latentEmbeddings: (obsId: string) => `mem:latent:${obsId}`,\n retentionScores: \"mem:retention\",\n accessLog: \"mem:access\",\n imageRefs: \"mem:image-refs\",\n imageEmbeddings: \"mem:image-embeddings\",\n slots: \"mem:slots\",\n globalSlots: \"mem:slots:global\",\n state: \"mem:state\",\n} as const;\n\nexport const STREAM = {\n name: \"mem-live\",\n group: (sessionId: string) => sessionId,\n viewerGroup: \"viewer\",\n} as const;\n\nexport function generateId(prefix: string): string {\n const ts = Date.now().toString(36);\n const rand = crypto.randomUUID().replace(/-/g, \"\").slice(0, 12);\n return `${prefix}_${ts}_${rand}`;\n}\n\nexport function fingerprintId(prefix: string, content: string): string {\n const hash = createHash(\"sha256\").update(content).digest(\"hex\");\n return `${prefix}_${hash.slice(0, 16)}`;\n}\n\nexport function jaccardSimilarity(a: string, b: string): number {\n const setA = new Set(a.split(/\\s+/).filter((t) => t.length > 2));\n const setB = new Set(b.split(/\\s+/).filter((t) => t.length > 2));\n if (setA.size === 0 && setB.size === 0) return 1;\n if (setA.size === 0 || setB.size === 0) return 0;\n let intersection = 0;\n for (const word of setA) {\n if (setB.has(word)) intersection++;\n }\n return intersection / (setA.size + setB.size - intersection);\n}\n","#!/usr/bin/env node\n\nimport {\n spawn,\n execFileSync,\n spawnSync,\n type ChildProcess,\n} from \"node:child_process\";\nimport { existsSync, readdirSync, readFileSync, readlinkSync, statSync } 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 { generateId } from \"./state/schema.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst args = process.argv.slice(2);\nconst IS_WINDOWS = platform() === \"win32\";\nconst IS_VERBOSE = args.includes(\"--verbose\") || args.includes(\"-v\");\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\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 status Show connection status, memory count, flags, and health\n doctor Run diagnostic checks (server, flags, graph, providers)\n demo Seed sample sessions and show recall in action\n upgrade Upgrade local deps + iii runtime (best effort)\n mcp Start standalone MCP server (no engine required)\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 and diagnostic info on startup\n --tools all|core Tool visibility (default: core = 7 tools)\n --no-engine Skip auto-starting iii-engine\n --port <N> Override REST port (default: 3111)\n\nEnvironment:\n AGENTMEMORY_URL Full REST base URL (e.g. http://localhost:3111).\n Honored by status, doctor, and MCP shim commands.\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 process.env[\"AGENTMEMORY_TOOLS\"] = args[toolsIdx + 1];\n}\n\nconst portIdx = args.indexOf(\"--port\");\nif (portIdx !== -1 && args[portIdx + 1]) {\n process.env[\"III_REST_PORT\"] = args[portIdx + 1];\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\nfunction getViewerUrl(): string {\n const envUrl = process.env[\"AGENTMEMORY_VIEWER_URL\"];\n if (envUrl) return envUrl.replace(/\\/+$/, \"\");\n try {\n const u = new URL(getBaseUrl());\n const vPort = (parseInt(u.port || \"3111\", 10) || 3111) + 2;\n return `${u.protocol}//${u.hostname}:${vPort}`;\n } catch {\n return `http://localhost:${getRestPort() + 2}`;\n }\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 return res.ok;\n } catch {\n return false;\n }\n}\n\nfunction findIiiConfig(): string {\n const candidates = [\n join(__dirname, \"iii-config.yaml\"),\n join(__dirname, \"..\", \"iii-config.yaml\"),\n join(process.cwd(), \"iii-config.yaml\"),\n ];\n for (const c of candidates) {\n if (existsSync(c)) return c;\n }\n return \"\";\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\nfunction fallbackIiiPaths(): string[] {\n if (IS_WINDOWS) {\n const userProfile = process.env[\"USERPROFILE\"];\n if (!userProfile) return [];\n return [\n join(userProfile, \".local\", \"bin\", \"iii.exe\"),\n join(userProfile, \"bin\", \"iii.exe\"),\n ];\n }\n const home = process.env[\"HOME\"];\n if (!home) return [\"/usr/local/bin/iii\"];\n return [join(home, \".local\", \"bin\", \"iii\"), \"/usr/local/bin/iii\"];\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 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: label.includes(\"Docker\") ? \"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 }\n });\n child.unref();\n return child;\n}\n\nasync function startEngine(): Promise<boolean> {\n const configPath = findIiiConfig();\n let iiiBin = whichBinary(\"iii\");\n vlog(`iii binary: ${iiiBin ?? \"(not on PATH)\"}, config: ${configPath || \"(not found)\"}`);\n\n if (iiiBin && configPath) {\n const s = p.spinner();\n s.start(`Starting iii-engine: ${iiiBin}`);\n spawnEngineBackground(iiiBin, [\"--config\", configPath], \"iii-engine\");\n s.stop(\"iii-engine process started\");\n return true;\n }\n\n const dockerBin = whichBinary(\"docker\");\n vlog(`docker binary: ${dockerBin ?? \"(not on PATH)\"}`);\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 if (dockerBin && composeFile) {\n const s = p.spinner();\n s.start(\"Starting iii-engine via Docker...\");\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 for (const iiiPath of fallbackIiiPaths()) {\n if (existsSync(iiiPath)) {\n p.log.info(`Found iii at: ${iiiPath}`);\n process.env[\"PATH\"] = `${dirname(iiiPath)}${PATH_DELIMITER}${process.env[\"PATH\"] ?? \"\"}`;\n iiiBin = iiiPath;\n break;\n }\n }\n\n if (iiiBin && configPath) {\n const s = p.spinner();\n s.start(`Starting iii-engine: ${iiiBin}`);\n spawnEngineBackground(iiiBin, [\"--config\", configPath], \"iii-engine\");\n s.stop(\"iii-engine process started\");\n return true;\n }\n\n if (!iiiBin && (!dockerBin || !composeFile)) {\n startupFailure = { kind: \"no-engine\" };\n } else if (!composeFile && dockerBin) {\n startupFailure = { kind: \"no-docker-compose\" };\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 requires the \\`iii-engine\\` runtime, pinned to 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`,\n \" (or iii-aarch64-pc-windows-msvc.zip on ARM)\",\n \" 3. Extract iii.exe and either add its folder to PATH\",\n \" or move it to %USERPROFILE%\\\\.local\\\\bin\\\\iii.exe\",\n \" 4. Re-run: npx @agentmemory/agentmemory\",\n \"\",\n \" B) Docker Desktop:\",\n \" 1. Install Docker Desktop for Windows\",\n ` 2. docker pull iiidev/iii:${IIPINNED_VERSION}`,\n \" 3. Start Docker Desktop (engine must be running)\",\n \" 4. Re-run: npx @agentmemory/agentmemory\",\n \"\",\n \"Or skip the engine entirely for standalone MCP:\",\n \" npx @agentmemory/agentmemory mcp\",\n ];\n }\n const linuxInstall = releaseUrl\n ? ` A) mkdir -p ~/.local/bin && curl -fsSL \"${releaseUrl}\" | tar -xz -C ~/.local/bin && chmod +x ~/.local/bin/iii`\n : ` A) Manual download from https://github.com/iii-hq/iii/releases/tag/iii%2Fv${IIPINNED_VERSION}`;\n return [\n `agentmemory requires the \\`iii-engine\\` runtime, pinned to v${IIPINNED_VERSION}. Pick one:`,\n \"\",\n linuxInstall,\n ` (installs iii v${IIPINNED_VERSION} into ~/.local/bin/iii)`,\n \"\",\n ` B) Docker: \\`docker pull iiidev/iii:${IIPINNED_VERSION}\\``,\n \"\",\n \"Or skip the engine entirely for standalone MCP:\",\n \" npx @agentmemory/agentmemory mcp\",\n \"\",\n \"Docs: https://iii.dev/docs\",\n `Why pinned: iii v0.11.6 introduces the new sandbox-everything model`,\n `(\\`iii worker add\\` registration). agentmemory still uses the older`,\n `iii-exec config-file worker model and needs a refactor before it`,\n `runs cleanly under the new engine. Override with`,\n `AGENTMEMORY_III_VERSION=<version> when you've migrated manually.`,\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 main() {\n p.intro(\"agentmemory\");\n\n if (skipEngine) {\n p.log.info(\"Skipping engine check (--no-engine)\");\n await import(\"./index.js\");\n return;\n }\n\n if (await isEngineRunning()) {\n p.log.success(\"iii-engine is running\");\n await import(\"./index.js\");\n return;\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 latest 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(\"iii-engine is ready\");\n await import(\"./index.js\");\n}\n\nasync function apiFetch<T = unknown>(base: string, path: string, timeoutMs = 5000): Promise<T | null> {\n try {\n const res = await fetch(`${base}/agentmemory/${path}`, { signal: AbortSignal.timeout(timeoutMs) });\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] = await Promise.all([\n apiFetch<any>(base, \"health\"),\n apiFetch<any>(base, \"sessions\"),\n apiFetch<any>(base, \"graph/stats\"),\n apiFetch<any>(base, \"export\"),\n apiFetch<any>(base, \"config/flags\"),\n ]);\n\n const h = healthRes?.health;\n const status = healthRes?.status || \"unknown\";\n const version = healthRes?.version || \"?\";\n const sessions = Array.isArray(sessionsRes?.sessions) ? sessionsRes.sessions.length : 0;\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 = memoriesRes?.observations?.length || 0;\n const memCount = memoriesRes?.memories?.length || 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\" ? \"✓ healthy\" : 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: ${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\" ? \"✓ llm\" : \"✗ noop (no key)\";\n const embed = flagsRes.embeddingProvider === \"embeddings\" ? \"✓ embeddings\" : \"bm25-only\";\n const flagRows = (flagsRes.flags || []).map((f: { key: string; enabled: boolean; label: string }) =>\n ` ${f.enabled ? \"✓\" : \"✗\"} ${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 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 ? \"✓\" : \"✗\"} ${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\nasync function runDoctor() {\n p.intro(\"agentmemory doctor\");\n const base = getBaseUrl();\n const viewerUrl = getViewerUrl();\n const checks: DoctorCheck[] = [];\n\n const serverUp = await isEngineRunning();\n checks.push({\n name: \"Server reachable\",\n ok: serverUp,\n hint: serverUp ? undefined : `Start with: npx @agentmemory/agentmemory (tried ${base})`,\n });\n\n if (!serverUp) {\n p.note(formatChecks(checks), \"server unreachable\");\n process.exit(1);\n }\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 viewerUp = await fetch(viewerUrl, { signal: AbortSignal.timeout(2000) })\n .then((r) => r.ok)\n .catch(() => false);\n\n const hasLlm = flags?.provider === \"llm\";\n const hasEmbed = flags?.embeddingProvider === \"embeddings\";\n const graphNodeCount = Number(graph?.totalNodes ?? graph?.nodes ?? graph?.nodeCount ?? 0);\n const graphHas = graphNodeCount > 0;\n\n checks.push(\n {\n name: \"Health status\",\n ok: health?.status === \"healthy\",\n hint: health?.status === \"healthy\" ? undefined : `Status: ${health?.status || \"unknown\"}`,\n },\n {\n name: \"Viewer reachable\",\n ok: viewerUp,\n hint: viewerUp ? undefined : `${viewerUrl} not responding`,\n },\n {\n name: \"LLM provider\",\n ok: hasLlm,\n hint: hasLlm ? undefined : \"export ANTHROPIC_API_KEY=sk-ant-... (or GEMINI/OPENROUTER/MINIMAX) then restart\",\n },\n {\n name: \"Embedding provider\",\n ok: hasEmbed,\n hint: hasEmbed ? undefined : \"Running BM25-only. Add OPENAI_API_KEY / VOYAGE_API_KEY / COHERE_API_KEY / OLLAMA_HOST for semantic recall\",\n },\n );\n\n for (const f of (flags?.flags || []) as { label: string; enabled: boolean; enableHow: string }[]) {\n checks.push({ name: f.label, ok: f.enabled, hint: f.enabled ? undefined : f.enableHow });\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: \"Plugin enabled but hooks not loaded by Claude Code. Try: /plugin uninstall agentmemory@agentmemory && /plugin install agentmemory@agentmemory, then restart the session. CC must be >= 2.1.x for plugin-hook auto-load.\",\n };\n case \"no-debug-log\":\n return {\n ok: false,\n hint: \"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 ? undefined : \"Graph is empty. Run a session with GRAPH_EXTRACTION_ENABLED=true, or POST /agentmemory/graph/extract\",\n });\n\n const passed = checks.filter((c) => c.ok).length;\n const total = checks.length;\n p.note(formatChecks(checks), `${passed}/${total} checks passing`);\n\n if (passed === total) {\n p.outro(\"✓ All checks passed. agentmemory is healthy.\");\n } else {\n p.outro(`${total - passed} issue(s) — follow hints above to fix.`);\n process.exit(1);\n }\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 runDemo() {\n const port = getRestPort();\n const base = `http://localhost:${port}`;\n p.intro(\"agentmemory demo\");\n\n 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 process.exit(1);\n }\n\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 const lines = [\n `Project: ${demoProject}`,\n `Sessions: ${sessions.length} seeded (${totalObs} observations)`,\n \"\",\n \"Search results:\",\n ...results.flatMap((r) => [\n ` \"${r.query}\"`,\n ` → ${r.hits} hit(s), top: ${r.topTitle.slice(0, 60)}`,\n ]),\n \"\",\n `Notice: searching \"database performance optimization\"`,\n `found the N+1 query fix — keyword matching can't do that.`,\n \"\",\n `Viewer: ${getViewerUrl()}`,\n `Clean up with: 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} ✓`);\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} ✗`);\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@latest\"], {\n label: \"Upgrading iii-sdk to latest\",\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@latest\"], {\n label: \"Upgrading iii-sdk to latest\",\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 shBin = whichBinary(\"sh\");\n const curlBin = whichBinary(\"curl\");\n if (shBin && curlBin) {\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 const releaseUrl = iiiReleaseUrl();\n const asset = iiiReleaseAsset();\n const isZipAsset = asset?.endsWith(\".zip\") === true;\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 } else if (IS_WINDOWS || isZipAsset) {\n // Windows ships a .zip, not a tarball, and the rest of this\n // branch assumes sh + tar -xz + chmod. Skip the auto-installer\n // there and point at the manual flow / Docker fallback. Same\n // guidance as installInstructions().\n p.log.info(\n `Skipping auto-install on ${platform()} — the ${asset} 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 } else {\n // Pinned to IIPINNED_VERSION rather than `install.iii.dev/iii/main`,\n // which would track `latest` and re-pull the broken 0.11.6 build.\n const homeDir = homedir();\n const binDir = join(homeDir, \".local\", \"bin\");\n const installCmd = [\n `mkdir -p \"${binDir}\"`,\n `curl -fsSL \"${releaseUrl}\" | tar -xz -C \"${binDir}\"`,\n `chmod +x \"${binDir}/iii\"`,\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 }\n }\n } else {\n p.log.info(\"Skipped iii-engine installer.\");\n }\n } else {\n p.log.warn(\"curl or sh not found. Skipping 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\nasync function runMcp(): Promise<void> {\n await import(\"./mcp/standalone.js\");\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\"]);\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\nconst commands: Record<string, () => Promise<void>> = {\n init: runInit,\n status: runStatus,\n doctor: runDoctor,\n demo: runDemo,\n upgrade: runUpgrade,\n mcp: runMcp,\n \"import-jsonl\": runImportJsonl,\n};\n\nconst handler = commands[args[0] ?? \"\"] ?? 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":["__dirname","findEnvExample","fsConstants","PATH_DELIMITER"],"sources":["../src/state/schema.ts","../src/cli/doctor-diagnostics.ts","../src/cli/remove-plan.ts","../src/cli/splash.ts","../src/cli/preferences.ts","../src/cli/onboarding.ts","../src/logger.ts","../src/version.ts","../src/cli.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\n\nexport const KV = {\n sessions: \"mem:sessions\",\n observations: (sessionId: string) => `mem:obs:${sessionId}`,\n memories: \"mem:memories\",\n summaries: \"mem:summaries\",\n config: \"mem:config\",\n metrics: \"mem:metrics\",\n health: \"mem:health\",\n embeddings: (obsId: string) => `mem:emb:${obsId}`,\n bm25Index: \"mem:index:bm25\",\n relations: \"mem:relations\",\n profiles: \"mem:profiles\",\n claudeBridge: \"mem:claude-bridge\",\n graphNodes: \"mem:graph:nodes\",\n graphEdges: \"mem:graph:edges\",\n semantic: \"mem:semantic\",\n procedural: \"mem:procedural\",\n teamShared: (teamId: string) => `mem:team:${teamId}:shared`,\n teamUsers: (teamId: string, userId: string) =>\n `mem:team:${teamId}:users:${userId}`,\n teamProfile: (teamId: string) => `mem:team:${teamId}:profile`,\n audit: \"mem:audit\",\n actions: \"mem:actions\",\n actionEdges: \"mem:action-edges\",\n leases: \"mem:leases\",\n routines: \"mem:routines\",\n routineRuns: \"mem:routine-runs\",\n signals: \"mem:signals\",\n checkpoints: \"mem:checkpoints\",\n mesh: \"mem:mesh\",\n sketches: \"mem:sketches\",\n facets: \"mem:facets\",\n sentinels: \"mem:sentinels\",\n crystals: \"mem:crystals\",\n lessons: \"mem:lessons\",\n insights: \"mem:insights\",\n graphEdgeHistory: \"mem:graph:edge-history\",\n enrichedChunks: (sessionId: string) => `mem:enriched:${sessionId}`,\n latentEmbeddings: (obsId: string) => `mem:latent:${obsId}`,\n retentionScores: \"mem:retention\",\n accessLog: \"mem:access\",\n imageRefs: \"mem:image-refs\",\n imageEmbeddings: \"mem:image-embeddings\",\n slots: \"mem:slots\",\n globalSlots: \"mem:slots:global\",\n state: \"mem:state\",\n} as const;\n\nexport const STREAM = {\n name: \"mem-live\",\n group: (sessionId: string) => sessionId,\n viewerGroup: \"viewer\",\n} as const;\n\nexport function generateId(prefix: string): string {\n const ts = Date.now().toString(36);\n const rand = crypto.randomUUID().replace(/-/g, \"\").slice(0, 12);\n return `${prefix}_${ts}_${rand}`;\n}\n\nexport function fingerprintId(prefix: string, content: string): string {\n const hash = createHash(\"sha256\").update(content).digest(\"hex\");\n return `${prefix}_${hash.slice(0, 16)}`;\n}\n\nexport function jaccardSimilarity(a: string, b: string): number {\n const setA = new Set(a.split(/\\s+/).filter((t) => t.length > 2));\n const setB = new Set(b.split(/\\s+/).filter((t) => t.length > 2));\n if (setA.size === 0 && setB.size === 0) return 1;\n if (setA.size === 0 || setB.size === 0) return 0;\n let intersection = 0;\n for (const word of setA) {\n if (setB.has(word)) intersection++;\n }\n return intersection / (setA.size + setB.size - intersection);\n}\n","// 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 ~/.local/bin/iii (the location we install to). */\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 in ~/.local/bin/iii (where we install).\",\n fixPreview:\n \"Suggest re-installing the pinned version via the installer — won't touch your PATH.\",\n moreInfo:\n \"agentmemory's installer writes to ~/.local/bin/iii. When a user-managed iii \" +\n \"lives somewhere else (homebrew, cargo, $XDG_BIN) we don't auto-overwrite it. \" +\n \"If you want our pinned build, run the installer; otherwise this is informational.\",\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 ~/.local/bin/iii. Your PATH wasn't modified — adjust it yourself if needed.\",\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\nexport function localBinIii(home: string): string {\n return join(home, \".local\", \"bin\", \"iii\");\n}\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 // ~/.local/bin/iii — only remove if it matches the version we installed.\n // Heuristic: spawn `iii --version`; if it returns pinnedVersion, safe to\n // remove. Otherwise mark `alwaysAsk` so the operator confirms explicitly.\n const localIii = localBinIii(home);\n if (pathExists(localIii)) {\n const matches = localBinIiiVersion === pinnedVersion;\n plan.push({\n id: \"local-bin-iii\",\n description: matches\n ? `Delete ~/.local/bin/iii (matches pinned v${pinnedVersion})`\n : `Delete ~/.local/bin/iii (version ${localBinIiiVersion ?? \"unknown\"} != pinned v${pinnedVersion}) — will ask`,\n path: localIii,\n alwaysAsk: !matches,\n applicable: true,\n sizeBytes: safeSize(localIii),\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// Block-art \"agentmemory\" lettering. Hand-drawn in box-drawing chars so\n// we don't need a figlet dependency. Each row is 70 columns wide which\n// gives ~25 cols of breathing room on the 120-col tier.\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 // 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}\n\nconst DEFAULTS: Prefs = {\n schemaVersion: 1,\n lastAgent: null,\n lastAgents: [],\n lastProvider: null,\n skipSplash: false,\n skipNpxHint: false,\n firstRunAt: null,\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 { writePrefs } from \"./preferences.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 `◇`.\nconst NATIVE_AGENTS: { value: string; label: string; glyph: string }[] = [\n { value: \"claude-code\", label: \"Claude Code\", glyph: \"⟁\" },\n { value: \"codex\", label: \"Codex\", glyph: \"◎\" },\n { value: \"openhuman\", label: \"OpenHuman\", glyph: \"◇\" },\n { value: \"openclaw\", label: \"OpenClaw\", glyph: \"◇\" },\n { value: \"hermes\", label: \"Hermes\", glyph: \"◇\" },\n { value: \"pi\", label: \"Pi\", glyph: \"◇\" },\n { value: \"cursor\", label: \"Cursor\", glyph: \"◫\" },\n { value: \"gemini-cli\", label: \"Gemini CLI\", glyph: \"✦\" },\n];\n\n// MCP-only row — these agents use the MCP server we ship rather than\n// a native plugin.\nconst MCP_AGENTS: { value: string; label: string; glyph: string }[] = [\n { value: \"opencode\", label: \"OpenCode\", glyph: \"⬡\" },\n { value: \"cline\", label: \"Cline\", glyph: \"◇\" },\n { value: \"goose\", label: \"Goose\", glyph: \"◇\" },\n { value: \"kilo\", label: \"Kilo\", glyph: \"◇\" },\n { value: \"aider\", label: \"Aider\", glyph: \"◇\" },\n { value: \"claude-desktop\", label: \"Claude Desktop\", glyph: \"⟁\" },\n { value: \"windsurf\", label: \"Windsurf\", glyph: \"◇\" },\n { value: \"roo\", label: \"Roo\", glyph: \"◇\" },\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-m1\", envKey: \"MINIMAX_API_KEY\" },\n { value: \"skip\", label: \"Skip — BM25-only mode (no LLM key)\", envKey: null },\n];\n\nfunction buildAgentOptions(): { value: string; label: string; hint?: string }[] {\n return [\n ...NATIVE_AGENTS.map((a) => ({\n value: a.value,\n label: `${a.glyph} ${a.label}`,\n hint: \"native plugin\",\n })),\n ...MCP_AGENTS.map((a) => ({\n value: a.value,\n label: `${a.glyph} ${a.label}`,\n hint: \"MCP server\",\n })),\n ];\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\nexport async function runOnboarding(): Promise<OnboardingResult> {\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: [\"claude-code\"],\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 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 const envPath = await seedEnvFile(provider);\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 return { agents, provider };\n}\n","// Thin logging shim for agentmemory.\n//\n// iii-sdk v0.11 dropped `getContext()`, which had been the source of a\n// contextual logger in every function handler (`getContext().logger`).\n// Migrating directly to the v0.11 OTEL-based `getLogger()` would force\n// every call site to care about the OTEL Logger API shape (`emit(...)`\n// with severity numbers and attributes maps). Instead, this module\n// exposes a single `logger` singleton with the same `.info/.warn/.error`\n// signature the old code used, so the mechanical replacement across\n// 30+ function files is: drop the `getContext` import, drop the\n// `const ctx = getContext();` line, and rename `ctx.logger.*` to\n// `logger.*`. Nothing else changes.\n//\n// Output goes to stderr as `[agentmemory] <level> <msg> <json-fields>`.\n// The iii-engine's `iii-exec` worker runs the agentmemory binary as a\n// child process and forwards stderr into `docker logs\n// agentmemory-iii-engine-1`, so these lines end up next to the engine's\n// own output without needing any OTEL wiring. If we later want\n// structured OTEL logs, this file is the only thing that changes.\n//\n// See rohitg00/agentmemory#143 follow-up — the #116 migration updated\n// test mocks but left the real `getContext()` imports in place, which\n// passed `npm test` (tests mock iii-sdk) and `npm run build` (tsdown\n// doesn't type-check) but crashed `node dist/index.mjs` on first\n// import.\n\ntype Fields = Record<string, unknown> | undefined;\n\nfunction fmt(level: string, msg: string, fields: Fields): string {\n if (!fields || Object.keys(fields).length === 0) {\n return `[agentmemory] ${level} ${msg}`;\n }\n try {\n return `[agentmemory] ${level} ${msg} ${JSON.stringify(fields)}`;\n } catch {\n // Fields contained a circular reference or a BigInt — fall back\n // to the plain message so a log line never throws.\n return `[agentmemory] ${level} ${msg}`;\n }\n}\n\nfunction emit(level: string, msg: string, fields: Fields): void {\n try {\n process.stderr.write(fmt(level, msg, fields) + \"\\n\");\n } catch {\n // stderr is unavailable in some weird test/worker contexts — swallow\n // so no log line can ever crash a handler.\n }\n}\n\nexport const logger = {\n info(msg: string, fields?: Fields): void {\n emit(\"info\", msg, fields);\n },\n warn(msg: string, fields?: Fields): void {\n emit(\"warn\", msg, fields);\n },\n error(msg: string, fields?: Fields): void {\n emit(\"error\", msg, fields);\n },\n};\n\n// ---------- boot log ----------\n//\n// `bootLog` is for the one-shot status lines that every register-*\n// function used to dump via `console.log` during engine startup. On a\n// fresh install that's ~25 lines of `[agentmemory] X enabled` noise\n// before the user can see a prompt. In quiet mode (default), each\n// line is captured into a buffer and discarded; the CLI surfaces a\n// single compressed summary instead. In verbose mode (set by\n// `--verbose` or `AGENTMEMORY_VERBOSE=1`) the lines pass straight\n// through to stderr exactly like the old console.log calls.\n\nlet bootVerbose =\n process.env[\"AGENTMEMORY_VERBOSE\"] === \"1\" ||\n process.env[\"AGENTMEMORY_VERBOSE\"] === \"true\";\n\nconst bootBuffer: string[] = [];\n\nexport function setBootVerbose(enabled: boolean): void {\n bootVerbose = enabled;\n}\n\nexport function isBootVerbose(): boolean {\n return bootVerbose;\n}\n\nexport function bootLog(msg: string): void {\n if (bootVerbose) {\n try {\n process.stderr.write(`[agentmemory] ${msg}\\n`);\n } catch {\n // stderr unavailable — drop.\n }\n return;\n }\n if (bootBuffer.length < 500) bootBuffer.push(msg);\n}\n\nexport function bootWarn(msg: string): void {\n // Warnings always surface; they're rare and the user needs to see\n // them even when the rest of the boot log is suppressed.\n try {\n process.stderr.write(`[agentmemory] warn ${msg}\\n`);\n } catch {}\n}\n\nexport function getBootBuffer(): readonly string[] {\n return bootBuffer;\n}\n","export const VERSION = \"0.9.15\";\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 { 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 localBinIii,\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 { VERSION } from \"./version.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// 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\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 (claude-code, codex,\n cursor, gemini-cli, openclaw, hermes, pi, openhuman).\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 Seed sample sessions and show recall in action\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 server (no engine required)\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: core = 7 tools)\n --no-engine Skip auto-starting iii-engine\n --port <N> Override REST port (default: 3111)\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_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\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 process.env[\"AGENTMEMORY_TOOLS\"] = args[toolsIdx + 1];\n}\n\nconst portIdx = args.indexOf(\"--port\");\nif (portIdx !== -1 && args[portIdx + 1]) {\n process.env[\"III_REST_PORT\"] = args[portIdx + 1];\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\nfunction getViewerUrl(): string {\n const envUrl = process.env[\"AGENTMEMORY_VIEWER_URL\"];\n if (envUrl) return envUrl.replace(/\\/+$/, \"\");\n try {\n const u = new URL(getBaseUrl());\n const vPort = (parseInt(u.port || \"3111\", 10) || 3111) + 2;\n return `${u.protocol}//${u.hostname}:${vPort}`;\n } catch {\n return `http://localhost:${getRestPort() + 2}`;\n }\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 return res.ok;\n } catch {\n return false;\n }\n}\n\nfunction findIiiConfig(): string {\n const candidates = [\n join(__dirname, \"iii-config.yaml\"),\n join(__dirname, \"..\", \"iii-config.yaml\"),\n join(process.cwd(), \"iii-config.yaml\"),\n ];\n for (const c of candidates) {\n if (existsSync(c)) return c;\n }\n return \"\";\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\nfunction fallbackIiiPaths(): string[] {\n if (IS_WINDOWS) {\n const userProfile = process.env[\"USERPROFILE\"];\n if (!userProfile) return [];\n return [\n join(userProfile, \".local\", \"bin\", \"iii.exe\"),\n join(userProfile, \"bin\", \"iii.exe\"),\n ];\n }\n const home = process.env[\"HOME\"];\n if (!home) return [\"/usr/local/bin/iii\"];\n return [join(home, \".local\", \"bin\", \"iii\"), \"/usr/local/bin/iii\"];\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\nlet warnedVersionMismatch = false;\nfunction warnIfEngineVersionMismatch(iiiBinPath: string | null | undefined): void {\n if (!iiiBinPath || warnedVersionMismatch) return;\n const detected = iiiBinVersion(iiiBinPath);\n if (!detected || detected === IIPINNED_VERSION) return;\n warnedVersionMismatch = true;\n const asset = iiiReleaseAsset();\n const downloadHint = asset\n ? `curl -fsSL https://github.com/iii-hq/iii/releases/download/iii/v${IIPINNED_VERSION}/${asset} | tar -xz -C ~/.local/bin`\n : `download v${IIPINNED_VERSION} from https://github.com/iii-hq/iii/releases/tag/iii%2Fv${IIPINNED_VERSION}`;\n p.log.warn(\n `iii-engine on PATH is v${detected} but agentmemory v0.9.14+ pins v${IIPINNED_VERSION}. Set AGENTMEMORY_III_VERSION=${detected} to silence, or downgrade with: \\`${downloadHint}\\``,\n );\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 }\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\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\nfunction shouldSkipNpxHint(): boolean {\n try {\n const prefsPath = join(homedir(), \".agentmemory\", \"preferences.json\");\n if (!existsSync(prefsPath)) return false;\n const raw = readFileSync(prefsPath, \"utf-8\");\n const prefs = JSON.parse(raw) as { skipNpxHint?: boolean };\n return prefs?.skipNpxHint === true;\n } catch {\n return false;\n }\n}\n\nfunction maybeEmitNpxHint(): void {\n if (!isInvokedViaNpx()) return;\n if (shouldSkipNpxHint()) return;\n p.log.info(\n \"Tip: install globally for the bare `agentmemory` command:\\n npm install -g @agentmemory/agentmemory\",\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 && !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(`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 = join(homedir(), \".local\", \"bin\");\n const binPath = join(binDir, \"iii\");\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 warnIfEngineVersionMismatch(iiiBin);\n const s = p.spinner();\n s.start(`Starting iii-engine: ${iiiBin}`);\n writeEngineState({ kind: \"native\", configPath });\n spawnEngineBackground(iiiBin, [\"--config\", configPath], \"iii-engine\");\n s.stop(\"iii-engine process started\");\n return true;\n}\n\nasync function startEngine(): Promise<boolean> {\n const configPath = findIiiConfig();\n let iiiBin = whichBinary(\"iii\");\n vlog(`iii binary: ${iiiBin ?? \"(not on PATH)\"}, config: ${configPath || \"(not found)\"}`);\n\n if (iiiBin && configPath) return startIiiBin(iiiBin, configPath);\n\n for (const iiiPath of fallbackIiiPaths()) {\n if (existsSync(iiiPath)) {\n const v = iiiBinVersion(iiiPath);\n vlog(`fallback iii at ${iiiPath} reports version: ${v ?? \"unknown\"}`);\n p.log.info(`Found iii at: ${iiiPath}${v ? ` (v${v})` : \"\"}`);\n process.env[\"PATH\"] = `${dirname(iiiPath)}${PATH_DELIMITER}${process.env[\"PATH\"] ?? \"\"}`;\n iiiBin = iiiPath;\n break;\n }\n }\n\n if (iiiBin && configPath) return startIiiBin(iiiBin, configPath);\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 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 if (dockerOptIn && dockerBin && composeFile) {\n choice = \"docker\";\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 ~/.local/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) curl -fsSL \"${releaseUrl}\" | tar -xz -C ~/.local/bin && chmod +x ~/.local/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\nfunction printReadyHint(): void {\n const port = getRestPort();\n const viewer = getViewerUrl();\n const hint = `Memory ready on :${port} · viewer on ${viewer} · try: agentmemory demo`;\n // Use plain stdout (not p.outro) so the hint isn't decorated with\n // clack's closing line — it reads as a status, not an end-of-flow.\n process.stdout.write(\"\\n\" + hint + \"\\n\");\n}\n\nasync function main() {\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)) printReadyHint();\n return;\n }\n\n if (await isEngineRunning()) {\n if (IS_VERBOSE) p.log.success(\"iii-engine is running\");\n const attachedBin =\n whichBinary(\"iii\") ?? fallbackIiiPaths().find((p) => existsSync(p)) ?? null;\n warnIfEngineVersionMismatch(attachedBin);\n adoptRunningEngine();\n maybeEmitNpxHint();\n await import(\"./index.js\");\n if (await waitForAgentmemoryReady(15000)) printReadyHint();\n return;\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 latest 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(\"iii-engine is ready\");\n maybeEmitNpxHint();\n await import(\"./index.js\");\n if (await waitForAgentmemoryReady(15000)) 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 res = await fetch(`${base}/agentmemory/${path}`, { signal: AbortSignal.timeout(timeoutMs) });\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] = await Promise.all([\n apiFetch<any>(base, \"health\"),\n apiFetch<any>(base, \"sessions\"),\n apiFetch<any>(base, \"graph/stats\"),\n apiFetch<any>(base, \"export\"),\n apiFetch<any>(base, \"config/flags\"),\n ]);\n\n const h = healthRes?.health;\n const status = healthRes?.status || \"unknown\";\n const version = healthRes?.version || \"?\";\n const sessions = Array.isArray(sessionsRes?.sessions) ? sessionsRes.sessions.length : 0;\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 = memoriesRes?.observations?.length || 0;\n const memCount = memoriesRes?.memories?.length || 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\" ? \"✓ healthy\" : 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: ${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\" ? \"✓ llm\" : \"✗ noop (no key)\";\n const embed = flagsRes.embeddingProvider === \"embeddings\" ? \"✓ embeddings\" : \"bm25-only\";\n const flagRows = (flagsRes.flags || []).map((f: { key: string; enabled: boolean; label: string }) =>\n ` ${f.enabled ? \"✓\" : \"✗\"} ${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 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 ? \"✓\" : \"✗\"} ${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: () => join(homedir(), \".local\", \"bin\", IS_WINDOWS ? \"iii.exe\" : \"iii\"),\n iiiBinaryVersion: (binPath: string) => iiiBinVersion(binPath),\n viewerReachable: async (timeoutMs = 2000) => {\n try {\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 runDemo() {\n const port = getRestPort();\n const base = `http://localhost:${port}`;\n p.intro(\"agentmemory demo\");\n\n 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 process.exit(1);\n }\n\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 const lines = [\n `Project: ${demoProject}`,\n `Sessions: ${sessions.length} seeded (${totalObs} observations)`,\n \"\",\n \"Search results:\",\n ...results.flatMap((r) => [\n ` \"${r.query}\"`,\n ` → ${r.hits} hit(s), top: ${r.topTitle.slice(0, 60)}`,\n ]),\n \"\",\n `Notice: searching \"database performance optimization\"`,\n `found the N+1 query fix — keyword matching can't do that.`,\n \"\",\n `Viewer: ${getViewerUrl()}`,\n `Clean up with: 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} ✓`);\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} ✗`);\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@latest\"], {\n label: \"Upgrading iii-sdk to latest\",\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@latest\"], {\n label: \"Upgrading iii-sdk to latest\",\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\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 const ok = runCommand(dockerBin, [\"compose\", \"-f\", composeFile, \"down\"], {\n label: `docker compose -f ${composeFile} down`,\n });\n clearEnginePidfile();\n clearEngineState();\n if (!ok) {\n p.log.error(\n `docker compose down 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 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\n if (!running) {\n if (portPids.length === 0 && pidfilePid === null) {\n clearEnginePidfile();\n clearEngineState();\n p.outro(\"Nothing to stop.\");\n return;\n }\n const survivors = new Set<number>(portPids);\n if (pidfilePid) survivors.add(pidfilePid);\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. 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 if (candidates.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 for (const pid of candidates) {\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 if (!allStopped) {\n p.log.error(\"One or more engine 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\"]);\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 = localBinIii(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 handler = commands[args[0] ?? \"\"] ?? 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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"}
|