claude-warden 1.5.1 → 1.5.2

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-warden",
3
- "version": "1.5.1",
3
+ "version": "1.5.2",
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/README.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Claude Warden
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/claude-warden)](https://www.npmjs.com/package/claude-warden)
4
+ [![npm downloads](https://img.shields.io/npm/dm/claude-warden)](https://www.npmjs.com/package/claude-warden)
5
+ [![GitHub license](https://img.shields.io/github/license/banyudu/claude-warden)](https://github.com/banyudu/claude-warden/blob/main/LICENSE)
6
+ [![GitHub stars](https://img.shields.io/github/stars/banyudu/claude-warden)](https://github.com/banyudu/claude-warden/stargazers)
7
+ [![CI](https://img.shields.io/github/actions/workflow/status/banyudu/claude-warden/ci.yml?label=CI)](https://github.com/banyudu/claude-warden/actions)
8
+
3
9
  Smart command safety filter for [Claude Code](https://claude.ai/code). Parses shell commands, evaluates each against configurable safety rules, and returns allow/deny/ask decisions — eliminating unnecessary permission prompts while blocking dangerous commands.
4
10
 
5
11
  ## The problem
package/dist/index.cjs CHANGED
@@ -18145,7 +18145,8 @@ function preprocessCatHeredocs(input) {
18145
18145
  }
18146
18146
  function convertCommand(node) {
18147
18147
  if (!node.name) return null;
18148
- const command = node.name.text.includes("/") ? (0, import_path.basename)(node.name.text) : node.name.text;
18148
+ const originalCommand = node.name.text;
18149
+ const command = originalCommand.includes("/") ? (0, import_path.basename)(originalCommand) : originalCommand;
18149
18150
  const envPrefixes = [];
18150
18151
  if (node.prefix) {
18151
18152
  for (const p of node.prefix) {
@@ -18168,7 +18169,7 @@ function convertCommand(node) {
18168
18169
  ...args2
18169
18170
  ];
18170
18171
  const raw = rawParts.join(" ");
18171
- return { command, args: args2, envPrefixes, raw };
18172
+ return { command, originalCommand, args: args2, envPrefixes, raw };
18172
18173
  }
18173
18174
  function collectCommandExpansions(node) {
18174
18175
  const commands = [];
@@ -18335,6 +18336,16 @@ function parseCommand(input) {
18335
18336
  }
18336
18337
 
18337
18338
  // src/evaluator.ts
18339
+ var import_os = require("os");
18340
+ function commandMatchesName(cmd, name) {
18341
+ if (name.startsWith("/")) {
18342
+ return cmd.originalCommand === name;
18343
+ }
18344
+ if (name.startsWith("~/")) {
18345
+ return cmd.originalCommand === (0, import_os.homedir)() + name.slice(1);
18346
+ }
18347
+ return cmd.command === name;
18348
+ }
18338
18349
  function evaluate(parsed, config) {
18339
18350
  if (parsed.parseError) {
18340
18351
  return { decision: "ask", reason: "Could not parse command safely", details: [] };
@@ -18382,10 +18393,10 @@ function evaluate(parsed, config) {
18382
18393
  function evaluateCommand(cmd, config) {
18383
18394
  const { command, args: args2 } = cmd;
18384
18395
  for (const layer of config.layers) {
18385
- if (layer.alwaysDeny.includes(command)) {
18396
+ if (layer.alwaysDeny.some((name) => commandMatchesName(cmd, name))) {
18386
18397
  return { command, args: args2, decision: "deny", reason: `"${command}" is blocked`, matchedRule: "alwaysDeny" };
18387
18398
  }
18388
- if (layer.alwaysAllow.includes(command)) {
18399
+ if (layer.alwaysAllow.some((name) => commandMatchesName(cmd, name))) {
18389
18400
  return { command, args: args2, decision: "allow", reason: `"${command}" is safe`, matchedRule: "alwaysAllow" };
18390
18401
  }
18391
18402
  }
@@ -18406,7 +18417,7 @@ function evaluateCommand(cmd, config) {
18406
18417
  if (spriteResult) return spriteResult;
18407
18418
  }
18408
18419
  for (const layer of config.layers) {
18409
- const rule = layer.rules.find((r) => r.command === command);
18420
+ const rule = layer.rules.find((r) => commandMatchesName(cmd, r.command));
18410
18421
  if (rule) {
18411
18422
  return evaluateRule(cmd, rule);
18412
18423
  }
@@ -18642,7 +18653,7 @@ function evaluateRemoteCommand(remoteArgs, config, target) {
18642
18653
  return evaluate(parsed2, overriddenConfig);
18643
18654
  }
18644
18655
  const parsed = {
18645
- commands: [{ command: remoteCmd, args: remoteArgs.slice(1), envPrefixes: [], raw: remoteArgs.join(" ") }],
18656
+ commands: [{ command: remoteCmd, originalCommand: remoteCmd, args: remoteArgs.slice(1), envPrefixes: [], raw: remoteArgs.join(" ") }],
18646
18657
  hasSubshell: false,
18647
18658
  subshellCommands: [],
18648
18659
  parseError: false
@@ -18842,7 +18853,7 @@ function evaluateSpriteExec(cmd, config) {
18842
18853
  // src/rules.ts
18843
18854
  var import_fs = require("fs");
18844
18855
  var import_yaml = __toESM(require_dist2(), 1);
18845
- var import_os = require("os");
18856
+ var import_os2 = require("os");
18846
18857
  var import_path2 = require("path");
18847
18858
 
18848
18859
  // src/defaults.ts
@@ -19486,8 +19497,8 @@ var DEFAULT_CONFIG = {
19486
19497
 
19487
19498
  // src/rules.ts
19488
19499
  var USER_CONFIG_PATHS = [
19489
- (0, import_path2.join)((0, import_os.homedir)(), ".claude", "warden.yaml"),
19490
- (0, import_path2.join)((0, import_os.homedir)(), ".claude", "warden.json")
19500
+ (0, import_path2.join)((0, import_os2.homedir)(), ".claude", "warden.yaml"),
19501
+ (0, import_path2.join)((0, import_os2.homedir)(), ".claude", "warden.json")
19491
19502
  ];
19492
19503
  var PROJECT_CONFIG_NAMES = [
19493
19504
  ".claude/warden.yaml",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-warden",
3
- "version": "1.5.1",
3
+ "version": "1.5.2",
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",