Codex Desktop subagent session logs grow to 145GiB from repeated compacted replacement_history

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

Codex Desktop subagent session logs grow to 145GiB due to repeated compacted replacement_history

Summary

Codex Desktop appears to persist full compacted.replacement_history snapshots repeatedly inside subagent rollout JSONL files. In one long parent thread with many subagents, this produced about 145.76GiB of subagent session logs while user/main session history for the same period was only about 5.5MiB.

This looks like a session-retention / compaction logging bug rather than useful work output growth.

Product / area

  • Product: Codex Desktop app
  • Platform: macOS
  • Observed local CLI version: codex-cli 0.142.5
  • Area: session storage, subagents, context compaction, retention policy
  • Data sensitivity: raw session files may contain private user/project content; this report only includes aggregate/redacted evidence.

Duplicate check

Searched existing openai/codex issues for:

  • replacement_history subagent session logs
  • session logs disk subagent

I found related session/performance issues, but not a direct duplicate for repeated compacted.replacement_history persistence in subagent rollout JSONL files.

Impact

  • ~/.codex/sessions grew to roughly 190G.
  • July sessions alone used about 146G.
  • The disk reached about 99% usage and left only about 10GiB free.
  • This blocks normal development/test workflows that need release builds, native UI verification, and longer runs.
  • The large raw logs are still registered as active/unarchived session files, so manual deletion is risky.

Observed evidence

Read-only inventory of <HOME>/.codex/sessions/2026/07:

  • Total indexed JSONL files: 641.
  • thread_source=subagent: 636 files, about 145.759GiB.
  • thread_source=user: 2 files, about 0.005GiB.
  • thread_source=automation: 6 files, about 0.002GiB.
  • Large subagent JSONL files >=1GiB: 71, total about 145.450GiB.
  • Current-day/open files were not modified or touched.

Representative largest subagent JSONL:

  • Raw file size: about 2.24GiB.
  • Lines: 156,005.
  • Top-level compacted records: 811.
  • context_compacted markers: 811.
  • compacted/replacement_history payload dominates storage.

Representative type breakdown:

type                            count   bytes_mib   pct
compacted                         811    2127.71   92.96
event_msg.token_count           73663      51.91    2.27
event_msg.thread_goal_updated   18278      36.97    1.62
event_msg.patch_apply_end        9153      22.01    0.96
event_msg.agent_message         46144      21.68    0.95
response_item                    2779      11.97    0.52
session_meta                      284       7.38    0.32
turn_context                     1672       2.46    0.11

Bounded scan of only the last 16MiB of each of the 71 large files:

  • task_complete seen in 69/71 files.
  • Evidence/tool/final-output refs are present, but tiny compared to repeated compaction payloads.

Expected behavior

Codex should not repeatedly persist full inherited replacement_history blobs per subagent/per compaction.

Expected alternatives:

  • Store only the current compacted summary state.
  • Store a digest/reference/backlink to an already persisted replacement history.
  • Store a delta instead of the whole inherited history.
  • Apply a retention policy that differentiates user/main chat history from subagent raw logs.

Actual behavior

Each large subagent rollout appears to persist full compacted.replacement_history snapshots repeatedly. In a long parent thread with many spawned subagents, this causes disk growth roughly proportional to:

number_of_subagents * number_of_compactions * replacement_history_size

This generated about 145.76GiB of subagent session logs from one parent-thread workflow.

Reproduction pattern

  1. Use a long Codex Desktop parent thread that has already gone through context compaction.
  2. Spawn many subagents from that parent thread.
  3. Let subagents continue far enough to compact context or persist inherited compacted context.
  4. Inspect <HOME>/.codex/sessions/<year>/<month>/<day>/rollout-*.jsonl.
  5. Compare thread_source=subagent file sizes and count top-level compacted records / replacement_history payload size.

Read-only checks used

The investigation only used read-only commands such as:

du -sh ~/.codex/sessions/2026/07
find ~/.codex/sessions/2026/07 -type f -name '*.jsonl'
stat -f%z <file>
head -n 1 <file>
rg -a -c '"type":"compacted"' <file>
rg -a -c '"replacement_history"' <file>
sqlite3 -readonly ~/.codex/state_5.sqlite 'select thread_source, archived, count(*) from threads ...'
lsof +D ~/.codex/sessions/2026/07

Raw session files were not deleted, moved, edited, or attached.

Safety note

Please do not request raw .codex/sessions files unless there is a private upload channel. They contain private project/user content. A redacted ledger with aggregate counts can be provided.

Suggested fix direction

  • Deduplicate compacted.replacement_history across subagent rollouts.
  • Avoid storing full inherited replacement histories inside every child rollout.
  • Add a bounded retention policy for subagent raw JSONL.
  • Add a storage guard/alert when session logs exceed a threshold or when compacted payload dominates a rollout file.
  • Make app-level archive/export handle subagent logs safely without breaking thread resume.

View original on GitHub ↗

10 Comments

github-actions[bot] contributor · 1 month ago

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

  • #30779
  • #30932

Powered by Codex Action

Revulf01 · 1 month ago

Thanks for the duplicate pointers. I reviewed #30779 and #30932, and I agree this issue is related to both, but I do not think it is only a size-only duplicate.

The additional signal in this report is the combined failure mode:

  • Codex Desktop + subagent storage: the large growth was concentrated in subagent session JSONL/history, not ordinary main chat history.
  • Repeated compacted.replacement_history payloads: the dominant multiplier appeared to be repeated full replacement-history snapshots inside compacted records.
  • Aggregate fan-out across many subagents: in the observed case this was spread across many subagent session files, not just one huge rollout.
  • Multiplicative growth pattern: roughly number_of_subagents * number_of_compactions * replacement_history_size.
  • Main/user history stayed tiny by comparison: this points to subagent compaction persistence rather than normal conversation history growth.

So my current read is:

  • #30779 covers the broader “subagent/fork session histories are retained and can grow very large” class.
  • #30932 covers the “repeated compacted records / replacement history can make resume or session loading pathological” class.
  • This issue adds a concrete Desktop repro where those combine into a multiplicative subagent-storage blowup, observed at ~145GiB.

If maintainers consider one of the other issues canonical, I am fine with closing this as a duplicate, but I think the Desktop subagents × compactions × replacement_history multiplier and the ~145GiB aggregate evidence should be kept attached to the canonical issue.

frontierkodiak · 1 month ago

Independent repro on Codex 0.144.6: one snapshot interval added 27.69 GB of rollout JSONL; 97.2% came from subagent rollouts. 15,983 inline-image occurrences consumed 23.63 GB, but represented only 69 unique values totaling 91.2 MB: 259× byte amplification. The two most frequent payloads were serialized 4,925 times each. Structural accounting only; no transcript text or image contents were inspected.

valtterivalo · 1 month ago

another data point on codex desktop 0.146.0-alpha.3.1 macos

one subagent rollout is 256 MB over 42765 lines
compacted is 254 records and 189 MB of that
session_meta is 519 records and 20.7 MB

the session_meta part looks separate from what is already in this thread
all 519 have the same session_id and each one repeats base_instructions at 21 KB and dynamic_tools at 20 KB

replacement_history itself stays bounded at around 212 entries and 430 KB so the compacted growth is the same snapshot written 254 times in a 33 minute session

in the last snapshot 210 of the 212 entries have role user
this was a read only review subagent that never sent a user message
if the rewritten history counts as user input then the next window fills straight away

no images in any of my files so this is not the inline image path
older ones look the same, 448 MB with 255 compacted records and 355 MB with 106

structural counts only, no transcript content inspected

winstally · 1 month ago

Additional reproduction on macOS / Codex CLI 0.145.0

I found the same compaction-persistence pattern in a current macOS installation. This is a structural, redacted report; no raw rollout files are attached because they contain private prompts, paths, tool output, and project data.

Impact

  • ~/.codex is approximately 362 GB.
  • ~/.codex/sessions is approximately 354 GB across 6,596 JSONL files.
  • July 2026 sessions alone account for approximately 309 GB.
  • July 21: approximately 133.7 GB across 234 files.
  • July 22: approximately 128.6 GB across 188 files.

Representative rollout

One representative JSONL file was:

  • 1,223,109,593 bytes (~1.14 GiB)
  • 29,373 lines
  • 122 top-level compacted records
  • compacted records totalled 1,141,482,978 bytes (~93.3% of the file)
  • event_msg and response_item data were comparatively small

The 122 compacted records were appended within approximately 0.88 seconds (from 2026-07-22T01:19:32.543Z to about 2026-07-22T01:19:33.422Z), averaging about 9.36 MB per record. A second sampled rollout was approximately 1.09 GB with 108 compacted records accounting for approximately 92.1%.

This is not normal growth from useful conversation output. The rapid burst strongly suggests that a compaction result is being persisted and then reprocessed or persisted again before the compaction cycle terminates.

Trigger and local logs

The affected workflow was a long multi-agent/inter-agent session. Local logs show the compaction path entering ContextLimit and codex_core::compact_remote_v2::attempt, including messages indicating that history outputs were rewritten before remote compaction v2.

The installed CLI reports:

codex-cli 0.145.0

The largest observed growth began before the local 0.145.0 package update, so this should be treated as an affected-version/current-regression data point rather than proof that the package update alone introduced the bug.

Expected behavior

After compaction, Codex should persist one bounded current state, a delta, or a reference to an existing compacted state. Previous compacted snapshots should not themselves become repeated input to another full snapshot. There should also be a per-rollout/per-session storage guard or retention policy.

Actual behavior

A long multi-agent session that reaches ContextLimit can append repeated full compacted snapshots to the append-only JSONL history. In the observed case this produced hundreds of gigabytes of session data and at least one active rollout of approximately 2.66 GB.

Reproduction pattern

  1. Run a long Codex Desktop/CLI task with multiple agents or inter-agent communication.
  2. Continue until automatic compaction is triggered by ContextLimit.
  3. Inspect the corresponding rollout JSONL structurally (record types and byte sizes only).
  4. Observe multiple large compacted records, sometimes emitted in a tight burst.
  5. Continue the task and observe that the session file keeps growing primarily from compacted records.

Please do not request raw session files publicly; they contain private data. I can provide further redacted aggregate statistics or a synthetic reproduction if needed.

Tom-R-Main · 14 days ago

Severe single-fork case: 153 MB child rollout in 64 seconds, followed by memory exhaustion and a forced reboot

I hit what appears to be the same subagent/compaction persistence bug on a 24 GB Apple Silicon Mac. In this case, the trigger was one successful spawn_agent call with fork_turns="all" from a large, image-heavy parent task.

The parent rollout was already 2.77 GB. The new child grew to 153 MB in about 64 seconds and immediately began repeating the parent's image-bearing compaction pattern. Shortly afterward, ChatGPT/Codex climbed to roughly 34 GB, macOS became unresponsive, and I had to force a restart.

Environment

  • Codex Desktop inside the ChatGPT macOS app
  • App version: 26.803.61601 (build 6396)
  • Chromium framework: 151.0.7922.76
  • Affected rollout metadata version: codex-cli 0.147.0-alpha.6.5
  • Platform: Darwin 25.5.0 arm64 arm
  • macOS: 26.5.1 (25F80)
  • Physical memory: 24 GiB
  • Parent session: 019fe255-8774-7091-bbc5-ad106a42aed4
  • Child session: 019ffd06-f6c9-7653-8ac4-e2f72e77d764

The child metadata identifies the parent and the subagent path /root/repair_osint_journey.

What happened

Times below are local, UTC-04:00, on August 13, 2026.

| Time | Event |
|---|---|
| 17:28:33.933 | Codex persisted the successful spawn_agent request with fork_turns="all". |
| 17:28:39.909 | Child session metadata timestamp. |
| 17:29:10 | Child rollout created on disk. |
| 17:30:14 | Child rollout last modified. |
| 17:30:15 | Parent rollout last modified. |
| 17:30:43 | macOS created .JetsamEvent-2026-08-13-173039.ips. The file is empty, apparently because collection did not finish before the restart. |
| 17:55:10 | Machine rebooted. I found no orderly shutdown entry or kernel panic report. |

The child never reached the implementation work it had been assigned.

Rollout measurements

Parent

| Metric | Value |
|---|---:|
| File size | 2,770,032,159 bytes |
| JSONL records | 24,530 |
| Top-level compacted records | 50 |
| Bytes in those records | 2,539,635,323 (91.68% of the file) |
| Largest single compacted record | 93,957,345 bytes |
| Compacted records containing data:image | 50 / 50 |
| SQLite tokens_used | 872,191,112 |

Child

| Metric | Value |
|---|---:|
| File size after about 64 seconds | 153,405,788 bytes |
| JSONL records | 1,198 |
| Top-level compacted records | 10 |
| Bytes in those records | 106,648,439 (69.52% of the file) |
| Largest single compacted record | 31,264,650 bytes |
| Compacted records containing data:image | 10 / 10 |
| SQLite tokens_used | 77,804,368 |

The token counts are included as evidence of repeated context processing. They should not be read as unique generated-text tokens.

The clearest signal here is the child's behavior: one full-history fork created a 153 MB rollout in roughly a minute, before doing useful work, and all 10 of its compaction records contained inline image data.

Other system evidence

The incomplete August 13 Jetsam artifact cannot tell us which process held the memory during the fatal event. A completed Jetsam report from August 12 on the same installation shows that this was not the first serious memory-pressure event:

  • The Codex/ChatGPT process coalition occupied 24.091 GiB on a 24 GiB machine.
  • One codex process had peaked at 22.147 GiB.
  • The coalition contained 286 processes, including 180 node, 29 node_repl, 24 python3.10, and 23 uv processes.

Two macOS diagnostics from August 11 also attributed heavy disk writes to codex:

  • 34.36 GB over 3,198 seconds, with a maximum footprint of 18.81 GB.
  • 137.44 GB over 8,735 seconds.

Those earlier reports are supporting evidence only; they are not measurements from the exact August 13 failure window. The unusually large process tree may also point to the cleanup problem reported in #12491, but I cannot show that it caused this particular crash.

Why this looks like a fork/compaction amplification bug

I compared the rollout evidence with openai/codex at origin/main commit 85f331772f54a9d518fefa6b1596cbde8cd78fd1. The installed app may not be byte-for-byte identical to that commit, but the current source describes the same sequence visible in these files:

  1. fork_turns defaults to all, which maps to FullHistory.
  2. The subagent path materializes and loads the parent model context, then gives it to the child as InitialHistory::Forked.
  3. Fork persistence defaults to Copied, and the non-paginated path writes the inherited prefix into the child's rollout.
  4. Compaction clones the replacement history into a new persisted record. In remote compaction v2, images and audio count as zero tokens and are kept when text is truncated.

In other words, an image-bearing replacement history can be copied from parent to child and then cloned again each time the child compacts. This case connects the behavior reported in #36557, #33493, and #34863.

Expected behavior

  • A full-history subagent fork should not copy a multi-gigabyte parent history into a new rollout.
  • If the parent exceeds a safe byte or image limit, Codex should refuse the fork or use a bounded recent tail and summary.
  • Compaction should not serialize the same inline image data into every new checkpoint.
  • Opening, resuming, or forking one oversized task should fail gracefully instead of exhausting the whole machine.
  • Completed subagents should not leave their MCP, Node, or Python process trees running.

Reference-backed fork persistence looks like the natural fix for the first part. Large images should also be stored once and referenced by ID or content hash, with explicit limits on the number and encoded size retained during compaction.

A useful regression test would create an image-bearing compacted parent, spawn one fork_turns="all" child, compact that child several times, and assert that both rollout size and process memory remain bounded.

Privacy note

I cannot attach the raw rollout files publicly. They contain private project history, screenshots, prompts, local paths, and tool output. I can provide the following through a private OpenAI upload channel:

  • Redacted Jetsam and disk-write diagnostics.
  • A structural ledger of JSONL record types, sizes, timestamps, and image-marker counts.
  • Sanitized process-coalition counts.
  • The parent and child session IDs listed above for internal correlation.
shleder · 14 days ago

The 145.76 GiB of subagent rollouts is a strong bounded-diagnostics case, especially the 2.24 GiB child with 811 persisted replacement_history snapshots and terminal events near the tail.

I’m testing whether Codex Rescue can enumerate and inspect this real session tree without loading or copying full histories. It will not prune subagents, compress records, or modify active/unarchived rollouts. The source remains untouched and any uncertain continuation state stays fail-closed.

If the retained files are still available, could you run:

pipx install codex-rescue==0.1.0a3
codex-rescue sessions
codex-rescue doctor --latest

Sanitized counts/status only are sufficient—please don’t share JSONL, databases, tool output, prompts, project content, private paths, or secrets.

https://github.com/shleder/codex-rescue

binaryanomaly · 10 days ago

Confirmed this is still reproducible in the current ChatGPT desktop build:

  • ChatGPT for macOS 26.810.52044 (build 6662)
  • Bundled codex-cli 0.148.0-alpha.9
  • macOS 26.6.1 (25G76)

On 2026-08-17, ~/.codex had grown to about 309 GiB, leaving the disk 99% full with about 12 GiB free. The normal app log directory was only about 64 MiB. Almost all usage came from rollout JSONL files:

  • 89 rollout files larger than 250 MiB
  • about 304.6 GiB combined
  • deleting 87 closed rollout files recovered about 292 GiB
  • two files still open by Codex were intentionally left untouched, totaling about 12.7 GiB

A representative 5.48 GiB rollout had thread_source: subagent, multi-agent v1, and was forked from an older parent task. It contained:

  • 1,119 replacement_history records
  • 1,118 compacted records
  • about 5.18 GiB, or 94.6% of the file, in compacted records
  • 628 records containing inline image data or input_image

This appears to be the same repeated compacted.replacement_history growth reported here. The image duplication aspect also overlaps #39013, which reports the same desktop app/build, and the full-history fork behavior described in #34268.

I have not attached the raw rollout files because they contain private conversation and image data. I can provide additional sanitized counts if useful.

teamleaderleo · 2 days ago

Confirming repeated compacted.replacement_history growth on a current Desktop build:

  • ChatGPT Desktop 26.818.61809 build 7019
  • bundled codex-cli 0.149.0-alpha.4.3
  • macOS 26.6.1 (25G76), arm64

A reproducible, modification-time-fenced scan of 368 local rollouts produced:

total storage:             34,059,784,421 bytes (31.72 GiB)
compacted records:         6,246
compacted storage:         28,319,667,945 bytes (26.37 GiB)
compacted share:           83.1%
with replacement_history:  6,246 of 6,246
files >= 1 GiB:            8
largest compacted record:  63,397,531 bytes

The scan retained only structural classes and byte counts; it excluded transcript content, paths, filenames, thread IDs, and timestamps.

Each of the eight ≥1 GiB rollouts was 91.4–94.8% compacted records by byte size. The largest was a 13.26 GB root/VS Code rollout, with 12.12 GB in 399 compacted records. The next seven were subagent rollouts. This shows that the same storage multiplier affects both inherited child histories and root threads.

A 202 MB rollout in the same store was only 1.4% compacted by byte size, providing a negative control for the classifier.

Current public source at c3953649156e15b67e572cb9e38bc825a811c24e still:

  1. constructs each checkpoint using replacement_history: Some(items.clone());
  2. appends the checkpoint without replacing earlier payloads;
  3. loads the complete rollout into a Vec on the full-history path.

Cold compression and retained-image budgeting are useful partial mitigations, but they do not bound active rollout growth or repeated non-image replacement histories.

The storage invariant should be:

H bytes of stable replacement history + N compactions
  -> O(H + N × checkpoint metadata), not O(N × H)

One implementation direction is to persist immutable checkpoint payloads once and let compacted records reference them. The corresponding regression should repeatedly compact a stable large history and assert sublinear physical growth.

The remaining design boundary is preserving resume, rollback, fork, window-lineage, world-state, and late-suffix behavior while making checkpoint storage proportional to unique retained history.

shleder · 1 day ago

Confirming the replacement_history growth shape here as well. For measurement: vetto rescue --json scan reports per-session bytes read-only, which makes the compaction-amplification claim concrete (before/after numbers per thread) without touching provider state.