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
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
STATIC_RULES,
|
|
3
3
|
applyPermissions,
|
|
4
|
+
cleanupStalePluginRules,
|
|
5
|
+
getAllRules,
|
|
4
6
|
getExistingRules,
|
|
5
|
-
groupByCategory
|
|
6
|
-
|
|
7
|
+
groupByCategory,
|
|
8
|
+
logPluginScriptWarning
|
|
9
|
+
} from "./chunk-7CAIGH2Y.js";
|
|
7
10
|
import {
|
|
8
|
-
claudeLocalSettingsPath
|
|
11
|
+
claudeLocalSettingsPath,
|
|
12
|
+
claudeSettingsPath
|
|
9
13
|
} from "./chunk-RWUTFVRB.js";
|
|
10
14
|
import {
|
|
11
15
|
log
|
|
@@ -34,6 +38,39 @@ function colorDescription(desc) {
|
|
|
34
38
|
}
|
|
35
39
|
return `${main} ${usedBy}`;
|
|
36
40
|
}
|
|
41
|
+
async function resolveSettingsPath(opts) {
|
|
42
|
+
if (opts.user && opts.project) {
|
|
43
|
+
log.error("Cannot use both --user and --project. Pick one.");
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
if (opts.user) {
|
|
47
|
+
const p2 = claudeSettingsPath();
|
|
48
|
+
return { path: p2, label: p2.replace(homedir(), "~"), scope: "user" };
|
|
49
|
+
}
|
|
50
|
+
if (opts.project) {
|
|
51
|
+
const p2 = claudeLocalSettingsPath();
|
|
52
|
+
return { path: p2, label: p2.replace(homedir(), "~"), scope: "project" };
|
|
53
|
+
}
|
|
54
|
+
if (!process.stdin.isTTY) {
|
|
55
|
+
const p2 = claudeLocalSettingsPath();
|
|
56
|
+
return { path: p2, label: p2.replace(homedir(), "~"), scope: "project" };
|
|
57
|
+
}
|
|
58
|
+
const scope = await select({
|
|
59
|
+
message: "Where should permissions be saved?",
|
|
60
|
+
choices: [
|
|
61
|
+
{
|
|
62
|
+
name: "Project \u2014 .claude/settings.local.json (this project only, gitignored)",
|
|
63
|
+
value: "project"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: "User \u2014 ~/.claude/settings.json (all projects)",
|
|
67
|
+
value: "user"
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
});
|
|
71
|
+
const p = scope === "user" ? claudeSettingsPath() : claudeLocalSettingsPath();
|
|
72
|
+
return { path: p, label: p.replace(homedir(), "~"), scope };
|
|
73
|
+
}
|
|
37
74
|
async function interactiveFlow(allRules, existing) {
|
|
38
75
|
const groups = groupByCategory(allRules);
|
|
39
76
|
const allRuleStrings = allRules.map((r) => r.rule);
|
|
@@ -98,14 +135,17 @@ async function interactiveFlow(allRules, existing) {
|
|
|
98
135
|
async function permissionCommand(opts) {
|
|
99
136
|
console.log("=== \u{1F33F} Coding Friend Permissions \u{1F33F} ===");
|
|
100
137
|
console.log();
|
|
101
|
-
const
|
|
102
|
-
|
|
138
|
+
const {
|
|
139
|
+
path: settingsPath,
|
|
140
|
+
label: settingsLabel,
|
|
141
|
+
scope
|
|
142
|
+
} = await resolveSettingsPath(opts);
|
|
103
143
|
const existing = getExistingRules(settingsPath);
|
|
104
|
-
const allRules =
|
|
144
|
+
const allRules = getAllRules();
|
|
105
145
|
const allRuleStrings = allRules.map((r) => r.rule);
|
|
106
146
|
const managedExisting = existing.filter((r) => allRuleStrings.includes(r));
|
|
107
147
|
const unmanagedExisting = existing.filter((r) => !allRuleStrings.includes(r));
|
|
108
|
-
log.dim(`Settings: ${settingsLabel} (
|
|
148
|
+
log.dim(`Settings: ${settingsLabel} (${scope})`);
|
|
109
149
|
log.dim(
|
|
110
150
|
`Current: ${managedExisting.length}/${allRules.length} Coding Friend rules configured`
|
|
111
151
|
);
|
|
@@ -122,13 +162,34 @@ async function permissionCommand(opts) {
|
|
|
122
162
|
log.success("All recommended permissions already configured.");
|
|
123
163
|
return;
|
|
124
164
|
}
|
|
125
|
-
|
|
165
|
+
const staticSet = new Set(STATIC_RULES.map((r) => r.rule));
|
|
166
|
+
const staticCount = toAdd2.filter((r) => staticSet.has(r)).length;
|
|
167
|
+
const pluginCount = toAdd2.length - staticCount;
|
|
168
|
+
console.log(
|
|
169
|
+
`Adding ${chalk.bold(toAdd2.length)} recommended permissions${pluginCount > 0 ? ` (${staticCount} static + ${pluginCount} plugin scripts)` : ""}:`
|
|
170
|
+
);
|
|
126
171
|
for (const r of toAdd2) {
|
|
127
172
|
console.log(` ${chalk.green("+")} ${r}`);
|
|
128
173
|
}
|
|
174
|
+
if (pluginCount > 0) {
|
|
175
|
+
console.log();
|
|
176
|
+
logPluginScriptWarning(log, chalk);
|
|
177
|
+
}
|
|
129
178
|
console.log();
|
|
179
|
+
const ok2 = !process.stdin.isTTY || await confirm({
|
|
180
|
+
message: `Apply ${toAdd2.length} permission rules to ${settingsLabel}?`,
|
|
181
|
+
default: true
|
|
182
|
+
});
|
|
183
|
+
if (!ok2) {
|
|
184
|
+
log.dim("Skipped.");
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
130
187
|
applyPermissions(settingsPath, toAdd2, []);
|
|
131
|
-
|
|
188
|
+
const cleaned = cleanupStalePluginRules(settingsPath);
|
|
189
|
+
if (cleaned > 0) {
|
|
190
|
+
log.dim(`Removed ${cleaned} stale old-format plugin rules.`);
|
|
191
|
+
}
|
|
192
|
+
log.success(`Added ${toAdd2.length} permission rules to ${settingsLabel}.`);
|
|
132
193
|
return;
|
|
133
194
|
}
|
|
134
195
|
const { toAdd, toRemove } = await interactiveFlow(allRules, existing);
|
|
@@ -160,7 +221,7 @@ async function permissionCommand(opts) {
|
|
|
160
221
|
}
|
|
161
222
|
applyPermissions(settingsPath, toAdd, toRemove);
|
|
162
223
|
log.success(
|
|
163
|
-
`Done \u2014 added ${toAdd.length}, removed ${toRemove.length} rules.`
|
|
224
|
+
`Done \u2014 added ${toAdd.length}, removed ${toRemove.length} rules in ${settingsLabel}.`
|
|
164
225
|
);
|
|
165
226
|
}
|
|
166
227
|
export {
|
package/dist/postinstall.js
CHANGED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolveMemoryDir
|
|
3
|
+
} from "./chunk-QMD7P67N.js";
|
|
4
|
+
import {
|
|
5
|
+
getCliVersion,
|
|
6
|
+
getLatestCliVersion,
|
|
7
|
+
getLatestVersion,
|
|
8
|
+
semverCompare
|
|
9
|
+
} from "./chunk-IRPW2BMP.js";
|
|
10
|
+
import {
|
|
11
|
+
detectPluginScope,
|
|
12
|
+
isPluginDisabled
|
|
13
|
+
} from "./chunk-JFGLNTZI.js";
|
|
14
|
+
import {
|
|
15
|
+
getExistingRules
|
|
16
|
+
} from "./chunk-7CAIGH2Y.js";
|
|
17
|
+
import {
|
|
18
|
+
getLibPath
|
|
19
|
+
} from "./chunk-RZRT7NGT.js";
|
|
20
|
+
import {
|
|
21
|
+
getInstalledVersion
|
|
22
|
+
} from "./chunk-ORACWEDN.js";
|
|
23
|
+
import "./chunk-POC2WHU2.js";
|
|
24
|
+
import "./chunk-NEQZP5D4.js";
|
|
25
|
+
import "./chunk-C5LYVVEI.js";
|
|
26
|
+
import "./chunk-CYQU33FY.js";
|
|
27
|
+
import {
|
|
28
|
+
claudeSettingsPath,
|
|
29
|
+
devStatePath,
|
|
30
|
+
globalConfigPath,
|
|
31
|
+
localConfigPath,
|
|
32
|
+
readJson
|
|
33
|
+
} from "./chunk-RWUTFVRB.js";
|
|
34
|
+
import "./chunk-W5CD7WTX.js";
|
|
35
|
+
|
|
36
|
+
// src/commands/status.ts
|
|
37
|
+
import { existsSync, readdirSync } from "fs";
|
|
38
|
+
import { join } from "path";
|
|
39
|
+
import chalk from "chalk";
|
|
40
|
+
var VERSION_COL = 11;
|
|
41
|
+
var CONFIG_KEY_COL = 16;
|
|
42
|
+
var CONFIG_SUB_COL = 16;
|
|
43
|
+
function countMdFiles(dir) {
|
|
44
|
+
if (!existsSync(dir)) return 0;
|
|
45
|
+
let count = 0;
|
|
46
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
47
|
+
if (entry.isDirectory()) {
|
|
48
|
+
count += countMdFiles(join(dir, entry.name));
|
|
49
|
+
} else if (entry.name.endsWith(".md") && entry.name !== "README.md") {
|
|
50
|
+
count++;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return count;
|
|
54
|
+
}
|
|
55
|
+
function formatUptime(seconds) {
|
|
56
|
+
if (seconds < 60) return `${Math.round(seconds)}s`;
|
|
57
|
+
if (seconds < 3600) return `${Math.round(seconds / 60)}m`;
|
|
58
|
+
return `${Math.round(seconds / 3600)}h ${Math.round(seconds % 3600 / 60)}m`;
|
|
59
|
+
}
|
|
60
|
+
function formatScalar(value) {
|
|
61
|
+
if (typeof value === "string") return value;
|
|
62
|
+
if (typeof value === "boolean") return value ? "true" : "false";
|
|
63
|
+
if (typeof value === "number") return String(value);
|
|
64
|
+
return String(value);
|
|
65
|
+
}
|
|
66
|
+
function pad(label, width) {
|
|
67
|
+
return ` ${label}${" ".repeat(Math.max(1, width - label.length))}`;
|
|
68
|
+
}
|
|
69
|
+
function subLine(key, value, overrides) {
|
|
70
|
+
console.log(
|
|
71
|
+
` ${key}${" ".repeat(Math.max(1, CONFIG_SUB_COL - key.length))}${value}${overrides}`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
function printConfig(obj, otherConfig) {
|
|
75
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
76
|
+
const overrides = otherConfig && key in otherConfig ? ` ${chalk.yellow("(overrides global)")}` : "";
|
|
77
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
78
|
+
console.log(pad(key, CONFIG_KEY_COL) + chalk.dim("\u2500") + overrides);
|
|
79
|
+
const nested = value;
|
|
80
|
+
const nestedOther = otherConfig && typeof otherConfig[key] === "object" ? otherConfig[key] : null;
|
|
81
|
+
for (const [subKey, subVal] of Object.entries(nested)) {
|
|
82
|
+
const subOverrides = nestedOther && subKey in nestedOther ? ` ${chalk.yellow("(overrides global)")}` : "";
|
|
83
|
+
if (subKey === "categories" && Array.isArray(subVal)) {
|
|
84
|
+
const names = subVal.map(
|
|
85
|
+
(c) => typeof c === "object" && c !== null && "name" in c ? c.name : String(c)
|
|
86
|
+
).join(", ");
|
|
87
|
+
subLine(subKey, names, subOverrides);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (typeof subVal === "object" && subVal !== null && !Array.isArray(subVal)) {
|
|
91
|
+
const innerEntries = Object.entries(
|
|
92
|
+
subVal
|
|
93
|
+
);
|
|
94
|
+
const inline = innerEntries.map(([k, v]) => `${k}: ${formatScalar(v)}`).join(", ");
|
|
95
|
+
subLine(subKey, inline, subOverrides);
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (Array.isArray(subVal)) {
|
|
99
|
+
subLine(
|
|
100
|
+
subKey,
|
|
101
|
+
subVal.map((v) => formatScalar(v)).join(", "),
|
|
102
|
+
subOverrides
|
|
103
|
+
);
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
subLine(subKey, formatScalar(subVal), subOverrides);
|
|
107
|
+
}
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (Array.isArray(value)) {
|
|
111
|
+
console.log(
|
|
112
|
+
`${pad(key, CONFIG_KEY_COL)}${value.map((v) => formatScalar(v)).join(", ")}${overrides}`
|
|
113
|
+
);
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
console.log(
|
|
117
|
+
`${pad(key, CONFIG_KEY_COL)}${formatScalar(value)}${overrides}`
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function versionLine(label, current, latest) {
|
|
122
|
+
const padded = pad(label, VERSION_COL);
|
|
123
|
+
if (!latest) {
|
|
124
|
+
return `${padded}${current} ${chalk.dim("(latest unavailable)")}`;
|
|
125
|
+
}
|
|
126
|
+
const cmp = semverCompare(current, latest);
|
|
127
|
+
const indicator = cmp >= 0 ? chalk.green("\u2714 up to date") : chalk.yellow("\u26A0 update available");
|
|
128
|
+
return `${padded}${current} \u2192 ${latest} ${indicator}`;
|
|
129
|
+
}
|
|
130
|
+
async function statusCommand() {
|
|
131
|
+
const pluginVersion = getInstalledVersion();
|
|
132
|
+
const latestPlugin = getLatestVersion();
|
|
133
|
+
const cliVersion = getCliVersion();
|
|
134
|
+
const latestCli = getLatestCliVersion();
|
|
135
|
+
console.log();
|
|
136
|
+
console.log(chalk.bold("\u{1F4E6} Versions"));
|
|
137
|
+
if (pluginVersion) {
|
|
138
|
+
console.log(versionLine("Plugin", pluginVersion, latestPlugin));
|
|
139
|
+
} else {
|
|
140
|
+
console.log(`${pad("Plugin", VERSION_COL)}${chalk.dim("not installed")}`);
|
|
141
|
+
}
|
|
142
|
+
console.log(versionLine("CLI", cliVersion, latestCli));
|
|
143
|
+
console.log();
|
|
144
|
+
console.log(chalk.bold("\u{1F527} Plugin"));
|
|
145
|
+
const detectedScope = detectPluginScope();
|
|
146
|
+
console.log(`${pad("Scope", VERSION_COL)}${detectedScope}`);
|
|
147
|
+
const disabled = isPluginDisabled(detectedScope);
|
|
148
|
+
console.log(
|
|
149
|
+
`${pad("Status", VERSION_COL)}${disabled ? chalk.yellow("disabled") : chalk.green("enabled")}`
|
|
150
|
+
);
|
|
151
|
+
try {
|
|
152
|
+
const claudeSettings = readJson(claudeSettingsPath());
|
|
153
|
+
const marketplaces = claudeSettings?.extraKnownMarketplaces;
|
|
154
|
+
const autoUpdate = marketplaces?.["coding-friend-marketplace"]?.autoUpdate === true;
|
|
155
|
+
console.log(
|
|
156
|
+
`${pad("Auto-update", VERSION_COL)}${autoUpdate ? chalk.green("on") : chalk.dim("off")}`
|
|
157
|
+
);
|
|
158
|
+
} catch {
|
|
159
|
+
console.log(`${pad("Auto-update", VERSION_COL)}${chalk.dim("unknown")}`);
|
|
160
|
+
}
|
|
161
|
+
const devState = readJson(devStatePath());
|
|
162
|
+
console.log(
|
|
163
|
+
`${pad("Dev mode", VERSION_COL)}${devState ? chalk.cyan("on") : chalk.dim("off")}`
|
|
164
|
+
);
|
|
165
|
+
const rules = getExistingRules(claudeSettingsPath());
|
|
166
|
+
console.log(
|
|
167
|
+
`${pad("Permissions", VERSION_COL)}${rules.length} rules ${chalk.dim('\u2192 Run "cf permission" for details')}`
|
|
168
|
+
);
|
|
169
|
+
console.log();
|
|
170
|
+
console.log(chalk.bold("\u{1F9E0} Memory"));
|
|
171
|
+
const memoryDir = resolveMemoryDir();
|
|
172
|
+
const docCount = countMdFiles(memoryDir);
|
|
173
|
+
let tierLabel = chalk.dim("unavailable");
|
|
174
|
+
let daemonLabel = chalk.dim("unavailable");
|
|
175
|
+
try {
|
|
176
|
+
const mcpDir = getLibPath("cf-memory");
|
|
177
|
+
if (existsSync(join(mcpDir, "dist"))) {
|
|
178
|
+
const { areSqliteDepsAvailable } = await import(join(mcpDir, "dist/lib/lazy-install.js"));
|
|
179
|
+
const { isDaemonRunning, getDaemonInfo } = await import(join(mcpDir, "dist/daemon/process.js"));
|
|
180
|
+
const sqliteAvailable = areSqliteDepsAvailable();
|
|
181
|
+
const running = await isDaemonRunning();
|
|
182
|
+
if (sqliteAvailable) {
|
|
183
|
+
tierLabel = chalk.cyan("Tier 1 (SQLite + Hybrid)");
|
|
184
|
+
} else if (running) {
|
|
185
|
+
tierLabel = chalk.cyan("Tier 2 (MiniSearch + Daemon)");
|
|
186
|
+
} else {
|
|
187
|
+
tierLabel = chalk.cyan("Tier 3 (Markdown)");
|
|
188
|
+
}
|
|
189
|
+
if (running) {
|
|
190
|
+
const info = getDaemonInfo();
|
|
191
|
+
if (info) {
|
|
192
|
+
const uptime = (Date.now() - info.startedAt) / 1e3;
|
|
193
|
+
daemonLabel = `${chalk.green("running")} (PID ${info.pid}, uptime ${formatUptime(uptime)}) ${chalk.dim('\u2192 "cf memory stop-daemon" to stop')}`;
|
|
194
|
+
} else {
|
|
195
|
+
daemonLabel = `${chalk.green("running")} ${chalk.dim('\u2192 "cf memory stop-daemon" to stop')}`;
|
|
196
|
+
}
|
|
197
|
+
} else {
|
|
198
|
+
daemonLabel = `${chalk.dim("stopped")} ${chalk.dim('\u2192 "cf memory start-daemon" to start')}`;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
} catch {
|
|
202
|
+
}
|
|
203
|
+
console.log(`${pad("Tier", VERSION_COL)}${tierLabel}`);
|
|
204
|
+
console.log(`${pad("Daemon", VERSION_COL)}${daemonLabel}`);
|
|
205
|
+
console.log(`${pad("Documents", VERSION_COL)}${docCount} files`);
|
|
206
|
+
console.log(chalk.dim(` \u2192 Run "cf memory status" for details`));
|
|
207
|
+
const globalConfig = readJson(globalConfigPath());
|
|
208
|
+
const localConfig = readJson(localConfigPath());
|
|
209
|
+
if (globalConfig && Object.keys(globalConfig).length > 0) {
|
|
210
|
+
console.log();
|
|
211
|
+
console.log(chalk.bold(`\u2699\uFE0F Config (global: ${globalConfigPath()})`));
|
|
212
|
+
printConfig(globalConfig, null);
|
|
213
|
+
}
|
|
214
|
+
if (localConfig && Object.keys(localConfig).length > 0) {
|
|
215
|
+
console.log();
|
|
216
|
+
console.log(chalk.bold(`\u2699\uFE0F Config (local: ${localConfigPath()})`));
|
|
217
|
+
printConfig(localConfig, globalConfig);
|
|
218
|
+
}
|
|
219
|
+
console.log();
|
|
220
|
+
}
|
|
221
|
+
export {
|
|
222
|
+
statusCommand
|
|
223
|
+
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isMarketplaceRegistered,
|
|
3
3
|
isPluginInstalled
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-JFGLNTZI.js";
|
|
5
5
|
import {
|
|
6
6
|
hasShellCompletion,
|
|
7
7
|
removeShellCompletion
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-NEQZP5D4.js";
|
|
9
9
|
import {
|
|
10
10
|
resolveScope
|
|
11
11
|
} from "./chunk-C5LYVVEI.js";
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
|
+
getCliVersion,
|
|
3
|
+
getLatestCliVersion,
|
|
2
4
|
getLatestVersion,
|
|
3
5
|
semverCompare,
|
|
4
6
|
updateCommand
|
|
5
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-IRPW2BMP.js";
|
|
6
8
|
import "./chunk-ORACWEDN.js";
|
|
7
9
|
import "./chunk-POC2WHU2.js";
|
|
8
|
-
import "./chunk-
|
|
10
|
+
import "./chunk-NEQZP5D4.js";
|
|
9
11
|
import "./chunk-C5LYVVEI.js";
|
|
10
12
|
import "./chunk-CYQU33FY.js";
|
|
11
13
|
import "./chunk-RWUTFVRB.js";
|
|
12
14
|
import "./chunk-W5CD7WTX.js";
|
|
13
15
|
export {
|
|
16
|
+
getCliVersion,
|
|
17
|
+
getLatestCliVersion,
|
|
14
18
|
getLatestVersion,
|
|
15
19
|
semverCompare,
|
|
16
20
|
updateCommand
|
package/package.json
CHANGED
package/dist/chunk-56U7US6J.js
DELETED
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
readJson,
|
|
3
|
-
writeJson
|
|
4
|
-
} from "./chunk-RWUTFVRB.js";
|
|
5
|
-
|
|
6
|
-
// src/lib/permissions.ts
|
|
7
|
-
var PERMISSION_RULES = [
|
|
8
|
-
// Core (hooks & infrastructure)
|
|
9
|
-
{
|
|
10
|
-
rule: "Bash(cat:*)",
|
|
11
|
-
description: "[read-only] Read file contents (\u26A0 system-wide scope, project boundary enforced by Claude Code) \xB7 Used by: session-init hook",
|
|
12
|
-
category: "Core",
|
|
13
|
-
recommended: true
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
rule: "Bash(grep:*)",
|
|
17
|
-
description: "[read-only] Search file contents (\u26A0 system-wide scope, project boundary enforced by Claude Code) \xB7 Used by: session-init hook, skills",
|
|
18
|
-
category: "Core",
|
|
19
|
-
recommended: true
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
rule: "Bash(sed:*)",
|
|
23
|
-
description: "[modify] Text transformation \xB7 Used by: session-init hook",
|
|
24
|
-
category: "Core",
|
|
25
|
-
recommended: true
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
rule: "Bash(tr:*)",
|
|
29
|
-
description: "[read-only] Character translation \xB7 Used by: session-init hook",
|
|
30
|
-
category: "Core",
|
|
31
|
-
recommended: true
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
rule: "Bash(wc:*)",
|
|
35
|
-
description: "[read-only] Count lines/words \xB7 Used by: cf-verification, skills",
|
|
36
|
-
category: "Core",
|
|
37
|
-
recommended: true
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
rule: "Bash(mkdir:*)",
|
|
41
|
-
description: "[write] Create directories \xB7 Used by: docs folder setup",
|
|
42
|
-
category: "Core",
|
|
43
|
-
recommended: true
|
|
44
|
-
},
|
|
45
|
-
// Git Operations
|
|
46
|
-
{
|
|
47
|
-
rule: "Bash(git add:*)",
|
|
48
|
-
description: "[modify] Stage files for commit \xB7 Used by: /cf-commit, /cf-ship",
|
|
49
|
-
category: "Git",
|
|
50
|
-
recommended: true
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
rule: "Bash(git commit:*)",
|
|
54
|
-
description: "[modify] Create commits \xB7 Used by: /cf-commit, /cf-ship",
|
|
55
|
-
category: "Git",
|
|
56
|
-
recommended: true
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
rule: "Bash(git status:*)",
|
|
60
|
-
description: "[read-only] Check working tree status \xB7 Used by: /cf-commit, /cf-review, cf-verification",
|
|
61
|
-
category: "Git",
|
|
62
|
-
recommended: true
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
rule: "Bash(git diff:*)",
|
|
66
|
-
description: "[read-only] View file changes \xB7 Used by: /cf-commit, /cf-review, cf-verification",
|
|
67
|
-
category: "Git",
|
|
68
|
-
recommended: true
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
rule: "Bash(git log:*)",
|
|
72
|
-
description: "[read-only] View commit history \xB7 Used by: /cf-commit, /cf-review, cf-sys-debug",
|
|
73
|
-
category: "Git",
|
|
74
|
-
recommended: true
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
rule: "Bash(git push:*)",
|
|
78
|
-
description: "[remote] Push commits to remote \xB7 Used by: /cf-ship",
|
|
79
|
-
category: "Git",
|
|
80
|
-
recommended: true
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
rule: "Bash(git pull:*)",
|
|
84
|
-
description: "[remote] Pull changes from remote \xB7 Used by: /cf-ship",
|
|
85
|
-
category: "Git",
|
|
86
|
-
recommended: true
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
rule: "Bash(gh pr create:*)",
|
|
90
|
-
description: "[remote] Create GitHub pull requests \xB7 Used by: /cf-ship",
|
|
91
|
-
category: "Git",
|
|
92
|
-
recommended: true
|
|
93
|
-
},
|
|
94
|
-
// Testing & Build
|
|
95
|
-
{
|
|
96
|
-
rule: "Bash(npm test:*)",
|
|
97
|
-
description: "[execute] Run test suites \xB7 Used by: cf-verification, /cf-fix, cf-tdd",
|
|
98
|
-
category: "Testing & Build",
|
|
99
|
-
recommended: true
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
rule: "Bash(npm run:*)",
|
|
103
|
-
description: "[execute] Run npm scripts (build, lint, format) \xB7 Used by: cf-verification",
|
|
104
|
-
category: "Testing & Build",
|
|
105
|
-
recommended: true
|
|
106
|
-
},
|
|
107
|
-
// Web & Research
|
|
108
|
-
{
|
|
109
|
-
rule: "WebSearch",
|
|
110
|
-
description: "[network] Perform web searches \xB7 Used by: /cf-research",
|
|
111
|
-
category: "Web & Research",
|
|
112
|
-
recommended: false
|
|
113
|
-
},
|
|
114
|
-
{
|
|
115
|
-
rule: "WebFetch(domain:*)",
|
|
116
|
-
description: "[network] Fetch content from web pages \xB7 Used by: /cf-research",
|
|
117
|
-
category: "Web & Research",
|
|
118
|
-
recommended: false
|
|
119
|
-
}
|
|
120
|
-
];
|
|
121
|
-
function getExistingRules(settingsPath) {
|
|
122
|
-
const settings = readJson(settingsPath);
|
|
123
|
-
if (!settings) return [];
|
|
124
|
-
const permissions = settings.permissions;
|
|
125
|
-
return permissions?.allow ?? [];
|
|
126
|
-
}
|
|
127
|
-
function getMissingRules(existing, rules) {
|
|
128
|
-
return rules.filter((r) => !existing.includes(r.rule));
|
|
129
|
-
}
|
|
130
|
-
function buildLearnDirRules(learnPath, autoCommit) {
|
|
131
|
-
const rules = [
|
|
132
|
-
{
|
|
133
|
-
rule: `Read(${learnPath}/**)`,
|
|
134
|
-
description: "[read-only] Read learning docs \xB7 Used by: /cf-learn",
|
|
135
|
-
category: "External Learn Directory",
|
|
136
|
-
recommended: true
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
rule: `Edit(${learnPath}/**)`,
|
|
140
|
-
description: "[modify] Edit learning docs \xB7 Used by: /cf-learn",
|
|
141
|
-
category: "External Learn Directory",
|
|
142
|
-
recommended: true
|
|
143
|
-
},
|
|
144
|
-
{
|
|
145
|
-
rule: `Write(${learnPath}/**)`,
|
|
146
|
-
description: "[write] Write learning docs \xB7 Used by: /cf-learn",
|
|
147
|
-
category: "External Learn Directory",
|
|
148
|
-
recommended: true
|
|
149
|
-
}
|
|
150
|
-
];
|
|
151
|
-
if (autoCommit) {
|
|
152
|
-
const quoted = learnPath.includes(" ") ? `"${learnPath}"` : learnPath;
|
|
153
|
-
rules.push({
|
|
154
|
-
rule: `Bash(cd ${quoted} && git add:*)`,
|
|
155
|
-
description: "[modify] Stage learning docs for commit \xB7 Used by: /cf-learn auto-commit",
|
|
156
|
-
category: "External Learn Directory",
|
|
157
|
-
recommended: true
|
|
158
|
-
});
|
|
159
|
-
rules.push({
|
|
160
|
-
rule: `Bash(cd ${quoted} && git commit:*)`,
|
|
161
|
-
description: "[modify] Commit learning docs \xB7 Used by: /cf-learn auto-commit",
|
|
162
|
-
category: "External Learn Directory",
|
|
163
|
-
recommended: true
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
return rules;
|
|
167
|
-
}
|
|
168
|
-
function applyPermissions(settingsPath, toAdd, toRemove) {
|
|
169
|
-
const settings = readJson(settingsPath) ?? {};
|
|
170
|
-
const permissions = settings.permissions ?? {};
|
|
171
|
-
const existing = permissions.allow ?? [];
|
|
172
|
-
const afterRemove = existing.filter((r) => !toRemove.includes(r));
|
|
173
|
-
const afterAdd = [
|
|
174
|
-
...afterRemove,
|
|
175
|
-
...toAdd.filter((r) => !afterRemove.includes(r))
|
|
176
|
-
];
|
|
177
|
-
permissions.allow = afterAdd;
|
|
178
|
-
settings.permissions = permissions;
|
|
179
|
-
writeJson(settingsPath, settings);
|
|
180
|
-
}
|
|
181
|
-
function groupByCategory(rules) {
|
|
182
|
-
const groups = /* @__PURE__ */ new Map();
|
|
183
|
-
for (const rule of rules) {
|
|
184
|
-
const list = groups.get(rule.category) ?? [];
|
|
185
|
-
list.push(rule);
|
|
186
|
-
groups.set(rule.category, list);
|
|
187
|
-
}
|
|
188
|
-
return groups;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
export {
|
|
192
|
-
PERMISSION_RULES,
|
|
193
|
-
getExistingRules,
|
|
194
|
-
getMissingRules,
|
|
195
|
-
buildLearnDirRules,
|
|
196
|
-
applyPermissions,
|
|
197
|
-
groupByCategory
|
|
198
|
-
};
|