ccdeck

Use ccdeck with Codex

Codex sessions on the ccdeck canvas from their rollout logs, with tokens and quota, what the deck cannot see, and a Codex-only start.

Codex only Checked against ccdeck 3.31.0 on

Before you start

Steps

  1. Start the deck and find the Codex row

    Run this in any terminal:

    npx ccdeck

    The report it prints has one row for Codex:

    • Codex sessions watching and a folder: the deck found Codex and reads the rollout files in that folder. It is $CODEX_HOME/sessions, or ~/.codex/sessions when CODEX_HOME is not set or is empty. A long path may be cut short with ….
    • Codex sessions skipped — no ~/.codex/, or --no-codex: no Codex folder existed when the deck started, or the deck was started with --no-codex. The row names ~/.codex/ even when CODEX_HOME is set.

    Nothing is installed for Codex. There is no hook and no trust prompt, and starting the deck writes nothing in the Codex folder. The deck reads the rollout file Codex writes for each session.

    If Codex keeps its files in another folder, start the deck with the same CODEX_HOME, and the row names that folder. In PowerShell, set it first: $env:CODEX_HOME="D:\codex"; npx ccdeck.

    CODEX_HOME=~/codex-home npx ccdeck

  2. Start a Codex session

    Run codex in any folder and give it something to do. If the deck was started with --workspace or --scope, run it inside that folder: the deck keeps or skips a Codex session by the folder the session started in.

    The card appears once Codex writes to its rollout file. The deck looks for new lines every 1.5 seconds, in the two newest day folders under sessions. The card is named after the folder and opens as LIVE.

    A Codex session that was already running when the deck started appears the next time it writes. The deck reads its file from that point on, so nothing the session did before is shown.

    The docs-site card, a Codex session the deck joined late: a LIVE pill, the name docs-s… with a question mark beside it, a context ring reading 13 and ≥ 4m 09s; the word session and a chip reading Codex; the line approvals not visible; then 1 tools and 65.4k tok, with no cost. To its right, a Shell bubble and an npm bubble, each with a tick.
    Demo data A session that began before the deck did: ? beside its name, ≥ before its time, and a Codex chip until its next turn names the model.

    Hover ? to read “No SessionStart captured — synthesised”, and the time to read “The deck joined this session after it began, so it has run at least this long — first seen …”. Until the session’s next turn starts, the deck has not read its model or its approval policy: the chip reads Codex, and the card shows tokens but no cost.

  3. Read a Codex card

    The infra session, a Codex session. Its card is marked LIVE, with a context ring reading 15, 9m 16s and a GPT-5.5 chip, and has no title row: under the chip comes the line approvals not visible, then 3 tools, 1 in-flight, 119.5k tok and 53¢. To its right, three tool bubbles: Shell for terraform and Edit for keys.tf with ticks, and a second Shell for terraform with a spinner.
    Demo data A running Codex session. Its third call, a Shell call to terraform, has no result yet, so its bubble shows a spinner where the others show ✓.

    The state pill reads LIVE while a turn runs. It turns DONE when Codex finishes the turn, or when you press Esc in Codex, and LIVE again at your next prompt. The chip names the model Codex reported: gpt-5.5 prints as GPT-5.5.

    A Codex card has no title row and no subagent cards, because a rollout file records neither. Its last row counts the calls (tools), any that failed (err) and those still running (in-flight), then gives the tokens (tok) and an estimated cost. tok is Codex’s input, cached tokens included, plus its output. Hover it for the split, and the cost for the sum, which prices cached tokens at the cache rate.

    On the canvas, Codex’s tools get the deck’s names: Shell for exec, exec_command, shell and shell_command, Edit for apply_patch, Plan for update_plan, Web for run, stdin for write_stdin, and wait. A tool the deck does not know keeps its own name. Beside a Shell bubble a second bubble names the program; beside an Edit bubble, the file.

    Hover a bubble for Codex’s own name for the tool and what it was given, for example “exec_command · {"cmd":"terraform plan"}”. The detail panel and the tool dialog use Codex’s own names too; Read a session on the canvas shows how to open them.

    A call counts as failed only when Codex’s result begins “Script failed”, or “Exit code:” with a number other than 0. Any other result counts as a success.

  4. Open the context breakdown

    Click the ring on the card. A screen reader announces it as “Context 15% of 258,400 tokens — show breakdown”.

    A dialog headed Context · infra, reported by the Codex CLI — as of its most recent request. A bar at 14.9%, and 38,600 / 258,400 tok (last request). Under Cumulative usage · whole session: input tokens 104,900, output tokens 14,600, cache reads 96,000, cache writes 0, cumulative total 119,500 and estimated cost 53¢. Under Transcript composition, a sentence beginning Not counted for Codex. Under AGENTS.md files in scope, /demo/infra/AGENTS.md at 1.8 KB.
    Demo data The window figure is the Codex CLI’s own, from its last request. The message and tool-call counts are left out, and the dialog says why.

    For Codex, both figures at the top come from the Codex CLI and describe its most recent request: the tokens in the context window and the window’s size. Under them is the session’s usage so far and its estimated cost. The dialog does not count messages and tool calls for Codex: the deck skips whatever a rollout file held before it started reading, so the counts would be short. The last section lists the AGENTS.md files in scope, each one from the session’s folder up to the root of the disk, and $CODEX_HOME/AGENTS.md. Press Esc to close the dialog.

    Claude Code differs. Its dialog is subtitled “approximation — CC's /context isn't hook-exposed”, counts messages and tool calls, and lists CLAUDE.md files.

  5. Watch the terminal for approvals

    Codex writes no approval request to its rollout files, so the deck cannot tell when a Codex session has stopped to ask you something. A Codex session never gets a waiting row, never counts in the session list’s waiting figure, and never changes the topbar count, the tab title or the favicon. With sound on, the deck plays its finish tone when a Codex turn ends, but never the tone for a session that asks for you.

    Instead, a running Codex card says approvals not visible when its approval policy can ask (untrusted, on-request or on-failure) or has not been read yet. The line is not there at never, which cannot ask, or on a DONE card. Hover it for the reason, which ends “Check the terminal.”

    Two Codex session cards, one above the other, both LIVE on GPT-5.5. The infra card has the line approvals not visible and reads 3 tools, 1 in-flight, 119.5k tok and 53¢. The billing card has no such line and reads 2 tools, 54.3k tok and 24¢.
    Demo data infra runs under on-request and says approvals not visible. billing runs under never, and its card says nothing about approvals.

    A call with no result yet looks the same whether it is running or waiting for your approval. Its bubble keeps its spinner, its dialog says in-flight… and (waiting…), and the deck never marks it failed for being quiet.

    A dialog headed exec_command, marked in-flight…. Under Input, cmd: terraform apply. Under Response, (waiting…).
    Demo data infra’s terraform apply, with no result yet. Whether it is still running or waiting for an approval in the terminal, the dialog shows the same.

    Claude Code only: waiting on you. The waiting rows, the count and the asking tone in See which session is waiting on you are for Claude Code sessions.

  6. Read your Codex quota

    Press U, or click Usage in the topbar. In a window narrower than 1440 px the button shows only its icon, and its tooltip reads “Show usage panel (U)”.

    The Codex quota section of the Usage panel, with a Plus badge and just now. A 5-hour window bar at 38%, resets in 2h 14m, 17% under pace. A 7-day window bar at 21%, resets in 4d 3h, 20% under pace. Under them, 9.42M tokens · 14 sessions (7d).
    Demo data One bar for each limit OpenAI reports, with when it resets and how the pace compares.

    The Codex quota section shows your plan and one bar for each limit OpenAI reports, named by its length: “5-hour window”, “7-day window”, “30-day window”, or “Rate limit” when OpenAI gives no length. Each bar shows how much is used, when it resets and how your pace compares. A spend cap and credits appear only when your plan has them.

    The line under the bars, such as “9.42M tokens · 14 sessions (7d)”, is counted from the rollout files on this computer. It needs no network and no account, and it stays when the quota cannot be read.

    The deck reads the quota about once a minute while the page is open; ↻ in the panel’s header reads it again now. To keep your codex login working, the deck refreshes the token in $CODEX_HOME/auth.json the way the CLI does, when it is within 90 seconds of expiring or the usage endpoint turns it down. It writes back only the token fields, and only while the page is open.

    Since 3.31.0, when OpenAI’s status page reports an incident on a Codex component, a line under the section’s heading says so and a chip appears in the topbar, both linking to status.openai.com. An incident elsewhere on that page, such as one in ChatGPT, is not shown.

  7. Run a deck for Codex only

    On a computer where the deck finds no Claude Code, this happens by itself. Where Claude Code is installed, start the deck with --no-claude:

    npx ccdeck --no-claude

    The report says Claude hooks skipped — no Claude Code found, or --no-claude and claude-swap skipped — accounts are Claude-only. The deck installs no Claude Code hook and no claude-swap, and does not redraw Claude Code sessions from its log when it starts.

    The topbar's buttons on a Codex-only deck: Session list, Usage, History, Machine, Browser watch and a sun for the appearance settings.
    Demo data The topbar at 1440 px with no Accounts and no Sound button. A Codex-only start was supplied to the page for this picture.

    The topbar has no Accounts and no Sound button, and A, M and V do nothing. The Usage panel shows Codex quota only.

    An earlier Claude Code hook stays. --no-claude does not take out a hook that an earlier start put in Claude Code’s settings, and the deck does not turn away what that hook sends. npx ccdeck --uninstall removes it, and the login item with it.

    The other switches:

    • --codex reads Codex even before its folder exists. Sessions appear once Codex creates it, without a restart.
    • --no-codex stops the deck reading Codex. Given both, --no-codex wins.
    • --claude turns Claude Code capture on when the deck did not find Claude Code.

    A start with other switches, or another CODEX_HOME, replaces the running deck, and the terminal says “stopped the deck on … · pid … · it was started with different settings”. The deck that starts when you log in gets none of these switches and decides by what it finds. On macOS and Linux it gets the CODEX_HOME that was set when the login item was made; on Windows it uses your saved user variables.

If something goes wrong

The report says Codex sessions skipped

When the deck started, the Codex folder did not exist, or the deck was started with --no-codex. Run codex once, or set CODEX_HOME to the folder Codex uses, and start the deck again; the new start replaces the running deck. npx ccdeck --codex reads the folder even before it exists.

Codex is running, but no card appears

One of three things. The deck was started with --workspace or --scope, and the session started outside that folder. Codex and the deck use different CODEX_HOME folders: check that the Codex sessions row names the folder Codex writes to. Or the session’s file is in an older day folder than the two newest, which are the only ones the deck reads.

A card shows ?, ≥ and a Codex chip

The session began before the deck started, so the deck reads it only from then on. Nothing needs repairing. The chip changes to the model when the session’s next turn starts.

Every Codex session appears twice

An older deck left hooks for Codex in its hooks.json, and the report says so in a Codex hooks row: “left by an older deck in …, so Codex sessions can arrive twice”. Run npx ccdeck --uninstall, then start the deck again. Uninstall also removes the Claude Code hook, which the next start puts back, and the login item, which npx ccdeck --install-service puts back.

Codex quota says “Quota unavailable.”

The line under it says why, and what to do:

  • “Run codex login to authenticate.”: Codex is not signed in on this computer.
  • “API-key login — ChatGPT quota is only available for codex login.”: Codex is signed in with an API key, which has no quota to read.
  • “Codex session expired — run codex login.”: OpenAI turned the sign-in down.
  • “Couldn't refresh the Codex token — click ↻ to retry.”
  • “chatgpt_base_url in ~/.codex/config.toml is not an https OpenAI host, so the token was not sent.”
  • “ChatGPT API unreachable — click ↻ to retry.”: the network, or the service.

The tokens line under the section is counted from files on this computer and does not depend on the quota.

A card stays LIVE after its terminal was closed

Codex writes nothing when a session closes, so a turn that was running when the terminal went away never ends in its file. The deck ends that session after 90 minutes with no new line. A turn that finished, or that you stopped with Esc, turns the card DONE at once.

A command that failed shows ✓

The deck marks a Codex call failed only from Codex’s own result line, and a plain exec_command result has none. Click the bubble to open the call and read its output.

After a reboot, the deck shows Claude Code again

The deck that starts at login gets no switches, and it found Claude Code. Start it again with npx ccdeck --no-claude, which replaces it.

Next