claude-warden 1.10.0 → 2.3.1
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +2 -2
- package/README.md +107 -27
- package/config/warden.default.yaml +83 -31
- package/dist/codex-export.cjs +20730 -0
- package/dist/index.cjs +815 -308
- package/package.json +3 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "
|
|
3
|
-
"version": "
|
|
2
|
+
"name": "warden",
|
|
3
|
+
"version": "2.3.1",
|
|
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
|
@@ -42,13 +42,35 @@ The result: **100+ common dev commands auto-approved**, dangerous commands auto-
|
|
|
42
42
|
| `ssh devserver cat /etc/hosts` | Prompted | Auto-allowed (trusted host + safe cmd) |
|
|
43
43
|
| `ssh devserver sudo rm -rf /` | Prompted | Auto-denied (trusted host + dangerous cmd) |
|
|
44
44
|
|
|
45
|
+
## Warden vs Auto Mode
|
|
46
|
+
|
|
47
|
+
Claude Code recently introduced [Auto Mode](https://code.claude.com/docs/en/permission-modes#eliminate-prompts-with-auto-mode), which uses a background classifier model to approve or block actions without manual prompts. Here's how it compares to Warden:
|
|
48
|
+
|
|
49
|
+
| | Warden | Auto Mode |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| **How it works** | Deterministic rule engine with AST-based shell parsing | LLM classifier (Sonnet 4.6) reviews each action |
|
|
52
|
+
| **Availability** | All plans, all models, all providers (API, Bedrock, Vertex) | Team/Enterprise only, Sonnet 4.6 or Opus 4.6 only |
|
|
53
|
+
| **Token cost** | Zero — runs locally as a hook | Extra classifier calls count toward token usage |
|
|
54
|
+
| **Latency** | Near-instant (local process) | Network round-trip per classified action |
|
|
55
|
+
| **Configurability** | Full control via YAML — per-command rules, `targetPolicies`, and `trustedRemotes` | Prose-based rules, admin-managed trusted infrastructure |
|
|
56
|
+
| **Predictability** | Deterministic — same command always gets the same decision | Probabilistic — classifier may have false positives/negatives |
|
|
57
|
+
| **Scope** | Shell commands only (Bash tool) | All tool calls (Bash, file edits, network, subagents) |
|
|
58
|
+
|
|
59
|
+
**Can I use both?** Yes. Warden runs as a `PreToolUse` hook, which executes before Auto Mode's classifier. Warden handles fast, deterministic decisions for shell commands, and Auto Mode covers everything else (file edits, network requests, subagent spawning). They are complementary.
|
|
60
|
+
|
|
61
|
+
**When to choose Warden alone:** You're on a Free/Pro plan, using API/Bedrock/Vertex providers, want zero extra token cost, or need deterministic and auditable command-level rules.
|
|
62
|
+
|
|
63
|
+
**When to choose Auto Mode alone:** You want broader coverage beyond shell commands and are comfortable with classifier-based decisions.
|
|
64
|
+
|
|
65
|
+
**When to use both:** You want the best of both worlds — instant deterministic shell command filtering from Warden, plus Auto Mode's broader safety net for non-shell actions.
|
|
66
|
+
|
|
45
67
|
## Install
|
|
46
68
|
|
|
47
69
|
Two commands inside Claude Code:
|
|
48
70
|
|
|
49
71
|
```
|
|
50
72
|
/plugin marketplace add banyudu/claude-warden
|
|
51
|
-
/plugin install
|
|
73
|
+
/plugin install warden@claude-warden
|
|
52
74
|
```
|
|
53
75
|
|
|
54
76
|
That's it. Restart Claude Code and Warden is active.
|
|
@@ -68,6 +90,27 @@ cd claude-warden && npm install && npm run build
|
|
|
68
90
|
claude --plugin-dir ./claude-warden
|
|
69
91
|
```
|
|
70
92
|
|
|
93
|
+
## Codex CLI (experimental)
|
|
94
|
+
|
|
95
|
+
Codex currently uses `execpolicy` (`.rules` files) for command approvals. Warden can export your effective command-level decisions to a Codex rules file:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
pnpm run build
|
|
99
|
+
pnpm run codex:export-rules
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
This writes `.codex/rules/warden.rules` in the current project by default.
|
|
103
|
+
|
|
104
|
+
- Use `--cwd <dir>` to choose which workspace config to load.
|
|
105
|
+
- Use `--out <path>` to choose an output path.
|
|
106
|
+
- Use `--stdout` to print the generated rules.
|
|
107
|
+
|
|
108
|
+
Example:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
node dist/codex-export.cjs --cwd . --out .codex/rules/warden.rules
|
|
112
|
+
```
|
|
113
|
+
|
|
71
114
|
## Configure
|
|
72
115
|
|
|
73
116
|
Warden works out of the box with sensible defaults. To customize, create a config file:
|
|
@@ -108,17 +151,34 @@ alwaysAllow:
|
|
|
108
151
|
alwaysDeny:
|
|
109
152
|
- nc
|
|
110
153
|
|
|
111
|
-
# Trusted remote
|
|
112
|
-
|
|
113
|
-
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
-
|
|
118
|
-
|
|
119
|
-
-
|
|
120
|
-
|
|
121
|
-
-
|
|
154
|
+
# Trusted remote contexts (auto-allow connection, evaluate remote commands)
|
|
155
|
+
trustedRemotes:
|
|
156
|
+
- context: ssh
|
|
157
|
+
name: devserver
|
|
158
|
+
- context: ssh
|
|
159
|
+
name: "*.internal.company.com"
|
|
160
|
+
- context: docker
|
|
161
|
+
name: my-app
|
|
162
|
+
- context: docker
|
|
163
|
+
name: dev-*
|
|
164
|
+
- context: kubectl
|
|
165
|
+
name: minikube
|
|
166
|
+
- context: sprite
|
|
167
|
+
name: my-sprite
|
|
168
|
+
|
|
169
|
+
# Target-based policy overrides for data-sensitive commands
|
|
170
|
+
targetPolicies:
|
|
171
|
+
- type: path
|
|
172
|
+
path: "{{cwd}}"
|
|
173
|
+
commands: [rm, cp, mv]
|
|
174
|
+
decision: allow
|
|
175
|
+
- type: endpoint
|
|
176
|
+
pattern: "http://localhost:*"
|
|
177
|
+
decision: allow
|
|
178
|
+
- type: database
|
|
179
|
+
host: "prod-db.internal"
|
|
180
|
+
decision: deny
|
|
181
|
+
reason: Production database
|
|
122
182
|
|
|
123
183
|
# Per-command rules (override built-in defaults for this scope)
|
|
124
184
|
rules:
|
|
@@ -140,13 +200,24 @@ Need to temporarily bypass all permission prompts? YOLO mode auto-allows all com
|
|
|
140
200
|
### Activate via slash command
|
|
141
201
|
|
|
142
202
|
```
|
|
143
|
-
/
|
|
144
|
-
/
|
|
145
|
-
/
|
|
146
|
-
/
|
|
203
|
+
/warden:yolo session # Full session, no expiry
|
|
204
|
+
/warden:yolo 5m # 5 minutes
|
|
205
|
+
/warden:yolo 15m # 15 minutes
|
|
206
|
+
/warden:yolo off # Turn off immediately
|
|
147
207
|
```
|
|
148
208
|
|
|
149
|
-
Running `/
|
|
209
|
+
Running `/warden:yolo` with no arguments shows a menu of duration options.
|
|
210
|
+
|
|
211
|
+
### Activate via environment variable
|
|
212
|
+
|
|
213
|
+
For non-interactive sessions where `/warden:yolo` can't be invoked (e.g. piped prompts), set the `WARDEN_YOLO` env var:
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
WARDEN_YOLO=true claude < prompts.txt
|
|
217
|
+
WARDEN_YOLO=1 claude < prompts.txt
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Unlike the slash command, `WARDEN_YOLO` bypasses **all** checks including always-deny commands — it short-circuits before any parsing or evaluation, same as `--dangerously-skip-permissions`.
|
|
150
221
|
|
|
151
222
|
### How it works
|
|
152
223
|
|
|
@@ -156,14 +227,14 @@ YOLO mode is **session-scoped** — it only affects the current Claude Code sess
|
|
|
156
227
|
|
|
157
228
|
When Warden prompts you for permission (`ask` decision), the system message includes a tip about YOLO mode so you can discover it when you need it most.
|
|
158
229
|
|
|
159
|
-
## Feedback and `/
|
|
230
|
+
## Feedback and `/warden:allow`
|
|
160
231
|
|
|
161
232
|
When Warden blocks or flags a command, it includes a system message explaining:
|
|
162
233
|
|
|
163
234
|
1. **Why** the command was blocked/flagged (per-command reasons)
|
|
164
235
|
2. **How to allow it** — a ready-to-use YAML snippet for your config
|
|
165
236
|
|
|
166
|
-
Use the `/
|
|
237
|
+
Use the `/warden:allow` slash command to apply the suggested config change. It will ask which scope (project or user) to use.
|
|
167
238
|
|
|
168
239
|
## Built-in defaults
|
|
169
240
|
|
|
@@ -179,21 +250,30 @@ Commands like `node`, `npx`, `docker`, `ssh`, `git push --force`, `rm`, `chmod`
|
|
|
179
250
|
- `rm temp.txt` is allowed but `rm -rf /` is prompted
|
|
180
251
|
- `chmod 644 file` prompts but `chmod -R 777 /var` is denied
|
|
181
252
|
|
|
182
|
-
### Trusted
|
|
183
|
-
Configure
|
|
184
|
-
- **SSH**: `
|
|
185
|
-
- **Docker**: `
|
|
186
|
-
- **kubectl**: `
|
|
187
|
-
- **Sprite**: `
|
|
253
|
+
### Trusted remotes
|
|
254
|
+
Configure `trustedRemotes` to auto-allow connections and recursively evaluate remote commands:
|
|
255
|
+
- **SSH**: `context: ssh` — also covers `scp` and `rsync`
|
|
256
|
+
- **Docker**: `context: docker` — for `docker exec`
|
|
257
|
+
- **kubectl**: `context: kubectl` — for `kubectl exec` (requires explicit `--context`)
|
|
258
|
+
- **Sprite**: `context: sprite` — for `sprite exec`/`console`
|
|
259
|
+
- **Fly.io**: `context: fly` — for `fly ssh console`
|
|
260
|
+
|
|
261
|
+
Remote names support glob patterns: `*`, `?`, `[...]`, `[!...]`, `{a,b,c}`
|
|
262
|
+
|
|
263
|
+
### Target-based policies
|
|
264
|
+
Configure `targetPolicies` to override decisions based on what a command touches:
|
|
265
|
+
- **Path**: allow or deny commands targeting specific files/directories, including `{{cwd}}`
|
|
266
|
+
- **Database**: match DB host, optional port, and optional database name
|
|
267
|
+
- **Endpoint**: match HTTP(S) endpoints for tools like `curl` and `wget`
|
|
188
268
|
|
|
189
|
-
|
|
269
|
+
Legacy aliases such as `trustedSSHHosts`, `trustedDockerContainers`, `trustedKubectlContexts`, `trustedSprites`, `trustedFlyApps`, `trustedPaths`, `trustedDatabases`, and `trustedEndpoints` are still supported, but new configs should prefer `trustedRemotes` and `targetPolicies`.
|
|
190
270
|
|
|
191
271
|
## How it works
|
|
192
272
|
|
|
193
273
|
1. Claude Code calls the `PreToolUse` hook before every Bash command
|
|
194
274
|
2. Warden parses the command into an AST via [bash-parser](https://github.com/vorpaljs/bash-parser), walking the tree to extract individual commands from pipes, chains, logical expressions, and subshells
|
|
195
275
|
3. Shell wrappers (`sh -c`, `bash -c`) and remote commands (`ssh`, `docker exec`, `kubectl exec`, `sprite exec`) are recursively parsed and evaluated
|
|
196
|
-
4. Each command is evaluated through the rule hierarchy: alwaysDeny → alwaysAllow → trusted remote
|
|
276
|
+
4. Each command is evaluated through the rule hierarchy: alwaysDeny → alwaysAllow → target-based policies → trusted remote contexts → command-specific rules with argument matching → default decision (checked per layer in priority order)
|
|
197
277
|
5. Results are combined: any deny → deny whole pipeline, any ask → ask, all allow → allow
|
|
198
278
|
6. Returns the decision via stdout JSON (allow/ask) or exit code 2 (deny), with a system message explaining the reasoning for deny/ask decisions
|
|
199
279
|
|
|
@@ -30,48 +30,100 @@ notifyOnDeny: true
|
|
|
30
30
|
# - nc
|
|
31
31
|
# - ncat
|
|
32
32
|
|
|
33
|
-
#
|
|
34
|
-
#
|
|
35
|
-
# Supports glob patterns (* wildcards).
|
|
36
|
-
#
|
|
37
|
-
#
|
|
38
|
-
#
|
|
39
|
-
# -
|
|
40
|
-
#
|
|
41
|
-
# -
|
|
33
|
+
# Remote execution contexts — SSH, Docker, kubectl, Sprite, Fly.io
|
|
34
|
+
# Commands on trusted remotes are recursively evaluated through warden rules.
|
|
35
|
+
# Supports glob patterns (* wildcards) for names.
|
|
36
|
+
# trustedRemotes:
|
|
37
|
+
# - context: ssh
|
|
38
|
+
# name: devserver
|
|
39
|
+
# - context: ssh
|
|
40
|
+
# name: staging-*
|
|
41
|
+
# - context: ssh
|
|
42
|
+
# name: "*.internal.company.com"
|
|
43
|
+
# - context: ssh
|
|
44
|
+
# name: prod-bastion
|
|
42
45
|
# overrides:
|
|
43
46
|
# alwaysAllow: [systemctl]
|
|
44
|
-
|
|
45
|
-
#
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
#
|
|
49
|
-
# -
|
|
50
|
-
#
|
|
51
|
-
# - name: staging-* # object with per-target overrides
|
|
47
|
+
# - context: docker
|
|
48
|
+
# name: my-app
|
|
49
|
+
# - context: docker
|
|
50
|
+
# name: dev-container
|
|
51
|
+
# allowAll: true # skip all checks (disposable env)
|
|
52
|
+
# - context: docker
|
|
53
|
+
# name: staging-*
|
|
52
54
|
# overrides:
|
|
53
55
|
# alwaysAllow: [sudo, apt]
|
|
54
|
-
|
|
55
|
-
#
|
|
56
|
-
#
|
|
57
|
-
#
|
|
58
|
-
# - minikube
|
|
59
|
-
# - name: dev-cluster-*
|
|
56
|
+
# - context: kubectl
|
|
57
|
+
# name: minikube
|
|
58
|
+
# - context: kubectl
|
|
59
|
+
# name: dev-cluster-*
|
|
60
60
|
# overrides:
|
|
61
61
|
# alwaysAllow: [sudo]
|
|
62
|
-
# -
|
|
62
|
+
# - context: kubectl
|
|
63
|
+
# name: prod-cluster
|
|
63
64
|
# overrides:
|
|
64
65
|
# alwaysDeny: [rm]
|
|
65
|
-
|
|
66
|
-
#
|
|
67
|
-
#
|
|
68
|
-
#
|
|
69
|
-
# - my-sprite # string → uses global overrides only
|
|
70
|
-
# - name: yudu-claw # allowAll: skip all checks (disposable env)
|
|
66
|
+
# - context: sprite
|
|
67
|
+
# name: my-sprite
|
|
68
|
+
# - context: sprite
|
|
69
|
+
# name: yudu-claw
|
|
71
70
|
# allowAll: true
|
|
72
|
-
# -
|
|
71
|
+
# - context: sprite
|
|
72
|
+
# name: dev-*
|
|
73
73
|
# overrides:
|
|
74
74
|
# alwaysAllow: [sudo, apt]
|
|
75
|
+
# - context: fly
|
|
76
|
+
# name: my-fly-app
|
|
77
|
+
# - context: fly
|
|
78
|
+
# name: staging-*
|
|
79
|
+
# allowAll: true
|
|
80
|
+
# - context: fly
|
|
81
|
+
# name: prod-app
|
|
82
|
+
# overrides:
|
|
83
|
+
# alwaysAllow: [sudo, apt]
|
|
84
|
+
|
|
85
|
+
# Target-based policies — override decisions based on paths, databases, or endpoints.
|
|
86
|
+
# targetPolicies:
|
|
87
|
+
# - type: path
|
|
88
|
+
# path: /tmp
|
|
89
|
+
# allowAll: true # any command targeting /tmp is auto-allowed
|
|
90
|
+
# - type: path
|
|
91
|
+
# path: "{{cwd}}" # expands to the project's working directory
|
|
92
|
+
# decision: allow
|
|
93
|
+
# commands: [rm, cp, mv] # only override these commands
|
|
94
|
+
# - type: path
|
|
95
|
+
# path: /etc
|
|
96
|
+
# decision: deny # block modifications to /etc
|
|
97
|
+
# reason: "System config directory"
|
|
98
|
+
# - type: path
|
|
99
|
+
# path: /opt/build
|
|
100
|
+
# recursive: false # exact match only (not children)
|
|
101
|
+
# decision: allow
|
|
102
|
+
# - type: database
|
|
103
|
+
# host: localhost
|
|
104
|
+
# decision: allow
|
|
105
|
+
# - type: database
|
|
106
|
+
# host: "dev-*.internal"
|
|
107
|
+
# database: "test_*"
|
|
108
|
+
# decision: allow
|
|
109
|
+
# - type: database
|
|
110
|
+
# host: "prod.example.com"
|
|
111
|
+
# decision: deny
|
|
112
|
+
# reason: "Production database"
|
|
113
|
+
# - type: endpoint
|
|
114
|
+
# pattern: "http://localhost:*"
|
|
115
|
+
# decision: allow
|
|
116
|
+
# - type: endpoint
|
|
117
|
+
# pattern: "https://api.dev.example.com/*"
|
|
118
|
+
# decision: allow
|
|
119
|
+
# - type: endpoint
|
|
120
|
+
# pattern: "https://api.prod.example.com/*"
|
|
121
|
+
# decision: deny
|
|
122
|
+
# reason: "Production API"
|
|
123
|
+
|
|
124
|
+
# Legacy keys (trustedSSHHosts, trustedDockerContainers, trustedKubectlContexts,
|
|
125
|
+
# trustedSprites, trustedFlyApps, trustedPaths, trustedDatabases, trustedEndpoints)
|
|
126
|
+
# are still supported and automatically converted to the unified form above.
|
|
75
127
|
|
|
76
128
|
# Override rules when evaluating commands inside trusted remote contexts
|
|
77
129
|
# (docker exec, kubectl exec, ssh, sprite exec). These overrides are applied
|