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
@@ -1,4 +1,16 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ collectOption,
4
+ emit,
5
+ parsePositiveInt,
6
+ readStdin
7
+ } from "./chunk-P3LDTCLB.js";
8
+ import {
9
+ assertAgentAuth,
10
+ runAgentsList,
11
+ runSetAgentModel,
12
+ runSetDefaultAgent
13
+ } from "./chunk-R3URPHGH.js";
2
14
  import {
3
15
  addEntry,
4
16
  ancestorsInFile,
@@ -24,21 +36,9 @@ import {
24
36
  } from "./chunk-3C5SY5SE.js";
25
37
  import {
26
38
  runDoctor
27
- } from "./chunk-QLHJP2XK.js";
39
+ } from "./chunk-D3B2EEHL.js";
40
+ import "./chunk-V3QOQSXI.js";
28
41
  import "./chunk-4CODZRHH.js";
29
- import {
30
- runUninstall
31
- } from "./chunk-BJVZLP6O.js";
32
- import {
33
- runUpdate
34
- } from "./chunk-Z6MBJ3D2.js";
35
- import {
36
- collectOption,
37
- emit,
38
- parsePositiveInt,
39
- readStdin
40
- } from "./chunk-P3LDTCLB.js";
41
- import "./chunk-QHQ6YH7U.js";
42
42
  import {
43
43
  BLUE,
44
44
  BOLD,
@@ -46,16 +46,27 @@ import {
46
46
  RST
47
47
  } from "./chunk-FM3VRDK7.js";
48
48
  import {
49
- assertClaudeAuth,
50
- resolveClaudeExecutable,
49
+ runUninstall
50
+ } from "./chunk-MX2EW5MR.js";
51
+ import {
51
52
  runSetup
52
- } from "./chunk-3LC55TG6.js";
53
+ } from "./chunk-ZDJSJIB6.js";
53
54
  import {
54
55
  runHookInstall,
55
56
  runHookStatus,
56
57
  runHookUninstall
57
- } from "./chunk-Z4MWLVS2.js";
58
- import "./chunk-AXFPUHBN.js";
58
+ } from "./chunk-447U3GQJ.js";
59
+ import {
60
+ resolveClaudeExecutable
61
+ } from "./chunk-SSYMRT4I.js";
62
+ import {
63
+ runUpdate
64
+ } from "./chunk-QQHIVTXT.js";
65
+ import "./chunk-F53U6JQG.js";
66
+ import {
67
+ isAgentProviderId,
68
+ readConfig
69
+ } from "./chunk-WRUSDYYE.js";
59
70
  import {
60
71
  findNearestAlmanacDir,
61
72
  getRepoAlmanacDir
@@ -1761,10 +1772,33 @@ function registerQueryCommands(program) {
1761
1772
 
1762
1773
  // src/cli/register-setup-commands.ts
1763
1774
  function registerSetupCommands(program) {
1764
- program.command("setup").description("install the hook + CLAUDE.md guides (bare codealmanac alias)").option("-y, --yes", "skip prompts; install everything").option("--skip-hook", "opt out of the SessionEnd hook").option("--skip-guides", "opt out of the CLAUDE.md guides").action(
1775
+ const agents = program.command("agents").description("list supported AI agent providers and readiness");
1776
+ agents.command("list").description("show Claude, Codex, and Cursor provider status").action(async () => {
1777
+ emit(await runAgentsList());
1778
+ });
1779
+ program.command("set").description("configure codealmanac defaults").argument("<key>", "setting key, e.g. default-agent or model").argument("[value...]", "setting value").action(async (key, value) => {
1780
+ if (key === "default-agent") {
1781
+ emit(await runSetDefaultAgent({ provider: value[0] ?? "" }));
1782
+ return;
1783
+ }
1784
+ if (key === "model") {
1785
+ emit(await runSetAgentModel({
1786
+ provider: value[0] ?? "",
1787
+ model: value[1]
1788
+ }));
1789
+ return;
1790
+ }
1791
+ emit({
1792
+ stdout: "",
1793
+ stderr: "almanac: unknown setting. Use `default-agent` or `model`.\n",
1794
+ exitCode: 1
1795
+ });
1796
+ });
1797
+ program.command("setup").description("install the hook + CLAUDE.md guides (bare codealmanac alias)").option("-y, --yes", "skip prompts; install everything").option("--agent <agent>", "default agent: claude, codex, or cursor").option("--skip-hook", "opt out of the SessionEnd hook").option("--skip-guides", "opt out of the CLAUDE.md guides").action(
1765
1798
  async (opts) => {
1766
1799
  const result = await runSetup({
1767
1800
  yes: opts.yes,
1801
+ agent: opts.agent,
1768
1802
  skipHook: opts.skipHook,
1769
1803
  skipGuides: opts.skipGuides
1770
1804
  });
@@ -1869,8 +1903,19 @@ async function loadPrompt(name) {
1869
1903
  }
1870
1904
 
1871
1905
  // src/agent/sdk.ts
1906
+ import { spawn } from "child_process";
1872
1907
  import { query } from "@anthropic-ai/claude-agent-sdk";
1873
1908
  async function runAgent(opts) {
1909
+ const provider = opts.provider ?? "claude";
1910
+ if (provider === "codex") {
1911
+ return await runCodexAgent(opts);
1912
+ }
1913
+ if (provider === "cursor") {
1914
+ return await runCursorAgent(opts);
1915
+ }
1916
+ return await runClaudeAgent(opts);
1917
+ }
1918
+ async function runClaudeAgent(opts) {
1874
1919
  const claudeExecutable = resolveClaudeExecutable();
1875
1920
  const q = query({
1876
1921
  prompt: opts.prompt,
@@ -1925,6 +1970,186 @@ async function runAgent(opts) {
1925
1970
  }
1926
1971
  return { success, cost, turns, result, sessionId, error: errorMsg };
1927
1972
  }
1973
+ function combinedPrompt(opts) {
1974
+ const reviewerFallback = buildReviewerFallback(opts);
1975
+ return `${opts.systemPrompt}${reviewerFallback}
1976
+
1977
+ ---
1978
+
1979
+ ${opts.prompt}`;
1980
+ }
1981
+ function buildReviewerFallback(opts) {
1982
+ if ((opts.provider ?? "claude") === "claude") return "";
1983
+ const reviewer = opts.agents?.reviewer;
1984
+ if (reviewer === void 0) return "";
1985
+ return "\n\nNon-Claude provider note: this runtime does not receive Claude's nested Agent tool contract. When the writer prompt asks you to invoke the reviewer subagent, perform that review pass yourself before final wiki edits. Treat this reviewer prompt as read-only review guidance:\n\n" + reviewer.prompt;
1986
+ }
1987
+ async function runCodexAgent(opts) {
1988
+ const args = [
1989
+ "exec",
1990
+ "--json",
1991
+ "--sandbox",
1992
+ "workspace-write",
1993
+ "--skip-git-repo-check",
1994
+ "-C",
1995
+ opts.cwd
1996
+ ];
1997
+ if (opts.model !== void 0 && opts.model.length > 0) {
1998
+ args.push("--model", opts.model);
1999
+ }
2000
+ args.push(combinedPrompt(opts));
2001
+ return await runJsonlCli({
2002
+ command: "codex",
2003
+ args,
2004
+ cwd: opts.cwd,
2005
+ env: { ...process.env, CODEALMANAC_INTERNAL_SESSION: "1" },
2006
+ onMessage: opts.onMessage,
2007
+ parseFinal: parseCodexFinal
2008
+ });
2009
+ }
2010
+ async function runCursorAgent(opts) {
2011
+ const args = [
2012
+ "--print",
2013
+ "--output-format",
2014
+ "stream-json",
2015
+ "--stream-partial-output",
2016
+ "--trust",
2017
+ "--workspace",
2018
+ opts.cwd
2019
+ ];
2020
+ if (opts.model !== void 0 && opts.model.length > 0) {
2021
+ args.push("--model", opts.model);
2022
+ }
2023
+ args.push(combinedPrompt(opts));
2024
+ return await runJsonlCli({
2025
+ command: "cursor-agent",
2026
+ args,
2027
+ cwd: opts.cwd,
2028
+ env: { ...process.env, CODEALMANAC_INTERNAL_SESSION: "1" },
2029
+ onMessage: opts.onMessage,
2030
+ parseFinal: parseCursorFinal
2031
+ });
2032
+ }
2033
+ function runJsonlCli(opts) {
2034
+ return new Promise((resolve) => {
2035
+ const child = spawn(opts.command, opts.args, {
2036
+ cwd: opts.cwd,
2037
+ env: opts.env,
2038
+ stdio: ["ignore", "pipe", "pipe"]
2039
+ });
2040
+ let stdoutBuf = "";
2041
+ let stderr = "";
2042
+ let cost = 0;
2043
+ let turns = 0;
2044
+ let result = "";
2045
+ let sessionId;
2046
+ let success = false;
2047
+ let finalSeen = false;
2048
+ let error;
2049
+ const observe = (msg) => {
2050
+ opts.onMessage?.(msg);
2051
+ if (sessionId === void 0 && typeof msg.session_id === "string" && msg.session_id.length > 0) {
2052
+ sessionId = msg.session_id;
2053
+ }
2054
+ const final = opts.parseFinal(msg);
2055
+ if (final === null) return;
2056
+ finalSeen = true;
2057
+ if (final.cost !== void 0) cost = final.cost;
2058
+ if (final.turns !== void 0) turns = final.turns;
2059
+ if (final.result !== void 0) result = final.result;
2060
+ if (final.sessionId !== void 0) sessionId = final.sessionId;
2061
+ if (final.success !== void 0) success = final.success;
2062
+ if (final.error !== void 0) error = final.error;
2063
+ };
2064
+ const flushLines = () => {
2065
+ let idx = stdoutBuf.indexOf("\n");
2066
+ while (idx !== -1) {
2067
+ const rawLine = stdoutBuf.slice(0, idx);
2068
+ stdoutBuf = stdoutBuf.slice(idx + 1);
2069
+ const line = rawLine.trim();
2070
+ if (line.length > 0) {
2071
+ try {
2072
+ const parsed = JSON.parse(line);
2073
+ observe(parsed);
2074
+ } catch {
2075
+ }
2076
+ }
2077
+ idx = stdoutBuf.indexOf("\n");
2078
+ }
2079
+ };
2080
+ child.stdout.on("data", (chunk) => {
2081
+ stdoutBuf += chunk.toString("utf8");
2082
+ flushLines();
2083
+ });
2084
+ child.stderr.on("data", (chunk) => {
2085
+ stderr += chunk.toString("utf8");
2086
+ });
2087
+ child.on("error", (err) => {
2088
+ resolve({
2089
+ success: false,
2090
+ cost,
2091
+ turns,
2092
+ result,
2093
+ sessionId,
2094
+ error: err.code === "ENOENT" ? `${opts.command} not found on PATH` : err.message
2095
+ });
2096
+ });
2097
+ child.on("close", (code) => {
2098
+ flushLines();
2099
+ if (stdoutBuf.trim().length > 0) {
2100
+ try {
2101
+ observe(JSON.parse(stdoutBuf.trim()));
2102
+ } catch {
2103
+ }
2104
+ }
2105
+ if (code === 0 && finalSeen && success) {
2106
+ resolve({ success, cost, turns, result, sessionId });
2107
+ return;
2108
+ }
2109
+ const firstStderr = stderr.trim().split("\n")[0];
2110
+ resolve({
2111
+ success: false,
2112
+ cost,
2113
+ turns,
2114
+ result,
2115
+ sessionId,
2116
+ error: error ?? (firstStderr !== void 0 && firstStderr.length > 0 ? firstStderr : `${opts.command} exited ${code ?? 1}`)
2117
+ });
2118
+ });
2119
+ });
2120
+ }
2121
+ function parseCodexFinal(msg) {
2122
+ if (msg.type === "item.completed") {
2123
+ const item = msg.item;
2124
+ if (item !== null && typeof item === "object") {
2125
+ const obj = item;
2126
+ if (obj.type === "agent_message" && typeof obj.text === "string") {
2127
+ return { result: obj.text };
2128
+ }
2129
+ }
2130
+ return null;
2131
+ }
2132
+ if (msg.type === "turn.completed") {
2133
+ return { success: true };
2134
+ }
2135
+ if (msg.type === "turn.failed" || msg.type === "error") {
2136
+ return {
2137
+ success: false,
2138
+ error: typeof msg.message === "string" ? msg.message : typeof msg.error === "string" ? msg.error : "codex turn failed"
2139
+ };
2140
+ }
2141
+ return null;
2142
+ }
2143
+ function parseCursorFinal(msg) {
2144
+ if (msg.type !== "result") return null;
2145
+ const isError = msg.is_error === true || msg.subtype !== "success";
2146
+ return {
2147
+ success: !isError,
2148
+ result: typeof msg.result === "string" ? msg.result : "",
2149
+ sessionId: typeof msg.session_id === "string" ? msg.session_id : void 0,
2150
+ error: isError ? typeof msg.result === "string" ? msg.result : `cursor result: ${String(msg.subtype ?? "error")}` : void 0
2151
+ };
2152
+ }
1928
2153
 
1929
2154
  // src/commands/init.ts
1930
2155
  import { existsSync as existsSync4 } from "fs";
@@ -2069,8 +2294,21 @@ and optional \`files:\`. The rest is prose.
2069
2294
  // src/commands/bootstrap.ts
2070
2295
  var BOOTSTRAP_TOOLS = ["Read", "Write", "Edit", "Glob", "Grep", "Bash"];
2071
2296
  async function runBootstrap(options) {
2297
+ const providerResolution = await resolveAgentSelection({
2298
+ agent: options.agent,
2299
+ model: options.model
2300
+ });
2301
+ if (!providerResolution.ok) {
2302
+ return {
2303
+ stdout: "",
2304
+ stderr: `almanac: ${providerResolution.error}
2305
+ `,
2306
+ exitCode: 1
2307
+ };
2308
+ }
2309
+ const { provider, model } = providerResolution;
2072
2310
  try {
2073
- await assertClaudeAuth(options.spawnCli);
2311
+ await assertAgentAuth({ provider, spawnCli: options.spawnCli });
2074
2312
  } catch (err) {
2075
2313
  const msg = err instanceof Error ? err.message : String(err);
2076
2314
  return {
@@ -2137,7 +2375,8 @@ async function runBootstrap(options) {
2137
2375
  prompt: userPrompt,
2138
2376
  allowedTools: BOOTSTRAP_TOOLS,
2139
2377
  cwd: repoRoot,
2140
- model: options.model,
2378
+ provider,
2379
+ model,
2141
2380
  onMessage
2142
2381
  });
2143
2382
  } finally {
@@ -2160,6 +2399,19 @@ async function runBootstrap(options) {
2160
2399
  exitCode: 1
2161
2400
  };
2162
2401
  }
2402
+ async function resolveAgentSelection(args) {
2403
+ const config = await readConfig();
2404
+ const rawProvider = args.agent ?? config.agent.default;
2405
+ if (!isAgentProviderId(rawProvider)) {
2406
+ return {
2407
+ ok: false,
2408
+ error: `unknown agent '${rawProvider}'. Expected one of: claude, codex, cursor.`
2409
+ };
2410
+ }
2411
+ const configuredModel = config.agent.models[rawProvider] ?? void 0;
2412
+ const model = args.model !== void 0 ? args.model : configuredModel === null ? void 0 : configuredModel;
2413
+ return { ok: true, provider: rawProvider, model };
2414
+ }
2163
2415
  function formatFinalLine(result, logPath, repoRoot) {
2164
2416
  const status = result.success ? "done" : "failed";
2165
2417
  const rel = relative(repoRoot, logPath);
@@ -2210,17 +2462,23 @@ var StreamingFormatter = class {
2210
2462
  this.currentAgent = name;
2211
2463
  }
2212
2464
  handle(msg) {
2213
- if (msg.type === "assistant") {
2465
+ if (!isRecord(msg)) return;
2466
+ if (msg.type === "assistant" && isRecord(msg.message)) {
2467
+ const content = msg.message.content;
2468
+ if (!Array.isArray(content)) return;
2214
2469
  for (const block of msg.message.content) {
2215
- if (block.type !== "tool_use") continue;
2470
+ if (!isRecord(block) || block.type !== "tool_use") continue;
2471
+ if (typeof block.name !== "string") continue;
2216
2472
  this.handleToolUse(block.name, block.input);
2217
2473
  }
2218
2474
  return;
2219
2475
  }
2220
2476
  if (msg.type === "result") {
2221
2477
  const status = msg.subtype === "success" ? "done" : `failed (${msg.subtype})`;
2478
+ const cost = typeof msg.total_cost_usd === "number" ? msg.total_cost_usd : 0;
2479
+ const turns = typeof msg.num_turns === "number" ? msg.num_turns : 0;
2222
2480
  this.sink.write(
2223
- `[${status}] cost: $${msg.total_cost_usd.toFixed(3)}, turns: ${msg.num_turns}
2481
+ `[${status}] cost: $${cost.toFixed(3)}, turns: ${turns}
2224
2482
  `
2225
2483
  );
2226
2484
  return;
@@ -2292,6 +2550,9 @@ function stringField(input, key) {
2292
2550
  const value = input[key];
2293
2551
  return typeof value === "string" ? value : void 0;
2294
2552
  }
2553
+ function isRecord(value) {
2554
+ return value !== null && typeof value === "object";
2555
+ }
2295
2556
 
2296
2557
  // src/commands/capture.ts
2297
2558
  import { createHash } from "crypto";
@@ -2307,8 +2568,21 @@ var WRITER_TOOLS = ["Read", "Write", "Edit", "Glob", "Grep", "Bash", "Agent"];
2307
2568
  var REVIEWER_TOOLS = ["Read", "Grep", "Glob", "Bash"];
2308
2569
  var REVIEWER_DESCRIPTION = "Reviews proposed wiki changes against the full knowledge base for cohesion, duplication, missing links, notability, and writing conventions.";
2309
2570
  async function runCapture(options) {
2571
+ const providerResolution = await resolveAgentSelection2({
2572
+ agent: options.agent,
2573
+ model: options.model
2574
+ });
2575
+ if (!providerResolution.ok) {
2576
+ return {
2577
+ stdout: "",
2578
+ stderr: `almanac: ${providerResolution.error}
2579
+ `,
2580
+ exitCode: 1
2581
+ };
2582
+ }
2583
+ const { provider, model } = providerResolution;
2310
2584
  try {
2311
- await assertClaudeAuth(options.spawnCli);
2585
+ await assertAgentAuth({ provider, spawnCli: options.spawnCli });
2312
2586
  } catch (err) {
2313
2587
  const msg = err instanceof Error ? err.message : String(err);
2314
2588
  return {
@@ -2387,7 +2661,8 @@ Working directory: ${repoRoot}.`;
2387
2661
  allowedTools: WRITER_TOOLS,
2388
2662
  agents,
2389
2663
  cwd: repoRoot,
2390
- model: options.model,
2664
+ provider,
2665
+ model,
2391
2666
  // Capture sessions can touch many pages; give it more headroom than
2392
2667
  // bootstrap. The SDK treats `maxTurns` as a hard stop — better to
2393
2668
  // overshoot than to cut off mid-review.
@@ -2416,6 +2691,19 @@ Working directory: ${repoRoot}.`;
2416
2691
  exitCode: 0
2417
2692
  };
2418
2693
  }
2694
+ async function resolveAgentSelection2(args) {
2695
+ const config = await readConfig();
2696
+ const rawProvider = args.agent ?? config.agent.default;
2697
+ if (!isAgentProviderId(rawProvider)) {
2698
+ return {
2699
+ ok: false,
2700
+ error: `unknown agent '${rawProvider}'. Expected one of: claude, codex, cursor.`
2701
+ };
2702
+ }
2703
+ const configuredModel = config.agent.models[rawProvider] ?? void 0;
2704
+ const model = args.model !== void 0 ? args.model : configuredModel === null ? void 0 : configuredModel;
2705
+ return { ok: true, provider: rawProvider, model };
2706
+ }
2419
2707
  async function resolveTranscript(args) {
2420
2708
  if (args.explicit !== void 0 && args.explicit.length > 0) {
2421
2709
  if (!existsSync6(args.explicit)) {
@@ -2594,18 +2882,19 @@ async function runReindex(options) {
2594
2882
  function registerWikiLifecycleCommands(program) {
2595
2883
  program.command("bootstrap").description(
2596
2884
  "scaffold a wiki in this repo via an AI agent (requires ANTHROPIC_API_KEY or Claude subscription)"
2597
- ).option("--quiet", "suppress per-tool streaming; print only the final line").option("--model <model>", "override the agent model").option("--force", "overwrite an existing populated wiki (default: refuse)").action(
2885
+ ).option("--quiet", "suppress per-tool streaming; print only the final line").option("--agent <agent>", "agent provider: claude, codex, or cursor").option("--model <model>", "override the agent model").option("--force", "overwrite an existing populated wiki (default: refuse)").action(
2598
2886
  async (opts) => {
2599
2887
  const result = await runBootstrap({
2600
2888
  cwd: process.cwd(),
2601
2889
  quiet: opts.quiet,
2890
+ agent: opts.agent,
2602
2891
  model: opts.model,
2603
2892
  force: opts.force
2604
2893
  });
2605
2894
  emit(result);
2606
2895
  }
2607
2896
  );
2608
- program.command("capture [transcript]").description("run the writer/reviewer pipeline on a session (usually automatic)").option("--session <id>", "target a specific session by ID").option("--quiet", "suppress per-tool streaming; print only the final summary").option("--model <model>", "override the agent model").action(
2897
+ program.command("capture [transcript]").description("run the writer/reviewer pipeline on a session (usually automatic)").option("--session <id>", "target a specific session by ID").option("--quiet", "suppress per-tool streaming; print only the final summary").option("--agent <agent>", "agent provider: claude, codex, or cursor").option("--model <model>", "override the agent model").action(
2609
2898
  async (transcript, opts) => {
2610
2899
  await autoRegisterIfNeeded(process.cwd());
2611
2900
  const result = await runCapture({
@@ -2613,14 +2902,17 @@ function registerWikiLifecycleCommands(program) {
2613
2902
  transcriptPath: transcript,
2614
2903
  sessionId: opts.session,
2615
2904
  quiet: opts.quiet,
2905
+ agent: opts.agent,
2616
2906
  model: opts.model
2617
2907
  });
2618
2908
  emit(result);
2619
2909
  }
2620
2910
  );
2621
2911
  const hook = program.command("hook").description("manage the SessionEnd auto-capture hook");
2622
- hook.command("install").description("add a SessionEnd entry that runs 'almanac capture' on session end").action(async () => {
2623
- const result = await runHookInstall();
2912
+ hook.command("install").description("add a SessionEnd entry that runs 'almanac capture' on session end").option("--source <source>", "claude, codex, cursor, or all").action(async (opts) => {
2913
+ const result = await runHookInstall({
2914
+ source: normalizeHookSource(opts.source)
2915
+ });
2624
2916
  emit(result);
2625
2917
  });
2626
2918
  hook.command("uninstall").description("remove codealmanac's SessionEnd entry; leaves foreign entries alone").action(async () => {
@@ -2641,6 +2933,12 @@ function registerWikiLifecycleCommands(program) {
2641
2933
  if (result.exitCode !== 0) process.exitCode = result.exitCode;
2642
2934
  });
2643
2935
  }
2936
+ function normalizeHookSource(source) {
2937
+ if (source === "claude" || source === "codex" || source === "cursor" || source === "all") {
2938
+ return source;
2939
+ }
2940
+ return void 0;
2941
+ }
2644
2942
 
2645
2943
  // src/cli/register-commands.ts
2646
2944
  function registerCommands(program) {
@@ -2652,4 +2950,4 @@ function registerCommands(program) {
2652
2950
  export {
2653
2951
  registerCommands
2654
2952
  };
2655
- //# sourceMappingURL=register-commands-JHC2OFKM.js.map
2953
+ //# sourceMappingURL=register-commands-7SKQLQW4.js.map