A single, unified permission model for everything the agent does. Write one rule to allow npm * commands across every session, or deny .env reads and have every tool respect it simultaneously. The visual consent flow builds your policy as you work: approve or deny from the prompt, choose a pattern, pick a scope, and you're done.
Each rule has four fields:
| Field | Description | Required |
|---|---|---|
capability | The operation type being controlled | Yes |
match | Glob patterns the resource must match | No (defaults to all) |
exclude | Glob patterns that exempt a resource from the rule | No |
effect | deny, ask, or allow | Yes |
Effects resolve by restrictiveness: deny > ask > allow. A more permissive rule can never override a more restrictive one.
| Scope | Location | Allowed effects |
|---|---|---|
| User | ~/.kiro/settings/permissions.yaml | deny, ask, allow |
| Workspace | ~/.kiro/workspace-roots/<hash>/permissions.yaml | deny, ask, allow |
Additional scopes are managed by the system:
| Scope | Purpose | Allowed effects |
|---|---|---|
| Kiro | Hardcoded security invariants (cannot be overridden) | deny, ask |
| Administration | Enterprise/MDM-managed policy (enterprise plans only) | deny, ask |
| Session | In-memory rules from consent decisions you make in the IDE | deny, ask, allow |
Workspace permissions are stored per-user outside the repository at ~/.kiro/workspace-roots/<hash(workspaceRoot)>/. A cloned repo cannot inject permission rules.
When a tool call evaluates to ask, the IDE shows a permission prompt at the top of the chat panel. You have four immediate options:
| Button | What it does |
|---|---|
| Allow | Permit this single invocation |
| Always allow | Open the persistence dialog to save an allow rule |
| Deny | Block this single invocation |
| Always deny | Open the persistence dialog to save a deny rule |
When you click "Always allow" or "Always deny", the prompt expands to show two additional controls:
Pattern: The glob pattern for the rule. The IDE auto-suggests a pattern based on the command (e.g., git add * for a git add invocation). You can customize this to be more or less specific.
Apply to: Where the rule is saved:
| Scope | What it means |
|---|---|
| All workspaces | Saved to ~/.kiro/settings/permissions.yaml, applies everywhere |
| This workspace | Saved to ~/.kiro/workspace-roots/<hash>/permissions.yaml, applies only in this project |
| This session | Remembered in memory until the session ends |
Click "Always allow" (or "Always deny") to confirm. The rule takes effect immediately and you won't be prompted again for matching operations in the selected scope.
The pattern dropdown suggests a generalized version of the specific command. For example:
git add contents/docs/ becomes pattern git add *.env.local becomes pattern .env* or **/.env*You can select the suggested pattern or edit it to be more restrictive (matching only specific subcommands) or more permissive (matching broader operations).
Create ~/.kiro/settings/permissions.yaml:
rules: - capability: shell effect: allow match: - git * - npm * - npx * - capability: mcp effect: allow - capability: fs_read effect: allow - capability: fs_write effect: allow match: - src/** - tests/**
Without any configuration, the default agent policy allows:
fs_read on ./**: read any file in the workspaceshell for common read-only commands (git status, git log, git diff, etc.)The Kiro scope (hardcoded, cannot be overridden) enforces:
~/.kiro/settings/, .kiro/settings/, and ~/.kiro/workspace-roots/ (prevents the agent from modifying its own permission files).git/**, .kiro/agents/**, .kiro/hooks/**, .kiroignoreEverything else prompts for approval. Creating a permissions.yaml adds to these defaults.
| Capability | What it controls |
|---|---|
fs_read | Reading files, listing directories, searching |
fs_write | Writing, editing, deleting files |
filesystem | Shorthand for fs_read + fs_write |
shell | Executing commands |
web_fetch | Fetching URLs |
web_search | Web search |
mcp | MCP server tool calls (pattern: server/tool) |
subagent | Subagent delegation |
skill | Skills activation |
power | Powers activation and tool calls |
diagnostics | Diagnostics tools |
context | Context and steering tools |
all | Every capability (meta) |
builtin | All built-in tools (meta) |
Rules use glob patterns. The syntax differs by capability type:
Filesystem patterns (fs_read, fs_write):
* matches within a single path component** matches across path separators{a,b} brace expansion and [abc] character classes are supported~/temp matches ~/temp/childShell, web, MCP patterns:
* matches any sequence of characters**, ?, and character classes are not supportedrules: # Allow npm commands except npm publish - capability: shell effect: allow match: - "npm *" exclude: - "npm publish*" # Deny reads to secrets at any depth - capability: fs_read effect: deny match: - "**/.env" - "**/.env.*" - "secrets/**" - "**/*.pem" # Allow a specific MCP server - capability: mcp effect: allow match: - "my-server/*"
Shell commands are parsed before pattern matching. Compound commands (using ;, &&, ||, |) are split and each sub-command is evaluated independently. This prevents a rule for npm test * from accidentally matching npm test ; curl attacker.com.
For more on how permissions work with hooks and custom agents, see those pages.
Permissions