coding-friend-cli 1.28.0 → 1.29.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.
@@ -203,9 +203,23 @@ var STATIC_RULES = [
203
203
  category: "Testing & Build",
204
204
  recommended: true
205
205
  },
206
+ // Narrow npx rules only — the broad "Bash(npx *)" used to live here but
207
+ // grants execution of any package from any registry, which conflicts with
208
+ // the auto-approve hook's threat model (see plugin/hooks/auto-approve.cjs).
209
+ // tsc and prettier are safe because they typecheck/format and do not
210
+ // execute arbitrary code from input files. Tools that execute arbitrary
211
+ // code (eslint plugins, jest test files, vitest, tsx) are intentionally
212
+ // NOT in the static recommended list — users who want them must add them
213
+ // explicitly with awareness of the risk.
214
+ {
215
+ rule: "Bash(npx tsc *)",
216
+ description: "[execute] Run TypeScript compiler \xB7 Used by: cf-verification",
217
+ category: "Testing & Build",
218
+ recommended: true
219
+ },
206
220
  {
207
- rule: "Bash(npx *)",
208
- description: "[execute] Run npx commands (eslint, tsc) \xB7 Used by: cf-verification",
221
+ rule: "Bash(npx prettier *)",
222
+ description: "[execute] Run Prettier formatter \xB7 Used by: cf-verification",
209
223
  category: "Testing & Build",
210
224
  recommended: true
211
225
  },
@@ -305,7 +319,8 @@ var DANGEROUS_RULE_PATTERNS = [
305
319
  reason: "Grants execution of any npm script"
306
320
  },
307
321
  {
308
- pattern: /^Bash\(npx\*?\)$/,
322
+ // Matches Bash(npx), Bash(npx*), and Bash(npx *) — any bare npx wildcard
323
+ pattern: /^Bash\(npx\s*\*?\)$/,
309
324
  reason: "Grants execution of any npx package"
310
325
  },
311
326
  {
@@ -47,7 +47,7 @@ import {
47
47
  import {
48
48
  getAllRules,
49
49
  getExistingRules
50
- } from "./chunk-JVYZ72EP.js";
50
+ } from "./chunk-ADCFJSCP.js";
51
51
  import {
52
52
  mergeJson,
53
53
  readJson
@@ -393,7 +393,7 @@ async function editAutoApprove(globalCfg, localCfg) {
393
393
  if (scope === "back") return;
394
394
  writeToScope(scope, { autoApprove: value });
395
395
  if (value) {
396
- const { runDangerousRulesAudit } = await import("./permissions-O24R7WUU.js");
396
+ const { runDangerousRulesAudit } = await import("./permissions-DDLSTTPS.js");
397
397
  await runDangerousRulesAudit(
398
398
  [
399
399
  claudeProjectSettingsPath(),
@@ -570,7 +570,7 @@ async function editPermissions() {
570
570
  )
571
571
  });
572
572
  if (choice === BACK) return;
573
- const { permissionCommand } = await import("./permission-K54DWLHN.js");
573
+ const { permissionCommand } = await import("./permission-HU36DY4C.js");
574
574
  switch (choice) {
575
575
  case "interactive":
576
576
  await permissionCommand({});
@@ -10,6 +10,7 @@ import {
10
10
  } from "./chunk-5UVDWG5L.js";
11
11
 
12
12
  // src/commands/guide.ts
13
+ import chalk from "chalk";
13
14
  import { existsSync, mkdirSync, readdirSync, writeFileSync } from "fs";
14
15
  import { join, resolve } from "path";
15
16
  var GUIDE_TEMPLATE = `# Custom Guide for {{SKILL_NAME}}
@@ -100,11 +101,14 @@ function guideListCommand() {
100
101
  return;
101
102
  }
102
103
  const skillsDir = findPluginSkillsDir();
103
- log.info(`Custom guides (${entries.length}):`);
104
+ log.info(`Custom guides (${chalk.bold(entries.length)}):`);
104
105
  for (const name of entries) {
105
106
  const path = join(customDir, `${name}-custom`, "SKILL.md");
106
- const exists = skillsDir != null && skillExists(skillsDir, name) ? "\u2714" : "\u26A0 skill not found";
107
- log.info(` ${name} \u2192 ${path} (${exists})`);
107
+ const found = skillsDir != null && skillExists(skillsDir, name);
108
+ const status = found ? chalk.green("\u2714") : chalk.yellow("\u26A0 skill not found");
109
+ log.info(
110
+ ` ${status} ${chalk.cyan(name)} ${chalk.dim("\u2192")} ${chalk.dim(path)}`
111
+ );
108
112
  }
109
113
  }
110
114
  export {
package/dist/index.js CHANGED
@@ -30,11 +30,11 @@ program.command("enable").description("Re-enable the Coding Friend plugin").opti
30
30
  await enableCommand(opts);
31
31
  });
32
32
  program.command("init").description("Initialize coding-friend in current project").action(async () => {
33
- const { initCommand } = await import("./init-R5L2GAFV.js");
33
+ const { initCommand } = await import("./init-4GHLRTOK.js");
34
34
  await initCommand();
35
35
  });
36
36
  program.command("config").description("Manage Coding Friend configuration").action(async () => {
37
- const { configCommand } = await import("./config-U2WEZXF6.js");
37
+ const { configCommand } = await import("./config-GRJ5WKFR.js");
38
38
  await configCommand();
39
39
  });
40
40
  program.command("host").description("Build and serve learning docs as a static website").argument("[path]", "path to docs folder").option("-p, --port <port>", "port number", "3333").action(async (path, opts) => {
@@ -49,7 +49,7 @@ program.command("permission").description("Manage Claude Code permission rules f
49
49
  "--project",
50
50
  "Save to project-level settings (.claude/settings.local.json)"
51
51
  ).action(async (opts) => {
52
- const { permissionCommand } = await import("./permission-K54DWLHN.js");
52
+ const { permissionCommand } = await import("./permission-HU36DY4C.js");
53
53
  await permissionCommand(opts);
54
54
  });
55
55
  program.command("statusline").description("Setup coding-friend statusline in Claude Code").action(async () => {
@@ -61,7 +61,7 @@ program.command("update").description("Update coding-friend plugin, CLI, and sta
61
61
  await updateCommand(opts);
62
62
  });
63
63
  program.command("status").description("Show comprehensive Coding Friend status").action(async () => {
64
- const { statusCommand } = await import("./status-JXUXVHRH.js");
64
+ const { statusCommand } = await import("./status-7WFW4JI2.js");
65
65
  await statusCommand();
66
66
  });
67
67
  var session = program.command("session").description("Save and load Claude Code sessions across machines");
@@ -150,11 +150,11 @@ memory.command("rm").description("Remove a project database").option("--project-
150
150
  );
151
151
  var guide = program.command("guide").description("Manage custom skill guides");
152
152
  guide.command("create").description("Create a custom guide for a skill").argument("<skill-name>", "skill to create guide for (e.g. cf-commit)").action(async (skillName) => {
153
- const { guideCreateCommand } = await import("./guide-F2FLCDYO.js");
153
+ const { guideCreateCommand } = await import("./guide-LQ2BHU5Y.js");
154
154
  guideCreateCommand(skillName);
155
155
  });
156
156
  guide.command("list").description("List existing custom guides").action(async () => {
157
- const { guideListCommand } = await import("./guide-F2FLCDYO.js");
157
+ const { guideListCommand } = await import("./guide-LQ2BHU5Y.js");
158
158
  guideListCommand();
159
159
  });
160
160
  var dev = program.command("dev").description("Development mode commands");
@@ -59,7 +59,7 @@ import {
59
59
  getExistingRules,
60
60
  getMissingRules,
61
61
  logPluginScriptWarning
62
- } from "./chunk-JVYZ72EP.js";
62
+ } from "./chunk-ADCFJSCP.js";
63
63
  import {
64
64
  mergeJson,
65
65
  readJson,
@@ -827,7 +827,7 @@ async function initMenu(gitAvailable) {
827
827
  log.success(`Saved to ${targetPath}`);
828
828
  }
829
829
  if (autoApproveChoice) {
830
- const { runDangerousRulesAudit } = await import("./permissions-O24R7WUU.js");
830
+ const { runDangerousRulesAudit } = await import("./permissions-DDLSTTPS.js");
831
831
  await runDangerousRulesAudit(
832
832
  [
833
833
  claudeProjectSettingsPath(),
@@ -26,7 +26,7 @@ import {
26
26
  groupByCategory,
27
27
  logPluginScriptWarning,
28
28
  runDangerousRulesAudit
29
- } from "./chunk-JVYZ72EP.js";
29
+ } from "./chunk-ADCFJSCP.js";
30
30
  import {
31
31
  mergeJson,
32
32
  readJson
@@ -15,7 +15,7 @@ import {
15
15
  logPluginScriptWarning,
16
16
  runDangerousRulesAudit,
17
17
  stripDangerousRules
18
- } from "./chunk-JVYZ72EP.js";
18
+ } from "./chunk-ADCFJSCP.js";
19
19
  import "./chunk-5UVDWG5L.js";
20
20
  export {
21
21
  DANGEROUS_RULE_PATTERNS,
@@ -30,7 +30,7 @@ import {
30
30
  import "./chunk-NREZK463.js";
31
31
  import {
32
32
  getExistingRules
33
- } from "./chunk-JVYZ72EP.js";
33
+ } from "./chunk-ADCFJSCP.js";
34
34
  import {
35
35
  readJson
36
36
  } from "./chunk-5UVDWG5L.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coding-friend-cli",
3
- "version": "1.28.0",
3
+ "version": "1.29.0",
4
4
  "description": "CLI for coding-friend — host learning docs, setup MCP server, initialize projects",
5
5
  "type": "module",
6
6
  "bin": {