toolpath-cursor 0.2.0

Derive Toolpath provenance documents from Cursor's bubble store and agent transcripts
Documentation

toolpath-cursor

Derive Toolpath provenance documents from Cursor sessions.

Cursor stores every conversation across two places — a thin JSONL transcript at ~/.cursor/projects/<slug>/agent-transcripts/<id>/<id>.jsonl (the agent's I/O log, lossy) and a rich SQLite bubble store at ~/Library/Application Support/Cursor/User/globalStorage/state.vscdb (the source of truth). This crate reads the SQLite store (read-only, with content-blob lookup) and maps it to Toolpath documents.

Overview

  • Reading: open state.vscdb via rusqlite, read ItemTable.composer.composerHeaders for the cross-workspace composer index, then per composer pull cursorDiskKV.composerData:<id> and the cursorDiskKV.bubbleId:<comp>:<bubble> rows. Content- addressed file blobs under composer.content.<hash> are looked up while reading so the IR-builder is pure.
  • Provider: implements toolpath_convo::ConversationProvider, pairing user/assistant bubbles into turns, lifting toolFormerData into ToolInvocation, decoding params / result JSON strings, and resolving edit_file_v2 to real before/after file content via the content store.
  • Derivation: produces toolpath::v1::Path documents through the shared toolpath_convo::derive_path. Edit-tool calls surface as sibling artifacts with the full unified diff as raw.

Mapping

Cursor source Toolpath destination
composerData.composerId ConversationView.id, path.id = path-cursor-<first-8>
composerData.modelConfig.modelName Default Turn.model
composerData.name path.meta.title
composerHeader.workspaceIdentifier.uri.fsPath path.base.uri (as file://…)
composerData.agentBackend ("cursor-agent") producer.name ("cursor")
Bubble type: 1 (user) Step with actor: "human:user"
Bubble type: 2 (assistant) Step with actor: "agent:<model>"
bubble.allThinkingBlocks[*].text Turn.thinking
bubble.toolFormerData one entry in Turn.tool_uses[]
toolFormerData.tool == 38 (edit_file_v2) ToolCategory::FileWrite + FileMutation with resolved before/after content and unified diff
toolFormerData.tool == 15 (run_terminal_command_v2) ToolCategory::Shell + ToolResult { content: output, is_error: exitCode != 0 }
toolFormerData.tool == 40 (read_file_v2) ToolCategory::FileRead
toolFormerData.tool == 42 (glob_file_search) ToolCategory::FileSearch
bubble.tokenCount Turn.token_usage
bubble.modelInfo.modelName Turn.model (overrides composer default)
Unknown toolFormerData.tool ids preserved as ToolInvocation { category: None }name + input still carry the call

Provider-specific UI metadata (checkpointId, requestId, capabilityType, richText, Lexical editor DOM, the anysphere.cursor-commits checkpoint store, the AI-authorship SQLite db) is intentionally not smuggled through the IR — those fields don't belong in a cross-harness representation, and the IR has no Turn.extra slot. They round-trip to nothing.

Usage

use toolpath_cursor::{CursorConvo, derive::{DeriveConfig, derive_path}};

let manager = CursorConvo::new();
let composer_id = "724686cd-875e-47da-a90b-dbc3e523efb8";
let session = manager.read_session(composer_id)?;
let path = derive_path(&session, &DeriveConfig::default());
# Ok::<(), toolpath_cursor::CursorError>(())

What's not read

  • ~/Library/Application Support/Cursor/User/globalStorage/anysphere.cursor-commits/ — per-request file snapshots. Their contents duplicate the composer.content.<hash> blobs already keyed in cursorDiskKV.
  • ~/.cursor/ai-tracking/ai-code-tracking.db — per-line AI-vs-human authorship stats. Derivable from the bubble store + git.
  • ~/Library/Application Support/Cursor/User/workspaceStorage/<id>/state.vscdb — per-workspace UI state. The cross-workspace composer.composerHeaders index in the global database covers session listing without it.
  • cursorAuth/* keys — live OAuth tokens. Never read.
  • ~/Library/Application Support/Cursor/logs/ — Chromium / renderer logs.

See docs/agents/formats/cursor.md in the workspace for the full on-disk format reference.

Part of Toolpath

This crate is part of the Toolpath workspace. See also: