Codex Source
Default location
Section titled “Default location”~/.codex/sessions/**/*.jsonl(or$CODEX_HOME/sessions/**/*.jsonlwhenCODEX_HOMEis set)
Override
Section titled “Override”llm-usage daily --codex-dir /path/to/codex/sessions# orllm-usage daily --source-dir codex=/path/to/codex/sessions# several directories (repeat the flag)llm-usage daily --codex-dir /path/one/sessions --codex-dir /path/two/sessionsParsing notes
Section titled “Parsing notes”The adapter handles Codex token-count events and computes deterministic usage deltas for cumulative counters. Newer Codex releases also write one token_usage_record row per API response; the adapter emits the records collected before each token_count row (deduplicated by response_id) in place of that row’s delta, and a token_count with no records before it still emits its delta. This recovers the response that triggers an auto-compaction (the cumulative counters never include it) and maps cache_write_input_tokens.
A forked session (/fork, a fork from the session picker, or a forked subagent) starts with its own session_meta, which names forked_from_id, followed by a copy of the parent’s lines stamped with the time of the fork. Codex 0.152 and later end the copy with a thread_settings_applied event carrying the fork’s id. The adapter emits nothing from the copied lines (no usage, messages or tool calls) and counts the fork’s own turns from the parent’s last running total, so a parent and its fork add up to the parent plus the fork’s own turns. A fork that references the parent’s history instead of copying it (history_mode: paginated) has no copied running total. From Codex 0.153, which logs a token_usage_record for every response, a token_count written before the fork’s first response (a usage limit, a full context window, a compaction) is taken as the parent’s running total, not new usage. A 0.152 fork of that kind gives no such signal, so it still counts the parent’s last response once in that case. Forks written by Codex 0.88 to 0.151, and 0.152 forks whose closing event lacks the fork’s id, do not mark where the copy ends. For those the adapter reads the parent rollout, found by the forked_from_id in its file name under the sessions directory or, when that directory is sessions in a Codex home, under archived_sessions next to it, where Codex moves an archived thread. The copy is the run of the fork’s first lines whose running totals and user and assistant messages match the parent’s one for one, and it ends at the last copied token_count. The fork’s own turn has its own model response, so it stops the match even when it repeats the parent’s next prompt and reaches the same total, and its usage counts from the last copied total. Lines copied after that token_count, such as an interrupted turn’s last tool output, count as the fork’s messages and tool calls. A subagent that Codex 0.120 to 0.134 spawned with fork_turns copies its parent’s last turns but names the parent only in source.subagent.thread_spawn.parent_thread_id; it is read the same way, and a subagent spawned without a copy reads as before. A change to the parent re-parses the fork, and a parent that is there but cannot be read fails the fork’s parse until it can. When the parent is missing, the copied lines count again on the day of the fork; a parent that turns up later (put back, or reached by a run over the usual directory after one over a narrower one) is found on the next run. A parent deleted after both were counted is missing too: with the event store on, the parent’s usage stays as history and the fork now counts the copy as well. A fork that ends its copy with its own closing event never reads the parent.
The project (repoRoot) comes from the cwd of the latest session_meta or turn_context row, and the provider from session_meta’s model_provider (openai when it is not logged).