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.
- package/README.md +9 -9
- package/dist/{agents-4Y7X24WW.js → agents-RVTQYE6A.js} +3 -3
- package/dist/{chunk-UU6FBRQO.js → chunk-6BJUYZ43.js} +15 -7
- package/dist/chunk-6BJUYZ43.js.map +1 -0
- package/dist/{chunk-BF2J4XTC.js → chunk-BGUID5BS.js} +2 -2
- package/dist/{chunk-H6QKCB7M.js → chunk-DL5BXZCX.js} +53 -3
- package/dist/chunk-DL5BXZCX.js.map +1 -0
- package/dist/{chunk-QRK3JLFX.js → chunk-GFUB57IT.js} +122 -44
- package/dist/chunk-GFUB57IT.js.map +1 -0
- package/dist/{chunk-CW4HRLMS.js → chunk-SMIK2YLU.js} +81 -73
- package/dist/chunk-SMIK2YLU.js.map +1 -0
- package/dist/{cli-MYMZ66EN.js → cli-CL4ID7EO.js} +8 -8
- package/dist/codealmanac.js +1 -1
- package/dist/{doctor-W5KQQLAX.js → doctor-DOLJRGS4.js} +4 -4
- package/dist/{register-commands-XTK2G2FB.js → register-commands-FBJ6XQ3L.js} +10 -10
- package/dist/register-commands-FBJ6XQ3L.js.map +1 -0
- package/dist/{uninstall-N7JY7ZV2.js → uninstall-DX6LFKMX.js} +4 -4
- package/guides/mini.md +3 -3
- package/guides/reference.md +7 -7
- package/package.json +1 -1
- package/dist/chunk-CW4HRLMS.js.map +0 -1
- package/dist/chunk-H6QKCB7M.js.map +0 -1
- package/dist/chunk-QRK3JLFX.js.map +0 -1
- package/dist/chunk-UU6FBRQO.js.map +0 -1
- package/dist/register-commands-XTK2G2FB.js.map +0 -1
- /package/dist/{agents-4Y7X24WW.js.map → agents-RVTQYE6A.js.map} +0 -0
- /package/dist/{chunk-BF2J4XTC.js.map → chunk-BGUID5BS.js.map} +0 -0
- /package/dist/{cli-MYMZ66EN.js.map → cli-CL4ID7EO.js.map} +0 -0
- /package/dist/{doctor-W5KQQLAX.js.map → doctor-DOLJRGS4.js.map} +0 -0
- /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
|
|
46
|
-
- lets you choose a provider model or inherit the provider default,
|
|
47
|
-
-
|
|
48
|
-
- installs auto-capture hooks for
|
|
49
|
-
-
|
|
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
|
|
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
|
|
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 +
|
|
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-
|
|
12
|
-
import "./chunk-
|
|
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-
|
|
25
|
+
//# sourceMappingURL=agents-RVTQYE6A.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
buildProviderSetupView,
|
|
4
4
|
parseAgentSelection
|
|
5
|
-
} from "./chunk-
|
|
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
|
|
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
|
-
"
|
|
34
|
-
"
|
|
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
|
|
96
|
-
` : `codealmanac: default
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
|
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-
|
|
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
|
-
|
|
8
|
+
getProviderLabel,
|
|
10
9
|
parseAgentSelection
|
|
11
|
-
} from "./chunk-
|
|
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
|
|
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
|
|
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
|
|
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, `
|
|
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, `
|
|
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
|
-
|
|
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 ? `
|
|
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
|
|
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
|
|
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}
|
|
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
|
-
|
|
492
|
-
|
|
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 {
|
|
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-
|
|
711
|
+
//# sourceMappingURL=chunk-GFUB57IT.js.map
|