coding-friend-cli 1.17.4 → 1.19.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 +9 -3
- package/dist/chunk-7CAIGH2Y.js +365 -0
- package/dist/{chunk-UWQPMVJY.js → chunk-IRPW2BMP.js} +3 -1
- package/dist/{chunk-YC6MBHCT.js → chunk-JFGLNTZI.js} +13 -0
- package/dist/{chunk-DVMWMXDZ.js → chunk-NEQZP5D4.js} +31 -6
- package/dist/{chunk-KTX4MGMR.js → chunk-QMD7P67N.js} +24 -4
- package/dist/chunk-WEMDLEK5.js +331 -0
- package/dist/{config-HVWEV2K6.js → config-UQXY45DN.js} +85 -244
- package/dist/{dev-AZSOM775.js → dev-7DLYIXBO.js} +2 -2
- package/dist/{disable-R6K5YJN4.js → disable-XYZRE3TD.js} +1 -1
- package/dist/{enable-HF4PYVJN.js → enable-3NZBQWLQ.js} +1 -1
- package/dist/{host-SYZH3FVC.js → host-QDWBFJB2.js} +1 -1
- package/dist/index.js +42 -30
- package/dist/{init-73ECEDU7.js → init-ONUC6QMM.js} +220 -35
- package/dist/{install-USFLRCS5.js → install-HLCVBOXO.js} +3 -3
- package/dist/{mcp-TBEDYELW.js → mcp-GFIOFXOL.js} +1 -1
- package/dist/{memory-BQK2R7BV.js → memory-BL37DXPU.js} +141 -21
- package/dist/{permission-L2QQR5PO.js → permission-Z3LOBJ4X.js} +72 -11
- package/dist/postinstall.js +1 -1
- package/dist/{session-H4XW2WXH.js → session-JGRF5SNX.js} +1 -1
- package/dist/status-V324NM64.js +223 -0
- package/dist/{uninstall-QSNKGNHR.js → uninstall-NNCEKPIE.js} +2 -2
- package/dist/{update-PNHTIB6M.js → update-EVOGWLKX.js} +6 -2
- package/package.json +1 -1
- package/dist/chunk-56U7US6J.js +0 -198
package/README.md
CHANGED
|
@@ -48,8 +48,11 @@ cf host [path] # Build and serve learning docs at localhost:3333
|
|
|
48
48
|
cf mcp [path] # Setup MCP server for LLM integration
|
|
49
49
|
# [path] is optional, default is `docs/learn`
|
|
50
50
|
# This prints a JSON config snippet to add to your client's MCP
|
|
51
|
-
cf permission
|
|
52
|
-
cf permission --all
|
|
51
|
+
cf permission # Manage Claude Code permission rules (interactive)
|
|
52
|
+
cf permission --all # Apply all recommended permissions without prompts
|
|
53
|
+
cf permission --user # Save to user-level settings (~/.claude/settings.json)
|
|
54
|
+
cf permission --project # Save to project-level settings (.claude/settings.local.json)
|
|
55
|
+
cf permission --all --user # Apply all recommended permissions to user settings
|
|
53
56
|
cf statusline # Setup coding-friend statusline
|
|
54
57
|
cf update # Update plugin + CLI + statusline
|
|
55
58
|
cf update --cli # Update only the CLI (npm package)
|
|
@@ -73,8 +76,11 @@ cf memory rm --prune # Remove orphaned projects (source dir missing or 0
|
|
|
73
76
|
cf memory start-daemon # Start memory daemon (enables Tier 2 search)
|
|
74
77
|
cf memory stop-daemon # Stop memory daemon
|
|
75
78
|
cf memory rebuild # Rebuild search index from markdown files
|
|
76
|
-
cf memory init # Initialize
|
|
79
|
+
cf memory init # Initialize memory system (interactive wizard)
|
|
80
|
+
cf memory config # Configure memory system settings
|
|
77
81
|
cf memory mcp # Show MCP server config for clients
|
|
82
|
+
cf status # Show comprehensive Coding Friend status
|
|
83
|
+
# (versions, plugin, memory, config)
|
|
78
84
|
cf session save # Save current Claude Code session to docs/sessions/
|
|
79
85
|
cf session load # Load a saved session from docs/sessions/
|
|
80
86
|
cf help # Show all commands
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import {
|
|
2
|
+
readJson,
|
|
3
|
+
writeJson
|
|
4
|
+
} from "./chunk-RWUTFVRB.js";
|
|
5
|
+
|
|
6
|
+
// src/lib/permissions.ts
|
|
7
|
+
import { homedir } from "os";
|
|
8
|
+
var STATIC_RULES = [
|
|
9
|
+
// Core Utilities (hooks & infrastructure)
|
|
10
|
+
{
|
|
11
|
+
rule: "Bash(cat *)",
|
|
12
|
+
description: "[read-only] Read file contents \xB7 Used by: session-init hook, skills",
|
|
13
|
+
category: "Core Utilities",
|
|
14
|
+
recommended: true
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
rule: "Bash(grep *)",
|
|
18
|
+
description: "[read-only] Search file contents \xB7 Used by: session-init hook, skills",
|
|
19
|
+
category: "Core Utilities",
|
|
20
|
+
recommended: true
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
rule: "Bash(sed *)",
|
|
24
|
+
description: "[modify] Text transformation \xB7 Used by: session-init hook",
|
|
25
|
+
category: "Core Utilities",
|
|
26
|
+
recommended: true
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
rule: "Bash(tr *)",
|
|
30
|
+
description: "[read-only] Character translation \xB7 Used by: session-init hook",
|
|
31
|
+
category: "Core Utilities",
|
|
32
|
+
recommended: true
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
rule: "Bash(wc *)",
|
|
36
|
+
description: "[read-only] Count lines/words \xB7 Used by: cf-verification, skills",
|
|
37
|
+
category: "Core Utilities",
|
|
38
|
+
recommended: true
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
rule: "Bash(mkdir *)",
|
|
42
|
+
description: "[write] Create directories \xB7 Used by: docs folder setup, /tmp/coding-friend",
|
|
43
|
+
category: "Core Utilities",
|
|
44
|
+
recommended: true
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
rule: "Bash(find *)",
|
|
48
|
+
description: "[read-only] Find files \xB7 Used by: /cf-learn list-learn-files",
|
|
49
|
+
category: "Core Utilities",
|
|
50
|
+
recommended: true
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
rule: "Bash(ls *)",
|
|
54
|
+
description: "[read-only] List files \xB7 Used by: statusline hook, session-init hook",
|
|
55
|
+
category: "Core Utilities",
|
|
56
|
+
recommended: true
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
rule: "Bash(jq *)",
|
|
60
|
+
description: "[read-only] Parse JSON \xB7 Used by: statusline hook, session-init hook, memory-capture hook",
|
|
61
|
+
category: "Core Utilities",
|
|
62
|
+
recommended: true
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
rule: "Bash(date *)",
|
|
66
|
+
description: "[read-only] Format timestamps \xB7 Used by: statusline hook",
|
|
67
|
+
category: "Core Utilities",
|
|
68
|
+
recommended: true
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
rule: "Bash(pwd)",
|
|
72
|
+
description: "[read-only] Get current directory \xB7 Used by: session-init hook, /cf-learn",
|
|
73
|
+
category: "Core Utilities",
|
|
74
|
+
recommended: true
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
rule: "Bash(stat *)",
|
|
78
|
+
description: "[read-only] File stats \xB7 Used by: statusline hook cache check",
|
|
79
|
+
category: "Core Utilities",
|
|
80
|
+
recommended: true
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
rule: "Bash(node -e *)",
|
|
84
|
+
description: "[execute] Run inline Node.js \xB7 Used by: memory-capture hook JSON parsing",
|
|
85
|
+
category: "Core Utilities",
|
|
86
|
+
recommended: true
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
rule: "Bash(touch /tmp/coding-friend/*)",
|
|
90
|
+
description: "[write] Create temp marker files \xB7 Used by: /cf-review mark-reviewed",
|
|
91
|
+
category: "Core Utilities",
|
|
92
|
+
recommended: true
|
|
93
|
+
},
|
|
94
|
+
// Git Operations
|
|
95
|
+
{
|
|
96
|
+
rule: "Bash(git status *)",
|
|
97
|
+
description: "[read-only] Check working tree status \xB7 Used by: /cf-commit, /cf-review, cf-verification",
|
|
98
|
+
category: "Git",
|
|
99
|
+
recommended: true
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
rule: "Bash(git diff *)",
|
|
103
|
+
description: "[read-only] View file changes \xB7 Used by: /cf-commit, /cf-review, cf-verification",
|
|
104
|
+
category: "Git",
|
|
105
|
+
recommended: true
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
rule: "Bash(git log *)",
|
|
109
|
+
description: "[read-only] View commit history \xB7 Used by: /cf-commit, /cf-review, cf-sys-debug",
|
|
110
|
+
category: "Git",
|
|
111
|
+
recommended: true
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
rule: "Bash(git branch *)",
|
|
115
|
+
description: "[read-only] List/manage branches \xB7 Used by: /cf-ship, cf-sys-debug",
|
|
116
|
+
category: "Git",
|
|
117
|
+
recommended: true
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
rule: "Bash(git rev-parse *)",
|
|
121
|
+
description: "[read-only] Check git repo state \xB7 Used by: hooks, /cf-commit",
|
|
122
|
+
category: "Git",
|
|
123
|
+
recommended: true
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
rule: "Bash(git add *)",
|
|
127
|
+
description: "[modify] Stage files for commit \xB7 Used by: /cf-commit, /cf-ship",
|
|
128
|
+
category: "Git",
|
|
129
|
+
recommended: true
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
rule: "Bash(git reset HEAD *)",
|
|
133
|
+
description: "[modify] Unstage files \xB7 Used by: /cf-commit",
|
|
134
|
+
category: "Git",
|
|
135
|
+
recommended: true
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
rule: "Bash(git commit *)",
|
|
139
|
+
description: "[modify] Create commits \xB7 Used by: /cf-commit, /cf-ship",
|
|
140
|
+
category: "Git",
|
|
141
|
+
recommended: true
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
rule: "Bash(git push *)",
|
|
145
|
+
description: "[remote] Push commits to remote \xB7 Used by: /cf-ship",
|
|
146
|
+
category: "Git",
|
|
147
|
+
recommended: true
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
rule: "Bash(git pull *)",
|
|
151
|
+
description: "[remote] Pull changes from remote \xB7 Used by: /cf-ship",
|
|
152
|
+
category: "Git",
|
|
153
|
+
recommended: true
|
|
154
|
+
},
|
|
155
|
+
// GitHub CLI
|
|
156
|
+
{
|
|
157
|
+
rule: "Bash(gh pr *)",
|
|
158
|
+
description: "[remote] Manage GitHub pull requests \xB7 Used by: /cf-ship",
|
|
159
|
+
category: "GitHub CLI",
|
|
160
|
+
recommended: true
|
|
161
|
+
},
|
|
162
|
+
// Testing & Build
|
|
163
|
+
{
|
|
164
|
+
rule: "Bash(npm test *)",
|
|
165
|
+
description: "[execute] Run test suites \xB7 Used by: cf-verification, /cf-fix, cf-tdd",
|
|
166
|
+
category: "Testing & Build",
|
|
167
|
+
recommended: true
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
rule: "Bash(npm run *)",
|
|
171
|
+
description: "[execute] Run npm scripts (build, lint, format) \xB7 Used by: cf-verification, /cf-commit",
|
|
172
|
+
category: "Testing & Build",
|
|
173
|
+
recommended: true
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
rule: "Bash(npx *)",
|
|
177
|
+
description: "[execute] Run npx commands (eslint, tsc) \xB7 Used by: cf-verification",
|
|
178
|
+
category: "Testing & Build",
|
|
179
|
+
recommended: true
|
|
180
|
+
},
|
|
181
|
+
// MCP Memory Tools
|
|
182
|
+
{
|
|
183
|
+
rule: "mcp__coding-friend-memory__memory_search",
|
|
184
|
+
description: "[read-only] Search project memories \xB7 Used by: cf-explorer agent, all skills",
|
|
185
|
+
category: "MCP Memory",
|
|
186
|
+
recommended: true
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
rule: "mcp__coding-friend-memory__memory_list",
|
|
190
|
+
description: "[read-only] List all memories \xB7 Used by: /cf-scan",
|
|
191
|
+
category: "MCP Memory",
|
|
192
|
+
recommended: true
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
rule: "mcp__coding-friend-memory__memory_retrieve",
|
|
196
|
+
description: "[read-only] Get a specific memory by ID \xB7 Used by: skills",
|
|
197
|
+
category: "MCP Memory",
|
|
198
|
+
recommended: true
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
rule: "mcp__coding-friend-memory__memory_store",
|
|
202
|
+
description: "[write] Create new memory \xB7 Used by: /cf-remember, /cf-scan, /cf-ask",
|
|
203
|
+
category: "MCP Memory",
|
|
204
|
+
recommended: true
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
rule: "mcp__coding-friend-memory__memory_update",
|
|
208
|
+
description: "[modify] Update existing memory \xB7 Used by: /cf-remember, /cf-scan",
|
|
209
|
+
category: "MCP Memory",
|
|
210
|
+
recommended: true
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
rule: "mcp__coding-friend-memory__memory_delete",
|
|
214
|
+
description: "[modify] Delete a memory \xB7 Used by: /cf-scan",
|
|
215
|
+
category: "MCP Memory",
|
|
216
|
+
recommended: true
|
|
217
|
+
},
|
|
218
|
+
// Web & Research
|
|
219
|
+
{
|
|
220
|
+
rule: "WebSearch",
|
|
221
|
+
description: "[network] Perform web searches \xB7 Used by: /cf-research",
|
|
222
|
+
category: "Web & Research",
|
|
223
|
+
recommended: false
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
rule: "WebFetch(domain:*)",
|
|
227
|
+
description: "[network] Fetch content from web pages \xB7 Used by: /cf-research",
|
|
228
|
+
category: "Web & Research",
|
|
229
|
+
recommended: false
|
|
230
|
+
}
|
|
231
|
+
];
|
|
232
|
+
var PLUGIN_CACHE_TILDE = "~/.claude/plugins/cache/coding-friend-marketplace/coding-friend";
|
|
233
|
+
function buildPluginScriptRules() {
|
|
234
|
+
const absBase = `${homedir()}/.claude/plugins/cache/coding-friend-marketplace/coding-friend`;
|
|
235
|
+
return [
|
|
236
|
+
{
|
|
237
|
+
rule: `Bash(bash ${absBase}/*)`,
|
|
238
|
+
description: "[execute] Run Coding Friend plugin scripts (unquoted) \xB7 Used by: all skills",
|
|
239
|
+
category: "Plugin Scripts",
|
|
240
|
+
recommended: true
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
rule: `Bash(bash "${absBase}/*)`,
|
|
244
|
+
description: "[execute] Run Coding Friend plugin scripts (quoted) \xB7 Used by: all skills",
|
|
245
|
+
category: "Plugin Scripts",
|
|
246
|
+
recommended: true
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
rule: `Read(${PLUGIN_CACHE_TILDE}/**)`,
|
|
250
|
+
description: "[read-only] Read plugin files \xB7 Used by: hooks, agents",
|
|
251
|
+
category: "Plugin Scripts",
|
|
252
|
+
recommended: true
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
rule: "Read(~/.coding-friend/**)",
|
|
256
|
+
description: "[read-only] Read user global config \xB7 Used by: session-init hook, /cf-learn",
|
|
257
|
+
category: "Plugin Scripts",
|
|
258
|
+
recommended: true
|
|
259
|
+
}
|
|
260
|
+
];
|
|
261
|
+
}
|
|
262
|
+
function getAllRules() {
|
|
263
|
+
return [...STATIC_RULES, ...buildPluginScriptRules()];
|
|
264
|
+
}
|
|
265
|
+
var PERMISSION_RULES = getAllRules();
|
|
266
|
+
function getExistingRules(settingsPath) {
|
|
267
|
+
const settings = readJson(settingsPath);
|
|
268
|
+
if (!settings) return [];
|
|
269
|
+
const permissions = settings.permissions;
|
|
270
|
+
return permissions?.allow ?? [];
|
|
271
|
+
}
|
|
272
|
+
function getMissingRules(existing, rules) {
|
|
273
|
+
return rules.filter((r) => !existing.includes(r.rule));
|
|
274
|
+
}
|
|
275
|
+
function buildLearnDirRules(learnPath, autoCommit) {
|
|
276
|
+
const rules = [
|
|
277
|
+
{
|
|
278
|
+
rule: `Read(${learnPath}/**)`,
|
|
279
|
+
description: "[read-only] Read learning docs \xB7 Used by: /cf-learn",
|
|
280
|
+
category: "External Learn Directory",
|
|
281
|
+
recommended: true
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
rule: `Edit(${learnPath}/**)`,
|
|
285
|
+
description: "[modify] Edit learning docs \xB7 Used by: /cf-learn",
|
|
286
|
+
category: "External Learn Directory",
|
|
287
|
+
recommended: true
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
rule: `Write(${learnPath}/**)`,
|
|
291
|
+
description: "[write] Write learning docs \xB7 Used by: /cf-learn",
|
|
292
|
+
category: "External Learn Directory",
|
|
293
|
+
recommended: true
|
|
294
|
+
}
|
|
295
|
+
];
|
|
296
|
+
if (autoCommit) {
|
|
297
|
+
const quoted = learnPath.includes(" ") ? `"${learnPath}"` : learnPath;
|
|
298
|
+
rules.push({
|
|
299
|
+
rule: `Bash(cd ${quoted} && git add *)`,
|
|
300
|
+
description: "[modify] Stage learning docs for commit \xB7 Used by: /cf-learn auto-commit",
|
|
301
|
+
category: "External Learn Directory",
|
|
302
|
+
recommended: true
|
|
303
|
+
});
|
|
304
|
+
rules.push({
|
|
305
|
+
rule: `Bash(cd ${quoted} && git commit *)`,
|
|
306
|
+
description: "[modify] Commit learning docs \xB7 Used by: /cf-learn auto-commit",
|
|
307
|
+
category: "External Learn Directory",
|
|
308
|
+
recommended: true
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
return rules;
|
|
312
|
+
}
|
|
313
|
+
function applyPermissions(settingsPath, toAdd, toRemove) {
|
|
314
|
+
const settings = readJson(settingsPath) ?? {};
|
|
315
|
+
const permissions = settings.permissions ?? {};
|
|
316
|
+
const existing = permissions.allow ?? [];
|
|
317
|
+
const afterRemove = existing.filter((r) => !toRemove.includes(r));
|
|
318
|
+
const afterAdd = [
|
|
319
|
+
...afterRemove,
|
|
320
|
+
...toAdd.filter((r) => !afterRemove.includes(r))
|
|
321
|
+
];
|
|
322
|
+
permissions.allow = afterAdd;
|
|
323
|
+
settings.permissions = permissions;
|
|
324
|
+
writeJson(settingsPath, settings);
|
|
325
|
+
}
|
|
326
|
+
function groupByCategory(rules) {
|
|
327
|
+
const groups = /* @__PURE__ */ new Map();
|
|
328
|
+
for (const rule of rules) {
|
|
329
|
+
const list = groups.get(rule.category) ?? [];
|
|
330
|
+
list.push(rule);
|
|
331
|
+
groups.set(rule.category, list);
|
|
332
|
+
}
|
|
333
|
+
return groups;
|
|
334
|
+
}
|
|
335
|
+
var OLD_PLUGIN_PATH_PATTERN = "/.claude/plugins/cache/coding-friend-marketplace/coding-friend/";
|
|
336
|
+
function cleanupStalePluginRules(settingsPath) {
|
|
337
|
+
const existing = getExistingRules(settingsPath);
|
|
338
|
+
const currentRules = new Set(getAllRules().map((r) => r.rule));
|
|
339
|
+
const stale = existing.filter(
|
|
340
|
+
(r) => r.includes(OLD_PLUGIN_PATH_PATTERN) && !currentRules.has(r)
|
|
341
|
+
);
|
|
342
|
+
if (stale.length === 0) return 0;
|
|
343
|
+
applyPermissions(settingsPath, [], stale);
|
|
344
|
+
return stale.length;
|
|
345
|
+
}
|
|
346
|
+
function logPluginScriptWarning(log, chalk) {
|
|
347
|
+
log.warn(
|
|
348
|
+
`Plugin script rules use ${chalk.bold("wide patterns")} that allow executing any script in the Coding Friend plugin cache.`
|
|
349
|
+
);
|
|
350
|
+
log.dim(
|
|
351
|
+
"This is scoped to Coding Friend only and survives plugin updates automatically."
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
export {
|
|
356
|
+
STATIC_RULES,
|
|
357
|
+
getAllRules,
|
|
358
|
+
getExistingRules,
|
|
359
|
+
getMissingRules,
|
|
360
|
+
buildLearnDirRules,
|
|
361
|
+
applyPermissions,
|
|
362
|
+
groupByCategory,
|
|
363
|
+
cleanupStalePluginRules,
|
|
364
|
+
logPluginScriptWarning
|
|
365
|
+
};
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-ORACWEDN.js";
|
|
5
5
|
import {
|
|
6
6
|
ensureShellCompletion
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-NEQZP5D4.js";
|
|
8
8
|
import {
|
|
9
9
|
resolveScope
|
|
10
10
|
} from "./chunk-C5LYVVEI.js";
|
|
@@ -255,6 +255,8 @@ async function updateCommand(opts) {
|
|
|
255
255
|
|
|
256
256
|
export {
|
|
257
257
|
semverCompare,
|
|
258
|
+
getCliVersion,
|
|
259
|
+
getLatestCliVersion,
|
|
258
260
|
getLatestVersion,
|
|
259
261
|
updateCommand
|
|
260
262
|
};
|
|
@@ -66,6 +66,18 @@ function enableMarketplaceAutoUpdate() {
|
|
|
66
66
|
return false;
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
+
function detectPluginScope() {
|
|
70
|
+
const scopeOrder = ["local", "project", "user"];
|
|
71
|
+
for (const scope of scopeOrder) {
|
|
72
|
+
const settings = readJson(
|
|
73
|
+
settingsPathForScope(scope)
|
|
74
|
+
);
|
|
75
|
+
if (!settings) continue;
|
|
76
|
+
const enabled = settings.enabledPlugins;
|
|
77
|
+
if (enabled && PLUGIN_ID in enabled) return scope;
|
|
78
|
+
}
|
|
79
|
+
return "user";
|
|
80
|
+
}
|
|
69
81
|
function setPluginEnabled(scope, enabled) {
|
|
70
82
|
const filePath = settingsPathForScope(scope);
|
|
71
83
|
const settings = readJson(filePath) ?? {};
|
|
@@ -89,5 +101,6 @@ export {
|
|
|
89
101
|
isMarketplaceRegistered,
|
|
90
102
|
isPluginDisabled,
|
|
91
103
|
enableMarketplaceAutoUpdate,
|
|
104
|
+
detectPluginScope,
|
|
92
105
|
setPluginEnabled
|
|
93
106
|
};
|
|
@@ -21,7 +21,7 @@ ${MARKER_START}
|
|
|
21
21
|
_cf_completions() {
|
|
22
22
|
local cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
23
23
|
local prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
24
|
-
local commands="install uninstall disable enable init config host mcp memory permission statusline update dev session"
|
|
24
|
+
local commands="install uninstall disable enable init config host mcp memory permission statusline update status dev session"
|
|
25
25
|
local scope_flags="--user --global --project --local"
|
|
26
26
|
local update_flags="--cli --plugin --statusline --user --global --project --local"
|
|
27
27
|
|
|
@@ -33,7 +33,7 @@ _cf_completions() {
|
|
|
33
33
|
|
|
34
34
|
# Subcommands for 'memory'
|
|
35
35
|
if [[ "\${COMP_WORDS[1]}" == "memory" && \${COMP_CWORD} -eq 2 ]]; then
|
|
36
|
-
COMPREPLY=($(compgen -W "status search list rm init start-daemon stop-daemon rebuild mcp" -- "$cur"))
|
|
36
|
+
COMPREPLY=($(compgen -W "status search list rm init config start-daemon stop-daemon rebuild mcp" -- "$cur"))
|
|
37
37
|
return
|
|
38
38
|
fi
|
|
39
39
|
|
|
@@ -61,6 +61,12 @@ _cf_completions() {
|
|
|
61
61
|
return
|
|
62
62
|
fi
|
|
63
63
|
|
|
64
|
+
# Flag completion for permission
|
|
65
|
+
if [[ "\${COMP_WORDS[1]}" == "permission" && "$cur" == -* ]]; then
|
|
66
|
+
COMPREPLY=($(compgen -W "--all --user --project" -- "$cur"))
|
|
67
|
+
return
|
|
68
|
+
fi
|
|
69
|
+
|
|
64
70
|
COMPREPLY=($(compgen -W "$commands" -- "$cur"))
|
|
65
71
|
}
|
|
66
72
|
complete -o default -F _cf_completions cf
|
|
@@ -82,6 +88,7 @@ var ZSH_FUNCTION_BODY = `_cf() {
|
|
|
82
88
|
'statusline:Setup coding-friend statusline in Claude Code'
|
|
83
89
|
'update:Update coding-friend plugin and refresh statusline'
|
|
84
90
|
'dev:Switch between local and remote plugin for development'
|
|
91
|
+
'status:Show comprehensive Coding Friend status'
|
|
85
92
|
'session:Save and load Claude Code sessions across machines'
|
|
86
93
|
)
|
|
87
94
|
|
|
@@ -110,6 +117,14 @@ var ZSH_FUNCTION_BODY = `_cf() {
|
|
|
110
117
|
_values 'flags' $scope_flags
|
|
111
118
|
elif (( CURRENT >= 3 )) && [[ "\${words[2]}" == "update" ]]; then
|
|
112
119
|
_values 'flags' $update_flags
|
|
120
|
+
elif (( CURRENT >= 3 )) && [[ "\${words[2]}" == "permission" ]]; then
|
|
121
|
+
local -a permission_flags
|
|
122
|
+
permission_flags=(
|
|
123
|
+
'--all[Apply all recommended permissions without prompts]'
|
|
124
|
+
'--user[Save to user-level settings]'
|
|
125
|
+
'--project[Save to project-level settings]'
|
|
126
|
+
)
|
|
127
|
+
_values 'flags' $permission_flags
|
|
113
128
|
elif (( CURRENT == 3 )) && [[ "\${words[2]}" == "dev" ]]; then
|
|
114
129
|
local -a subcommands
|
|
115
130
|
subcommands=(
|
|
@@ -128,7 +143,8 @@ var ZSH_FUNCTION_BODY = `_cf() {
|
|
|
128
143
|
'search:Search memories by query'
|
|
129
144
|
'list:List memories (--projects for all DBs)'
|
|
130
145
|
'rm:Remove a project database'
|
|
131
|
-
'init:Initialize
|
|
146
|
+
'init:Initialize memory system (interactive wizard)'
|
|
147
|
+
'config:Configure memory system settings'
|
|
132
148
|
'start-daemon:Start the memory daemon (Tier 2)'
|
|
133
149
|
'stop-daemon:Stop the memory daemon'
|
|
134
150
|
'rebuild:Rebuild the daemon search index'
|
|
@@ -171,6 +187,7 @@ complete -c cf -n "__fish_use_subcommand" -a permission -d "Manage Claude Code p
|
|
|
171
187
|
complete -c cf -n "__fish_use_subcommand" -a statusline -d "Setup coding-friend statusline in Claude Code"
|
|
172
188
|
complete -c cf -n "__fish_use_subcommand" -a update -d "Update coding-friend plugin and refresh statusline"
|
|
173
189
|
complete -c cf -n "__fish_use_subcommand" -a dev -d "Switch between local and remote plugin for development"
|
|
190
|
+
complete -c cf -n "__fish_use_subcommand" -a status -d "Show comprehensive Coding Friend status"
|
|
174
191
|
complete -c cf -n "__fish_use_subcommand" -a session -d "Save and load Claude Code sessions across machines"
|
|
175
192
|
# Scope flags for install/uninstall/disable/enable
|
|
176
193
|
complete -c cf -n "__fish_seen_subcommand_from install uninstall disable enable" -l user -d "User scope (all projects)"
|
|
@@ -185,6 +202,10 @@ complete -c cf -n "__fish_seen_subcommand_from update" -l user -d "User scope (a
|
|
|
185
202
|
complete -c cf -n "__fish_seen_subcommand_from update" -l global -d "User scope (all projects)"
|
|
186
203
|
complete -c cf -n "__fish_seen_subcommand_from update" -l project -d "Project scope"
|
|
187
204
|
complete -c cf -n "__fish_seen_subcommand_from update" -l local -d "Local scope"
|
|
205
|
+
# Flags for permission
|
|
206
|
+
complete -c cf -n "__fish_seen_subcommand_from permission" -l all -d "Apply all recommended permissions"
|
|
207
|
+
complete -c cf -n "__fish_seen_subcommand_from permission" -l user -d "Save to user-level settings"
|
|
208
|
+
complete -c cf -n "__fish_seen_subcommand_from permission" -l project -d "Save to project-level settings"
|
|
188
209
|
# Dev subcommands
|
|
189
210
|
complete -c cf -n "__fish_seen_subcommand_from dev" -a on -d "Switch to local plugin source"
|
|
190
211
|
complete -c cf -n "__fish_seen_subcommand_from dev" -a off -d "Switch back to remote marketplace"
|
|
@@ -197,7 +218,8 @@ complete -c cf -n "__fish_seen_subcommand_from memory" -a status -d "Show memory
|
|
|
197
218
|
complete -c cf -n "__fish_seen_subcommand_from memory" -a search -d "Search memories by query"
|
|
198
219
|
complete -c cf -n "__fish_seen_subcommand_from memory" -a list -d "List memories (--projects for all DBs)"
|
|
199
220
|
complete -c cf -n "__fish_seen_subcommand_from memory" -a rm -d "Remove a project database"
|
|
200
|
-
complete -c cf -n "__fish_seen_subcommand_from memory" -a init -d "Initialize
|
|
221
|
+
complete -c cf -n "__fish_seen_subcommand_from memory" -a init -d "Initialize memory system (interactive wizard)"
|
|
222
|
+
complete -c cf -n "__fish_seen_subcommand_from memory" -a config -d "Configure memory system settings"
|
|
201
223
|
complete -c cf -n "__fish_seen_subcommand_from memory" -a start-daemon -d "Start the memory daemon (Tier 2)"
|
|
202
224
|
complete -c cf -n "__fish_seen_subcommand_from memory" -a stop-daemon -d "Stop the memory daemon"
|
|
203
225
|
complete -c cf -n "__fish_seen_subcommand_from memory" -a rebuild -d "Rebuild the daemon search index"
|
|
@@ -211,9 +233,9 @@ var POWERSHELL_BLOCK = `
|
|
|
211
233
|
${MARKER_START}
|
|
212
234
|
Register-ArgumentCompleter -Native -CommandName cf -ScriptBlock {
|
|
213
235
|
param($wordToComplete, $commandAst, $cursorPosition)
|
|
214
|
-
$commands = @('install','uninstall','disable','enable','init','config','host','mcp','memory','permission','statusline','update','dev','session')
|
|
236
|
+
$commands = @('install','uninstall','disable','enable','init','config','host','mcp','memory','permission','statusline','update','status','dev','session')
|
|
215
237
|
$devSubcommands = @('on','off','status','restart','sync','update')
|
|
216
|
-
$memorySubcommands = @('status','search','list','rm','init','start-daemon','stop-daemon','rebuild','mcp')
|
|
238
|
+
$memorySubcommands = @('status','search','list','rm','init','config','start-daemon','stop-daemon','rebuild','mcp')
|
|
217
239
|
$sessionSubcommands = @('save','load')
|
|
218
240
|
$scopeFlags = @('--user','--global','--project','--local')
|
|
219
241
|
$updateFlags = @('--cli','--plugin','--statusline','--user','--global','--project','--local')
|
|
@@ -230,6 +252,9 @@ Register-ArgumentCompleter -Native -CommandName cf -ScriptBlock {
|
|
|
230
252
|
} elseif ($words.Count -ge 2 -and ($words[1].ToString() -eq 'install' -or $words[1].ToString() -eq 'uninstall' -or $words[1].ToString() -eq 'disable' -or $words[1].ToString() -eq 'enable')) {
|
|
231
253
|
$scopeFlags | Where-Object { $_ -like "$wordToComplete*" } |
|
|
232
254
|
ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) }
|
|
255
|
+
} elseif ($words.Count -ge 2 -and $words[1].ToString() -eq 'permission') {
|
|
256
|
+
@('--all','--user','--project') | Where-Object { $_ -like "$wordToComplete*" } |
|
|
257
|
+
ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) }
|
|
233
258
|
} elseif ($words.Count -ge 2 -and $words[1].ToString() -eq 'update') {
|
|
234
259
|
$updateFlags | Where-Object { $_ -like "$wordToComplete*" } |
|
|
235
260
|
ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) }
|
|
@@ -9,10 +9,33 @@ import {
|
|
|
9
9
|
} from "./chunk-RWUTFVRB.js";
|
|
10
10
|
|
|
11
11
|
// src/lib/config.ts
|
|
12
|
+
function deepMerge(base, override) {
|
|
13
|
+
const result = { ...base };
|
|
14
|
+
for (const key of Object.keys(override)) {
|
|
15
|
+
const baseVal = result[key];
|
|
16
|
+
const overVal = override[key];
|
|
17
|
+
if (baseVal && overVal && typeof baseVal === "object" && typeof overVal === "object" && !Array.isArray(baseVal) && !Array.isArray(overVal)) {
|
|
18
|
+
result[key] = deepMerge(
|
|
19
|
+
baseVal,
|
|
20
|
+
overVal
|
|
21
|
+
);
|
|
22
|
+
} else {
|
|
23
|
+
result[key] = overVal;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
12
28
|
function loadConfig() {
|
|
13
29
|
const global = readJson(globalConfigPath());
|
|
14
30
|
const local = readJson(localConfigPath());
|
|
15
|
-
|
|
31
|
+
const base = deepMerge(
|
|
32
|
+
DEFAULT_CONFIG,
|
|
33
|
+
global ?? {}
|
|
34
|
+
);
|
|
35
|
+
return deepMerge(
|
|
36
|
+
base,
|
|
37
|
+
local ?? {}
|
|
38
|
+
);
|
|
16
39
|
}
|
|
17
40
|
function resolveDocsDir(explicitPath) {
|
|
18
41
|
if (explicitPath) {
|
|
@@ -33,9 +56,6 @@ function resolveMemoryDir(explicitPath) {
|
|
|
33
56
|
return resolvePath(explicitPath);
|
|
34
57
|
}
|
|
35
58
|
const config = loadConfig();
|
|
36
|
-
if (config.memory?.docsDir) {
|
|
37
|
-
return resolvePath(config.memory.docsDir);
|
|
38
|
-
}
|
|
39
59
|
if (config.docsDir) {
|
|
40
60
|
return resolvePath(`${config.docsDir}/memory`);
|
|
41
61
|
}
|