Architecture Overview
This document explains how Beads' three-layer architecture works: Git, JSONL, and SQLite.
The Three Layersβ
Beads uses a layered architecture where each layer serves a specific purpose:
flowchart TD
subgraph GIT["ποΈ Layer 1: Git Repository"]
G[(".beads/*.jsonl<br/><i>Historical Source of Truth</i>")]
end
subgraph JSONL["π Layer 2: JSONL Files"]
J[("issues.jsonl<br/><i>Operational Source of Truth</i>")]
end
subgraph SQL["β‘ Layer 3: SQLite"]
D[("beads.db<br/><i>Fast Queries / Derived State</i>")]
end
G <-->|"bd sync"| J
J -->|"rebuild"| D
D -->|"append"| J
U((π€ User)) -->|"bd create<br/>bd update"| D
D -->|"bd list<br/>bd show"| U
style GIT fill:#2d5a27,stroke:#4a9c3e,color:#fff
style JSONL fill:#1a4a6e,stroke:#3a8ac4,color:#fff
style SQL fill:#6b3a6b,stroke:#a45ea4,color:#fff
Git is the historical source of truthβcommits preserve the full history of your issues and can be recovered from any point in time.
JSONL is the operational source of truthβwhen recovering from database corruption, Beads rebuilds SQLite from JSONL files, not directly from Git commits.
This layered model enables recovery: if SQLite is corrupted but JSONL is intact, run bd sync --import-only to rebuild. If JSONL is corrupted, recover it from Git history first.
Layer 1: Git Repositoryβ
Git is the historical source of truth. All issue data lives in the repository alongside your code, with full history preserved in commits.
Why Git?
- Issues travel with the code
- No external service dependency
- Full history via Git log (recover any point in time)
- Works offline
- Enables multi-machine and multi-agent workflows
Layer 2: JSONL Filesβ
JSONL (JSON Lines) files store issue data in an append-only format. This is the operational source of truthβSQLite databases are rebuilt from JSONL.
Location: .beads/*.jsonl
Why JSONL?
- Human-readable and inspectable
- Git-mergeable (append-only reduces conflicts)
- Portable across systems
- Can be recovered from Git history
- Recovery source:
bd sync --import-onlyrebuilds SQLite from JSONL
Layer 3: SQLite Databaseβ
SQLite provides fast local queries without network latency. This is derived stateβit can always be rebuilt from JSONL.
Location: .beads/beads.db
Why SQLite?
- Instant queries (no network)
- Complex filtering and sorting
- Derived from JSONL (always rebuildable)
- Safe to delete and rebuild:
rm .beads/beads.db* && bd sync --import-only
Data Flowβ
Write Pathβ
User runs bd create
β SQLite updated
β JSONL appended
β Git commit (on sync)
Read Pathβ
User runs bd list
β SQLite queried
β Results returned immediately
Sync Pathβ
User runs bd sync
β Git pull
β JSONL merged
β SQLite rebuilt if needed
β Git push
Sync Modesβ
Beads provides specialized sync modes for different recovery scenarios:
Standard Syncβ
bd sync
Normal bidirectional sync: pulls remote changes, merges JSONL, rebuilds SQLite if needed, pushes local changes.
Import-Only Modeβ
bd sync --import-only
Rebuilds the SQLite database from JSONL without pushing changes. Use this when:
- SQLite is corrupted or missing
- Recovering from a fresh clone
- Rebuilding after database migration issues
This is the safest recovery option when JSONL is intact.
Force Rebuild Modeβ
bd sync --force-rebuild
Forces complete SQLite rebuild from JSONL, discarding any SQLite-only state. Use with caution:
- More aggressive than
--import-only - May lose any uncommitted database state
- Recommended when standard sync fails repeatedly
Multi-Machine Sync Considerationsβ
When working across multiple machines or clones:
-
Always sync before switching machines
bd sync # Push changes before leaving -
Pull before creating new issues
bd sync # Pull changes first on new machine
bd create "New issue" -
Avoid parallel edits - If two machines create issues simultaneously without syncing, conflicts may occur
See Sync Failures Recovery for data loss prevention in multi-machine workflows (Pattern A5/C3).
The Daemonβ
The Beads daemon (bd daemon) handles background synchronization:
- Watches for file changes
- Triggers sync on changes
- Keeps SQLite in sync with JSONL
- Manages lock files
The daemon is optional but recommended for multi-agent workflows.
Running Without the Daemonβ
For CI/CD pipelines, containers, and single-use scenarios, run commands without spawning a daemon:
bd --no-daemon create "CI-generated issue"
bd --no-daemon sync
When to use --no-daemon:
- CI/CD pipelines (Jenkins, GitHub Actions)
- Docker containers
- Ephemeral environments
- Scripts that should not leave background processes
- Debugging daemon-related issues
Daemon in Multi-Clone Scenariosβ
When multiple git clones of the same repository run daemons simultaneously, race conditions can occur during push/pull operations. This is particularly common in:
- Multi-agent AI workflows (multiple Claude/GPT instances)
- Developer workstations with multiple checkouts
- Worktree-based development workflows
Prevention:
- Use
bd daemons killallbefore switching between clones - Ensure only one clone's daemon is active at a time
- Consider
--no-daemonmode for automated workflows
See Sync Failures Recovery for daemon race condition troubleshooting (Pattern B2).
Recovery Modelβ
The three-layer architecture makes recovery straightforward because each layer can rebuild from the one above it:
- Lost SQLite? β Rebuild from JSONL:
bd sync --import-only - Lost JSONL? β Recover from Git history:
git checkout HEAD~1 -- .beads/issues.jsonl - Conflicts? β Git merge, then rebuild
Universal Recovery Sequenceβ
The following sequence demonstrates how the architecture enables quick recovery. For detailed procedures, see Recovery Runbooks.
This sequence resolves the majority of reported issues:
bd daemons killall # Stop daemons (prevents race conditions)
git worktree prune # Clean orphaned worktrees
rm .beads/beads.db* # Remove potentially corrupted database
bd sync --import-only # Rebuild from JSONL source of truth
bd doctor --fixAnalysis of 54 GitHub issues revealed that bd doctor --fix frequently causes more damage than the original problem:
- Deletes "circular" dependencies that are actually valid parent-child relationships
- False positive detection removes legitimate issue links
- Recovery after
--fixis harder than recovery from the original issue
Safe alternatives:
bd doctorβ Diagnostic only, no changes madebd blockedβ Check which issues are blocked and whybd show <issue-id>β Inspect a specific issue's state
If bd doctor reports problems, investigate each one manually before taking any action.
See Recovery for specific procedures and Database Corruption Recovery for bd doctor --fix recovery (Pattern D4).
Design Decisionsβ
Why not just SQLite?β
SQLite alone doesn't travel with Git or merge well across branches. Binary database files create merge conflicts that are nearly impossible to resolve.
Why not just JSONL?β
JSONL is slow for complex queries. Scanning thousands of lines for filtering and sorting is inefficient. SQLite provides indexed lookups in milliseconds.
Why append-only JSONL?β
Append-only format minimizes Git merge conflicts. When two branches add issues, Git can cleanly merge by concatenating the additions. Edit operations append new records rather than modifying existing lines.
Why not a server?β
Beads is designed for offline-first, local-first development. No server means no downtime, no latency, no vendor lock-in, and full functionality on airplanes or in restricted networks.
Trade-offsβ
| Benefit | Trade-off |
|---|---|
| Works offline | No real-time collaboration |
| Git-native history | Requires Git knowledge |
| No server dependency | No web UI or mobile app |
| Local-first speed | Manual sync required |
| Append-only merging | JSONL files grow over time |
When NOT to use Beadsβ
Beads is not suitable for:
- Large teams (10+) β Git-based sync doesn't scale well for high-frequency concurrent edits
- Non-developers β Requires Git and command-line familiarity
- Real-time collaboration β No live updates; requires explicit sync
- Cross-repository tracking β Issues are scoped to a single repository
- Rich media attachments β Designed for text-based issue tracking
For these use cases, consider GitHub Issues, Linear, or Jira.
Related Documentationβ
- Recovery Runbooks β Step-by-step procedures for common issues
- CLI Reference β Complete command documentation
- Getting Started β Installation and first steps