Claude Code vs Cursor: What Your AI Coding Tools Store Locally
One stores everything as plain-text JSONL. The other spreads data across SQLite databases, global state blobs, and checkpoint systems. A side-by-side comparison of how Claude Code and Cursor handle local storage — and why it matters.
Run these two commands:
du -sh ~/.claude/
du -sh ~/.cursor/ ~/Library/Application\ Support/Cursor 2>/dev/null
On my machine, Claude Code weighs in at 858 MB. Cursor? 2.1 GB in ~/.cursor/ plus another 4.9 GB in Application Support — 7 GB total.
Both tools record everything: your prompts, the AI’s responses, tool calls, file edits, thinking traces. But they store it in fundamentally different ways.
I spent weeks reverse-engineering both systems while building vibe-replay. Here’s what I found.
The one-sentence summary
Claude Code = one JSONL file per session. Readable, greppable, done.
Cursor = a distributed storage system across SQLite databases, JSONL transcripts, global state blobs, workspace DBs, and checkpoint diffs. Powerful, but not something you casually inspect.
Session storage: text files vs. a database stack
Claude Code
Every session is a single JSONL file in ~/.claude/projects/:
~/.claude/projects/<project-hash>/<session-id>.jsonl
Each line is a JSON object — a user message, an assistant response, a tool call, a system event. You can cat it, jq it, pipe it through anything.
129 sessions on my machine. That’s 129 files. Simple.
Cursor
Cursor has at least three primary storage layers:
| Layer | Location | Format |
|---|---|---|
| Chat databases | ~/.cursor/chats/*/*/store.db | SQLite |
| Transcript files | ~/.cursor/projects/*/agent-transcripts/*.jsonl | JSONL |
| Global state | ~/Library/Application Support/Cursor/User/globalStorage/state.vscdb | SQLite (1.24 GB) |
On my machine, that’s 171 SQLite chat databases, 138 transcript JSONL files, and a global state.vscdb with over 88,000 key-value entries just in the agentKv family.
The critical detail: these layers don’t share a universal session ID. My store.db session IDs and composerData session IDs were completely disjoint. Cursor effectively has two separate replay stacks, and transcript files can attach to either one.
What’s inside the data?
Both tools record more than just chat messages. Here’s a side-by-side comparison:
| What’s stored | Claude Code | Cursor |
|---|---|---|
| User prompts | In session JSONL | Across transcripts, store.db, composerData |
| AI responses | In session JSONL | Across transcripts, store.db, bubbleId blobs |
| Tool calls | In session JSONL (structured) | In bubble payloads (toolFormerData) |
| Token counts | Every response, exact | Some bubbles (inputTokens/outputTokens), but coverage is uneven |
| Thinking traces | Full extended thinking blocks (2,130 in my data) | thinkingDurationMs on some bubbles |
| File context | Implicit via Read/Edit tool calls | Explicit relevantFiles, recentlyViewedFiles fields |
| Sub-agents | Separate JSONL files per sub-agent | No equivalent (Cursor subagents are server-side) |
| Screenshots | Base64 PNG inline (343 in my data) | Image references in some bubbles |
| Cache metrics | Exact per-response (cache read/create tokens) | Not exposed locally |
The cost visibility gap
Claude Code logs exact token counts on every response. Aggregate them and you get real numbers:
| Metric | Value |
|---|---|
| Cache read tokens | 3.25 billion |
| Cache hit rate | 97.8% |
| API-equivalent cost | ~$7,900 |
| Saved by caching | ~$42,300 |
Cursor logs token counts on some bubbles, but coverage is inconsistent. Any aggregate cost estimate is a lower bound, not a full picture.
File recovery
Claude Code
Before every edit, Claude Code saves a snapshot to ~/.claude/file-history/:
file-history/<session-uuid>/
├── 12e0d72e037caf5f@v1 # before first edit
├── 12e0d72e037caf5f@v2 # before second edit
├── 12e0d72e037caf5f@v3 # before third edit
36 MB of versioned file snapshots on my machine. Plus the built-in /rewind command.
Cursor
File recovery is split across three systems:
- Agent checkpoints — diffs and metadata in
~/Library/Application Support/Cursor/User/globalStorage/anysphere.cursor-commits/checkpoints/ - VS Code local history — in
~/Library/Application Support/Cursor/User/History/(5,162 files on my machine) - Git — standard version control
Cursor checkpoints are real and useful, but they’re keyed by request ID, not session ID, so you need to cross-reference to find the right one.
Prompt history
Claude Code
~/.claude/history.jsonl — a global index of every prompt across all projects:
{
"display": "Fix the authentication bug in login.ts",
"timestamp": 1772598497513,
"project": "/Users/you/Code/myapp",
"sessionId": "f79f8cf8-..."
}
1,642 entries on my machine. Timestamped, project-tagged, session-linked.
Cursor
~/.cursor/prompt_history.json — 500 plain strings. No timestamps, no project association, no session links. A rolling buffer, not a structured log.
Data retention
Claude Code has a default 30-day TTL. Old sessions get cleaned up automatically. You can see this clearly if you check file dates.
Cursor shows no evidence of automatic cleanup. I found store.db files older than 30 days (61 of them), and local history entries going back months. It appears to keep everything indefinitely.
The AI attribution database (Cursor only)
This was the most surprising Cursor-specific finding. At ~/.cursor/ai-tracking/ai-code-tracking.db, Cursor maintains a dedicated database for tracking AI-generated code:
- 42,000 hash entries linking code to sources (
cli,composer) - 1,071 scored commits with fields like
tabLinesAdded,composerLinesAdded,humanLinesAdded,v2AiPercentage
Cursor is tracking, at the commit level, how much of your code was written by AI vs. by you. Claude Code has no equivalent.
Context compaction
Both tools hit context window limits and need to manage them.
Claude Code handles this transparently: when the context fills up, it compresses the conversation and continues. Every compaction event is logged in the session JSONL with metadata (trigger, pre-compaction token count). I found 51 compaction events across my sessions.
Cursor manages context server-side. Local artifacts don’t expose compaction events in the same way.
The architectural takeaway
| Claude Code | Cursor | |
|---|---|---|
| Philosophy | One format, one location | Multiple systems, layered |
| Session format | Plain-text JSONL | SQLite + JSONL + KV blobs |
| Inspectability | cat and jq | Need SQLite tools + custom parsing |
| Session ID model | One ID per session | Multiple overlapping ID spaces |
| Total local footprint | ~858 MB | ~7 GB |
| Data retention | 30-day TTL | Appears indefinite |
| Cost visibility | Complete | Partial |
Neither approach is objectively “better.” Claude Code’s simplicity makes it trivially inspectable — any developer can jq their way through a session file. Cursor’s complexity reflects a different architecture: an IDE that needs to track editor state, checkpoints, file history, and AI attribution all at once.
But if you’re trying to understand what your AI coding tool actually did — what it tried, what it cost, where it struggled — the data accessibility gap is real.
One tool that reads both
This is why I built vibe-replay.
npx vibe-replay
One command. It discovers both Claude Code and Cursor sessions, merges their respective storage formats, and generates an interactive replay you can open in any browser.
For Claude Code, it reads the JSONL directly. For Cursor, it merges the JSONL transcripts, SQLite chat databases, and global state blobs into a unified session view.
No server, no account, no data leaves your machine. The output is a self-contained HTML file you can share with your team or publish to the cloud.
Your AI coding tools store everything. Now you can actually see it.
Try it on your sessions · Watch a live demo · Explore public replays