skills/swarm-deepdive/references/schema.md

Swarm DB Schema Cheatsheet

Database file: ${SWARM_DB_PATH:-~/.swarm-mcp/swarm.db}. The default is ~/.swarm-mcp/swarm.db; SWARM_DB_PATH overrides it for the MCP server, swarm-ui, and swarm-server.

The database is SQLite with WAL journaling. Ordinary *_at timestamps are Unix seconds unless noted. tasks.changed_at, kv_scope_updates.changed_at, and planner assigned_at payloads are Unix milliseconds.

instances - Live And Recently Live Agents

ColumnNotes
idUUID primary key. actor, assignee, requester, and instance_id columns elsewhere often reference this.
scopeShared directory key. Usually a git root.
directoryWhere the agent was launched.
rootGit root detected at registration time, or the launch directory fallback.
file_rootFilesystem root used to resolve relative paths for locks/tasks.
pidOS PID. 0 is used for UI-precreated, not-yet-adopted rows.
labelFree-form tokens such as role:planner provider:claude team:backend. These are conventions, not schema.
registered_atUnix seconds when the row was created.
heartbeatUnix seconds for the latest heartbeat. Runtime stale threshold is about 30 seconds.
adopted1 after the child MCP process adopts the row. 0 means a UI-spawned PTY row is pending adoption.

Rows disappear on clean deregister or stale reclaim. instance.registered, instance.deregistered, and instance.stale_reclaimed events preserve labels for the 24-hour event window.

tasks - Work Items

ColumnNotes
idUUID.
scopeProject scope.
typereview, implement, fix, test, research, or other.
title / descriptionHuman-readable task text.
requesterInstance ID that created the task.
assigneeInstance ID currently assigned, or NULL.
statusopen, claimed, in_progress, done, failed, cancelled, blocked, or approval_required.
filesJSON array of paths. Paths are resolved through the requester's registration context.
resultJSON string or plain string set on terminal update. Structured convention is {files_changed, test_status, summary}.
priorityInteger. Higher is more urgent; task listing orders by priority descending.
depends_onJSON array of task IDs. Unmet dependencies hold a task in blocked; failed/cancelled dependencies cascade-cancel dependents.
parent_task_idOptional parent for task trees.
idempotency_keyUnique per scope when present; prevents duplicate task creation on retry.
created_at / updated_atUnix seconds.
changed_atUnix milliseconds for polling and UI snapshots.

Active tasks persist. Terminal tasks are deleted after 24 hours when MCP cleanup runs. swarm-ui snapshots also hide terminal tasks whose changed_at is older than 24 hours.

messages - Direct And Broadcast Communication

ColumnNotes
idAuto-increment integer; monotonic message order.
scopeProject scope.
senderInstance ID, or system for some automatic notifications.
recipientInstance ID. Broadcasts are fanned out as one row per recipient.
contentPlain text. [auto] prefixes system notifications; [signal:complete] is the planner completion signal.
created_atUnix seconds.
read1 once the recipient consumed it with poll_messages. CLI and resource peeks do not flip this.

Messages are short-lived. Runtime prune deletes rows older than one hour and deletes queued rows for recipients that deregister or go stale. For message history inside the 24-hour event window, prefer message.sent and message.broadcast events because their payloads include content.

message.cleared events are emitted by swarm-ui when a user clears the history between two instances.

events - Append-Only Audit Log

ColumnNotes
idAuto-increment integer, monotonic per DB.
scopeProject scope.
typeEvent type string. See event families below.
actorInstance ID, system, a UI worker ID, or NULL depending on event source.
subjectMost-relevant entity: task ID, KV key, file path, recipient ID, instance ID, command kind, etc.
payloadJSON detail. Often contains content. Treat as sensitive evidence.
created_atUnix seconds.

Event families currently emitted into swarm.db:

FamilyEvent types
Instancesinstance.registered, instance.deregistered, instance.stale_reclaimed
Taskstask.created, task.claimed, task.updated, task.approved, task.cascade.unblocked, task.cascade.cancelled
Messagesmessage.sent, message.broadcast, message.cleared
KVkv.set, kv.deleted, kv.appended
File contextcontext.annotated, context.lock_acquired, context.lock_released
UI commandsui.command.started, ui.command.completed, ui.command.failed

Payload facts that matter for investigations:

EventPayload notes
message.sentIncludes content and length; subject is the recipient.
message.broadcastIncludes content, recipients, and length; subject is usually NULL.
kv.setIncludes full value and length for MCP-side writes.
kv.deletedIncludes prior_value and prior_length when the row existed.
kv.appendedIncludes parsed appended JSON and resulting array length.
task.createdIncludes type, title, status, assignee, files, priority, dependency and parent fields, and idempotency metadata where present.
task.updatedIncludes status, prior_status, and result where present.
context.annotatedIncludes annotation type, annotation ID, and content.
context.lock_acquired / context.lock_releasedIncludes lock ID/content or release count/reason.
ui.command.*Includes command_id, result or error, and command metadata.

Events are deleted after 24 hours when an MCP server process exits cleanly. The CLI has no events subcommand; inspect this table with SQL.

context - File Locks And Annotations

ColumnNotes
idUUID.
scopeProject scope.
instance_idLock owner or annotation author.
fileAbsolute path.
typelock, finding, warning, note, bug, or todo.
contentLock reason or annotation text.
created_atUnix seconds.

A unique partial index enforces one active lock per (scope, file). Locks clear on explicit unlock, terminal task update for task files, instance deregister, or stale reclaim. Non-lock annotations are deleted after 24 hours when MCP cleanup runs.

kv - Shared Coordination State

ColumnNotes
scopePart of the composite primary key.
keyFree-form. Common namespaces: owner/<role>, progress/<instance-id>, plan/<...>, queue/<...>, handoff/<...>, ui/<...>.
valueText, usually JSON for structured values.
updated_atUnix seconds.

Only the current value lives here. MCP-side kv_set, kv_delete, and kv_append also emit events with enough content to reconstruct changes inside the event window. Some internal swarm-ui KV writes, such as layout and planner-owner refreshes, update kv directly and may not emit kv.* events. Always compare current kv rows against event history before claiming a complete KV timeline.

kv_scope_updates stores one row per scope with changed_at in Unix milliseconds for polling.

ui_commands - Async Desktop UI Queue

ColumnNotes
idAuto-increment integer.
scopeProject scope.
created_byInstance ID of the requester when available.
kindspawn_shell, send_prompt, move_node, organize_nodes, etc.
payloadJSON args.
statuspending, running, done, or failed.
claimed_byUI worker that picked the command up.
result / errorSet on completion/failure.
created_at / started_at / completed_atUnix seconds.

If a command stays pending, no swarm-ui worker is actively claiming commands for that DB. Cross-reference ui.command.started, ui.command.completed, and ui.command.failed events for execution history.