[BUG] `claude -w` can't remove a clean worktree on exit when launched inside a git submodule
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?
When I run claude -w inside a git submodule and exit a session without making changes, Claude Code prints "Worktree could not be removed" and leaves the worktree directory and its worktree-* branch behind.
The leftover worktree has nothing that should block removal. Its HEAD matches main, git status is clean, it isn't locked, and running git worktree remove on it by hand succeeds.
Running claude -w in the submodule's origin repo, a standalone repo with the same commit, removes the worktree as expected.
What Should Happen?
A clean, unnamed worktree created inside a submodule is removed on exit, the same as in a standalone repo:
Removing worktree…
Worktree removed (no changes)
Error Messages/Logs
~/claude-wt-repro/parent/child (main) % claude -w
# exit immediately
Removing worktree…
Worktree could not be removed — kept at ~/claude-wt-repro/parent/child/.claude/worktrees/shimmering-stirring-simon
~/claude-wt-repro/parent/child (main) % git worktree list --porcelain
worktree ~/claude-wt-repro/parent/.git/modules/child
HEAD 7e7224347acc815b391d61e962d3f33ac4a3ea73
branch refs/heads/main
worktree ~/claude-wt-repro/parent/child/.claude/worktrees/shimmering-stirring-simon
HEAD 7e7224347acc815b391d61e962d3f33ac4a3ea73
branch refs/heads/worktree-shimmering-stirring-simon
~/claude-wt-repro/parent/child (main) % git -C .claude/worktrees/shimmering-stirring-simon status --short --branch
## worktree-shimmering-stirring-simon
~/claude-wt-repro/child-origin (main) % claude -w
# exit immediately
Removing worktree…
Worktree removed (no changes)
Steps to Reproduce
- Create a repo to use as the submodule's origin:
``sh``
git init -b main child-origin
cd child-origin
echo '# child' > README.md
echo '.claude/worktrees/' > .gitignore
git add . && git commit -m "init child"
cd ..
- Create a parent repo and add
child-originas a submodule:
``sh`
git init -b main parent && cd parent
echo '# parent' > README.md && git add . && git commit -m "init parent"
git clone ../child-origin child
git submodule add ../child-origin child
git submodule absorbgitdirs
git commit -m "add child submodule"
child/.git
This yields the standard submodule layout: is a file containing gitdir: ../.git/modules/child, and .git/modules/child/config sets core.worktree = ../../../child`.
cd child, runclaudeonce and accept the trust dialog (claude -wrefuses to start until the directory is trusted), then runclaude -wand exit without making changes.- "Worktree could not be removed — kept at …" appears, and
git worktree liststill shows the worktree. - Control:
cd ../../child-origin, runclaudeonce to accept trust, then runclaude -wand exit. "Worktree removed (no changes)" appears.
Note: the only difference between steps 3 and 5 is the submodule layout. Inside a submodule, git worktree list reports the main worktree as the git directory (.git/modules/child), not the checkout (parent/child).
Claude Model
Not sure / Multiple models
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.300 (Claude Code)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
Git 2.54.0 (Apple Git-157). Terminal: cmux.
Installed via the Homebrew claude-code@latest cask, 2.1.300, which is the newest cask release. npm has 2.1.301, which I haven't tested.
Git itself handles this layout. In the same repro, a worktree created with plain git worktree add inside the submodule is removed by git worktree remove, whether git runs from the submodule checkout or from .git/modules/child. Inside that worktree, git rev-parse --show-toplevel returns the worktree path. The failure seems to be in Claude Code's own pre-removal checks, not in git.
Related: #27156 (claude -w repo-root detection inside a submodule), #60131 (worktree creation fails in repos with submodules), #45179 (/resume with a submodule worktree). None of them covers removal on exit.