anomalyco / anomalyco/opencode
`write` permission rules are silently ignored — write.ts asks under `edit`
@nexxeln is already working on this.
Since Aug 2, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
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
writedeny 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 @ 1882c33827
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.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 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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.