Skip to content

Index schema

The SQLite index at ~/.claudex/index.db. Schema version: 3.

Not a stable surface

Table and column names may change between releases. Use claudex <cmd> --json for automation. This page is for curiosity and debugging.

meta

Single-row key/value scratchpad.

ColumnTypeNotes
keyTEXT PKe.g. schema_version, last_sync.
valueTEXTStringified value.

schema_version is the source of truth for rebuild-on-mismatch logic.

sessions

One row per JSONL file.

ColumnTypeNotes
idINTEGER PKSurrogate key.
project_nameTEXTDecoded project name, with (worktree) for worktree sessions.
file_pathTEXT UNIQUEAbsolute path to the JSONL.
file_sizeINTEGERBytes. Part of the incremental-sync key.
file_mtimeINTEGERUnix seconds. Part of the sync key.
session_idTEXTSession UUID from Claude Code.
first_timestampINTEGERUnix ms.
last_timestampINTEGERUnix ms.
duration_msINTEGERLast minus first.
message_countINTEGERUser + assistant.
modelTEXTSole model tag, or mixed when a session switched models.
indexed_atINTEGERUnix seconds.

Indexes: idx_sessions_project, idx_sessions_timestamp.

token_usage

One row per (session, model) pair. A session that switched models has multiple rows.

ColumnNotes
session_idFK → sessions.id (ON DELETE CASCADE).
modelModel tag.
assistant_message_countAssistant messages contributing to the row.
input_tokens, output_tokens, cache_creation_tokens, cache_read_tokensFour counters.
cost_usdPre-computed cost for this row.
inference_geoDistinct reported regions for the row, joined with ASCII Unit Separator (\u001f) in the raw DB value.
speedAverage tokens/sec for the session-model row, if reported.
service_tierDistinct reported service tiers for the row, joined with ASCII Unit Separator (\u001f) in the raw DB value.
iterationsCount of messages contributing to the row.

Index: idx_token_usage_session.

tool_calls

One row per (session, tool_name) pair.

ColumnNotes
session_idFK.
tool_nameTool name as reported (e.g. Edit, Bash, mcp__*__*).
countInvocations.

Index: idx_tool_calls_session.

turn_durations

One row per turn.

ColumnNotes
session_rowidFK.
turn_number1-based.
duration_msWall-clock from user message to assistant reply.
timestampISO-8601 string of the user message.

Index: idx_turn_durations_session.

One row per PR URL detected in the session.

ColumnNotes
session_rowidFK.
pr_numberParsed from URL.
pr_urlFull URL.
pr_repositoryowner/repo.
timestampWhen the URL appeared.

file_modifications

One row per file edit event.

ColumnNotes
session_rowidFK.
file_pathAs recorded.
is_snapshot_update1 for standard Edit/Write; 0 for special cases.

Indexes: idx_file_mods_session, idx_file_mods_path.

thinking_usage

ColumnNotes
session_rowidFK.
thinking_blocksCount of extended-thinking blocks.
thinking_tokensToken count, if available.

stop_reasons

ColumnNotes
session_rowidFK.
stop_reasonend_turn, tool_use, max_tokens, etc.
countNumber of messages with this reason.

attachments

ColumnNotes
session_rowidFK.
filenameAs attached.
mime_typeIf recorded.

permission_changes

ColumnNotes
session_rowidFK.
modePermission mode switched into.
timestampISO-8601.

messages_fts (virtual)

FTS5 virtual table over every user + assistant message.

sql
CREATE VIRTUAL TABLE messages_fts USING fts5(
    session_id   UNINDEXED,
    message_type,
    content,
    timestamp    UNINDEXED,
    tokenize     = 'porter unicode61'
);

Used by search. The porter stemmer means migrat matches migration, migrated, migrates.

Migration strategy

Schema changes follow one rule: bump SCHEMA_VERSION. A version mismatch on open triggers a full rebuild. Additive changes (new column defaulting to 0, new table) go inside the same CREATE TABLE IF NOT EXISTS block; destructive changes still need a version bump.

Released under the MIT License.