Codex turn-diff checkpoint blobs silently consume 100+ GB disk space

Open 💬 2 comments Opened Jun 22, 2026 by lg320531124
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

Summary

Codex Desktop creates refs/codex/turn-diffs/checkpoints/ refs that store full project tree snapshots as git objects. On projects with large files (databases, models, binary artifacts), these checkpoint blobs accumulate without any garbage collection, silently consuming massive disk space.

In my case: 102 GB of orphan git objects accumulated in a single project ~/.git/objects/ directory, bringing total project size from ~5.7 GB to ~140 GB.

Version

  • Codex Desktop 26.616.51431 (App Store build 4212)
  • Codex CLI 0.80.0
  • macOS Darwin 27.0.0 arm64

Impact

Disk exhaustion. Unlike #28241 which reports that turn-diff refs break libgit2 clients, this issue focuses on the disk space bomb created by the underlying git objects.

Reproduction

  1. Open a project directory with Codex Desktop where the project contains large files (e.g., .db, .bin, .sqlite, model weights, node_modules, etc.)
  2. Use Codex normally for several sessions
  3. Observe .git/objects/ growing unboundedly

What Happened

My ~/project directory (a trusted Codex project) accumulated:

$ git count-objects -vH
count: 8476
size: 101.86 GiB     <-- 8476 loose objects totaling 102 GB
in-pack: 6459
packs: 1
size-pack: 4.64 MiB

The repo had zero commits and zero staged files — all 8476 loose objects were orphans. 429 of them were individual blobs exceeding 100 MB each (largest ~244 MB), all binary content.

The only refs were Codex checkpoint refs:

refs/codex/turn-diffs/checkpoints/dc36a859.../.../476a1d45-...
refs/codex/turn-diffs/checkpoints/e31f75308.../.../99b0aa92-...

Root Cause Analysis

Based on source code review of codex-rs/git-utils/src/baseline.rs:

  1. write_tree() recursively walks the entire project directory
  2. For every file, it calls repo.write_blob(bytes) — writing the full file content as a git loose object
  3. This happens on every checkpoint/capture operation
  4. Large binary files (databases, model weights, etc.) each become 100MB+ loose objects
  5. No garbage collection or pruning is performed after checkpoints are superseded
  6. Git default gc.pruneExpire is 2 weeks, but Codex never triggers git gc or git prune

The same write_blob behavior appears in current_file_entries() which also reads every file into memory to compute blob OIDs for diffing.

Workaround

# Nuclear: delete .git and reinitialize
rm -rf .git && git init

# Or: prune orphan objects
git gc --prune=now

After cleanup: 140 GB → 5.7 GB.

Suggested Fixes

  1. Add .gitignore awareness: The write_tree() function in baseline.rs skips .git but nothing else. It should respect the project .gitignore to avoid writing blobs for node_modules/, .db files, model weights, etc.
  1. Size limits: Skip files above a configurable size threshold (e.g., 10 MB) when writing checkpoint blobs.
  1. Garbage collection: After creating new checkpoints, prune old/superseded checkpoint refs and their unreachable objects.
  1. Use separate git repo: Store checkpoints in a separate bare repo under ~/.codex/ (similar to how codex-rs/memories/ uses codex_home/memories with its own git baseline), rather than polluting the user project .git/objects/.
  1. Dont write blobs for diff computation: The test status_scan_does_not_write_added_file_blobs explicitly verifies diff scans do not write objects, but write_tree() does. The checkpoint path should use hash-only approach.

Related Issues

  • #28241 — turn-diff refs break libgit2-based Git clients (same refs/codex/turn-diffs/ mechanism)
  • #28750 — Codex.app repeatedly runs git add -A filling .git/objects/pack (same disk space impact, different mechanism)
  • #19588 — Ghost snapshot runs git add -A on trusted home directory (same root cause: uncontrolled git object creation)
  • #12644 — Excessive file I/O from Codex scanning

View original on GitHub ↗

2 Comments

github-actions[bot] contributor · 2 months ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #28241
  • #28847

Powered by Codex Action

ethanhawkes-gif · 25 days ago

We hit the same shape of problem (multi-GB .git/objects with git status clean) from a different writer — large files that entered the object store and were never referenced by any commit — and can offer the diagnosis + safe-reclaim recipe that worked, with numbers.

Confirm what the space actually is — two independent measurements that should agree:

# loose object count + size
git count-objects -v          # 'count' and 'size' (KiB) = loose objects

# what fsck thinks is unreachable
git fsck --unreachable --no-reflogs | sort | uniq -c | sort -rn | head

If you want the set-difference proof: git cat-file --batch-all-objects --batch-check minus git rev-list --objects --all gives you exactly the orphans. In our case: 4.3GB .git, of which 4.20GB was 5,050 unreachable blobs; only 9.9MB of loose objects were reachable. The largest unreachable blobs exactly size-matched files still in the working tree — i.e. the content was duplicated into the object store, not unique data at risk.

Before pruning, check nothing you need lives only in the object store:

git stash list                                  # stashes keep objects alive via reflogs
git fsck --unreachable | grep -v blob           # unreachable COMMITS may be work you want

Reclaim:

git gc --prune=2.hours.ago     # or --prune=now if you're confident

Result for us: .git 4.3GB → 6.5MB, git fsck clean afterwards, HEAD and all working-tree files intact. The reason the space survives normal operation is gc.pruneExpire's two-week grace period for loose objects — orphans younger than that are deliberately kept.

Caveats for this issue specifically: this reclaims the 102GB but won't stop Codex from re-creating snapshots — that half is genuinely upstream's to fix. And if you want a tripwire while waiting: alert on git count-objects -v loose size, which catches the accumulation long before it's 102GB.