Cowork desktop app: GitWorktreeManager runs `git add -A` on ancestor `.git` and leaks 8GB tmp_pack files every ~7 min until disk full

Resolved 💬 3 comments Opened May 1, 2026 by langers1980 Closed Jun 1, 2026

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?

Product: Claude Cowork desktop app (NOT Claude Code CLI)

The Cowork feature's GitWorktreeManager repeatedly spawns git add -A against whichever .git it discovers when walking up from a session's cwd. If the discovered repo is an ancestor far above the session's project (in my case $HOME/.git, an empty repo with zero commits), Cowork tries to stage the entire ancestor working tree (~100GB of caches, node_modules, VM bundles, etc.). The git child process exceeds Claude.app's internal timeout/maxBuffer and is killed — but the ~8GB partial pack file at <repo>/.git/objects/pack/tmp_pack_XXXXXX is never cleaned up.

Cycle repeats every ~7 minutes. In my case it leaked ~82GB (eleven 8GB orphans + one 1.5GB) before I noticed; total .git was 97GB. Free space went from ~90GB to 8.7GB before I caught it.

Live process signature when this is happening:

/Library/Developer/CommandLineTools/usr/bin/git \
  -c core.quotepath=false \
  -c safe.directory=* \
  -c core.fsmonitor=false \
  -c filter.lfs.smudge= -c filter.lfs.process= -c filter.lfs.required=false \
  add -A

Parent PID: /Applications/Claude.app/Contents/MacOS/Claude.

Source location (confirmed by extracting app.asar):

/Applications/Claude.app/Contents/Resources/app.asar.vite/build/index.js → class GitWorktreeManager. The flag set above matches the comment in the same file: "git-lfs not on PATH — disabling LFS filter for worktree operations (pointer files only)".

Two distinct defects:

  1. No scope check on the resolved repo. Cowork accepts any ancestor .git git resolves, even if (a) the repo has zero commits, (b) the repo root is many levels above the session's cwd, or (c) the repo root is $HOME / a system path. None of those should be staged.
  2. No cleanup on kill. When Claude.app's own timeout/maxBuffer kills the git child, the half-written tmp_pack_* is left behind. There's no unlink in the catch path.

The cleanup-on-kill bug alone would have downgraded this from a disk-fill outage to wasted CPU. The scope-check bug is the real prevention.

What Should Happen?

At minimum one of the following:

  • Bound the operation to the session's cwd subtree. Use git -C <cwd> add -- <cwd> rather than letting git resolve to an arbitrary ancestor.
  • Refuse to operate on the discovered repo if it looks unintended. Sane signals: zero commits, repo root equals $HOME or any path that contains the session's cwd through more than N intermediate directories, or the repo root is a path the user never explicitly opened in Cowork.
  • Clean up tmp_pack_* on kill/timeout. When Claude.app kills its own git child due to maxBuffer / timeout, the catch handler should unlink any tmp_pack_* it spawned, or pre-flight check disk space and abort early.

Any one of those would have prevented the disk-fill outage. Together they make the feature robust.

Error Messages/Logs

No error surfaced inside Claude.app — the failure is silent. Evidence is on the host filesystem and in `ps`:


$ df -h /
/dev/disk3s1s1   228Gi    11Gi   8.7Gi    57%   ...    /
# went from ~90GB free to 8.7GB free over ~1 hour

$ ls -lah ~/.git/objects/pack/tmp_pack_*
-r--r--r--  1 jarvis  staff   8.0G  May  1 17:38  tmp_pack_35UNxx
-r--r--r--  1 jarvis  staff   8.0G  May  1 17:46  tmp_pack_TnJofU
-r--r--r--  1 jarvis  staff   8.0G  May  1 17:54  tmp_pack_fsF2Cq
-r--r--r--  1 jarvis  staff   8.0G  May  1 18:02  tmp_pack_Ca4hZk
-r--r--r--  1 jarvis  staff   8.0G  May  1 18:09  tmp_pack_Om9zDE
-r--r--r--  1 jarvis  staff   8.0G  May  1 18:17  tmp_pack_A35EEK
-r--r--r--  1 jarvis  staff   8.0G  May  1 18:24  tmp_pack_uU93YE
-r--r--r--  1 jarvis  staff   8.0G  May  1 18:32  tmp_pack_vBoIwT
-r--r--r--  1 jarvis  staff   8.0G  May  1 18:40  tmp_pack_rV0JFL
-r--r--r--  1 jarvis  staff   8.0G  May  1 18:47  tmp_pack_V4OfP2
-r--r--r--  1 jarvis  staff   1.5G  May  1 18:51  tmp_pack_lRqekk
-r--r--r--  1 jarvis  staff   3.9M  May  1 18:57  tmp_pack_p0hQTq   # actively being written
# one new 8GB orphan every ~7-8 minutes

$ ps auxww | grep "git add -A" | grep -v grep
jarvis  3757  29.8  0.5  ...  /Library/Developer/CommandLineTools/usr/bin/git \
  -c core.quotepath=false -c safe.directory=* -c core.fsmonitor=false \
  -c filter.lfs.smudge= -c filter.lfs.process= -c filter.lfs.required=false \
  add -A

$ ps -o ppid -p 3757
 641   # /Applications/Claude.app/Contents/MacOS/Claude

$ du -sh ~/.git
 97G  ~/.git    # repo had ZERO commits — entire size is leaked tmp_packs


After `pkill -9 -f "git add -A"` and `rm -f ~/.git/objects/pack/tmp_pack_*`, free space recovered from 8.7GB to 91GB instantly. New tmp_pack started forming again within ~7 minutes — confirming Claude.app was the source.

Steps to Reproduce

Setup (one-time):

# 1. Create a rogue git repo at $HOME (or any ancestor of where you'll work).
#    Don't commit anything — leave the working tree as-is.
cd ~
git init

# 2. Create a project dir under that ancestor that is NOT its own git repo.
mkdir -p ~/Documents/test-project
cd ~/Documents/test-project
echo "hello" > file.txt
# When git walks up from here, it finds ~/.git

Trigger:

  1. Launch the Claude desktop app (NOT Claude Code CLI). My version: 1.5354.0.
  2. Start a Cowork session with the working directory set to ~/Documents/test-project.
  3. Leave it running.

Observe within ~7 minutes:

# 8GB orphan packs accumulating
ls -lah ~/.git/objects/pack/tmp_pack_*

# Active git process spawned by Claude.app
ps auxww | grep "git add -A" | grep -v grep
# Parent PID will resolve to /Applications/Claude.app/Contents/MacOS/Claude

# Disk filling
df -h /

Cleanup after testing:

pkill -9 -f "git add -A"
pkill -9 -f "git.*ls-files"
rm -rf ~/.git
rm -rf ~/Documents/test-project

My environment when this hit:

  • macOS, Apple Silicon
  • Claude desktop app: 1.5354.0
  • Claude Code CLI: 2.1.116 (separate, not the cause)
  • Git: /Library/Developer/CommandLineTools/usr/bin/git (Apple Command Line Tools)
  • Home directory contained an unintended ~/.git (created Feb 10, no commits) — likely from an accidental git init or earlier-version auto-init. With it removed, the leak stops because Claude.app no longer finds an ancestor repo to act on. Bug is latent without the trigger but still present.

Claude Model

Not sure / Multiple models

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

Claude Code version: 2.1.116

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

Related but distinct issue: #55246 ("Cowork bash workspace: VM disk full") is about Anthropic's server-side Cowork bash workspace VM filling up. This bug is different — it's the Cowork desktop client filling up the user's local Mac disk via leaked git pack files. Same symptom (disk full) but different layer and root cause.

Extracted source location for whoever picks this up:

  • File: Claude.app/Contents/Resources/app.asar.vite/build/index.js
  • Class: GitWorktreeManager
  • Method involved: the LFS-filter-disabling worktree operation path that builds the safe.directory=* + filter.lfs.* flag set, then invokes git add -A. The same file contains the comment: "git-lfs not on PATH — disabling LFS filter for worktree operations (pointer files only)".
  • The nbn / sn helpers in the same file run git child processes with t=5e3-style timeout / maxBuffer — when those fire, the tmp_pack_* orphan is left behind because there is no unlink in the catch path.

Suggested minimal fix priority:

  1. (highest impact, lowest risk) On every spawned git operation, register a kill-time cleanup that removes any newly created <repo>/.git/objects/pack/tmp_pack_* whose mtime is after the spawn time. Turns the worst case from "fills disk" into "wastes CPU."
  2. Refuse to operate on any resolved repo with zero commits — strong signal of an accidental ancestor .git.
  3. Bound git add to the session's cwd subtree (git -C <cwd> add -- <cwd>), or refuse to operate when the resolved repo root is $HOME or shorter than the session's cwd by more than a small threshold.

My account: clyde@mymastery.biz. Happy to provide logs, a packet capture of the loop firing, or any other diagnostic if useful.

Disclosure: this report was investigated and drafted with help from Claude Code (claude.ai/code).

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗