Beads: Building a Version-Controlled Memory System for AI Coding Agents
Hook
Your AI coding agent forgets everything between sessions, or worse—merges conflicts with itself when working across branches. Beads treats agent memory as a database problem, not a file problem.
Context
AI coding agents like Claude Code, Cursor, and Aider have transformed how we write software, but they're fundamentally stateless. Every conversation starts fresh. They can't remember insights from previous sessions, can't track dependencies between tasks, and can't coordinate when multiple agents work on different branches. Developers compensate by dumping context into markdown files (TODO.md, AGENTS.md), but this creates new problems: merge conflicts when agents edit the same task list, no way to track task dependencies, and ever-growing files that blow past context window limits.
Traditional issue trackers like GitHub Issues don't solve this either. They're designed for human project management—web UIs, sequential IDs, complex permission models—when agents need structured JSON, dependency graphs, and zero-conflict merging. The core insight of Beads is recognizing that agent memory is a distributed database problem. By building on Dolt (a version-controlled SQL database that works like Git), Beads provides cell-level merge resolution, content-addressed IDs, and SQL-queryable task graphs that agents can actually use.
Technical Insight
Beads' architecture makes several opinionated choices that differentiate it from file-based task trackers. The most critical is its use of hash-based identifiers instead of sequential IDs. When you create an issue, Beads generates an ID like bd-a7f3 from the content hash. This means two agents creating tasks on different branches will never collide—even if they're working simultaneously. Compare this to sequential IDs (TASK-1, TASK-2) where every new task creates a merge conflict.
The data model stores issues in a SQL schema with explicit dependency relationships:
-- Simplified Beads schema
CREATE TABLE issues (
id VARCHAR(16) PRIMARY KEY, -- hash-based like bd-a7f3
title TEXT,
status ENUM('open', 'in_progress', 'done', 'archived'),
issue_type ENUM('epic', 'task', 'subtask'),
created_at TIMESTAMP,
parent_id VARCHAR(16),
compacted BOOLEAN DEFAULT FALSE
);
CREATE TABLE dependencies (
issue_id VARCHAR(16),
blocks_id VARCHAR(16), -- this issue blocks blocks_id
PRIMARY KEY (issue_id, blocks_id)
);
CREATE TABLE messages (
id VARCHAR(16) PRIMARY KEY,
issue_id VARCHAR(16),
content TEXT,
message_type ENUM('comment', 'insight', 'decision')
);
This schema enables powerful queries that agents can use to find actionable work. The bd ready command, for example, queries for tasks where all dependencies are resolved:
$ bd ready --json
[
{
"id": "bd-f8a2",
"title": "Implement user authentication",
"type": "task",
"parent": "bd-c3d1",
"dependencies_resolved": true,
"context": [
"Remember: Use bcrypt for password hashing (bd-a1b2)",
"Decision: JWT tokens with 24h expiration (bd-e4f5)"
]
}
]
The JSON output is specifically formatted for AI consumption—not human readability. Agents parse this, understand what's actionable, and can even inject relevant historical context from the bd remember command, which stores persistent insights across sessions.
Beads operates in two modes. Embedded mode runs Dolt in-process and uses file-based locking for single-writer scenarios—perfect for individual developers with their own agents. Server mode connects to an external Dolt server, enabling multi-writer scenarios where multiple agents (or developers with agents) collaborate on the same planning database. The mode switch is transparent:
# Embedded mode - local only
$ bd init
$ bd add "Refactor auth module" --type task
# Server mode - collaborative
$ export DOLT_SERVER_URL="http://dolt.company.com:3306/planning"
$ bd add "Add login endpoint" --parent bd-f8a2
The most innovative feature is semantic compaction. As issue threads grow long with messages and updates, they consume precious context window tokens. Beads can compact old issues by summarizing their history:
$ bd compact bd-a7f3 --threshold 30d
Compacted bd-a7f3: 847 tokens → 124 tokens
Summary: Implemented OAuth2 flow. Decision to use PKCE.
Final state: Complete, merged in PR #234.
This compaction is lossy but intentional—keeping full history in Dolt's version control while presenting agents with condensed context. You can always dolt checkout to a previous commit and see the full uncompacted history.
The integration with coding agents happens through instruction files. You create an AGENTS.md file that tells the agent to consult Beads:
# Agent Instructions
Before starting work:
1. Run `bd prime` to inject current context
2. Check `bd ready --json` for actionable tasks
3. After completing work, run `bd done <issue-id>`
4. Use `bd remember <insight>` to store important decisions
When you discover architectural insights or make decisions,
always record them with `bd remember` so future sessions
don't repeat the same analysis.
The bd prime command is particularly clever—it generates a condensed context document with active tasks, recent decisions, and dependency chains, formatted to fit within typical 8K-32K context windows. Agents like Claude can ingest this at session start and maintain coherent long-term planning.
Gotcha
Beads' reliance on Dolt is both its strength and weakness. You need either the Dolt binary installed or must set up a Dolt server for multi-writer scenarios. This adds operational complexity—Dolt itself is a sophisticated piece of infrastructure with its own versioning semantics, storage requirements, and learning curve. If you're working in a locked-down environment or deploying to constrained systems, the Dolt dependency is non-trivial.
Embedded mode's single-writer constraint is more limiting than it first appears. If you run multiple agent sessions simultaneously (say, Claude on one feature branch, Cursor on another), they can't both write to the Beads database without setting up server mode. The file lock prevents corruption but forces serialization. Additionally, while hash-based IDs prevent conflicts, they're not human-friendly. Remembering that "bd-a7f3 blocks bd-f8a2" requires either excellent memory or constantly querying the database. This is fine for agents parsing JSON, but painful when you need to manually intervene or debug workflows. The project is also relatively young despite its GitHub stars, meaning the ecosystem of integrations, editor plugins, and community workflows is still emerging. You're an early adopter.
Verdict
Use if: You're building multi-agent systems where agents need to coordinate across branches or sessions, you're hitting context window limits with existing TODO files, or you're working in distributed teams where merge conflicts in planning documents are a constant headache. Beads shines when you need structured dependency tracking and your agents are sophisticated enough to consume JSON output. Skip if: You're running simple single-agent workflows where a markdown TODO file suffices, you can't install or manage Dolt in your environment, or you need tight integration with existing project management tools like Jira or Linear. Also skip if your team doesn't use AI coding assistants heavily—Beads is purpose-built for agent memory, and its human UX is deliberately minimal. For traditional project management, stick with traditional tools.