Skip to content

Insane Codex Disk Usage from Subagents #34061

Open

Description

@jezell

What version of Codex CLI is running?

0.144.6

What subscription do you have?

Pro

Which model were you using?

gpt-5.6

What platform is your computer?

macos

What terminal emulator and version are you using (if applicable)?

No response

Codex doctor report

What issue are you seeing?

Subagents are eating my hard drive alive with session logs

What steps can reproduce the bug?

Codex CLI subagent session logs consumed ~755 GiB and nearly exhausted a 1.8 TiB disk

Summary

Codex CLI persisted approximately 755 GiB of JSONL session data under $HOME/.codex/sessions. Approximately 731.5 GiB of the logical file size is attributable to 2,393 subagent session files spawned from a single resumed parent thread.

The problem is not primarily one malformed or unusually large JSON record. Representative sessions show either extremely high event volume or repeated retention of large compaction/tool-output records:

  • One child session ran for 3 minutes 19 seconds and wrote 483,714,063 bytes across 353,255 valid JSONL records—approximately 2.31 MiB/sec and 1,770 records/sec.
  • Another session grew to 925,599,939 bytes; in that file, 175 compacted records accounted for 571,600,883 bytes and 27,848 custom_tool_call_output records accounted for 211,681,025 bytes.
  • July contained approximately 2,931 session files, including 797 files larger than 400 MiB.

This nearly exhausted the system's APFS Data volume. During diagnosis, df reported only 10–32 GiB available and 99–100% capacity used.

Severity and impact

Suggested severity: Critical / P1 for affected users

  • The Codex session store grew to approximately 760 GiB total, with session JSONL files accounting for approximately 755 GiB.
  • The user's entire home directory occupied approximately 1.46 TiB; Codex session data alone accounted for roughly half of it.
  • The 1.8 TiB Data volume reached 99–100% reported capacity.
  • Continued logging risks failed builds, corrupted application state, OS instability, and data loss due to complete disk exhaustion.
  • The affected processes were still actively holding session JSONL files open during diagnosis.
  • Removing these files would likely make historical sessions unavailable to codex resume, so cleanup has a product-data-loss cost even though the files are not project source files.

Environment

Captured on 2026-07-18 in the America/Los_Angeles timezone.

Component Value
Current Codex CLI codex-cli 0.144.6
Versions recorded in affected July session metadata 0.142.4 through 0.144.6
Primary affected versions by file count 0.144.1 (1,138), 0.144.4 (819), 0.144.5 (461)
Originator Mostly codex-tui (2,870 files); codex_exec (62 files)
OS macOS 15.5 (24F74)
Architecture arm64
Node.js v26.0.0
Filesystem APFS Data volume, 1.8 TiB
Working directory in representative session metadata $HOME/office
History mode in representative session metadata legacy
Explicit history/session persistence config None found in $HOME/.codex/config.toml

Observed behavior

Disk usage

760G  $HOME/.codex
755G  $HOME/.codex/sessions
734G  $HOME/.codex/sessions/2026/07

July's growth accelerated sharply:

Date (2026) Session files Files >400 MiB Allocated size (approx.)
Jul 10 50 0 2.8 GiB
Jul 11 473 0 109.1 GiB
Jul 12 506 0 149.2 GiB
Jul 13 291 1 50.6 GiB
Jul 14 313 4 88.4 GiB
Jul 15 340 265 108.6 GiB
Jul 16 355 263 109.0 GiB
Jul 17 300 189 81.7 GiB
Jul 18, partial day 137+ 75+ 33.5+ GiB

Counts for the partial day continued increasing during diagnosis.

Single-parent concentration

Parsing only the first session_meta record from each July file showed:

source: subagent
parent_thread_id: 019ee8d1-94c0-7090-a65a-faeeab8c626d
child session files: 2,393
combined logical size: 785,467,490,368 bytes (~731.5 GiB)

The parent was actively running as a resumed Codex TUI session:

codex resume 019ee8d1-94c0-7090-a65a-faeeab8c626d

At capture time, that resumed process had been running for approximately 23 hours. Another codex resume process had been running for approximately 22 hours and held open a separate 6.9 GiB session file.

Representative high-event-volume child session

Representative child session metadata:

session id: 019f76a8-32b1-77e3-854c-4fb405a58155
parent thread id: 019ee8d1-94c0-7090-a65a-faeeab8c626d
source: subagent/thread_spawn
depth: 1
originator: codex-tui
CLI version: 0.144.5
history mode: legacy
started: 2026-07-18T19:16:06.710Z
last record: 2026-07-18T19:19:26.008Z
duration represented: ~199.3 seconds
file size: 483,714,063 bytes
records: 353,255
JSON parse errors: 0

Largest record categories by aggregate bytes:

JSONL record category Record count Aggregate bytes Largest record
event_msg/token_count 185,461 139,268,416 815
compacted 1,618 121,571,279 105,608
event_msg/patch_apply_end 36,295 110,668,600 521,129
event_msg/agent_message 104,653 41,623,387 2,780
response_item/message 9,947 34,412,319 34,584
world_state 607 18,638,285 34,723
turn_context 5,322 11,032,351 2,915
event_msg/task_complete 3,682 4,879,881 2,870
event_msg/task_started 3,718 866,294 233

This implies severe event amplification. The file does not depend on a single giant line; many categories are being emitted thousands to hundreds of thousands of times during a short-lived subagent task.

Representative large-payload session

A second file, 925,599,939 bytes, showed a different but related persistence pattern:

JSONL record category Record count Aggregate bytes Largest record
compacted 175 571,600,883 5,986,172
response_item/custom_tool_call_output 27,848 211,681,025 5,586,220
response_item/reasoning 27,400 50,952,588 5,164
response_item/custom_tool_call 27,841 31,213,363 35,226
event_msg/token_count 31,379 22,580,057 755
event_msg/patch_apply_end 5,137 14,546,399 33,282

This suggests that both event frequency and repeated retention of large compacted/tool-output payloads contribute to growth.

Expected behavior

  • Session persistence should remain bounded relative to actual user-visible conversation and tool activity.
  • A subagent lasting about three minutes should not persist hundreds of megabytes or hundreds of thousands of events under normal use.
  • Repeated subagent spawning should not replicate parent state, compaction payloads, tool outputs, or event streams into every child log without bounds.
  • Codex should protect the host from disk exhaustion through quotas, rotation, deduplication, compression, backpressure, or a clear warning before storage becomes critical.
  • codex resume should not allow a long-running thread to generate hundreds of gigabytes of local history silently.

Actual behavior

  • A single resumed parent thread produced 2,393 child JSONL logs totaling approximately 731.5 GiB.
  • Hundreds of child session files were created per day.
  • Many individual child sessions grew to approximately 400–500 MiB within minutes.
  • At least one historical session file reached 6.9 GiB and remained open for writing by a resumed Codex process.
  • No storage warning, retention limit, or automatic pruning was observed before the Data volume reached 99–100% capacity.

Reproduction / observed workflow

This is an observed reproduction rather than a minimal deterministic reproducer:

  1. Start Codex TUI in a local project.
  2. Work in a thread that uses collaboration/subagent spawning.
  3. Resume the long-running parent thread with codex resume <thread-id>.
  4. Allow the resumed process to run for many hours and continue spawning depth-1 subagents.
  5. Monitor $HOME/.codex/sessions/YYYY/MM/DD.
  6. Observe hundreds of new child JSONL files per day, many hundreds of MiB each.
  7. Aggregate session_meta.source.subagent.thread_spawn.parent_thread_id; most affected files resolve to the same parent.

The exact prompt/task content has intentionally not been included. The issue is visible from metadata, event counts, byte counts, and process/file-handle information alone.

Suspected failure modes

These are hypotheses based on the persisted metadata and should be verified by the Codex team:

  1. Child event fan-out: parent or sibling events may be replicated into each subagent's JSONL stream.
  2. Unbounded task/event loop: task_started, task_complete, agent_message, patch_apply_end, and token_count events are emitted at implausibly high rates.
  3. Compaction persistence amplification: compacted state may be repeatedly stored in full instead of referenced, deduplicated, or replaced.
  4. Tool-output replay: custom tool outputs may be retained repeatedly across compactions or child sessions.
  5. Legacy history interaction: representative sessions report history_mode: legacy; no explicit user history configuration was found.
  6. Resume lifecycle leak: long-running resumed sessions may keep spawning or persisting child state after user-visible work has completed.

Requested investigation

Please investigate:

  • Why one parent thread spawned 2,393 persisted child sessions totaling ~731.5 GiB.
  • Whether parent/child/sibling events are being copied into multiple JSONL files.
  • Whether compacted records retain repeated full snapshots or previously persisted tool output.
  • Why a three-minute child task emits ~353,000 records, including ~185,000 token-count events and ~36,000 patch-apply completion events.
  • Whether completed subagent sessions continue receiving or retaining events.
  • Whether history_mode: legacy is expected for these versions and whether it changes persistence behavior.
  • Whether the resume path leaks task/event subscriptions across subagent generations.

Recommended safeguards

Independent of the root-cause fix, consider:

  • A configurable per-session and global session-store quota.
  • Automatic rotation/compression and an age/size-based retention policy.
  • Deduplication or content-addressing for compaction snapshots and tool outputs.
  • Rate limiting or coalescing high-frequency telemetry-like events such as token counts.
  • A warning and pause when Codex storage exceeds a threshold or the disk approaches exhaustion.
  • A built-in command to report and safely prune session storage while explaining the impact on resumability.
  • Detection of anomalous event rates or session growth, with a diagnostic bundle users can attach to reports.

Privacy-safe diagnostic commands

These commands report sizes and metadata without printing prompts, messages, tool arguments, or tool outputs.

# Overall usage
du -sh "$HOME/.codex" "$HOME/.codex/sessions"
df -h /System/Volumes/Data

# Counts and large files
find "$HOME/.codex/sessions" -type f | wc -l
find "$HOME/.codex/sessions" -type f -size +400M | wc -l

# Size by day
du -k -d 3 "$HOME/.codex/sessions" 2>/dev/null | sort -n | tail -30

# Open session files and their writer processes
lsof +D "$HOME/.codex/sessions/2026/07/18" 2>/dev/null

# Read only selected, non-content session metadata from the first record
head -1 path/to/session.jsonl | jq '{
  timestamp,
  type,
  payload: {
    id: .payload.id,
    cli_version: .payload.cli_version,
    originator: .payload.originator,
    source: .payload.source,
    history_mode: .payload.history_mode
  }
}'

Suggested attachments

Safe to attach after review:

  • Output of the size/count commands above.
  • The redacted session_meta line for the parent and one representative child.
  • Record-type count/byte aggregations that do not include payload content.
  • lsof output showing active writers, with username/path redacted.
  • Codex version and macOS version output.

Do not attach the full JSONL files without reviewing them. They contain conversation history, instructions, tool inputs/outputs, filesystem paths, and other potentially sensitive content.

Cleanup caveat

The session JSONL files appear to support session history and codex resume. Before deleting them:

  1. Stop the processes actively writing the affected sessions.
  2. Preserve a small, redacted diagnostic sample if the Codex team requests it.
  3. Assume deleted sessions may no longer be resumable or visible in local history.
  4. Verify that disk space is actually released after the writers exit.

What is the expected behavior?

No response

Additional information

No response

Activity

  1. added
    CLIIssues related to the Codex CLI
    subagentIssues involving subagents or multi-agent features
    sessionIssues involving session (thread) management, resuming, forking, naming, archiving
    on Jul 18, 2026
  2. github-actions commented on Jul 18, 2026

    @github-actions
    Contributor

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

    Powered by Codex Action

  3. jezell commented on Jul 18, 2026

    @jezell
    Author

    Seems to be what you get when you combine long running sessions like this:

    Image

    with subagents.

  4. jezell commented on Jul 18, 2026

    @jezell
    Author

    Asked whether subagents are forking the context.

    • Yes—in your affected run, Codex copied a large filtered snapshot of the parent context into almost every forked child.

    It is conditional, not universal:

    • MultiAgent V1: fork_context=true creates a full-history fork; default is false.
    • MultiAgent V2: omitting fork_turns defaults to "all", which creates a full-history fork.
    • fork_turns:"none" starts without parent conversation history.
    • fork_turns:"N" copies only the last N turns.

    The Rust path is:

    1. spawn_agent maps "all" or fork_context=true to SpawnAgentForkMode::FullHistory. V2 spawn handler (https://github.com/openai/codex/blob/main/codex-rs/core/src/tools/handlers/multi_agents_v2/spawn.rs), V1 spawn
      handler (https://github.com/openai/codex/blob/main/codex-rs/core/src/tools/handlers/multi_agents/spawn.rs)

    2. It flushes the parent rollout to disk.

    3. It loads the parent’s model context. With your history_mode: legacy, this uses include_history: true.

    4. Unless LastNTurns was requested, it does not truncate the history.

    5. It constructs the child with InitialHistory::Forked(forked_rollout_items). Fork implementation (https://github.com/openai/codex/blob/main/codex-rs/core/src/agent/control/spawn.rs)

    “Full history” is filtered, but still very broad. It retains:

    • System, developer, and user messages
    • Final assistant messages
    • Compaction records
    • All EventMsg records in legacy mode
    • Session metadata
    • Turn context and world state

    It removes most raw tool-call/output and reasoning records, although those may remain embedded in compaction snapshots. Paginated history has an additional filter for token-count and several other event types;
    legacy history does not.

    On your machine, the affected parent rollout contains 2,322 detectable spawn_agent calls:

    Setting Calls
    ━━━━━━━━━━━━━━━━━━━━ ━━━━━━━
    fork_context=true 1,932
    ──────────────────── ───────
    Setting omitted 234
    ──────────────────── ───────
    fork_context=false 156

    That matches the 2,393 child logs totaling approximately 731.5 GiB. A representative child JSONL contains both the child and parent session_meta, confirming inherited history was serialized into the child file.

    This also corrects part of the earlier bug report: the 353,255 records in a three-minute child were probably copied during initialization, not all newly generated during those three minutes. The core bug is
    primarily repeated full-history materialization, compounded by legacy mode retaining event records.

    There is already an upstream issue describing this exact large-parent snapshot risk: openai/codex#14981 (#14981).

    The immediate workaround is to use fork_context:false on V1 or fork_turns:"none"—or a small bounded number—on V2.

  5. jezell commented on Jul 18, 2026

    @jezell
    Author

    Subagent session cleanup script (python) if anyone runs into this and needs to free up the space:

    https://gist.github.com/jezell/6ad849791fc64d61d1ef1e66ad788eb5

  6. georgfranz commented on Jul 18, 2026

    @georgfranz

    I can independently reproduce this on Codex CLI 0.144.5 on Linux x86_64 with gpt-5.6-sol, ultra effort, MultiAgent V2, and legacy history.

    One child rollout contained:

    • 53,897 valid JSONL records
    • 118,285,692 bytes
    • child session_meta at line 1
    • embedded parent session_meta at line 2
    • first inter_agent_communication_metadata record with trigger_turn: true at line 53,749

    The persisted prefix before the child’s first actual turn therefore contained 53,748 records and 117,949,758 bytes: 99.72% of both the records and bytes in the child file.

    Reproduction

    1. Build up or resume a sizeable parent thread using history_mode: legacy.
    2. Spawn a V2 subagent with fork_turns: "all" or omit it, since all is the default.
    3. Inspect the child rollout JSONL.
    4. Observe that almost the complete parent history is serialized before the child’s first turn.

    Expected behavior

    Inherited context should be referenced, content-addressed, paginated, or otherwise bounded. The child rollout should primarily contain child-owned records.

    Actual behavior

    Legacy full-history forks physically materialize the parent rollout into every child file. Repeated spawning therefore causes multiplicative disk growth.

    Downstream consumers also require special replay detection to avoid interpreting the copied prefix as new events.

    Suggested improvement

    The current source contains special handling for paginated subagents, but existing local sessions remain in legacy mode.

    Could paginated or reference-based storage become the default, with a size guard or warning for legacy full-history forks?

  7. ayanamislover commented on Jul 21, 2026

    @ayanamislover

    Independent Windows / Codex Desktop reproduction, captured 2026-07-21 and cleaned up on 2026-07-22.

    Environment

    • Windows x64
    • Codex Desktop package: 26.715.7063.0
    • Affected rollout metadata spans embedded CLI versions 0.136.0-alpha.2 through 0.145.0-alpha.18
    • Model: gpt-5.6-sol
    • Originator: Codex Desktop
    • Representative parent and child rollouts use history_mode: legacy

    No conversation content, thread IDs, project names, or filesystem paths are included below.

    Storage concentration

    Before cleanup, the local session store contained:

    • 1,379 rollout JSONL files
    • 87.142 GiB total (sessions + archived_sessions)
    • 33 files larger than 1 GiB
    • 79 files larger than 100 MiB

    The files were neither sparse nor hardlinked, so this was real allocated storage.

    Two parent families accounted for 76.747 GiB, about 88% of the entire store:

    Family Root Children Family total
    A 2.708 GiB 43 files / 37.128 GiB 39.836 GiB
    B 1.495 GiB 69 files / 35.416 GiB 36.911 GiB

    This strongly matches multiplicative full-history materialization rather than ordinary child-owned output growth.

    Representative child

    One depth-1 child rollout was 2.429 GiB. It contained roughly 38.7k JSONL records, 56 session_meta blocks, and about 20.8k cumulative token_count events. The actual child takeover / inter-agent boundary appeared near line 38,690, so almost the entire persisted file preceded the child's own work.

    This also explains why downstream usage readers can badly overcount child usage unless they identify and strip the inherited prefix.

    Cleanup evidence

    The Desktop state DB contained 1,307 spawn edges:

    • 989 closed
    • 318 open

    A dependency-aware cleanup removed 982 closed child rollouts while protecting seven closed nodes that still had open descendants. That reclaimed 20.595 GiB without deleting any parent rollout or in-use file. This required a custom manifest, state DB backup, open-descendant traversal, file-handle checks, and transactional thread/edge deletion.

    This is functionality the product should provide directly. Users should not need to reverse-engineer the local thread graph to recover disk space safely.

    There was also a separate 3.153 GB logs_2.sqlite file. SQLite reported 713,127 free pages out of 769,925 total pages (92.6% free), but the file had not been compacted. Automatic checkpoint/rotation/compaction would recover roughly another 2.7 GiB in this case.

    Requested safeguards

    1. Persist inherited parent context by reference or content address instead of serializing it into every child rollout.
    2. Make bounded/empty fork history the default, or warn before a full-history fork materializes a very large parent.
    3. Add per-thread and global session-store quotas with visible disk-usage warnings.
    4. Add a built-in dependency-aware command/UI action to prune closed subagents while preserving roots and open descendants.
    5. Rotate and compact logs_2.sqlite automatically after retention deletes rows.

    I can provide the privacy-safe metadata audit and dependency-aware cleanup scripts if maintainers would find them useful.

  8. shrishmanglik commented on Jul 22, 2026

    @shrishmanglik

    We hit this at scale and ran a byte-level attribution that may help prioritize — sharing the evidence.

    Environment: Codex app 26.715.8383.0 / codex-cli 0.145.0-alpha.27, Windows 11.

    Measured (single day, 2026-07-21): 52 rollout .jsonl files, 15,367,765,044 bytes. Attribution:

    • Inline data:image/...;base64 strings: 89.98% of all bytes (13.83GB)
    • compacted.replacement_history records: 83.3% of bytes; images inside compaction snapshots = 90.4% of all image bytes
    • In the largest file (1.02GB, 18,658 lines): 1,219 inline-image occurrences but only 241 unique payloads (45MB) — a 20.95× duplication factor from subagent history-forks re-materializing parent history plus compaction retaining images
    • 25 child sessions forked from one image-heavy parent = 77.3% of the day's bytes
    • Tool output was negligible (~8KB in the largest file) — this is not a tool-log problem

    Config-schema check (0.145.0-alpha.27): no supported key for image persistence, rollout retention, rollout max-bytes, or append-only references. [history].max_bytes caps a different file; tool_output_token_limit doesn't touch this cohort.

    Mitigation that worked for us: developer_instructions mandating fork_turns="none" (children get a bounded task packet instead of forked image history) + an external retention prune. Happy to share the full audit methodology if useful.

    Suggested fixes from the data: store images as content-addressed references (241 unique payloads would collapse 13.8GB → 45MB), and/or exclude image payloads from fork materialization and compaction snapshots.

  9. Coldain commented on Jul 25, 2026

    @Coldain

    Independent macOS Codex Desktop corroboration, captured 2026-07-25. I inspected sizes, selected session metadata, JSON record types, and string lengths only; no prompts, task names, tool arguments, payload values, thread IDs, or project paths are included.

    Environment

    • macOS 27.0 (26A5388g), Apple Silicon
    • APFS
    • ChatGPT/Codex Desktop app: 26.721.41059
    • Current bundled runtime: codex-cli 0.146.0-alpha.3.1
    • Representative affected child metadata: Codex Desktop, 0.145.0-alpha.18, depth-1 thread_spawn subagent, history_mode: legacy

    Store-level measurements

    • $HOME/.codex/sessions: 122.2 GiB
    • rollout files: 1,007
    • files over 100 MB: 397
    • files over 400 MB: 57
    • files over 512 MB: 15
    • files over 1 GB: 5
    • 2026-07-18 alone: 41.2 GiB across 250 files
    • largest observed rollout: 4,102,031,496 bytes

    Representative depth-1 child rollout

    • size: 597,936,910 bytes
    • valid JSONL records: 14,933
    • records over 1 MiB: 130
    • largest record: 18,742,520 bytes

    Aggregate bytes by record category:

    Category Count Aggregate
    event_msg/image_generation_end 102 406.3 MiB
    response_item/custom_tool_call_output 362 114.4 MiB
    compacted 54 18.1 MiB
    event_msg/mcp_tool_call_end 352 14.2 MiB
    event_msg/token_count 9,271 7.2 MiB

    The largest strings were multi-megabyte payload.result and payload.output.*.image_url values. This case therefore combines full-history subagent materialization with inline visual/tool artifacts; compaction is present but is not the dominant category in this representative child.

    The current runtime is newer than the representative affected runtime, but there is still no visible quota, retention warning, or safe built-in cleanup flow. Deleting these files would affect resumability, so I have not attached or removed them.

  10. LiuChang-ao commented on Jul 26, 2026

    @LiuChang-ao

    Additional anonymized Windows/Desktop data point (no session content, images, full paths, user IDs, thread IDs, or hashes included):

    I performed a read-only stream scan of a local Codex state directory.

    • Total .codex storage: ~13.56 GiB; sessions: 12.01 GiB across 726 rollout JSONL files.
    • Across readable rollout files (a few currently active files were locked and therefore excluded), 198 files contained inline data:image/...;base64,... values.
    • There were 37,621 inline image occurrences but only 1,282 distinct payload hashes: 36,339 copies beyond the first occurrence.
    • The inline image Base64 character data alone totaled ~8.11 GiB. The most frequently repeated payload appeared 3,369 times.
    • The largest inspected non-subagent rollout was 236.72 MiB and contained 532 inline image occurrences (~115.84 MiB of Base64 data).
    • Among the 40 largest rollouts, 39 were marked thread_source=subagent; together they totaled 4,969.75 MiB.
    • The largest inspected non-subagent rollout also contained 160 compacted records and 80 replacement_history references.

    This is a lower-bound measurement, but it independently corroborates the same combination of inline image persistence and subagent-driven storage amplification described here. The scan used only structural markers, byte counts, and payload hashes; no conversation or tool-output content was inspected or retained.

  11. guanxuewen-eng commented on Jul 26, 2026

    @guanxuewen-eng

    Additional reproduction from a newer Codex Desktop build (privacy-safe; paths, project names, thread IDs, and conversation contents omitted).

    Environment

    • Codex Desktop: 26.721.41059 (build 5848)
    • Bundled CLI: codex-cli 0.146.0-alpha.3.1
    • Model: GPT-5.6
    • Platform: macOS / arm64

    Observed

    • ~/.codex/sessions reached approximately 209 GiB.
    • One depth-1 subagent session grew to 3,846,420,707 bytes (~3.58 GiB) in about 7 minutes.
    • The session metadata identified it as a subagent spawned from a long-lived parent Desktop thread.
    • In the first 5,000 valid JSONL records, the largest categories were:
      • event_msg/token_count: 2,075
      • event_msg/agent_message: 1,743
      • event_msg/patch_apply_end: 298
      • response_item/message: 250
      • turn_context: 136
      • task_started: 114
      • task_complete: 112
      • compacted: 22
    • Individual repeated JSONL records reached about 4.46 MiB.
    • The Codex app-server reached roughly 5 GiB RSS and 55-70% CPU while holding multiple multi-GiB session files open.
    • During the incident, system write counters increased by about 58 GiB in 83 minutes; ~/.codex grew by about 10 GiB, while APFS free space fell by about 15 GiB.

    Important distinction
    The diagnostic SQLite database was not the active growth source: logs_2.sqlite remained around 627 MiB and its WAL stayed around 4-32 KiB. The rapid growth was in sessions/**/*.jsonl.

    This appears to reproduce the same subagent event amplification / compaction persistence problem on 0.146.0-alpha.3.1, so the issue is either still unfixed in this newer build or has regressed.

    The practical workaround was to restart Codex Desktop, avoid resuming the affected long-lived parent thread, and temporarily avoid subagent spawning in long sessions. Please consider a per-session size cap/rotation and an automatic pause or warning when a session grows at GiB-per-minute rates.

  12. tylorsaling-source commented on Jul 26, 2026

    @tylorsaling-source

    Sharing measured evidence on where these bytes come from, because it reframes the mechanism and rules one candidate out.

    Post-cap tool output is not the source

    The legacy shell path discards output beyond its 1 MiB cap without persisting it (details in #35421). I verified this on a real event — a 4,095,789-byte single-line match:

    • raw output ≥ 4.1 MB → 1 MiB capture cap → 40,073-byte persisted JSONL record
    • the persisted tail fingerprints the 1 MiB boundary, not command EOF; the ~3.05 M chars after it appear nowhere in the rollout (source-EOF fingerprint: 0 matches)
    • the 13 custom_tool_call_output records in that rollout maxed out at 609 chars

    So oversized single tool outputs are not what fills the disk — the dropped bytes are gone, not stored.

    The bytes are in amplification, not raw capture

    This issue's own numbers point the same way:

    • custom_tool_call_output: 211,681,025 B ÷ 27,848 records ≈ 7.6 KB/record
    • compacted: 571,600,883 B ÷ 175 records ≈ 3.3 MB/record

    The mass is in compaction snapshots (~430× larger per record) and in sheer record volume multiplied across subagents. So the mechanism worth measuring is how often already-persisted records (the ~40 KB tool results and the multi-MB compacted snapshots) are replayed or copied across compactions, resumes, and child sessions — i.e. duplication, not first-write size.

    Closely related on that mechanism: #35226 (compaction loop), #33735 (session JSONL → 24 GB from repeated inline image data during compaction), #24191 (remote compact creates huge compacted records), #33493 (compaction retains unbounded payloads), #24048 (~27 GB memory handling large output).

    Separate branch worth noting

    The SQLite state stores (logs_2.sqlite, state_5.sqlite) are independently affected by a lifecycle gap — e.g. logs_2 was ~1.5 GiB with ~75% free-list pages (no VACUUM/auto_vacuum) and heavy WAL churn from a 4-index log table. That's high-rate tracing/telemetry, not truncation-driven, so it's a distinct issue from the JSONL growth here — possibly relevant to #23168 (configurable storage backend).

  13. tylorsaling-source commented on Jul 26, 2026

    @tylorsaling-source

    Following up with the measured version of the amplification I described above — including which lifecycle boundaries do the copying. All read-only, bounded scans of the local session store.

    Duplication is large and crosses file boundaries

    Bounded scan of a high-mass cohort (one parent + its 8 largest children; 9 files; 758 MB of canonical payload; 534,723 records; 0 parse errors):

    • 46.96% of canonical payload bytes are exact SHA-256 duplicates (356 MB of 758 MB); ≥286 MB crosses file boundaries. Still 49% after normalizing volatile id/timestamp fields, so it isn't an artifact of those.
    • Hash-proven examples: one 37,905-byte session_meta payload repeated 1,354× across 9 files; a 1,086,769-byte mcp_tool_call_end payload in 7 files; token_count 81% duplicate; compacted 64.77% duplicate.

    (The cohort was deliberately picked for high mass — this is not a whole-store rate.)

    Which boundary copies (separate test, strict causal criteria)

    Child attribution required explicit parent linkage and pre-spawn timing and ordered replay and anchors unique in the parent prefix — equality alone was never treated as causal.

    • Child spawn — confirmed. 12 of 14 parent-linked children begin by re-emitting an ordered prefix of parent payloads that existed before the child's spawn timestamp (2,937 records, ~4.3 MB, 2,385 unique-parent anchors). Zero exact raw-line matches → it's payload re-emission into new records, not file copying.
    • Compaction — confirmed, localized. Prior persisted items are rewritten inside compacted.payload.replacement_history (171 matching earlier top-level payloads; 155 repeated across compaction histories). No large post-boundary burst (~2 KB in ±64-record windows) — the compaction record itself carries the cost.
    • Desktop reopen — confirmed. Identical session_meta rewritten on reinitialization (175,891 duplicate bytes across 7 rows).
    • CLI codex resume — NOT isolated. The reopens here are Desktop reinitializations; attributing them to codex resume would be a false positive. That needs a controlled before/after test in a disposable store.

    Fix targets these suggest

    • Child spawn: reference immutable inherited history (a content-addressed shared segment) instead of re-emitting parent payloads into each child rollout.
    • Compaction: dedupe stable history items across successive replacement_history snapshots by content hash.
    • Session reopen: don't rewrite identical session_meta — one record plus small versioned deltas.

    Notes

    The dominant mechanism in this cohort is duplication after first persistence, not the size of any single first write. (Confirming the separate point from my earlier comment: the legacy-shell truncation path discards post-cap bytes rather than persisting them — verified on a 4.1 MB line that contracted to a 40 KB record, source-EOF fingerprint absent everywhere — so truncation is not the disk driver; duplication is.) Related manifestations: #33735 (session JSONL → 24 GB from repeated inline images during compaction), #24191 (huge compacted records). Method: read-only file opens, zero DB connections/writes/locks, no payload dumps, a pre-open byte fence to handle the live parent.

  14. Loong0x00 commented on Jul 27, 2026

    @Loong0x00

    Independent Linux reproduction: this is still present in codex-cli 0.145.0.

    Environment:

    • Arch Linux x86_64
    • Codex CLI 0.145.0
    • Btrfs home filesystem
    • Measurements below used metadata, record types, byte counts, and bounded structural comparisons only. No prompt, tool payload, repository content, username, absolute path, or thread UUID is included.

    Current store snapshot:

    Item Measurement
    Total Codex home 9.145 GB
    Session JSONL 7.212 GB
    Session files 979
    Files >= 10 MiB 121
    Files >= 100 MiB 14
    Files >= 300 MiB 3
    Files carrying forked_from_id 528
    Bytes in fork-marked files 6.521 GB
    Subagent-source files 747 files / 3.425 GB
    CLI-source files 69 files / 3.686 GB

    The 528 fork-marked files holding 6.521 GB does not mean all 6.521 GB is duplicate data, so I separately tested a large explicit fork chain.

    Three consecutive rollouts in that chain were approximately 386.1 MB, 440.1 MB, and 443.6 MB. After excluding the leading inherited session_meta records and normalizing only the volatile top-level timestamp, ordered comparison confirmed:

    • first child re-emitted a 302.5 MB / 87,930-record parent prefix;
    • second child re-emitted a 386.0 MB / 103,977-record parent prefix.

    That is at least 688.5 MB of confirmed inherited history re-persisted by only two forks. This is payload re-emission with fresh timestamps, not byte-for-byte file copying.

    A structural scan of the 443.6 MB rollout found:

    Record category Rows Aggregate bytes
    response_item/custom_tool_call_output 17,363 189.6 MB
    compacted 376 112.0 MB
    response_item/reasoning 23,492 49.9 MB
    response_item/function_call_output 4,110 29.2 MB
    event_msg/token_count 23,285 19.0 MB

    Within the custom-tool outputs, string aggregation attributed about 142.2 MB to text fields and 32.2 MB to inline image_url fields.

    A read-only zstd level-3 measurement across all 979 session files reduced 7.212 GB to 1.541 GB, a 78.6% reduction. The installed binary contains transparent .jsonl.zst reader/materialization support, but codex features list reports:

    local_thread_store_compression  under development  false
    

    There were zero compressed rollout files in this store. This suggests that enabling bounded cold-rollout compression by default would be a useful safeguard even before the fork/compaction amplification is fully fixed.

    This Linux data independently confirms both mechanisms already discussed here: full-history child/fork materialization and repeated retention of compaction/tool-output state. The issue persists in 0.145.0.

  15. dheeraj5612 commented on Jul 27, 2026

    @dheeraj5612

    Adding another data point for this, from a macOS install.

    Environment

    • codex-cli 0.144.0
    • macOS (Darwin 25.5.0), Apple Silicon
    • 460 GB internal volume

    Scale

    ~/.codex had grown to 79 GB, of which sessions/ was 72 GB across 6,856 files. This was the single largest consumer on the machine apart from the system Messages store, and it took the volume to 96% full.

    Monthly totals under sessions/2026/:

    Month Size
    01 1.7 MB
    02 151 MB
    03 19 MB
    04 38 MB
    05 1.3 GB
    06 2.6 GB
    07 67 GB

    Growth is not linear with usage — July alone was 25x June. Daily breakdown for July shows it concentrated in a handful of days rather than spread evenly:

    Day Size
    13 6.5 GB
    15 5.2 GB
    16 15 GB
    17 5.4 GB
    18 2.5 GB
    19 3.8 GB
    20 25 GB
    23 1.3 GB

    25 GB in a single day, and 15 GB in another. Individual rollout files:

    • largest single file: 1.3 GB
    • several in the 500-552 MB range

    Per #22004 the 1.3 GB file would already be unopenable in the desktop app, so the session is effectively lost while still occupying the disk.

    Separately, ~/.codex/logs_2.sqlite was 6.2 GB on its own — worth noting as a second sink distinct from sessions/.

    Config context that may be relevant

    The spike days correlate with heavy Computer Use and subagent activity, which lines up with the amplification described in this issue.

    On mitigation

    There is currently no way to bound this from config. Per the configuration reference, [history] persistence and history.max_bytes govern history.jsonl only, not the rollout files under sessions/. codex archive moves rollouts into archived_sessions/ on the same volume, so it reclaims nothing. The only available remedy is deleting files out from under Codex manually, which is what I ended up doing — 72 GB down to ~275 MB by deleting everything older than a few days.

    Echoing #6015 and #20230: an age or size based retention policy, even opt-in, would make this self-limiting. A per-session size cap would additionally prevent the #22004 unopenable-session failure mode.

  16. NasCorp commented on Jul 28, 2026

    @NasCorp

    I traced a remaining amplification path in current main. The paginated-history changes filter legacy presentation events, but multi-agent full-history forks still appear to persist inherited context through the copied path.

    spawn_forked_thread constructs InitialHistory::Forked and calls fork_thread_with_source. That path uses ForkPersistence::Copied, and paginated subagents are initialized through LiveThread::create_with_inherited_model_context.

    This means a retained Compacted.replacement_history, including a large ImageGenerationCall.result or another inline payload, can still be serialized into every full-history child rollout. Paginated mode reduces event noise but does not eliminate N children x large compacted context storage amplification.

    The repository already has a reference-backed paginated fork path using ForkPersistence::Referenced and history_base. Would maintainers be open to using an equivalent mechanism for multi-agent full-history forks, with child-specific developer instructions represented as an overlay rather than by mutating and copying inherited history?

    I can prepare an invited PR with a deterministic regression test:

    1. create a paginated parent containing a large sentinel payload inside Compacted.replacement_history;
    2. spawn multiple full-history children;
    3. verify the inherited context remains model-visible;
    4. verify the sentinel is not reserialized into each child rollout;
    5. verify the child records a reference-backed history boundary.

    If reference-backed multi-agent forks are not currently compatible with the instruction-sanitization design, I can instead prepare a bounded-size guard that rejects or warns on oversized inherited prefixes.

  17. IkenHuub commented on Aug 1, 2026

    @IkenHuub

    Can confirm this is still happening in Codex Desktop 26.727.51351 on macOS 15.7.5 (arm64). ~/.codex had grown to 105 GB, including 103 GB under sessions, leaving only 2.4 GiB free. I found approximately 849 completed subagent JSONL files totaling about 95 GiB; individual files were commonly 0.5–1.5 GB.

    After deleting only completed subagent rollouts that were no longer open, ~/.codex dropped to 9.8 GB and free space increased to 98 GiB. The main threads and two active subagents were preserved. I have not shared raw logs because they contain private project data.

  18. haoyu-haoyu commented on Aug 2, 2026

    @haoyu-haoyu

    I had the same problem here the bundle of subagent take way almost 60-70GB from me and after research out just find they never close it after it complete, sometime in a heavy task run can also cause crash. I just made this componet to doing storage usage monitor of codex session and subagent session. And It can also help you he clean completed/dead subagent session to free more disk space
    https://github.com/haoyu-haoyu/codex-janitor

  19. mik-0 commented on Aug 18, 2026

    @mik-0

    Another confirmed reproduction, this time on Codex Desktop 26.810.52044 with bundled codex-cli 0.148.0-alpha.9 on macOS 26.2 arm64.

    ~/.codex/sessions grew to 42.52 GiB. A metadata-only classification showed 97 inactive subagent rollouts using 37.71 GiB. Individual child files were approximately 0.4–2.21 GiB, and three subagents spawned from one huge parent generated 6.53 GiB in a single batch. Free disk fell from 50+ GiB to 3.1 GiB.

    The rollout metadata confirmed the files were subagent forks tied to the same parent thread. This is severe storage amplification from normal multi-agent use, with no quota, warning, deduplication, or automatic cleanup. We had to delete the inactive subagent files manually after excluding open sessions and sessions belonging to another workspace.

    Please prioritize deduplicated fork history, bounded inheritance persistence, completed-subagent garbage collection, storage quotas/warnings, and a supported cleanup UI/command. A coding agent should not be able to silently consume the host disk as a side effect of delegation.

  20. hes7 commented on Aug 20, 2026

    @hes7

    Additional Windows case with the same failure pattern (privacy-safe metrics only):

    • Platform: Windows x64
    • Session store: %USERPROFILE%\.codex\sessions
    • Total session store before cleanup: 390.77 GB across 924 rollout files
    • Parsing only the first session_meta record classified:
      • 454 ROOT files totaling 30.41 GB
      • 470 FORK files totaling 360.32 GB
    • The largest fork family contained 107 child/fork files totaling 179.61 GB from one parent; another contained 158 forks totaling 137.21 GB.
    • Many child rollouts were ~8.0–8.1 GB each and shared the same parent session_id / forked_from_id relationship.
    • C: drive free space had fallen to 9.15 GB before intervention.
    • After backing up and verifying all 470 fork files byte-for-byte on an external NTFS drive, removing only those verified fork files recovered 360.32 GB, leaving the ROOT session store at 30.45 GB and increasing C: free space to 369.22 GB.

    This strongly suggests that full-history fork persistence is responsible for the overwhelming majority of local storage in this Windows case as well (about 92% of the session store). No raw JSONL files are attached because they may contain private conversation/tool data.

    A product safeguard would be very valuable here: global/per-session storage caps, warnings before the system drive becomes critically full, and/or a supported command/UI to identify and safely prune duplicated fork/session data without risking root conversation history.

  21. robert-claypool commented on Aug 27, 2026

    @robert-claypool

    Still reproducible in codex-cli 0.149.1.

    Environment

    • macOS 26.5.1, Apple Silicon
    • GPT-5.6 Sol, xhigh
    • MultiAgent V2 depth-one subagents
    • Representative rollouts report history_mode: legacy

    Impact

    Captured today:

    • ~/.codex: approx 897 GiB
    • ~/.codex/sessions: approx 890 GiB
    • Rollout files: 1,443
    • Files larger than 1 GiB: 65
    • One day's directory: 354 GiB across 81 files
    • One resumed parent accounted for 39 depth-one child files totaling 336.3 GiB
    • The 1.8 TiB APFS Data volume reached 100% capacity with approximately 182 MiB free
    • Codex emitted no storage warning, quota refusal, or backpressure before exhaustion

    Byte-level representative child

    One bounded subagent provides a clear attribution:

    • Spawn record explicitly used fork_turns: "all"
    • Parent rollout prefix at spawn: 19,728,188,607 bytes
    • Completed child rollout: 18,404,435,437 bytes
    • First inter_agent_communication_metadata boundary in the child: byte 18,399,038,336
    • Therefore 99+% of the child file preceded its own inter-agent activity boundary
    • Only 5,397,101 bytes followed that boundary
    • Elapsed time from child session_meta to task_complete: approx 7 minutes 29 seconds

    The runtime re-materialized ~18.4 GB of inherited parent history for one child. Repeating that across 39 children used ~336 GiB in one day.

  22. torronen commented on Aug 29, 2026

    @torronen

    This appears to be even worse when combined with browser automation, including in-app browser, living copies on Mac in com.google.Chrome.code_sign_clone.

    This is a critical issues for users experiencing it.

    For temporary workaround there should be a log trim / log clean feature in CLI and a button in Codex app.

  23. Adil2662 commented on Sep 3, 2026

    @Adil2662

    Whole-corpus measurement by requested fork mode (full-history children median 377.65 MB vs 8.59 MB recent-N vs 3.39 MB none, n=163/99/23), the record-kind composition of the copied bytes (event stream, not conversation), and evidence that the current desktop bundle 0.153.0-alpha.5 still does it, posted with sanitized evidence and rerunnable scripts on #35458: #35458 (comment)

  24. jon4v commented on Sep 4, 2026

    @jon4v

    Adding one WSL2 datapoint from a read-only, metadata-and-size-only audit.

    Environment: Ubuntu 24.04 on WSL2. One long-lived session tree whose rollouts reported history_mode: legacy contained 988 rollout JSONL files totaling ~55.9 GB: ~0.7 GB in the root and ~55.2 GB in descendants. Across ~/.codex/sessions, subagent rollouts accounted for ~55.8 GB of ~61.1 GB total (91.3%).

    The host experienced freezes under combined storage pressure, but I captured no I/O, CPU, memory, or ETW trace during a freeze, so this does not attribute the freeze to Codex alone. The tree topology and size concentration are consistent with descendant persistence amplification, but this audit did not establish byte-for-byte inheritance or determine which mechanism wrote each byte.

    The affected tree was legacy and long-lived. codex-cli 0.153.2 is only the version currently installed after the incident; it is not evidence that 0.153.2 created these files or that a fresh 0.153.2 session reproduces the issue. No raw rollout content is included.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    CLIIssues related to the Codex CLIbugSomething isn't workingperformancesessionIssues 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