Skip to content

plan: plan agent cannot write to its own plan dir when the session cwd contains it #59838

Closed as duplicate

Description

@Lomare

Summary

The built-in plan agent (Plan mode) cannot write to its own plan directory (~/.opencode/plan/) when the session's working directory is an ancestor of that directory — the common case, e.g. starting a session from ~. The write is hard-denied (no prompt) with a misleading error — "Cannot use write to modify files outside the Plan directory" — even though the target file is inside the plan directory. Root cause is a resource-format mismatch: the plan plugin's allow rule uses an absolute path, but the permission check passes a location-relative resource for files inside the session's cwd.

Environment

  • opencode version: 2.1.4
  • OS: Linux 6.18.55-2-cachyos-lts (x86_64)
  • Terminal: TERM=xterm-256color, COLORTERM=truecolor
  • Shell: /bin/bash
  • Install/channel: latest
  • Active plugins: * (all plugins in ~/.opencode/plugins/)

Reproduction

  1. Start a session on the plan agent from a working directory that is an ancestor of ~/.opencode/plan (e.g. cd ~).
  2. Have the plan agent write a file into ~/.opencode/plan/ (e.g. via the write tool).
  3. Observe the result.

Contrast: starting the same session from a cwd that does not contain the plan dir (e.g. a project subdirectory) makes the write succeed — the plan dir is then "external" to the location and the resource is absolute.

Expected Behavior

The plan agent can create/modify files inside ~/.opencode/plan/ (its designated plan directory), per the built-in opencode.plan plugin's allow edit <home>/.opencode/plan/* rule.

Actual Behavior

The write is hard-denied (no prompt) with:

Cannot use write to modify files outside the Plan directory: <home>/.opencode/plan

even though the target file is inside that directory.

Additional Context

Root cause (from decompiling the built-in opencode.plan plugin in the opencode binary, v2.1.4):

  1. The plugin pushes three rules onto the plan agent:

    • allow question *
    • deny edit *
    • allow edit <home>/.opencode/plan/* (absolute path)
  2. The permission resolver is last-match-wins (findLast over the matching rules), and a single deny match short-circuits to deny.

  3. The write/edit/patch tools check action: "edit" with resources: [q.resource], where q.resource comes from FileAccess.resolve:

    • file inside the session's location/project dir → resource is relative to the cwd (e.g. .opencode/plan/foo.md);
    • file outside → resource is the absolute path.
  4. So when cwd is an ancestor of the plan dir (e.g. ~), the resource is .opencode/plan/foo.md (relative). The plugin's allow rule <home>/.opencode/plan/* (absolute) does not match it. Only deny edit * matches → last-match-wins → deny. The plan-dir allow rule is effectively dead code for the common case.

  5. The plugin's tool.hook("execute.after") then rewrites any Permission.BlockedError from a plan-agent edit/write/patch to "Cannot use <tool> to modify files outside the Plan directory" — misleading here because the file is inside the plan dir.

Workaround (user-side): add a relative-path allow rule to the plan agent in opencode.json:

{ "action": "edit", "resource": ".opencode/plan/*", "effect": "allow" }

This lands after the plugin's deny edit * in the merged rule list and wins under last-match-wins. (Alternatively, write plan files via a shell heredoc, since shell is ask.)

Suggested fix (upstream): make the plan plugin's allow rule match the resource format the resolver actually produces — e.g. also allow the location-relative form (.opencode/plan/*), or have FileAccess.resolve pass an absolute resource for permission checks. And make the execute.after error message accurate (only claim "outside the Plan directory" when the target actually is outside it).

Activity

  1. opencodejr commented on Oct 28, 2026

    @opencodejr
    Contributor

    Thanks for the detailed root-cause analysis and the workaround. I think this is a duplicate of #46358, which is open and tracking the same problem: the plan agent's absolute allow rule for ~/.opencode/plan/* never matches the cwd-relative path the file tools check when the session runs from an ancestor directory such as ~. So deny edit * wins, and you get the misleading "outside the Plan directory" error.

    Possible duplicates and related issues, ordered from most to least likely:

    Your point about the error message may be worth adding on #46358, since the linked PR leaves the message as it is. Your relative-path workaround ({ "action": "edit", "resource": ".opencode/plan/*", "effect": "allow" }) would also be useful to others there.

    The bot will close this issue as a duplicate in 1 day unless you reply explaining how your problem is different.

  2. opencodejr commented on Oct 29, 2026

    @opencodejr
    Contributor

    We haven't heard back, so I'm closing this as a duplicate of #46358. That issue tracks the same bug: the plan agent's absolute allow rule for ~/.opencode/plan/* doesn't match the cwd-relative path that is checked when the session runs from an ancestor directory like ~. The open PR #53365 proposes a fix for it.

    Please subscribe to #46358 for updates. Your note about the misleading "outside the Plan directory" message, and your relative-path workaround, would be useful to add there. If your problem turns out to be different, reply here and we can reopen this. Thanks again for the thorough analysis!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions