Skip to content

Database schema ​

The warehouse is one SQLite file, and logbook sql runs read-only queries over it. These are its tables, as logbook sql --help prints them.

sh
logbook sql "SELECT bare_name, COUNT(*) AS calls FROM tool_call GROUP BY bare_name ORDER BY calls DESC LIMIT 10"

Times are epoch milliseconds, UTC; NULL means the source did not record it. Booleans are 0 or 1. A session id is <harness id>:<source id>; message, tool call and event ids are <session id>/<source id>; a reaction id is <message id>#<n>.

harness ​

One row per adapter any sync registered.

ColumnNotes
idthe adapter id, the prefix of its session ids
name
default_agentshown when a session names no agent
filter_aliasthe word after harness: in the conversation filter
is_found0|1
checked_at
locationwhere the data was found, or where the adapter looked
location_variablesJSON array of the variables that move it
version_seenthe newest harness version the last sync saw
notice
problem

source_state ​

Per source unit, the fingerprint and parser version that decide whether a sync imports it again.

ColumnNotes
harness
locator
fingerprint
parser_version
imported_at

sync_run ​

One row per sync, the newest 100.

ColumnNotes
id
started_at
ended_at
outcomeok|partial|failed|stopped
error

session ​

ColumnNotes
id
harness
source_idthe id the harness shows
origininteractive|scripted|subagent (scripted: a program started it)
is_scripted0|1 (the source shows a program started it)
project_dir
title
agent
spawned_by_session_id
spawned_by_tool_call_id
started_at
ended_at

message ​

ColumnNotes
id
session_id
seqorders a conversation; times can overlap
actoruser|assistant|tool|harness (harness: text the harness injected or wrote in the user's name)
source_rolethe role as the harness recorded it
created_at
completed_at
requested_atwhen the model request behind an assistant message started
model
agent
git_branch
tokens_input
tokens_output
tokens_reasoning
tokens_cache_read
tokens_cache_writetokens per model request
reported_costas the provider reported it; 0 under a subscription is not a price

part ​

ColumnNotes
rowid
message_id
session_id
idxthe part's place in its message
kindtext|reasoning|tool_call|tool_result|compaction
textevery message's text, whole
tool_call_id

part_fts ​

FTS5 over part.text, join on part_fts.rowid = part.rowid; it does not stem, and a quoted phrase matches as a phrase.

ColumnNotes
text

tool_call ​

ColumnNotes
id
session_id
message_id
nameas the model called it
bare_namewithout any server prefix
serverthe MCP server or plugin, NULL for a built-in tool
familyshell|read|edit|search|subagent|dispatch|web|todo|skill|tool-search|question|wait|mcp:<server>|other (dispatch: a tool that starts another agent as its own session)
input_json
statuscompleted|error|pending
child_session_id
started_at
ended_at

event ​

Data_json of the kinds readers parse, only when the harness records them: tools-offered {added, removed, surfaced, pendingServers, needsAuthServers, failedServers [{name, error}]}; tools-loaded {tools [{name, chars}]}; skill-loaded {name, chars, toolCallId} (toolCallId NULL when no call loaded it).

ColumnNotes
id
session_id
kindcompaction|model-switched|agent-switched|idle|error|tools-offered|tools-loaded|skill-loaded|interrupted|tool-rejected|unknown (interrupted: the human stopped the agent; tool-rejected: the human refused a tool call)
at
data_json

Which session started which.

ColumnNotes
parent_session_id
parent_tool_call_id
child_session_id
kindsubagent|dispatch
confidence
evidence

session_command ​

ColumnNotes
session_id
message_id
at
commandwithout its slash
sourcetyped|template
has_file0|1 (1 for a user or project command file, 0 for a harness built-in)

turn ​

Per turn, rebuilt on every sync: wall time is ended_at - started_at, active time model_ms + tool_ms, and parent_turn_id and parent_tool_call_id say where it nests.

ColumnNotes
session_id
message_idits first message, join message.id
seq
is_prompt0|1
requests
tool_calls
started_at
ended_at
model_ms
tool_ms
idle_ms
human_wait_msthe part of idle_ms a tool waited for the human to answer
parent_turn_id
parent_tool_call_id

label ​

One row per field; take a model field from its newest row.

ColumnNotes
record_typetool_call|session|message|reaction
record_idjoin tool_call.id, session.id or message.id; a reaction is <message id>#<n>
labellerrules, rebuilt on every sync, or the model id that gave it, kept
version
name
value
labelled_at

label_run ​

One row per model labelling run.

ColumnNotes
id
pid
started_at
ended_at
outcomeok|stopped|limit|unreachable|failed
error
model

label_run_task ​

One row per task of a labelling run: done of planned records.

ColumnNotes
run_id
task
version
planned
done

forgotten ​

The ids of sessions the user asked Log Book to forget.

ColumnNotes
session_id
forgotten_at

Source-available under the PolyForm Noncommercial License 1.0.0.