OpenCode Permission Configuration
OpenCode's permission system controls which operations can run automatically, which require your manual approval, and which are directly blocked. Properly configuring permissions lets AI complete tasks efficiently while preventing accidental operations that could damage code or leak sensitive files.
Starting from v1.1.1, the old
toolsboolean configuration has been deprecated and merged intopermission. The old configuration is still supported for backward compatibility, but it is recommended to migrate to the newpermissionsyntax.
Three Permission Actions
Each permission rule ultimately resolves to one of the following three actions:
| Action | Effect | Applicable scenarios |
|---|---|---|
"allow" |
Runs automatically without approval | Low-risk, high-frequency operations, such as reading files and running tests |
"ask" |
Shows an approval prompt for you to decide whether to allow | Operations with some risk, such as writing files and executing scripts |
"deny" |
Blocked directly, neither executed nor prompted | Dangerous operations that are explicitly disallowed, such as deleting files and pushing code |
Basic Configuration
Permission configuration is written under the repository root directory (or user configuration directory) in theopencode.jsonfile, usingpermissionfield to configure.
1. Set all permissions globally
The simplest way: use a single string to set permissions for all operations at once. Suitable for quick start or temporary debugging:
Example
"$schema": "https://opencode.ai/config.json",
"permission": "allow" // All operations run automatically without any prompts (suitable for local development, when fully trusting AI)
}
2. Configure by tool name
Using object syntax, you can specify permissions for different tools separately."*"is a wildcard, meaning it matches all operations, usually used as the fallback default value:
Example
"$schema": "https://opencode.ai/config.json",
"permission": {
"*": "ask", // Fallback rule: all tools not individually configured default to showing a prompt
"bash": "allow", // bash (executing Shell commands): allow directly, no prompt
"edit": "deny" // edit (modifying files): block directly
}
}
Fine-grained rules (object syntax)
For most permissions, in addition to setting a unified action, you can also useobject syntaxto apply different rules based on the tool's specific input. For example, forbashtools, you can distinguish which commands are allowed, which require approval, and which are directly rejected:
Example
"$schema": "https://opencode.ai/config.json",
"permission": {
"bash": {
"*": "ask", // Fallback: all bash commands require approval by default
"git *": "allow", // Commands starting with git (e.g., git status, git log) are allowed directly
"npm *": "allow", // Commands starting with npm (e.g., npm install, npm run build) are allowed directly
"grep *": "allow", // grep search commands are allowed directly
"rm *": "deny" // rm delete commands are directly blocked (to prevent accidental file deletion)
},
"edit": {
"*": "deny", // Block all file edits by default
"packages/web/src/content/docs/*.mdx": "allow" // Only allow editing .mdx files under the docs directory
}
}
}
Rule matching order: the last matched rule takes precedence.It is recommended to put the wildcard
"*"rule at the top as the default value, and place more specific rules after it to override it. This way, the more specific a rule is, the higher its priority, making the logic clear and less error-prone.
Wildcard rules
Permission patterns support simple wildcard matching, with the following rules:
| Wildcard | Meaning | Example |
|---|---|---|
* |
Matches zero or more arbitrary characters (not crossing directories) | git *Matchesgit status、git log --onelinewait |
** |
Matches any path across directories | ~/projects/**Matches all files and subdirectories under projects |
? |
Exactly matches one arbitrary character | file?.txtMatchesfile1.txt、fileA.txt |
| Other characters | Matches exactly by literal value | git statusOnly matchesgit status, does not match variants with parameters |
Note:For commands with parameters, be sure to append at the end
*. For example"grep *"can matchgrep pattern file.txt, while writing alone"grep"only matches bare commands without any parameters, which will almost never be matched in actual execution.
Home directory expansion
At the beginning of a pattern, you can use~or$HOMEto refer to the current user's home directory, and OpenCode will automatically expand it to the full path:
Example
"~/projects/*"
"$HOME/projects/*"
"/Users/username/projects/*" // Writing the absolute path directly also works, but is not recommended (not portable enough)
External directory permissions (external_directory)
By default, OpenCode only allows tools to accessthe working directory at startupand its subdirectories. If you need to access paths outside the project directory (e.g., another project or a shared configuration directory), you must useexternal_directoryexplicit authorization.
Home directory expansion (
~/...) is only a pathshorthand notation, and does not automatically authorize access to that path. Paths outside the working directory must still go throughexternal_directoryto be allowed.
1. Allow access to external directories
Example
"$schema": "https://opencode.ai/config.json",
"permission": {
"external_directory": {
"~/projects/personal/**": "allow" // Allow access to all files and subdirectories under ~/projects/personal/
// ** matches subpaths at any level
}
}
}
2. Allow reading but forbid editing
Byexternal_directoryAuthorized directories inherit the default permissions of the current workspace. Sincereaddefaults to"allow", after authorization, files under that directory can be read. If you need to further restrict a certain operation (e.g., allow reading but forbid editing), you can add extra rules:
Example
"$schema": "https://opencode.ai/config.json",
"permission": {
"external_directory": {
"~/projects/personal/**": "allow" // Step 1: Grant access to this external directory
},
"edit": {
"~/projects/personal/**": "deny" // Step 2: Add an overriding rule on this directory, allowing reading but forbidding editing
}
}
}
All available permission items
OpenCode's permissions use tool names as keys, covering all types including file operations, command execution, and network access:
| Permission item | Controlled operation | Pattern matching content | Default value |
|---|---|---|---|
read |
Read file contents | File path (e.g.,src/index.js) |
allow(.envfiles excluded) |
edit |
All file modifications, covering edit, write, patch, and multiedit | File path | allow |
glob |
File glob search (e.g., find all.tsfiles) |
Glob pattern (e.g.,**/*.ts) |
allow |
grep |
Search for text in file contents | Regular expression pattern | allow |
list |
List files in a directory | Directory path | allow |
bash |
Run shell command | Parsed full command (e.g.,git status --porcelain) |
allow |
task |
Start sub-agent | Sub-agent type name | allow |
skill |
Load skill | Skill name | allow |
lsp |
Run LSP language service query | Fine-grained configuration is currently not supported | allow |
webfetch |
Fetch network URL content | Full URL (e.g.,https://example.com/api) |
allow |
websearch |
Web search | Search query string | allow |
codesearch |
Code search | Search query string | allow |
external_directory |
Access paths outside the working directory | External directory path | ask |
doom_loop |
Triggered when the same tool is called 3 times repeatedly with the same input (prevents the AI from getting stuck in a loop) | — | ask |
Default permission description
If you have not configured any permissions, OpenCode uses the following built-in defaults:
- Most tool permissions default to
"allow", meaning they run automatically without prompting doom_loopandexternal_directoryDefaults to"ask", requiring manual approvalreadReading all files is allowed by default, but.envrelated files have built-in protection:
Example
{
"permission": {
"read": {
"*": "allow", // Allow reading all files by default
"*.env": "deny", // Block reading .env files (prevent leaking database passwords, API keys, etc.)
"*.env.*": "deny", // Block reading variants such as .env.local, .env.production
"*.env.example": "allow" // Allow reading .env.example (sample file, no real secrets)
}
}
}
Three options in the approval prompt
When an operation's permission is"ask", OpenCode pops up an approval prompt offering the following three choices:
| Option | Effect | Applicable scenario |
|---|---|---|
| once (this time only) | Only approve this request; the same operation next time will still prompt | Temporarily allow an operation without permanently enabling it |
| always (always allow) | Add the operation's matching pattern to the whitelist; no more prompts for the rest of the current session | Confirm that a type of operation is safe and want it to pass automatically in this session |
| reject (refuse) | Reject this request; the operation will not be executed | The operation appears risky and you explicitly do not want it executed |
Selectingalwaysafter, OpenCode will have the tool automatically provide a suggested whitelist pattern (e.g., after approvinggit status, it will usually addgit status*to the whitelist).The whitelist is only valid for the current session and will be reset after restarting OpenCode.
Configure permissions separately for agents
If your workflow uses multiple agents, you can override the permission configuration for each agent individually. Agent permissions are merged with the global configuration, andagent rules take priority over global rules。
1. Configure agent permissions in opencode.json
Example
"$schema": "https://opencode.ai/config.json",
"permission": {
// Global permissions: git operations allowed, but commit and push forbidden
"bash": {
"*": "ask",
"git *": "allow",
"git commit *": "deny",
"git push *": "deny",
"grep *": "allow"
}
},
"agent": {
"build": { // Agent named build
"permission": {
"bash": {
"*": "ask",
"git *": "allow",
"git commit *": "ask", // Overrides global: build agent allows commit, but requires approval
"git push *": "deny", // Inherits global: push still forbidden
"grep *": "allow"
}
}
}
}
}
2. Configure agent permissions in Markdown files
Agents can also be configured via Markdown files, with permissions written in the YAML Front Matter at the top of the file (---the part in between):
Example
---
description: Code review agent (only analyzes code, makes no changes)
mode: subagent
permission:
edit: deny # Forbid all file editing
bash: ask # bash commands require approval
webfetch: deny # Forbid access to external URLs
---
Only analyze code and suggest changes.
# Below is the agent's system prompt, describing the agent's responsibilities and behavioral norms
Practical configuration examples
Example 1: Conservative mode (all operations require approval)
Suitable for those new to OpenCode or when working on important projects; all operations require manual confirmation:
Example
"$schema": "https://opencode.ai/config.json",
"permission": {
"*": "ask" // All operations of all tools trigger approval prompts
}
}
Example 2: Common development configuration (read operations allowed, write operations require approval)
Suitable for daily development: allows the AI to freely read and search code, but requires confirmation when modifying files and executing commands:
Example
"$schema": "https://opencode.ai/config.json",
"permission": {
"*": "ask", // Fallback: tools not individually configured require approval by default
"read": "allow", // Read files: allow directly
"glob": "allow", // File glob search: allow directly
"grep": "allow", // Content search: allow directly
"list": "allow", // List directories: allow directly
"bash": {
"*": "ask", // bash commands require approval by default
"git status *": "allow", // View git status: allow
"git log *": "allow", // View git log: allow
"git diff *": "allow", // View git diff: allow
"npm run *": "allow", // Run npm scripts: allow
"npm test *": "allow", // Run tests: allow
"rm *": "deny" // Delete files: block directly
}
}
}
Example 3: Allow access to multiple project directories
When the AI needs to work across multiple project directories, grant access to external directories:
Example
"$schema": "https://opencode.ai/config.json",
"permission": {
"external_directory": {
"~/projects/personal/**": "allow", // Allow access to personal project directories
"~/projects/work/**": "allow", // Allow access to work project directories
"~/dotfiles/**": "allow" // Allow access to the dotfiles directory
},
"edit": {
"~/dotfiles/**": "deny" // Even if access to dotfiles is allowed, editing is forbidden (read-only)
}
}
}