Skip to content
| Marketplace
Sign in
Visual Studio Code>Visualization>Claude Action TimelineNew to Visual Studio Code? Get it now.
Claude Action Timeline

Claude Action Timeline

SKKokkula

|
1 install
| (0) | Free
Timestamps for every Claude Code action: a live timeline of prompts, tool calls, replies and durations, read from the session transcripts Claude Code already writes locally. Unofficial.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Claude Action Timeline

Timestamps for every Claude Code action. A live timeline of what Claude Code is doing in your workspace — every prompt, tool call, reply and how long each took — read from the session transcripts Claude Code already writes locally.

Licence: MIT

Unofficial. This is an independent, community-built extension. It is not made by, endorsed by, or affiliated with Anthropic. "Claude" is Anthropic's trademark and is used here only to describe what the extension reads.

What you get

  • Timeline view (activity bar → clock icon): one row per action with the wall-clock time beside it. Tool calls show a one-line summary (the command's description, the file's name, the search pattern…) and gain a duration the moment their result lands. Failed tool calls are marked, and a call the permission layer refused reads denied with its reason — a permission rule, a call you declined, or an auto-mode classifier outcome — in a muted icon rather than the error red, because a rule doing its job is not a failing tool. A call still waiting for its result reads no result 4m with an ellipsis icon — the age stays current — and API errors and conversation compactions get rows of their own instead of masquerading as replies or vanishing.
  • Click to open: rows for file tools (Read, Edit, Write, NotebookEdit) open the file they acted on; the hover shows the full path. Rows for everything else stay inert.
  • Reveal in Transcript: right-click any row to open the session's .jsonl at the line that row came from — the raw record behind the summary.
  • Status bar: the time and name of Claude's latest action, always in view. Hovering it shows the session being followed, its state (working, awaiting your input, or quiet), when it started and how long it spans, the last action with its duration, what the view holds, the busiest tool, the transcript file being read, and a Send feedback link (also in the palette as Claude Timeline: Send Feedback): rate the extension on the store your editor installs from — the VS Marketplace in official VS Code, Open VSX in VSCodium, Cursor or Windsurf — or report a problem or idea on GitHub issues. Click the status bar item to open the timeline.
  • Frozen-session triage: the session's state is assessed from the transcript — the one signal that keeps answering when the chat UI hangs. When a turn is open but nothing has been written for a while (3 minutes; 10 for shells, agents and workflows, which legitimately run long), the status bar turns warning-coloured with the measured span (quiet 4m) and the hover names the unanswered call and the recovery path. Facts, not verdicts: an idle session reads as awaiting your input, never as a flag, because the transcript cannot tell a hung tool from a slow one — and this extension does not pretend it can. Large single-turn writes (16k+ characters) note the known VS Code extension hang they can trigger in the row's tooltip, with the workaround.
  • Copy Freeze Report: one command puts a paste-ready diagnostic on the clipboard — state, unanswered calls with ages, recent API errors, compactions, transcript stat, recovery steps. Prompt and reply text is counted, never quoted, so the report is safe for a public issue after a read-through.
  • Live: the view follows the newest session for the workspace and updates as the transcript grows (directory watch + a 2-second polling backstop).
  • Session picker: pin an older session or go back to following the latest.
  • Copy as text: the whole visible timeline as timestamped plain text.
  • Log (Claude Timeline: Show Log): which directory was searched, which session is being followed and why it changed, and a lines-in/events-out tally. An empty timeline has several causes and this is how you tell them apart. Raise the detail with Developer: Set Log Level.

Rows read like this — a text illustration, not a screenshot; the right-hand part is VS Code's dimmed item description, aligned here only for legibility:

Both sessions were writing, so it stayed put  14:04:12
Publish the package                           14:03:59 · Bash · 0.3s · denied (permission rule)
Run the unit tests                            14:03:58 · Bash · 6.4s · failed
FOLLOW_HYSTERESIS_MS                          14:03:57 · Grep · 0.2s
follow.ts                                     14:03:56 · Read · 0.1s
why does the timeline keep flipping?          14:02:41

On the left, whatever the action carried: a Bash call's description, a file tool's file name, a search pattern, or — for a prompt, reply or thinking block — its opening 80 characters, all whitespace collapsed to single spaces and an ellipsis at the cut. A multi-line prompt therefore reads as one flattened line, not as its first line. On the right, the timestamp, the tool, the duration once its result lands, and the outcome when there is one to report — failed when the result came back an error, or denied with its reason when the call was refused before it ran. Newest is at the top by default.

How it works

Claude Code appends one JSON line per event to ~/.claude/projects/<workspace-slug>/<session-id>.jsonl. This extension only reads those files — no network, no processes, nothing written to disk. The transcript format is internal to Claude Code and changes between versions, so the parser is deliberately defensive: lines it does not recognize are skipped silently rather than breaking the view.

Durations come from pairing each tool_use id with its tool_result line, so they measure the real gap between the call and its result.

Settings

Setting Default Meaning
claudeActionTimeline.claudeDir "" Directory holding projects/; empty means ~/.claude
claudeActionTimeline.showThinking false Show thinking blocks as entries
claudeActionTimeline.showSubagents false Show subagent (sidechain) activity
claudeActionTimeline.showDurations true Per-tool durations — in the row, its tooltip and Copy as Text
claudeActionTimeline.newestFirst true Newest action at the top
claudeActionTimeline.maxEvents 500 Entries kept in the view (50–5000)
claudeActionTimeline.timeFormat time time = HH:MM:SS, timeWithDate = MMM D HH:MM:SS

timeFormat governs the row's description, the status bar and Copy as Text. A row's tooltip is the detail view and always shows the full local date and time, whichever format is set.

Limitations

  • Multi-root workspaces: the first folder is used (re-resolved when folders change). A window with no folder open has no workspace path to resolve, so the view stays empty.
  • Transcripts are found by the absolute path Claude Code ran in, which is what names the directory under projects/. A drive letter in the other case is handled; reaching the same project by a different path (a symlink, a subfolder, a UNC share) is not — that path has its own directory, or none.
  • Remote development: the extension prefers the workspace side (extensionKind: ["workspace", "ui"]), so in SSH/WSL/container windows it reads the remote ~/.claude — the machine where Claude Code actually runs.
  • When two sessions write concurrently (an interactive one plus a background agent), follow-latest sticks with the current session until the other has been ahead for 30 seconds, instead of flip-flopping between them.
  • Long sessions are trimmed, not paged: the view shows the last maxEvents entries and at most 5000 are held in memory, so the earliest actions of a very long session eventually drop out of the view.
  • The transcript format is Claude Code's internal format. When a Claude Code update changes it, unrecognized lines simply do not appear until this extension catches up. The log warns when a batch of lines yields no events, which is what that looks like from in here.
  • CLAUDE_CONFIG_DIR is honoured when claudeActionTimeline.claudeDir is empty, so a relocated ~/.claude is usually found with no configuration. Treat it as best-effort: it is undocumented upstream, so the setting remains the supported way to point this extension somewhere else. The log records which of the two won.

Development

npm install
npm run lint      # ESLint
npm test          # tsc + node:test over src/test
npm run package   # the installable .vsix, via @vscode/vsce

Press F5 in VS Code to launch an Extension Development Host.

TypeScript is pinned to ~6.0.3: typescript-eslint throws on TS 7.0 rather than warning, so the compiler and the lint step have to move together (see typescript-eslint#10940). Raise both once TS >= 7.1 is supported.

engines.node (>=20.19.0) is the floor for linting and testing, inherited from ESLint 10 — deliberately higher than the oldest runtime the extension itself supports, which is VS Code 1.90's Node 20.9 host (see below). npm run package needs Node 22 or newer — @vscode/vsce pulls in @azure/* packages and @typespec/ts-http-runtime that require it — so npm ci on Node 20 logs EBADENGINE warnings for a tool that only the packaging step uses.

CI (GitHub Actions) runs lint and tests on a matrix of ubuntu-latest and windows-latest against Node 20, 22 and 24; a second job then runs the packaging step on Linux and uploads the resulting .vsix as a build artifact. Node 20 is in the matrix deliberately: engines.vscode admits VS Code 1.90, whose extension host runs Node 20.9, so the 20.x line is where the oldest supported host lives. The @types/node pin to ^20.19 keeps the compiler on that line — it rejects APIs from Node 21 and later, though not the handful added between 20.9 and 20.19 — and the matrix's Node 20 leg proves the code runs there.

The requirements (each paired with the test or CI step that holds it), the design rationale, and the security posture — including the ledger of accepted warnings — live in docs/.

Releasing

Pushing a v* tag builds the .vsix and attaches it to a draft GitHub Release. The workflow refuses tags whose commit is not on main, and tags that disagree with package.json about the version — so a release can only come from reviewed history, and its artifact can never contradict its own label.

git tag -a vX.Y.Z -m "X.Y.Z"
git push origin vX.Y.Z

Then review the draft and publish it. Storefront publishing stays manual: publish tokens are long-lived credentials with write access to the publisher account, which is not something to keep in CI for a project this size. From a Node 22+ shell, with the .vsix downloaded from the release, the same tested artifact goes to both storefronts:

npx @vscode/vsce publish --packagePath claude-action-timeline-X.Y.Z.vsix
npx ovsx publish claude-action-timeline-X.Y.Z.vsix -p <open-vsx-token>

(vsce reads its Azure DevOps token from VSCE_PAT or an earlier vsce login; Open VSX serves VSCodium, Cursor and Windsurf users.)

License

MIT

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft