Repository navigation
Description
- I have searched existing issues and confirmed this is not a duplicate
Problem
OpenCode currently has two related but separate symlink issues:
- Symlinked/junction directories need to be visible as directories in pickers and file listing.
- Symlinks inside the project that point outside the project need a safe user-consent path.
The first problem is being discussed in #28526 / #28532. This issue is for the second problem.
A common workflow is to link external project context into a repo, for example:
ln -s ~/Obsidian/projects/my-app ./notesThe desired behavior is that OpenCode can read/write ./notes only after the user explicitly approves access to the resolved external target. Without that consent, following the symlink would be a symlink escape vulnerability: a repository could contain a link to /, ~/.ssh, or another sensitive directory.
Proposed behavior
When OpenCode encounters a symlink or junction inside the project whose resolved target is outside the active project/worktree:
- Detect that the canonical target escapes the project boundary.
- Prompt with the existing
external_directorypermission instead of silently treating the path as internal. - Show both the link path and target path in the prompt, for example:
Permission required
Access external directory ~/Obsidian/projects/my-app
Link: ./notes
Target: ~/Obsidian/projects/my-app
Pattern: ~/Obsidian/projects/my-app/**
Allow oncepermits only the current operation.Allow alwayspermits matching operations until OpenCode restarts, consistent with current permission behavior.- Persistent approval can use existing config:
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"external_directory": {
"~/Obsidian/projects/my-app/**": "allow"
}
}
}- Tool-specific permissions still apply. For read-only external symlinks:
{
"permission": {
"external_directory": {
"~/Obsidian/projects/my-app/**": "allow"
},
"edit": {
"~/Obsidian/projects/my-app/**": "deny"
}
}
}Use cases
- Notes/memory layer: Linking an Obsidian vault into a project so the agent can read/write notes while working on code
- Virtual workspace: Symlinking multiple projects into one place for agent to work across them
- Shared resources: Linking shared configs, libraries, or documentation across projects
Security requirements
- Do not treat external symlink targets as part of the project without approval.
- Bind approval to the resolved target boundary, not only the symlink path.
- For write/edit/apply_patch flows, revalidate immediately before mutation so a symlink target swap after approval is rejected.
- Broken symlinks and symlink loops must fail safely.
- Windows junctions/reparse points should follow the same rules.
- Existing
external_directorydeny rules must still win. - Existing config ordering and wildcard semantics should remain unchanged.
Why use external_directory
OpenCode already has the right permission primitive:
external_directoryprompts when tools touch paths outside the project.- The UI already supports
Allow once,Allow always, andReject. Allow alwaysis already documented as session-scoped.- Persistent grants already exist through
permission.external_directoryinopencode.json.
This keeps the implementation focused and avoids introducing a new trust store before the product needs one.
Non-goals
- This is not a request to blindly follow all symlinks.
- This is not a request to trust plugin or MCP executable paths.
- This is not a replacement for multi-root workspaces ([FEATURE]: workspace folders — explicit multi-directory support #19515).
- This does not make project-owned config files silently grant access to arbitrary host paths.
Related issues / PRs
- fix: symlink/junction directories invisible in directory picker and @file #28526: symlink/junction directories invisible in directory picker and @file
- fix(filesystem): resolve symlink/junction targets to directory type in readDirectoryEntries #28532: resolve symlink/junction targets to directory type
- fix: grep external directory permission evaluation #26958: grep external directory permission evaluation for symlink/alias paths (merged)
- external_directory NOT resolving symlinked directory #27601: external_directory not resolving symlinked directory paths
- Symlinked directories not visible in project picker (opencode serve) #10365: symlinked directories not visible in project picker
- Does OpenCode not recognize the reference paths of symbolic links? in windows 11 #16342: Windows symbolic links not recognized in @file
- [FEATURE]: workspace folders — explicit multi-directory support #19515: explicit multi-directory workspace folders
- Path traversal vulnerability via symlinks and cross-drive paths #8313: path traversal vulnerability via symlinks and cross-drive paths
Activity
[-]feat(filesystem): allow external symlink targets via external_directory consent[/-][+][FEATURE]: allow external symlink targets via external_directory consent[/+]github-actions commentedon Jun 4, 2026
Thank you for updating the issue! It now follows the contributing guidelines and the
needs:compliancelabel has been removed. We appreciate you taking the time to fill out the feature request template properly.sghng commentedon Jun 5, 2026
Very looking forward to this feature! I can think of another potential use case: a global
mailboxdir that is symlinked into multiple working directories of opencode, so that agents can drop messages into this dir and read messages from others. This enables the the coordination/orchestration of agents on multiple projects.danielxxomg commentedon Jun 6, 2026
I also explored a small TUI direction for this, based on the Obsidian and shared-mailbox use cases.
The permission flow would still be the core of the feature, using the existing
external_directorybehavior described above. Separately, it might be useful to make active or configured external links visible in the UI, so users can tell when a workspace is connected to paths outside the project.One possible treatment would be:
↗ 2 LinksLinkssection for a quick overview/statussection showing the link path, resolved target, and relevant permission stateMockups:
These are only UI explorations, not a proposal to expand the initial implementation. My preference would be to keep the first change focused on safe consent behavior, then consider TUI visibility as a follow-up if the direction is useful.
sghng commentedon Jun 7, 2026
@danielxxomg Speaking of TUI, it may also need some change for the virtual workspace. Currently the file diffs/review are designed for one Git repo at the root of the work dir. But with virtual workspace implemented, the diff list would need several sections for changes in different repos.
Also virtual workspace is not a niche thing, VSCode has had it for a long time: VSCode docs
github-actions commentedon Aug 7, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.
dcunited001 commentedon Sep 8, 2026
why not add hardlinks in your git repo. it's super fun