New:Microsoft Teams Notifications Are Now Available in Socket.Learn more →
Get Started

claude-code-session-tracker

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

claude-code-session-tracker

See every Claude Code session on your machine in a local dashboard.

Source
npmnpm
Version
0.1.0
Version published
Weekly downloads
33
73.68%
Maintainers
1
Weekly downloads
 
Created
Source

claude-code-session-tracker

CI npm node license

See every Claude Code session on your machine in a local dashboard — grouped by project, with live status, titles, and token usage.

npx claude-code-session-tracker

Then open the printed http://127.0.0.1:4747.

Run Claude Code in four terminals and you lose track of which one is waiting on you, which is still working, and what you asked the one you abandoned yesterday. Claude Code already writes all of that to ~/.claude. This reads it — nothing else — and puts it on one page.

What you get

  • Active sessions, checked twice against the OS so a stale file or a recycled PID never shows up as running.
  • Recent sessions across every project, with Claude's own title, the first and last prompt, the model, and the branch.
  • A detail panel per session: message and tool-call counts, token totals, elapsed and working time, subagent count, a copyable claude --resume <id>, and a button that shows the transcript in your file manager.
  • --json for scripting, and an HTTP API if you would rather build your own.
  • No dependencies, no install scripts, no network calls, no writes to your Claude directory.

Requirements

Node 20 or newer, and Claude Code having run at least once on this machine. macOS, Linux, and Windows are all covered by CI. Nothing else is needed — if ~/.claude does not exist yet, the page says so and fills in the moment your first session starts.

Run it with any package manager

npx      claude-code-session-tracker   # npm
pnpm dlx claude-code-session-tracker   # pnpm
yarn dlx claude-code-session-tracker   # yarn
bunx     claude-code-session-tracker   # bun

The package has no runtime dependencies and no install scripts, so every runner behaves the same.

Options

FlagDescription
-p, --port <number>Port to listen on, stepping forward up to 20 times if taken (default 4747)
--host <address>Address to bind (default 127.0.0.1 — see the warning below)
--no-openDo not open a browser
--jsonPrint the session list as JSON and exit
-n, --limit <number>How many sessions to list (default 50; running ones are always shown)
--claude-dir <path>Override the Claude data directory
-h, --helpShow usage
-v, --versionShow the version

Scripting

--json prints the same payload the page uses, then exits:

npx claude-code-session-tracker --json | jq '.sessions[] | .project.name'
{
  "sessions": [
    {
      "id": "279ed6ae-49fd-4234-a74e-145f5535341c",
      "source": "claude-code",
      "status": "busy",              // busy · waiting · idle · ended
      "project": { "name": "…", "path": "…", "slug": "…", "gitBranch": "main" },
      "title": "Disable dependabot", // Claude's own title, when it wrote one
      "firstPrompt": "…",
      "lastPrompt": "…",
      "model": "claude-sonnet-5",
      "version": "2.1.235",          // the Claude Code that wrote the session
      "startedAt": 1787142489923,
      "lastActiveAt": 1787142700231,
      "transcriptPath": "…/279ed6ae….jsonl",
      "sizeBytes": 136133,
      "live": { "pid": 4129, "kind": "interactive", "entrypoint": "cli" }
    }
  ],
  "sources": [ /* one entry per adapter, with whether it found its data */ ],
  "total": 794,
  "generatedAt": 1787142701002
}

Only running sessions carry live. Everything else is optional — a field that was not in the transcript is absent rather than null.

HTTP API

The server is the same one the page talks to, so anything the page can do you can do with curl:

RouteReturns
GET /api/sessions?limit=NThe list above. limit matches --limit, and running sessions are always included
GET /api/sessions/:idOne session with counts, tokens, models, activeMs, awaySummary, and notes
GET /api/healthok, the version, the Node it runs on, the resolved Claude directory, and per-source status
POST /api/sessions/:id/revealShows that transcript in your file manager. Requires a loopback Origin

Every route refuses a request whose Host is not loopback. reveal is the only one that acts rather than reports, so it is a POST, it checks Origin as well, and the path it opens comes from our own lookup — never from the request.

On the page

Click any row for the full read. Everything has a key:

KeyDoes
/Jump to the filter
↑ ↓Move between sessions, across both tables
Home EndFirst and last session
↵Open the selected session
EscClose the panel, or clear the filter

The list refreshes every 2 seconds and says so when the server goes away. The page takes the same limit from the query string, so ?limit=200 and --limit 200 show the same depth of history.

The theme follows your OS by default; Auto / Light / Dark in the top right overrides it, and the choice is remembered.

What it reads

Everything comes from what Claude Code already writes to disk:

PathUsed for
~/.claude/sessions/<pid>.jsonRunning sessions and their live status
<session cwd>/.git/HEADThe branch a running session is on
~/.claude/projects/**/*.jsonlSession history — titles, prompts, models, branch
~/.claude.jsonPer-project rollup metrics (not read yet)

Set CLAUDE_CONFIG_DIR (or pass --claude-dir) if your Claude data lives somewhere other than ~/.claude. Some Claude Code versions accept a comma-separated list there; the first entry wins.

Privacy

The tool never writes to the Claude directory, binds to loopback only, rejects requests that are not addressed to a loopback host, and makes no outbound network calls of any kind. There is no telemetry and no update check.

Transcripts hold your prompts, your paths, and sometimes your secrets. That is why the default bind is 127.0.0.1 and why every request has to be addressed to a loopback host — a page on any website can otherwise point a browser at your localhost. Passing --host to something else drops that guard, so the CLI says so, loudly, before it starts.

For a machine you are SSH'd into, forward the port instead of opening the bind:

ssh -L 4747:127.0.0.1:4747 you@the-machine

Troubleshooting

Nothing is listed. Check curl -s 127.0.0.1:4747/api/health — it prints the directory that was searched. If that is not where your transcripts are, set CLAUDE_CONFIG_DIR or pass --claude-dir.

A session I just started is missing. The list refreshes every 2 seconds and a session appears once Claude Code has written its first record.

A session shows as idle while it is clearly working. Status comes from what Claude Code itself records in ~/.claude/sessions/. If that file is stale, the row is honest about the file rather than guessing.

The port is taken. It steps forward automatically, up to 20 times; the address it actually bound is the one printed. --port picks a different start.

An old session has no title. Titles are Claude's own, and older transcripts predate them. The derived name and the first prompt stand in.

Programmatic use

import { createConfig, SessionRegistry } from 'claude-code-session-tracker/core';

const registry = new SessionRegistry(createConfig());
const { sessions } = await registry.list({ limit: 20 });
const detail = await registry.detail(sessions[0].id);

createConfig() takes { claudeDir, host, port } overrides. registry.detail() resolves to null for an unknown id rather than throwing.

Development

Requires Node 22.6+ for the dev script (native TypeScript stripping); the published package runs on Node 20+.

pnpm install
pnpm dev                       # run from source, watch mode
pnpm build                     # tsc + copy web assets
pnpm typecheck
npm pack                       # -> claude-code-session-tracker-<version>.tgz
pnpm smoke ./claude-code-session-tracker-0.1.0.tgz pnpm

pnpm smoke installs the packed tarball into a temporary directory with the package manager you name, then runs the installed binary against a fixture transcript. It is what CI runs — Node 20/22/24 × npm/pnpm/yarn/bun on Linux, plus npm on macOS and Windows — so a change that only works from source fails before it ships.

Everything that parses a transcript lives in src/sources/claude-code/. The Source interface in src/sources/source.ts is the seam a second tool (Codex, Cursor) would plug into; src/core/ knows nothing about Claude Code.

Releasing is a tag: npm version <patch|minor|major> then git push --follow-tags. The release workflow re-runs the checks and publishes with npm provenance.

Project plan and phase breakdown: PLAN.md.

How it stays fast

Feature-complete for v1 — phases 0 through 4 of PLAN.md.

Running sessions come from ~/.claude/sessions/*.json. Those files outlive the processes that write them, so each one is checked twice before it becomes an Active row: process.kill(pid, 0), then the recorded start time against the real one, which is what rules out a recycled PID.

Recent sessions come from the transcripts, which run to about a gigabyte on a working machine. Listing them reads no file contents at all — one readdir per project and a stat per file is enough to sort by recency. Only the sessions actually shown are opened, and only their first 16 KB and last 64 KB, which is where the title, the prompts, the model and the branch live. Results are memoised against each file's size and mtime, so an untouched transcript is never read twice. Listing all 794 transcripts on the development machine takes ~230 ms cold and ~75 ms warm.

Opening a session streams its transcript once, line by line, capping how much of any single line it holds — the largest record on the development machine is 9.4 MB, and memory should be a property of the reader, not of the biggest tool output in the session. A 37 MB transcript answers in 99 ms; the slowest of all 795 is 140 ms.

Malformed lines are counted and skipped, never thrown on: the .jsonl format is private and undocumented, and it will change under us. When it does, the detail panel reports what it could not read in notes instead of pretending.

Contributing

Issues and pull requests are welcome. pnpm typecheck and a passing pnpm smoke against a fresh npm pack are what CI will ask of a change; both run in well under a minute locally.

Since every number here was measured on one machine, a bug report that includes your GET /api/health output and the notes from an affected session is worth far more than a description.

License

MIT © Yusuf Demirci

Keywords

claude

FAQs

Package last updated on 19 Aug 2026

Related posts