Skip to content

feat(server): run project worktree setup for Claude subagent worktrees - #127

Merged
adampeterhiggins merged 1 commit into
mainfrom
ah/subagent-worktree-environment-variables
Oct 1, 2026
Merged

adampeterhiggins merged 1 commit into
mainfrom
ah/subagent-worktree-environment-variables

Conversation

@adampeterhiggins

Copy link
Copy Markdown
Owner

Claude Code creates the worktree for an isolation: "worktree" subagent itself, so T3's worktree preparation never ran there. Files to copy weren't copied, the setup script didn't run, and the project's Conductor environment variables never reached it.

Fix

  • The Claude adapter registers a SubagentStart SDK hook. I checked against the real CLI (2.1.286) that this hook fires after Claude creates the subagent's worktree and before its first tool call, with the worktree as cwd, and that Claude waits for the hook to finish.
  • When the subagent's cwd differs from the session's own, the hook calls SubagentWorktreeSetup.prepare. Each worktree is prepared at most once.
  • That service runs the existing ProjectSetupScriptRunner.runForThread for the parent thread's project. Files to copy, script selection (T3 setup action first, then Conductor scripts.setup) and the CONDUCTOR_* / environment_variables env all match what a thread's own worktree gets. Output goes to a subagent-setup-<agentId> terminal on the parent thread.
  • Same blocking rule as threads: a non-async script holds the subagent until it exits, and an async one keeps running beside it. The hook timeout is raised to 10 minutes for long installs. Setup is best effort, so a failure is logged and the subagent still starts.
  • Provider layers are built below the project/git layers, so the runner reaches the adapter through a small late-bound service. SubagentWorktreeSetup.layer sits beside the provider layers, and installLive, at the top of the runtime layers, plugs in the real implementation. Without the install (as in tests), prepare does nothing.

Scope

  • Claude only. No other adapter hands T3 a per-subagent worktree.
  • No archive script runs on subagent worktrees. Claude Code removes them itself, and taking over WorktreeCreate/WorktreeRemove would mean re-implementing its worktree creation.
  • Docs: docs/fork-differences.md and the Conductor section of docs/user/project-settings.md.

Testing

  • vp test run src/provider/Layers/ClaudeAdapter.test.ts (148 pass, including a new hook test) and src/project/SubagentWorktreeSetup.test.ts (3 new). tsc --noEmit for apps/server is clean.
  • server.test.ts > flushes more than one tool chunk before the synchronization marker fails, but it fails on main as well.
  • Not tested end to end through a running T3 server. The hook's timing was confirmed with a standalone SDK script against the real CLI.

Done by Claude Opus 5.5 in Claude Code (via T3 Code).

🤖 Generated with Claude Code

Claude Code creates the worktree for an `isolation: "worktree"` subagent
itself, so T3's files to copy, setup script, and Conductor environment
variables never reached it. A SubagentStart hook now prepares that
worktree through the project setup runner before the subagent's first
tool call, waiting only for non-async scripts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant