coding-friend-cli 1.34.0 → 1.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/chunk-2DTXVMPQ.js +26 -0
- package/dist/{chunk-OYPOADCX.js → chunk-57EGAXYI.js} +3 -3
- package/dist/{chunk-K6EDQGDN.js → chunk-B2NFXRFP.js} +17 -12
- package/dist/{chunk-3UIH5U3Y.js → chunk-C5YWESSF.js} +2 -6
- package/dist/chunk-E5J24GD5.js +190 -0
- package/dist/{chunk-UGTNIFBH.js → chunk-H5TXJZD7.js} +6 -6
- package/dist/{chunk-5X3JZKYW.js → chunk-L53RNEV3.js} +116 -73
- package/dist/{chunk-DMJCO6LJ.js → chunk-RLUNNJWJ.js} +2 -1
- package/dist/{chunk-XOHLBLN2.js → chunk-WNTMKIKC.js} +1 -1
- package/dist/chunk-WSUYLIYX.js +61 -0
- package/dist/clean-67ACB4OS.js +95 -0
- package/dist/{chunk-CXG6I6ZF.js → config-HTQAALMA.js} +182 -194
- package/dist/{dev-S6VZUD33.js → dev-PFUF67SH.js} +7 -7
- package/dist/{disable-ZWQVU3QZ.js → disable-CDOM7SSI.js} +2 -2
- package/dist/{enable-NXP6APNI.js → enable-SF7742UR.js} +2 -2
- package/dist/{host-Y3WIXDSS.js → host-HKA4OHBM.js} +3 -3
- package/dist/index.js +38 -34
- package/dist/{init-WDFYY5MM.js → init-YM7YEEGK.js} +154 -99
- package/dist/{install-FKL6WLIG.js → install-VYZSTXN6.js} +8 -8
- package/dist/{mcp-J4SD646S.js → mcp-7MO2MCLE.js} +72 -67
- package/dist/{mcp-serve-learn-UNW6VH5M.js → mcp-serve-learn-OKVC5WV3.js} +19 -3
- package/dist/{memory-RLZR7XQY.js → memory-XALEMWQF.js} +7 -7
- package/dist/{permission-DNW7DE24.js → permission-C5R3LMZQ.js} +2 -2
- package/dist/postinstall.js +1 -1
- package/dist/{session-6WQGKIRG.js → session-M4KRQ4VU.js} +2 -2
- package/dist/{status-BX2SVBBW.js → status-2XM5OZDR.js} +19 -14
- package/dist/{statusline-MLLKBHHR.js → statusline-VFIA7OS2.js} +3 -3
- package/dist/{uninstall-6ZJRS2H4.js → uninstall-QKEC3O64.js} +6 -6
- package/dist/{update-G5HZINBK.js → update-IV4Y3T72.js} +6 -6
- package/package.json +1 -1
- package/dist/chunk-AYIREX73.js +0 -85
- package/dist/chunk-TVAY4OQL.js +0 -118
- package/dist/config-MCEQOLE5.js +0 -22
- package/dist/{chunk-Z5Q533UG.js → chunk-HPNRQYLM.js} +3 -3
- package/dist/{update-check-5SCD2JR2.js → update-check-BPCQ25AR.js} +3 -3
|
@@ -1,6 +1,17 @@
|
|
|
1
|
+
import {
|
|
2
|
+
listMdFilesRecursive
|
|
3
|
+
} from "./chunk-2DTXVMPQ.js";
|
|
4
|
+
import {
|
|
5
|
+
registerLearnMcp,
|
|
6
|
+
unregisterLearnMcp
|
|
7
|
+
} from "./chunk-WSUYLIYX.js";
|
|
1
8
|
import {
|
|
2
9
|
memoryConfigMenu
|
|
3
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-C5YWESSF.js";
|
|
11
|
+
import {
|
|
12
|
+
resolveLearnDir
|
|
13
|
+
} from "./chunk-B2NFXRFP.js";
|
|
14
|
+
import "./chunk-RZRT7NGT.js";
|
|
4
15
|
import {
|
|
5
16
|
findStatuslineHookPath,
|
|
6
17
|
getCurrentAccountEmail,
|
|
@@ -11,16 +22,16 @@ import {
|
|
|
11
22
|
saveStatuslineConfig,
|
|
12
23
|
selectStatuslineComponents,
|
|
13
24
|
writeStatuslineSettings
|
|
14
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-WNTMKIKC.js";
|
|
15
26
|
import {
|
|
16
27
|
ALL_COMPONENT_IDS,
|
|
17
28
|
DEFAULT_CONFIG
|
|
18
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-57EGAXYI.js";
|
|
19
30
|
import {
|
|
20
31
|
ensureShellCompletion,
|
|
21
32
|
hasShellCompletion,
|
|
22
33
|
removeShellCompletion
|
|
23
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-RLUNNJWJ.js";
|
|
24
35
|
import {
|
|
25
36
|
BACK,
|
|
26
37
|
applyDocsDirChange,
|
|
@@ -30,7 +41,8 @@ import {
|
|
|
30
41
|
getScopeLabel,
|
|
31
42
|
injectBackChoice,
|
|
32
43
|
showConfigHint
|
|
33
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-HPNRQYLM.js";
|
|
45
|
+
import "./chunk-EVGXUDX4.js";
|
|
34
46
|
import {
|
|
35
47
|
claudeLocalSettingsPath,
|
|
36
48
|
claudeProjectSettingsPath,
|
|
@@ -39,9 +51,6 @@ import {
|
|
|
39
51
|
localConfigPath,
|
|
40
52
|
resolvePath
|
|
41
53
|
} from "./chunk-TWKNGPBO.js";
|
|
42
|
-
import {
|
|
43
|
-
run
|
|
44
|
-
} from "./chunk-EVGXUDX4.js";
|
|
45
54
|
import {
|
|
46
55
|
log,
|
|
47
56
|
printBanner
|
|
@@ -58,29 +67,14 @@ import {
|
|
|
58
67
|
// src/commands/config.ts
|
|
59
68
|
import { checkbox, confirm, input, select } from "@inquirer/prompts";
|
|
60
69
|
import chalk from "chalk";
|
|
61
|
-
import {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (inLocal) return "local";
|
|
70
|
-
return "-";
|
|
71
|
-
}
|
|
72
|
-
function getLearnFieldScope(field, globalCfg, localCfg) {
|
|
73
|
-
return getNestedFieldScope("learn", field, globalCfg, localCfg);
|
|
74
|
-
}
|
|
75
|
-
function getMergedNestedValue(section, field, globalCfg, localCfg) {
|
|
76
|
-
const localSection = localCfg?.[section];
|
|
77
|
-
if (localSection?.[field] !== void 0) return localSection[field];
|
|
78
|
-
const globalSection = globalCfg?.[section];
|
|
79
|
-
return globalSection?.[field];
|
|
80
|
-
}
|
|
81
|
-
function getMergedLearnValue(field, globalCfg, localCfg) {
|
|
82
|
-
return getMergedNestedValue("learn", field, globalCfg, localCfg);
|
|
83
|
-
}
|
|
70
|
+
import {
|
|
71
|
+
cpSync,
|
|
72
|
+
existsSync,
|
|
73
|
+
mkdirSync,
|
|
74
|
+
readFileSync,
|
|
75
|
+
rmSync,
|
|
76
|
+
writeFileSync
|
|
77
|
+
} from "fs";
|
|
84
78
|
function writeToScope(scope, data) {
|
|
85
79
|
const targetPath = scope === "global" ? globalConfigPath() : localConfigPath();
|
|
86
80
|
mergeJson(targetPath, data);
|
|
@@ -143,43 +137,92 @@ async function editLanguage(globalCfg, localCfg) {
|
|
|
143
137
|
if (scope === "back") return;
|
|
144
138
|
writeToScope(scope, { language: lang });
|
|
145
139
|
}
|
|
146
|
-
async function editLearnOutputDir(globalCfg
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
140
|
+
async function editLearnOutputDir(globalCfg) {
|
|
141
|
+
const defaultLearnDir = DEFAULT_CONFIG.learn.outputDir;
|
|
142
|
+
const oldOutputDir = globalCfg?.learn?.outputDir ?? defaultLearnDir;
|
|
143
|
+
log.dim(`Current: ${oldOutputDir}`);
|
|
151
144
|
const locationChoice = await select({
|
|
152
145
|
message: "Where to store learning docs?",
|
|
153
146
|
choices: [
|
|
154
|
-
{
|
|
155
|
-
|
|
147
|
+
{
|
|
148
|
+
name: `Use default (${defaultLearnDir})`,
|
|
149
|
+
value: "default"
|
|
150
|
+
},
|
|
151
|
+
{ name: "Custom path\u2026", value: "custom" }
|
|
156
152
|
]
|
|
157
153
|
});
|
|
158
|
-
let
|
|
159
|
-
if (locationChoice === "
|
|
160
|
-
|
|
154
|
+
let newOutputDir = defaultLearnDir;
|
|
155
|
+
if (locationChoice === "custom") {
|
|
156
|
+
newOutputDir = await input({
|
|
161
157
|
message: "Enter path (absolute or ~/...):",
|
|
162
|
-
default:
|
|
163
|
-
validate: (val) =>
|
|
158
|
+
default: oldOutputDir !== defaultLearnDir ? oldOutputDir : void 0,
|
|
159
|
+
validate: (val) => {
|
|
160
|
+
if (val.length === 0) return "Path cannot be empty";
|
|
161
|
+
if (!val.startsWith("/") && !val.startsWith("~/"))
|
|
162
|
+
return "Path must be absolute (e.g. /home/user/learn) or start with ~/ (e.g. ~/learn)";
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
164
165
|
});
|
|
165
|
-
const resolved = resolvePath(
|
|
166
|
+
const resolved = resolvePath(newOutputDir);
|
|
166
167
|
if (!existsSync(resolved)) {
|
|
167
168
|
const create = await confirm({
|
|
168
169
|
message: `Folder ${resolved} doesn't exist. Create it?`,
|
|
169
170
|
default: true
|
|
170
171
|
});
|
|
171
172
|
if (create) {
|
|
172
|
-
|
|
173
|
+
mkdirSync(resolved, { recursive: true });
|
|
173
174
|
log.success(`Created ${resolved}`);
|
|
174
175
|
}
|
|
175
176
|
}
|
|
176
177
|
}
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
writeLearnField(
|
|
178
|
+
const oldResolved = resolvePath(oldOutputDir);
|
|
179
|
+
const newResolved = resolvePath(newOutputDir);
|
|
180
|
+
writeLearnField("global", "outputDir", newOutputDir);
|
|
181
|
+
if (oldResolved !== newResolved) {
|
|
182
|
+
const mdFiles = existsSync(oldResolved) ? listMdFilesRecursive(oldResolved) : [];
|
|
183
|
+
if (mdFiles.length > 0) {
|
|
184
|
+
const doMove = await confirm({
|
|
185
|
+
message: `Found ${mdFiles.length} learning doc(s) in ${oldResolved}. Move entire folder to ${newResolved}? (overwrites any existing files at target)`,
|
|
186
|
+
default: true
|
|
187
|
+
});
|
|
188
|
+
if (doMove) {
|
|
189
|
+
const existingAtTarget = existsSync(newResolved) ? listMdFilesRecursive(newResolved) : [];
|
|
190
|
+
if (existingAtTarget.length > 0) {
|
|
191
|
+
const doOverwrite = await confirm({
|
|
192
|
+
message: `${newResolved} already contains ${existingAtTarget.length} file(s). Overwrite them?`,
|
|
193
|
+
default: false
|
|
194
|
+
});
|
|
195
|
+
if (!doOverwrite) {
|
|
196
|
+
log.dim("Move cancelled. Config saved with new path.");
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
mkdirSync(newResolved, { recursive: true });
|
|
201
|
+
cpSync(oldResolved, newResolved, { recursive: true });
|
|
202
|
+
rmSync(oldResolved, { recursive: true, force: true });
|
|
203
|
+
log.success(
|
|
204
|
+
`Moved ${mdFiles.length} doc(s) from ${oldResolved} to ${newResolved}.`
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (!globalCfg?.learn?.disabled) {
|
|
209
|
+
unregisterLearnMcp();
|
|
210
|
+
const registered = registerLearnMcp(newResolved);
|
|
211
|
+
if (registered) {
|
|
212
|
+
log.success(
|
|
213
|
+
`Updated CF Learn MCP to point to ${newResolved}. Restart Claude Code to apply.`
|
|
214
|
+
);
|
|
215
|
+
} else {
|
|
216
|
+
log.warn(
|
|
217
|
+
`Could not re-register MCP. Run manually:
|
|
218
|
+
claude mcp add --scope user coding-friend-learn -- npx -y coding-friend-cli mcp-serve-learn ${newResolved}`
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
180
223
|
}
|
|
181
|
-
async function editLearnLanguage(globalCfg
|
|
182
|
-
const currentValue =
|
|
224
|
+
async function editLearnLanguage(globalCfg) {
|
|
225
|
+
const currentValue = globalCfg?.learn?.language;
|
|
183
226
|
if (currentValue) {
|
|
184
227
|
log.dim(`Current: ${currentValue}`);
|
|
185
228
|
}
|
|
@@ -200,16 +243,10 @@ async function editLearnLanguage(globalCfg, localCfg) {
|
|
|
200
243
|
lang = await input({ message: "Enter language name:" });
|
|
201
244
|
if (!lang) lang = "en";
|
|
202
245
|
}
|
|
203
|
-
|
|
204
|
-
if (scope === "back") return;
|
|
205
|
-
writeLearnField(scope, "language", lang);
|
|
246
|
+
writeLearnField("global", "language", lang);
|
|
206
247
|
}
|
|
207
|
-
async function editLearnCategories(globalCfg
|
|
208
|
-
const existingCats =
|
|
209
|
-
"categories",
|
|
210
|
-
globalCfg,
|
|
211
|
-
localCfg
|
|
212
|
-
);
|
|
248
|
+
async function editLearnCategories(globalCfg) {
|
|
249
|
+
const existingCats = globalCfg?.learn?.categories;
|
|
213
250
|
const defaultNames = DEFAULT_CONFIG.learn.categories.map((c) => c.name).join(", ");
|
|
214
251
|
const catChoices = [
|
|
215
252
|
{ name: `Use defaults (${defaultNames})`, value: "defaults" }
|
|
@@ -260,33 +297,24 @@ async function editLearnCategories(globalCfg, localCfg) {
|
|
|
260
297
|
}
|
|
261
298
|
if (customCats.length > 0) categories = customCats;
|
|
262
299
|
}
|
|
263
|
-
|
|
264
|
-
if (scope === "back") return;
|
|
265
|
-
writeLearnField(scope, "categories", categories);
|
|
300
|
+
writeLearnField("global", "categories", categories);
|
|
266
301
|
}
|
|
267
|
-
async function editLearnAutoCommit(globalCfg
|
|
268
|
-
const currentValue =
|
|
269
|
-
"autoCommit",
|
|
270
|
-
globalCfg,
|
|
271
|
-
localCfg
|
|
272
|
-
);
|
|
302
|
+
async function editLearnAutoCommit(globalCfg) {
|
|
303
|
+
const currentValue = globalCfg?.learn?.autoCommit;
|
|
273
304
|
if (currentValue !== void 0) {
|
|
274
305
|
log.dim(`Current: ${currentValue}`);
|
|
275
306
|
}
|
|
307
|
+
log.dim(
|
|
308
|
+
"Note: auto-commit only works if your learn folder is a git repository."
|
|
309
|
+
);
|
|
276
310
|
const value = await confirm({
|
|
277
311
|
message: "Auto-commit learning docs to git after each /cf-learn?",
|
|
278
312
|
default: currentValue ?? false
|
|
279
313
|
});
|
|
280
|
-
|
|
281
|
-
if (scope === "back") return;
|
|
282
|
-
writeLearnField(scope, "autoCommit", value);
|
|
314
|
+
writeLearnField("global", "autoCommit", value);
|
|
283
315
|
}
|
|
284
|
-
async function editLearnReadmeIndex(globalCfg
|
|
285
|
-
const currentValue =
|
|
286
|
-
"readmeIndex",
|
|
287
|
-
globalCfg,
|
|
288
|
-
localCfg
|
|
289
|
-
);
|
|
316
|
+
async function editLearnReadmeIndex(globalCfg) {
|
|
317
|
+
const currentValue = globalCfg?.learn?.readmeIndex;
|
|
290
318
|
if (currentValue !== void 0) {
|
|
291
319
|
log.dim(`Current: ${currentValue}`);
|
|
292
320
|
}
|
|
@@ -301,62 +329,72 @@ async function editLearnReadmeIndex(globalCfg, localCfg) {
|
|
|
301
329
|
let readmeIndex = false;
|
|
302
330
|
if (indexChoice === "single") readmeIndex = true;
|
|
303
331
|
else if (indexChoice === "per-category") readmeIndex = "per-category";
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
332
|
+
writeLearnField("global", "readmeIndex", readmeIndex);
|
|
333
|
+
}
|
|
334
|
+
async function editLearnDisabled(globalCfg) {
|
|
335
|
+
const current = globalCfg?.learn?.disabled ?? false;
|
|
336
|
+
log.dim(`Current: ${current ? "disabled" : "enabled"}`);
|
|
337
|
+
const value = await confirm({
|
|
338
|
+
message: current ? "CF Learn is disabled. Re-enable it? (resumes file writing and re-registers MCP)" : "Disable CF Learn? (stops file writing and MCP serving)",
|
|
339
|
+
default: !current
|
|
340
|
+
});
|
|
341
|
+
writeLearnField("global", "disabled", value ? !current : current);
|
|
342
|
+
if (!current && value) {
|
|
343
|
+
const unregistered = unregisterLearnMcp();
|
|
344
|
+
if (unregistered) {
|
|
345
|
+
log.dim(
|
|
346
|
+
"Removed coding-friend-learn from Claude Code MCP. Restart Claude Code to apply."
|
|
347
|
+
);
|
|
348
|
+
} else {
|
|
349
|
+
log.warn(
|
|
350
|
+
"Could not unregister MCP automatically. Run manually:\n claude mcp remove --scope user coding-friend-learn"
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
} else if (current && value) {
|
|
354
|
+
const freshGlobal = readJson(globalConfigPath());
|
|
355
|
+
const learnDir = resolveLearnDir(freshGlobal);
|
|
356
|
+
registerLearnMcp(learnDir);
|
|
357
|
+
log.dim(
|
|
358
|
+
"Re-registered coding-friend-learn. Restart Claude Code to activate."
|
|
359
|
+
);
|
|
360
|
+
}
|
|
307
361
|
}
|
|
308
362
|
async function learnSubMenu() {
|
|
309
363
|
while (true) {
|
|
310
364
|
const globalCfg = readJson(globalConfigPath());
|
|
311
|
-
const
|
|
312
|
-
const
|
|
313
|
-
const
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
);
|
|
318
|
-
const langScope = getLearnFieldScope("language", globalCfg, localCfg);
|
|
319
|
-
const langVal = getMergedLearnValue("language", globalCfg, localCfg);
|
|
320
|
-
const catScope = getLearnFieldScope("categories", globalCfg, localCfg);
|
|
321
|
-
const autoCommitScope = getLearnFieldScope(
|
|
322
|
-
"autoCommit",
|
|
323
|
-
globalCfg,
|
|
324
|
-
localCfg
|
|
325
|
-
);
|
|
326
|
-
const autoCommitVal = getMergedLearnValue(
|
|
327
|
-
"autoCommit",
|
|
328
|
-
globalCfg,
|
|
329
|
-
localCfg
|
|
330
|
-
);
|
|
331
|
-
const readmeScope = getLearnFieldScope("readmeIndex", globalCfg, localCfg);
|
|
332
|
-
const readmeVal = getMergedLearnValue(
|
|
333
|
-
"readmeIndex",
|
|
334
|
-
globalCfg,
|
|
335
|
-
localCfg
|
|
336
|
-
);
|
|
365
|
+
const outputDirVal = globalCfg?.learn?.outputDir ?? DEFAULT_CONFIG.learn.outputDir;
|
|
366
|
+
const langVal = globalCfg?.learn?.language;
|
|
367
|
+
const autoCommitVal = globalCfg?.learn?.autoCommit;
|
|
368
|
+
const readmeVal = globalCfg?.learn?.readmeIndex;
|
|
369
|
+
const isDisabled = globalCfg?.learn?.disabled ?? false;
|
|
370
|
+
const disabledLabel = isDisabled ? chalk.yellow(" [disabled]") : "";
|
|
337
371
|
const choice = await select({
|
|
338
|
-
message:
|
|
372
|
+
message: `Learn settings${disabledLabel}:`,
|
|
339
373
|
choices: injectBackChoice(
|
|
340
374
|
[
|
|
341
375
|
{
|
|
342
|
-
name: `Output dir
|
|
376
|
+
name: `Output dir (${outputDirVal})`,
|
|
343
377
|
value: "outputDir"
|
|
344
378
|
},
|
|
345
379
|
{
|
|
346
|
-
name: `Language
|
|
380
|
+
name: `Language${langVal ? ` (${langVal})` : ""}`,
|
|
347
381
|
value: "language"
|
|
348
382
|
},
|
|
349
383
|
{
|
|
350
|
-
name:
|
|
384
|
+
name: "Categories",
|
|
351
385
|
value: "categories"
|
|
352
386
|
},
|
|
353
387
|
{
|
|
354
|
-
name: `Auto-commit
|
|
388
|
+
name: `Auto-commit${autoCommitVal !== void 0 ? ` (${autoCommitVal})` : ""}`,
|
|
355
389
|
value: "autoCommit"
|
|
356
390
|
},
|
|
357
391
|
{
|
|
358
|
-
name: `README index
|
|
392
|
+
name: `README index${readmeVal !== void 0 ? ` (${readmeVal})` : ""}`,
|
|
359
393
|
value: "readmeIndex"
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
name: isDisabled ? "Enable CF Learn" : "Disable CF Learn",
|
|
397
|
+
value: "disabled"
|
|
360
398
|
}
|
|
361
399
|
],
|
|
362
400
|
"Back"
|
|
@@ -365,23 +403,39 @@ async function learnSubMenu() {
|
|
|
365
403
|
if (choice === BACK) return;
|
|
366
404
|
switch (choice) {
|
|
367
405
|
case "outputDir":
|
|
368
|
-
await editLearnOutputDir(globalCfg
|
|
406
|
+
await editLearnOutputDir(globalCfg);
|
|
369
407
|
break;
|
|
370
408
|
case "language":
|
|
371
|
-
await editLearnLanguage(globalCfg
|
|
409
|
+
await editLearnLanguage(globalCfg);
|
|
372
410
|
break;
|
|
373
411
|
case "categories":
|
|
374
|
-
await editLearnCategories(globalCfg
|
|
412
|
+
await editLearnCategories(globalCfg);
|
|
375
413
|
break;
|
|
376
414
|
case "autoCommit":
|
|
377
|
-
await editLearnAutoCommit(globalCfg
|
|
415
|
+
await editLearnAutoCommit(globalCfg);
|
|
378
416
|
break;
|
|
379
417
|
case "readmeIndex":
|
|
380
|
-
await editLearnReadmeIndex(globalCfg
|
|
418
|
+
await editLearnReadmeIndex(globalCfg);
|
|
419
|
+
break;
|
|
420
|
+
case "disabled":
|
|
421
|
+
await editLearnDisabled(globalCfg);
|
|
381
422
|
break;
|
|
382
423
|
}
|
|
383
424
|
}
|
|
384
425
|
}
|
|
426
|
+
async function editTdd(globalCfg, localCfg) {
|
|
427
|
+
const currentValue = getMergedValue("tdd", globalCfg, localCfg);
|
|
428
|
+
if (currentValue !== void 0) {
|
|
429
|
+
log.dim(`Current: ${currentValue}`);
|
|
430
|
+
}
|
|
431
|
+
const value = await confirm({
|
|
432
|
+
message: "Enable TDD by default? (writes failing tests before code \u2014 RED \u2192 GREEN \u2192 REFACTOR)",
|
|
433
|
+
default: currentValue ?? false
|
|
434
|
+
});
|
|
435
|
+
const scope = await askScope();
|
|
436
|
+
if (scope === "back") return;
|
|
437
|
+
writeToScope(scope, { tdd: value });
|
|
438
|
+
}
|
|
385
439
|
async function editAutoApprove(globalCfg, localCfg) {
|
|
386
440
|
const currentValue = getMergedValue("autoApprove", globalCfg, localCfg);
|
|
387
441
|
if (currentValue !== void 0) {
|
|
@@ -411,68 +465,6 @@ async function editAutoApprove(globalCfg, localCfg) {
|
|
|
411
465
|
log.dim("Docs: https://cf.dinhanhthi.com/docs/reference/auto-approve/");
|
|
412
466
|
}
|
|
413
467
|
}
|
|
414
|
-
function buildCodexConfig(input2) {
|
|
415
|
-
return {
|
|
416
|
-
enabled: input2.enabled,
|
|
417
|
-
modes: input2.modes,
|
|
418
|
-
effort: input2.effort
|
|
419
|
-
};
|
|
420
|
-
}
|
|
421
|
-
async function editCodex(globalCfg, localCfg) {
|
|
422
|
-
const current = localCfg?.codex ?? globalCfg?.codex;
|
|
423
|
-
const defaults = DEFAULT_CONFIG.codex;
|
|
424
|
-
if (current !== void 0) {
|
|
425
|
-
log.dim(
|
|
426
|
-
`Current: enabled=${current.enabled}, modes=${(current.modes ?? []).join(",") || "(none)"}, effort=${current.effort}`
|
|
427
|
-
);
|
|
428
|
-
}
|
|
429
|
-
const enabled = await confirm({
|
|
430
|
-
message: "Enable Codex as 6th specialist in /cf-review? (requires `codex` CLI in PATH)",
|
|
431
|
-
default: current?.enabled ?? defaults.enabled
|
|
432
|
-
});
|
|
433
|
-
const modes = await checkbox({
|
|
434
|
-
message: "Which review modes should Codex run in?",
|
|
435
|
-
choices: [
|
|
436
|
-
{ name: "QUICK (\u22643 files, \u226450 lines)", value: "QUICK" },
|
|
437
|
-
{ name: "STANDARD (4\u201310 files or 51\u2013300 lines)", value: "STANDARD" },
|
|
438
|
-
{
|
|
439
|
-
name: "DEEP (>10 files, >300 lines, or sensitive paths)",
|
|
440
|
-
value: "DEEP"
|
|
441
|
-
}
|
|
442
|
-
],
|
|
443
|
-
default: current?.modes ?? defaults.modes
|
|
444
|
-
});
|
|
445
|
-
if (modes.length === 0) {
|
|
446
|
-
log.dim(
|
|
447
|
-
"Warning: no modes selected \u2014 Codex will never run. Select at least one mode."
|
|
448
|
-
);
|
|
449
|
-
}
|
|
450
|
-
const effort = await select({
|
|
451
|
-
message: "Codex reasoning effort level:",
|
|
452
|
-
choices: [
|
|
453
|
-
{ name: "minimal \u2014 fastest, least thorough", value: "minimal" },
|
|
454
|
-
{ name: "low", value: "low" },
|
|
455
|
-
{ name: "medium (default)", value: "medium" },
|
|
456
|
-
{ name: "high", value: "high" },
|
|
457
|
-
{ name: "xhigh \u2014 slowest, most thorough", value: "xhigh" }
|
|
458
|
-
],
|
|
459
|
-
default: current?.effort ?? defaults.effort
|
|
460
|
-
});
|
|
461
|
-
const scope = await askScope();
|
|
462
|
-
if (scope === "back") return;
|
|
463
|
-
const codexCfg = buildCodexConfig({ enabled, modes, effort });
|
|
464
|
-
writeToScope(scope, { codex: codexCfg });
|
|
465
|
-
if (enabled) {
|
|
466
|
-
log.dim(
|
|
467
|
-
"Tip: make sure `codex` CLI is installed \u2014 `npm install -g @openai/codex`"
|
|
468
|
-
);
|
|
469
|
-
log.dim(
|
|
470
|
-
"Docs: https://cf.dinhanhthi.com/docs/configuration/config-json/#codex"
|
|
471
|
-
);
|
|
472
|
-
} else {
|
|
473
|
-
log.dim("Codex disabled.");
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
468
|
async function editStatusline() {
|
|
477
469
|
const hookResult = findStatuslineHookPath();
|
|
478
470
|
if (!hookResult) {
|
|
@@ -525,7 +517,6 @@ async function editGitignore(globalCfg, localCfg) {
|
|
|
525
517
|
`${docsDir}/plans/`,
|
|
526
518
|
`${docsDir}/memory/`,
|
|
527
519
|
`${docsDir}/research/`,
|
|
528
|
-
`${docsDir}/learn/`,
|
|
529
520
|
`${docsDir}/sessions/`,
|
|
530
521
|
`${docsDir}/reviews/`,
|
|
531
522
|
`${docsDir}/context/`,
|
|
@@ -653,7 +644,7 @@ async function editPermissions() {
|
|
|
653
644
|
)
|
|
654
645
|
});
|
|
655
646
|
if (choice === BACK) return;
|
|
656
|
-
const { permissionCommand } = await import("./permission-
|
|
647
|
+
const { permissionCommand } = await import("./permission-C5R3LMZQ.js");
|
|
657
648
|
switch (choice) {
|
|
658
649
|
case "interactive":
|
|
659
650
|
await permissionCommand({});
|
|
@@ -680,14 +671,14 @@ async function configCommand() {
|
|
|
680
671
|
const langVal = getMergedValue("language", globalCfg, localCfg);
|
|
681
672
|
const learnScope = getScopeLabel("learn", globalCfg, localCfg);
|
|
682
673
|
const memoryScope = getScopeLabel("memory", globalCfg, localCfg);
|
|
674
|
+
const tddScope = getScopeLabel("tdd", globalCfg, localCfg);
|
|
675
|
+
const tddVal = getMergedValue("tdd", globalCfg, localCfg);
|
|
683
676
|
const autoApproveScope = getScopeLabel("autoApprove", globalCfg, localCfg);
|
|
684
677
|
const autoApproveVal = getMergedValue(
|
|
685
678
|
"autoApprove",
|
|
686
679
|
globalCfg,
|
|
687
680
|
localCfg
|
|
688
681
|
);
|
|
689
|
-
const codexScope = getScopeLabel("codex", globalCfg, localCfg);
|
|
690
|
-
const codexEnabled = getMergedValue("codex", globalCfg, localCfg)?.enabled;
|
|
691
682
|
const statuslineStatus = isStatuslineConfigured() ? chalk.green("configured") : chalk.yellow("not configured");
|
|
692
683
|
const completionStatus = hasShellCompletion() ? chalk.green("installed") : chalk.yellow("not installed");
|
|
693
684
|
const projectRules = getExistingRules(claudeLocalSettingsPath());
|
|
@@ -723,16 +714,16 @@ async function configCommand() {
|
|
|
723
714
|
value: "memory",
|
|
724
715
|
description: " Tier, auto-capture, auto-start, embedding provider"
|
|
725
716
|
},
|
|
717
|
+
{
|
|
718
|
+
name: `TDD ${formatScopeLabel(tddScope)}${tddVal !== void 0 ? ` (${tddVal})` : ""}`,
|
|
719
|
+
value: "tdd",
|
|
720
|
+
description: " Enable TDD (RED\u2192GREEN\u2192REFACTOR) by default for all implementations"
|
|
721
|
+
},
|
|
726
722
|
{
|
|
727
723
|
name: `Auto-approve ${formatScopeLabel(autoApproveScope)}${autoApproveVal !== void 0 ? ` (${autoApproveVal})` : ""}`,
|
|
728
724
|
value: "autoApprove",
|
|
729
725
|
description: " Auto-approve safe tool calls, block destructive ones, prompt for ambiguous"
|
|
730
726
|
},
|
|
731
|
-
{
|
|
732
|
-
name: `Codex cross-engine review ${formatScopeLabel(codexScope)}${codexEnabled !== void 0 ? ` (${codexEnabled ? "enabled" : "disabled"})` : ""}`,
|
|
733
|
-
value: "codex",
|
|
734
|
-
description: " Enable OpenAI Codex as 6th specialist in /cf-review (opt-in)"
|
|
735
|
-
},
|
|
736
727
|
{
|
|
737
728
|
name: `Statusline (${statuslineStatus})`,
|
|
738
729
|
value: "statusline",
|
|
@@ -773,12 +764,12 @@ async function configCommand() {
|
|
|
773
764
|
case "memory":
|
|
774
765
|
await memoryConfigMenu();
|
|
775
766
|
break;
|
|
767
|
+
case "tdd":
|
|
768
|
+
await editTdd(globalCfg, localCfg);
|
|
769
|
+
break;
|
|
776
770
|
case "autoApprove":
|
|
777
771
|
await editAutoApprove(globalCfg, localCfg);
|
|
778
772
|
break;
|
|
779
|
-
case "codex":
|
|
780
|
-
await editCodex(globalCfg, localCfg);
|
|
781
|
-
break;
|
|
782
773
|
case "statusline":
|
|
783
774
|
await editStatusline();
|
|
784
775
|
break;
|
|
@@ -795,9 +786,6 @@ async function configCommand() {
|
|
|
795
786
|
console.log();
|
|
796
787
|
}
|
|
797
788
|
}
|
|
798
|
-
|
|
799
789
|
export {
|
|
800
|
-
buildCodexConfig,
|
|
801
|
-
editCodex,
|
|
802
790
|
configCommand
|
|
803
791
|
};
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ensureStatusline
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-WNTMKIKC.js";
|
|
4
|
+
import "./chunk-57EGAXYI.js";
|
|
5
5
|
import {
|
|
6
6
|
ensureShellCompletion
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-RLUNNJWJ.js";
|
|
8
8
|
import {
|
|
9
9
|
isMarketplaceRegistered,
|
|
10
10
|
isPluginInstalled
|
|
11
11
|
} from "./chunk-R6HDMRYL.js";
|
|
12
|
+
import {
|
|
13
|
+
commandExists,
|
|
14
|
+
run
|
|
15
|
+
} from "./chunk-EVGXUDX4.js";
|
|
12
16
|
import {
|
|
13
17
|
devStatePath,
|
|
14
18
|
knownMarketplacesPath,
|
|
15
19
|
pluginCachePath
|
|
16
20
|
} from "./chunk-TWKNGPBO.js";
|
|
17
|
-
import {
|
|
18
|
-
commandExists,
|
|
19
|
-
run
|
|
20
|
-
} from "./chunk-EVGXUDX4.js";
|
|
21
21
|
import {
|
|
22
22
|
log,
|
|
23
23
|
printBanner
|
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
} from "./chunk-R6HDMRYL.js";
|
|
5
5
|
import {
|
|
6
6
|
resolveScope
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-TWKNGPBO.js";
|
|
7
|
+
} from "./chunk-HPNRQYLM.js";
|
|
9
8
|
import "./chunk-EVGXUDX4.js";
|
|
9
|
+
import "./chunk-TWKNGPBO.js";
|
|
10
10
|
import {
|
|
11
11
|
log
|
|
12
12
|
} from "./chunk-NREZK463.js";
|
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
} from "./chunk-R6HDMRYL.js";
|
|
5
5
|
import {
|
|
6
6
|
resolveScope
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-TWKNGPBO.js";
|
|
7
|
+
} from "./chunk-HPNRQYLM.js";
|
|
9
8
|
import "./chunk-EVGXUDX4.js";
|
|
9
|
+
import "./chunk-TWKNGPBO.js";
|
|
10
10
|
import {
|
|
11
11
|
log
|
|
12
12
|
} from "./chunk-NREZK463.js";
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveDocsDir
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-B2NFXRFP.js";
|
|
4
4
|
import {
|
|
5
5
|
getLibPath
|
|
6
6
|
} from "./chunk-RZRT7NGT.js";
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-TWKNGPBO.js";
|
|
7
|
+
import "./chunk-57EGAXYI.js";
|
|
9
8
|
import {
|
|
10
9
|
run,
|
|
11
10
|
streamExec
|
|
12
11
|
} from "./chunk-EVGXUDX4.js";
|
|
12
|
+
import "./chunk-TWKNGPBO.js";
|
|
13
13
|
import {
|
|
14
14
|
log,
|
|
15
15
|
printBanner
|