A run rooted under ~ gets the operator's ~/.agents and ~/.claude skills in its system prompt #89
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Runs isolate opencode's HOME and XDG dirs (
src/osf/agent/server.py,build_env/ISOLATION_ENV_KEYS) so the operator's config, MCP servers and skills never reach a run's system prompt (§21). That doesn't cover every path.Measured (2026-09-27, opencode 1.18.21,
osf.fakeinferrecording the upstream request)With the run root, and so its work dir, under
/Users/cmoriarty(for example~/.osfm/rN/runs/r1/work), the system prompt was 14,228 characters instead of 9,707. The difference was a<skill>index listing/Users/cmoriarty/.agents/skills/*(caveman, caveman-commit, ...). The same run rooted under/private/tmphad none of those entries. That is about 1.5k tokens a turn, per step, on a laptop osfd whose root is under ~. Production roots runs under/opt/openspecflow, so it is not affected.Cause (from the 1.18.21 bundle,
Skill.discovery)Unless
OPENCODE_DISABLE_EXTERNAL_SKILLSis set, opencode scans forskills/**/SKILL.mdin two places:<home>/.claudeand<home>/.agents. The home comes fromHOME, which is isolated, so this scan finds nothing.up({targets: [".claude", ".agents"], start: directory, stop: worktree}), a walk-up from the session directory to the project's worktree. For a directory that is not a git repo, opencode's worktree is/, so the walk goes to the filesystem root and picks up~/.agents/skillsand~/.claude/skills. In a git checkout it stops at the repo root.Reproduced with a probe skill planted in
.agents/skillsand.claude/skillsabove the run root. With the work dir not a git repo, both probe skills show up inGET /skill. Withgit initin the work dir, neither does.Fix
build_envsetsOPENCODE_DISABLE_EXTERNAL_SKILLS=1, which switches off both scans whether or not the work dir is a git repo..claude/skillsand.agents/skills. For example, a dogfood run on openspec-flow sees itsopenspec-*skills today. So the per-runopencode.jsonadds them back explicitly withskills.paths: [".claude/skills", ".agents/skills"], which opencode resolves against the session directory. The run keeps the project's skills, and nothing above the work dir can leak in.needs_opencodelive test plants skills above the run root and asserts that they do not reachGET /skill, while the project's own skills do.Shipped on main in
665f6fe(fix), with the proposal indcf78d0and the archive ine0f3bec. The change was OpenSpecrun-skills-stay-in-the-worktree, and it added a new spec,openspec/specs/run-isolation.build_envsetsOPENCODE_DISABLE_EXTERNAL_SKILLS=1, written after the caller's layers so they cannot undo it. This stops 1.18.21's walk-up for.claude/.agentsskills, which reaches/when the work dir isn't a git repo.opencode.jsonsetsskills.paths: [".claude/skills", ".agents/skills"], relative to the session directory, so the project's own skills still load..opencode/skillsis unaffected.test_skills_above_the_run_root_never_reach_the_run, parametrized over a git and a plain work dir. Without the fix, the plain-dir case lists both skills planted above the run root.osf.fakeinferand the run root under~: the implement floor was 37,732 characters without the fix and 33,077 with it, 4,655 fewer, in line with the 4,521 in the report.The stale live tests found along the way were fixed under #97.