feat(opencode): allow agents to read external Rust crate source

@make, @test, @check often need to inspect dependency source (trait
definitions, impl details, test patterns) to inform implementation or
verify findings. Opencode applies a CWD check on tool access, so reads
outside the worktree previously prompted for each access.

- Add permission.read/grep/glob path allowlists for the three locations
  cargo deps live: ~/.cargo/registry/src/, ~/.cargo/git/checkouts/, and
  /nix/store/*-vendor-*/ for crane / buildRustPackage projects.
- Document the discovery pattern in each agent: `cargo metadata
  --format-version 1` returns absolute paths via packages[].manifest_path.
- Cross-reference the registry paths from the permission.bash allowlist
  comment so future readers see the bash inspection commands (rg/ls)
  intentionally accept paths outside CWD.
- @check gets its first permission block (was tools-only before).

Path-pattern syntax for read/grep/glob isn't fully documented; if
opencode rejects it, fall back to `permission: { external_directory:
allow }` at the project config level.
This commit is contained in:
Harald Hoyer 2026-05-08 13:24:30 +02:00
parent af6481a5a7
commit 3e515d54eb
3 changed files with 129 additions and 0 deletions

View file

@ -6,6 +6,23 @@ tools:
edit: true
bash: true
permission:
# ── External-directory reads (registry / git deps / nix-vendored) ──
# Opencode applies a CWD check on tool access; these patterns whitelist
# the cargo dependency source trees so the Read/Grep/Glob tools (and
# bash inspection commands like `rg`/`ls`) don't prompt for each access.
# See "Reading External Crate Source" below for the discovery pattern.
read:
"~/.cargo/registry/src/**": allow
"~/.cargo/git/checkouts/**": allow
"/nix/store/*-vendor-*/**": allow
grep:
"~/.cargo/registry/src/**": allow
"~/.cargo/git/checkouts/**": allow
"/nix/store/*-vendor-*/**": allow
glob:
"~/.cargo/registry/src/**": allow
"~/.cargo/git/checkouts/**": allow
"/nix/store/*-vendor-*/**": allow
bash:
# Default deny
"*": deny
@ -28,6 +45,12 @@ permission:
"cargo fmt*": allow
# ── Read-only inspection ──
# The wildcarded patterns below accept any path argument, including
# paths *outside* the worktree. This is intentional — see "Reading
# External Crate Source" below. Specifically reachable:
# ~/.cargo/registry/src/index.crates.io-*/<crate>-<version>/ (registry)
# ~/.cargo/git/checkouts/<crate>-<hash>/<branch>/ (git deps)
# /nix/store/*-vendor-*/<crate>-<version>/ (nix-vendored)
"ls *": allow
"ls": allow
"wc *": allow
@ -126,6 +149,25 @@ Rust:
**Anti-patterns — refuse the path even if it would technically be writable:**
- `src/tests/foo.rs` and similar regular submodule paths under `src/`. These are not `#[cfg(test)]` modules — they are normal modules that would require a `mod tests;` declaration in production code (`lib.rs` / `main.rs`), which you cannot add. Report as `BLOCKED` and suggest either `tests/<feature>.rs` (integration) or a `#[cfg(test)] mod tests` block inside the relevant `src/<module>.rs`.
## Reading External Crate Source
When you need to inspect a dependency's source — to understand a trait you're testing against, find a known-good test pattern from a well-tested crate, or check a dep's behavior under specific conditions — external source is reachable via the Read/Grep/Glob tools and via `rg`/`ls` in bash. **Do not edit external source.**
**Where dependency source lives:**
| Source | Path pattern |
|---|---|
| Registry crates | `~/.cargo/registry/src/index.crates.io-*/<crate>-<version>/` |
| Git deps | `~/.cargo/git/checkouts/<crate>-<hash>/<branch>/` |
| Nix-vendored deps (crane, buildRustPackage) | `/nix/store/<hash>-vendor-*/<crate>-<version>/` |
Discover paths via `nix develop -c cargo metadata --format-version 1`; the JSON has `packages[].manifest_path` per dep. The registry must be populated — run `nix develop -c cargo check` once if the metadata call shows missing source.
Read patterns:
- `rg "trait Serialize" ~/.cargo/registry/src/index.crates.io-*/serde-1.*/src/`
- `ls ~/.cargo/registry/src/index.crates.io-*/tokio-1.*/tests/` — useful for borrowing test patterns
- Read tool with absolute path for a specific file.
## Test Philosophy
**Contract tests + regression.** Write tests that verify: