Summary
A worktree-isolated agent (Agent with isolation: "worktree", or any subagent with a pinned cwd)
cannot invoke any skill that declares two or more ! precompute commands when at least one is a
git command. The invocation fails before the skill body is ever reached.
Discovered while running /session-flow:handoff at the end of an inbox item. It is not a
handoff-specific bug — handoff is just where it surfaced. 42 skills across this marketplace
match the pattern, including most of the core workflow: source-control:commit,
source-control:pull-request, source-control:worktree, implementation:implement,
verification:confirm, review:fanout, session-flow:retro, session-flow:handoff,
planning:plan, testing:plan, toolchain:check.
Reproduction
From an agent isolated in .claude/worktrees/<name>:
Skill(session-flow:handoff)
fails with:
This agent is isolated in the worktree C:\...\.claude\worktrees\agent-a4324d31193dece2f, but this
command is too complex to verify that it stays inside the worktree; break it into plain, separate
commands. Refusing to run it — a worktree-isolated agent's git operations must target its own
worktree.
Identical failure with and without arguments. The skill body never runs.
Root cause
plugins/session-flow/skills/handoff/SKILL.md declares four precompute lines:
Current branch: !`git branch --show-current 2>/dev/null || echo "unknown"`
Claude session: !`echo "${CLAUDE_CODE_SESSION_ID:-unknown}" || echo "unknown"`
Uncommitted changes: !`git status --porcelain 2>/dev/null | head -20 || echo "clean"`
Recent commits: !`git log --oneline -5 2>/dev/null || echo "no commits"`
Each line passes the guard individually — verified one at a time:
| precompute line |
result |
git branch --show-current 2>/dev/null || echo "unknown" |
ok — main |
git status --porcelain 2>/dev/null | head -20 || echo "clean" |
ok — (clean) |
git log --oneline -5 2>/dev/null || echo "no commits" |
ok — 5 commits |
Joined with ; into a single invocation, the exact guard error reproduces:
git branch --show-current 2>/dev/null || echo "unknown"; echo "${CLAUDE_CODE_SESSION_ID:-unknown}" || echo "unknown"; git status --porcelain 2>/dev/null | head -20 || echo "clean"; git log --oneline -5 2>/dev/null || echo "no commits"
…this command is too complex to verify that it stays inside the worktree…
So the skill runner appears to concatenate all ! precompute commands into one shell
invocation. The guard's complexity heuristic rejects the compound form, even though every component
is individually safe and every one of them is read-only.
Blast radius
Counted across plugins/**/SKILL.md:
- 172
! precompute lines across 62 skills
- 123 git-bearing precompute lines across 49 skills
- 42 of those 49 declare two or more git precompute lines
Any skill with ≥2 precompute lines and ≥1 git command is affected, so the true count is at least 42.
This makes worktree-isolated agents unable to use the marketplace's own core workflow skills — which
is precisely the context those skills are most needed in, since CLAUDE.md and the worktree
convention push agents into worktrees for parallel work.
Impact
Fails closed and loudly, which is the good news — no silent degradation, no wrong output. But the
skill is simply unavailable, and the fallback is for the agent to hand-write whatever the skill would
have produced. In the session that found this, the handoff document had to be written by hand and
could not be placed in its canonical .work/handoffs/ location at all (see the second issue below).
Suggested directions (not verified end to end)
- Run precompute commands separately rather than joined. Each line already passes the guard on
its own; if the runner issued them as N invocations, the problem disappears with no change to any
skill. This looks like the correct fix and it is upstream of the marketplace.
- Failing that, simplify the precompute lines in the affected skills so the joined form stays
within the guard's tolerance — e.g. drop the || echo "…" fallbacks, which mostly guard against a
non-git directory that the guard itself already implies is not the case.
- Degrade rather than abort. A precompute that cannot run could yield an empty value and let the
skill body proceed; every one of these lines is contextual, none is load-bearing for correctness.
Direction 1 is the only one that fixes all 42 skills at once, but it may live in the harness rather
than in this repository — worth confirming before any skill here is edited.
Related observation (separate, may warrant its own issue)
A cwd-pinned subagent also cannot call ExitWorktree:
ExitWorktree cannot be called from a subagent with a cwd override … This agent is already
isolated; use Bash with cd for directory changes within it.
Combined with the guard refusing writes to the shared checkout, an isolated agent has no path to
write a file that is meant to live outside its worktree — such as a handoff in .work/handoffs/,
which is deliberately shared so it survives worktree cleanup. In this session the worktree was
reclaimed by cleanup within minutes of the merge, so a handoff written inside it would have been
destroyed anyway.
Summary
A worktree-isolated agent (
Agentwithisolation: "worktree", or any subagent with a pinned cwd)cannot invoke any skill that declares two or more
!precompute commands when at least one is agit command. The invocation fails before the skill body is ever reached.
Discovered while running
/session-flow:handoffat the end of an inbox item. It is not ahandoff-specific bug —handoffis just where it surfaced. 42 skills across this marketplacematch the pattern, including most of the core workflow:
source-control:commit,source-control:pull-request,source-control:worktree,implementation:implement,verification:confirm,review:fanout,session-flow:retro,session-flow:handoff,planning:plan,testing:plan,toolchain:check.Reproduction
From an agent isolated in
.claude/worktrees/<name>:fails with:
Identical failure with and without arguments. The skill body never runs.
Root cause
plugins/session-flow/skills/handoff/SKILL.mddeclares four precompute lines:Each line passes the guard individually — verified one at a time:
git branch --show-current 2>/dev/null || echo "unknown"maingit status --porcelain 2>/dev/null | head -20 || echo "clean"git log --oneline -5 2>/dev/null || echo "no commits"Joined with
;into a single invocation, the exact guard error reproduces:So the skill runner appears to concatenate all
!precompute commands into one shellinvocation. The guard's complexity heuristic rejects the compound form, even though every component
is individually safe and every one of them is read-only.
Blast radius
Counted across
plugins/**/SKILL.md:!precompute lines across 62 skillsAny skill with ≥2 precompute lines and ≥1 git command is affected, so the true count is at least 42.
This makes worktree-isolated agents unable to use the marketplace's own core workflow skills — which
is precisely the context those skills are most needed in, since
CLAUDE.mdand the worktreeconvention push agents into worktrees for parallel work.
Impact
Fails closed and loudly, which is the good news — no silent degradation, no wrong output. But the
skill is simply unavailable, and the fallback is for the agent to hand-write whatever the skill would
have produced. In the session that found this, the handoff document had to be written by hand and
could not be placed in its canonical
.work/handoffs/location at all (see the second issue below).Suggested directions (not verified end to end)
its own; if the runner issued them as N invocations, the problem disappears with no change to any
skill. This looks like the correct fix and it is upstream of the marketplace.
within the guard's tolerance — e.g. drop the
|| echo "…"fallbacks, which mostly guard against anon-git directory that the guard itself already implies is not the case.
skill body proceed; every one of these lines is contextual, none is load-bearing for correctness.
Direction 1 is the only one that fixes all 42 skills at once, but it may live in the harness rather
than in this repository — worth confirming before any skill here is edited.
Related observation (separate, may warrant its own issue)
A cwd-pinned subagent also cannot call
ExitWorktree:Combined with the guard refusing writes to the shared checkout, an isolated agent has no path to
write a file that is meant to live outside its worktree — such as a handoff in
.work/handoffs/,which is deliberately shared so it survives worktree cleanup. In this session the worktree was
reclaimed by cleanup within minutes of the merge, so a handoff written inside it would have been
destroyed anyway.