You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Tools registered by external plugins execute without applying their configured permission action. The same bypass occurs when a plugin tool is called through Code Mode.
A tool with options.permission: "demo_create_work_item" executes immediately even when that action is configured to ask. It should prompt before calling the executor.
On V2 this is currently expected behavior, though I get why it's surprising.
The reason we don't auto prompt: for an arbitrary plugin tool, opencode has no idea which inputs matter for a permission decision. Built-in tools know this. shell asks about the command, edit asks about the file path, and "always allow" saves that pattern. For a plugin tool we could prompt on every call, but then "always allow" gets messy. Which parameters are you saving approval for? All of them? Just the tool name? There isn't a good generic answer, so right now the tool itself decides what to ask about.
So for now, call ctx.permission.assert inside your tool's execute. It's available from v2.0.29 and goes through the same rules, saved approvals and prompt as built-in tools, for direct calls and Code Mode:
Use resources (and save) to say what's being approved, for example a project or environment name, so "always allow" saves something meaningful. Docs are in the plugin guide under Permissions.
We'll probably change this so plugin tools get sensible permission checks by default, so I'm leaving this open for now.
Thanks for the detailed report! What you're asking for is that a plugin tool's declared options.permission be checked automatically when the tool runs, so an ask rule prompts before the tool's execute is called, both for direct calls and through Code Mode.
As mentioned above, this is how v2 currently works by design. options.permission only decides whether a tool is hidden when its action is denied outright. When the tool runs, the tool itself has to request permission. Until that changes, calling ctx.permission.assert at the start of your tool's execute (v2.0.29+) gives you the normal rules, saved approvals and the approval prompt, for direct calls and Code Mode:
On "sensible permission checks by default": what if a plugin tool that never calls ctx.permission.assert gets a tool-wide check against its options.permission key, but without "always allow"? ask would prompt once per call, deny would block, and nothing would persist, so there's no question of which parameters to save.
Tools that do their own assert would declare that, e.g. options.experimental.permission: { self: true }, and skip the host check, so there's no double prompt.
I already have this working on a branch, if the direction sounds right.
Activity
github-actions commentedon Sep 22, 2026
This issue might be a duplicate of existing issues. Please check:
askpermission for nested plugin tools — identical symptom (plugin tool withoptions.permissionexecutes without prompting, Code Mode explicitly called out)permission.askplugin hook is never triggered — same root cause, hook never firespermission.askplugin hook is defined but not triggered #7006:permission.askplugin hook is defined but not triggered — long-standing report of the same missing hook triggerpermission.evaluateask verdicts are ignored — related: plugin verdicts not honoreddocs: explain deny and ask rules for computer_use in OpenCode 2.0.16
fix: follow the Codex approval policy and drop the approvals option (#3)
soar commentedon Oct 11, 2026
This is still an issue and needs to be fixed, verified on v2.0.25
rekram1-node commentedon Oct 23, 2026
On V2 this is currently expected behavior, though I get why it's surprising.
The reason we don't auto prompt: for an arbitrary plugin tool, opencode has no idea which inputs matter for a permission decision. Built-in tools know this.
shellasks about the command,editasks about the file path, and "always allow" saves that pattern. For a plugin tool we could prompt on every call, but then "always allow" gets messy. Which parameters are you saving approval for? All of them? Just the tool name? There isn't a good generic answer, so right now the tool itself decides what to ask about.So for now, call
ctx.permission.assertinside your tool'sexecute. It's available from v2.0.29 and goes through the same rules, saved approvals and prompt as built-in tools, for direct calls and Code Mode:Use
resources(andsave) to say what's being approved, for example a project or environment name, so "always allow" saves something meaningful. Docs are in the plugin guide under Permissions.We'll probably change this so plugin tools get sensible permission checks by default, so I'm leaving this open for now.
opencodejr commentedon Oct 28, 2026
Thanks for the detailed report! What you're asking for is that a plugin tool's declared
options.permissionbe checked automatically when the tool runs, so anaskrule prompts before the tool'sexecuteis called, both for direct calls and through Code Mode.As mentioned above, this is how v2 currently works by design.
options.permissiononly decides whether a tool is hidden when its action is denied outright. When the tool runs, the tool itself has to request permission. Until that changes, callingctx.permission.assertat the start of your tool'sexecute(v2.0.29+) gives you the normal rules, saved approvals and the approval prompt, for direct calls and Code Mode:We're keeping this issue open as the request for plugin tools to get permission checks by default, and maintainers will consider it.
Related:
ctx.permission.assertfor plugins; enforcingoptions.permissionautomatically was left as a follow-upaskrules for MCP tools being treated asallow(a similar gap, for MCP tools)Project579 commentedon Nov 7, 2026
On "sensible permission checks by default": what if a plugin tool that never calls
ctx.permission.assertgets a tool-wide check against itsoptions.permissionkey, but without "always allow"?askwould prompt once per call,denywould block, and nothing would persist, so there's no question of which parameters to save.Tools that do their own
assertwould declare that, e.g.options.experimental.permission: { self: true }, and skip the host check, so there's no double prompt.I already have this working on a branch, if the direction sounds right.