[BUG] .worktreeinclude patterns with leading `**/` silently match nothing during worktree copy
Bug Description
.worktreeinclude patterns with a leading **/ (e.g. **/.claude/skills/*-local/) silently match nothing during the worktree file copy — the matching gitignored files are not copied into the new worktree, with no warning. The same pattern without the leading **/ works.
The docs (https://code.claude.com/docs/en/worktrees.md, "Copy gitignored files into worktrees") say:
The file uses .gitignore syntax. Only files that match a pattern and are also gitignored are copied, so tracked files are never duplicated.
Under gitignore syntax a leading **/ is valid and means "at any depth including the root" — git check-ignore -v matches these paths against the same pattern. So this is a divergence from the documented contract.
Steps to Reproduce
mkdir repro && cd repro && git init
printf '**/.claude/skills/*-local/\n.claude/worktrees/\n' > .gitignore
printf '**/.claude/skills/*-local/\n' > .worktreeinclude
mkdir -p .claude/skills/foo-local
echo hello > .claude/skills/foo-local/SKILL.md
git add -A && git commit -m init
# sanity: the pattern is valid gitignore and matches
git check-ignore -v .claude/skills/foo-local/SKILL.md
# .gitignore:1:**/.claude/skills/*-local/ .claude/skills/foo-local/SKILL.md
claude -w t1 -p "ok"
ls .claude/worktrees/t1/.claude/skills/foo-local/SKILL.md # MISSING
# drop the leading **/ and try again
printf '.claude/skills/*-local/\n' > .worktreeinclude
claude -w t2 -p "ok"
ls .claude/worktrees/t2/.claude/skills/foo-local/SKILL.md # copied
Expected Behavior
**/.claude/skills/*-local/ copies .claude/skills/foo-local/ into the worktree (gitignore semantics: leading **/ matches at any depth, including the repo root), or at minimum a warning is emitted that the pattern matched nothing.
Actual Behavior
Files matching the leading-**/ pattern are silently not copied. The "Copied N files from .worktreeinclude" flow gives no indication the pattern was dropped.
Additional Observations
Tested on v2.1.215 in a larger real repo as well; in the same spawn:
- Exact file paths (
foo/.env) — copied - Single-star globs (
frontend/*/.env) — copied - Trailing-slash directory patterns (
infrastructure/local-dev/certs/) — copied - Leading
**/patterns — not copied, both**/x/*-local/and**/x/*-local/**forms
The failure doesn't reproduce in the obvious building blocks in isolation, so it appears to be in how they're composed:
git ls-files --others --ignored --exclude-standard --directory -- '**/.claude/skills/*-local/'lists the directory- the
ignorenpm package (tested v5.3.2 and v7.0.5):ignore().add('**/.claude/skills/*-local/').ignores('.claude/skills/foo-local/SKILL.md')returnstrue
Environment
- Claude Code version: 2.1.215 (native install)
- OS: Linux 6.17.0-40-generic (Ubuntu)
- Shell: bash
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗