[BUG] `--worktree` fails in non-git repos even when `WorktreeCreate` hook is configured
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
claude --worktree <name> immediately exits with an error in non-git repositories (e.g., Mercurial/Sapling), even when a WorktreeCreate hook is configured in ~/.claude/settings.json. The git repository check in the setup function runs before the hook is considered, so the hook never fires.
What Should Happen?
When a WorktreeCreate hook is registered, claude --worktree should delegate to that hook instead of requiring a git repository. The hook mechanism exists precisely to support non-git VCS systems (Mercurial, Sapling, SVN, etc.), and the internal worktree creation function already handles this correctly — it just never gets called.
Error Messages/Logs
Error: Can only use --worktree in a git repository, but /path/to/repo is not a git repository
Steps to Reproduce
- Navigate to a non-git repository (e.g., a Mercurial/Sapling repo)
- Add a
WorktreeCreatehook to~/.claude/settings.json:
``json``
{
"hooks": {
"WorktreeCreate": [
{
"type": "command",
"command": "my-worktree-create-script $name"
}
]
}
}
- Run
claude --worktree mytree - Error fires immediately — the hook is never invoked
Claude Model
Opus
Is this a regression?
No, this never worked
Last Working Version
_No response_
Claude Code Version
v2.1.58
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
Root cause in code:
The setup function checks isGitRepo() before the worktree creation function is called. The worktree creation function itself already correctly checks for a WorktreeCreate hook first, but the early guard prevents it from ever being reached:
setup() {
if (worktreeFlag) {
if (!isGitRepo()) // ← blocks non-git repos before hooks are checked
exit("not a git repo")
// ... git-specific setup ...
createWorktree() // ← never reached for non-git repos
}
}
createWorktree() {
if (hasWorktreeCreateHook()) { // ← correctly checks for hook first
delegateToHook(name) // but never gets called
} else {
// git-based worktree
}
}
Suggested fix: Check for a WorktreeCreate hook before the git repo check. If a hook exists, skip git-specific pre-checks and delegate directly:
if (worktreeFlag) {
if (hasWorktreeCreateHook()) {
// Hook-based path: skip git checks entirely
let result = await createWorktree(sessionId, name);
process.chdir(result.worktreePath);
} else {
// Existing git-based path (unchanged)
if (!isGitRepo()) exit("not a git repo");
// ...
}
}
This is consistent with how agent worktree creation and the worktree creation function itself already handle the hook-based path.
Related: #27439 — --worktree also fails in bare git repos due to the same early guard. Both issues stem from the overly restrictive git check in the setup function.
Environment:
- OS: macOS / Linux
- VCS: Sapling (Mercurial-based)
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗