[FEATURE] Add PostWorktreeCreate hook (or setup command) for environment initialization in worktrees
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
When using --worktree, isolation: worktree (subagents), or Agent Teams, Claude Code creates a new git worktree via git worktree add. This correctly copies all tracked files but does not carry over gitignored state — most critically:
.venv/— Python virtual environment with all project dependencies.env— environment variables (DB credentials, API keys, service URLs)node_modules/— (less critical,npm installis fast and safe)
For Python projects, this means agents in worktrees cannot execute code, run tests, or use linters — the core value proposition of worktree isolation is lost.
Why this matters
The worktree feature is designed for parallel agent execution. But in a typical Python project:
- Agent starts in a fresh worktree
- Agent tries to run
pytest,ruff,mypy, or any Python script - Fails — no
.venv, no dependencies installed - Agent must either:
pip installinto system Python (unsafe, contaminates host)- Create a new venv + install all deps (slow: 30-120s depending on project size, wastes disk)
- Fail and report it cannot complete the task
This affects all three worktree use cases:
| Use case | Can user manually set up env? | Automated? |
|---|---|---|
| claude --worktree (CLI) | ✅ Yes, before running claude | ❌ No hook |
| isolation: worktree (subagents) | ❌ No, agent creates worktree automatically | ❌ No hook |
| Agent Teams (teammates) | ❌ No, worktrees created automatically | ❌ No hook |
For subagents and Agent Teams — the primary use case for parallel development — there is no way for the user to intervene between worktree creation and agent start.
Current workarounds and why they're insufficient
Workaround 1: CLAUDE.md instructions
# CLAUDE.md
When working in a worktree, first run: python -m venv .venv && source .venv/bin/activate && pip install -e ".[dev]"
Problems:
- Unreliable — Claude often ignores venv instructions (see #273, #2709, #9368)
- Slow — full dependency installation on every worktree creation
- Wastes tokens on environment setup instead of actual work
- Not deterministic — hooks exist precisely because LLM compliance isn't guaranteed
Workaround 2: Hijack WorktreeCreate hook
#!/bin/bash
set -e
INPUT=$(cat)
NAME=$(echo "$INPUT" | jq -r '.name')
DIR="$CLAUDE_PROJECT_DIR/.claude/worktrees/$NAME"
# Reproduce default git behavior
git worktree add "$DIR" -b "worktree-$NAME" HEAD >&2
# Set up environment
ln -s "$CLAUDE_PROJECT_DIR/.venv" "$DIR/.venv" >&2
ln -s "$CLAUDE_PROJECT_DIR/.env" "$DIR/.env" >&2
echo "$DIR"
Problems:
- Fragile — reproduces internal Claude Code logic (
git worktree add -b worktree-$NAME HEAD). If the default behavior changes (branch naming, base ref, worktree path), the hook silently creates incompatible worktrees WorktreeCreateis documented as a replacement for non-git VCS, not a post-creation hook- Symlinked
.venvis unsafe if agent runspip install— it modifies the shared venv
Workaround 3: Use uv instead of pip/venv
uv sync && uv run pytest is fast and doesn't require a pre-existing venv. But:
- Requires the project to adopt
uv(not always possible) - Still doesn't solve
.envfiles - Still relies on CLAUDE.md instructions (non-deterministic)
Proposed Solution
Add a PostWorktreeCreate hook event that fires after the standard git worktree add completes successfully.
Hook specification
Event name: PostWorktreeCreate
When it fires: After Claude Code's built-in git worktree add creates the worktree, but before the agent session starts in it.
Input (stdin JSON):
{
"session_id": "abc123",
"hook_event_name": "PostWorktreeCreate",
"cwd": "/Users/dev/my-project",
"worktree_path": "/Users/dev/my-project/.claude/worktrees/feature-auth",
"worktree_name": "feature-auth",
"branch_name": "worktree-feature-auth",
"base_ref": "HEAD"
}
Key fields:
worktree_path— absolute path to the created worktree (critical for setup scripts)worktree_name— the slug identifierbranch_name— the branch created by git worktree addbase_ref— the ref the worktree was branched from
Output: Standard allow/block decision model (or no output required — just run the command).
On failure: Warning only, do not block worktree creation. The agent should still start — it can attempt to set up the environment itself or report the issue. This is environment optimization, not a gate.
Example usage
.claude/settings.json:
{
"hooks": {
"PostWorktreeCreate": [
{
"hooks": [
{
"type": "command",
"command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/post-worktree-setup.sh\"",
"timeout": 60
}
]
}
]
}
}
.claude/hooks/post-worktree-setup.sh:
#!/bin/bash
set -e
INPUT=$(cat)
WORKTREE_PATH=$(echo "$INPUT" | jq -r '.worktree_path')
PROJECT_DIR=$(echo "$INPUT" | jq -r '.cwd')
# Symlink Python venv (fast, no disk overhead)
if [ -d "$PROJECT_DIR/.venv" ] && [ ! -e "$WORKTREE_PATH/.venv" ]; then
ln -s "$PROJECT_DIR/.venv" "$WORKTREE_PATH/.venv" >&2
echo "Symlinked .venv" >&2
fi
# Copy .env (not symlink — agent might modify it)
if [ -f "$PROJECT_DIR/.env" ] && [ ! -e "$WORKTREE_PATH/.env" ]; then
cp "$PROJECT_DIR/.env" "$WORKTREE_PATH/.env" >&2
echo "Copied .env" >&2
fi
Alternative: worktreeSetupFiles configuration
If a new hook event is too heavy, a simpler alternative: a configuration option in settings.json that specifies files/directories to symlink or copy into new worktrees:
{
"worktree": {
"setupFiles": [
{ "path": ".venv", "strategy": "symlink" },
{ "path": ".env", "strategy": "copy" },
{ "path": "config/local.yaml", "strategy": "copy" }
]
}
}
This would cover 90% of use cases without requiring users to write shell scripts.
Related Issues
- #273 — Claude doesn't detect
.venv/automatically - #2709 — Claude uses global pip instead of venv
- #8855 — No persistent venv activation across commands
- #9368 — Claude ignores CLAUDE.md instructions about venv/uv
- #19938 — Missing instructions for environment file setup in worktree workflow
- #20905 — Dependency installation guidance buried in Tips, not in Steps
- #21613 — No Python support in official devcontainer
Additional Context
Scope of impact
Python is one of the most popular languages for Claude Code users (acknowledged in #21613). Every Python project using venv/virtualenv (which is effectively all of them) is affected when using worktree isolation.
What other tools do
claude-worktree(PyPI) — third-party wrapper that auto-symlinks.venvandnode_modules, supports configurable copy-files. Validates the need exists.git-worktree-runner(coderabbitai) — supportscopy_patternsandrun_hooks_in()post-creation.worktrunk— supports post-start hooks for dependency installation.
The ecosystem has independently converged on the same solution: a post-creation setup step. Claude Code is the only tool in this space that lacks it.
Why WorktreeCreate is not sufficient
Per the docs: "For other version control systems like SVN, Perforce, or Mercurial, configure WorktreeCreate and WorktreeRemove hooks to provide custom worktree creation and cleanup logic. When configured, these hooks replace the default git behavior."
WorktreeCreate replaces git worktree add — it's a VCS adapter, not a setup hook. Using it for environment setup requires reproducing Claude Code's internal git worktree logic, which is undocumented, may change, and creates a maintenance burden for users.
Showing cached comments. Read the full discussion on GitHub ↗
7 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
This is not a duplicate of the flagged issues. Here's why:
#19938 — [DOCS] Missing instructions for environment file setup
That issue asks to update documentation with a manual
cp .envstep. It's a docs gap. My issue requests a new hook event (PostWorktreeCreate) because manual copying is impossible when worktrees are created automatically by subagents and Agent Teams.#26697 — [Feature Request] Configurable untracked file copying
Closest in spirit, but different in scope:
copyUntrackedFilesfor simple files (.env,.env.local)WorktreeCreatereplacesgit worktree add(it's a VCS adapter), so there's no post-creation hook for environment setup.venv/— a directory that should be symlinked (not copied), because copying a full venv is slow and wastes disk, while symlinking is instant#20905 — [DOCS] Dependency installation buried in Tips
Pure documentation ordering issue. No feature request.
What makes this issue unique
isolation: "worktree"subagents and Agent Teams, the user has zero opportunity to set up the environment. No amount of documentation fixes this — it requires a programmatic hook.WorktreeCreatecannot solve this. Per the docs, it replacesgit worktree add. Using it for post-creation setup requires reproducing Claude Code's internal git worktree logic — fragile and undocumented.PostWorktreeCreatehook (fires aftergit worktree add, receivesworktree_path)worktreeSetupFilesconfig with symlink/copy strategies (simpler alternative, covers 90% of cases — similar to #26697'scopyUntrackedFilesbut with symlink support for directories like.venv)I do reference #19938 and #20905 as related issues in my submission. They describe symptoms of the same underlying problem — but my issue proposes the fix at the right abstraction level (hooks/config, not docs).
i was just about to file this :)
Would fix our monorepo worktrees where
node_modulesworkspace symlinks resolve to the main checkout instead of the worktree — a post-createbun install(combined with #27282 for external placement) would solve it. Related: #27282Our current alternative is to use gtr (https://github.com/coderabbitai/git-worktree-runner/) to manage worktrees.
Then we have:
.gtrconfigthat can handle executing scripts when you rungtr cd, the ones it sounds like we're looking for in this thread arepostCdandpostCreate:Also ran into this. Wrote about it (along with the broader worktree isolation model) here:
https://my.feishu.cn/docx/O1O0daR6SoSiKsxksiecFjk7nKc
The article covers the
.venv/.envproblem as one of the real-world cracks in the worktree isolation design, alongside stale cleanup and build cache collisions across languages.+1 to this — the "ecosystem has independently converged on the same solution" point is right, and it's worth adding workz to that list alongside
claude-worktreeandgit-worktree-runner. It's a standalone binary that does exactly the symlink-venv/copy-env step described here (project-aware —.venv,node_modules,target, etc.), plus optionally allocates a unique port range, database name, and Docker Compose project per worktree, so parallel worktrees don't collide on top of not having deps.For the
claude --worktreeCLI case,WorktreeCreatealready works as the seam today:But this issue's real point stands regardless of that workaround: for
isolation: "worktree"subagents and Agent Teams, there's no seam at all today, since the worktree is created and populated with an agent before a user (or a project-level hook aimed at the CLI flow) gets a chance to intervene. APostWorktreeCreatehook (or the simplerworktreeSetupFiles-style config also proposed here) would close that gap — right now it's the one worktree-creation path with zero customization point, which is exactly backwards from the automated/parallel use case the feature is for.