ccdeck

Read a session on the canvas

What each card, line and bubble on the canvas means, how to open one agent's details and tool calls, and what a restart brings back.

Claude Code and Codex Checked against ccdeck 3.31.0 on

Before you start

Steps

  1. Choose which sessions the deck draws

    Started with no flag, the deck draws every Claude Code and Codex session on this computer.

    npx ccdeck

    To draw one project only, start it from that project's folder with --scope, or name the folder with --workspace.

    npx ccdeck --scope

    npx ccdeck --workspace ~/code/web-api

    A session belongs to the folder when it runs in that folder or anywhere under it. The same rule decides for Claude Code's hook, for Codex's rollout files and for the event log the deck reads back when it starts. A relative path is resolved once, against the folder you start the deck in, and symbolic links are followed. macOS and Windows ignore case when they compare folder names. Linux does not, so /srv/proj and /srv/Proj are two folders.

    The report in the terminal has a workspace row: (all) for a deck that draws everything, or the folder it resolved. --status lists each running deck with its address, its workspace or (all), and its log file.

    npx ccdeck --status

    One deck at a time. Only one deck runs per Claude configuration directory. A start with a different workspace stops the running deck and takes its place, and the terminal says so: “stopped the deck on 4317 · pid … · it was started with different settings”. --workspace and --scope choose what one deck draws. They are a filter, not a sandbox.

  2. Read the cards and the lines

    Each card is one agent: a session, or a subagent that a Claude Code session started. A subagent's card sits to the right of its session's card, one level deep, and a line joins the two.

    The web-api session on the canvas. Its card, marked LIVE, with a context ring reading 14, an Opus 5 chip and an arrow reading 4, is joined by lines to four subagent cards on Sonnet 5: migrator, docs and general-purpose marked DONE on solid lines, and reviewer marked LIVE on a dashed line. Tool bubbles sit to the right of every card; reviewer's last one, Bash npm, has a spinner and the others a tick. Open the full-size picture
    Demo data One Claude Code session with four subagents. The line to reviewer, which is still running, is dashed; the lines to the three that finished are solid.

    A card's top row gives its state (LIVE, DONE or ERR), its name and how long it has run. A session is named after its folder, a subagent after its type. The second row says session, or subagent and the folder it runs in, shows → 4 on a session that started four subagents, and holds the model chip. A Claude Code session's title comes next, then a small chart of the last 60 seconds of activity. The last row counts its tool calls (tools), the calls still running (in-flight) and, once a call has failed, how many failed; a session's card adds its input and output tokens (tok) and its spend.

    A session's card also has a ring before its clock once the deck knows how full the model's context window is. The number in the ring is the percentage in use; click the ring for the breakdown. For Claude Code the deck estimates it from the session's transcript. Codex reports its own figure.

    The web-api session's card: a LIVE pill, the name web-api, a context ring reading 14 and 14 minutes of running time; the word session, an arrow with 4 and an Opus 5 chip; the title Add rate limiting to the public A…; a thin chart of the last 60 seconds; then 7 tools, 1 in-flight, 138.0k tok and $4.28. Four Agent bubbles sit to its right, three with a tick and the last with a spinner.
    Demo data A session's card. Its four Agent bubbles are the calls that started its subagents; the last one, the call that started reviewer, is still in flight.

    The line from a session to a subagent is dashed and moving while the subagent runs, and turns solid and thinner, in a duller shade, when it finishes. If your system asks for reduced motion, the dashes stay and do not move.

    The bubbles to the right of a card are its last four tool calls, each on a dashed connector. A call that is still running has a spinner and a moving connector, a finished call shows ✓ and a failed one ×. Beside a Bash call, a second bubble names the program it ran, such as npm; beside a file call, the file.

    The reviewer subagent's card, marked LIVE, reading subagent · web-api beside a Sonnet 5 chip, with 4 tools and 1 in-flight. A dashed line comes in from the left. To its right, four bubbles: Read limit.ts, Grep and Read limit.test.ts with ticks, and Bash npm with a spinner.
    Demo data A subagent that is still running: the line into it is dashed, and its Bash call, npm, has a spinner where the finished calls show ✓.
  3. Tell Claude Code and Codex sessions apart

    Look at the model chip. It names the model, and the model says which CLI it came from: Claude models print as their family and version (Opus 5, Sonnet 5, Haiku 4.5), OpenAI models as GPT-5.5 and the like. A Codex session that has not reported its model yet shows a chip reading Codex. A Claude Code session with no model yet shows no chip.

    The infra session, a Codex session, on its own. Its card is marked LIVE, with a context ring reading 15 and a GPT-5.5 chip, and has no title row: under the chip comes the line approvals not visible, then 3 tools, 119.5k tok and 53¢. Three tool bubbles sit to its right, named Shell, Edit and Shell, for terraform, keys.tf and terraform.
    Demo data A running Codex session: a GPT-5.5 chip, no title row, no subagent cards, and “approvals not visible” where a Claude Code card would say it is waiting on you.

    Codex sessions have no subagent cards. The deck reads Codex from the rollout log Codex writes, and that log records no subagents. It records no session title either, so a Codex card has no title row. Codex's own tools appear as Shell and Edit bubbles.

    Claude Code only: waiting on you. Codex writes no approval request to its rollout files, so the deck cannot tell when a Codex session has stopped to ask you something. While a Codex session runs, its card says approvals not visible instead (unless the session's approval policy is never, which cannot ask). Check the terminal that session runs in.

  4. Fit the board and move around it

    Press F to fit every agent on screen. Drag the empty canvas, or scroll, to pan. To zoom, hold Ctrl (Cmd on macOS) and scroll, pinch on a trackpad, or click the plus and minus buttons in the canvas controls at the bottom left. Click a card to frame it with the rest of its session.

    The bottom left of an empty stretch of canvas: a column of seven symbol buttons (plus, minus, a crosshair, pause, a tree, a bin and a question mark), and further right a chip reading Auto-fit off with a Resume button.
    Demo data The canvas controls, and the Auto-fit off chip that appears once you move the view yourself. The crosshair is brighter while auto-fit is off.

    The seven canvas controls carry symbols rather than words. Hover over one for a tooltip that says what it does and, for four of them, the key that does the same. From the top, the tooltips read:

    • plus and minus: “Zoom in” and “Zoom out”;
    • the crosshair: “Recenter view + re-enable autofit”, or “Recenter view (autofit already on)”;
    • two bars: “Pause live updates — events keep arriving and are applied when you resume (Space)”;
    • the tree: “Auto-arrange — clear pins (R)”;
    • the bin: “Clear the canvas and the server's event log — asks first (C)”;
    • the question mark: “Keyboard shortcuts (?)”.

    A screen reader announces them as Zoom in, Zoom out, Recenter view, Pause the canvas, Re-arrange the canvas, Clear the canvas and Open the keyboard shortcuts.

    A pan, a zoom, a drag or a click on a card stops the deck from bringing new sessions into view, and the canvas shows Auto-fit off. Click Resume, or the crosshair, to fit the board and turn that back on. F fits once and leaves it off.

    Zoomed far out, cards are drawn as small faces that keep their state, and their name where there is room. Hover over one to read its name, state and numbers, or zoom back in to see the whole card.

  5. Move from card to card with the keyboard

    Every key below works while the deck's tab has focus and no dialog is open. ? opens the full list.

    • J and K: the next and the previous agent. Each opens that agent's detail panel.
    • Tab reaches the agent cards, and Enter selects the focused card and opens its detail panel.
    • Z: zoom to the selected agent and its session.
    • F: fit every agent on screen.
    • W: the session waiting on you, oldest first; press again for the next. Claude Code only, for the reason in step 3.
    • L: the session list. D: the detail panel.
    • Esc: close what is open, deselect, release focus.

    The arrow keys do not pan the canvas. Letter keys give way to a control you reached with the keyboard, and to your browser's own Ctrl, Cmd and Alt shortcuts.

  6. Open the session list

    Press L, or click Session list in the topbar. In a window narrower than 1440 px the button shows only its list icon. The list has a row for every session on the canvas.

    The session list open on the left, headed Sessions 3 and 2 LIVE, with rows for infra (GPT-5.5, 3 tools, 53 cents, 14m), web-api (Opus 5, 18 tools, $4.28, 14m) and data-pipeline (Sonnet 5, 7 tools, 46 cents, 7s). The canvas beside it is zoomed out, so web-api and its four subagents are drawn as small faces. Open the full-size picture
    Demo data Two running sessions, then the finished one. A row's tool count includes its subagents' calls, which is why web-api reads 18 here and 7 on its card.

    Sessions waiting on you come first, longest wait first. Running sessions come next and finished ones last, the most recently active first. A row gives the state, the folder name, the model chip, the tool calls of the session and its subagents together, the session's spend, and how long it has run. For a session that is waiting on you, it gives how long it has waited instead.

    Claude Code only. Only a Claude Code session can sort to the top as waiting on you. Codex sessions are never counted in the list's waiting figure, because Codex records no approval request the deck could read.

    Click a row to frame that session and open its detail panel. ‹ or L closes the list; Esc does not.

  7. Open one agent's detail panel

    Double-click a card. From the keyboard, Tab to the card and press Enter. A single click only frames the session.

    The detail panel for the web-api session: LIVE, session, 14 minutes, Opus 5, $4.28 spend, then Export JSON and Remove from board. Below: Activity with 7 calls and 1 live, Tokens with in 41.2k, out 96.8k, cache r 1.84M and cache c 118.0k, Identity with cwd /demo/web-api, one prompt reading Add rate limiting to the public API, and seven tool calls, newest first, the first still running.
    Demo data The panel for a session. Its newest tool call, the Agent call that started reviewer, is still running, so it shows … where the others show a duration.

    The top of the panel gives the agent's state and name, whether it is a session or a subagent, how long it has run, its model and the session's spend, with Export JSON and Remove from board. Then, in order:

    • Activity: how many calls, how many are running or failed, and the calls by kind.
    • Tokens: in, out, cache r (read) and cache c (created).
    • Identity: the folder (cwd), the session id and, for a subagent, its parent.
    • Prompts: what was typed into the session, newest first.
    • Tool calls: each call, newest first, with how long it took.

    Tokens and spend belong to the session. A Claude Code session's figures include its subagents, and a subagent's panel has no Tokens, no spend and no Prompts. Close the panel with × or D, or press Esc, which also deselects the card.

  8. Open one tool call

    Click a row under Tool calls in the detail panel. A dialog opens with the tool's name and how long the call took, or in-flight… while it is still running. Under Input and Response it shows the call as it happened: the command and its output for Bash, the file and the change for Edit, the file for Read.

    A dialog headed Bash, 2.31s, with Input showing the command npm test -- store and Response showing its output: PASS test/store.test.ts, two passing tests, and Tests: 2 passed, 2 total. Each section has a copy button. Open the full-size picture
    Demo data A finished Bash call from the migrator subagent. copy puts one side on the clipboard.

    A long block ends in show all, which opens it in full. With a mouse you can also click a bubble on the canvas to open the same dialog; the bubbles are not reachable from the keyboard, the Tool calls list is. Esc or × closes the dialog.

    The panel keeps the last 200 calls of each agent, and the full input and response of the newest 25 only. For an older call the dialog says its full payloads were released, and shows a short preview.

  9. Know what a restart brings back

    The deck appends every event it captures to a log file and reads the newest part of it back when it starts. Stopping and starting the deck, a restart after an upgrade and a reboot all redraw the sessions that were there.

    npx ccdeck --stop

    What comes back has limits. The deck replays at most the newest 2,000 hook events, and fewer when they are large. A deck with a workspace replays only what happened inside it. Nothing that happens while the deck is stopped is recorded. The board also keeps at most six finished sessions.

    The log is events.jsonl in ~/Library/Logs/ccdeck on macOS, in %LOCALAPPDATA%\ccdeck\Log on Windows, and in $XDG_STATE_HOME/ccdeck on Linux, which is ~/.local/state/ccdeck when that variable is not set. CCDECK_HOME moves it; with CLAUDE_CONFIG_DIR set it is in agent-dag inside that directory. --status names each running deck's log.

    --history uses a file of your choosing, and --no-persist writes nothing and replays nothing.

    npx ccdeck --history ~/ccdeck-events.jsonl

    npx ccdeck --no-persist

    Clearing the canvas (C, or the bin in the canvas controls) asks first, in a dialog headed Clear the deck?, then empties the canvas and the log. A session whose start is older than what was replayed shows ? beside its name and ≥ before its clock: the deck joined it late, so the time is a floor. Positions you give cards by dragging them are kept by this browser, not by the log; R drops them.

If something goes wrong

The canvas says “Waiting for Claude Code or Codex” while a session is running

The deck was started with --scope or --workspace, and the session runs outside that folder. The message names the folder. On Linux, a difference in case alone makes it another folder. Start the session inside the named folder, or restart the deck without --workspace or --scope.

The terminal says “missing value --workspace — expected a path; using the default”

The value after --workspace was empty or looked like another flag, for example a shell variable that was not set. The deck started without a workspace and draws every session. Give it a real path, in quotes if it contains spaces.

Starting a scoped deck made the other deck disappear

Only one deck runs per Claude configuration directory, so a start with other settings replaces the running one. npx ccdeck --status shows which deck is running and what it draws. npx ccdeck with no flag goes back to a deck that draws every session.

Clicking a card does not open its details

Since ccdeck 3.25.0 a single click frames the card's session and closes the detail panel. Double-click the card, or Tab to it and press Enter. J, K, D and a session-list row open the panel too.

A letter key does nothing

A control you reached with the keyboard is keeping its keys, or a dialog is open. Press Esc first.

New sessions appear off screen

Auto-fit turned off when you panned, zoomed or clicked a card, and the canvas says Auto-fit off. Click Resume, or the crosshair in the canvas controls. F fits once without turning it back on.

After a restart a card shows ? beside its name and ≥ before its clock

The deck did not see that session start: it began before the part of the log that was replayed, or while the deck was stopped. Its first prompts and calls are missing, and its clock counts from when the deck first saw it. Nothing needs repairing.

A tool call's dialog says its full payloads were released

Only the newest 25 calls of each agent keep their full input and response. The preview in the dialog is what the deck still holds for that call.

Nothing came back after a restart

The deck ran with --no-persist, the canvas was cleared, or the deck was started with a different --history file. Start it without --no-persist and with the same --history as before; npx ccdeck --status names each running deck's log.

A finished session is gone from the canvas and the session list

The board keeps six finished sessions and lets an older one go two minutes after it finishes. That is different from Remove from board: a removed session keeps its row in the session list, and clicking the row brings it back.

Next