Claude Code Worktree Git LFS Pointer Files: How to Fix Them
Prepared and checked using AI. Sources are linked in the article.
Claude Code worktree Git LFS pointer files usually mean the LFS content was not substituted during checkout. A specific cause is a repository configured with git lfs install --local: Claude Code skips repository-local filter drivers while creating a worktree, so the new directory can contain pointers even when the main checkout contains full files. From inside the affected worktree, run git lfs pull; it downloads LFS objects for the checked-out ref and updates the working copy.
What the pointer means
Git LFS stores small pointer files in Git and keeps the corresponding file content separately. A pointer commonly begins with version https://git-lfs.github.com/spec/v1. Seeing that text when an agent opens an asset does not, by itself, mean Claude edited or damaged the asset. It means the working copy currently contains the reference Git stores, rather than the content the task needs.
A linked Git worktree has its own working files and index while sharing repository data with the main checkout. The full asset appearing in the main checkout therefore does not guarantee that the new worktree’s copy has been populated. Treat each worktree as a separate working directory when checking whether an agent can read a model, fixture, image, or other LFS-tracked file.
Git normally invokes an LFS smudge filter during checkout to replace a pointer with content. If that step is skipped, the pointer remains. Claude Code’s treatment of repository-local filters is intentional: a filter driver is a shell command configured in repository data that something with write access to the repository could change. The worktree documentation identifies this behavior for git lfs install --local and says versions before 2.1.247 ran those drivers during creation. Other reasons for pointers include an LFS installation that skips smudging, an environment setting that skips it, a path excluded from LFS fetching, or a download error. Diagnose those separately rather than assuming every pointer has the same cause.
Fetch the files in the affected worktree
Use the directory where Claude will work. For example, if a named session created .claude/worktrees/asset-fix/, run:
cd .claude/worktrees/asset-fix
git lfs pull
git lfs ls-files
The example name and path are illustrative; use the path of your actual worktree. git lfs pull applies to the currently checked-out ref. It combines an LFS fetch with checkout, so a successful download can replace eligible pointers in that working copy. In git lfs ls-files, * indicates a full object and - indicates a pointer. Check the paths your agent needs, then open one of those files to confirm it contains the expected content before asking the agent to process it.
If the object is already in local LFS storage and the working file is still a pointer, the command git lfs checkout can populate it without downloading:
git lfs checkout
That command only fills missing files or matching placeholder pointers for objects available locally; it does not overwrite modified files. If the object is absent locally, use git lfs pull instead. Do not replace a file that contains an agent’s edits merely because it appears in an LFS file list; inspect the change first.
Find out why the pointer remained
Start with the file and the worktree, not the main checkout. For example, substitute a real LFS-tracked path for assets/model.bin:
pwd
git lfs ls-files
git check-attr filter -- assets/model.bin
git config --show-origin --get filter.lfs.process
git check-attr reports the attributes applied to a path. A filter: lfs result supports treating that path as an LFS file. If it does not have the LFS filter, check the committed .gitattributes rules and the path’s spelling before treating the text as a missing download. git lfs ls-files helps establish whether LFS recognizes the file on the current branch.
git config --show-origin prints the configuration value’s source. If filter.lfs.process comes from the repository’s .git/config, the setup matches Claude Code’s documented repository-local filter case. A value sourced from the global configuration points elsewhere; it does not rule out a skipped download or an LFS fetch setting. If the command prints nothing, inspect how LFS was installed for this user account.
Check settings that deliberately leave pointers or limit downloads:
git config --show-origin --get lfs.fetchinclude
git config --show-origin --get lfs.fetchexclude
git config --show-origin --get lfs.skipdownloaderrors
The lfs.fetchinclude and lfs.fetchexclude settings restrict which paths are fetched. A configured lfs.skipdownloaderrors can allow checkout to succeed while files whose downloads failed remain pointers. Also check whether the shell or the process that launched Claude sets GIT_LFS_SKIP_SMUDGE; when true, that environment variable tells LFS to skip pointer conversion during checkout.
If those git config queries return nothing or do not explain the behavior, inspect .lfsconfig in the worktree. Git LFS also reads lfs.fetchinclude, lfs.fetchexclude, and lfs.skipdownloaderrors from that file, but the queries above do not read it automatically. When the file is present, display its settings with:
git config --file .lfsconfig --list
If .lfsconfig is absent from the working tree, inspect its copy in the index or HEAD: Git LFS can read those copies too. Settings in Git configuration files take precedence over .lfsconfig. These settings may be deliberate, especially in a repository with assets that most tasks do not need. Change them only if they conflict with the files this worktree requires.
If git lfs pull reports an error, use its error message to investigate the remote, credentials, or unavailable object. Repeating git lfs checkout cannot solve a missing local object because that command performs no download. A pointer still present after a successful pull also warrants checking the file’s attributes and any include or exclude rules.
Choose between automatic and selective downloads
Plain git lfs install configures the LFS filters globally, while git lfs install --local places them in the repository’s Git config. Claude Code’s worktree behavior distinguishes those locations. If you want automatic LFS conversion when new Claude worktrees are created, a global LFS filter setup avoids the specific repository-local filter issue. git lfs install also installs a pre-push hook for the current repository when run inside one, so account for that change before using it as a setup command.
Running plain git lfs install does not remove existing repository-local filter.lfs definitions. If you previously used git lfs install --local, review those definitions before relying on global filters:
git config --local --get-regexp '^filter\.lfs\.'
After confirming the global filters are configured and every local entry shown is redundant, remove the local filter.lfs section and check the origins again:
git config --local --remove-section filter.lfs
git config --show-origin --get-regexp '^filter\.lfs\.'
The remaining LFS filter definitions should come from global configuration. If repository-local definitions remain, Claude Code can still encounter the condition that causes pointers during worktree creation.
Keeping repository-local filters can also be a deliberate choice. In that case, make git lfs pull part of worktree preparation, before the agent reads LFS-backed inputs. This keeps the policy explicit: create the worktree, enter it, fetch the needed objects, verify the needed paths, and then start work. For more on which parts of a repository are separate across worktrees, see Git worktrees explained.
You can fetch only paths needed for a task. For example, to populate one illustrative asset while overriding an existing exclude rule for this invocation:
git lfs pull -I "assets/model.bin" -X ""
-I supplies an include pattern, and the empty -X clears the exclude value for that command. Check the pattern against the repository path; an include that misses the file will leave its pointer in place. Fetching only required assets reduces unnecessary transfers, but it also means the agent must not assume every LFS-backed file in the worktree is ready. When assigning separate tasks to several Claude sessions, record the required assets for each one; the broader workflow is covered in running multiple Claude Code agents in parallel.
Where Parallel Code fits
Parallel Code is our free, open-source desktop app for running Claude Code and other AI coding agents in parallel, each in its own Git worktree. Its diff-first review surface helps you review their changes. If a task needs LFS content, prepare the relevant worktree with git lfs pull before its agent reads those files.
Frequently asked questions
Why does the main checkout have the full file while Claude’s worktree has a pointer?
The worktrees have separate working files. If Claude Code skipped a repository-local LFS filter when it created its worktree, that worktree can retain the pointer even though the main checkout already contains full content. Run git lfs pull inside the affected worktree.
Does git lfs checkout fetch a missing asset?
No. It uses LFS objects already available locally to fill eligible files in the working copy. Use git lfs pull when the object needs to be downloaded.
Should I run git lfs install --local again to fix the worktree?
That repeats the configuration associated with Claude Code’s documented worktree case; it does not populate an existing pointer. Fetch the content inside the worktree with git lfs pull, then decide whether global filter setup or an explicit pull during worktree preparation fits your repository. If you switch to global filters, review and remove redundant local definitions too.
Why is one file still a pointer after git lfs pull?
Check that its path has filter: lfs, that it appears in git lfs ls-files, and that include or exclude settings in Git configuration or .lfsconfig allow it to be fetched. If the pull reported an error, resolve that error first; git lfs checkout cannot download an object that is missing locally.