codealmanac 0.2.4 → 0.2.5

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 (30) hide show
  1. package/README.md +9 -9
  2. package/dist/{agents-4Y7X24WW.js → agents-RVTQYE6A.js} +3 -3
  3. package/dist/{chunk-UU6FBRQO.js → chunk-6BJUYZ43.js} +15 -7
  4. package/dist/chunk-6BJUYZ43.js.map +1 -0
  5. package/dist/{chunk-BF2J4XTC.js → chunk-BGUID5BS.js} +2 -2
  6. package/dist/{chunk-H6QKCB7M.js → chunk-DL5BXZCX.js} +53 -3
  7. package/dist/chunk-DL5BXZCX.js.map +1 -0
  8. package/dist/{chunk-QRK3JLFX.js → chunk-GFUB57IT.js} +122 -44
  9. package/dist/chunk-GFUB57IT.js.map +1 -0
  10. package/dist/{chunk-CW4HRLMS.js → chunk-SMIK2YLU.js} +81 -73
  11. package/dist/chunk-SMIK2YLU.js.map +1 -0
  12. package/dist/{cli-MYMZ66EN.js → cli-CL4ID7EO.js} +8 -8
  13. package/dist/codealmanac.js +1 -1
  14. package/dist/{doctor-W5KQQLAX.js → doctor-DOLJRGS4.js} +4 -4
  15. package/dist/{register-commands-XTK2G2FB.js → register-commands-FBJ6XQ3L.js} +10 -10
  16. package/dist/register-commands-FBJ6XQ3L.js.map +1 -0
  17. package/dist/{uninstall-N7JY7ZV2.js → uninstall-DX6LFKMX.js} +4 -4
  18. package/guides/mini.md +3 -3
  19. package/guides/reference.md +7 -7
  20. package/package.json +1 -1
  21. package/dist/chunk-CW4HRLMS.js.map +0 -1
  22. package/dist/chunk-H6QKCB7M.js.map +0 -1
  23. package/dist/chunk-QRK3JLFX.js.map +0 -1
  24. package/dist/chunk-UU6FBRQO.js.map +0 -1
  25. package/dist/register-commands-XTK2G2FB.js.map +0 -1
  26. /package/dist/{agents-4Y7X24WW.js.map → agents-RVTQYE6A.js.map} +0 -0
  27. /package/dist/{chunk-BF2J4XTC.js.map → chunk-BGUID5BS.js.map} +0 -0
  28. /package/dist/{cli-MYMZ66EN.js.map → cli-CL4ID7EO.js.map} +0 -0
  29. /package/dist/{doctor-W5KQQLAX.js.map → doctor-DOLJRGS4.js.map} +0 -0
  30. /package/dist/{uninstall-N7JY7ZV2.js.map → uninstall-DX6LFKMX.js.map} +0 -0
package/README.md CHANGED
@@ -42,18 +42,17 @@ codealmanac --yes
42
42
  ```
43
43
 
44
44
  `codealmanac` (the bare invocation) routes to a setup wizard that:
45
- - lets you choose a default agent: Claude, Codex, or Cursor,
46
- - lets you choose a provider model or inherit the provider default,
47
- - checks local agent readiness,
48
- - installs auto-capture hooks for Claude, Codex, and Cursor,
49
- - drops two agent guides into `~/.claude/` (`codealmanac.md` mini, `codealmanac-reference.md` full),
50
- - appends `@~/.claude/codealmanac.md` to `~/.claude/CLAUDE.md` so every Claude Code session loads the mini guide.
45
+ - lets you choose a default provider: Claude, Codex, or Cursor,
46
+ - lets you choose a provider-local model or inherit the provider default,
47
+ - reports local provider readiness,
48
+ - installs auto-capture hooks for supported agents,
49
+ - installs the codealmanac guide into the selected provider's instruction surface: Claude uses `~/.claude/CLAUDE.md`, Codex uses `~/.codex/AGENTS.md`, and Cursor uses `.cursor/rules/codealmanac.mdc`.
51
50
 
52
51
  The setup is idempotent — safe to re-run. Opt out with `--skip-hook` or `--skip-guides`. Later, `almanac uninstall` reverses it.
53
52
 
54
53
  Two binaries ship, both pointing at the same entry: `codealmanac` (install surface) and `almanac` (day-to-day). Requires Node 20 or 22.
55
54
 
56
- `bootstrap` and `capture` invoke your configured default agent. Claude uses the bundled Claude Agent SDK, Codex uses `codex exec --json`, and Cursor uses `cursor-agent --print --output-format stream-json`. The query commands (`search`, `show`, `health`, `topics`) need no credentials at all.
55
+ `bootstrap` and `capture` invoke your configured default provider. Claude uses the bundled Claude Agent SDK, Codex uses `codex exec --json`, and Cursor uses `cursor-agent --print --output-format stream-json`. The query commands (`search`, `show`, `health`, `topics`) need no credentials at all.
57
56
 
58
57
  ## Authentication
59
58
 
@@ -99,7 +98,7 @@ codealmanac # interactive setup wizard; choose provider + mode
99
98
  # (or: codealmanac --yes)
100
99
 
101
100
  cd your-repo
102
- almanac bootstrap # default agent reads the repo and seeds pages + topic DAG
101
+ almanac bootstrap # default provider reads the repo and seeds pages + topic DAG
103
102
 
104
103
  almanac search "auth" # full-text search across pages
105
104
  almanac show checkout-flow # read a page
@@ -139,9 +138,10 @@ almanac capture --json <transcript> # structured CommandOutcome output
139
138
  almanac hook install --source all # auto-capture for Claude/Codex/Cursor
140
139
 
141
140
  # Setup & diagnose
142
- almanac agents list # provider readiness + default
141
+ almanac agents list # provider readiness + current model
143
142
  almanac agents use codex # change default provider
144
143
  almanac agents model claude claude-opus-4-6 # set provider model
144
+ almanac agents model claude --default # inherit provider default
145
145
  almanac config list --show-origin # scriptable settings view
146
146
  almanac doctor # check install + wiki health
147
147
  almanac update # update to latest version
@@ -8,8 +8,8 @@ import {
8
8
  runDeprecatedSetDefaultAgent,
9
9
  runSetAgentModel,
10
10
  runSetDefaultAgent
11
- } from "./chunk-UU6FBRQO.js";
12
- import "./chunk-BF2J4XTC.js";
11
+ } from "./chunk-6BJUYZ43.js";
12
+ import "./chunk-BGUID5BS.js";
13
13
  import "./chunk-P5WGG4FJ.js";
14
14
  import "./chunk-7JUX4ADQ.js";
15
15
  export {
@@ -22,4 +22,4 @@ export {
22
22
  runSetAgentModel,
23
23
  runSetDefaultAgent
24
24
  };
25
- //# sourceMappingURL=agents-4Y7X24WW.js.map
25
+ //# sourceMappingURL=agents-RVTQYE6A.js.map
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  buildProviderSetupView,
4
4
  parseAgentSelection
5
- } from "./chunk-BF2J4XTC.js";
5
+ } from "./chunk-BGUID5BS.js";
6
6
  import {
7
7
  isAgentProviderId,
8
8
  readConfig,
@@ -12,7 +12,13 @@ import {
12
12
  // src/commands/agents.ts
13
13
  async function runAgentsList() {
14
14
  const view = await buildProviderSetupView();
15
- const lines = ["codealmanac agents\n"];
15
+ const active = view.choices.find((choice) => choice.selected);
16
+ const activeModel = active?.effectiveModel ?? "provider default";
17
+ const lines = [
18
+ "codealmanac agents",
19
+ `current: ${view.defaultProvider} (model: ${activeModel})`,
20
+ ""
21
+ ];
16
22
  for (const choice of view.choices) {
17
23
  const selected = choice.selected ? "*" : " ";
18
24
  const recommended = choice.recommended ? "recommended" : "";
@@ -30,8 +36,10 @@ async function runAgentsList() {
30
36
  );
31
37
  }
32
38
  lines.push(
33
- "\nUse: almanac agents use <claude|codex|cursor>",
34
- "Set model: almanac agents model <provider> <model>"
39
+ "",
40
+ "Change provider: almanac agents use <claude|codex|cursor>",
41
+ "Set model: almanac agents model <provider> <model>",
42
+ "Reset model: almanac agents model <provider> --default"
35
43
  );
36
44
  return { stdout: `${lines.join("\n")}
37
45
  `, stderr: "", exitCode: 0 };
@@ -92,8 +100,8 @@ async function setDefaultAgent(opts) {
92
100
  };
93
101
  await writeConfig(next);
94
102
  return {
95
- stdout: parsed.model === void 0 ? `codealmanac: default agent set to ${provider}.
96
- ` : `codealmanac: default agent set to ${provider}; ${provider} model set to ${parsed.model}.
103
+ stdout: parsed.model === void 0 ? `codealmanac: default provider set to ${provider}.
104
+ ` : `codealmanac: default provider set to ${provider}; ${provider} model set to ${parsed.model}.
97
105
  `,
98
106
  stderr: "",
99
107
  exitCode: 0
@@ -184,4 +192,4 @@ export {
184
192
  runDeprecatedSetAgentModel,
185
193
  runAgentsModel
186
194
  };
187
- //# sourceMappingURL=chunk-UU6FBRQO.js.map
195
+ //# sourceMappingURL=chunk-6BJUYZ43.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/agents.ts"],"sourcesContent":["import {\n buildProviderSetupView,\n parseAgentSelection,\n type ProviderReadiness,\n} from \"../agent/provider-view.js\";\nimport {\n isAgentProviderId,\n readConfig,\n writeConfig,\n type AgentProviderId,\n} from \"../update/config.js\";\n\nexport interface AgentsResult {\n stdout: string;\n stderr: string;\n exitCode: number;\n}\n\nexport async function runAgentsList(): Promise<AgentsResult> {\n const view = await buildProviderSetupView();\n const active = view.choices.find((choice) => choice.selected);\n const activeModel = active?.effectiveModel ?? \"provider default\";\n const lines = [\n \"codealmanac agents\",\n `current: ${view.defaultProvider} (model: ${activeModel})`,\n \"\",\n ];\n for (const choice of view.choices) {\n const selected = choice.selected ? \"*\" : \" \";\n const recommended = choice.recommended ? \"recommended\" : \"\";\n const model = choice.effectiveModel ?? \"provider default\";\n const detail = choice.account ?? choice.fixCommand ?? choice.detail;\n lines.push(\n [\n selected,\n choice.label.padEnd(6),\n readinessLabel(choice.readiness).padEnd(15),\n recommended.padEnd(11),\n `model: ${model}`.padEnd(31),\n detail,\n ].join(\" \").trimEnd(),\n );\n }\n lines.push(\n \"\",\n \"Change provider: almanac agents use <claude|codex|cursor>\",\n \"Set model: almanac agents model <provider> <model>\",\n \"Reset model: almanac agents model <provider> --default\",\n );\n return { stdout: `${lines.join(\"\\n\")}\\n`, stderr: \"\", exitCode: 0 };\n}\n\nexport async function runAgentsDoctor(): Promise<AgentsResult> {\n const view = await buildProviderSetupView();\n const lines = [\"codealmanac agent doctor\\n\"];\n for (const choice of view.choices) {\n lines.push(`${choice.ready ? \"✓\" : \"✗\"} ${choice.label}`);\n lines.push(` status: ${readinessLabel(choice.readiness)}`);\n lines.push(` model: ${choice.effectiveModel ?? \"provider default\"}`);\n if (choice.account !== null) {\n lines.push(` account: ${choice.account}`);\n } else if (choice.detail.length > 0) {\n lines.push(` detail: ${choice.detail}`);\n }\n if (choice.fixCommand !== null) lines.push(` fix: ${choice.fixCommand}`);\n lines.push(\"\");\n }\n return { stdout: `${lines.join(\"\\n\").trimEnd()}\\n`, stderr: \"\", exitCode: 0 };\n}\n\nexport interface SetDefaultAgentOptions {\n provider: string;\n}\n\nexport async function runSetDefaultAgent(\n opts: SetDefaultAgentOptions,\n): Promise<AgentsResult> {\n return setDefaultAgent(opts);\n}\n\nexport async function runDeprecatedSetDefaultAgent(\n opts: SetDefaultAgentOptions,\n): Promise<AgentsResult> {\n return withDeprecation(\n await setDefaultAgent(opts),\n \"almanac set default-agent <provider>\",\n \"almanac agents use <provider>\",\n );\n}\n\nexport async function runAgentsUse(opts: SetDefaultAgentOptions): Promise<AgentsResult> {\n return setDefaultAgent(opts);\n}\n\nasync function setDefaultAgent(\n opts: SetDefaultAgentOptions,\n): Promise<AgentsResult> {\n const parsed = parseAgentSelection(opts.provider);\n if (parsed.provider === null) {\n return {\n stdout: \"\",\n stderr:\n `almanac: unknown agent '${opts.provider}'. ` +\n \"Expected one of: claude, codex, cursor.\\n\",\n exitCode: 1,\n };\n }\n const provider = parsed.provider;\n const config = await readConfig();\n const next = {\n ...config,\n agent: {\n ...config.agent,\n default: provider,\n models:\n parsed.model === undefined\n ? config.agent.models\n : {\n ...config.agent.models,\n [provider]: parsed.model,\n },\n },\n };\n await writeConfig(next);\n return {\n stdout:\n parsed.model === undefined\n ? `codealmanac: default provider set to ${provider}.\\n`\n : `codealmanac: default provider set to ${provider}; ${provider} model set to ${parsed.model}.\\n`,\n stderr: \"\",\n exitCode: 0,\n };\n}\n\nexport async function runSetAgentModel(opts: {\n provider: string;\n model?: string;\n defaultModel?: boolean;\n}): Promise<AgentsResult> {\n return setProviderModel(opts);\n}\n\nexport async function runDeprecatedSetAgentModel(opts: {\n provider: string;\n model?: string;\n defaultModel?: boolean;\n}): Promise<AgentsResult> {\n return withDeprecation(\n await setProviderModel(opts),\n \"almanac set model <provider> <model>\",\n \"almanac agents model <provider> <model>\",\n );\n}\n\nexport async function runAgentsModel(opts: {\n provider: string;\n model?: string;\n defaultModel?: boolean;\n}): Promise<AgentsResult> {\n return setProviderModel(opts);\n}\n\nasync function setProviderModel(opts: {\n provider: string;\n model?: string;\n defaultModel?: boolean;\n}): Promise<AgentsResult> {\n if (!isAgentProviderId(opts.provider)) {\n return {\n stdout: \"\",\n stderr:\n `almanac: unknown agent '${opts.provider}'. ` +\n \"Expected one of: claude, codex, cursor.\\n\",\n exitCode: 1,\n };\n }\n if (\n opts.defaultModel !== true &&\n (opts.model === undefined || opts.model.length === 0)\n ) {\n return {\n stdout: \"\",\n stderr:\n `almanac: missing model for ${opts.provider}. ` +\n \"Pass a model id or --default.\\n\",\n exitCode: 1,\n };\n }\n const provider = opts.provider as AgentProviderId;\n const config = await readConfig();\n const model = normalizeRequestedModel(opts);\n await writeConfig({\n ...config,\n agent: {\n ...config.agent,\n models: {\n ...config.agent.models,\n [provider]: model,\n },\n },\n });\n return {\n stdout:\n model === null\n ? `codealmanac: ${provider} model reset to provider default.\\n`\n : `codealmanac: ${provider} model set to ${model}.\\n`,\n stderr: \"\",\n exitCode: 0,\n };\n}\n\nfunction normalizeRequestedModel(opts: {\n provider: string;\n model?: string;\n defaultModel?: boolean;\n}): string | null {\n if (opts.defaultModel === true) return null;\n if (opts.model === undefined || opts.model.length === 0) return null;\n if (opts.model === \"default\" || opts.model === \"null\") return null;\n return opts.model;\n}\n\nfunction readinessLabel(readiness: ProviderReadiness): string {\n switch (readiness) {\n case \"ready\":\n return \"ready\";\n case \"missing\":\n return \"missing\";\n case \"not-authenticated\":\n return \"not ready\";\n }\n}\n\nfunction withDeprecation(\n result: AgentsResult,\n oldUsage: string,\n newUsage: string,\n): AgentsResult {\n return {\n ...result,\n stderr:\n `almanac: warning: \\`${oldUsage}\\` is deprecated; use \\`${newUsage}\\`.\\n` +\n result.stderr,\n };\n}\n"],"mappings":"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","names":[]}
@@ -754,13 +754,13 @@ function missingStatus(id) {
754
754
 
755
755
  export {
756
756
  checkClaudeAuth,
757
- UNAUTHENTICATED_MESSAGE,
758
757
  DEFAULT_AGENT_MODEL,
759
758
  assertAgentAuth,
760
759
  getAgentProvider,
760
+ getProviderLabel,
761
761
  getProviderDefaultModel,
762
762
  buildProviderSetupView,
763
763
  buildProviderModelChoices,
764
764
  parseAgentSelection
765
765
  };
766
- //# sourceMappingURL=chunk-BF2J4XTC.js.map
766
+ //# sourceMappingURL=chunk-BGUID5BS.js.map
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  IMPORT_LINE
4
- } from "./chunk-QRK3JLFX.js";
4
+ } from "./chunk-GFUB57IT.js";
5
5
  import {
6
6
  runHookUninstall
7
7
  } from "./chunk-447U3GQJ.js";
@@ -50,7 +50,7 @@ async function runUninstall(options = {}) {
50
50
  } else if (interactive) {
51
51
  removeGuides = await confirm(
52
52
  out,
53
- "Remove the guides + CLAUDE.md import line?",
53
+ "Remove guides and provider imports/rules?",
54
54
  true
55
55
  );
56
56
  }
@@ -101,8 +101,58 @@ async function removeGuideFiles(claudeDir) {
101
101
  }
102
102
  }
103
103
  }
104
+ touched.push(...await removeCodexGuides());
105
+ touched.push(...await removeCursorGuides(process.cwd()));
104
106
  return { anyChanges: touched.length > 0, filesTouched: touched };
105
107
  }
108
+ async function removeCodexGuides() {
109
+ const touched = [];
110
+ const codexDir = path.join(homedir(), ".codex");
111
+ const mini = path.join(codexDir, "codealmanac.md");
112
+ const ref = path.join(codexDir, "codealmanac-reference.md");
113
+ const agents = path.join(codexDir, "AGENTS.md");
114
+ if (existsSync(mini)) {
115
+ await rm(mini, { force: true });
116
+ touched.push("~/.codex/codealmanac.md");
117
+ }
118
+ if (existsSync(ref)) {
119
+ await rm(ref, { force: true });
120
+ touched.push("~/.codex/codealmanac-reference.md");
121
+ }
122
+ if (existsSync(agents)) {
123
+ const existing = await readFile(agents, "utf8");
124
+ const body = removeManagedBlock(
125
+ existing,
126
+ "<!-- codealmanac:start -->",
127
+ "<!-- codealmanac:end -->"
128
+ );
129
+ if (body !== existing) {
130
+ if (body.trim().length === 0) {
131
+ await rm(agents, { force: true });
132
+ touched.push("~/.codex/AGENTS.md (deleted)");
133
+ } else {
134
+ await writeFile(agents, body, "utf8");
135
+ touched.push("~/.codex/AGENTS.md");
136
+ }
137
+ }
138
+ }
139
+ return touched;
140
+ }
141
+ async function removeCursorGuides(cwd) {
142
+ const rule = path.join(cwd, ".cursor", "rules", "codealmanac.mdc");
143
+ if (!existsSync(rule)) return [];
144
+ await rm(rule, { force: true });
145
+ return [".cursor/rules/codealmanac.mdc"];
146
+ }
147
+ function removeManagedBlock(contents, start, end) {
148
+ const pattern = new RegExp(
149
+ `\\n?${escapeRegex(start)}[\\s\\S]*?${escapeRegex(end)}\\n?`
150
+ );
151
+ return contents.replace(pattern, "\n").replace(/\n\n\n+/g, "\n\n");
152
+ }
153
+ function escapeRegex(value) {
154
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
155
+ }
106
156
  function removeImportLine(contents) {
107
157
  const eol = contents.includes("\r\n") ? "\r\n" : "\n";
108
158
  const lines = contents.split(/\r?\n/);
@@ -142,4 +192,4 @@ export {
142
192
  runUninstall,
143
193
  removeImportLine
144
194
  };
145
- //# sourceMappingURL=chunk-H6QKCB7M.js.map
195
+ //# sourceMappingURL=chunk-DL5BXZCX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/uninstall.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { readFile, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\n\nimport { runHookUninstall } from \"./hook.js\";\nimport { IMPORT_LINE } from \"./setup.js\";\n\n/**\n * `almanac uninstall` — the reverse of `setup`.\n *\n * Idempotent and order-insensitive: each step is a no-op if that\n * artifact was never installed. We remove exactly the things setup added,\n * nothing else:\n *\n * 1. The `@~/.claude/codealmanac.md` line from `~/.claude/CLAUDE.md`.\n * Other content stays untouched. If removing our line leaves the\n * file empty, we delete the file so our fingerprint doesn't persist\n * as zero bytes.\n * 2. The guide files `~/.claude/codealmanac.md` and\n * `~/.claude/codealmanac-reference.md`.\n * 3. The SessionEnd hook entry (delegated to `runHookUninstall`, which\n * already knows how to leave foreign entries alone).\n *\n * Flags:\n * --yes skip confirmations; remove everything\n * --keep-hook leave the hook alone\n * --keep-guides leave guides and provider imports/rules alone\n *\n * Non-interactive (no TTY) → behaves as if `--yes` was passed. Same\n * contract as `setup`.\n */\n\nexport interface UninstallOptions {\n yes?: boolean;\n keepHook?: boolean;\n keepGuides?: boolean;\n\n // ─── Injection points ────────────────────────────────────────────\n settingsPath?: string;\n hookScriptPath?: string;\n claudeDir?: string;\n isTTY?: boolean;\n stdout?: NodeJS.WritableStream;\n}\n\nexport interface UninstallResult {\n stdout: string;\n stderr: string;\n exitCode: number;\n}\n\nconst BLUE = \"\\x1b[38;5;75m\";\nconst DIM = \"\\x1b[2m\";\nconst RST = \"\\x1b[0m\";\n\nexport async function runUninstall(\n options: UninstallOptions = {},\n): Promise<UninstallResult> {\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 const claudeDir = options.claudeDir ?? path.join(homedir(), \".claude\");\n\n out.write(\"\\n\");\n\n // Hook removal.\n let removeHook = true;\n if (options.keepHook === true) {\n removeHook = false;\n } else if (interactive) {\n removeHook = await confirm(\n out,\n \"Remove the SessionEnd hook from ~/.claude/settings.json?\",\n true,\n );\n }\n if (removeHook) {\n const res = await runHookUninstall({\n settingsPath: options.settingsPath,\n hookScriptPath: options.hookScriptPath,\n });\n if (res.exitCode !== 0) {\n return { stdout: \"\", stderr: res.stderr, exitCode: res.exitCode };\n }\n out.write(` ${BLUE}\\u25c7${RST} ${res.stdout.trim()}\\n`);\n } else {\n out.write(` ${DIM}\\u25cb Hook kept${RST}\\n`);\n }\n\n // Guide + import removal.\n let removeGuides = true;\n if (options.keepGuides === true) {\n removeGuides = false;\n } else if (interactive) {\n removeGuides = await confirm(\n out,\n \"Remove guides and provider imports/rules?\",\n true,\n );\n }\n if (removeGuides) {\n const summary = await removeGuideFiles(claudeDir);\n if (summary.anyChanges) {\n out.write(\n ` ${BLUE}\\u25c7${RST} Guides removed (${summary.filesTouched.join(\", \")})\\n`,\n );\n } else {\n out.write(` ${DIM}\\u25cb Guides not installed${RST}\\n`);\n }\n } else {\n out.write(` ${DIM}\\u25cb Guides kept${RST}\\n`);\n }\n\n out.write(`\\n ${BLUE}\\u25c7${RST} ${BLUE}Uninstall complete${RST}\\n\\n`);\n\n return { stdout: \"\", stderr: \"\", exitCode: 0 };\n}\n\ninterface RemoveGuidesResult {\n anyChanges: boolean;\n filesTouched: string[];\n}\n\nasync function removeGuideFiles(\n claudeDir: string,\n): Promise<RemoveGuidesResult> {\n const touched: string[] = [];\n\n const mini = path.join(claudeDir, \"codealmanac.md\");\n const ref = path.join(claudeDir, \"codealmanac-reference.md\");\n const claudeMd = path.join(claudeDir, \"CLAUDE.md\");\n\n if (existsSync(mini)) {\n await rm(mini, { force: true });\n touched.push(\"codealmanac.md\");\n }\n if (existsSync(ref)) {\n await rm(ref, { force: true });\n touched.push(\"codealmanac-reference.md\");\n }\n\n if (existsSync(claudeMd)) {\n const existing = await readFile(claudeMd, \"utf8\");\n const { changed, body } = removeImportLine(existing);\n if (changed) {\n // If the file is now content-free, delete it outright so our\n // installation leaves no trace. A user who was using CLAUDE.md\n // before we touched it still has their content; only the case\n // where CLAUDE.md contained nothing but our line gets cleaned up.\n if (body.trim().length === 0) {\n await rm(claudeMd, { force: true });\n touched.push(\"CLAUDE.md (deleted)\");\n } else {\n await writeFile(claudeMd, body, \"utf8\");\n touched.push(\"CLAUDE.md\");\n }\n }\n }\n\n touched.push(...await removeCodexGuides());\n touched.push(...await removeCursorGuides(process.cwd()));\n\n return { anyChanges: touched.length > 0, filesTouched: touched };\n}\n\nasync function removeCodexGuides(): Promise<string[]> {\n const touched: string[] = [];\n const codexDir = path.join(homedir(), \".codex\");\n const mini = path.join(codexDir, \"codealmanac.md\");\n const ref = path.join(codexDir, \"codealmanac-reference.md\");\n const agents = path.join(codexDir, \"AGENTS.md\");\n if (existsSync(mini)) {\n await rm(mini, { force: true });\n touched.push(\"~/.codex/codealmanac.md\");\n }\n if (existsSync(ref)) {\n await rm(ref, { force: true });\n touched.push(\"~/.codex/codealmanac-reference.md\");\n }\n if (existsSync(agents)) {\n const existing = await readFile(agents, \"utf8\");\n const body = removeManagedBlock(\n existing,\n \"<!-- codealmanac:start -->\",\n \"<!-- codealmanac:end -->\",\n );\n if (body !== existing) {\n if (body.trim().length === 0) {\n await rm(agents, { force: true });\n touched.push(\"~/.codex/AGENTS.md (deleted)\");\n } else {\n await writeFile(agents, body, \"utf8\");\n touched.push(\"~/.codex/AGENTS.md\");\n }\n }\n }\n return touched;\n}\n\nasync function removeCursorGuides(cwd: string): Promise<string[]> {\n const rule = path.join(cwd, \".cursor\", \"rules\", \"codealmanac.mdc\");\n if (!existsSync(rule)) return [];\n await rm(rule, { force: true });\n return [\".cursor/rules/codealmanac.mdc\"];\n}\n\nfunction removeManagedBlock(\n contents: string,\n start: string,\n end: string,\n): string {\n const pattern = new RegExp(\n `\\\\n?${escapeRegex(start)}[\\\\s\\\\S]*?${escapeRegex(end)}\\\\n?`,\n );\n return contents.replace(pattern, \"\\n\").replace(/\\n\\n\\n+/g, \"\\n\\n\");\n}\n\nfunction escapeRegex(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * Remove the import line from a CLAUDE.md body. Match is line-anchored\n * (trimmed equality) so we don't munge a line that happens to include\n * the token as part of a longer string. Returns the unchanged body (and\n * `changed: false`) if the line isn't present — this is what makes the\n * command safe to run repeatedly.\n */\nexport function removeImportLine(contents: string): {\n changed: boolean;\n body: string;\n} {\n const eol = contents.includes(\"\\r\\n\") ? \"\\r\\n\" : \"\\n\";\n const lines = contents.split(/\\r?\\n/);\n\n const indices: number[] = [];\n for (let i = 0; i < lines.length; i++) {\n if (lines[i]!.trim() === IMPORT_LINE) indices.push(i);\n }\n if (indices.length === 0) return { changed: false, body: contents };\n\n // Remove the line(s). Iterate from the end so earlier indices stay\n // valid as we splice.\n for (let i = indices.length - 1; i >= 0; i--) {\n lines.splice(indices[i]!, 1);\n }\n\n let body = lines.join(eol);\n\n // Cleanup: collapse any double-blank that our removal created at the\n // spot the line used to live. A best-effort tidy — we don't try to\n // normalize the whole file.\n body = body.replace(/\\n\\n\\n+/g, \"\\n\\n\");\n\n return { changed: true, body };\n}\n\nfunction confirm(\n out: NodeJS.WritableStream,\n question: string,\n defaultYes: boolean,\n): Promise<boolean> {\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);\n };\n\n process.stdin.resume();\n process.stdin.on(\"data\", onData);\n });\n}\n"],"mappings":"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","names":[]}
@@ -3,12 +3,11 @@ import {
3
3
  runHookInstall
4
4
  } from "./chunk-447U3GQJ.js";
5
5
  import {
6
- UNAUTHENTICATED_MESSAGE,
7
6
  buildProviderModelChoices,
8
7
  buildProviderSetupView,
9
- checkClaudeAuth,
8
+ getProviderLabel,
10
9
  parseAgentSelection
11
- } from "./chunk-BF2J4XTC.js";
10
+ } from "./chunk-BGUID5BS.js";
12
11
  import {
13
12
  isAgentProviderId,
14
13
  readConfig,
@@ -192,7 +191,7 @@ function printBanner(out) {
192
191
  `);
193
192
  }
194
193
  out.write(`
195
- ${WHITE_BOLD2} Install the hook + agent guides${RST2}
194
+ ${WHITE_BOLD2} Install provider integrations${RST2}
196
195
  `);
197
196
  }
198
197
  function printBadge(out) {
@@ -225,9 +224,6 @@ async function runSetup(options = {}) {
225
224
  }
226
225
  printBanner(out);
227
226
  printBadge(out);
228
- const auth = await safeCheckAuth(options.spawnCli);
229
- reportAuth(out, auth);
230
- out.write(BAR + "\n");
231
227
  const agentChoice = await chooseDefaultAgent({
232
228
  out,
233
229
  interactive,
@@ -245,7 +241,7 @@ async function runSetup(options = {}) {
245
241
  }
246
242
  stepDone(
247
243
  out,
248
- `Default agent: ${WHITE_BOLD2}${agentChoice.provider}${RST2} (${agentChoice.model ?? "provider default"})`
244
+ `Default provider: ${WHITE_BOLD2}${agentChoice.provider}${RST2} (${agentChoice.model ?? "provider default"})`
249
245
  );
250
246
  out.write(BAR + "\n");
251
247
  const ephem = options.installPath !== void 0 ? options.installPath !== null ? detectEphemeral(options.installPath) : false : detectEphemeral(detectCurrentInstallPath());
@@ -285,7 +281,7 @@ async function runSetup(options = {}) {
285
281
  } else if (interactive) {
286
282
  hookAction = await confirm(
287
283
  out,
288
- "Install auto-capture hooks for Claude, Codex, and Cursor?",
284
+ "Install auto-capture hooks for supported agents?",
289
285
  true
290
286
  );
291
287
  }
@@ -298,7 +294,7 @@ async function runSetup(options = {}) {
298
294
  stableHooksDir: options.stableHooksDir
299
295
  });
300
296
  if (res.exitCode !== 0) {
301
- stepActive(out, `SessionEnd hook: ${res.stderr.trim()}`);
297
+ stepActive(out, `Auto-capture hook: ${res.stderr.trim()}`);
302
298
  return {
303
299
  stdout: "",
304
300
  stderr: res.stderr,
@@ -308,16 +304,17 @@ async function runSetup(options = {}) {
308
304
  hookResultLine = res.stdout.includes("already installed") ? `Auto-capture hooks ${DIM2}already installed${RST2}` : `Auto-capture hooks installed`;
309
305
  stepDone(out, hookResultLine);
310
306
  } else {
311
- stepSkipped(out, `SessionEnd hook ${DIM2}skipped${RST2}`);
307
+ stepSkipped(out, `Auto-capture hooks ${DIM2}skipped${RST2}`);
312
308
  }
313
309
  out.write(BAR + "\n");
314
310
  let guidesAction = "install";
311
+ const providerLabel = getProviderLabel(agentChoice.provider);
315
312
  if (options.skipGuides === true) {
316
313
  guidesAction = "skip";
317
314
  } else if (interactive) {
318
315
  guidesAction = await confirm(
319
316
  out,
320
- "Install the codealmanac usage guides into ~/.claude/ and import them from CLAUDE.md?",
317
+ `Install the codealmanac guide for ${providerLabel}?`,
321
318
  true
322
319
  );
323
320
  }
@@ -325,10 +322,12 @@ async function runSetup(options = {}) {
325
322
  if (guidesAction === "install") {
326
323
  try {
327
324
  const summary = await installGuides({
325
+ provider: agentChoice.provider,
328
326
  claudeDir: options.claudeDir ?? path3.join(homedir2(), ".claude"),
329
- guidesDir: options.guidesDir ?? resolveGuidesDir()
327
+ guidesDir: options.guidesDir ?? resolveGuidesDir(),
328
+ cwd: process.cwd()
330
329
  });
331
- guidesSummary = summary.anyChanges ? `Guides installed (${summary.filesWritten.join(", ")})` : `Guides ${DIM2}already installed${RST2}`;
330
+ guidesSummary = summary.anyChanges ? `Guide installed for ${summary.providerLabel} (${summary.filesWritten.join(", ")})` : `Guide for ${summary.providerLabel} ${DIM2}already installed${RST2}`;
332
331
  stepDone(out, guidesSummary);
333
332
  } catch (err) {
334
333
  const msg = err instanceof Error ? err.message : String(err);
@@ -347,15 +346,9 @@ async function runSetup(options = {}) {
347
346
  out.write("\n");
348
347
  const existingPageCount = countExistingPages(process.cwd());
349
348
  printNextSteps(out, existingPageCount);
349
+ printProviderNextSteps(out);
350
350
  return { stdout: "", stderr: "", exitCode: 0 };
351
351
  }
352
- async function safeCheckAuth(spawnCli) {
353
- try {
354
- return await checkClaudeAuth(spawnCli);
355
- } catch {
356
- return { loggedIn: false };
357
- }
358
- }
359
352
  async function chooseDefaultAgent(args) {
360
353
  const config = await readConfig();
361
354
  let view = null;
@@ -364,7 +357,7 @@ async function chooseDefaultAgent(args) {
364
357
  view = await buildProviderSetupView({ config, spawnCli: args.spawnCli });
365
358
  }
366
359
  if (args.interactive && args.requested === void 0 && view !== null) {
367
- args.out.write(" Choose default agent:\n");
360
+ args.out.write(" Choose default provider for bootstrap/capture:\n");
368
361
  view.choices.forEach((choice, index) => {
369
362
  const tag = choice.recommended ? " recommended" : "";
370
363
  const status = choice.ready ? "ready" : "not ready";
@@ -376,7 +369,7 @@ async function chooseDefaultAgent(args) {
376
369
  });
377
370
  selected = (await promptText(
378
371
  args.out,
379
- "Default agent",
372
+ "Default provider",
380
373
  view.recommendedProvider
381
374
  )).toLowerCase();
382
375
  const number = Number.parseInt(selected, 10);
@@ -441,7 +434,7 @@ async function chooseProviderModel(args) {
441
434
  if (!args.interactive) {
442
435
  return args.configuredModel ?? recommended?.value ?? null;
443
436
  }
444
- args.out.write(` Choose ${args.provider} model:
437
+ args.out.write(` Choose model for ${getProviderLabel(args.provider)}:
445
438
  `);
446
439
  choices.forEach((choice, index) => {
447
440
  const marker = choice.recommended ? " recommended" : "";
@@ -488,25 +481,9 @@ async function runLoginCommand(command) {
488
481
  });
489
482
  });
490
483
  }
491
- function reportAuth(out, auth) {
492
- if (auth.loggedIn) {
493
- const who = auth.email ?? "Claude account";
494
- const plan = auth.subscriptionType !== void 0 ? ` ${DIM2}(${auth.subscriptionType})${RST2}` : "";
495
- stepDone(out, `Claude auth: ${WHITE_BOLD2}${who}${RST2}${plan}`);
496
- return;
497
- }
498
- if (process.env.ANTHROPIC_API_KEY !== void 0 && process.env.ANTHROPIC_API_KEY.length > 0) {
499
- stepDone(out, `Claude auth: ${WHITE_BOLD2}ANTHROPIC_API_KEY${RST2} set`);
500
- return;
501
- }
502
- stepActive(out, `Claude auth: ${DIM2}not signed in${RST2}`);
503
- for (const line of UNAUTHENTICATED_MESSAGE.split("\n")) {
504
- out.write(` ${DIM2}\u2502 ${line}${RST2}
505
- `);
506
- }
507
- }
484
+ var CODEX_BLOCK_START = "<!-- codealmanac:start -->";
485
+ var CODEX_BLOCK_END = "<!-- codealmanac:end -->";
508
486
  async function installGuides(options) {
509
- await mkdir(options.claudeDir, { recursive: true });
510
487
  const srcMini = path3.join(options.guidesDir, "mini.md");
511
488
  const srcRef = path3.join(options.guidesDir, "reference.md");
512
489
  if (!existsSync2(srcMini)) {
@@ -515,6 +492,17 @@ async function installGuides(options) {
515
492
  if (!existsSync2(srcRef)) {
516
493
  throw new Error(`missing bundled guide: ${srcRef}`);
517
494
  }
495
+ switch (options.provider) {
496
+ case "claude":
497
+ return await installClaudeGuides(options, srcMini, srcRef);
498
+ case "codex":
499
+ return await installCodexGuides(srcMini, srcRef);
500
+ case "cursor":
501
+ return await installCursorGuides(options.cwd, srcMini);
502
+ }
503
+ }
504
+ async function installClaudeGuides(options, srcMini, srcRef) {
505
+ await mkdir(options.claudeDir, { recursive: true });
518
506
  const destMini = path3.join(options.claudeDir, "codealmanac.md");
519
507
  const destRef = path3.join(options.claudeDir, "codealmanac-reference.md");
520
508
  const miniChanged = await copyIfChanged(srcMini, destMini);
@@ -525,7 +513,45 @@ async function installGuides(options) {
525
513
  if (miniChanged) filesWritten.push("codealmanac.md");
526
514
  if (refChanged) filesWritten.push("codealmanac-reference.md");
527
515
  if (importChanged) filesWritten.push("CLAUDE.md");
528
- return { anyChanges: filesWritten.length > 0, filesWritten };
516
+ return {
517
+ providerLabel: "Claude",
518
+ anyChanges: filesWritten.length > 0,
519
+ filesWritten
520
+ };
521
+ }
522
+ async function installCodexGuides(srcMini, srcRef) {
523
+ const codexDir = path3.join(homedir2(), ".codex");
524
+ await mkdir(codexDir, { recursive: true });
525
+ const destMini = path3.join(codexDir, "codealmanac.md");
526
+ const destRef = path3.join(codexDir, "codealmanac-reference.md");
527
+ const miniChanged = await copyIfChanged(srcMini, destMini);
528
+ const refChanged = await copyIfChanged(srcRef, destRef);
529
+ const agentsChanged = await ensureManagedBlock(
530
+ path3.join(codexDir, "AGENTS.md"),
531
+ codexGuideBlock()
532
+ );
533
+ const filesWritten = [];
534
+ if (miniChanged) filesWritten.push("codealmanac.md");
535
+ if (refChanged) filesWritten.push("codealmanac-reference.md");
536
+ if (agentsChanged) filesWritten.push("AGENTS.md");
537
+ return {
538
+ providerLabel: "Codex",
539
+ anyChanges: filesWritten.length > 0,
540
+ filesWritten
541
+ };
542
+ }
543
+ async function installCursorGuides(cwd, srcMini) {
544
+ const rulesDir = path3.join(cwd, ".cursor", "rules");
545
+ await mkdir(rulesDir, { recursive: true });
546
+ const mini = await readFile(srcMini, "utf8");
547
+ const dest = path3.join(rulesDir, "codealmanac.mdc");
548
+ const body = "---\ndescription: Use codealmanac wiki context during coding work\nalwaysApply: true\n---\n\n" + mini;
549
+ const changed = await writeIfChanged(dest, body);
550
+ return {
551
+ providerLabel: "Cursor",
552
+ anyChanges: changed,
553
+ filesWritten: changed ? [".cursor/rules/codealmanac.mdc"] : []
554
+ };
529
555
  }
530
556
  async function copyIfChanged(src, dest) {
531
557
  const srcBytes = await readFile(src);
@@ -539,6 +565,45 @@ async function copyIfChanged(src, dest) {
539
565
  await copyFile(src, dest);
540
566
  return true;
541
567
  }
568
+ async function writeIfChanged(dest, body) {
569
+ if (existsSync2(dest)) {
570
+ try {
571
+ if (await readFile(dest, "utf8") === body) return false;
572
+ } catch {
573
+ }
574
+ }
575
+ await writeFile(dest, body, "utf8");
576
+ return true;
577
+ }
578
+ async function ensureManagedBlock(file, block) {
579
+ let existing = "";
580
+ if (existsSync2(file)) existing = await readFile(file, "utf8");
581
+ const pattern = new RegExp(
582
+ `${escapeRegex(CODEX_BLOCK_START)}[\\s\\S]*?${escapeRegex(CODEX_BLOCK_END)}`
583
+ );
584
+ const next = pattern.test(existing) ? existing.replace(pattern, block.trimEnd()) : `${existing.trimEnd()}${existing.trim().length > 0 ? "\n\n" : ""}${block.trimEnd()}
585
+ `;
586
+ const normalized = next.endsWith("\n") ? next : `${next}
587
+ `;
588
+ if (normalized === existing) return false;
589
+ await writeFile(file, normalized, "utf8");
590
+ return true;
591
+ }
592
+ function codexGuideBlock() {
593
+ return [
594
+ CODEX_BLOCK_START,
595
+ "# codealmanac",
596
+ "",
597
+ "This machine has codealmanac installed: a local wiki for codebases.",
598
+ "Before codealmanac/wiki-related work, read `~/.codex/codealmanac.md`.",
599
+ "For the full command reference, read `~/.codex/codealmanac-reference.md` on demand.",
600
+ CODEX_BLOCK_END,
601
+ ""
602
+ ].join("\n");
603
+ }
604
+ function escapeRegex(value) {
605
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
606
+ }
542
607
  var IMPORT_LINE = "@~/.claude/codealmanac.md";
543
608
  async function ensureImport(claudeMdPath) {
544
609
  let existing = "";
@@ -625,9 +690,22 @@ function resolveGuidesDir() {
625
690
  function looksLikeGuidesDir(dir) {
626
691
  return existsSync2(path3.join(dir, "mini.md"));
627
692
  }
693
+ function printProviderNextSteps(out) {
694
+ out.write(` ${DIM2}Change provider/model later:${RST2}
695
+ `);
696
+ out.write(` ${DIM2} almanac agents list${RST2}
697
+ `);
698
+ out.write(` ${DIM2} almanac agents use <claude|codex|cursor>${RST2}
699
+ `);
700
+ out.write(
701
+ ` ${DIM2} almanac agents model <provider> <model|--default>${RST2}
702
+
703
+ `
704
+ );
705
+ }
628
706
 
629
707
  export {
630
708
  runSetup,
631
709
  IMPORT_LINE
632
710
  };
633
- //# sourceMappingURL=chunk-QRK3JLFX.js.map
711
+ //# sourceMappingURL=chunk-GFUB57IT.js.map