tool-permissions.md

  1# Tool Permissions
  2
  3Configure which agent actions run automatically and which require your approval.
  4
  5> **Note:** In Zed v0.224.0 and above, this page documents the granular `agent.tool_permissions` system.
  6>
  7> **Note:** Before Zed v0.224.0, tool approval was controlled by the `agent.always_allow_tool_actions` boolean (default `false`). Set it to `true` to auto-approve tool actions, or leave it `false` to require confirmation.
  8
  9## Quick Start
 10
 11You can use Zed's Settings UI to configure tool permissions, or add rules directly to your `settings.json`:
 12
 13```json [settings]
 14{
 15  "agent": {
 16    "tool_permissions": {
 17      "default": "allow",
 18      "tools": {
 19        "terminal": {
 20          "default": "confirm",
 21          "always_allow": [
 22            { "pattern": "^cargo\\s+(build|test|check)" },
 23            { "pattern": "^npm\\s+(install|test|run)" }
 24          ],
 25          "always_confirm": [{ "pattern": "sudo\\s+/" }]
 26        }
 27      }
 28    }
 29  }
 30}
 31```
 32
 33This example auto-approves `cargo` and `npm` commands in the terminal tool, while requiring manual confirmation on a case-by-case basis for `sudo` commands. Non-terminal commands follow the global `"default": "allow"` setting, but tool-specific defaults and `always_confirm` rules can still prompt.
 34
 35## How It Works
 36
 37The `tool_permissions` setting lets you customize tool permissions by specifying regex patterns that:
 38
 39- **Auto-approve** actions you trust
 40- **Auto-deny** dangerous actions (blocked even when `tool_permissions.default` is set to `"allow"`)
 41- **Always confirm** sensitive actions regardless of other settings
 42
 43## Supported Tools
 44
 45| Tool                     | Input Matched Against        |
 46| ------------------------ | ---------------------------- |
 47| `terminal`               | The shell command string     |
 48| `edit_file`              | The file path                |
 49| `delete_path`            | The path being deleted       |
 50| `move_path`              | Source and destination paths |
 51| `copy_path`              | Source and destination paths |
 52| `create_directory`       | The directory path           |
 53| `restore_file_from_disk` | The file paths               |
 54| `save_file`              | The file paths               |
 55| `fetch`                  | The URL                      |
 56| `web_search`             | The search query             |
 57
 58For MCP tools, use the format `mcp:<server>:<tool_name>`. For example, a tool called `create_issue` on a server called `github` would be `mcp:github:create_issue`.
 59
 60## Configuration
 61
 62```json [settings]
 63{
 64  "agent": {
 65    "tool_permissions": {
 66      "default": "confirm",
 67      "tools": {
 68        "<tool_name>": {
 69          "default": "confirm",
 70          "always_allow": [{ "pattern": "...", "case_sensitive": false }],
 71          "always_deny": [{ "pattern": "...", "case_sensitive": false }],
 72          "always_confirm": [{ "pattern": "...", "case_sensitive": false }]
 73        }
 74      }
 75    }
 76  }
 77}
 78```
 79
 80### Options
 81
 82| Option           | Description                                                                    |
 83| ---------------- | ------------------------------------------------------------------------------ |
 84| `default`        | Fallback when no patterns match: `"confirm"` (default), `"allow"`, or `"deny"` |
 85| `always_allow`   | Patterns that auto-approve (unless deny or confirm also matches)               |
 86| `always_deny`    | Patterns that block immediately—highest priority, cannot be overridden         |
 87| `always_confirm` | Patterns that always prompt, even when `tool_permissions.default` is `"allow"` |
 88
 89### Pattern Syntax
 90
 91```json [settings]
 92{
 93  "pattern": "your-regex-here",
 94  "case_sensitive": false
 95}
 96```
 97
 98Patterns use Rust regex syntax. Matching is case-insensitive by default.
 99
100## Rule Precedence
101
102From highest to lowest priority:
103
1041. **Built-in security rules** — Hardcoded protections (e.g., `rm -rf /`). Cannot be overridden.
1052. **`always_deny`** — Blocks matching actions
1063. **`always_confirm`** — Requires confirmation for matching actions
1074. **`always_allow`** — Auto-approves matching actions
1085. **Tool-specific `default`** — Per-tool fallback when no patterns match (e.g., `tools.terminal.default`)
1096. **Global `default`** — Falls back to `tool_permissions.default` when no tool-specific default is set
110
111## Examples
112
113### Terminal: Auto-Approve Build Commands
114
115```json [settings]
116{
117  "agent": {
118    "tool_permissions": {
119      "tools": {
120        "terminal": {
121          "default": "confirm",
122          "always_allow": [
123            { "pattern": "^cargo\\s+(build|test|check|clippy|fmt)" },
124            { "pattern": "^npm\\s+(install|test|run|build)" },
125            { "pattern": "^git\\s+(status|log|diff|branch)" },
126            { "pattern": "^ls\\b" },
127            { "pattern": "^cat\\s" }
128          ],
129          "always_deny": [
130            { "pattern": "rm\\s+-rf\\s+(/|~)" },
131            { "pattern": "sudo\\s+rm" }
132          ],
133          "always_confirm": [
134            { "pattern": "sudo\\s" },
135            { "pattern": "git\\s+push" }
136          ]
137        }
138      }
139    }
140  }
141}
142```
143
144### File Editing: Protect Sensitive Files
145
146```json [settings]
147{
148  "agent": {
149    "tool_permissions": {
150      "tools": {
151        "edit_file": {
152          "default": "confirm",
153          "always_allow": [
154            { "pattern": "\\.(md|txt|json)$" },
155            { "pattern": "^src/" }
156          ],
157          "always_deny": [
158            { "pattern": "\\.env" },
159            { "pattern": "secrets?/" },
160            { "pattern": "\\.(pem|key)$" }
161          ]
162        }
163      }
164    }
165  }
166}
167```
168
169### Path Deletion: Block Critical Directories
170
171```json [settings]
172{
173  "agent": {
174    "tool_permissions": {
175      "tools": {
176        "delete_path": {
177          "default": "confirm",
178          "always_deny": [
179            { "pattern": "^/etc" },
180            { "pattern": "^/usr" },
181            { "pattern": "\\.git/?$" },
182            { "pattern": "node_modules/?$" }
183          ]
184        }
185      }
186    }
187  }
188}
189```
190
191### URL Fetching: Control External Access
192
193```json [settings]
194{
195  "agent": {
196    "tool_permissions": {
197      "tools": {
198        "fetch": {
199          "default": "confirm",
200          "always_allow": [
201            { "pattern": "docs\\.rs" },
202            { "pattern": "github\\.com" }
203          ],
204          "always_deny": [{ "pattern": "internal\\.company\\.com" }]
205        }
206      }
207    }
208  }
209}
210```
211
212### MCP Tools
213
214```json [settings]
215{
216  "agent": {
217    "tool_permissions": {
218      "tools": {
219        "mcp:github:create_issue": {
220          "default": "confirm"
221        },
222        "mcp:github:create_pull_request": {
223          "default": "confirm"
224        }
225      }
226    }
227  }
228}
229```
230
231## Global Auto-Approve
232
233To auto-approve all tool actions:
234
235```json [settings]
236{
237  "agent": {
238    "tool_permissions": {
239      "default": "allow"
240    }
241  }
242}
243```
244
245This bypasses confirmation prompts for most actions, but `always_deny`, `always_confirm`, built-in security rules, and paths inside Zed settings directories still prompt or block.
246
247## Shell Compatibility
248
249For the `terminal` tool, Zed parses chained commands (e.g., `echo hello && rm file`) to check each sub-command against your patterns.
250
251All supported shells work with tool permission patterns, including sh, bash, zsh, dash, fish, PowerShell 7+, pwsh, cmd, xonsh, csh, tcsh, Nushell, Elvish, and rc (Plan 9).
252
253## Writing Patterns
254
255- Use `\b` for word boundaries: `\brm\b` matches "rm" but not "storm"
256- Use `^` and `$` to anchor patterns to start/end of input
257- Escape special characters: `\.` for literal dot, `\\` for backslash
258- Test carefully—a typo in a deny pattern blocks legitimate actions
259
260## Built-in Security Rules
261
262Zed includes a small set of hardcoded security rules that **cannot be overridden** by any setting. These only apply to the **terminal** tool and block recursive deletion of critical directories:
263
264- `rm -rf /` and `rm -rf /*` — filesystem root
265- `rm -rf ~` and `rm -rf ~/*` — home directory
266- `rm -rf $HOME` / `rm -rf ${HOME}` (and `$HOME/*`) — home directory via environment variable
267- `rm -rf .` and `rm -rf ./*` — current directory
268- `rm -rf ..` and `rm -rf ../*` — parent directory
269
270These patterns catch any flag combination (e.g., `-fr`, `-rfv`, `-r -f`, `--recursive --force`) and are case-insensitive. They are checked against both the raw command and each parsed sub-command in chained commands (e.g., `ls && rm -rf /`).
271
272There are no other built-in rules. The default settings file ({#action zed::OpenDefaultSettings}) includes commented-out examples for protecting `.env` files, secrets directories, and private keys — you can uncomment or adapt these to suit your needs.
273
274## UI Options
275
276When the agent requests permission, the dialog includes:
277
278- **Allow once** / **Deny once** — One-time decision
279- **Always for <tool>** — Sets a tool-level default to allow or deny
280- **Always for <pattern>** — Adds an `always_allow` or `always_deny` pattern (when a safe pattern can be extracted)
281
282Selecting "Always for <tool>" sets `tools.<tool>.default` to allow or deny. When a pattern can be safely extracted, selecting "Always for <pattern>" adds an `always_allow` or `always_deny` rule for that input. MCP tools only support the tool-level option.