by sudomichael via GitHub · MIT licensed · 80 versions
Open source, kept here so you can read it and make your own copy. Not our work.
Local-first analytics dashboard for AI coding sessions. See what you built with Claude Code & Codex CLI.
About this project (the project's own write-up)

What it does
AgentGraphed automatically indexes every Claude Code and Codex session on your machine. With it you can:
- Find old work you forgot about — every session, searchable.
- Resume abandoned sessions with one click.
- Browse project history across every git repo you've touched.
- Generate context for a new chat from any past conversation.
- Track usage and costs across providers, models, and projects.
Everything stays local. AgentGraphed reads the JSONL logs your CLI tools were already writing (~/.claude/projects/, ~/.codex/sessions/) and turns them into a real dashboard.
Try it
npx agentgraphed
That's the whole install. No clone, no signup, no config file. The dashboard opens at http://localhost:3737. Re-run any time, or leave it running — it re-scans every 5 minutes.
Prefer a global install?
npm install -g agentgraphed
agentgraphed
Don't have npx / Node? Install Node 20+ from https://nodejs.org (the LTS version is fine).
What to expect on first run
npx agentgrapheddownloads the package once (~15 MB, takes 30-60s on a typical connection). Subsequent runs start in seconds — npm caches the package.- You'll see one
npm warn execline and a couple ofnpm warn deprecatedwarnings from transitive dependencies. Harmless. - The dashboard server boots:
› Starting AgentGraphed on http://localhost:3737 › Scanning local AI coding sessions… Found 142 Claude + 8 Codex sessions (14821 messages indexed in 1943ms) › Ready. Press Ctrl+C to stop. - Your browser opens to the dashboard automatically.
- To stop the server, hit
Ctrl+C. Your indexed data stays at~/.agentgraphed/agentgraphed.sqlitefor next time — even after Claude Code rotates the original log files off disk.
Troubleshooting: native better-sqlite3 errors
AgentGraphed uses better-sqlite3, a native module that compiles (or downloads
a prebuilt binary) during install via an npm install script. If your npm is
configured with ignore-scripts=true (common in hardened or corporate setups),
that step is skipped and you'll hit errors on launch like:
Error: Could not locate the bindings file
or a NODE_MODULE_VERSION mismatch. The fix is to (re)install while allowing
install scripts to run:
npm install -g agentgraphed --foreground-scripts --ignore-scripts=false
# …or, if you run it with npx:
npm_config_ignore_scripts=false npx agentgraphed
If it still fails, you likely need build tools for the native compile: Python 3
and a C++ toolchain (build-essential on Debian/Ubuntu, Xcode Command Line
Tools on macOS, or the "Desktop development with C++" workload on Windows).
Screenshots
Features
- Timeline — every session grouped by day, with
STARTED · SPANS Nd/CONTINUED/CLOSEDbadges so multi-day work doesn't hide on a single bucket. - Sessions — read past conversations in a chat-bubble view; search by content, project, provider, or model.
- Resume — one click copies
cd <cwd> && claude --resume <id>to your clipboard. - Generate context (optional, BYO LLM key) — produces a primer to paste into a fresh chat so you don't lose context when resuming.
- Projects — auto-detected from git repo roots; per-project usage, model spend, and session history.
- Dashboard — usage chart, KPIs, top projects, work-type breakdown, per-model cost. Filter the whole dashboard by project or model family.
- Auto-classification (optional, BYO LLM key, on by default) — categorizes sessions as Feature / Debugging / Planning / Refactor / Styling / DevOps / Data / Payments / Docs / Content and writes a clean past-tense title for each. Typically a few cents for hundreds of sessions.
- Live quota probe (optional) — hover the sidebar widget to read your live Anthropic 5h/7d and OpenAI per-minute rate-limit utilization. Single-token probes (~$0.00006 each).
- Share — generate a stat-card PNG of your dashboard, project, or session view and copy it straight to your clipboard.
- Background ingest — re-scans local logs every 5 minutes; new sessions appear without you doing anything.
- Cost estimates — LiteLLM's auto-updating retail pricing for 2700+ models. Treat as directional.
- Range picker — 7d / 30d / 90d / all-time on every chart, with auto-suggested log scale when the data is long-tailed.
Privacy
AgentGraphed is local-first by default. Everything lives in ~/.agentgraphed/agentgraphed.sqlite on your machine.
There are exactly three things that can ever leave your computer, and every one of them is opt-in:
-
LLM session classification + "Summarize for new chat" — only fires when you click the button or enable auto-classify. Sends a sampled set of your own prompts to your configured LLM provider with your API key. Nothing reaches AgentGraphed servers.
-
The opt-in leaderboard. Off by default. When you turn it on, every six hours (or sooner if you finished a new session since the last submit) your local app posts a batch of session-level rows to
https://agentgraphed.com/api/leaderboard/submit. Each row contains: the handle you picked, a random per-session UUID, start time, duration, provider, model, tokens by kind (input/output/cache_read/cache_write), est. cost, and message count. No prompts, no project names, no session content, no file paths, no git branches, no API keys. Full breakdown of what is and isn't sent: https://agentgraphed.com/privacy. -
API keys are stored in plaintext in your local SQLite file — same threat model as
~/.aws/credentialsor a.env. Don't commit your home folder to git.
To verify any of this, read the source. The leaderboard submitter is one function (maybeSubmitLeaderboard) in src/lib/ingest/auto.ts. The wire format is one schema — what's not in the schema isn't sent.
To audit or delete your leaderboard data:
# See everything we have for your handle
curl "https://agentgraphed.com/api/leaderboard/my-data?handle=YOUR_HANDLE"
# Delete it all
curl -X DELETE "https://agentgraphed.com/api/leaderboard/my-data?handle=YOUR_HANDLE"
Supported sources
- Claude Code — reads
~/.claude/projects/*/*.jsonl - Codex CLI — reads
~/.codex/sessions/YYYY/MM/DD/*.jsonl
More adapters coming. If you want a specific one, open an issue.
Optional: LLM session titles & categories
Without an API key, sessions show the first line of the first prompt as the title. With a key:
- Anthropic — Haiku 4.5 (default) gives clean past-tense titles like "Fixed Stripe checkout double-decimal bug"
- OpenAI — GPT-5 mini works equally well, often cheaper
Click Settings → LLM provider, paste your key, then Classify uncategorized. Cost is fractions of a cent per session — typically $0.01–0.03 for a few hundred sessions.
Configuration
Environment variables:
| Variable | Default | What it does |
|---|---|---|
AGENTGRAPHED_PORT |
3737 |
Starting port (auto-increments if in use) |
AGENTGRAPHED_DATA_DIR |
~/.agentgraphed |
Where to store the SQLite DB |
AGENTGRAPHED_CLAUDE_DIR |
~/.claude/projects |
Override Claude Code log location |
AGENTGRAPHED_CODEX_DIR |
~/.codex/sessions |
Override Codex log location |
AGENTGRAPHED_NO_OPEN |
(unset) | Set to 1 to never open a browser (--no-open) |
Log directories can also be edited at Settings → Data sources without restarting.
Run as a service
To keep AgentGraphed running in the background so the dashboard is always at
http://localhost:3737, run it with --no-open (or AGENTGRAPHED_NO_OPEN=1)
under your OS service manager. The flag skips the browser launch, which would
otherwise pop a window on every (re)start.
macOS (launchd)
Save as ~/Library/LaunchAgents/com.agentgraphed.plist (replace YOU with your
username), then launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.agentgraphed.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.agentgraphed</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/env</string>
<string>npx</string>
<string>agentgraphed</string>
<string>--no-open</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
<key>HOME</key>
<string>/Users/YOU</string>
</dict>
<key>RunAtLoad</key><true/>
<key>KeepAlive</key><true/>
<key>StandardOutPath</key><string>/Users/YOU/Library/Logs/agentgraphed.log</string>
<key>StandardErrorPath</key><string>/Users/YOU/Library/Logs/agentgraphed.log</string>
</dict>
</plist>
Linux (systemd user service)
Save as ~/.config/systemd/user/agentgraphed.service, then
systemctl --user enable --now agentgraphed (and loginctl enable-linger $USER
to keep it running after logout):
[Unit]
Description=AgentGraphed
After=network-online.target
[Service]
ExecStart=/usr/bin/env npx agentgraphed --no-open
Restart=always
RestartSec=5
[Install]
WantedBy=default.target
Node version note: the bundled
better-sqlite3ships prebuilt binaries for current LTS releases. Ifnpx agentgraphedfails to install on a very new Node with anode-gyp/compile error, install and run under the latest LTS (e.g. Node 22).
Development
git clone https://github.com/sudomichael/agentgraphed.git
cd agentgraphed
npm install
npm run dev
Open http://localhost:3737. Hot reload, source under src/.
To produce a publishable build:
npm run build # builds Next.js standalone bundle
npm pack # creates agentgraphed-X.Y.Z.tgz
License
MIT © Michael Patrick
Built and maintained by @ushercakes.
Versions (80 — latest: feat: multiple tagged log directories per provider (#5))
- Version 80 — Jul 1, 9:02pm — feat: multiple tagged log directories per provider (#5) latest
- Version 79 — Jun 15, 11:19am — Merge pull request #4 from asachs01/pr/better-sqlite3-12
- Version 78 — Jun 15, 11:19am — Merge branch 'main' into pr/better-sqlite3-12
- Version 77 — Jun 15, 11:18am — Merge pull request #3 from asachs01/pr/git-timeout
- Version 76 — Jun 15, 11:18am — Merge branch 'main' into pr/git-timeout
- Version 75 — Jun 15, 11:17am — Merge pull request #2 from asachs01/pr/no-open
- Version 74 — Jun 15, 11:15am — chore(deps): bump better-sqlite3 to ^12.10.1 for Node 26 support
- Version 73 — Jun 15, 11:14am — fix(ingest): bound git execSync calls with a timeout
- Version 72 — Jun 15, 11:12am — feat(cli): add --no-open / AGENTGRAPHED_NO_OPEN for headless use
- Version 71 — Jun 12, 4:10pm — Clean up build warnings: fix actions.ts version require path and bin field
- Version 70 — Jun 12, 3:57pm — Fix leaderboard submit blocked by one implausible-duration session
- Version 69 — Jun 11, 9:26am — feat(cli): npx agentgraphed --join (0.5.8)
- Version 68 — Jun 10, 9:20pm — chore(release): 0.5.7 — anonymous install_id on leaderboard submits
- Version 67 — Jun 10, 8:57pm — fix(leaderboard): seed all-time history on first submit (0.5.6)
- Version 66 — Jun 10, 6:56pm — chore(release): 0.5.5 — rename actually renames
- Version 65 — Jun 10, 3:57pm — fix(leaderboard): rename now moves rows server-side, not creates new ones
- Version 64 — Jun 10, 3:22pm — feat(leaderboard): rename handle from the opt-in panel
- Version 63 — Jun 10, 2:50pm — chore(release): 0.5.4 — title fixes, share toast, social links
- Version 62 — Jun 10, 12:05pm — chore(release): 0.5.3 — leaderboard page is now a signup page
- Version 61 — Jun 10, 11:53am — ci(publish): poll the tarball URL, not just the metadata
- Version 60 — Jun 10, 11:41am — chore(release): 0.5.2 — real tooltips with concrete explanations
- Version 59 — Jun 10, 11:28am — chore(release): 0.5.1 — dollar shares + clearer labels for billing mix
- Version 58 — Jun 10, 11:04am — chore(release): 0.5.0 — leaderboard goes session-level (schema v2)
- Version 57 — Jun 10, 10:15am — chore(release): 0.4.0 — opt-in leaderboard goes live
- Version 56 — Jun 10, 10:08am — Revert "Revert "feat(leaderboard): phase 1 — sidebar CTA + opt-in flow + stub submitter""
- Version 55 — Jun 10, 9:30am — chore(release): 0.3.6 — share + collapse for analytics cost-breakdown card
- Version 54 — Jun 10, 9:29am — Revert "feat(leaderboard): phase 1 — sidebar CTA + opt-in flow + stub submitter"
- Version 53 — Jun 10, 9:27am — feat(leaderboard): phase 1 — sidebar CTA + opt-in flow + stub submitter
- Version 52 — Jun 10, 9:19am — feat(analytics): collapse + share for "Where your cost went" card
- Version 51 — Jun 9, 9:38pm — chore(release): 0.3.5 — token breakdown by source
- Version 50 — Jun 9, 9:35pm — feat(dashboard): cost breakdown as 4th chart toggle + cache health strip
- Version 49 — Jun 9, 9:01pm — feat(dashboard): "Where your tokens went" breakdown across the window
- Version 48 — Jun 9, 8:54pm — feat(session): "Where the tokens came from" content breakdown
- Version 47 — Jun 9, 8:35pm — chore(release): 0.3.4 — 24h preset, hourly buckets, area/bar toggle
- Version 46 — Jun 9, 8:31pm — feat(dashboard): hourly buckets for sub-2-day windows + area/bar toggle
- Version 45 — Jun 9, 8:21pm — feat(dashboard): add 24h range preset
- Version 44 — Jun 9, 8:09pm — fix(sidebar): align logo mark with wordmark + add favicon
- Version 43 — Jun 9, 5:09pm — chore(release): 0.3.3 — first release validated on macOS, Windows, Linux
- Version 42 — Jun 9, 5:04pm — ci(publish): verify the published tarball on macos + windows + linux
- Version 41 — Jun 9, 4:57pm — fix: strip Linux better-sqlite3 binary from standalone bundle
- Version 40 — Jun 9, 1:27pm — docs(readme): credit @ushercakes as maintainer
- Version 39 — Jun 9, 11:19am — ci(publish): grant contents:write so the GitHub Release step can run
- Version 38 — Jun 9, 11:14am — chore(release): 0.3.1 — per-day attribution + recall-first README
- Version 37 — Jun 9, 11:03am — fix(range): rangeDays('all') was silently returning 30, not null
- Version 36 — Jun 9, 10:41am — fix(chart): suggestLog uses p10, not median, to catch long-tailed histories
- Version 35 — Jun 9, 10:36am — fix(ingest): fold periodic scheduler into auto.ts, drop instrumentation
- Version 34 — Jun 9, 10:29am — fix(next): externalize bindings + move typedRoutes out of experimental
- Version 33 — Jun 9, 10:25am — fix(backfill): seed synthetic messages for orphaned sessions + close cost gaps
- Version 32 — Jun 9, 10:17am — fix(ingest): preserve all per-session messages + backfill historical tokens
- Version 31 — Jun 9, 9:31am — fix: per-day token attribution + server-side scheduled ingest
- Version 30 — Jun 8, 3:11pm — ci(publish): use npm Trusted Publisher OIDC, no token needed
- Version 29 — Jun 8, 2:57pm — feat: 0.3.0 — project + model filters, model breakdown, share-image graph
- Version 28 — Jun 8, 9:28am — refactor(share): clipboard-copy only, three clean states
- Version 27 — Jun 8, 9:22am — feat(share): native share sheet, dashboard share, sharper copy
- Version 26 — Jun 8, 9:13am — feat: shareable stat-card images for sessions + projects
- Version 25 — Jun 8, 8:55am — fix(quota-widget): portal popover so the chart SVG filter can't bleed
- Version 24 — Jun 8, 8:44am — fix(quota-widget): opaque popover background + copy polish
- Version 23 — Jun 8, 8:40am — fix(dashboard): provider-aware Daily Summary footer
- Version 22 — Jun 7, 9:36pm — chore(release): 0.2.2
- Version 21 — Jun 7, 9:34pm — feat(quota): hover-to-probe widget in the sidebar
- Version 20 — Jun 7, 9:23pm — feat(quota): inline KPIs with auto-probe, drop the strip
- Version 19 — Jun 7, 9:11pm — perf: background ingest + read query memoization
- Version 18 — Jun 7, 8:49pm — chore(release): 0.2.1 — Keychain quota, Codex tab, auto-ingest
- Version 17 — Jun 7, 8:47pm — feat(quota): compact strip + Codex provider tab
- Version 16 — Jun 7, 8:46pm — feat(dashboard): auto-ingest on every render, debounced
- Version 15 — Jun 7, 8:46pm — fix(quota): read Claude credentials from macOS Keychain
- Version 14 — Jun 7, 3:13pm — docs(readme): lead with install, not with prose
- Version 13 — Jun 7, 3:04pm — chore(release): 0.2.0
- Version 12 — Jun 7, 3:04pm — feat(cli): --version flag, expanded --help
- Version 11 — Jun 7, 3:03pm — feat(dashboard): live quota probe against Anthropic
- Version 10 — Jun 7, 2:38pm — docs: anonymize the apifyStuff row in projects.png
- Version 9 — Jun 6, 9:42pm — chore(release): 0.1.1
- Version 8 — Jun 6, 9:30pm — docs: add usage walkthrough to README
- Version 7 — Jun 6, 9:25pm — docs: add screenshot gallery to README
- Version 6 — Jun 6, 9:24pm — build: trim ~13 MB of dead weight from npm tarball
- Version 5 — Jun 6, 9:24pm — chore: drop team-tier ingest surface from OSS build
- Version 4 — Jun 6, 9:15pm — fix(timeline): show multi-day sessions on every day they touched
- Version 3 — Jun 6, 3:01pm — ci: bump matrix to node 22
- Version 2 — Jun 6, 2:58pm — ci: drop deprecated next lint step
- Version 1 — Jun 6, 2:40pm — Initial public release: v0.1.0
Files (108 · 7.1 MB)
- .github/4 files · 9.1 KB
- bin/1 file · 6.7 KB
- docs/10 files · 6.5 MB
- scripts/2 files · 5.9 KB
- src/79 files · 469.0 KB
- .gitignore412 bytes
- CHANGELOG.md31.6 KB
- CONTRIBUTING.md2.3 KB
- LICENSE1.1 KB
- README.md12.8 KB
- next-env.d.ts262 bytes
- next.config.mjs705 bytes
- package-lock.json139.8 KB
- package.json2.2 KB
- postcss.config.js83 bytes
- tailwind.config.ts2.6 KB
- tsconfig.json566 bytes
Open a version to see exactly what changed in it, or download the zip for everything.
Get it on your computer
With the Library Mode tool: librarymode get ken/agentgraphed
Or tell Claude Code / OpenCode: "get ken/agentgraphed from Library Mode"



