Forked thread token monitor over-accumulates usage after fork

Resolved 💬 1 comment Opened Jul 7, 2026 by martinmclee Closed Jul 7, 2026

Observed behavior

  • Fork a thread that already has token usage history.
  • Continue in the forked session with a short follow-up conversation.
  • Token monitor in Codex Desktop reports inflated usage that jumps far more than the forked turns.

Expected behavior

Forked sessions should report usage for the fork itself, not re-apply parent cumulative totals in a way that double-counts usage.

What appears to be happening

During session bootstrap, forked history reconstruction seeds token state from the last persisted EventMsg::TokenCount in rollout (record_initial_history path sets state.set_token_info(Some(info))).
After that, normal token updates still arrive and are applied.
If those updates are cumulative, then a fork can overcount by adding already-restored totals again.

Relevant code path

  • codex-rs/core/src/session/mod.rs
  • record_initial_history(...)
  • InitialHistory::Forked seeds token_info via last_token_info_from_rollout(...)
  • token_usage_info() is used as cached state for reshowing totals

Why this likely breaks after fork

  • Both resumed/forked bootstrap and per-turn token updates can include cumulative state.
  • In a fork, restoring prior token totals and then applying cumulative updates again causes the UI/monitor to “blow up” token counts.

Minimal fix

In the fork bootstrap path, avoid double-counting by:

  1. Using fork-specific token initialization baseline, and/or
  2. Treating thread/tokenUsage updates in forked sessions as deltas from that baseline.

This is one place to keep the logic consistent so both resume and fork have unambiguous semantics.

Repro steps

  1. Open a thread with substantial token usage.
  2. Fork the thread in Codex Desktop.
  3. Run 1–3 turns in the fork.
  4. Observe the token monitor jumps beyond expected fork delta.

Impact

Budget/usage visibility becomes misleading after fork, and token burn planning becomes unreliable.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗