{ "$id": "https://raw.githubusercontent.com/Mearman/agent-permissions/main/agent-permissions.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "$schema": { "type": "string", "description": "JSON Schema URI for editor validation and autocomplete." }, "defaultMode": { "type": "string", "enum": [ "standard", "autonomous", "restricted", "readonly", "plan", "dontAsk", "acceptEdits", "bypassPermissions", "default", "auto" ], "description": "Default permission mode. Agent Permission Policy modes: standard, autonomous, restricted, readonly. Claude Code compatible modes: plan, dontAsk, acceptEdits, bypassPermissions, default.", "default": "standard" }, "activeProfile": { "type": "string", "description": "Name of the active profile from `profiles`. If unset, use the top-level permission tiers directly." }, "permissions": { "type": "object", "properties": { "allow": { "type": "array", "items": { "type": "string" }, "description": "Tools auto-approved without prompting. Evaluated after deny rules.", "examples": [ "Bash(git status)", "Bash(npm run test:*)", "Read", "Grep" ] }, "deny": { "type": "array", "items": { "type": "string" }, "description": "Tools always denied — short-circuits before allow and ask. A deny cannot be overridden by an allow in any other source.", "examples": [ "Bash(sudo:*)", "Bash(rm -rf /)", "Read(./.env)" ] }, "ask": { "type": "array", "items": { "type": "string" }, "description": "Tools that always prompt, even in autonomous mode. Evaluated after deny but before allow.", "examples": [ "Bash(git push:*)", "Bash(npm publish:*)" ] }, "additionalDirectories": { "type": "array", "items": { "type": "string" }, "description": "Directories beyond project root that agents may access.", "examples": [ "../shared-libs/", "/tmp/build-cache" ] }, "defaultMode": { "type": "string", "enum": [ "standard", "autonomous", "restricted", "readonly", "plan", "dontAsk", "acceptEdits", "bypassPermissions", "default", "auto" ], "description": "Default permission mode. Accepted here for Claude Code compatibility, or at the top level for the canonical placement.", "default": "standard" } }, "additionalProperties": false, "description": "Tool permission rules — evaluated in deny → ask → allow order." }, "rules": { "type": "array", "items": { "type": "object", "properties": { "tool": { "type": "string", "description": "Canonical tool name.", "examples": [ "Bash", "Read", "Write", "Edit", "Grep", "WebFetch", "Agent", "mcp__github__create_issue" ] }, "pattern": { "description": "Pattern to match against tool input. When absent, matches any input.", "examples": [ "npm run *", "./config/**", "git push --force:*" ], "type": "string" }, "tier": { "type": "string", "enum": [ "allow", "deny", "ask" ], "description": "Permission tier to apply when this rule matches." }, "when": { "description": "Optional conditions. All must match for the rule to apply (AND logic).", "type": "object", "properties": { "cwd": { "type": "string", "description": "Working directory pattern (glob)." }, "branch": { "type": "string", "description": "Git branch name pattern (glob)." } }, "additionalProperties": false } }, "required": [ "tool", "tier" ], "additionalProperties": false, "description": "Permission rule. Evaluated deny-first: all deny rules, then ask, then allow." }, "description": "Permission rules. Evaluated deny-first: all deny rules checked, then ask, then allow. Falls back to defaultMode when no rule matches." }, "profiles": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": { "type": "object", "properties": { "allow": { "type": "array", "items": { "type": "string" }, "description": "Tools auto-approved without prompting. Evaluated after deny rules.", "examples": [ "Bash(git status)", "Bash(npm run test:*)", "Read", "Grep" ] }, "deny": { "type": "array", "items": { "type": "string" }, "description": "Tools always denied — short-circuits before allow and ask. A deny cannot be overridden by an allow in any other source.", "examples": [ "Bash(sudo:*)", "Bash(rm -rf /)", "Read(./.env)" ] }, "ask": { "type": "array", "items": { "type": "string" }, "description": "Tools that always prompt, even in autonomous mode. Evaluated after deny but before allow.", "examples": [ "Bash(git push:*)", "Bash(npm publish:*)" ] }, "additionalDirectories": { "type": "array", "items": { "type": "string" }, "description": "Directories beyond project root that agents may access.", "examples": [ "../shared-libs/", "/tmp/build-cache" ] }, "defaultMode": { "type": "string", "enum": [ "standard", "autonomous", "restricted", "readonly", "plan", "dontAsk", "acceptEdits", "bypassPermissions", "default", "auto" ], "description": "Default permission mode. Accepted here for Claude Code compatibility, or at the top level for the canonical placement.", "default": "standard" } }, "additionalProperties": false }, "description": "Named permission profiles.", "examples": [ { "strict": { "deny": [ "Write", "Edit", "Bash" ], "allow": [ "Read", "Grep" ] }, "relaxed": { "allow": [ "Read", "Write", "Edit", "Bash(git:*)", "Bash(npm:*)" ] } } ] }, "delegation": { "type": "object", "properties": { "maxDepth": { "type": "integer", "minimum": 0, "maximum": 9007199254740991, "description": "Maximum depth of agent nesting. 0 = no subagents allowed.", "default": 2 }, "nonDelegable": { "type": "array", "items": { "type": "string" }, "description": "Tools that cannot be delegated to subagents. Uses the same rule syntax.", "examples": [ "Bash(sudo:*)", "Write(./.agents/**)" ] }, "bubbleUp": { "type": "boolean", "description": "Whether subagents can request elevated permissions from their parent.", "default": true }, "agents": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": { "type": "object", "properties": { "allow": { "type": "array", "items": { "type": "string" }, "description": "Tools auto-approved without prompting. Evaluated after deny rules.", "examples": [ "Bash(git status)", "Bash(npm run test:*)", "Read", "Grep" ] }, "deny": { "type": "array", "items": { "type": "string" }, "description": "Tools always denied — short-circuits before allow and ask. A deny cannot be overridden by an allow in any other source.", "examples": [ "Bash(sudo:*)", "Bash(rm -rf /)", "Read(./.env)" ] }, "ask": { "type": "array", "items": { "type": "string" }, "description": "Tools that always prompt, even in autonomous mode. Evaluated after deny but before allow.", "examples": [ "Bash(git push:*)", "Bash(npm publish:*)" ] }, "additionalDirectories": { "type": "array", "items": { "type": "string" }, "description": "Directories beyond project root that agents may access.", "examples": [ "../shared-libs/", "/tmp/build-cache" ] }, "defaultMode": { "type": "string", "enum": [ "standard", "autonomous", "restricted", "readonly", "plan", "dontAsk", "acceptEdits", "bypassPermissions", "default", "auto" ], "description": "Default permission mode. Accepted here for Claude Code compatibility, or at the top level for the canonical placement.", "default": "standard" } }, "additionalProperties": false }, "description": "Per-agent permission overrides. Keys are agent names or glob patterns. Values replace (not merge with) the parent policy for that agent.", "examples": [ { "review": { "deny": [ "Write", "Edit", "Bash" ], "allow": [ "Read", "Grep" ] }, "docs": { "allow": [ "Read", "Write(./docs/**)", "Bash(mdbook build:*)" ] } } ] } }, "additionalProperties": false, "description": "Agent delegation controls — what subagents may do." }, "sandbox": { "type": "object", "properties": { "mode": { "type": "string", "enum": [ "readonly", "workspace-write", "full-access" ], "description": "Sandbox isolation mode.", "default": "workspace-write" }, "writableRoots": { "type": "array", "items": { "type": "string" }, "description": "Additional paths the agent may write to (beyond project root). Only meaningful when mode is `workspace-write`.", "examples": [ "/tmp/build-cache", "../shared-libs" ] }, "networkAccess": { "type": "boolean", "description": "Whether the agent may make network requests from within the sandbox. When false, network access is blocked at the OS level.", "default": true } }, "additionalProperties": false, "description": "OS-level sandbox configuration." }, "network": { "type": "object", "properties": { "enabled": { "type": "boolean", "description": "Whether network access is permitted at all. When false, WebFetch and WebSearch are denied regardless of allow rules.", "default": true }, "domains": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": { "type": "string", "enum": [ "allow", "deny" ] }, "description": "Domain-level allow/deny rules for HTTP(S) requests. Supplements the WebFetch(domain:...) permission rules.", "examples": [ { "api.example.com": "allow", "evil.com": "deny" } ] } }, "additionalProperties": false, "description": "Network access controls." }, "env": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": { "type": "string" }, "description": "Environment variables injected into all agent sessions.", "examples": [ { "NODE_ENV": "development", "DISABLE_TELEMETRY": "1" } ] }, "with": { "type": "array", "items": { "type": "string", "enum": [ "claude-code", "codex", "kiro", "opencode", "crush" ] }, "description": "Agent configs to include when loading. Only these native configs are read (plus canonical). Mutually exclusive with `without`.", "examples": [ [ "claude-code", "opencode" ] ] }, "without": { "type": "array", "items": { "type": "string", "enum": [ "claude-code", "codex", "kiro", "opencode", "crush" ] }, "description": "Agent configs to exclude when loading. Mutually exclusive with `with`.", "examples": [ [ "codex" ] ] }, "up": { "anyOf": [ { "type": "string", "enum": [ "all" ] }, { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } ], "description": "How far to walk up the directory tree when loading configs. 'all' walks to the filesystem root. A number limits parent directories (0 = cwd only).", "default": "all", "examples": [ "all", 0, 3, 5 ] }, "sync": { "type": "object", "properties": { "mode": { "anyOf": [ { "type": "string", "enum": [ "sync", "watch" ] }, { "type": "boolean", "const": false } ], "description": "Sync mode. 'sync' = one-shot at startup. 'watch' = continuous via fs.watch. false = disabled.", "default": false }, "backup": { "type": "boolean", "description": "Write .bak files before overwriting.", "default": false } }, "additionalProperties": false, "description": "Sync configuration for the MCP server and CLI sync command." } }, "additionalProperties": false, "title": "Agent Permission Policy", "description": "Cross-agent permission policy for AI coding agents. Defines what tools agents may use, under what conditions, and how subagents are constrained. The `with`/`without`/`up` fields control which native agent configs are discovered and merged during walk-up loading. Placed at .agents/permissions.json (team, committed) or .agents/permissions.local.json (personal, gitignored)." }