Description
A write: block in opencode.json or in agent frontmatter parses without error, loads into the ruleset, and is never consulted by anything.
write is not a declared permission key. packages/core/src/v1/config/permission.ts:18-34 declares:
read · edit · glob · grep · list · bash · task · external_directory
todowrite · question · webfetch · websearch · lsp · doom_loop · skill
The struct has a Schema.Record(Schema.String, Rule) rest element, so any unknown key parses cleanly and is carried into the ruleset by fromConfig. Nothing then asks under it.
The write tool asks under edit:
// packages/opencode/src/tool/write.ts:55-57
yield* ctx.ask({
permission: "edit",
patterns: [path.relative(instance.worktree, filepath)],
There is no permission: "write" anywhere in src.
The practical effect is that a config like this does not do what it reads as:
{
"permission": {
"edit": { "*": "allow" },
"write": { "*.env": "deny" }
}
}
The write block is inert; writes are governed entirely by the edit rules. An operator who tightens write and leaves edit open has not tightened anything.
This also means unknown keys generally are silent no-ops — a typo like edt: or bahs: parses, loads, and does nothing, with no warning at any level.
Steps to reproduce
- Configure
"permission": { "edit": { "*": "allow" }, "write": { "*": "deny" } }.
- Have the agent write a file.
- The write is allowed. The
write deny never participates.
- Nothing is logged about the unused key.
The evaluated log line at permission/index.ts:74 confirms it directly: writes appear as permission=edit, and permission=write never appears at all. An independent deployment checked 125,800 evaluated lines and found zero permission=write entries.
OpenCode version
dev @ 1882c33
Expected
One of:
- Reject unknown permission keys at parse time. Preferred — it makes this class of mistake loud, and it catches typos as a side effect. It is a breaking change for any config carrying an undeclared key, so it wants a release note.
- Make
write.ts ask under permission: "write" and document the key. Existing write: blocks become live as written, which is what their authors intended, but anyone relying on edit rules covering writes would see a behaviour change.
Either way write should appear in docs/permissions.mdx — as a supported key, or in the list of keys that do not exist.
Notes
Found while working on #30551 / #40149 (absolute permission patterns not matching outside the worktree). Filed separately because the fixes are unrelated: that one changes which path is matched, this one changes which key is consulted.
Two deployments were carrying write: blocks written in good faith that had never done anything.
Description
A
write:block inopencode.jsonor in agent frontmatter parses without error, loads into the ruleset, and is never consulted by anything.writeis not a declared permission key.packages/core/src/v1/config/permission.ts:18-34declares:The struct has a
Schema.Record(Schema.String, Rule)rest element, so any unknown key parses cleanly and is carried into the ruleset byfromConfig. Nothing then asks under it.The write tool asks under
edit:There is no
permission: "write"anywhere insrc.The practical effect is that a config like this does not do what it reads as:
{ "permission": { "edit": { "*": "allow" }, "write": { "*.env": "deny" } } }The
writeblock is inert; writes are governed entirely by theeditrules. An operator who tightenswriteand leaveseditopen has not tightened anything.This also means unknown keys generally are silent no-ops — a typo like
edt:orbahs:parses, loads, and does nothing, with no warning at any level.Steps to reproduce
"permission": { "edit": { "*": "allow" }, "write": { "*": "deny" } }.writedeny never participates.The
evaluatedlog line atpermission/index.ts:74confirms it directly: writes appear aspermission=edit, andpermission=writenever appears at all. An independent deployment checked 125,800 evaluated lines and found zeropermission=writeentries.OpenCode version
dev @ 1882c33
Expected
One of:
write.tsask underpermission: "write"and document the key. Existingwrite:blocks become live as written, which is what their authors intended, but anyone relying oneditrules covering writes would see a behaviour change.Either way
writeshould appear indocs/permissions.mdx— as a supported key, or in the list of keys that do not exist.Notes
Found while working on #30551 / #40149 (absolute permission patterns not matching outside the worktree). Filed separately because the fixes are unrelated: that one changes which path is matched, this one changes which key is consulted.
Two deployments were carrying
write:blocks written in good faith that had never done anything.