claude-warden 1.1.1 → 1.1.5

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.
Files changed (3) hide show
  1. package/README.md +3 -3
  2. package/dist/index.cjs +44 -7
  3. package/package.json +10 -11
package/README.md CHANGED
@@ -15,7 +15,7 @@ Warden hooks into Claude Code's `PreToolUse` event and **parses every shell comm
15
15
  This AST-based approach enables:
16
16
 
17
17
  - **Pipe and chain decomposition**: `cat file | grep pattern | wc -l` is parsed into three commands, each evaluated separately. All safe → auto-allow. One dangerous → deny the whole pipeline.
18
- - **Argument-aware rules**: `git status` → allow, `git push --force` → prompt. `rm temp.txt` → allow, `rm -rf /` → deny. The evaluator matches against argument patterns, not just command names.
18
+ - **Argument-aware rules**: `git status` → allow, `git push --force` → prompt. `rm temp.txt` → allow, `rm -rf /` → prompt. The evaluator matches against argument patterns, not just command names.
19
19
  - **Recursive evaluation of remote commands**: `ssh devserver 'cat /etc/hosts'` → Warden extracts the remote command, parses it through the same pipeline, and allows it. `ssh devserver 'sudo rm -rf /'` → denied. Same for `docker exec`, `kubectl exec`, and `sprite exec`.
20
20
  - **Shell wrapper unwrapping**: `sh -c "npm run build && npm test"` → the inner command is extracted and recursively parsed/evaluated, not treated as an opaque string.
21
21
  - **Env prefix handling**: `NODE_ENV=production npm run build` → correctly evaluates `npm run build`, ignoring the env prefix.
@@ -32,7 +32,7 @@ The result: **100+ common dev commands auto-approved**, dangerous commands auto-
32
32
  | `cat file \| grep pattern \| wc -l` | Prompted | Auto-allowed (3 safe commands) |
33
33
  | `npm run build && npm test` | Prompted | Auto-allowed |
34
34
  | `git push --force origin main` | Prompted | Prompted (force push is risky) |
35
- | `sudo rm -rf /` | Prompted | Auto-denied |
35
+ | `sudo rm -rf /` | Prompted | Auto-denied (sudo is blocked) |
36
36
  | `ssh devserver cat /etc/hosts` | Prompted | Auto-allowed (trusted host + safe cmd) |
37
37
  | `ssh devserver sudo rm -rf /` | Prompted | Auto-denied (trusted host + dangerous cmd) |
38
38
 
@@ -147,7 +147,7 @@ File readers (`cat`, `head`, `tail`, `less`), search tools (`grep`, `rg`, `find`
147
147
  ### Conditional rules
148
148
  Commands like `node`, `npx`, `docker`, `ssh`, `git push --force`, `rm`, `chmod` have argument-aware rules. For example:
149
149
  - `git` is allowed but `git push --force` triggers a prompt
150
- - `rm temp.txt` is allowed but `rm -rf /` is denied
150
+ - `rm temp.txt` is allowed but `rm -rf /` is prompted
151
151
  - `chmod 644 file` prompts but `chmod -R 777 /var` is denied
152
152
 
153
153
  ### Trusted remote targets
package/dist/index.cjs CHANGED
@@ -18944,6 +18944,28 @@ var DEFAULT_CONFIG = {
18944
18944
  { match: { anyArgMatches: ["^--(version|help)$", "^-[vh]$"] }, decision: "allow", description: "Version/help flags" }
18945
18945
  ]
18946
18946
  },
18947
+ // --- Shell interpreters ---
18948
+ {
18949
+ command: "bash",
18950
+ default: "ask",
18951
+ argPatterns: [
18952
+ { match: { anyArgMatches: ["^--(version|help)$"] }, decision: "allow", description: "Version/help flags" }
18953
+ ]
18954
+ },
18955
+ {
18956
+ command: "sh",
18957
+ default: "ask",
18958
+ argPatterns: [
18959
+ { match: { anyArgMatches: ["^--(version|help)$"] }, decision: "allow", description: "Version/help flags" }
18960
+ ]
18961
+ },
18962
+ {
18963
+ command: "zsh",
18964
+ default: "ask",
18965
+ argPatterns: [
18966
+ { match: { anyArgMatches: ["^--(version|help)$"] }, decision: "allow", description: "Version/help flags" }
18967
+ ]
18968
+ },
18947
18969
  // --- Node.js ecosystem ---
18948
18970
  {
18949
18971
  command: "node",
@@ -18959,7 +18981,7 @@ var DEFAULT_CONFIG = {
18959
18981
  default: "ask",
18960
18982
  argPatterns: [
18961
18983
  {
18962
- match: { anyArgMatches: ["^(jest|vitest|tsx|ts-node|tsc|eslint|prettier|mkdirp|concurrently|turbo|next|nuxt|vite|astro|playwright|cypress|mocha|nyc|c8|nodemon|ts-jest|tsup|esbuild|rollup|webpack|prisma|drizzle-kit|typeorm|knex|sequelize-cli|tailwindcss|postcss|autoprefixer|lint-staged|husky|changeset|semantic-release|lerna|nx|create-react-app|create-next-app|create-vite|degit|storybook|wrangler|netlify|vercel)$"] },
18984
+ match: { anyArgMatches: ["^(jest|vitest|tsx|ts-node|tsc|eslint|prettier|mkdirp|concurrently|turbo|next|nuxt|vite|astro|playwright|cypress|mocha|nyc|c8|nodemon|ts-jest|tsup|esbuild|rollup|webpack|prisma|drizzle-kit|typeorm|knex|sequelize-cli|tailwindcss|postcss|autoprefixer|lint-staged|husky|changeset|semantic-release|lerna|nx|create-react-app|create-next-app|create-vite|degit|storybook|wrangler|netlify|vercel|json)$"] },
18963
18985
  decision: "allow",
18964
18986
  description: "Well-known dev tools"
18965
18987
  },
@@ -18971,7 +18993,7 @@ var DEFAULT_CONFIG = {
18971
18993
  default: "ask",
18972
18994
  argPatterns: [
18973
18995
  {
18974
- match: { anyArgMatches: ["^(jest|vitest|tsx|ts-node|tsc|eslint|prettier|mkdirp|concurrently|turbo|next|nuxt|vite|astro|playwright|cypress|mocha|nyc|c8|nodemon|ts-jest|tsup|esbuild|rollup|webpack|prisma|drizzle-kit|typeorm|knex|sequelize-cli|tailwindcss|postcss|autoprefixer|lint-staged|husky|changeset|semantic-release|lerna|nx|create-react-app|create-next-app|create-vite|degit|storybook|wrangler|netlify|vercel)$"] },
18996
+ match: { anyArgMatches: ["^(jest|vitest|tsx|ts-node|tsc|eslint|prettier|mkdirp|concurrently|turbo|next|nuxt|vite|astro|playwright|cypress|mocha|nyc|c8|nodemon|ts-jest|tsup|esbuild|rollup|webpack|prisma|drizzle-kit|typeorm|knex|sequelize-cli|tailwindcss|postcss|autoprefixer|lint-staged|husky|changeset|semantic-release|lerna|nx|create-react-app|create-next-app|create-vite|degit|storybook|wrangler|netlify|vercel|json)$"] },
18975
18997
  decision: "allow",
18976
18998
  description: "Well-known dev tools"
18977
18999
  },
@@ -19088,7 +19110,7 @@ var DEFAULT_CONFIG = {
19088
19110
  command: "rm",
19089
19111
  default: "ask",
19090
19112
  argPatterns: [
19091
- { match: { argsMatch: ["-[^\\s]*r[^\\s]*f|-[^\\s]*f[^\\s]*r"] }, decision: "deny", reason: "Recursive force delete (rm -rf)" },
19113
+ { match: { argsMatch: ["-[^\\s]*r[^\\s]*f|-[^\\s]*f[^\\s]*r"] }, decision: "ask", reason: "Recursive force delete (rm -rf)" },
19092
19114
  { match: { argsMatch: ["-[^\\s]*r"] }, decision: "ask", reason: "Recursive delete" },
19093
19115
  { match: { argCount: { max: 3 }, not: false }, decision: "allow", description: "Deleting a small number of non-recursive files" }
19094
19116
  ]
@@ -19243,9 +19265,12 @@ function generateAllowSnippet(details) {
19243
19265
  return lines.join("\n");
19244
19266
  }
19245
19267
  function formatSystemMessage(decision, rawCommand, details) {
19246
- const header = decision === "deny" ? "[warden] Command blocked" : "[warden] Command flagged for review";
19247
- const lines = [header, ""];
19248
19268
  const relevant = details.filter((d) => d.decision !== "allow");
19269
+ if (decision === "ask") {
19270
+ const parts = relevant.map((d) => `\`${d.command}\`: ${d.reason}`);
19271
+ return `[warden] ${parts.join(" | ")} \u2014 To auto-allow, see /warden-allow`;
19272
+ }
19273
+ const lines = ["[warden] Command blocked", ""];
19249
19274
  if (relevant.length > 0) {
19250
19275
  for (const d of relevant) {
19251
19276
  lines.push(`- \`${d.command}\`: ${d.reason}`);
@@ -19304,14 +19329,26 @@ async function main() {
19304
19329
  }
19305
19330
  if (result.decision === "deny") {
19306
19331
  const msg2 = formatSystemMessage("deny", command, result.details);
19307
- const output2 = { systemMessage: msg2 };
19332
+ const output2 = {
19333
+ hookSpecificOutput: {
19334
+ hookEventName: "PreToolUse",
19335
+ permissionDecision: "deny",
19336
+ permissionDecisionReason: msg2
19337
+ }
19338
+ };
19308
19339
  process.stdout.write(JSON.stringify(output2));
19309
19340
  process.stderr.write(`[warden] Blocked: ${result.reason}
19310
19341
  `);
19311
19342
  process.exit(2);
19312
19343
  }
19313
19344
  const msg = formatSystemMessage("ask", command, result.details);
19314
- const output = { systemMessage: msg };
19345
+ const output = {
19346
+ hookSpecificOutput: {
19347
+ hookEventName: "PreToolUse",
19348
+ permissionDecision: "ask",
19349
+ permissionDecisionReason: msg
19350
+ }
19351
+ };
19315
19352
  process.stdout.write(JSON.stringify(output));
19316
19353
  process.exit(0);
19317
19354
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-warden",
3
- "version": "1.1.1",
3
+ "version": "1.1.5",
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",
@@ -28,15 +28,6 @@
28
28
  "README.md",
29
29
  "LICENSE"
30
30
  ],
31
- "scripts": {
32
- "build": "tsup",
33
- "dev": "tsup --watch",
34
- "test": "vitest run",
35
- "test:watch": "vitest",
36
- "typecheck": "tsc --noEmit",
37
- "eval": "node dist/index.cjs",
38
- "prepublishOnly": "pnpm run build && pnpm run test"
39
- },
40
31
  "devDependencies": {
41
32
  "@types/node": "^20.0.0",
42
33
  "bash-parser": "^0.5.0",
@@ -44,5 +35,13 @@
44
35
  "typescript": "^5.4.0",
45
36
  "vitest": "^1.6.0",
46
37
  "yaml": "^2.4.0"
38
+ },
39
+ "scripts": {
40
+ "build": "tsup",
41
+ "dev": "tsup --watch",
42
+ "test": "vitest run",
43
+ "test:watch": "vitest",
44
+ "typecheck": "tsc --noEmit",
45
+ "eval": "node dist/index.cjs"
47
46
  }
48
- }
47
+ }