coding-friend-cli 1.17.2 → 1.18.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 +7 -4
- package/dist/chunk-7CAIGH2Y.js +365 -0
- package/dist/{chunk-G6CEEMAR.js → chunk-A427XMWE.js} +1 -1
- package/dist/{chunk-YO6JKGR3.js → chunk-VUAUAO2R.js} +27 -6
- package/dist/{config-LZFXXOI4.js → config-6SBGNTAQ.js} +80 -1
- package/dist/{dev-R3IYWZ3M.js → dev-MC6TGHRT.js} +1 -1
- package/dist/index.js +31 -28
- package/dist/{init-MF7ISADJ.js → init-2HLPKYXB.js} +220 -35
- package/dist/{install-Q4PWEU43.js → install-3QCRGPTY.js} +2 -2
- package/dist/{memory-3M2IY6MR.js → memory-BQK2R7BV.js} +10 -10
- package/dist/{permission-L2QQR5PO.js → permission-Z3LOBJ4X.js} +72 -11
- package/dist/postinstall.js +1 -1
- package/dist/{uninstall-3PSUDGI4.js → uninstall-5LRHXFSF.js} +1 -1
- package/dist/{update-WL6SFGGO.js → update-4YUSCBCB.js} +2 -2
- package/lib/cf-memory/CHANGELOG.md +5 -0
- package/lib/cf-memory/README.md +2 -2
- package/lib/cf-memory/package.json +1 -1
- package/lib/cf-memory/src/__tests__/project-id.test.ts +43 -0
- package/lib/cf-memory/src/backends/sqlite/index.ts +13 -11
- 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)
|
|
@@ -70,8 +73,8 @@ cf memory list --projects # List all project databases with size and metadata
|
|
|
70
73
|
cf memory rm --project-id <id> # Remove a specific project database
|
|
71
74
|
cf memory rm --all # Remove all project databases
|
|
72
75
|
cf memory rm --prune # Remove orphaned projects (source dir missing or 0 memories)
|
|
73
|
-
cf memory start
|
|
74
|
-
cf memory stop
|
|
76
|
+
cf memory start-daemon # Start memory daemon (enables Tier 2 search)
|
|
77
|
+
cf memory stop-daemon # Stop memory daemon
|
|
75
78
|
cf memory rebuild # Rebuild search index from markdown files
|
|
76
79
|
cf memory init # Initialize SQLite backend (Tier 1) and import memories
|
|
77
80
|
cf memory mcp # Show MCP server config for clients
|
|
@@ -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
|
+
};
|
|
@@ -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 stop rebuild mcp" -- "$cur"))
|
|
36
|
+
COMPREPLY=($(compgen -W "status search list rm init 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
|
|
@@ -110,6 +116,14 @@ var ZSH_FUNCTION_BODY = `_cf() {
|
|
|
110
116
|
_values 'flags' $scope_flags
|
|
111
117
|
elif (( CURRENT >= 3 )) && [[ "\${words[2]}" == "update" ]]; then
|
|
112
118
|
_values 'flags' $update_flags
|
|
119
|
+
elif (( CURRENT >= 3 )) && [[ "\${words[2]}" == "permission" ]]; then
|
|
120
|
+
local -a permission_flags
|
|
121
|
+
permission_flags=(
|
|
122
|
+
'--all[Apply all recommended permissions without prompts]'
|
|
123
|
+
'--user[Save to user-level settings]'
|
|
124
|
+
'--project[Save to project-level settings]'
|
|
125
|
+
)
|
|
126
|
+
_values 'flags' $permission_flags
|
|
113
127
|
elif (( CURRENT == 3 )) && [[ "\${words[2]}" == "dev" ]]; then
|
|
114
128
|
local -a subcommands
|
|
115
129
|
subcommands=(
|
|
@@ -129,8 +143,8 @@ var ZSH_FUNCTION_BODY = `_cf() {
|
|
|
129
143
|
'list:List memories (--projects for all DBs)'
|
|
130
144
|
'rm:Remove a project database'
|
|
131
145
|
'init:Initialize Tier 1 (SQLite + Hybrid Search)'
|
|
132
|
-
'start:Start the memory daemon (Tier 2)'
|
|
133
|
-
'stop:Stop the memory daemon'
|
|
146
|
+
'start-daemon:Start the memory daemon (Tier 2)'
|
|
147
|
+
'stop-daemon:Stop the memory daemon'
|
|
134
148
|
'rebuild:Rebuild the daemon search index'
|
|
135
149
|
'mcp:Show MCP server setup instructions'
|
|
136
150
|
)
|
|
@@ -185,6 +199,10 @@ complete -c cf -n "__fish_seen_subcommand_from update" -l user -d "User scope (a
|
|
|
185
199
|
complete -c cf -n "__fish_seen_subcommand_from update" -l global -d "User scope (all projects)"
|
|
186
200
|
complete -c cf -n "__fish_seen_subcommand_from update" -l project -d "Project scope"
|
|
187
201
|
complete -c cf -n "__fish_seen_subcommand_from update" -l local -d "Local scope"
|
|
202
|
+
# Flags for permission
|
|
203
|
+
complete -c cf -n "__fish_seen_subcommand_from permission" -l all -d "Apply all recommended permissions"
|
|
204
|
+
complete -c cf -n "__fish_seen_subcommand_from permission" -l user -d "Save to user-level settings"
|
|
205
|
+
complete -c cf -n "__fish_seen_subcommand_from permission" -l project -d "Save to project-level settings"
|
|
188
206
|
# Dev subcommands
|
|
189
207
|
complete -c cf -n "__fish_seen_subcommand_from dev" -a on -d "Switch to local plugin source"
|
|
190
208
|
complete -c cf -n "__fish_seen_subcommand_from dev" -a off -d "Switch back to remote marketplace"
|
|
@@ -198,8 +216,8 @@ complete -c cf -n "__fish_seen_subcommand_from memory" -a search -d "Search memo
|
|
|
198
216
|
complete -c cf -n "__fish_seen_subcommand_from memory" -a list -d "List memories (--projects for all DBs)"
|
|
199
217
|
complete -c cf -n "__fish_seen_subcommand_from memory" -a rm -d "Remove a project database"
|
|
200
218
|
complete -c cf -n "__fish_seen_subcommand_from memory" -a init -d "Initialize Tier 1 (SQLite + Hybrid Search)"
|
|
201
|
-
complete -c cf -n "__fish_seen_subcommand_from memory" -a start -d "Start the memory daemon (Tier 2)"
|
|
202
|
-
complete -c cf -n "__fish_seen_subcommand_from memory" -a stop -d "Stop the memory daemon"
|
|
219
|
+
complete -c cf -n "__fish_seen_subcommand_from memory" -a start-daemon -d "Start the memory daemon (Tier 2)"
|
|
220
|
+
complete -c cf -n "__fish_seen_subcommand_from memory" -a stop-daemon -d "Stop the memory daemon"
|
|
203
221
|
complete -c cf -n "__fish_seen_subcommand_from memory" -a rebuild -d "Rebuild the daemon search index"
|
|
204
222
|
complete -c cf -n "__fish_seen_subcommand_from memory" -a mcp -d "Show MCP server setup instructions"
|
|
205
223
|
# Session subcommands
|
|
@@ -213,7 +231,7 @@ Register-ArgumentCompleter -Native -CommandName cf -ScriptBlock {
|
|
|
213
231
|
param($wordToComplete, $commandAst, $cursorPosition)
|
|
214
232
|
$commands = @('install','uninstall','disable','enable','init','config','host','mcp','memory','permission','statusline','update','dev','session')
|
|
215
233
|
$devSubcommands = @('on','off','status','restart','sync','update')
|
|
216
|
-
$memorySubcommands = @('status','search','list','rm','init','start','stop','rebuild','mcp')
|
|
234
|
+
$memorySubcommands = @('status','search','list','rm','init','start-daemon','stop-daemon','rebuild','mcp')
|
|
217
235
|
$sessionSubcommands = @('save','load')
|
|
218
236
|
$scopeFlags = @('--user','--global','--project','--local')
|
|
219
237
|
$updateFlags = @('--cli','--plugin','--statusline','--user','--global','--project','--local')
|
|
@@ -230,6 +248,9 @@ Register-ArgumentCompleter -Native -CommandName cf -ScriptBlock {
|
|
|
230
248
|
} 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
249
|
$scopeFlags | Where-Object { $_ -like "$wordToComplete*" } |
|
|
232
250
|
ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) }
|
|
251
|
+
} elseif ($words.Count -ge 2 -and $words[1].ToString() -eq 'permission') {
|
|
252
|
+
@('--all','--user','--project') | Where-Object { $_ -like "$wordToComplete*" } |
|
|
253
|
+
ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) }
|
|
233
254
|
} elseif ($words.Count -ge 2 -and $words[1].ToString() -eq 'update') {
|
|
234
255
|
$updateFlags | Where-Object { $_ -like "$wordToComplete*" } |
|
|
235
256
|
ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) }
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getAllRules,
|
|
3
|
+
getExistingRules
|
|
4
|
+
} from "./chunk-7CAIGH2Y.js";
|
|
1
5
|
import {
|
|
2
6
|
findStatuslineHookPath,
|
|
3
7
|
isStatuslineConfigured,
|
|
@@ -13,7 +17,7 @@ import {
|
|
|
13
17
|
ensureShellCompletion,
|
|
14
18
|
hasShellCompletion,
|
|
15
19
|
removeShellCompletion
|
|
16
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-VUAUAO2R.js";
|
|
17
21
|
import {
|
|
18
22
|
BACK,
|
|
19
23
|
applyDocsDirChange,
|
|
@@ -28,6 +32,8 @@ import {
|
|
|
28
32
|
run
|
|
29
33
|
} from "./chunk-CYQU33FY.js";
|
|
30
34
|
import {
|
|
35
|
+
claudeLocalSettingsPath,
|
|
36
|
+
claudeSettingsPath,
|
|
31
37
|
globalConfigPath,
|
|
32
38
|
localConfigPath,
|
|
33
39
|
mergeJson,
|
|
@@ -729,6 +735,62 @@ async function editShellCompletion() {
|
|
|
729
735
|
ensureShellCompletion({ silent: false });
|
|
730
736
|
}
|
|
731
737
|
}
|
|
738
|
+
async function editPermissions() {
|
|
739
|
+
const projectPath = claudeLocalSettingsPath();
|
|
740
|
+
const userPath = claudeSettingsPath();
|
|
741
|
+
const projectRules = getExistingRules(projectPath);
|
|
742
|
+
const userRules = getExistingRules(userPath);
|
|
743
|
+
const allRules = getAllRules();
|
|
744
|
+
const allRuleStrings = allRules.map((r) => r.rule);
|
|
745
|
+
const projectManaged = projectRules.filter(
|
|
746
|
+
(r) => allRuleStrings.includes(r)
|
|
747
|
+
).length;
|
|
748
|
+
const userManaged = userRules.filter(
|
|
749
|
+
(r) => allRuleStrings.includes(r)
|
|
750
|
+
).length;
|
|
751
|
+
console.log(
|
|
752
|
+
chalk.dim(
|
|
753
|
+
` Project: ${projectManaged}/${allRules.length} rules \xB7 User: ${userManaged}/${allRules.length} rules`
|
|
754
|
+
)
|
|
755
|
+
);
|
|
756
|
+
console.log();
|
|
757
|
+
const choice = await select({
|
|
758
|
+
message: "Permissions action:",
|
|
759
|
+
choices: injectBackChoice(
|
|
760
|
+
[
|
|
761
|
+
{
|
|
762
|
+
name: "Run full permission setup (interactive)",
|
|
763
|
+
value: "interactive",
|
|
764
|
+
description: " Opens `cf permission` \u2014 pick categories and rules"
|
|
765
|
+
},
|
|
766
|
+
{
|
|
767
|
+
name: "Apply all recommended (project scope)",
|
|
768
|
+
value: "all-project",
|
|
769
|
+
description: " Quick: adds all recommended rules to .claude/settings.local.json"
|
|
770
|
+
},
|
|
771
|
+
{
|
|
772
|
+
name: "Apply all recommended (user scope)",
|
|
773
|
+
value: "all-user",
|
|
774
|
+
description: " Quick: adds all recommended rules to ~/.claude/settings.json"
|
|
775
|
+
}
|
|
776
|
+
],
|
|
777
|
+
"Back"
|
|
778
|
+
)
|
|
779
|
+
});
|
|
780
|
+
if (choice === BACK) return;
|
|
781
|
+
const { permissionCommand } = await import("./permission-Z3LOBJ4X.js");
|
|
782
|
+
switch (choice) {
|
|
783
|
+
case "interactive":
|
|
784
|
+
await permissionCommand({});
|
|
785
|
+
break;
|
|
786
|
+
case "all-project":
|
|
787
|
+
await permissionCommand({ all: true, project: true });
|
|
788
|
+
break;
|
|
789
|
+
case "all-user":
|
|
790
|
+
await permissionCommand({ all: true, user: true });
|
|
791
|
+
break;
|
|
792
|
+
}
|
|
793
|
+
}
|
|
732
794
|
var em = chalk.hex("#10b981");
|
|
733
795
|
async function configCommand() {
|
|
734
796
|
console.log();
|
|
@@ -752,6 +814,15 @@ async function configCommand() {
|
|
|
752
814
|
const memoryScope = getScopeLabel("memory", globalCfg, localCfg);
|
|
753
815
|
const statuslineStatus = isStatuslineConfigured() ? chalk.green("configured") : chalk.yellow("not configured");
|
|
754
816
|
const completionStatus = hasShellCompletion() ? chalk.green("installed") : chalk.yellow("not installed");
|
|
817
|
+
const projectRules = getExistingRules(claudeLocalSettingsPath());
|
|
818
|
+
const userRules = getExistingRules(claudeSettingsPath());
|
|
819
|
+
const allRules = getAllRules();
|
|
820
|
+
const allRuleStrings = allRules.map((r) => r.rule);
|
|
821
|
+
const configuredCount = (/* @__PURE__ */ new Set([
|
|
822
|
+
...projectRules.filter((r) => allRuleStrings.includes(r)),
|
|
823
|
+
...userRules.filter((r) => allRuleStrings.includes(r))
|
|
824
|
+
])).size;
|
|
825
|
+
const permissionStatus = configuredCount > 0 ? chalk.green(`${configuredCount}/${allRules.length}`) : chalk.yellow(`0/${allRules.length}`);
|
|
755
826
|
const choice = await select({
|
|
756
827
|
message: "What to configure?",
|
|
757
828
|
choices: injectBackChoice(
|
|
@@ -786,6 +857,11 @@ async function configCommand() {
|
|
|
786
857
|
value: "gitignore",
|
|
787
858
|
description: " Add or update coding-friend artifacts in .gitignore"
|
|
788
859
|
},
|
|
860
|
+
{
|
|
861
|
+
name: `Permissions (${permissionStatus} rules)`,
|
|
862
|
+
value: "permissions",
|
|
863
|
+
description: " Manage Claude Code permissions for Coding Friend skills and hooks"
|
|
864
|
+
},
|
|
789
865
|
{
|
|
790
866
|
name: `Shell completion (${completionStatus})`,
|
|
791
867
|
value: "completion",
|
|
@@ -817,6 +893,9 @@ async function configCommand() {
|
|
|
817
893
|
case "gitignore":
|
|
818
894
|
await editGitignore(globalCfg, localCfg);
|
|
819
895
|
break;
|
|
896
|
+
case "permissions":
|
|
897
|
+
await editPermissions();
|
|
898
|
+
break;
|
|
820
899
|
case "completion":
|
|
821
900
|
await editShellCompletion();
|
|
822
901
|
break;
|