codealmanac 0.2.1 → 0.2.3

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.
@@ -3,7 +3,8 @@ import {
3
3
  runAgentsList,
4
4
  runSetAgentModel,
5
5
  runSetDefaultAgent
6
- } from "./chunk-R3URPHGH.js";
6
+ } from "./chunk-PIYJQE4Z.js";
7
+ import "./chunk-TWM7I2LU.js";
7
8
  import "./chunk-SSYMRT4I.js";
8
9
  import "./chunk-WRUSDYYE.js";
9
10
  import "./chunk-7JUX4ADQ.js";
@@ -12,4 +13,4 @@ export {
12
13
  runSetAgentModel,
13
14
  runSetDefaultAgent
14
15
  };
15
- //# sourceMappingURL=agents-A4II4YJC.js.map
16
+ //# sourceMappingURL=agents-RVYQ44DB.js.map
@@ -15,7 +15,7 @@ import {
15
15
  } from "./chunk-FM3VRDK7.js";
16
16
  import {
17
17
  IMPORT_LINE
18
- } from "./chunk-ZDJSJIB6.js";
18
+ } from "./chunk-XNTNXEWY.js";
19
19
  import {
20
20
  checkClaudeAuth
21
21
  } from "./chunk-SSYMRT4I.js";
@@ -442,4 +442,4 @@ async function safeGatherWikiChecks(options) {
442
442
  export {
443
443
  runDoctor
444
444
  };
445
- //# sourceMappingURL=chunk-B2AGSRXL.js.map
445
+ //# sourceMappingURL=chunk-HNVOYWC2.js.map
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  IMPORT_LINE
4
- } from "./chunk-ZDJSJIB6.js";
4
+ } from "./chunk-XNTNXEWY.js";
5
5
  import {
6
6
  runHookUninstall
7
7
  } from "./chunk-447U3GQJ.js";
@@ -142,4 +142,4 @@ export {
142
142
  runUninstall,
143
143
  removeImportLine
144
144
  };
145
- //# sourceMappingURL=chunk-MX2EW5MR.js.map
145
+ //# sourceMappingURL=chunk-NBVIEZZQ.js.map
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ assertAgentAuth,
4
+ listProviderStatuses
5
+ } from "./chunk-TWM7I2LU.js";
6
+ import {
7
+ isAgentProviderId,
8
+ readConfig,
9
+ writeConfig
10
+ } from "./chunk-WRUSDYYE.js";
11
+
12
+ // src/commands/agents.ts
13
+ async function runAgentsList() {
14
+ const config = await readConfig();
15
+ const statuses = await listProviderStatuses();
16
+ const lines = ["codealmanac agents\n"];
17
+ for (const status of statuses) {
18
+ const selected = status.id === config.agent.default ? "*" : " ";
19
+ const auth = status.authenticated ? "ready" : "not ready";
20
+ const installed = status.installed ? "installed" : "missing";
21
+ lines.push(
22
+ `${selected} ${status.id.padEnd(6)} ${installed.padEnd(9)} ${auth.padEnd(9)} ${status.detail}`
23
+ );
24
+ }
25
+ lines.push("\nChange default with: almanac set default-agent <claude|codex|cursor>");
26
+ return { stdout: `${lines.join("\n")}
27
+ `, stderr: "", exitCode: 0 };
28
+ }
29
+ async function runSetDefaultAgent(opts) {
30
+ if (!isAgentProviderId(opts.provider)) {
31
+ return {
32
+ stdout: "",
33
+ stderr: `almanac: unknown agent '${opts.provider}'. Expected one of: claude, codex, cursor.
34
+ `,
35
+ exitCode: 1
36
+ };
37
+ }
38
+ try {
39
+ await assertAgentAuth({ provider: opts.provider });
40
+ } catch (err) {
41
+ const msg = err instanceof Error ? err.message : String(err);
42
+ return {
43
+ stdout: "",
44
+ stderr: `almanac: ${msg}
45
+ Run \`almanac agents list\` to see provider readiness.
46
+ `,
47
+ exitCode: 1
48
+ };
49
+ }
50
+ const config = await readConfig();
51
+ const next = {
52
+ ...config,
53
+ agent: {
54
+ ...config.agent,
55
+ default: opts.provider
56
+ }
57
+ };
58
+ await writeConfig(next);
59
+ return {
60
+ stdout: `codealmanac: default agent set to ${opts.provider}.
61
+ `,
62
+ stderr: "",
63
+ exitCode: 0
64
+ };
65
+ }
66
+ async function runSetAgentModel(opts) {
67
+ if (!isAgentProviderId(opts.provider)) {
68
+ return {
69
+ stdout: "",
70
+ stderr: `almanac: unknown agent '${opts.provider}'. Expected one of: claude, codex, cursor.
71
+ `,
72
+ exitCode: 1
73
+ };
74
+ }
75
+ const provider = opts.provider;
76
+ const config = await readConfig();
77
+ const model = opts.model !== void 0 && opts.model.length > 0 ? opts.model : null;
78
+ await writeConfig({
79
+ ...config,
80
+ agent: {
81
+ ...config.agent,
82
+ models: {
83
+ ...config.agent.models,
84
+ [provider]: model
85
+ }
86
+ }
87
+ });
88
+ return {
89
+ stdout: model === null ? `codealmanac: ${provider} model reset to provider default.
90
+ ` : `codealmanac: ${provider} model set to ${model}.
91
+ `,
92
+ stderr: "",
93
+ exitCode: 0
94
+ };
95
+ }
96
+
97
+ export {
98
+ runAgentsList,
99
+ runSetDefaultAgent,
100
+ runSetAgentModel
101
+ };
102
+ //# sourceMappingURL=chunk-PIYJQE4Z.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/agents.ts"],"sourcesContent":["import { assertAgentAuth, listProviderStatuses } from \"../agent/providers.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 config = await readConfig();\n const statuses = await listProviderStatuses();\n const lines = [\"codealmanac agents\\n\"];\n for (const status of statuses) {\n const selected = status.id === config.agent.default ? \"*\" : \" \";\n const auth = status.authenticated ? \"ready\" : \"not ready\";\n const installed = status.installed ? \"installed\" : \"missing\";\n lines.push(\n `${selected} ${status.id.padEnd(6)} ${installed.padEnd(9)} ${auth.padEnd(9)} ${status.detail}`,\n );\n }\n lines.push(\"\\nChange default with: almanac set default-agent <claude|codex|cursor>\");\n return { stdout: `${lines.join(\"\\n\")}\\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 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 try {\n await assertAgentAuth({ provider: opts.provider });\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n stdout: \"\",\n stderr:\n `almanac: ${msg}\\n` +\n \"Run `almanac agents list` to see provider readiness.\\n\",\n exitCode: 1,\n };\n }\n const config = await readConfig();\n const next = {\n ...config,\n agent: {\n ...config.agent,\n default: opts.provider,\n },\n };\n await writeConfig(next);\n return {\n stdout: `codealmanac: default agent set to ${opts.provider}.\\n`,\n stderr: \"\",\n exitCode: 0,\n };\n}\n\nexport async function runSetAgentModel(opts: {\n provider: string;\n model?: string;\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 const provider = opts.provider as AgentProviderId;\n const config = await readConfig();\n const model =\n opts.model !== undefined && opts.model.length > 0 ? opts.model : null;\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"],"mappings":";;;;;;;;;;;;AAcA,eAAsB,gBAAuC;AAC3D,QAAM,SAAS,MAAM,WAAW;AAChC,QAAM,WAAW,MAAM,qBAAqB;AAC5C,QAAM,QAAQ,CAAC,sBAAsB;AACrC,aAAW,UAAU,UAAU;AAC7B,UAAM,WAAW,OAAO,OAAO,OAAO,MAAM,UAAU,MAAM;AAC5D,UAAM,OAAO,OAAO,gBAAgB,UAAU;AAC9C,UAAM,YAAY,OAAO,YAAY,cAAc;AACnD,UAAM;AAAA,MACJ,GAAG,QAAQ,IAAI,OAAO,GAAG,OAAO,CAAC,CAAC,IAAI,UAAU,OAAO,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,IAAI,OAAO,MAAM;AAAA,IAC9F;AAAA,EACF;AACA,QAAM,KAAK,wEAAwE;AACnF,SAAO,EAAE,QAAQ,GAAG,MAAM,KAAK,IAAI,CAAC;AAAA,GAAM,QAAQ,IAAI,UAAU,EAAE;AACpE;AAMA,eAAsB,mBACpB,MACuB;AACvB,MAAI,CAAC,kBAAkB,KAAK,QAAQ,GAAG;AACrC,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,QACE,2BAA2B,KAAK,QAAQ;AAAA;AAAA,MAE1C,UAAU;AAAA,IACZ;AAAA,EACF;AACA,MAAI;AACF,UAAM,gBAAgB,EAAE,UAAU,KAAK,SAAS,CAAC;AAAA,EACnD,SAAS,KAAc;AACrB,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,QACE,YAAY,GAAG;AAAA;AAAA;AAAA,MAEjB,UAAU;AAAA,IACZ;AAAA,EACF;AACA,QAAM,SAAS,MAAM,WAAW;AAChC,QAAM,OAAO;AAAA,IACX,GAAG;AAAA,IACH,OAAO;AAAA,MACL,GAAG,OAAO;AAAA,MACV,SAAS,KAAK;AAAA,IAChB;AAAA,EACF;AACA,QAAM,YAAY,IAAI;AACtB,SAAO;AAAA,IACL,QAAQ,qCAAqC,KAAK,QAAQ;AAAA;AAAA,IAC1D,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ;AACF;AAEA,eAAsB,iBAAiB,MAGb;AACxB,MAAI,CAAC,kBAAkB,KAAK,QAAQ,GAAG;AACrC,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,QACE,2BAA2B,KAAK,QAAQ;AAAA;AAAA,MAE1C,UAAU;AAAA,IACZ;AAAA,EACF;AACA,QAAM,WAAW,KAAK;AACtB,QAAM,SAAS,MAAM,WAAW;AAChC,QAAM,QACJ,KAAK,UAAU,UAAa,KAAK,MAAM,SAAS,IAAI,KAAK,QAAQ;AACnE,QAAM,YAAY;AAAA,IAChB,GAAG;AAAA,IACH,OAAO;AAAA,MACL,GAAG,OAAO;AAAA,MACV,QAAQ;AAAA,QACN,GAAG,OAAO,MAAM;AAAA,QAChB,CAAC,QAAQ,GAAG;AAAA,MACd;AAAA,IACF;AAAA,EACF,CAAC;AACD,SAAO;AAAA,IACL,QACE,UAAU,OACN,gBAAgB,QAAQ;AAAA,IACxB,gBAAgB,QAAQ,iBAAiB,KAAK;AAAA;AAAA,IACpD,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ;AACF;","names":[]}
@@ -3,10 +3,7 @@ import {
3
3
  assertClaudeAuth
4
4
  } from "./chunk-SSYMRT4I.js";
5
5
  import {
6
- AGENT_PROVIDER_IDS,
7
- isAgentProviderId,
8
- readConfig,
9
- writeConfig
6
+ AGENT_PROVIDER_IDS
10
7
  } from "./chunk-WRUSDYYE.js";
11
8
 
12
9
  // src/agent/providers.ts
@@ -112,83 +109,8 @@ ${stderr}`.trim();
112
109
  });
113
110
  }
114
111
 
115
- // src/commands/agents.ts
116
- async function runAgentsList() {
117
- const config = await readConfig();
118
- const statuses = await listProviderStatuses();
119
- const lines = ["codealmanac agents\n"];
120
- for (const status of statuses) {
121
- const selected = status.id === config.agent.default ? "*" : " ";
122
- const auth = status.authenticated ? "ready" : "not ready";
123
- const installed = status.installed ? "installed" : "missing";
124
- lines.push(
125
- `${selected} ${status.id.padEnd(6)} ${installed.padEnd(9)} ${auth.padEnd(9)} ${status.detail}`
126
- );
127
- }
128
- lines.push("\nChange default with: almanac set default-agent <claude|codex|cursor>");
129
- return { stdout: `${lines.join("\n")}
130
- `, stderr: "", exitCode: 0 };
131
- }
132
- async function runSetDefaultAgent(opts) {
133
- if (!isAgentProviderId(opts.provider)) {
134
- return {
135
- stdout: "",
136
- stderr: `almanac: unknown agent '${opts.provider}'. Expected one of: claude, codex, cursor.
137
- `,
138
- exitCode: 1
139
- };
140
- }
141
- const config = await readConfig();
142
- const next = {
143
- ...config,
144
- agent: {
145
- ...config.agent,
146
- default: opts.provider
147
- }
148
- };
149
- await writeConfig(next);
150
- return {
151
- stdout: `codealmanac: default agent set to ${opts.provider}.
152
- `,
153
- stderr: "",
154
- exitCode: 0
155
- };
156
- }
157
- async function runSetAgentModel(opts) {
158
- if (!isAgentProviderId(opts.provider)) {
159
- return {
160
- stdout: "",
161
- stderr: `almanac: unknown agent '${opts.provider}'. Expected one of: claude, codex, cursor.
162
- `,
163
- exitCode: 1
164
- };
165
- }
166
- const provider = opts.provider;
167
- const config = await readConfig();
168
- const model = opts.model !== void 0 && opts.model.length > 0 ? opts.model : null;
169
- await writeConfig({
170
- ...config,
171
- agent: {
172
- ...config.agent,
173
- models: {
174
- ...config.agent.models,
175
- [provider]: model
176
- }
177
- }
178
- });
179
- return {
180
- stdout: model === null ? `codealmanac: ${provider} model reset to provider default.
181
- ` : `codealmanac: ${provider} model set to ${model}.
182
- `,
183
- stderr: "",
184
- exitCode: 0
185
- };
186
- }
187
-
188
112
  export {
189
113
  assertAgentAuth,
190
- runAgentsList,
191
- runSetDefaultAgent,
192
- runSetAgentModel
114
+ listProviderStatuses
193
115
  };
194
- //# sourceMappingURL=chunk-R3URPHGH.js.map
116
+ //# sourceMappingURL=chunk-TWM7I2LU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/agent/providers.ts"],"sourcesContent":["import { spawn, spawnSync, type ChildProcess } from \"node:child_process\";\n\nimport {\n assertClaudeAuth,\n type ClaudeAuthStatus,\n type SpawnCliFn,\n} from \"./auth.js\";\nimport {\n AGENT_PROVIDER_IDS,\n type AgentProviderId,\n} from \"../update/config.js\";\n\nexport interface ProviderStatus {\n id: AgentProviderId;\n installed: boolean;\n authenticated: boolean;\n detail: string;\n}\n\nexport async function assertAgentAuth(args: {\n provider: AgentProviderId;\n spawnCli?: SpawnCliFn;\n}): Promise<void> {\n if (args.provider === \"claude\") {\n await assertClaudeAuth(args.spawnCli);\n return;\n }\n const status = await checkProviderStatus(args.provider);\n if (!status.installed || !status.authenticated) {\n const err = new Error(`${status.id} not ready: ${status.detail}`);\n (err as { code?: string }).code = \"AGENT_AUTH_MISSING\";\n throw err;\n }\n}\n\nexport async function listProviderStatuses(\n spawnCli?: SpawnCliFn,\n): Promise<ProviderStatus[]> {\n const out: ProviderStatus[] = [];\n for (const id of AGENT_PROVIDER_IDS) {\n if (id === \"claude\") {\n out.push(await checkClaudeProvider(spawnCli));\n } else {\n out.push(await checkProviderStatus(id));\n }\n }\n return out;\n}\n\nasync function checkClaudeProvider(\n spawnCli?: SpawnCliFn,\n): Promise<ProviderStatus> {\n let auth: ClaudeAuthStatus = { loggedIn: false };\n try {\n auth = await import(\"./auth.js\").then((m) => m.checkClaudeAuth(spawnCli));\n } catch {\n auth = { loggedIn: false };\n }\n const hasApiKey =\n process.env.ANTHROPIC_API_KEY !== undefined &&\n process.env.ANTHROPIC_API_KEY.length > 0;\n const installed = commandExists(\"claude\");\n const authenticated = auth.loggedIn || hasApiKey;\n const detail = authenticated\n ? auth.email ?? (hasApiKey ? \"ANTHROPIC_API_KEY set\" : \"logged in\")\n : installed\n ? \"not logged in\"\n : \"claude not found on PATH\";\n return { id: \"claude\", installed, authenticated, detail };\n}\n\nasync function checkProviderStatus(\n provider: Exclude<AgentProviderId, \"claude\">,\n): Promise<ProviderStatus> {\n const command = provider === \"codex\" ? \"codex\" : \"cursor-agent\";\n if (!commandExists(command)) {\n return {\n id: provider,\n installed: false,\n authenticated: false,\n detail: `${command} not found on PATH`,\n };\n }\n\n const auth =\n provider === \"codex\"\n ? await runStatusCommand(command, [\"login\", \"status\"])\n : await runStatusCommand(command, [\"status\"]);\n\n return {\n id: provider,\n installed: true,\n authenticated: auth.ok,\n detail: auth.detail,\n };\n}\n\nfunction commandExists(command: string): boolean {\n const result = spawnSync(\"sh\", [\"-lc\", `command -v ${command}`], {\n encoding: \"utf8\",\n });\n return result.status === 0 && result.stdout.trim().length > 0;\n}\n\nfunction runStatusCommand(\n command: string,\n args: string[],\n): Promise<{ ok: boolean; detail: string }> {\n return new Promise((resolve) => {\n let stdout = \"\";\n let stderr = \"\";\n let child: ChildProcess;\n try {\n child = spawn(command, args, { stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n resolve({ ok: false, detail: msg });\n return;\n }\n const timer = setTimeout(() => {\n try {\n child.kill(\"SIGTERM\");\n } catch {\n // already exited\n }\n resolve({ ok: false, detail: `${command} status timed out` });\n }, 10_000);\n child.stdout?.on(\"data\", (chunk) => {\n stdout += chunk.toString(\"utf8\");\n });\n child.stderr?.on(\"data\", (chunk) => {\n stderr += chunk.toString(\"utf8\");\n });\n child.on(\"error\", (err) => {\n clearTimeout(timer);\n resolve({ ok: false, detail: err.message });\n });\n child.on(\"close\", (code) => {\n clearTimeout(timer);\n const text = `${stdout}\\n${stderr}`.trim();\n resolve({\n ok: code === 0,\n detail: text.split(\"\\n\").find((line) => line.trim().length > 0)?.trim() ??\n (code === 0 ? \"ready\" : `${command} exited ${code ?? 1}`),\n });\n });\n });\n}\n"],"mappings":";;;;;;;;;AAAA,SAAS,OAAO,iBAAoC;AAmBpD,eAAsB,gBAAgB,MAGpB;AAChB,MAAI,KAAK,aAAa,UAAU;AAC9B,UAAM,iBAAiB,KAAK,QAAQ;AACpC;AAAA,EACF;AACA,QAAM,SAAS,MAAM,oBAAoB,KAAK,QAAQ;AACtD,MAAI,CAAC,OAAO,aAAa,CAAC,OAAO,eAAe;AAC9C,UAAM,MAAM,IAAI,MAAM,GAAG,OAAO,EAAE,eAAe,OAAO,MAAM,EAAE;AAChE,IAAC,IAA0B,OAAO;AAClC,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,qBACpB,UAC2B;AAC3B,QAAM,MAAwB,CAAC;AAC/B,aAAW,MAAM,oBAAoB;AACnC,QAAI,OAAO,UAAU;AACnB,UAAI,KAAK,MAAM,oBAAoB,QAAQ,CAAC;AAAA,IAC9C,OAAO;AACL,UAAI,KAAK,MAAM,oBAAoB,EAAE,CAAC;AAAA,IACxC;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAe,oBACb,UACyB;AACzB,MAAI,OAAyB,EAAE,UAAU,MAAM;AAC/C,MAAI;AACF,WAAO,MAAM,OAAO,oBAAW,EAAE,KAAK,CAAC,MAAM,EAAE,gBAAgB,QAAQ,CAAC;AAAA,EAC1E,QAAQ;AACN,WAAO,EAAE,UAAU,MAAM;AAAA,EAC3B;AACA,QAAM,YACJ,QAAQ,IAAI,sBAAsB,UAClC,QAAQ,IAAI,kBAAkB,SAAS;AACzC,QAAM,YAAY,cAAc,QAAQ;AACxC,QAAM,gBAAgB,KAAK,YAAY;AACvC,QAAM,SAAS,gBACX,KAAK,UAAU,YAAY,0BAA0B,eACrD,YACE,kBACA;AACN,SAAO,EAAE,IAAI,UAAU,WAAW,eAAe,OAAO;AAC1D;AAEA,eAAe,oBACb,UACyB;AACzB,QAAM,UAAU,aAAa,UAAU,UAAU;AACjD,MAAI,CAAC,cAAc,OAAO,GAAG;AAC3B,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,WAAW;AAAA,MACX,eAAe;AAAA,MACf,QAAQ,GAAG,OAAO;AAAA,IACpB;AAAA,EACF;AAEA,QAAM,OACJ,aAAa,UACT,MAAM,iBAAiB,SAAS,CAAC,SAAS,QAAQ,CAAC,IACnD,MAAM,iBAAiB,SAAS,CAAC,QAAQ,CAAC;AAEhD,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,WAAW;AAAA,IACX,eAAe,KAAK;AAAA,IACpB,QAAQ,KAAK;AAAA,EACf;AACF;AAEA,SAAS,cAAc,SAA0B;AAC/C,QAAM,SAAS,UAAU,MAAM,CAAC,OAAO,cAAc,OAAO,EAAE,GAAG;AAAA,IAC/D,UAAU;AAAA,EACZ,CAAC;AACD,SAAO,OAAO,WAAW,KAAK,OAAO,OAAO,KAAK,EAAE,SAAS;AAC9D;AAEA,SAAS,iBACP,SACA,MAC0C;AAC1C,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,QAAI,SAAS;AACb,QAAI,SAAS;AACb,QAAI;AACJ,QAAI;AACF,cAAQ,MAAM,SAAS,MAAM,EAAE,OAAO,CAAC,UAAU,QAAQ,MAAM,EAAE,CAAC;AAAA,IACpE,SAAS,KAAc;AACrB,YAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,cAAQ,EAAE,IAAI,OAAO,QAAQ,IAAI,CAAC;AAClC;AAAA,IACF;AACA,UAAM,QAAQ,WAAW,MAAM;AAC7B,UAAI;AACF,cAAM,KAAK,SAAS;AAAA,MACtB,QAAQ;AAAA,MAER;AACA,cAAQ,EAAE,IAAI,OAAO,QAAQ,GAAG,OAAO,oBAAoB,CAAC;AAAA,IAC9D,GAAG,GAAM;AACT,UAAM,QAAQ,GAAG,QAAQ,CAAC,UAAU;AAClC,gBAAU,MAAM,SAAS,MAAM;AAAA,IACjC,CAAC;AACD,UAAM,QAAQ,GAAG,QAAQ,CAAC,UAAU;AAClC,gBAAU,MAAM,SAAS,MAAM;AAAA,IACjC,CAAC;AACD,UAAM,GAAG,SAAS,CAAC,QAAQ;AACzB,mBAAa,KAAK;AAClB,cAAQ,EAAE,IAAI,OAAO,QAAQ,IAAI,QAAQ,CAAC;AAAA,IAC5C,CAAC;AACD,UAAM,GAAG,SAAS,CAAC,SAAS;AAC1B,mBAAa,KAAK;AAClB,YAAM,OAAO,GAAG,MAAM;AAAA,EAAK,MAAM,GAAG,KAAK;AACzC,cAAQ;AAAA,QACN,IAAI,SAAS;AAAA,QACb,QAAQ,KAAK,MAAM,IAAI,EAAE,KAAK,CAAC,SAAS,KAAK,KAAK,EAAE,SAAS,CAAC,GAAG,KAAK,MACnE,SAAS,IAAI,UAAU,GAAG,OAAO,WAAW,QAAQ,CAAC;AAAA,MAC1D,CAAC;AAAA,IACH,CAAC;AAAA,EACH,CAAC;AACH;","names":[]}
@@ -2,6 +2,9 @@
2
2
  import {
3
3
  runHookInstall
4
4
  } from "./chunk-447U3GQJ.js";
5
+ import {
6
+ listProviderStatuses
7
+ } from "./chunk-TWM7I2LU.js";
5
8
  import {
6
9
  UNAUTHENTICATED_MESSAGE,
7
10
  checkClaudeAuth
@@ -227,7 +230,10 @@ async function runSetup(options = {}) {
227
230
  const agentChoice = await chooseDefaultAgent({
228
231
  out,
229
232
  interactive,
230
- requested: options.agent
233
+ requested: options.agent,
234
+ spawnCli: options.spawnCli,
235
+ listProviderStatuses: options.listProviderStatuses,
236
+ promptText: options.promptText ?? promptText
231
237
  });
232
238
  if (!agentChoice.ok) {
233
239
  return {
@@ -239,11 +245,12 @@ async function runSetup(options = {}) {
239
245
  }
240
246
  stepDone(out, `Default agent: ${WHITE_BOLD2}${agentChoice.provider}${RST2}`);
241
247
  out.write(BAR + "\n");
248
+ const confirmPrompt = options.confirm ?? confirm;
242
249
  const ephem = options.installPath !== void 0 ? options.installPath !== null ? detectEphemeral(options.installPath) : false : detectEphemeral(detectCurrentInstallPath());
243
250
  if (ephem) {
244
251
  let globalAction = "install";
245
252
  if (interactive) {
246
- globalAction = await confirm(
253
+ globalAction = await confirmPrompt(
247
254
  out,
248
255
  `Running from an ephemeral npx location. Install globally so 'almanac' stays on PATH?`,
249
256
  true
@@ -274,7 +281,7 @@ async function runSetup(options = {}) {
274
281
  if (options.skipHook === true) {
275
282
  hookAction = "skip";
276
283
  } else if (interactive) {
277
- hookAction = await confirm(
284
+ hookAction = await confirmPrompt(
278
285
  out,
279
286
  "Install auto-capture hooks for Claude, Codex, and Cursor?",
280
287
  true
@@ -306,7 +313,7 @@ async function runSetup(options = {}) {
306
313
  if (options.skipGuides === true) {
307
314
  guidesAction = "skip";
308
315
  } else if (interactive) {
309
- guidesAction = await confirm(
316
+ guidesAction = await confirmPrompt(
310
317
  out,
311
318
  "Install the codealmanac usage guides into ~/.claude/ and import them from CLAUDE.md?",
312
319
  true
@@ -349,12 +356,27 @@ async function safeCheckAuth(spawnCli) {
349
356
  }
350
357
  async function chooseDefaultAgent(args) {
351
358
  const config = await readConfig();
352
- let selected = args.requested ?? config.agent.default;
359
+ let statuses;
360
+ try {
361
+ statuses = args.listProviderStatuses !== void 0 ? await args.listProviderStatuses() : await listProviderStatuses(args.spawnCli);
362
+ } catch (err) {
363
+ const msg = err instanceof Error ? err.message : String(err);
364
+ return { ok: false, error: `failed to check agent providers: ${msg}` };
365
+ }
366
+ const readyProviders = statuses.filter((status) => status.installed && status.authenticated).map((status) => status.id);
367
+ if (readyProviders.length === 0) {
368
+ return {
369
+ ok: false,
370
+ error: "no ready agent providers found. Run `almanac agents list` to see provider readiness."
371
+ };
372
+ }
373
+ const defaultProvider = readyProviders.includes(config.agent.default) ? config.agent.default : readyProviders[0];
374
+ let selected = args.requested ?? defaultProvider;
353
375
  if (args.interactive && args.requested === void 0) {
354
- selected = await promptText(
376
+ selected = await args.promptText(
355
377
  args.out,
356
- "Choose default agent: claude, codex, or cursor",
357
- config.agent.default
378
+ `Choose default agent: ${formatProviderChoiceList(readyProviders)}`,
379
+ defaultProvider
358
380
  );
359
381
  }
360
382
  if (!isAgentProviderId(selected)) {
@@ -363,6 +385,13 @@ async function chooseDefaultAgent(args) {
363
385
  error: `unknown agent '${selected}'. Expected one of: claude, codex, cursor.`
364
386
  };
365
387
  }
388
+ const selectedStatus = statuses.find((status) => status.id === selected);
389
+ if (selectedStatus === void 0 || !selectedStatus.installed || !selectedStatus.authenticated) {
390
+ return {
391
+ ok: false,
392
+ error: `${selected} not ready: ${selectedStatus?.detail ?? "not available"}. Run \`almanac agents list\` to see provider readiness.`
393
+ };
394
+ }
366
395
  await writeConfig({
367
396
  ...config,
368
397
  agent: {
@@ -372,6 +401,11 @@ async function chooseDefaultAgent(args) {
372
401
  });
373
402
  return { ok: true, provider: selected };
374
403
  }
404
+ function formatProviderChoiceList(providers) {
405
+ if (providers.length === 1) return providers[0];
406
+ if (providers.length === 2) return `${providers[0]} or ${providers[1]}`;
407
+ return `${providers.slice(0, -1).join(", ")}, or ${providers.at(-1)}`;
408
+ }
375
409
  function reportAuth(out, auth) {
376
410
  if (auth.loggedIn) {
377
411
  const who = auth.email ?? "Claude account";
@@ -514,4 +548,4 @@ export {
514
548
  runSetup,
515
549
  IMPORT_LINE
516
550
  };
517
- //# sourceMappingURL=chunk-ZDJSJIB6.js.map
551
+ //# sourceMappingURL=chunk-XNTNXEWY.js.map
@@ -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 listProviderStatuses,\n type ProviderStatus,\n} from \"../agent/providers.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 provider readiness checks. */\n listProviderStatuses?: () => Promise<ProviderStatus[]>;\n /** Override the text prompt reader. */\n promptText?: PromptTextFn;\n /** Override the yes/no prompt reader. */\n confirm?: ConfirmFn;\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\ntype PromptTextFn = (\n out: NodeJS.WritableStream,\n question: string,\n defaultValue: string,\n) => Promise<string>;\n\ntype ConfirmFn = (\n out: NodeJS.WritableStream,\n question: string,\n defaultYes: boolean,\n) => Promise<InstallDecision>;\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 spawnCli: options.spawnCli,\n listProviderStatuses: options.listProviderStatuses,\n promptText: options.promptText ?? promptText,\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 confirmPrompt = options.confirm ?? confirm;\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 confirmPrompt(\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 confirmPrompt(\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 confirmPrompt(\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 spawnCli?: SpawnCliFn;\n listProviderStatuses?: () => Promise<ProviderStatus[]>;\n promptText: PromptTextFn;\n}): Promise<AgentChoice> {\n const config = await readConfig();\n let statuses: ProviderStatus[];\n try {\n statuses =\n args.listProviderStatuses !== undefined\n ? await args.listProviderStatuses()\n : await listProviderStatuses(args.spawnCli);\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return { ok: false, error: `failed to check agent providers: ${msg}` };\n }\n\n const readyProviders = statuses\n .filter((status) => status.installed && status.authenticated)\n .map((status) => status.id);\n\n if (readyProviders.length === 0) {\n return {\n ok: false,\n error:\n \"no ready agent providers found. \" +\n \"Run `almanac agents list` to see provider readiness.\",\n };\n }\n\n const defaultProvider = readyProviders.includes(config.agent.default)\n ? config.agent.default\n : readyProviders[0]!;\n\n let selected = args.requested ?? defaultProvider;\n if (args.interactive && args.requested === undefined) {\n selected = await args.promptText(\n args.out,\n `Choose default agent: ${formatProviderChoiceList(readyProviders)}`,\n defaultProvider,\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 const selectedStatus = statuses.find((status) => status.id === selected);\n if (\n selectedStatus === undefined ||\n !selectedStatus.installed ||\n !selectedStatus.authenticated\n ) {\n return {\n ok: false,\n error:\n `${selected} not ready: ${selectedStatus?.detail ?? \"not available\"}. ` +\n \"Run `almanac agents list` to see provider readiness.\",\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 formatProviderChoiceList(providers: AgentProviderId[]): string {\n if (providers.length === 1) return providers[0]!;\n if (providers.length === 2) return `${providers[0]} or ${providers[1]}`;\n return `${providers.slice(0, -1).join(\", \")}, or ${providers.at(-1)}`;\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"]}
@@ -14,8 +14,9 @@ import {
14
14
  } from "./chunk-FM3VRDK7.js";
15
15
  import {
16
16
  runSetup
17
- } from "./chunk-ZDJSJIB6.js";
17
+ } from "./chunk-XNTNXEWY.js";
18
18
  import "./chunk-447U3GQJ.js";
19
+ import "./chunk-TWM7I2LU.js";
19
20
  import "./chunk-SSYMRT4I.js";
20
21
  import {
21
22
  getStatePath,
@@ -448,7 +449,7 @@ async function run(argv, deps = {}) {
448
449
  if (await tryRunSqliteFreeCommand(argv.slice(2), runSetupFn)) {
449
450
  return;
450
451
  }
451
- const { registerCommands } = await import("./register-commands-DPH4ZWEE.js");
452
+ const { registerCommands } = await import("./register-commands-IXYE5CNZ.js");
452
453
  registerCommands(program);
453
454
  configureGroupedHelp(program);
454
455
  await program.parseAsync(argv);
@@ -516,7 +517,7 @@ async function tryRunSqliteFreeCommand(args, runSetupFn) {
516
517
  return false;
517
518
  }
518
519
  if (command === "agents") {
519
- const { runAgentsList } = await import("./agents-A4II4YJC.js");
520
+ const { runAgentsList } = await import("./agents-RVYQ44DB.js");
520
521
  if (subcommand === "list" || subcommand === void 0) {
521
522
  emit(await runAgentsList());
522
523
  return true;
@@ -524,7 +525,7 @@ async function tryRunSqliteFreeCommand(args, runSetupFn) {
524
525
  return false;
525
526
  }
526
527
  if (command === "set") {
527
- const { runSetAgentModel, runSetDefaultAgent } = await import("./agents-A4II4YJC.js");
528
+ const { runSetAgentModel, runSetDefaultAgent } = await import("./agents-RVYQ44DB.js");
528
529
  if (subcommand === "default-agent") {
529
530
  emit(await runSetDefaultAgent({ provider: args[2] ?? "" }));
530
531
  return true;
@@ -541,7 +542,7 @@ async function tryRunSqliteFreeCommand(args, runSetupFn) {
541
542
  return true;
542
543
  }
543
544
  if (command === "doctor") {
544
- const { runDoctor } = await import("./doctor-3BYSF3JD.js");
545
+ const { runDoctor } = await import("./doctor-DD7EQGCA.js");
545
546
  emit(await runDoctor({
546
547
  cwd: process.cwd(),
547
548
  ...parseDoctorFlags(args.slice(1))
@@ -549,7 +550,7 @@ async function tryRunSqliteFreeCommand(args, runSetupFn) {
549
550
  return true;
550
551
  }
551
552
  if (command === "uninstall") {
552
- const { runUninstall } = await import("./uninstall-FDIOBAAR.js");
553
+ const { runUninstall } = await import("./uninstall-OBV4Z3JE.js");
553
554
  emit(await runUninstall(parseUninstallFlags(args.slice(1))));
554
555
  return true;
555
556
  }
@@ -604,4 +605,4 @@ export {
604
605
  run,
605
606
  tryParseSetupShortcut
606
607
  };
607
- //# sourceMappingURL=cli-MZEXRV6E.js.map
608
+ //# sourceMappingURL=cli-6BOB6KAN.js.map