Cursor IDE

The Cursor desktop application, modelled as its own backend (cursor-ide) separate from the terminal CLI. It stores chat history in VS Code-style state.vscdb SQLite databases under the platform user-data directory.

Cursor IDE has no dedicated fast prompt-history backend. Pass --exhaustive to project prompt records from these databases. Targeted effort cannot route this backend.

Stores

Role:

primary_chat

Format:

sqlite

Coverage:

default_search

Adapter:

cursor_ide.state_vscdb_modern.v1, cursor_ide.state_vscdb_legacy.v1

Role:

primary_chat

Format:

sqlite

Coverage:

default_search

Adapter:

cursor_ide.state_vscdb_modern.v1

Role:

app_state

Format:

sqlite

Coverage:

catalog_only

Adapter:

-

Role:

cache

Format:

sqlite

Coverage:

catalog_only

Adapter:

-

Role:

app_state

Format:

text

Coverage:

catalog_only

Adapter:

-

Role:

app_state

Format:

text

Coverage:

private

Adapter:

-

cursor-ide.state_vscdb

cursor-ide.state_vscdb
default store
default store
cursor-ide.state_vscdb

Cursor IDE chat storage; known prompt/chat keys in ItemTable/cursorDiskKV hold conversation JSON. agentgrep does not scan arbitrary state values. Cursor does not publish a formal schema — agentgrep’s parser is the reference implementation. On WSL the store is discovered under the Windows-host mount too (see ADR 0009).

Agent:

Cursor IDE

Role:

primary_chat

Format:

sqlite

Coverage:

default_search

Path:

${HOME}/.config/Cursor/User/globalStorage/state.vscdb

Adapter:

cursor_ide.state_vscdb_modern.v1, cursor_ide.state_vscdb_legacy.v1

Data version:

-

Version strategies:

-

Observed:

Cursor IDE 3.26.13 (2026-10-25)

Default search:

yes

SQLite tables observed (3.26.13, 2026-10-25)

ItemTable columns:

key, value

composerHeaders columns:

composerId, workspaceId, createdAt, lastUpdatedAt, isArchived, isSubagent, recency, checkpointAt, value, subagentTypeName

cursorDiskKV columns:

key, value

Cursor IDE store, parsed by the current cursor_ide.state_vscdb_modern.v1 adapter. Not the same as the Cursor CLI agent transcripts.

cursor-ide.workspace_state

cursor-ide.workspace_state
default store
default store
cursor-ide.workspace_state

Per-workspace state.vscdb, one per opened project under workspaceStorage/<hash>/. Same ItemTable shape as the global store; the aiService.prompts key holds that workspace’s prompt history. The directory hash contributes origin.cwd_hash; sibling workspace.json can contribute origin.cwd. Reuses the cursor_ide.state_vscdb_modern.v1 adapter.

Agent:

Cursor IDE

Role:

primary_chat

Format:

sqlite

Coverage:

default_search

Path:

${HOME}/.config/Cursor/User/workspaceStorage/<hash>/state.vscdb

Adapter:

cursor_ide.state_vscdb_modern.v1

Data version:

-

Version strategies:

-

Observed:

Cursor IDE 3.26.13 (2026-10-25)

Default search:

yes

SQLite tables observed (3.26.13, 2026-10-25)

ItemTable columns:

key, value

composerHeaders columns:

composerId, workspaceId, createdAt, lastUpdatedAt, isArchived, isSubagent, recency, checkpointAt, value, subagentTypeName

cursorDiskKV columns:

key, value

Per-workspace IDE history, complementing the global cursor-ide.state_vscdb. Parsed by the shared cursor_ide.state_vscdb_modern.v1 adapter.

cursor-ide.composer_headers

cursor-ide.composer_headers
catalog store
catalog store
cursor-ide.composer_headers

A third table in the same state.vscdb as ItemTable and cursorDiskKV, holding one row per session: composerHeaders(composerId, workspaceId, createdAt, lastUpdatedAt, isArchived, isSubagent, recency, checkpointAt, value, subagentTypeName). The value JSON carries session identity and origin — name, isWorktree, trackedGitRepos, agentLocation, workspaceIdentifier, referencedPlans. Notably it lists sessions that have neither a composerData: nor a bubbleId: row, which no other store can see at all. agentgrep reads it as a lookup: workspaceIdentifier.uri gives a composer’s working directory, workspaceId its cwd_hash, and name backs up the composerData title. Sessions only this table knows have no turns, so they yield no records.

Agent:

Cursor IDE

Role:

app_state

Format:

sqlite

Coverage:

catalog_only

Path:

${HOME}/.config/Cursor/User/globalStorage/state.vscdb

Adapter:

-

Data version:

-

Version strategies:

shape_inference

Observed:

Cursor IDE 3.26.13 (2026-10-25)

Default search:

no

cursor-ide.server_log

cursor-ide.server_log
catalog store
catalog store
cursor-ide.server_log

The remote server’s startup log for one build, named by the build’s commit: the address it bound and the extension host’s port. Runtime state, not conversation content.

Agent:

Cursor IDE

Role:

app_state

Format:

text

Coverage:

catalog_only

Path:

${HOME}/.cursor-server/.<commit>.log

Adapter:

-

Data version:

-

Version strategies:

-

Observed:

Cursor IDE 3.26.13 (2026-10-25)

Default search:

no

cursor-ide.server_token

cursor-ide.server_token
private store
private store
cursor-ide.server_token

The connection token for one remote-server build, named by its commit. A credential, so it is documented and never enumerated.

Agent:

Cursor IDE

Role:

app_state

Format:

text

Coverage:

private

Path:

${HOME}/.cursor-server/.<commit>.token

Adapter:

-

Data version:

-

Version strategies:

-

Observed:

Cursor IDE 3.26.13 (2026-10-25)

Default search:

no

Record schemas

Global state database

cursor-ide.state_vscdb is the platform-specific global SQLite database (state.vscdb). agentgrep reads known prompt and chat keys in ItemTable/cursorDiskKV; it does not scan arbitrary state values. Global records may not carry project origin because the database is shared across workspaces.

Platform

Path

Linux

~/.config/Cursor/User/globalStorage/state.vscdb

macOS

~/Library/Application Support/Cursor/User/globalStorage/state.vscdb

Windows

%APPDATA%/Cursor/User/globalStorage/state.vscdb

Workspace state databases

cursor-ide.workspace_state covers one state.vscdb per opened project under workspaceStorage/<hash>/. These share the global store’s ItemTable shape; the aiService.prompts key holds that workspace’s typed prompt history. agentgrep enumerates them through the platform workspaceStorage directory and parses them with the same adapter as the global store.

Project context

Store

model

cwd

branch

cursor-ide.state_vscdb

composerData modelConfig.modelName, bubbleId modelInfo.modelName

composerData gitWorktree.worktreePath, else composerHeaders workspaceIdentifier.uri

composerData gitWorktree.branchName

cursor-ide.workspace_state

same composer keys

sibling workspace.json folder URI

composerData gitWorktree.branchName

Cursor keeps the interesting metadata in cursorDiskKV, not in the prompt keys: composerData:<uuid> is the session document, carrying the model it ran under and a gitWorktree block with the worktree path and branch name, and bubbleId:<uuid>:<uuid> is one turn of that session, naming its own model. Both are read, and both are lossless — Cursor writes the path, so --cwd, cwd:, and branch: answer with the real values. A turn that ran in its own worktree keeps its own origin rather than inheriting the session’s.

Per-workspace stores also contribute origin.cwd_hash from the workspaceStorage/<hash> directory, and agentgrep resolves the sibling workspace.json folder URI to origin.cwd. That pair lets --cwd, cwd:, MCP cwd, and cwd_hash: target one Cursor workspace without opening unrelated workspace databases. The workspace cwd is a fact about the database, not a promise about every record in it, so a composer bubble that names a different worktree still wins for its own record.

Where a composer has no gitWorktree block, its row in the cursor-ide.composer_headers table fills in: the workspaceIdentifier.uri folder becomes origin.cwd (a vscode-remote://wsl+<distro> URI maps to its Linux path) and workspaceId becomes origin.cwd_hash, the same digest the per-workspace databases are filed under. Every turn of a composer also takes the session’s name as its title, from composerData, else from composerHeaders. A title is searchable text, so a term in it matches every turn of that composer.

Global state.vscdb records stay conservative when no composer origin is known. They remain searchable by text, agent, scope, and other non-origin fields, but they do not satisfy a hard current-project filter unless the stored record itself carries project metadata.

Note

Cursor publishes no schema for the composerData and bubbleId keys. Every read is guarded, so a schema change degrades to an absent field rather than a wrong one.

Cross-host discovery on WSL

Cursor is a VS Code fork, so when its UI runs on a Windows host and edits a project inside WSL, the IDE chat is written client-side on Windows under /mnt/c/Users/<user>/AppData/Roaming/Cursor/User, not inside the distro. On WSL, agentgrep detects this and also probes the Windows users mount so both the global and per-workspace state.vscdb databases are searchable from Linux. AGENTGREP_WSL_USERS_ROOT overrides the mount root (default /mnt/c/Users) for non-default drive letters. See ADR 0009: Cross-host discovery and remote-workspace path mapping for the design.

Changes by version

Each entry brackets a change between the observation that first saw it and the last one that did not; see Observed record shapes.

Observed 2026-10-25

The observer now reads a version for the WSL remote-server build, 3.26.13 (3.17.8 on 2026-09-11), so this entry is bracketed by date: seen 2026-10-25, absent 2026-09-11. The Windows install directory still has no product.json, so the desktop app’s own version is unread.

  • No store changed shape: the global and workspace state.vscdb tables and columns match the last observation.

  • The remote server keeps a .<commit>.log and a .<commit>.token file per build beside bin/. They are catalogued since as cursor-ide.server_log and cursor-ide.server_token; the token is private.

Observed 2026-09-11

The observer reads no version for the desktop app, so this entry is bracketed by date: seen 2026-09-11, absent 2026-08-08. The WSL remote-server build present at the later date reports Cursor 3.17.8. The Windows install directory has no product.json, so the desktop app’s own version could not be read.

  • composerHeaders, in both the global and per-workspace state.vscdb, adds a subagentTypeName column. agentgrep reads the table for workspace origin and titles, not for that column.