codealmanac 0.1.10 → 0.2.0

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.
Files changed (48) hide show
  1. package/README.md +36 -21
  2. package/dist/agents-A4II4YJC.js +15 -0
  3. package/dist/auth-S5DVUIUJ.js +18 -0
  4. package/dist/{chunk-Z4MWLVS2.js → chunk-447U3GQJ.js} +162 -5
  5. package/dist/chunk-447U3GQJ.js.map +1 -0
  6. package/dist/{chunk-QLHJP2XK.js → chunk-D3B2EEHL.js} +12 -8
  7. package/dist/{chunk-QLHJP2XK.js.map → chunk-D3B2EEHL.js.map} +1 -1
  8. package/dist/{chunk-AXFPUHBN.js → chunk-F53U6JQG.js} +8 -49
  9. package/dist/chunk-F53U6JQG.js.map +1 -0
  10. package/dist/{chunk-BJVZLP6O.js → chunk-MX2EW5MR.js} +3 -3
  11. package/dist/{chunk-Z6MBJ3D2.js → chunk-QQHIVTXT.js} +6 -4
  12. package/dist/{chunk-Z6MBJ3D2.js.map → chunk-QQHIVTXT.js.map} +1 -1
  13. package/dist/chunk-R3URPHGH.js +194 -0
  14. package/dist/chunk-R3URPHGH.js.map +1 -0
  15. package/dist/chunk-SSYMRT4I.js +126 -0
  16. package/dist/chunk-SSYMRT4I.js.map +1 -0
  17. package/dist/{chunk-QHQ6YH7U.js → chunk-V3QOQSXI.js} +5 -3
  18. package/dist/{chunk-QHQ6YH7U.js.map → chunk-V3QOQSXI.js.map} +1 -1
  19. package/dist/chunk-WRUSDYYE.js +97 -0
  20. package/dist/chunk-WRUSDYYE.js.map +1 -0
  21. package/dist/{chunk-3LC55TG6.js → chunk-ZDJSJIB6.js} +77 -126
  22. package/dist/chunk-ZDJSJIB6.js.map +1 -0
  23. package/dist/{cli-W3OYVJYH.js → cli-CMGYLJSN.js} +52 -13
  24. package/dist/cli-CMGYLJSN.js.map +1 -0
  25. package/dist/codealmanac.js +1 -1
  26. package/dist/doctor-BTH7GCFV.js +17 -0
  27. package/dist/{hook-CRJMWSSO.js → hook-2NP3UE7U.js} +2 -2
  28. package/dist/{register-commands-JHC2OFKM.js → register-commands-7SKQLQW4.js} +330 -32
  29. package/dist/register-commands-7SKQLQW4.js.map +1 -0
  30. package/dist/uninstall-FDIOBAAR.js +15 -0
  31. package/dist/uninstall-FDIOBAAR.js.map +1 -0
  32. package/dist/update-RAF7QRYF.js +11 -0
  33. package/dist/update-RAF7QRYF.js.map +1 -0
  34. package/hooks/almanac-capture.sh +40 -7
  35. package/package.json +1 -1
  36. package/dist/chunk-3LC55TG6.js.map +0 -1
  37. package/dist/chunk-AXFPUHBN.js.map +0 -1
  38. package/dist/chunk-Z4MWLVS2.js.map +0 -1
  39. package/dist/cli-W3OYVJYH.js.map +0 -1
  40. package/dist/doctor-ODFNJUKH.js +0 -15
  41. package/dist/register-commands-JHC2OFKM.js.map +0 -1
  42. package/dist/uninstall-HE2Z2LN2.js +0 -12
  43. package/dist/update-IL243I4E.js +0 -10
  44. /package/dist/{doctor-ODFNJUKH.js.map → agents-A4II4YJC.js.map} +0 -0
  45. /package/dist/{hook-CRJMWSSO.js.map → auth-S5DVUIUJ.js.map} +0 -0
  46. /package/dist/{chunk-BJVZLP6O.js.map → chunk-MX2EW5MR.js.map} +0 -0
  47. /package/dist/{uninstall-HE2Z2LN2.js.map → doctor-BTH7GCFV.js.map} +0 -0
  48. /package/dist/{update-IL243I4E.js.map → hook-2NP3UE7U.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/setup.ts","../src/commands/setup/install-path.ts","../src/commands/setup/next-steps.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport {\n copyFile,\n mkdir,\n readFile,\n writeFile,\n} from \"node:fs/promises\";\nimport { createRequire } from \"node:module\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport {\n checkClaudeAuth,\n type ClaudeAuthStatus,\n type SpawnCliFn,\n UNAUTHENTICATED_MESSAGE,\n} from \"../agent/auth.js\";\nimport {\n isAgentProviderId,\n readConfig,\n writeConfig,\n type AgentProviderId,\n} from \"../update/config.js\";\nimport { runHookInstall } from \"./hook.js\";\nimport {\n detectCurrentInstallPath,\n detectEphemeral,\n spawnGlobalInstall,\n} from \"./setup/install-path.js\";\nimport {\n countExistingPages,\n printNextSteps,\n} from \"./setup/next-steps.js\";\n\n/**\n * `codealmanac setup` — the MCP-style branded TUI that runs when a user\n * invokes the bare `codealmanac` binary (or `almanac setup` / `codealmanac\n * setup` explicitly).\n *\n * Model: `mcp-ts/src/setup.ts` from openalmanac. Same ASCII banner + badge\n * + step-indicator style, same interactive + `--yes` + non-interactive\n * modes.\n *\n * Three things get installed:\n *\n * 1. The `SessionEnd` hook in `~/.claude/settings.json` (delegated to\n * `runHookInstall` from `./hook.ts`).\n * 2. The short \"how to use codealmanac\" guide at\n * `~/.claude/codealmanac.md`, sourced from `guides/mini.md` in the\n * package.\n * 3. The full reference at `~/.claude/codealmanac-reference.md`,\n * sourced from `guides/reference.md`.\n * 4. An `@~/.claude/codealmanac.md` import line in `~/.claude/CLAUDE.md`\n * so Claude Code picks up the short guide globally.\n *\n * Everything is idempotent — running setup again is safe. `--skip-hook`\n * and `--skip-guides` opt out of the individual installs. `--yes` or a\n * non-TTY stdin skips all prompts and installs everything.\n */\n\nexport interface SetupOptions {\n /** Install everything without prompting. */\n yes?: boolean;\n /** Don't install the SessionEnd hook. */\n skipHook?: boolean;\n /** Don't install the CLAUDE.md guides. */\n skipGuides?: boolean;\n /** Set the default agent provider during setup. */\n agent?: string;\n\n // ─── Injection points (tests only) ────────────────────────────────\n /** Override the subprocess spawner for `claude auth status`. */\n spawnCli?: SpawnCliFn;\n /** Override `~/.claude/settings.json` path. */\n settingsPath?: string;\n /** Override the bundled hook script path. */\n hookScriptPath?: string;\n /** Override the stable hooks directory for the hook script copy. */\n stableHooksDir?: string;\n /** Override `~/.claude/` dir for guide install. */\n claudeDir?: string;\n /** Override the directory containing `mini.md` / `reference.md`. */\n guidesDir?: string;\n /** Override interactivity; defaults to `process.stdin.isTTY`. */\n isTTY?: boolean;\n /** Stdout sink; defaults to `process.stdout`. */\n stdout?: NodeJS.WritableStream;\n /**\n * Override the install-path probe result. When `null` the probe is\n * bypassed (tests that don't care about the ephemeral-path step).\n * When a string it's treated as the detected install path.\n */\n installPath?: string | null;\n /**\n * Override the npm global install spawner (tests inject a no-op to\n * avoid actually spawning npm during CI).\n */\n spawnGlobalInstall?: () => Promise<void>;\n}\n\nexport interface SetupResult {\n stdout: string;\n stderr: string;\n exitCode: number;\n}\n\n// ─── ANSI helpers ────────────────────────────────────────────────────\n\nconst RST = \"\\x1b[0m\";\nconst DIM = \"\\x1b[2m\";\nconst WHITE_BOLD = \"\\x1b[1;37m\";\nconst BLUE = \"\\x1b[38;5;75m\";\nconst ACCENT_BG = \"\\x1b[48;5;252m\\x1b[38;5;16m\";\n\nconst GRADIENT = [\n \"\\x1b[38;5;255m\",\n \"\\x1b[38;5;253m\",\n \"\\x1b[38;5;251m\",\n \"\\x1b[38;5;249m\",\n \"\\x1b[38;5;246m\",\n \"\\x1b[38;5;243m\",\n];\n\n// `codealmanac` 11-letter ASCII banner. Chosen for tasteful rendering —\n// same banner used in the MCP setup wizard design, retooled letters for\n// the word \"codealmanac\". Each glyph is 6 lines tall.\n//\n// If you tweak this, keep it to ≤80 visual columns wide so it fits in\n// narrow terminals (80 cols is the classic default).\nconst LOGO_LINES = [\n \" ___ ___ ___ ___ _ _ __ __ _ _ _ _ ___ \",\n \" / __/ _ \\\\| \\\\| __| /_\\\\ | | | \\\\/ | /_\\\\ | \\\\| | /_\\\\ / __|\",\n \"| (_| (_) | |) | _| / _ \\\\| |__| |\\\\/| |/ _ \\\\| .` |/ _ \\\\ (__ \",\n \" \\\\___\\\\___/|___/|___/_/ \\\\_\\\\____|_| |_/_/ \\\\_\\\\_|\\\\_/_/ \\\\_\\\\___|\",\n \" \",\n \" a living wiki for codebases, for your agent \",\n];\n\nconst BAR = ` ${DIM}\\u2502${RST}`;\n\nfunction printBanner(out: NodeJS.WritableStream): void {\n out.write(\"\\n\");\n for (let i = 0; i < LOGO_LINES.length; i++) {\n const color = GRADIENT[Math.min(i, GRADIENT.length - 1)] ?? \"\";\n out.write(`${color}${LOGO_LINES[i]}${RST}\\n`);\n }\n out.write(`\\n${WHITE_BOLD} Install the hook + agent guides${RST}\\n`);\n}\n\nfunction printBadge(out: NodeJS.WritableStream): void {\n out.write(`\\n ${ACCENT_BG} codealmanac ${RST}\\n\\n`);\n}\n\nfunction stepDone(out: NodeJS.WritableStream, msg: string): void {\n out.write(` ${BLUE}\\u25c7${RST} ${msg}\\n`);\n}\n\nfunction stepActive(out: NodeJS.WritableStream, msg: string): void {\n out.write(` ${BLUE}\\u25c6${RST} ${msg}\\n`);\n}\n\nfunction stepSkipped(out: NodeJS.WritableStream, msg: string): void {\n out.write(` ${DIM}\\u25cb ${msg}${RST}\\n`);\n}\n\n// ─── Entry point ─────────────────────────────────────────────────────\n\nexport async function runSetup(\n options: SetupOptions = {},\n): Promise<SetupResult> {\n const out = options.stdout ?? process.stdout;\n const isTTY =\n options.isTTY ?? (process.stdin.isTTY === true);\n const interactive = isTTY && options.yes !== true;\n\n // No-op fast path. When the caller explicitly skipped every install\n // step, rendering the full banner + step markers + \"Setup complete\"\n // box is actively misleading — nothing was actually set up. Emit a\n // single terse line and exit so the user gets honest feedback and\n // piped callers (CI, scripts) don't parse through nine lines of ANSI\n // to conclude nothing happened.\n if (options.skipHook === true && options.skipGuides === true) {\n out.write(\n \"codealmanac: nothing to install — use --help to see what setup does\\n\",\n );\n return { stdout: \"\", stderr: \"\", exitCode: 0 };\n }\n\n printBanner(out);\n printBadge(out);\n\n // Step 1: auth status. We report what we find; we don't block. The user\n // can still install the hook + guides without being logged in — they'll\n // hit the auth wall on first `capture`, not on setup.\n const auth = await safeCheckAuth(options.spawnCli);\n reportAuth(out, auth);\n out.write(BAR + \"\\n\");\n\n const agentChoice = await chooseDefaultAgent({\n out,\n interactive,\n requested: options.agent,\n });\n if (!agentChoice.ok) {\n return {\n stdout: \"\",\n stderr: `almanac: ${agentChoice.error}\\n`,\n exitCode: 1,\n };\n }\n stepDone(out, `Default agent: ${WHITE_BOLD}${agentChoice.provider}${RST}`);\n out.write(BAR + \"\\n\");\n\n // Step 1b: ephemeral install detection. When codealmanac was invoked via\n // `npx codealmanac` (no prior `npm i -g`), the binary lives inside an\n // npx cache directory or pnpm store that can be evicted at any time.\n // `almanac` is also not on PATH, so the user can't use it after setup.\n //\n // When we detect an ephemeral location, we offer (or, on --yes, perform)\n // a `npm install -g codealmanac` to make the install permanent.\n //\n // This is Bug #2 from codealmanac-known-bugs.md.\n const ephem = options.installPath !== undefined\n ? (options.installPath !== null\n ? detectEphemeral(options.installPath)\n : false)\n : detectEphemeral(detectCurrentInstallPath());\n if (ephem) {\n let globalAction: InstallDecision = \"install\";\n if (interactive) {\n globalAction = await confirm(\n out,\n `Running from an ephemeral npx location. Install globally so 'almanac' stays on PATH?`,\n true,\n );\n }\n if (globalAction === \"install\") {\n stepActive(out, \"Installing codealmanac globally…\");\n try {\n await (options.spawnGlobalInstall ?? spawnGlobalInstall)();\n stepDone(out, \"codealmanac installed globally (almanac now on PATH)\");\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n stepActive(out, `Global install failed: ${msg}`);\n out.write(\n ` ${DIM}You can retry manually: npm install -g codealmanac${RST}\\n`,\n );\n }\n } else {\n stepSkipped(\n out,\n `Global install ${DIM}skipped — almanac will not be on PATH after this session${RST}`,\n );\n }\n out.write(BAR + \"\\n\");\n }\n\n // Step 2: install the hook (default yes).\n let hookAction: InstallDecision = \"install\";\n if (options.skipHook === true) {\n hookAction = \"skip\";\n } else if (interactive) {\n hookAction = await confirm(\n out,\n \"Install auto-capture hooks for Claude, Codex, and Cursor?\",\n true,\n );\n }\n\n let hookResultLine = \"\";\n if (hookAction === \"install\") {\n const res = await runHookInstall({\n source: \"all\",\n settingsPath: options.settingsPath,\n hookScriptPath: options.hookScriptPath,\n stableHooksDir: options.stableHooksDir,\n });\n if (res.exitCode !== 0) {\n stepActive(out, `SessionEnd hook: ${res.stderr.trim()}`);\n return {\n stdout: \"\",\n stderr: res.stderr,\n exitCode: res.exitCode,\n };\n }\n hookResultLine = res.stdout.includes(\"already installed\")\n ? `Auto-capture hooks ${DIM}already installed${RST}`\n : `Auto-capture hooks installed`;\n stepDone(out, hookResultLine);\n } else {\n stepSkipped(out, `SessionEnd hook ${DIM}skipped${RST}`);\n }\n out.write(BAR + \"\\n\");\n\n // Step 3: install the guides.\n let guidesAction: InstallDecision = \"install\";\n if (options.skipGuides === true) {\n guidesAction = \"skip\";\n } else if (interactive) {\n guidesAction = await confirm(\n out,\n \"Install the codealmanac usage guides into ~/.claude/ and import them from CLAUDE.md?\",\n true,\n );\n }\n\n let guidesSummary: string;\n if (guidesAction === \"install\") {\n try {\n const summary = await installGuides({\n claudeDir: options.claudeDir ?? path.join(homedir(), \".claude\"),\n guidesDir: options.guidesDir ?? resolveGuidesDir(),\n });\n guidesSummary = summary.anyChanges\n ? `Guides installed (${summary.filesWritten.join(\", \")})`\n : `Guides ${DIM}already installed${RST}`;\n stepDone(out, guidesSummary);\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n stdout: \"\",\n stderr: `almanac: guide install failed: ${msg}\\n`,\n exitCode: 1,\n };\n }\n } else {\n stepSkipped(out, `Guides ${DIM}skipped${RST}`);\n }\n out.write(BAR + \"\\n\");\n\n stepDone(out, `${BLUE}Setup complete${RST}`);\n out.write(\"\\n\");\n\n // Detect whether the current working directory is inside a repo that\n // already has a wiki with pages. This fixes Bug #6 from\n // codealmanac-known-bugs.md: Engineer B clones a repo that already has\n // `.almanac/pages/` (committed by Engineer A) and gets told to run\n // `almanac bootstrap`, which is wrong — the wiki already exists.\n const existingPageCount = countExistingPages(process.cwd());\n printNextSteps(out, existingPageCount);\n\n return { stdout: \"\", stderr: \"\", exitCode: 0 };\n}\n\n// ─── Auth reporting ──────────────────────────────────────────────────\n\nasync function safeCheckAuth(\n spawnCli?: SpawnCliFn,\n): Promise<ClaudeAuthStatus> {\n try {\n return await checkClaudeAuth(spawnCli);\n } catch {\n return { loggedIn: false };\n }\n}\n\ntype AgentChoice =\n | { ok: true; provider: AgentProviderId }\n | { ok: false; error: string };\n\nasync function chooseDefaultAgent(args: {\n out: NodeJS.WritableStream;\n interactive: boolean;\n requested?: string;\n}): Promise<AgentChoice> {\n const config = await readConfig();\n let selected = args.requested ?? config.agent.default;\n if (args.interactive && args.requested === undefined) {\n selected = await promptText(\n args.out,\n \"Choose default agent: claude, codex, or cursor\",\n config.agent.default,\n );\n }\n if (!isAgentProviderId(selected)) {\n return {\n ok: false,\n error:\n `unknown agent '${selected}'. Expected one of: claude, codex, cursor.`,\n };\n }\n await writeConfig({\n ...config,\n agent: {\n ...config.agent,\n default: selected,\n },\n });\n return { ok: true, provider: selected };\n}\n\nfunction reportAuth(\n out: NodeJS.WritableStream,\n auth: ClaudeAuthStatus,\n): void {\n if (auth.loggedIn) {\n const who = auth.email ?? \"Claude account\";\n const plan =\n auth.subscriptionType !== undefined\n ? ` ${DIM}(${auth.subscriptionType})${RST}`\n : \"\";\n stepDone(out, `Claude auth: ${WHITE_BOLD}${who}${RST}${plan}`);\n return;\n }\n if (\n process.env.ANTHROPIC_API_KEY !== undefined &&\n process.env.ANTHROPIC_API_KEY.length > 0\n ) {\n stepDone(out, `Claude auth: ${WHITE_BOLD}ANTHROPIC_API_KEY${RST} set`);\n return;\n }\n // Not blocking — just report and show the two paths.\n stepActive(out, `Claude auth: ${DIM}not signed in${RST}`);\n for (const line of UNAUTHENTICATED_MESSAGE.split(\"\\n\")) {\n out.write(` ${DIM}\\u2502 ${line}${RST}\\n`);\n }\n}\n\n// ─── Guide installation ──────────────────────────────────────────────\n\ninterface InstallGuidesOptions {\n claudeDir: string;\n guidesDir: string;\n}\n\ninterface InstallGuidesResult {\n anyChanges: boolean;\n filesWritten: string[];\n}\n\n/**\n * Copy the two guide files into `~/.claude/` and append an `@import`\n * line to `~/.claude/CLAUDE.md`. Every step is idempotent:\n *\n * - Guide files are compared by bytes before we write. If the content\n * matches the bundled version, we skip (so `setup` doesn't cause a\n * spurious mtime bump on every invocation).\n * - The import line is appended only if `CLAUDE.md` doesn't already\n * contain the exact `@~/.claude/codealmanac.md` token on a line by\n * itself. We don't try to parse the file — any mention of the token\n * on a non-comment line is treated as \"already present\".\n *\n * Returns a summary the caller uses to decide whether to say \"installed\"\n * or \"already installed\" in the TUI.\n */\nasync function installGuides(\n options: InstallGuidesOptions,\n): Promise<InstallGuidesResult> {\n await mkdir(options.claudeDir, { recursive: true });\n\n const srcMini = path.join(options.guidesDir, \"mini.md\");\n const srcRef = path.join(options.guidesDir, \"reference.md\");\n if (!existsSync(srcMini)) {\n throw new Error(`missing bundled guide: ${srcMini}`);\n }\n if (!existsSync(srcRef)) {\n throw new Error(`missing bundled guide: ${srcRef}`);\n }\n\n const destMini = path.join(options.claudeDir, \"codealmanac.md\");\n const destRef = path.join(options.claudeDir, \"codealmanac-reference.md\");\n\n const miniChanged = await copyIfChanged(srcMini, destMini);\n const refChanged = await copyIfChanged(srcRef, destRef);\n\n const claudeMd = path.join(options.claudeDir, \"CLAUDE.md\");\n const importChanged = await ensureImport(claudeMd);\n\n const filesWritten: string[] = [];\n if (miniChanged) filesWritten.push(\"codealmanac.md\");\n if (refChanged) filesWritten.push(\"codealmanac-reference.md\");\n if (importChanged) filesWritten.push(\"CLAUDE.md\");\n\n return { anyChanges: filesWritten.length > 0, filesWritten };\n}\n\nasync function copyIfChanged(src: string, dest: string): Promise<boolean> {\n const srcBytes = await readFile(src);\n if (existsSync(dest)) {\n try {\n const destBytes = await readFile(dest);\n if (srcBytes.equals(destBytes)) return false;\n } catch {\n // Fall through to write.\n }\n }\n await copyFile(src, dest);\n return true;\n}\n\n/** The exact import line we manage. Changing this requires updating\n * uninstall too. */\nexport const IMPORT_LINE = \"@~/.claude/codealmanac.md\";\n\n/**\n * Append the import line to `~/.claude/CLAUDE.md` if it isn't already\n * present. Creates the file if absent. Returns true when we wrote, false\n * when the line was already there.\n *\n * We match on `@~/.claude/codealmanac.md` appearing on any non-empty\n * line (trimmed). This catches both the bare line we write and any\n * user-edited variant (comments, trailing whitespace). We deliberately\n * do NOT try to repair a user who deleted the newline — that's their\n * file to shape.\n */\nasync function ensureImport(claudeMdPath: string): Promise<boolean> {\n let existing = \"\";\n if (existsSync(claudeMdPath)) {\n existing = await readFile(claudeMdPath, \"utf8\");\n }\n if (hasImportLine(existing)) return false;\n\n const sep =\n existing.length === 0 ? \"\" : existing.endsWith(\"\\n\") ? \"\\n\" : \"\\n\\n\";\n const body = `${existing}${sep}${IMPORT_LINE}\\n`;\n await writeFile(claudeMdPath, body, \"utf8\");\n return true;\n}\n\nexport function hasImportLine(contents: string): boolean {\n // Match line-starts-with-token rather than exact-line equality so a\n // user who annotated the import line (`@~/.claude/codealmanac.md #\n // codealmanac`) doesn't cause us to re-append a duplicate below.\n // The trailing-character check rules out accidental matches on a\n // longer line like `@~/.claude/codealmanac.md-extra`.\n const lines = contents.split(/\\r?\\n/).map((l) => l.trim());\n return lines.some((line) => {\n if (line === IMPORT_LINE) return true;\n if (!line.startsWith(IMPORT_LINE)) return false;\n const next = line[IMPORT_LINE.length];\n return next === \" \" || next === \"\\t\";\n });\n}\n\n// ─── Interactive prompt ──────────────────────────────────────────────\n\ntype InstallDecision = \"install\" | \"skip\";\n\n/**\n * Minimal `[Y/n]` prompt. No raw mode, no cursor — just readline. The\n * MCP setup uses a fancy arrow-key TUI for multi-choice; we only have\n * binary decisions here, so a line-reader prompt is clearer and doesn't\n * fight with the step-indicator rendering above it.\n */\nfunction confirm(\n out: NodeJS.WritableStream,\n question: string,\n defaultYes: boolean,\n): Promise<InstallDecision> {\n return new Promise((resolve) => {\n const hint = defaultYes ? \"[Y/n]\" : \"[y/N]\";\n out.write(` ${BLUE}\\u25c6${RST} ${question} ${DIM}${hint}${RST} `);\n\n let buf = \"\";\n const onData = (chunk: Buffer): void => {\n buf += chunk.toString(\"utf8\");\n const nl = buf.indexOf(\"\\n\");\n if (nl === -1) return;\n process.stdin.removeListener(\"data\", onData);\n process.stdin.pause();\n\n const answer = buf.slice(0, nl).trim().toLowerCase();\n const accepted =\n answer.length === 0\n ? defaultYes\n : answer === \"y\" || answer === \"yes\";\n resolve(accepted ? \"install\" : \"skip\");\n };\n\n process.stdin.resume();\n process.stdin.on(\"data\", onData);\n });\n}\n\nfunction promptText(\n out: NodeJS.WritableStream,\n question: string,\n defaultValue: string,\n): Promise<string> {\n return new Promise((resolve) => {\n out.write(\n ` ${BLUE}\\u25c6${RST} ${question} ${DIM}[${defaultValue}]${RST} `,\n );\n\n let buf = \"\";\n const onData = (chunk: Buffer): void => {\n buf += chunk.toString(\"utf8\");\n const nl = buf.indexOf(\"\\n\");\n if (nl === -1) return;\n process.stdin.removeListener(\"data\", onData);\n process.stdin.pause();\n\n const answer = buf.slice(0, nl).trim().toLowerCase();\n resolve(answer.length === 0 ? defaultValue : answer);\n };\n\n process.stdin.resume();\n process.stdin.on(\"data\", onData);\n });\n}\n\n// ─── Guides path resolution ──────────────────────────────────────────\n\n/**\n * Locate `guides/` relative to the installed package. Mirrors\n * `resolvePromptsDir` from `src/agent/prompts.ts`.\n *\n * Two runtime layouts to handle:\n *\n * 1. **Bundled dist.** `dist/codealmanac.js` → walk one level up →\n * `guides/`.\n * 2. **Source (tests / tsx).** `src/commands/setup.ts` → walk two\n * levels up → `guides/`.\n *\n * We also try `createRequire` to resolve the package root from the\n * `codealmanac/package.json` manifest, as a belt-and-suspenders fallback\n * for unusual install layouts (monorepo hoisting, etc.). That path is\n * only exercised when the direct walk-up fails.\n */\nexport function resolveGuidesDir(): string {\n const here = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(here, \"..\", \"guides\"), // dist layout\n path.resolve(here, \"..\", \"..\", \"guides\"), // src layout\n path.resolve(here, \"..\", \"..\", \"..\", \"guides\"),\n ];\n for (const dir of candidates) {\n if (looksLikeGuidesDir(dir)) return dir;\n }\n // Fallback: resolve via the package.json of the currently-running\n // codealmanac. createRequire lets us ask Node's resolver rather than\n // guessing at directory layouts.\n try {\n const require = createRequire(import.meta.url);\n const pkgJson = require.resolve(\"codealmanac/package.json\");\n const guides = path.join(path.dirname(pkgJson), \"guides\");\n if (looksLikeGuidesDir(guides)) return guides;\n } catch {\n // Ignore — we'll throw with the candidate list below.\n }\n throw new Error(\n \"could not locate bundled guides/ directory. Tried:\\n\" +\n candidates.map((c) => ` - ${c}`).join(\"\\n\"),\n );\n}\n\nfunction looksLikeGuidesDir(dir: string): boolean {\n return existsSync(path.join(dir, \"mini.md\"));\n}\n","import { execFile } from \"node:child_process\";\nimport { createRequire } from \"node:module\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n/**\n * Return the directory of the currently-running codealmanac install by\n * walking up from this module's file to the nearest `package.json` whose\n * `name` is `codealmanac`. Returns the empty string when the walk fails.\n */\nexport function detectCurrentInstallPath(): string {\n try {\n const req = createRequire(import.meta.url);\n const here = fileURLToPath(import.meta.url);\n let dir = path.dirname(here);\n for (let i = 0; i < 6; i++) {\n const pkgPath = path.join(dir, \"package.json\");\n try {\n const raw = req(\"fs\").readFileSync(pkgPath, \"utf-8\") as string;\n const pkg = JSON.parse(raw) as { name?: unknown };\n if (pkg.name === \"codealmanac\") return dir;\n } catch {\n // keep walking\n }\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n } catch {\n // import.meta.url unavailable — not ephemeral for our purposes.\n }\n return \"\";\n}\n\n/**\n * Return true when the given install path looks ephemeral.\n *\n * Ephemeral locations we recognize:\n * - `~/.npm/_npx/` — npm's npx cache (GC'd on version bumps or\n * `npm cache clean`)\n * - `~/.local/share/pnpm/dlx/` — pnpm's dlx (like npx) cache\n * - `/tmp/` or `/var/folders/` — common CI / temp paths\n *\n * A global install (`~/.nvm/.../lib/node_modules/`, `/usr/local/lib/...`,\n * `~/.local/lib/node_modules/`) is NOT ephemeral.\n */\nexport function detectEphemeral(installPath: string): boolean {\n if (installPath.length === 0) return false;\n const home = homedir();\n if (installPath.startsWith(path.join(home, \".npm\", \"_npx\"))) return true;\n if (\n installPath.startsWith(path.join(home, \".local\", \"share\", \"pnpm\", \"dlx\"))\n ) return true;\n if (installPath.startsWith(\"/tmp/\")) return true;\n if (installPath.startsWith(\"/var/folders/\")) return true;\n return false;\n}\n\n/**\n * Spawn `npm install -g codealmanac@latest` in a child process and wait\n * for it to finish. Rejects on non-zero exit or spawn error.\n */\nexport function spawnGlobalInstall(): Promise<void> {\n return new Promise((resolve, reject) => {\n execFile(\n \"npm\",\n [\"install\", \"-g\", \"codealmanac@latest\"],\n { shell: false },\n (err, _stdout, stderr) => {\n if (err !== null) {\n reject(\n new Error(\n stderr.length > 0\n ? stderr.trim().split(\"\\n\")[0] ?? err.message\n : err.message,\n ),\n );\n } else {\n resolve();\n }\n },\n );\n });\n}\n","import { existsSync, readdirSync } from \"node:fs\";\nimport path from \"node:path\";\n\nconst RST = \"\\x1b[0m\";\nconst BOLD = \"\\x1b[1m\";\nconst DIM = \"\\x1b[2m\";\nconst WHITE_BOLD = \"\\x1b[1;37m\";\nconst BLUE = \"\\x1b[38;5;75m\";\nconst BLUE_DIM = \"\\x1b[38;5;69m\";\n\n/**\n * Print the \"Next steps\" box. When `existingPageCount` is greater than 0,\n * the current working directory already has a wiki with committed pages.\n * In that case we skip the `almanac bootstrap` step and tell the user to\n * start querying.\n */\nexport function printNextSteps(\n out: NodeJS.WritableStream,\n existingPageCount: number,\n): void {\n const innerW = 62;\n const vis = (s: string): number =>\n s.replace(/\\x1b\\[[0-9;]*m/g, \"\").length;\n const row = (content: string): string => {\n const padding = Math.max(0, innerW - vis(content));\n return ` ${BLUE_DIM}\\u2502${RST}${content}${\" \".repeat(padding)}${BLUE_DIM}\\u2502${RST}\\n`;\n };\n const empty = row(\"\");\n\n out.write(` ${BLUE_DIM}\\u256d${\"─\".repeat(innerW)}\\u256e${RST}\\n`);\n out.write(empty);\n out.write(row(` ${WHITE_BOLD}Next steps${RST}`));\n out.write(empty);\n\n if (existingPageCount > 0) {\n out.write(\n row(\n ` ${BLUE}\\u25c7${RST} This repo already has a wiki ${DIM}(${existingPageCount} page${existingPageCount === 1 ? \"\" : \"s\"})${RST}`,\n ),\n );\n out.write(empty);\n out.write(row(` ${BLUE}1.${RST} Start querying your wiki:`));\n out.write(row(` ${BOLD}almanac search --mentions <file>${RST}`));\n out.write(\n row(` ${BLUE}2.${RST} Work normally — capture runs on session end`),\n );\n } else {\n out.write(\n row(` ${BLUE}1.${RST} ${BOLD}cd${RST} into a repo you want to document`),\n );\n out.write(\n row(\n ` ${BLUE}2.${RST} ${BOLD}almanac bootstrap${RST} ${DIM}# scaffold the wiki${RST}`,\n ),\n );\n out.write(\n row(` ${BLUE}3.${RST} Work normally — capture runs on session end`),\n );\n }\n\n out.write(empty);\n out.write(` ${BLUE_DIM}\\u2570${\"─\".repeat(innerW)}\\u256f${RST}\\n\\n`);\n}\n\n/**\n * Count `.md` files in `.almanac/pages/` under the current working\n * directory or any parent. Returns 0 when no wiki is found or the pages\n * directory is empty.\n */\nexport function countExistingPages(cwd: string): number {\n try {\n let dir = cwd;\n for (let i = 0; i < 10; i++) {\n const pagesDir = path.join(dir, \".almanac\", \"pages\");\n if (existsSync(pagesDir)) {\n try {\n const entries = readdirSync(pagesDir);\n return entries.filter((e) => e.endsWith(\".md\")).length;\n } catch {\n return 0;\n }\n }\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n } catch {\n // Swallow — never crash setup because of this.\n }\n return 0;\n}\n"],"mappings":"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","names":["existsSync","createRequire","homedir","path","fileURLToPath","path","RST","DIM","WHITE_BOLD","BLUE","path","homedir","existsSync","fileURLToPath","require","createRequire"]}
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  runInternalUpdateCheck,
7
7
  scheduleBackgroundUpdateCheck
8
- } from "./chunk-QHQ6YH7U.js";
8
+ } from "./chunk-V3QOQSXI.js";
9
9
  import {
10
10
  BLUE,
11
11
  BOLD,
@@ -14,13 +14,16 @@ import {
14
14
  } from "./chunk-FM3VRDK7.js";
15
15
  import {
16
16
  runSetup
17
- } from "./chunk-3LC55TG6.js";
18
- import "./chunk-Z4MWLVS2.js";
17
+ } from "./chunk-ZDJSJIB6.js";
18
+ import "./chunk-447U3GQJ.js";
19
+ import "./chunk-SSYMRT4I.js";
19
20
  import {
20
- getConfigPath,
21
21
  getStatePath,
22
22
  isNewer
23
- } from "./chunk-AXFPUHBN.js";
23
+ } from "./chunk-F53U6JQG.js";
24
+ import {
25
+ getConfigPath
26
+ } from "./chunk-WRUSDYYE.js";
24
27
  import "./chunk-7JUX4ADQ.js";
25
28
 
26
29
  // src/cli.ts
@@ -270,7 +273,7 @@ async function run(argv, deps = {}) {
270
273
  if (await tryRunSqliteFreeCommand(argv.slice(2), runSetupFn)) {
271
274
  return;
272
275
  }
273
- const { registerCommands } = await import("./register-commands-JHC2OFKM.js");
276
+ const { registerCommands } = await import("./register-commands-7SKQLQW4.js");
274
277
  registerCommands(program);
275
278
  configureGroupedHelp(program);
276
279
  await program.parseAsync(argv);
@@ -283,8 +286,10 @@ function isRootVersionInvocation(args) {
283
286
  return args.length === 1 && (args[0] === "--version" || args[0] === "-v");
284
287
  }
285
288
  function parseSetupFlags(args) {
289
+ const agentIdx = args.indexOf("--agent");
286
290
  return {
287
291
  yes: args.includes("--yes") || args.includes("-y"),
292
+ agent: agentIdx === -1 ? void 0 : args[agentIdx + 1],
288
293
  skipHook: args.includes("--skip-hook"),
289
294
  skipGuides: args.includes("--skip-guides")
290
295
  };
@@ -320,9 +325,9 @@ async function tryRunSqliteFreeCommand(args, runSetupFn) {
320
325
  return true;
321
326
  }
322
327
  if (command === "hook") {
323
- const { runHookInstall, runHookStatus, runHookUninstall } = await import("./hook-CRJMWSSO.js");
328
+ const { runHookInstall, runHookStatus, runHookUninstall } = await import("./hook-2NP3UE7U.js");
324
329
  if (subcommand === "install") {
325
- emit(await runHookInstall());
330
+ emit(await runHookInstall({ source: parseHookSource(args.slice(2)) }));
326
331
  return true;
327
332
  }
328
333
  if (subcommand === "uninstall") {
@@ -335,13 +340,33 @@ async function tryRunSqliteFreeCommand(args, runSetupFn) {
335
340
  }
336
341
  return false;
337
342
  }
343
+ if (command === "agents") {
344
+ const { runAgentsList } = await import("./agents-A4II4YJC.js");
345
+ if (subcommand === "list" || subcommand === void 0) {
346
+ emit(await runAgentsList());
347
+ return true;
348
+ }
349
+ return false;
350
+ }
351
+ if (command === "set") {
352
+ const { runSetAgentModel, runSetDefaultAgent } = await import("./agents-A4II4YJC.js");
353
+ if (subcommand === "default-agent") {
354
+ emit(await runSetDefaultAgent({ provider: args[2] ?? "" }));
355
+ return true;
356
+ }
357
+ if (subcommand === "model") {
358
+ emit(await runSetAgentModel({ provider: args[2] ?? "", model: args[3] }));
359
+ return true;
360
+ }
361
+ return false;
362
+ }
338
363
  if (command === "update") {
339
- const { runUpdate } = await import("./update-IL243I4E.js");
364
+ const { runUpdate } = await import("./update-RAF7QRYF.js");
340
365
  emit(await runUpdate(parseUpdateFlags(args.slice(1))));
341
366
  return true;
342
367
  }
343
368
  if (command === "doctor") {
344
- const { runDoctor } = await import("./doctor-ODFNJUKH.js");
369
+ const { runDoctor } = await import("./doctor-BTH7GCFV.js");
345
370
  emit(await runDoctor({
346
371
  cwd: process.cwd(),
347
372
  ...parseDoctorFlags(args.slice(1))
@@ -349,12 +374,20 @@ async function tryRunSqliteFreeCommand(args, runSetupFn) {
349
374
  return true;
350
375
  }
351
376
  if (command === "uninstall") {
352
- const { runUninstall } = await import("./uninstall-HE2Z2LN2.js");
377
+ const { runUninstall } = await import("./uninstall-FDIOBAAR.js");
353
378
  emit(await runUninstall(parseUninstallFlags(args.slice(1))));
354
379
  return true;
355
380
  }
356
381
  return false;
357
382
  }
383
+ function parseHookSource(args) {
384
+ const idx = args.indexOf("--source");
385
+ const value = idx === -1 ? void 0 : args[idx + 1];
386
+ if (value === "claude" || value === "codex" || value === "cursor" || value === "all") {
387
+ return value;
388
+ }
389
+ return void 0;
390
+ }
358
391
  function readPackageVersion() {
359
392
  try {
360
393
  const require2 = createRequire2(import.meta.url);
@@ -369,11 +402,17 @@ function readPackageVersion() {
369
402
  function tryParseSetupShortcut(args) {
370
403
  if (args.length === 0) return {};
371
404
  const opts = {};
372
- for (const arg of args) {
405
+ for (let i = 0; i < args.length; i++) {
406
+ const arg = args[i];
373
407
  if (arg === "--yes" || arg === "-y") {
374
408
  opts.yes = true;
375
409
  continue;
376
410
  }
411
+ if (arg === "--agent") {
412
+ opts.agent = args[i + 1];
413
+ i += 1;
414
+ continue;
415
+ }
377
416
  if (arg === "--skip-hook") {
378
417
  opts.skipHook = true;
379
418
  continue;
@@ -390,4 +429,4 @@ export {
390
429
  run,
391
430
  tryParseSetupShortcut
392
431
  };
393
- //# sourceMappingURL=cli-W3OYVJYH.js.map
432
+ //# sourceMappingURL=cli-CMGYLJSN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts","../src/cli/help.ts","../src/update/announce.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport { basename } from \"node:path\";\n\nimport { Command } from \"commander\";\n\nimport { runSetup } from \"./commands/setup.js\";\nimport { configureGroupedHelp } from \"./cli/help.js\";\nimport { emit } from \"./cli/helpers.js\";\nimport { announceUpdateIfAvailable } from \"./update/announce.js\";\nimport {\n runInternalUpdateCheck,\n scheduleBackgroundUpdateCheck,\n} from \"./update/schedule.js\";\n\n/**\n * Optional dependency overrides for `run`. Tests use these to avoid\n * spawning the real setup wizard, the real update background check,\n * and the real update banner. Production callers pass nothing.\n */\nexport interface RunDeps {\n /** Replace the setup wizard (bare `codealmanac` / `almanac setup`). */\n runSetup?: typeof runSetup;\n /** Replace the pre-command update-nag banner. */\n announceUpdate?: (stderr: NodeJS.WritableStream) => void;\n /** Replace the post-command background update check scheduler. */\n scheduleUpdateCheck?: (argv: string[]) => void;\n /** Replace the internal update-check worker (run on --internal-check-updates). */\n runInternalUpdateCheck?: () => Promise<void>;\n}\n\n/**\n * Process-level CLI entrypoint. This owns invocation-level behavior:\n * update checks, bare `codealmanac` setup routing, Commander creation,\n * grouped help, and parsing. Individual command wiring lives in\n * `src/cli/register-commands.ts`.\n */\nexport async function run(argv: string[], deps: RunDeps = {}): Promise<void> {\n const runSetupFn = deps.runSetup ?? runSetup;\n const announceUpdateFn = deps.announceUpdate ?? announceUpdateIfAvailable;\n const scheduleUpdateCheckFn =\n deps.scheduleUpdateCheck ?? scheduleBackgroundUpdateCheck;\n const runInternalUpdateCheckFn =\n deps.runInternalUpdateCheck ?? runInternalUpdateCheck;\n\n if (argv.slice(2).includes(\"--internal-check-updates\")) {\n await runInternalUpdateCheckFn();\n return;\n }\n\n const programName = getProgramName(argv);\n\n announceUpdateFn(process.stderr);\n scheduleUpdateCheckFn(argv);\n\n const program = new Command();\n program\n .name(programName)\n .description(\n \"codealmanac — a living wiki for codebases, maintained by AI agents\",\n )\n .version(readPackageVersion(), \"-v, --version\", \"print version\");\n\n if (isRootVersionInvocation(argv.slice(2))) {\n await program.parseAsync(argv);\n return;\n }\n\n if (programName === \"codealmanac\") {\n const setupInvocation = tryParseSetupShortcut(argv.slice(2));\n if (setupInvocation !== null) {\n emit(await runSetupFn(setupInvocation));\n return;\n }\n }\n\n if (await tryRunSqliteFreeCommand(argv.slice(2), runSetupFn)) {\n return;\n }\n\n const { registerCommands } = await import(\"./cli/register-commands.js\");\n registerCommands(program);\n configureGroupedHelp(program);\n\n await program.parseAsync(argv);\n}\n\nfunction getProgramName(argv: string[]): \"almanac\" | \"codealmanac\" {\n const invoked = argv[1] !== undefined ? basename(argv[1]) : \"almanac\";\n return invoked === \"codealmanac\" ? \"codealmanac\" : \"almanac\";\n}\n\nfunction isRootVersionInvocation(args: string[]): boolean {\n return args.length === 1 && (args[0] === \"--version\" || args[0] === \"-v\");\n}\n\nfunction parseSetupFlags(args: string[]): {\n yes?: boolean;\n agent?: string;\n skipHook?: boolean;\n skipGuides?: boolean;\n} {\n const agentIdx = args.indexOf(\"--agent\");\n return {\n yes: args.includes(\"--yes\") || args.includes(\"-y\"),\n agent: agentIdx === -1 ? undefined : args[agentIdx + 1],\n skipHook: args.includes(\"--skip-hook\"),\n skipGuides: args.includes(\"--skip-guides\"),\n };\n}\n\nfunction parseUpdateFlags(args: string[]): {\n dismiss?: boolean;\n check?: boolean;\n enableNotifier?: boolean;\n disableNotifier?: boolean;\n} {\n return {\n dismiss: args.includes(\"--dismiss\"),\n check: args.includes(\"--check\"),\n enableNotifier: args.includes(\"--enable-notifier\"),\n disableNotifier: args.includes(\"--disable-notifier\"),\n };\n}\n\nfunction parseUninstallFlags(args: string[]): {\n yes?: boolean;\n keepHook?: boolean;\n keepGuides?: boolean;\n} {\n return {\n yes: args.includes(\"--yes\") || args.includes(\"-y\"),\n keepHook: args.includes(\"--keep-hook\"),\n keepGuides: args.includes(\"--keep-guides\"),\n };\n}\n\nfunction parseDoctorFlags(args: string[]): {\n json?: boolean;\n installOnly?: boolean;\n wikiOnly?: boolean;\n} {\n return {\n json: args.includes(\"--json\"),\n installOnly: args.includes(\"--install-only\"),\n wikiOnly: args.includes(\"--wiki-only\"),\n };\n}\n\nasync function tryRunSqliteFreeCommand(\n args: string[],\n runSetupFn: typeof runSetup,\n): Promise<boolean> {\n if (args.includes(\"--help\") || args.includes(\"-h\")) return false;\n\n const [command, subcommand] = args;\n if (command === undefined) return false;\n\n if (command === \"setup\") {\n emit(await runSetupFn(parseSetupFlags(args.slice(1))));\n return true;\n }\n\n if (command === \"hook\") {\n const { runHookInstall, runHookStatus, runHookUninstall } = await import(\n \"./commands/hook.js\"\n );\n if (subcommand === \"install\") {\n emit(await runHookInstall({ source: parseHookSource(args.slice(2)) }));\n return true;\n }\n if (subcommand === \"uninstall\") {\n emit(await runHookUninstall());\n return true;\n }\n if (subcommand === \"status\") {\n emit(await runHookStatus());\n return true;\n }\n return false;\n }\n\n if (command === \"agents\") {\n const { runAgentsList } = await import(\"./commands/agents.js\");\n if (subcommand === \"list\" || subcommand === undefined) {\n emit(await runAgentsList());\n return true;\n }\n return false;\n }\n\n if (command === \"set\") {\n const { runSetAgentModel, runSetDefaultAgent } = await import(\n \"./commands/agents.js\"\n );\n if (subcommand === \"default-agent\") {\n emit(await runSetDefaultAgent({ provider: args[2] ?? \"\" }));\n return true;\n }\n if (subcommand === \"model\") {\n emit(await runSetAgentModel({ provider: args[2] ?? \"\", model: args[3] }));\n return true;\n }\n return false;\n }\n\n if (command === \"update\") {\n const { runUpdate } = await import(\"./commands/update.js\");\n emit(await runUpdate(parseUpdateFlags(args.slice(1))));\n return true;\n }\n\n if (command === \"doctor\") {\n const { runDoctor } = await import(\"./commands/doctor.js\");\n emit(await runDoctor({\n cwd: process.cwd(),\n ...parseDoctorFlags(args.slice(1)),\n }));\n return true;\n }\n\n if (command === \"uninstall\") {\n const { runUninstall } = await import(\"./commands/uninstall.js\");\n emit(await runUninstall(parseUninstallFlags(args.slice(1))));\n return true;\n }\n\n return false;\n}\n\nfunction parseHookSource(\n args: string[],\n): \"claude\" | \"codex\" | \"cursor\" | \"all\" | undefined {\n const idx = args.indexOf(\"--source\");\n const value = idx === -1 ? undefined : args[idx + 1];\n if (\n value === \"claude\" ||\n value === \"codex\" ||\n value === \"cursor\" ||\n value === \"all\"\n ) {\n return value;\n }\n return undefined;\n}\n\nfunction readPackageVersion(): string {\n try {\n const require = createRequire(import.meta.url);\n const pkg = require(\"../package.json\") as { version?: unknown };\n if (typeof pkg.version === \"string\" && pkg.version.length > 0) {\n return pkg.version;\n }\n } catch {\n // Fall back to \"unknown\" rather than crashing the CLI on a broken install.\n }\n return \"unknown\";\n}\n\nexport interface SetupShortcutOptions {\n yes?: boolean;\n agent?: string;\n skipHook?: boolean;\n skipGuides?: boolean;\n}\n\n/**\n * Decide whether a bare `codealmanac [...args]` invocation should route\n * straight to `runSetup` (and if so, with which flags). Returns the\n * options object when it's a setup shortcut, or `null` when Commander\n * should parse the invocation normally.\n */\nexport function tryParseSetupShortcut(args: string[]): SetupShortcutOptions | null {\n if (args.length === 0) return {};\n\n const opts: SetupShortcutOptions = {};\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n if (arg === \"--yes\" || arg === \"-y\") {\n opts.yes = true;\n continue;\n }\n if (arg === \"--agent\") {\n opts.agent = args[i + 1];\n i += 1;\n continue;\n }\n if (arg === \"--skip-hook\") {\n opts.skipHook = true;\n continue;\n }\n if (arg === \"--skip-guides\") {\n opts.skipGuides = true;\n continue;\n }\n return null;\n }\n return opts;\n}\n","import { Command, type Help } from \"commander\";\n\nimport { BLUE, BOLD, DIM, RST } from \"../ansi.js\";\n\nconst HELP_GROUPS: Array<{ title: string; commands: string[] }> = [\n {\n title: \"Query\",\n commands: [\"search\", \"show\", \"health\", \"list\"],\n },\n {\n title: \"Edit\",\n commands: [\"tag\", \"untag\", \"topics\"],\n },\n {\n title: \"Wiki lifecycle\",\n commands: [\"bootstrap\", \"capture\", \"hook\", \"reindex\"],\n },\n {\n title: \"Setup\",\n commands: [\"setup\", \"uninstall\", \"doctor\", \"update\"],\n },\n];\n\n/**\n * Install a custom `formatHelp` that replaces commander's flat\n * \"Commands:\" section with grouped headings. Keeps usage + options +\n * per-command short descriptions; only the commands section changes.\n */\nexport function configureGroupedHelp(program: Command): void {\n program.configureHelp({\n formatHelp(cmd, helper): string {\n if (cmd.parent !== null) {\n return renderDefault(cmd, helper);\n }\n\n const termWidth = helper.padWidth(cmd, helper);\n const helpWidth =\n helper.helpWidth ?? process.stdout.columns ?? 80;\n const itemSepWidth = 2;\n\n const out: string[] = [];\n out.push(`${BOLD}Usage:${RST} ${helper.commandUsage(cmd)}\\n`);\n\n const description = helper.commandDescription(cmd);\n if (description.length > 0) {\n out.push(\n helper.wrap(description, helpWidth, 0) + \"\\n\",\n );\n }\n\n const optionList = helper\n .visibleOptions(cmd)\n .map((o) => {\n const term = helper.optionTerm(o);\n const pad = \" \".repeat(Math.max(0, termWidth - term.length) + itemSepWidth);\n return `${BLUE}${term}${RST}${pad}${DIM}${helper.optionDescription(o)}${RST}`;\n });\n if (optionList.length > 0) {\n out.push(`${BOLD}Options:${RST}`);\n for (const l of optionList) out.push(` ${l}`);\n out.push(\"\");\n }\n\n const visible = helper.visibleCommands(cmd);\n const byName = new Map<string, (typeof visible)[number]>();\n for (const c of visible) byName.set(c.name(), c);\n\n for (const group of HELP_GROUPS) {\n const members = group.commands\n .map((n) => byName.get(n))\n .filter((c): c is (typeof visible)[number] => c !== undefined);\n if (members.length === 0) continue;\n out.push(`${BOLD}${group.title}:${RST}`);\n for (const c of members) {\n const term = helper.subcommandTerm(c);\n const desc = helper.subcommandDescription(c);\n const padding = Math.max(\n 0,\n termWidth - term.length + itemSepWidth,\n );\n out.push(` ${BLUE}${term}${RST}${\" \".repeat(padding)}${DIM}${desc}${RST}`);\n byName.delete(c.name());\n }\n out.push(\"\");\n }\n\n byName.delete(\"help\");\n if (byName.size > 0) {\n out.push(`${BOLD}Other:${RST}`);\n for (const c of byName.values()) {\n const term = helper.subcommandTerm(c);\n const desc = helper.subcommandDescription(c);\n const padding = Math.max(\n 0,\n termWidth - term.length + itemSepWidth,\n );\n out.push(` ${BLUE}${term}${RST}${\" \".repeat(padding)}${DIM}${desc}${RST}`);\n }\n out.push(\"\");\n }\n\n return out.join(\"\\n\");\n },\n });\n}\n\nfunction renderDefault(cmd: Command, helper: Help): string {\n const termWidth = helper.padWidth(cmd, helper);\n const helpWidth = helper.helpWidth ?? process.stdout.columns ?? 80;\n const itemSepWidth = 2;\n\n const lines: string[] = [`${BOLD}Usage:${RST} ${helper.commandUsage(cmd)}\\n`];\n const description = helper.commandDescription(cmd);\n if (description.length > 0) {\n lines.push(helper.wrap(description, helpWidth, 0) + \"\\n\");\n }\n\n const args = helper.visibleArguments(cmd).map((a) => {\n const term = helper.argumentTerm(a);\n const pad = \" \".repeat(Math.max(0, termWidth - term.length) + itemSepWidth);\n return `${BLUE}${term}${RST}${pad}${DIM}${helper.argumentDescription(a)}${RST}`;\n });\n if (args.length > 0) {\n lines.push(`${BOLD}Arguments:${RST}`);\n for (const a of args) lines.push(` ${a}`);\n lines.push(\"\");\n }\n\n const opts = helper.visibleOptions(cmd).map((o) => {\n const term = helper.optionTerm(o);\n const pad = \" \".repeat(Math.max(0, termWidth - term.length) + itemSepWidth);\n return `${BLUE}${term}${RST}${pad}${DIM}${helper.optionDescription(o)}${RST}`;\n });\n if (opts.length > 0) {\n lines.push(`${BOLD}Options:${RST}`);\n for (const o of opts) lines.push(` ${o}`);\n lines.push(\"\");\n }\n\n const subs = helper.visibleCommands(cmd).map((c) => {\n const term = helper.subcommandTerm(c);\n const pad = \" \".repeat(Math.max(0, termWidth - term.length) + itemSepWidth);\n return `${BLUE}${term}${RST}${pad}${DIM}${helper.subcommandDescription(c)}${RST}`;\n });\n if (subs.length > 0) {\n lines.push(`${BOLD}Commands:${RST}`);\n for (const s of subs) lines.push(` ${s}`);\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\");\n}\n","import { readFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\n\nimport { getConfigPath } from \"./config.js\";\nimport { isNewer } from \"./semver.js\";\nimport { getStatePath, type UpdateState } from \"./state.js\";\n\n/**\n * Pre-command update-nag banner. Runs synchronously at the very top of\n * every `run()` invocation, before commander even touches argv. Prints\n * one line to stderr if:\n *\n * 1. `~/.almanac/update-state.json` exists and parses.\n * 2. `latest_version` is strictly newer than `installed_version`.\n * 3. `latest_version` is NOT in `dismissed_versions`.\n * 4. `~/.almanac/config.json`.`update_notifier` is not `false`.\n *\n * Otherwise silent. Deliberately synchronous and filesystem-blocking:\n * this runs in the CLI critical path and waiting on a Promise would\n * force every command to become async upfront. The files are tiny\n * (<1KB each); a sync read is cheap.\n *\n * Why stderr: agents and scripts parse stdout; stderr is the\n * conventional channel for diagnostics and nags. A tool piping\n * `almanac search` into `xargs` shouldn't see the banner mixed into\n * its slug list. Users running interactively see stderr anyway, so\n * the nag is visible in practice.\n */\n\nexport interface AnnounceOptions {\n statePath?: string;\n configPath?: string;\n /** Override for tests — normally reads from package.json at import time. */\n installedVersion?: string;\n /** Enable ANSI coloring regardless of isTTY. Tests pass `false`. */\n color?: boolean;\n}\n\nconst RST = \"\\x1b[0m\";\nconst BOLD = \"\\x1b[1m\";\nconst YELLOW = \"\\x1b[33m\";\n\nexport function announceUpdateIfAvailable(\n stderr: NodeJS.WritableStream,\n opts: AnnounceOptions = {},\n): void {\n const statePath = opts.statePath ?? getStatePath();\n const configPath = opts.configPath ?? getConfigPath();\n const installed = opts.installedVersion ?? readInstalledVersion();\n\n // Config gate. Must be checked before state: a user who disabled the\n // notifier shouldn't pay even a state-file read.\n if (!shouldNotify(configPath)) return;\n\n const state = readStateSync(statePath);\n if (state === null) return;\n if (state.latest_version.length === 0) return;\n if (!isNewer(state.latest_version, installed)) return;\n if (state.dismissed_versions.includes(state.latest_version)) return;\n\n const useColor =\n opts.color ?? (process.stderr.isTTY === true && !(\"NO_COLOR\" in process.env));\n const warn = useColor ? `${YELLOW}${BOLD}\\u26a0${RST}` : \"!\";\n const cmd = useColor ? `${BOLD}almanac update${RST}` : \"almanac update\";\n stderr.write(\n `${warn} codealmanac ${state.latest_version} available ` +\n `(you're on ${installed}) — run: ${cmd}\\n`,\n );\n}\n\n/**\n * Sync-read the state file. Returns `null` when missing, empty, or\n * malformed — the announce path MUST NOT throw into the CLI critical\n * path. Avoids the `async readState` used by the worker because\n * `run()` would otherwise need `await announceUpdateIfAvailable(...)`\n * on every invocation, which turns into a multi-millisecond penalty\n * on commands that don't care.\n */\nfunction readStateSync(path: string): UpdateState | null {\n let raw: string;\n try {\n raw = readFileSync(path, \"utf8\");\n } catch {\n return null;\n }\n const trimmed = raw.trim();\n if (trimmed.length === 0) return null;\n try {\n const parsed = JSON.parse(trimmed) as Partial<UpdateState>;\n return {\n last_check_at:\n typeof parsed.last_check_at === \"number\" ? parsed.last_check_at : 0,\n installed_version:\n typeof parsed.installed_version === \"string\"\n ? parsed.installed_version\n : \"\",\n latest_version:\n typeof parsed.latest_version === \"string\" ? parsed.latest_version : \"\",\n dismissed_versions: Array.isArray(parsed.dismissed_versions)\n ? parsed.dismissed_versions.filter(\n (v): v is string => typeof v === \"string\",\n )\n : [],\n };\n } catch {\n return null;\n }\n}\n\nfunction shouldNotify(configPath: string): boolean {\n let raw: string;\n try {\n raw = readFileSync(configPath, \"utf8\");\n } catch {\n return true; // no config file → default notify on\n }\n const trimmed = raw.trim();\n if (trimmed.length === 0) return true;\n try {\n const parsed = JSON.parse(trimmed) as { update_notifier?: unknown };\n if (parsed.update_notifier === false) return false;\n return true;\n } catch {\n return true;\n }\n}\n\nfunction readInstalledVersion(): string {\n // Dev: `src/update/announce.ts` → `../../package.json`. Bundled:\n // `dist/codealmanac.js` → `../package.json`. Try both.\n try {\n const require = createRequire(import.meta.url);\n const pkg = require(\"../../package.json\") as { version?: unknown };\n if (typeof pkg.version === \"string\" && pkg.version.length > 0) {\n return pkg.version;\n }\n } catch {\n // Fall through.\n }\n try {\n const require = createRequire(import.meta.url);\n const pkg = require(\"../package.json\") as { version?: unknown };\n if (typeof pkg.version === \"string\" && pkg.version.length > 0) {\n return pkg.version;\n }\n } catch {\n // Fall through.\n }\n return \"unknown\";\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,iBAAAA,sBAAqB;AAC9B,SAAS,gBAAgB;AAEzB,SAAS,eAAe;;;ACCxB,IAAM,cAA4D;AAAA,EAChE;AAAA,IACE,OAAO;AAAA,IACP,UAAU,CAAC,UAAU,QAAQ,UAAU,MAAM;AAAA,EAC/C;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,UAAU,CAAC,OAAO,SAAS,QAAQ;AAAA,EACrC;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,UAAU,CAAC,aAAa,WAAW,QAAQ,SAAS;AAAA,EACtD;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,UAAU,CAAC,SAAS,aAAa,UAAU,QAAQ;AAAA,EACrD;AACF;AAOO,SAAS,qBAAqB,SAAwB;AAC3D,UAAQ,cAAc;AAAA,IACpB,WAAW,KAAK,QAAgB;AAC9B,UAAI,IAAI,WAAW,MAAM;AACvB,eAAO,cAAc,KAAK,MAAM;AAAA,MAClC;AAEA,YAAM,YAAY,OAAO,SAAS,KAAK,MAAM;AAC7C,YAAM,YACJ,OAAO,aAAa,QAAQ,OAAO,WAAW;AAChD,YAAM,eAAe;AAErB,YAAM,MAAgB,CAAC;AACvB,UAAI,KAAK,GAAG,IAAI,SAAS,GAAG,IAAI,OAAO,aAAa,GAAG,CAAC;AAAA,CAAI;AAE5D,YAAM,cAAc,OAAO,mBAAmB,GAAG;AACjD,UAAI,YAAY,SAAS,GAAG;AAC1B,YAAI;AAAA,UACF,OAAO,KAAK,aAAa,WAAW,CAAC,IAAI;AAAA,QAC3C;AAAA,MACF;AAEA,YAAM,aAAa,OAChB,eAAe,GAAG,EAClB,IAAI,CAAC,MAAM;AACV,cAAM,OAAO,OAAO,WAAW,CAAC;AAChC,cAAM,MAAM,IAAI,OAAO,KAAK,IAAI,GAAG,YAAY,KAAK,MAAM,IAAI,YAAY;AAC1E,eAAO,GAAG,IAAI,GAAG,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,OAAO,kBAAkB,CAAC,CAAC,GAAG,GAAG;AAAA,MAC7E,CAAC;AACH,UAAI,WAAW,SAAS,GAAG;AACzB,YAAI,KAAK,GAAG,IAAI,WAAW,GAAG,EAAE;AAChC,mBAAW,KAAK,WAAY,KAAI,KAAK,KAAK,CAAC,EAAE;AAC7C,YAAI,KAAK,EAAE;AAAA,MACb;AAEA,YAAM,UAAU,OAAO,gBAAgB,GAAG;AAC1C,YAAM,SAAS,oBAAI,IAAsC;AACzD,iBAAW,KAAK,QAAS,QAAO,IAAI,EAAE,KAAK,GAAG,CAAC;AAE/C,iBAAW,SAAS,aAAa;AAC/B,cAAM,UAAU,MAAM,SACnB,IAAI,CAAC,MAAM,OAAO,IAAI,CAAC,CAAC,EACxB,OAAO,CAAC,MAAqC,MAAM,MAAS;AAC/D,YAAI,QAAQ,WAAW,EAAG;AAC1B,YAAI,KAAK,GAAG,IAAI,GAAG,MAAM,KAAK,IAAI,GAAG,EAAE;AACvC,mBAAW,KAAK,SAAS;AACvB,gBAAM,OAAO,OAAO,eAAe,CAAC;AACpC,gBAAM,OAAO,OAAO,sBAAsB,CAAC;AAC3C,gBAAM,UAAU,KAAK;AAAA,YACnB;AAAA,YACA,YAAY,KAAK,SAAS;AAAA,UAC5B;AACA,cAAI,KAAK,KAAK,IAAI,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,OAAO,OAAO,CAAC,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,EAAE;AAC1E,iBAAO,OAAO,EAAE,KAAK,CAAC;AAAA,QACxB;AACA,YAAI,KAAK,EAAE;AAAA,MACb;AAEA,aAAO,OAAO,MAAM;AACpB,UAAI,OAAO,OAAO,GAAG;AACnB,YAAI,KAAK,GAAG,IAAI,SAAS,GAAG,EAAE;AAC9B,mBAAW,KAAK,OAAO,OAAO,GAAG;AAC/B,gBAAM,OAAO,OAAO,eAAe,CAAC;AACpC,gBAAM,OAAO,OAAO,sBAAsB,CAAC;AAC3C,gBAAM,UAAU,KAAK;AAAA,YACnB;AAAA,YACA,YAAY,KAAK,SAAS;AAAA,UAC5B;AACA,cAAI,KAAK,KAAK,IAAI,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,OAAO,OAAO,CAAC,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,EAAE;AAAA,QAC5E;AACA,YAAI,KAAK,EAAE;AAAA,MACb;AAEA,aAAO,IAAI,KAAK,IAAI;AAAA,IACtB;AAAA,EACF,CAAC;AACH;AAEA,SAAS,cAAc,KAAc,QAAsB;AACzD,QAAM,YAAY,OAAO,SAAS,KAAK,MAAM;AAC7C,QAAM,YAAY,OAAO,aAAa,QAAQ,OAAO,WAAW;AAChE,QAAM,eAAe;AAErB,QAAM,QAAkB,CAAC,GAAG,IAAI,SAAS,GAAG,IAAI,OAAO,aAAa,GAAG,CAAC;AAAA,CAAI;AAC5E,QAAM,cAAc,OAAO,mBAAmB,GAAG;AACjD,MAAI,YAAY,SAAS,GAAG;AAC1B,UAAM,KAAK,OAAO,KAAK,aAAa,WAAW,CAAC,IAAI,IAAI;AAAA,EAC1D;AAEA,QAAM,OAAO,OAAO,iBAAiB,GAAG,EAAE,IAAI,CAAC,MAAM;AACnD,UAAM,OAAO,OAAO,aAAa,CAAC;AAClC,UAAM,MAAM,IAAI,OAAO,KAAK,IAAI,GAAG,YAAY,KAAK,MAAM,IAAI,YAAY;AAC1E,WAAO,GAAG,IAAI,GAAG,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,OAAO,oBAAoB,CAAC,CAAC,GAAG,GAAG;AAAA,EAC/E,CAAC;AACD,MAAI,KAAK,SAAS,GAAG;AACnB,UAAM,KAAK,GAAG,IAAI,aAAa,GAAG,EAAE;AACpC,eAAW,KAAK,KAAM,OAAM,KAAK,KAAK,CAAC,EAAE;AACzC,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,QAAM,OAAO,OAAO,eAAe,GAAG,EAAE,IAAI,CAAC,MAAM;AACjD,UAAM,OAAO,OAAO,WAAW,CAAC;AAChC,UAAM,MAAM,IAAI,OAAO,KAAK,IAAI,GAAG,YAAY,KAAK,MAAM,IAAI,YAAY;AAC1E,WAAO,GAAG,IAAI,GAAG,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,OAAO,kBAAkB,CAAC,CAAC,GAAG,GAAG;AAAA,EAC7E,CAAC;AACD,MAAI,KAAK,SAAS,GAAG;AACnB,UAAM,KAAK,GAAG,IAAI,WAAW,GAAG,EAAE;AAClC,eAAW,KAAK,KAAM,OAAM,KAAK,KAAK,CAAC,EAAE;AACzC,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,QAAM,OAAO,OAAO,gBAAgB,GAAG,EAAE,IAAI,CAAC,MAAM;AAClD,UAAM,OAAO,OAAO,eAAe,CAAC;AACpC,UAAM,MAAM,IAAI,OAAO,KAAK,IAAI,GAAG,YAAY,KAAK,MAAM,IAAI,YAAY;AAC1E,WAAO,GAAG,IAAI,GAAG,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,OAAO,sBAAsB,CAAC,CAAC,GAAG,GAAG;AAAA,EACjF,CAAC;AACD,MAAI,KAAK,SAAS,GAAG;AACnB,UAAM,KAAK,GAAG,IAAI,YAAY,GAAG,EAAE;AACnC,eAAW,KAAK,KAAM,OAAM,KAAK,KAAK,CAAC,EAAE;AACzC,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;;;ACvJA,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;AAqC9B,IAAMC,OAAM;AACZ,IAAMC,QAAO;AACb,IAAM,SAAS;AAER,SAAS,0BACd,QACA,OAAwB,CAAC,GACnB;AACN,QAAM,YAAY,KAAK,aAAa,aAAa;AACjD,QAAM,aAAa,KAAK,cAAc,cAAc;AACpD,QAAM,YAAY,KAAK,oBAAoB,qBAAqB;AAIhE,MAAI,CAAC,aAAa,UAAU,EAAG;AAE/B,QAAM,QAAQ,cAAc,SAAS;AACrC,MAAI,UAAU,KAAM;AACpB,MAAI,MAAM,eAAe,WAAW,EAAG;AACvC,MAAI,CAAC,QAAQ,MAAM,gBAAgB,SAAS,EAAG;AAC/C,MAAI,MAAM,mBAAmB,SAAS,MAAM,cAAc,EAAG;AAE7D,QAAM,WACJ,KAAK,UAAU,QAAQ,OAAO,UAAU,QAAQ,EAAE,cAAc,QAAQ;AAC1E,QAAM,OAAO,WAAW,GAAG,MAAM,GAAGA,KAAI,SAASD,IAAG,KAAK;AACzD,QAAM,MAAM,WAAW,GAAGC,KAAI,iBAAiBD,IAAG,KAAK;AACvD,SAAO;AAAA,IACL,GAAG,IAAI,gBAAgB,MAAM,cAAc,yBAC3B,SAAS,iBAAY,GAAG;AAAA;AAAA,EAC1C;AACF;AAUA,SAAS,cAAc,MAAkC;AACvD,MAAI;AACJ,MAAI;AACF,UAAM,aAAa,MAAM,MAAM;AAAA,EACjC,QAAQ;AACN,WAAO;AAAA,EACT;AACA,QAAM,UAAU,IAAI,KAAK;AACzB,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,OAAO;AACjC,WAAO;AAAA,MACL,eACE,OAAO,OAAO,kBAAkB,WAAW,OAAO,gBAAgB;AAAA,MACpE,mBACE,OAAO,OAAO,sBAAsB,WAChC,OAAO,oBACP;AAAA,MACN,gBACE,OAAO,OAAO,mBAAmB,WAAW,OAAO,iBAAiB;AAAA,MACtE,oBAAoB,MAAM,QAAQ,OAAO,kBAAkB,IACvD,OAAO,mBAAmB;AAAA,QACxB,CAAC,MAAmB,OAAO,MAAM;AAAA,MACnC,IACA,CAAC;AAAA,IACP;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,aAAa,YAA6B;AACjD,MAAI;AACJ,MAAI;AACF,UAAM,aAAa,YAAY,MAAM;AAAA,EACvC,QAAQ;AACN,WAAO;AAAA,EACT;AACA,QAAM,UAAU,IAAI,KAAK;AACzB,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,OAAO;AACjC,QAAI,OAAO,oBAAoB,MAAO,QAAO;AAC7C,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,uBAA+B;AAGtC,MAAI;AACF,UAAME,WAAU,cAAc,YAAY,GAAG;AAC7C,UAAM,MAAMA,SAAQ,oBAAoB;AACxC,QAAI,OAAO,IAAI,YAAY,YAAY,IAAI,QAAQ,SAAS,GAAG;AAC7D,aAAO,IAAI;AAAA,IACb;AAAA,EACF,QAAQ;AAAA,EAER;AACA,MAAI;AACF,UAAMA,WAAU,cAAc,YAAY,GAAG;AAC7C,UAAM,MAAMA,SAAQ,iBAAiB;AACrC,QAAI,OAAO,IAAI,YAAY,YAAY,IAAI,QAAQ,SAAS,GAAG;AAC7D,aAAO,IAAI;AAAA,IACb;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;;;AFjHA,eAAsB,IAAI,MAAgB,OAAgB,CAAC,GAAkB;AAC3E,QAAM,aAAa,KAAK,YAAY;AACpC,QAAM,mBAAmB,KAAK,kBAAkB;AAChD,QAAM,wBACJ,KAAK,uBAAuB;AAC9B,QAAM,2BACJ,KAAK,0BAA0B;AAEjC,MAAI,KAAK,MAAM,CAAC,EAAE,SAAS,0BAA0B,GAAG;AACtD,UAAM,yBAAyB;AAC/B;AAAA,EACF;AAEA,QAAM,cAAc,eAAe,IAAI;AAEvC,mBAAiB,QAAQ,MAAM;AAC/B,wBAAsB,IAAI;AAE1B,QAAM,UAAU,IAAI,QAAQ;AAC5B,UACG,KAAK,WAAW,EAChB;AAAA,IACC;AAAA,EACF,EACC,QAAQ,mBAAmB,GAAG,iBAAiB,eAAe;AAEjE,MAAI,wBAAwB,KAAK,MAAM,CAAC,CAAC,GAAG;AAC1C,UAAM,QAAQ,WAAW,IAAI;AAC7B;AAAA,EACF;AAEA,MAAI,gBAAgB,eAAe;AACjC,UAAM,kBAAkB,sBAAsB,KAAK,MAAM,CAAC,CAAC;AAC3D,QAAI,oBAAoB,MAAM;AAC5B,WAAK,MAAM,WAAW,eAAe,CAAC;AACtC;AAAA,IACF;AAAA,EACF;AAEA,MAAI,MAAM,wBAAwB,KAAK,MAAM,CAAC,GAAG,UAAU,GAAG;AAC5D;AAAA,EACF;AAEA,QAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,iCAA4B;AACtE,mBAAiB,OAAO;AACxB,uBAAqB,OAAO;AAE5B,QAAM,QAAQ,WAAW,IAAI;AAC/B;AAEA,SAAS,eAAe,MAA2C;AACjE,QAAM,UAAU,KAAK,CAAC,MAAM,SAAY,SAAS,KAAK,CAAC,CAAC,IAAI;AAC5D,SAAO,YAAY,gBAAgB,gBAAgB;AACrD;AAEA,SAAS,wBAAwB,MAAyB;AACxD,SAAO,KAAK,WAAW,MAAM,KAAK,CAAC,MAAM,eAAe,KAAK,CAAC,MAAM;AACtE;AAEA,SAAS,gBAAgB,MAKvB;AACA,QAAM,WAAW,KAAK,QAAQ,SAAS;AACvC,SAAO;AAAA,IACL,KAAK,KAAK,SAAS,OAAO,KAAK,KAAK,SAAS,IAAI;AAAA,IACjD,OAAO,aAAa,KAAK,SAAY,KAAK,WAAW,CAAC;AAAA,IACtD,UAAU,KAAK,SAAS,aAAa;AAAA,IACrC,YAAY,KAAK,SAAS,eAAe;AAAA,EAC3C;AACF;AAEA,SAAS,iBAAiB,MAKxB;AACA,SAAO;AAAA,IACL,SAAS,KAAK,SAAS,WAAW;AAAA,IAClC,OAAO,KAAK,SAAS,SAAS;AAAA,IAC9B,gBAAgB,KAAK,SAAS,mBAAmB;AAAA,IACjD,iBAAiB,KAAK,SAAS,oBAAoB;AAAA,EACrD;AACF;AAEA,SAAS,oBAAoB,MAI3B;AACA,SAAO;AAAA,IACL,KAAK,KAAK,SAAS,OAAO,KAAK,KAAK,SAAS,IAAI;AAAA,IACjD,UAAU,KAAK,SAAS,aAAa;AAAA,IACrC,YAAY,KAAK,SAAS,eAAe;AAAA,EAC3C;AACF;AAEA,SAAS,iBAAiB,MAIxB;AACA,SAAO;AAAA,IACL,MAAM,KAAK,SAAS,QAAQ;AAAA,IAC5B,aAAa,KAAK,SAAS,gBAAgB;AAAA,IAC3C,UAAU,KAAK,SAAS,aAAa;AAAA,EACvC;AACF;AAEA,eAAe,wBACb,MACA,YACkB;AAClB,MAAI,KAAK,SAAS,QAAQ,KAAK,KAAK,SAAS,IAAI,EAAG,QAAO;AAE3D,QAAM,CAAC,SAAS,UAAU,IAAI;AAC9B,MAAI,YAAY,OAAW,QAAO;AAElC,MAAI,YAAY,SAAS;AACvB,SAAK,MAAM,WAAW,gBAAgB,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC;AACrD,WAAO;AAAA,EACT;AAEA,MAAI,YAAY,QAAQ;AACtB,UAAM,EAAE,gBAAgB,eAAe,iBAAiB,IAAI,MAAM,OAChE,oBACF;AACA,QAAI,eAAe,WAAW;AAC5B,WAAK,MAAM,eAAe,EAAE,QAAQ,gBAAgB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;AACrE,aAAO;AAAA,IACT;AACA,QAAI,eAAe,aAAa;AAC9B,WAAK,MAAM,iBAAiB,CAAC;AAC7B,aAAO;AAAA,IACT;AACA,QAAI,eAAe,UAAU;AAC3B,WAAK,MAAM,cAAc,CAAC;AAC1B,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAEA,MAAI,YAAY,UAAU;AACxB,UAAM,EAAE,cAAc,IAAI,MAAM,OAAO,sBAAsB;AAC7D,QAAI,eAAe,UAAU,eAAe,QAAW;AACrD,WAAK,MAAM,cAAc,CAAC;AAC1B,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAEA,MAAI,YAAY,OAAO;AACrB,UAAM,EAAE,kBAAkB,mBAAmB,IAAI,MAAM,OACrD,sBACF;AACA,QAAI,eAAe,iBAAiB;AAClC,WAAK,MAAM,mBAAmB,EAAE,UAAU,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;AAC1D,aAAO;AAAA,IACT;AACA,QAAI,eAAe,SAAS;AAC1B,WAAK,MAAM,iBAAiB,EAAE,UAAU,KAAK,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC,CAAC;AACxE,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAEA,MAAI,YAAY,UAAU;AACxB,UAAM,EAAE,UAAU,IAAI,MAAM,OAAO,sBAAsB;AACzD,SAAK,MAAM,UAAU,iBAAiB,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC;AACrD,WAAO;AAAA,EACT;AAEA,MAAI,YAAY,UAAU;AACxB,UAAM,EAAE,UAAU,IAAI,MAAM,OAAO,sBAAsB;AACzD,SAAK,MAAM,UAAU;AAAA,MACnB,KAAK,QAAQ,IAAI;AAAA,MACjB,GAAG,iBAAiB,KAAK,MAAM,CAAC,CAAC;AAAA,IACnC,CAAC,CAAC;AACF,WAAO;AAAA,EACT;AAEA,MAAI,YAAY,aAAa;AAC3B,UAAM,EAAE,aAAa,IAAI,MAAM,OAAO,yBAAyB;AAC/D,SAAK,MAAM,aAAa,oBAAoB,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC;AAC3D,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,SAAS,gBACP,MACmD;AACnD,QAAM,MAAM,KAAK,QAAQ,UAAU;AACnC,QAAM,QAAQ,QAAQ,KAAK,SAAY,KAAK,MAAM,CAAC;AACnD,MACE,UAAU,YACV,UAAU,WACV,UAAU,YACV,UAAU,OACV;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,qBAA6B;AACpC,MAAI;AACF,UAAMC,WAAUC,eAAc,YAAY,GAAG;AAC7C,UAAM,MAAMD,SAAQ,iBAAiB;AACrC,QAAI,OAAO,IAAI,YAAY,YAAY,IAAI,QAAQ,SAAS,GAAG;AAC7D,aAAO,IAAI;AAAA,IACb;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAeO,SAAS,sBAAsB,MAA6C;AACjF,MAAI,KAAK,WAAW,EAAG,QAAO,CAAC;AAE/B,QAAM,OAA6B,CAAC;AACpC,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,QAAQ,WAAW,QAAQ,MAAM;AACnC,WAAK,MAAM;AACX;AAAA,IACF;AACA,QAAI,QAAQ,WAAW;AACrB,WAAK,QAAQ,KAAK,IAAI,CAAC;AACvB,WAAK;AACL;AAAA,IACF;AACA,QAAI,QAAQ,eAAe;AACzB,WAAK,WAAW;AAChB;AAAA,IACF;AACA,QAAI,QAAQ,iBAAiB;AAC3B,WAAK,aAAa;AAClB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;","names":["createRequire","RST","BOLD","require","require","createRequire"]}
@@ -59,7 +59,7 @@ if (shouldCheckSqliteAbi(process.argv)) {
59
59
  process.exit(1);
60
60
  }
61
61
  }
62
- var { run } = await import("./cli-W3OYVJYH.js");
62
+ var { run } = await import("./cli-CMGYLJSN.js");
63
63
  run(process.argv).catch((err) => {
64
64
  const message = err instanceof Error ? err.message : String(err);
65
65
  process.stderr.write(`almanac: ${message}
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ runDoctor
4
+ } from "./chunk-D3B2EEHL.js";
5
+ import "./chunk-V3QOQSXI.js";
6
+ import "./chunk-4CODZRHH.js";
7
+ import "./chunk-FM3VRDK7.js";
8
+ import "./chunk-ZDJSJIB6.js";
9
+ import "./chunk-447U3GQJ.js";
10
+ import "./chunk-SSYMRT4I.js";
11
+ import "./chunk-F53U6JQG.js";
12
+ import "./chunk-WRUSDYYE.js";
13
+ import "./chunk-7JUX4ADQ.js";
14
+ export {
15
+ runDoctor
16
+ };
17
+ //# sourceMappingURL=doctor-BTH7GCFV.js.map
@@ -3,10 +3,10 @@ import {
3
3
  runHookInstall,
4
4
  runHookStatus,
5
5
  runHookUninstall
6
- } from "./chunk-Z4MWLVS2.js";
6
+ } from "./chunk-447U3GQJ.js";
7
7
  export {
8
8
  runHookInstall,
9
9
  runHookStatus,
10
10
  runHookUninstall
11
11
  };
12
- //# sourceMappingURL=hook-CRJMWSSO.js.map
12
+ //# sourceMappingURL=hook-2NP3UE7U.js.map