Blog Comparisons

Beads Is Excellent Until Two People Need the Same Board

A field guide to where Beads' local-first, Dolt-backed model stops paying off, and what a hosted tracker costs you in exchange.

A cluttered developer desk shot from above with two open laptops showing terminal windows, dim office lighting, candid not staged.
Photo from Unsplash

The short answer

Beads is a free, MIT-licensed CLI issue tracker that stores tasks in Dolt, a version-controlled SQL database, not in a flat JSONL file as many earlier write-ups still describe. It works well for one developer and their agents in a single clone. The model gets expensive once a second developer needs concurrent write access, once someone without the CLI needs to see status, or once an external audit needs to know a change was made by an authenticated person rather than a self-reported actor string. A hosted tracker such as Trail trades Beads' zero-cost, git-adjacent storage for a shared server, a client-facing view, and per-account attribution.

You installed Beads three weeks ago, watched your agent file its own dependency graph without being asked, and it has been quietly excellent. Then a second developer cloned the repo and tried to claim a task at the same time you did. This is not a takedown of Beads - the first section below says plainly what it gets right, and none of it stops being true. It is an inventory of exactly where the model that makes Beads so good for one developer in one clone stops covering what a real project needs, and what you trade away going the other direction.

What Beads gets right, stated plainly

Beads is a free, MIT-licensed issue tracker built for AI coding agents, with more than 26,000 stars on GitHub. It replaces the markdown scratch file your agent used to keep - the one that a context reset quietly erases - with a real dependency graph, and bd init writes agent-facing instructions straight into your project's AGENTS.md rather than a proprietary file. bd ready computes which tasks have no open blockers in milliseconds, entirely offline. bd update <id> --claim atomically assigns and starts a task so two agents can't grab the same one. Hash-based IDs like bd-a1b2 replace sequential numbers specifically so that two branches creating issues at the same time never mint the same ID. None of this needs a subscription, an account, or a network connection. For one developer running one or several agents against one clone, it is a genuinely well-designed tool, and it's free.

The storage model, and what people get wrong about it

Here is the correction most write-ups about Beads still miss: it is not a JSONL-in-git tool. Earlier versions were closer to that shape, but as of version 0.56.0 in February 2026, Beads removed the JSONL sync pipeline entirely - "the entire JSONL-based sync system (bd sync, git-portable mode, belt-and-suspenders mode) has been removed." Issues live in Dolt, a version-controlled SQL database that applies git-style commits, branches, and merges to table rows instead of text files. Beads' own sync concepts doc is explicit: "the local Dolt database is the source of truth... .beads/issues.jsonl is an export. It exists for viewers, interchange, migration, and backup. It is not the canonical cross-machine sync channel." Cross-machine sync happens through bd dolt push / bd dolt pull, which move history under a separate refs/dolt/data ref on your normal git remote - adjacent to your source code's git history, not stored inside it.

Merge conflicts are the tax, and they are payable

Because Dolt merges at the cell level rather than the line level, two people editing different fields on the same issue almost always merge cleanly - DoltHub's own blog post on cell-level three-way merge walks through exactly this case, and the mechanism is also covered in Dolt's merge reference. Beads' FAQ confirms the practical result: "Dolt merges at the cell level, so most concurrent changes resolve automatically." The one case that still produces a real conflict - both sides changing the same field - gets a documented runbook: back up .beads, run bd doctor, then bd doctor --fix to reconcile before pushing again.

25%
The hash-ID collision probability Beads tolerates before automatically growing ID length - a bet on the IDs staying unique, not a promise about what two people write into the same field. Beads collision math

That threshold is deliberate: Beads' own collision math shows that even at a 25% collision probability, the expected number of actual collisions stays under one per thousand issues created. ID collisions were solved thoroughly. Field-level conflicts are handled well but not silently - someone still has to notice the pull failed, run the fix, and push again.

Wall one: the second developer on the same board

The conflict math is generous, but it assumes both people are already writing to the same store. By default, they are not. Beads' Dolt architecture guide is direct about this: "Embedded mode is single-writer (enforced via file lock). If you need concurrent access, switch to server mode." Embedded mode - the default since bd init - runs Dolt in-process with no server to manage, which is exactly what makes solo use frictionless. It is also why a second developer working from a second clone at the same time isn't merely inconvenient, it's blocked, until someone runs bd init --server, stands up a dolt sql-server process, and everyone reconnects to it:

# turning a solo embedded project into a shared one
cd ~/.dolt-data/beads && dolt sql-server --port 3307
cd your-project
bd init --server

Even after that, there is no live shared board. Nothing pushes to you; you pull. Beads' own comparison table in its FAQ names this tradeoff without flinching: offline-first task memory is a feature until someone else's clone is the one with the current state, and "GitHub Issues and Jira excel for human teams working in a web UI with cross-repo dashboards and integrations." Beads doesn't try to be that, deliberately.

Mode Writers Where data lives Extra process to run
Embedded (default) One .beads/embeddeddolt/ None
Server (bd init --server) Multiple, concurrent .beads/dolt/ dolt sql-server
Hosted (e.g. Trail) Any number Vendor's servers None, on any device
Two people's hands over an open laptop on a dark table, one pointing at the screen.
Two developers on the same project is exactly the case Beads' embedded mode was not built to handle without extra setup.

Wall two: someone who is not a developer needs to look

Beads has no official web UI, by design - it's a CLI tool with a Dolt database underneath. The community has filled some of that gap: community-built UIs range from terminal dashboards to Tauri desktop apps, and at least one, Bead Me Up, Scotty, adds human-vs-agent attribution and a static "publish" view. None of them are official, none ship with Beads, and all of them assume the viewer already has bd and repo access installed. A client, a project sponsor, or a manager who has never opened a terminal isn't the audience any of that was built for - Beads' own FAQ says so directly, naming the audience it's optimized for as agents that need offline, version-controlled task memory, not human teams wanting a dashboard.

This is the specific gap Trail was built to close from the other direction. Every card an agent writes over MCP into Trail also lands on a hosted, read-only client portal that a non-technical stakeholder opens in a browser with no CLI and no repo access, plus PDF delivery reports for anyone who wants a record rather than a login. It's a paid feature on Trail's Team and Studio plans, and it's the one thing on this list that a local Dolt database structurally can't hand to someone outside your machine without you building the bridge yourself.

Wall three: authorship you can hand to an auditor

Beads does track who did what. Every mutation carries an actor, and bd show prints who created and touched an issue. What that attribution is not is authenticated identity. Beads' own changelog is unusually candid about this, describing its own bearer-token server auth: "a token is a shared secret granting the whole surface, not an identity, so actor is still caller-asserted provenance and not the authenticated principal." In plain terms: the CLI takes your word for who you are. That's a reasonable tradeoff for a tool built to run offline on a laptop, and it costs nothing until someone external - a client, an enterprise security review, or a regulator asking who changed what and when - needs a record tied to a logged-in account rather than a string a process passed in.

What you actually give up by going hosted

None of this is one-directional. The base of this whole market is free and open source, and Beads sits in good company there - Trail does not, and charges for anything past three projects. Beads' issues live inside your own git-adjacent history, portable and yours forever; Trail's live on a vendor's servers, and if your hard requirement is that your issue data ships inside your own repository, Beads is the correct shape and Trail is not. Beads also works fully offline on a plane with no account anywhere - genuinely useful, and not something a hosted board can match. And Beads keeps every project's data in that project's own repo by design, which sidesteps a different problem entirely: an agent bleeding context between repos it shouldn't be able to see.

A decision table instead of a verdict

If you are... Beads covers you Look at a hosted tracker instead
One developer, one clone, offline-friendly Yes - this is the design target Not necessary
A small team writing to the same board daily Only after switching to server mode and running it Worth it if nobody wants to own a database process
Working with someone who won't touch a CLI No - no official viewer ships with Beads Yes - this is the specific gap a client portal fills
Needing to show an external party a signed-off record Partially - attribution exists but is self-reported Yes, if the record needs an authenticated identity behind it

If you are staying on Beads, do these three things

Most readers of a post like this one are staying on Beads for now, and that's a reasonable call. Three concrete adjustments make the walls above smaller without switching tools:

  1. Move to server mode the day a second person joins the repo, not after the first conflict. bd init --server plus a shared dolt sql-server costs one setup conversation; a corrupted merge costs an afternoon.
  2. Run bd dolt pull at the start of every session and bd dolt push at the end, on a habit, not a memory. Nothing notifies you that someone else's clone has moved ahead.
  3. Pick one community viewer from the community tools list before a non-developer asks for a status update, not after. A read-only dashboard set up in advance costs you nothing; explaining bd show over a screen share does.

None of that closes wall three - there's no local configuration that turns caller-asserted attribution into an authenticated one - but it removes the two walls that are actually about setup order rather than architecture. For a broader look at how the current field of agent-native issue trackers compares, including tools that made different tradeoffs than either Beads or Trail, that's the next post to read.

What to remember

  • Beads is MIT-licensed and free, and stores issues in Dolt, a version-controlled SQL database, not in git-committed JSONL as its own docs now explicitly correct.
  • The default embedded storage mode is single-writer, enforced by a file lock; a second concurrent contributor requires switching to server mode and running a live dolt sql-server process.
  • Dolt resolves most concurrent edits automatically with cell-level three-way merge, and Beads' own collision math tolerates up to a 25 percent hash-ID collision probability before growing ID length.
  • Beads' FAQ states plainly that GitHub Issues and Jira, not Beads, are the better fit for human teams working in a web UI.
  • Beads records an actor on each mutation, but its changelog is explicit that the actor is caller-asserted provenance, not an authenticated identity, even behind bearer-token auth.
  • Trail's honest tradeoff going the other way is that it is a hosted product, not free, and issues do not live in your git repo the way Beads' do.

Questions people ask

Is Beads free to use?

Yes. Beads is MIT-licensed and open source, published at github.com/steveyegge/beads with more than 26,000 stars, and there is no paid tier for the CLI itself. Community-built UIs, editor extensions, and desktop apps built around it are listed separately and carry their own licenses.

Does Beads still store issues as JSONL files in git?

No, not since version 0.56.0 in February 2026. Beads issues live in Dolt, a version-controlled SQL database; .beads/issues.jsonl is only an export kept for viewers, migration, and backup, and cross-machine sync runs through bd dolt push and bd dolt pull against a separate ref on your normal git remote, not through committing that JSONL file.

Can multiple developers use Beads on the same project at once?

Yes, but not by default. The default embedded storage mode allows only one writer at a time, enforced by a file lock, which is fine for one person but blocks a second concurrent contributor outright. Concurrent writers require initializing with bd init --server and running a dolt sql-server process that everyone's bd connects to over a port.

What happens when two people edit the same Beads issue at the same time?

Dolt merges most changes automatically at the individual field level, so edits to different fields on the same issue rarely conflict, and hash-based IDs mean two people creating separate issues never collide either. When both sides change the same field, bd dolt pull reports a real conflict, and a documented runbook walks you through resolving it with bd doctor --fix before pushing again.

Which AI coding agents does Beads work with?

Beads is agent-agnostic at the CLI level and ships setup helpers for several, including bd setup claude for Claude Code, bd setup codex, bd setup factory for Factory.ai Droid, and bd setup cursor, plus a separate beads-mcp package on PyPI for agents that integrate through MCP instead of the CLI directly.

Keep reading