Skip to content

Codex Desktop: screenshots re-persisted in full on every compaction and inherited by subagent forks - ~/.codex/sessions reached ~165 GiB (95% base64 images) #35458

Description

@viborc

What version of the Codex App are you using (From “About Codex” dialog)?

Version 26.721.41059

What subscription do you have?

Pro ($200)

What platform is your computer?

Darwin 25.5.0 arm64 arm

What issue are you seeing?

ChatGPT Desktop's bundled Codex persisted ~165 GiB of session JSONL under ~/.codex/sessions (Codex's own scan reported 176.7 billion bytes), driving my 460 GB Data volume to ~99% capacity and putting unrelated writes at risk.

There is no error message - the failure mode is silent. I got no warning, quota, retention policy, or UI surfacing of session storage exists. The only user-visible symptoms were the disk filling at a sustained ~21 GB/hour (four ~2.6 GiB rollouts in ~28 minutes, three of them within a single minute) and df approaching 100%.

I diagnosed the files with privacy-safe sampling (line-length histograms via awk, structure via jq on small samples - never loading full files).

Measured root cause:

1. The bytes are overwhelmingly repeated screenshots.

I'm sharing some representative 2.64 GiB rollout:

Metric Value
JSONL records 35,826
Lines < 1 KiB 30,356
Lines between 1 and 16 MiB 184
Largest single line 16,711,982 bytes
Inline image occurrences 6,412
Unique images 555
Mean copies per unique image ~11.6
Total base64 characters 2,703,184,704
Share of file that is base64 image payload 95.41%

2. The duplication lives in compacted replacement history.

Here's the byte attribution by field path:

Field path Approx. characters
payload.replacement_history[].content[].image_url (in type: "compacted" records) 2.55 × 10⁹
payload.result.Ok._meta["codex/toolSurface"].screenshot.url 1.37 × 10⁸
payload.content[].image_url 1.6 × 10⁷

Payloads are data:image/png;base64,… data URLs. My ~/.codex/computer-use/ directory is only 60 MB while transcripts are gigabytes - screenshots are inlined into the JSONL rather than stored once and referenced.

3. Each compaction appends another near-complete copy. Verified on the live root rollout: same inode (73927096) throughout, SHA-256 of the first 1 MiB unchanged, size grew 3,118,851,621 → 3,135,728,720 bytes with only the tail changing. So the file is physically append-only; the amplification is that every new compacted record can carry a near-full copy of the image-bearing replacement_history.

4. Subagent forks multiply the inflated context. Three subagents created within 60 seconds (23:34:16, 23:34:45, 23:35:16) each have distinct session IDs, thread_source: "subagent", and the same forked_from_id pointing at the giant parent - and each materialized its own ~2.6 GiB rollout (~7.8 GiB written by one fork action). Verified these were deliberate forks, not crash restarts: same continuously-running app-server writer, no process restart, no macOS crash report, no fatal/OOM/termination event in system logs.

5. Scale. The root session (created 2026-07-11) accumulated, through resumes and forks, a family of 329 sessions totaling ~164 GiB by 2026-07-26 - essentially the entire store.

Configuration ruled out: history.persistence unset (default save-all); history.max_bytes unset (and per docs applies to the prompt history file, not rollouts); RUST_LOG=warn; no OTel exporters; no screenshot-retention or verbose-logging options enabled. I found no documented setting that caps rollout size, strips/externalizes images during compaction, or imposes any quota or retention on ~/.codex/sessions.

Related: #24388 (closed), #24948 (closed), #34061 (open) - detailed comparison under Additional information. In short, this report shows the image-retention behavior of #24388 persisting in 0.145.0-alpha.18 on the Desktop surface (all prior reports are CLI/TUI), amplified by the subagent pattern of #34061.

What steps can reproduce the bug?

Observed workflow (this is not a minimal deterministic reproducer so keep that in mind):

  1. In ChatGPT Desktop, run a long-lived Codex task that drives a browser / computer-use surface taking screenshots. ine was running for multiple days (longer WordPress to Hugo migration project)
  2. Keep working in (resuming) that same thread until remote compaction has occurred many times.
  3. Inspect the newest type: "compacted" records in the session rollout under ~/.codex/sessions/YYYY/MM/DD/: payload.replacement_history[].content[].image_url will contain repeated data:image/png;base64,… payloads.
  4. Spawn subagents from this session with inherited context; each child rollout materializes at roughly the parent's inflated size.

The controlling variables are compaction count × image count, not session length.

I'm sharing two sessions from the same evening, same version, same workload type:

Control (22:26) Failure case (23:07)
File size 48.4 MiB 2.64 GiB
Base64 share 96.54% 95.42%
Unique images 38 543
compacted records 3 232

A 54× size difference within 40 minutes with the storage format unchanged. Context-window usage: the failure-case session repeatedly hit the context limit - 232 remote compactions - and each compaction persisted another near-complete copy of the image-keeping history.

Session IDs (most files since deleted via the supported codex delete path to recover the disk; IDs provided for correlation with any server-side logs):

  • Root / parent thread: 019f5098-3b7d-7a23-bd3a-7027dd7eef7b (created 2026-07-11T11:53Z)
  • Failure-case rollout sampled above: 019f9b33-43fd-7321-bdf0-a579840349d5 (2.64 GiB)
  • Sibling subagent forks (~2.6 GiB each, same forked_from_id): 019f9b33-b6f4-7ef1-9791-01c7fc82215a, 019f9b34-300b-7e01-a4c9-14bbdbbd1de6
  • Earlier same-evening 2.6 GiB session: 019f9b1a-e255-7df2-8635-73368e0bcf5d
  • Preserved control sample (48.4 MiB, retained as evidence): 019f9af4-fd7d-71c1-8f82-095825e66f48

Privacy-safe inspection commands (report sizes/structure without printing content):

# Overall usage and large files
du -sh ~/.codex ~/.codex/sessions
find ~/.codex/sessions -type f -size +500M -exec ls -lh {} \;

# Line-length histogram of a rollout (finds the multi-MiB lines)
awk '{ n=length($0); if (n>1048576) big++; else small++; if (n>max) max=n }
     END { print small" lines <1MiB, "big" lines >1MiB, largest "max" bytes" }' path/to/rollout.jsonl

# Record types on a sample, no payload content
head -50 path/to/rollout.jsonl | jq -r '.type' | sort | uniq -c

# Confirm image data URLs inside compacted replacement history (prints only counts)
grep -c '"type":"compacted"' path/to/rollout.jsonl
grep -o 'data:image/png;base64' path/to/rollout.jsonl | wc -l

What is the expected behavior?

  • Compaction should not re-persist raw historical image payloads in full on every compacted record. Binary payloads should be stored once (content-addressed, or as files under e.g. computer-use/) and referenced from the transcript.
  • Subagent forks should not inherit and re-serialize the parent's full binary history; a bounded or text-only handoff should be the default - I had to limit the number of agents working in parallel to keep this manageable
  • Session storage should be bounded: per-session and global quotas, retention/rotation, and a user-visible warning before storage becomes critical.
  • A screenshot-heavy session of ordinary length should not be able to silently consume hundreds of gigabytes, and ~/.codex/sessions growth should be visible to the user somewhere in the product.

Additional information

Relationship to existing issues. #24388 (closed) documents the same data shape and field path - input_image data URLs preserved in compacted replacement_history - with a remote-compaction context deadlock as the symptom; this report shows the same retention behavior present in 0.145.0-alpha.18 with disk exhaustion as the failure mode.

There's also #24948 (closed) documents repeated persistence of large compacted records (text/tool-output variant, 91 GB store). #34061 (open) documents subagent fan-out consuming 755 GiB via event amplification on CLI 0.144.x.

Howwver, I decided to file this as a new issue because
(a) the affected surface is the Desktop app, which none of the above cover,
(b) the image-retention behavior persists after #24388's closure, and
(c) the byte-level quantification of image duplication is new. Happy to have this merged wherever the team prefers.

What I can provide: redacted structural statistics, field paths, record-type histograms, and before/after hashes for the affected files; the preserved 48 MiB control rollout's redacted structural data. I will not attach raw rollouts - the embedded screenshots capture private on-screen content from real work sessions.

Impact timeline: the store reached ~165 GiB and the 460 GB volume peaked around 99% used before intervention; the store grew a further ~16 GiB during the diagnostic session alone. That was a little crazy but necessary :D

Workarounds that contained it for me (for other affected users until a fix ships):

  • Keep screenshot-heavy browser/computer-use work in short-lived tasks; start a fresh task per phase instead of resuming one thread for weeks.
  • Give subagents a short text brief instead of full inherited context.
  • [agents] max_concurrent_threads_per_session = 1 in config.toml caps the fork multiplier (does not fix in-session duplication).
  • Monitor with du -sh ~/.codex/sessions and find ~/.codex/sessions -type f -size +500M.
  • Clean up only after every Codex writer has exited (deleting open files does not free space), preferably via codex delete <session-id>.

Metadata

Metadata

Assignees

No one assigned

    Labels

    appIssues related to the Codex desktop appbugSomething isn't workingcomputer-usecontextIssues related to context management (including compaction)sessionIssues involving session (thread) management, resuming, forking, naming, archivingsubagentIssues involving subagents or multi-agent features

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions