claude-warden 2.9.0 → 2.10.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.
@@ -8,7 +8,7 @@
8
8
  {
9
9
  "name": "warden",
10
10
  "description": "Auto-approves safe commands, blocks dangerous ones, prompts for the rest",
11
- "version": "2.9.0",
11
+ "version": "2.10.0",
12
12
  "author": {
13
13
  "name": "banyudu"
14
14
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "warden",
3
- "version": "2.9.0",
3
+ "version": "2.10.0",
4
4
  "description": "Smart command safety filter for Claude Code — parses shell pipelines and evaluates per-command safety rules to auto-approve safe commands and block dangerous ones",
5
5
  "author": {
6
6
  "name": "banyudu"
package/dist/cli.cjs CHANGED
@@ -18280,7 +18280,6 @@ function walkNode(node, result) {
18280
18280
  break;
18281
18281
  }
18282
18282
  case "Subshell": {
18283
- result.hasSubshell = true;
18284
18283
  const subshell = node;
18285
18284
  if (subshell.list?.commands) {
18286
18285
  for (const cmd of subshell.list.commands) {
@@ -19519,7 +19518,18 @@ var DEFAULT_CONFIG = {
19519
19518
  })),
19520
19519
  // --- Scripting languages ---
19521
19520
  { command: "ruby", default: "ask", argPatterns: [...inlineExecPatterns("Ruby", ["^-e$", "^--eval"]), VERSION_HELP_FLAGS] },
19522
- { command: "perl", default: "ask", argPatterns: [...inlineExecPatterns("Perl", ["^-e$", "^-E$"]), VERSION_HELP_FLAGS] },
19521
+ // `[npa]` bundles perl's common read-only short flags (`-pe`, `-ne`, `-ane`).
19522
+ // `-i` (in-place edit) mutates files — detected separately so it's caught whether
19523
+ // bundled (`-pie`, `-pi`) or passed as its own arg (`-i -pe`, `-i.bak -pe`).
19524
+ {
19525
+ command: "perl",
19526
+ default: "ask",
19527
+ argPatterns: [
19528
+ { match: { anyArgMatches: ["^-[a-z]*i"] }, decision: "ask", reason: "Perl `-i` does in-place file edits. Save the script to scripts/*.pl and run it." },
19529
+ ...inlineExecPatterns("Perl", ["^-[npa]*[eE]$"]),
19530
+ VERSION_HELP_FLAGS
19531
+ ]
19532
+ },
19523
19533
  { command: "php", default: "ask", argPatterns: [...inlineExecPatterns("PHP", ["^-r$"]), VERSION_HELP_FLAGS] },
19524
19534
  // --- Java ecosystem ---
19525
19535
  { command: "java", default: "ask", argPatterns: [VERSION_HELP_FLAGS] },
@@ -18284,7 +18284,6 @@ function walkNode(node, result) {
18284
18284
  break;
18285
18285
  }
18286
18286
  case "Subshell": {
18287
- result.hasSubshell = true;
18288
18287
  const subshell = node;
18289
18288
  if (subshell.list?.commands) {
18290
18289
  for (const cmd of subshell.list.commands) {
@@ -19523,7 +19522,18 @@ var DEFAULT_CONFIG = {
19523
19522
  })),
19524
19523
  // --- Scripting languages ---
19525
19524
  { command: "ruby", default: "ask", argPatterns: [...inlineExecPatterns("Ruby", ["^-e$", "^--eval"]), VERSION_HELP_FLAGS] },
19526
- { command: "perl", default: "ask", argPatterns: [...inlineExecPatterns("Perl", ["^-e$", "^-E$"]), VERSION_HELP_FLAGS] },
19525
+ // `[npa]` bundles perl's common read-only short flags (`-pe`, `-ne`, `-ane`).
19526
+ // `-i` (in-place edit) mutates files — detected separately so it's caught whether
19527
+ // bundled (`-pie`, `-pi`) or passed as its own arg (`-i -pe`, `-i.bak -pe`).
19528
+ {
19529
+ command: "perl",
19530
+ default: "ask",
19531
+ argPatterns: [
19532
+ { match: { anyArgMatches: ["^-[a-z]*i"] }, decision: "ask", reason: "Perl `-i` does in-place file edits. Save the script to scripts/*.pl and run it." },
19533
+ ...inlineExecPatterns("Perl", ["^-[npa]*[eE]$"]),
19534
+ VERSION_HELP_FLAGS
19535
+ ]
19536
+ },
19527
19537
  { command: "php", default: "ask", argPatterns: [...inlineExecPatterns("PHP", ["^-r$"]), VERSION_HELP_FLAGS] },
19528
19538
  // --- Java ecosystem ---
19529
19539
  { command: "java", default: "ask", argPatterns: [VERSION_HELP_FLAGS] },
package/dist/copilot.cjs CHANGED
@@ -18280,7 +18280,6 @@ function walkNode(node, result) {
18280
18280
  break;
18281
18281
  }
18282
18282
  case "Subshell": {
18283
- result.hasSubshell = true;
18284
18283
  const subshell = node;
18285
18284
  if (subshell.list?.commands) {
18286
18285
  for (const cmd of subshell.list.commands) {
@@ -19519,7 +19518,18 @@ var DEFAULT_CONFIG = {
19519
19518
  })),
19520
19519
  // --- Scripting languages ---
19521
19520
  { command: "ruby", default: "ask", argPatterns: [...inlineExecPatterns("Ruby", ["^-e$", "^--eval"]), VERSION_HELP_FLAGS] },
19522
- { command: "perl", default: "ask", argPatterns: [...inlineExecPatterns("Perl", ["^-e$", "^-E$"]), VERSION_HELP_FLAGS] },
19521
+ // `[npa]` bundles perl's common read-only short flags (`-pe`, `-ne`, `-ane`).
19522
+ // `-i` (in-place edit) mutates files — detected separately so it's caught whether
19523
+ // bundled (`-pie`, `-pi`) or passed as its own arg (`-i -pe`, `-i.bak -pe`).
19524
+ {
19525
+ command: "perl",
19526
+ default: "ask",
19527
+ argPatterns: [
19528
+ { match: { anyArgMatches: ["^-[a-z]*i"] }, decision: "ask", reason: "Perl `-i` does in-place file edits. Save the script to scripts/*.pl and run it." },
19529
+ ...inlineExecPatterns("Perl", ["^-[npa]*[eE]$"]),
19530
+ VERSION_HELP_FLAGS
19531
+ ]
19532
+ },
19523
19533
  { command: "php", default: "ask", argPatterns: [...inlineExecPatterns("PHP", ["^-r$"]), VERSION_HELP_FLAGS] },
19524
19534
  // --- Java ecosystem ---
19525
19535
  { command: "java", default: "ask", argPatterns: [VERSION_HELP_FLAGS] },
package/dist/index.cjs CHANGED
@@ -18280,7 +18280,6 @@ function walkNode(node, result) {
18280
18280
  break;
18281
18281
  }
18282
18282
  case "Subshell": {
18283
- result.hasSubshell = true;
18284
18283
  const subshell = node;
18285
18284
  if (subshell.list?.commands) {
18286
18285
  for (const cmd of subshell.list.commands) {
@@ -19519,7 +19518,18 @@ var DEFAULT_CONFIG = {
19519
19518
  })),
19520
19519
  // --- Scripting languages ---
19521
19520
  { command: "ruby", default: "ask", argPatterns: [...inlineExecPatterns("Ruby", ["^-e$", "^--eval"]), VERSION_HELP_FLAGS] },
19522
- { command: "perl", default: "ask", argPatterns: [...inlineExecPatterns("Perl", ["^-e$", "^-E$"]), VERSION_HELP_FLAGS] },
19521
+ // `[npa]` bundles perl's common read-only short flags (`-pe`, `-ne`, `-ane`).
19522
+ // `-i` (in-place edit) mutates files — detected separately so it's caught whether
19523
+ // bundled (`-pie`, `-pi`) or passed as its own arg (`-i -pe`, `-i.bak -pe`).
19524
+ {
19525
+ command: "perl",
19526
+ default: "ask",
19527
+ argPatterns: [
19528
+ { match: { anyArgMatches: ["^-[a-z]*i"] }, decision: "ask", reason: "Perl `-i` does in-place file edits. Save the script to scripts/*.pl and run it." },
19529
+ ...inlineExecPatterns("Perl", ["^-[npa]*[eE]$"]),
19530
+ VERSION_HELP_FLAGS
19531
+ ]
19532
+ },
19523
19533
  { command: "php", default: "ask", argPatterns: [...inlineExecPatterns("PHP", ["^-r$"]), VERSION_HELP_FLAGS] },
19524
19534
  // --- Java ecosystem ---
19525
19535
  { command: "java", default: "ask", argPatterns: [VERSION_HELP_FLAGS] },
@@ -20913,11 +20923,12 @@ function generateAllowSnippet(details) {
20913
20923
  }
20914
20924
  return lines.join("\n");
20915
20925
  }
20916
- function formatSystemMessage(decision, rawCommand, details) {
20926
+ function formatSystemMessage(decision, rawCommand, details, fallbackReason) {
20917
20927
  const relevant = details.filter((d) => d.decision !== "allow");
20918
20928
  if (decision === "ask") {
20919
20929
  const parts = relevant.map((d) => `\`${d.command}\`: ${d.reason}`);
20920
- const header = `[warden] ${parts.join(" | ")}`;
20930
+ const body = parts.length > 0 ? parts.join(" | ") : fallbackReason || "";
20931
+ const header = `[warden] ${body}`;
20921
20932
  const subcommandHints = relevant.filter((d) => d.args.length > 0).map((d) => {
20922
20933
  const sub = d.args[0];
20923
20934
  return ` Option A: Allow all \`${d.command}\` \u2192 \`/warden:allow ${d.command}\`
@@ -21191,14 +21202,14 @@ function emitResult(result, label, config) {
21191
21202
  const truncated = label.length > 80 ? label.slice(0, 77) + "..." : label;
21192
21203
  sendNotification("Claude Warden", `Blocked: ${truncated}`, config);
21193
21204
  }
21194
- const msg2 = formatSystemMessage("deny", label, result.details);
21205
+ const msg2 = formatSystemMessage("deny", label, result.details, result.reason);
21195
21206
  emitDecision("deny", msg2, `[warden] Blocked: ${result.reason}`);
21196
21207
  }
21197
21208
  if (config.notifyOnAsk) {
21198
21209
  const truncated = label.length > 80 ? label.slice(0, 77) + "..." : label;
21199
21210
  sendNotification("Claude Warden", `Permission needed: ${truncated}`, config);
21200
21211
  }
21201
- const msg = formatSystemMessage("ask", label, result.details);
21212
+ const msg = formatSystemMessage("ask", label, result.details, result.reason);
21202
21213
  emitDecision("ask", msg);
21203
21214
  }
21204
21215
  main().catch(() => process.exit(0));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-warden",
3
- "version": "2.9.0",
3
+ "version": "2.10.0",
4
4
  "description": "Smart command safety filter for Claude Code — auto-approves safe commands, blocks dangerous ones",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",