permissions.mdx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. ---
  2. title: "Permissions"
  3. description: ""
  4. ---
  5. Permissions control whether an agent may perform an action on a resource. V2
  6. configuration uses the `permissions` field and an ordered array of rules.
  7. <Callout type="warning">
  8. The V1 object syntax uses different field and action names. Do not use `permission`, `bash`, or `task` in V2
  9. configuration; use `permissions`, `shell`, and `subagent`.
  10. </Callout>
  11. ## Rule schema
  12. Each rule has three required string fields:
  13. ```jsonc
  14. {
  15. "$schema": "https://opencode.ai/config.json",
  16. "permissions": [
  17. { "action": "*", "resource": "*", "effect": "ask" },
  18. { "action": "read", "resource": "*", "effect": "allow" },
  19. { "action": "read", "resource": "*.env", "effect": "deny" },
  20. { "action": "shell", "resource": "git status *", "effect": "allow" },
  21. { "action": "shell", "resource": "git push *", "effect": "deny" },
  22. { "action": "edit", "resource": "packages/docs/*.mdx", "effect": "allow" },
  23. ],
  24. }
  25. ```
  26. - `action` matches a tool permission action.
  27. - `resource` matches the value the tool is trying to use, such as a path,
  28. command, URL, query, or agent ID.
  29. - `effect` is `"allow"`, `"deny"`, or `"ask"`.
  30. `allow` proceeds without prompting, `deny` blocks the operation, and `ask`
  31. waits for a user decision. If no rule matches, the result is `ask`.
  32. ## Matching and order
  33. Both `action` and `resource` support simple wildcards:
  34. - `*` matches zero or more characters, including `/`.
  35. - `?` matches exactly one character.
  36. - All other characters are literal.
  37. Matches cover the entire value. Slashes are normalized, and matching is
  38. case-insensitive on Windows. For shell convenience, a pattern ending in
  39. `" *"` also matches the command without arguments: `"git status *"` matches
  40. both `git status` and `git status --short`.
  41. The **last matching rule wins**. Put broad rules first and exceptions later.
  42. Rules from lower-priority configuration files are loaded first. OpenCode then
  43. appends all global rules before agent-specific rules, so a matching agent rule
  44. overrides a global rule.
  45. Some operations check several resources at once, such as a patch touching
  46. multiple files. OpenCode denies the operation if any resource resolves to
  47. `deny`; otherwise it asks if any resolves to `ask`; otherwise it allows it.
  48. ## Actions and resources
  49. V2 action names are strings, so plugins may introduce additional actions. The
  50. current built-in actions use these resources:
  51. | Action | Resource matched |
  52. | -------------------- | ---------------------------------------------------------------------------------------------------------------- |
  53. | `read` | Location-relative path for an internal file or directory; canonical absolute path for an external target |
  54. | `edit` | Target path for `edit`, `write`, and `patch`; all three tools share this action |
  55. | `glob` | The requested glob pattern |
  56. | `grep` | The requested regular expression, not the search path |
  57. | `shell` | The complete raw shell command string |
  58. | `subagent` | The target agent ID |
  59. | `skill` | The skill ID |
  60. | `question` | `*` |
  61. | `webfetch` | The requested URL |
  62. | `websearch` | The search query |
  63. | `external_directory` | A canonical external directory boundary, normally ending in `/*` |
  64. | `<server>_<tool>` | `*` for an MCP tool; unsupported characters in both names become `_` |
  65. | `execute` | `*`; controls availability of the Code Mode dispatcher, while each nested tool still enforces its own permission |
  66. `doom_loop` and `lsp` are not current V2 Core permission actions.
  67. ## External directories
  68. An external path requires a separate `external_directory` decision before the
  69. tool's own `read` or `edit` decision. This applies to external paths used by
  70. `read`, `edit`, `write`, and `patch`, and to an external `shell` working
  71. directory.
  72. ```jsonc
  73. {
  74. "$schema": "https://opencode.ai/config.json",
  75. "permissions": [
  76. {
  77. "action": "external_directory",
  78. "resource": "~/projects/reference/*",
  79. "effect": "allow",
  80. },
  81. {
  82. "action": "read",
  83. "resource": "~/projects/reference/*",
  84. "effect": "allow",
  85. },
  86. {
  87. "action": "edit",
  88. "resource": "~/projects/reference/*",
  89. "effect": "deny",
  90. },
  91. ],
  92. }
  93. ```
  94. For `external_directory`, `read`, and `edit` resources, a leading `~`, `~/`,
  95. `$HOME`, or `$HOME/` is expanded when configuration loads. Shell resources are
  96. raw command text and are **not** home-expanded.
  97. <Callout type="warning">
  98. `shell` runs with the host user's filesystem, process, and network authority. Its resource is raw text, not a parsed
  99. command. External command arguments produce only best-effort warnings; `external_directory` is enforced for the
  100. working directory, not every path embedded in a command. Prefer a narrow shell allowlist over patterns intended to
  101. identify every dangerous command.
  102. </Callout>
  103. Relative mutation paths cannot escape the active Location, and symlink escapes
  104. from inside it are rejected. Explicit external paths are canonicalized before
  105. matching, so authorize only trusted directory boundaries.
  106. ## Defaults
  107. Every agent, including custom agents, starts with ordered defaults that allow
  108. tools, ask for external directories, ask for `.env` reads, and allow
  109. `.env.example` reads. Shipped agents then add their own policies:
  110. | Agent | Effective default policy |
  111. | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
  112. | `build` | Allows most actions; asks for external directories and `.env` reads; allows questions and entering plan mode; denies exiting plan mode |
  113. | `plan` | Uses the same base, allows questions and exiting plan mode, and denies edits except OpenCode plan files |
  114. | `general` | Uses the base policy but cannot launch another subagent; questions and plan transitions remain denied |
  115. | `explore` | Denies everything except `read`, `glob`, `grep`, `webfetch`, and `websearch`; cannot launch subagents and asks for external directories |
  116. | Hidden maintenance agents | Deny all actions |
  117. The base read rules are ordered as follows:
  118. ```jsonc
  119. [
  120. { "action": "read", "resource": "*", "effect": "allow" },
  121. { "action": "read", "resource": "*.env", "effect": "ask" },
  122. { "action": "read", "resource": "*.env.*", "effect": "ask" },
  123. { "action": "read", "resource": "*.env.example", "effect": "allow" },
  124. ]
  125. ```
  126. OpenCode also permits its managed tool-output, shell-output, temporary, and
  127. global configuration directories. These exceptions apply only to the
  128. external-directory boundary for every agent; the underlying action still uses
  129. its own permission rules. The environment instructions identify the temporary
  130. directory available for work outside the workspace. Later global and
  131. agent-specific rules can override these defaults.
  132. ## Agent overrides
  133. Configure shared policy at the top level and append narrower rules to a named
  134. agent under `agents.<id>.permissions`:
  135. ```jsonc
  136. {
  137. "$schema": "https://opencode.ai/config.json",
  138. "permissions": [
  139. { "action": "shell", "resource": "*", "effect": "ask" },
  140. { "action": "shell", "resource": "git diff *", "effect": "allow" },
  141. { "action": "shell", "resource": "git status *", "effect": "allow" },
  142. ],
  143. "agents": {
  144. "reviewer": {
  145. "description": "Review code without changing it",
  146. "mode": "subagent",
  147. "permissions": [
  148. { "action": "edit", "resource": "*", "effect": "deny" },
  149. { "action": "shell", "resource": "git diff *", "effect": "allow" },
  150. { "action": "shell", "resource": "git status *", "effect": "allow" },
  151. ],
  152. },
  153. },
  154. }
  155. ```
  156. Agent rules do not replace the global array; they are appended after it. A
  157. custom subagent executes with its own permissions, not a permission subset
  158. derived from the parent agent.
  159. ## Approval choices
  160. When an `ask` rule matches, clients can reply with:
  161. - **Allow once** (`once`): approve only the pending request.
  162. - **Allow always** (`always`): approve this request and save the patterns
  163. proposed by the tool for the current project.
  164. - **Reject** (`reject`): reject the request. Rejecting also rejects other
  165. pending permission requests in the same session; clients may attach feedback.
  166. Saved approvals are durable and project-scoped. They are additional `allow`
  167. rules, but they can never override a configured `deny`. The proposed saved
  168. pattern may be broader than the displayed resource: several tools propose `*`,
  169. shell proposes the exact command text, and skills and subagents propose their
  170. IDs. Review the confirmation carefully and remove saved approvals that are no
  171. longer needed.
  172. For non-interactive runs, `opencode2 run --auto` replies `once` to permission
  173. requests. It does not save approvals, and explicit `deny` rules remain enforced.
  174. Without `--auto`, a non-interactive run rejects permission requests.