·

Claude Code Project Skills Missing in Worktrees

Prepared and checked using AI. Sources are linked in the article.

claude-code git-worktrees tutorial ai-coding

Claude Code project skills missing in a worktree usually come down to which files that worktree checked out and where Claude Code looks for skills. A project skill belongs under .claude/skills/<name>/SKILL.md in the repository; a linked worktree has its own checkout of the repository’s files. Check whether the skill is committed on the worktree’s branch, whether its directory exists there, and whether the Claude Code version can read skills from the main checkout when that directory is absent.

Why the main checkout and worktree differ

A git worktree checks out a commit into a separate working directory. It shares repository history with the main checkout, but it does not copy the main checkout’s uncommitted edits or untracked files. A skill you created locally can therefore work in the main checkout while its SKILL.md is absent from the worktree. See why worktrees miss uncommitted changes for the same issue with ordinary project files.

Claude Code adds a version-dependent detail. In a terminal session started with claude --worktree or inside a worktree made with git worktree add, Claude Code searches for project skills up to the worktree root. Since v2.1.277, if that root has no .claude/skills directory, it loads the main checkout’s project skills. If the worktree has its own .claude/skills directory, only the worktree’s copy loads. A directory containing one tracked skill can therefore prevent a different, untracked skill in the main checkout from appearing through this fallback.

The branch matters too. Claude Code’s --worktree command normally starts from the repository’s remote default branch, rather than assuming the main checkout’s current local commit. A skill committed only on your local feature branch may be absent even though git status in the main checkout is clean. Claude Code sessions started from its desktop app use the main checkout’s root project configuration for skills, so distinguish that case from a terminal session before diagnosing file discovery.

Identify which case you have

For example, suppose the missing skill is .claude/skills/review-pr/SKILL.md. Run the following from the root directory of the main checkout, then run the same commands from the root directory of the worktree. Keep the outputs side by side. The .claude/skills paths are relative to the current directory; running these commands from a subdirectory can produce empty results even when the root skill exists.

git worktree list
git ls-files -- .claude/skills/review-pr/SKILL.md
git ls-tree -r --name-only HEAD -- .claude/skills
git status --short --untracked-files=all -- .claude/skills

git worktree list identifies the checkout paths and branches. git ls-files lists files in that checkout’s index, so an empty result from the main checkout’s root means the example skill is not tracked there. git ls-tree -r --name-only HEAD lists files in the checkout’s current commit; comparing its outputs tells you whether the two committed snapshots contain the same skills. git status --short --untracked-files=all reports changed and untracked skill files. A ?? entry in the main checkout explains why a newly created worktree did not check that file out.

If the file exists in the main checkout but git ls-files did not list it, check whether an ignore rule excludes the untracked file. Run this from the main checkout’s root too:

git check-ignore -v -- .claude/skills/review-pr/SKILL.md

git check-ignore -v shows the matching pattern and its source. Interpret it alongside the preceding git ls-files result: Git skips tracked files in this check by default, so silence for a tracked file does not establish whether a pattern matches it. For an untracked file, silence means this check found no matching exclude pattern. A verbose result whose pattern begins with ! is a negated pattern and means the file is not excluded; a matching, non-negated pattern means it is excluded.

Now check the worktree’s root .claude/skills directory. Its presence changes the fallback behavior on Claude Code v2.1.277 and later, even when the particular skill you want is missing from that directory. Finally, compare claude --version with v2.1.277. If you rely on the main-checkout fallback and use an older version, follow the official Claude Code update instructions for your installation method.

FindingLikely explanationNext step
Skill is untracked or ignored in the main checkoutThe new worktree checked out repository files without that local skillCommit a shared skill, or place a personal skill under ~/.claude/skills/
Skill is committed in the main checkout but absent from the worktree’s HEADThe worktree started from a different commitBring the skill commit into the worktree branch
Worktree has .claude/skills, but lacks this skillIts own directory prevents the main-checkout skills fallbackAdd the skill to the worktree’s branch or use another suitable scope
Skill file exists in the worktreeFile availability is no longer the main questionCheck discovery, invocation, naming, and settings

Choose a fix that matches the skill’s scope

Share a project skill through Git

If everyone working on the repository should receive the skill, keep its SKILL.md and any supporting files in the project’s .claude/skills/ directory and commit them. git add stages the named file. For the example path, stage it and inspect every change in the index before committing:

git add .claude/skills/review-pr/SKILL.md
git diff --cached
git commit -m "Add review PR skill"

git diff --cached shows all staged changes, including files staged before this example. Review the full output and resolve any unrelated staged changes before the commit. git commit -m records the entire index with the supplied message; staging the named skill does not limit that commit to the skill file. Review the skill’s contents before sharing it: committing the file distributes its instructions with the repository. If git add says the file is ignored, inspect the rule shown by git check-ignore -v and decide whether the rule should change. Avoid treating a forced add as the default fix for a rule intended to keep local configuration private.

A commit on one branch still needs to reach the worktree branch. If the worktree was created before the skill commit, or from a different base, bring that commit across using your repository’s normal branch update process. The worktree update guide covers that step. Recheck git ls-tree -r --name-only HEAD -- .claude/skills from the worktree’s root afterward; it should list the skill path in the commit that session is using.

If you regularly start Claude Code worktrees from work on your current local branch, worktree.baseRef can change their starting point. Merge the following worktree entry into ~/.claude/settings.json for your personal default or the repository’s .claude/settings.json for a shared project setting, preserving any existing settings. Commit the project settings file if teammates should receive it.

{
  "worktree": {
    "baseRef": "head"
  }
}

"head" starts a new Claude Code worktree from the current local HEAD; the default "fresh" starts from the repository’s remote default branch. This setting carries commits, including a committed skill, into new worktrees. It does not carry uncommitted files, and changing it does not update an existing worktree.

Keep a personal skill outside the repository

For a skill you want across your local projects, use ~/.claude/skills/<name>/SKILL.md. That personal location is independent of a particular project checkout, so it suits private workflows that should follow you into local worktree sessions. It also changes the skill’s scope: the same name is available in other projects, and a personal skill takes precedence over a project skill with that name. Choose a distinct name when both should remain directly invocable.

For a private skill tied to one repository, the current main-checkout fallback may be convenient, but understand its condition: it applies only when the worktree has no root .claude/skills directory and only on Claude Code v2.1.277 or later. It is a poor substitute for a committed project skill when collaborators or worktrees with their own skills need the same instructions.

Claude Code also supports a .worktreeinclude file for copying gitignored files into new worktrees it creates. That can help with intentionally ignored local skill files, but the pattern must match the file and the file must actually be gitignored. It does not apply to worktrees created directly with git worktree add, and it does not retroactively populate existing worktrees. Use it for an intentional local setup, rather than for a skill the team should commit.

If the file is present but the skill still seems missing

First determine whether discovery or automatic triggering failed. Open /skills in the worktree session and try /review-pr directly if the skill is user invocable. A skill can be available for direct invocation while its description is too vague for Claude to select automatically. Put the relevant task words in the frontmatter description, then try a request that uses those words.

Check the exact SKILL.md spelling and location. A project skill at the repository root has the form .claude/skills/review-pr/SKILL.md; a skill placed under a subdirectory has different discovery timing. A session started above that subdirectory does not load the nested skill at startup. It becomes available after Claude works with files there, or when that directory is added to the session with /add-dir on supported versions.

Then inspect invocation settings. disable-model-invocation: true intentionally prevents Claude from selecting a skill automatically while leaving direct invocation available. user-invocable: false does the reverse. A skillOverrides value of "off" hides the skill from both Claude and the slash-command menu; "user-invocable-only" leaves manual invocation available. If the skill appears under a different name, check its frontmatter name and whether a personal skill with the same name takes precedence.

Malformed frontmatter can create another misleading symptom: the skill body loads, but Claude cannot use an invalid description to match the request. Claude Code can report the parse error with --debug, and claude plugin validate .claude/skills checks project skill files on versions that support that command. Fixing metadata is useful only after you have established that the session can reach the file.

Where Parallel Code fits

Parallel Code is our free, open-source desktop app for running several AI coding agents in parallel, each in its own git worktree. Its diff-first review surface helps you inspect the resulting changes. The same Git distinction still matters for Claude Code project skills: put shared instructions in commits that each agent’s worktree can access.

Frequently asked questions

Does Claude Code copy project skills when it creates a worktree?

A worktree checks out files from its starting commit; it does not copy uncommitted or untracked project skills from the main checkout. Current Claude Code can load the main checkout’s project skills when the worktree has no root .claude/skills directory, subject to the version behavior described above.

Why does one skill appear in the worktree while another does not?

Check both the worktree’s committed skill paths and whether it has its own .claude/skills directory. On Claude Code v2.1.277 or later, that directory makes the worktree’s skills take the place of the main-checkout fallback, even if it contains only one of your skills.

Should a project skill go in ~/.claude/skills instead?

Use the personal directory when the skill should be available to you across local projects. Commit it under the repository’s .claude/skills/ directory when the team and the project’s worktree branches need the same instructions.

Is a missing slash command always a missing skill file?

No. A nested skill may not have loaded yet, a setting may hide it, or its command name may differ from the directory name. Check /skills and the file path before changing Git history.