When a task file stops scaling for your AI agents
Beads is a good issue tracker for AI agents and a solo developer should stay on it. Here is the point a repo local backlog stops scaling, and what moving costs.

A teammate asks where the auth rewrite stands. The answer lives in a database inside your working copy, and the fastest way to show them is a screenshot of bd list in Slack. Nothing is broken. You just cannot hand anyone a link.
We build Taskfolk, a hosted tracker, so the bias is obvious. What follows is where a repo local backlog stops fitting, what moving costs, and how to move back out. If you stay put, that is a correct outcome.
What Beads gets right, and who should stay on it
Beads (bd) is a graph issue tracker built as memory for coding agents. MIT licensed, written in Go, past 25,000 GitHub stars, and v1.1.2 published on 26 July 2026, the day we checked every number here. Task Master, which occupies the same niche, last shipped 0.43.1 in March 2026.
One correction first. If a write up tells you Beads keeps issues in SQLite with a JSONL file as the git tracked source, it predates February 2026. Embedded Dolt became the default in v0.49.3 on 1 February, and v0.50.2 nudged the last SQLite users out two weeks later. The database lives at .beads/embeddeddolt/ and syncs against refs/dolt/data. The README is blunt about the file everyone still writes about: it is "an export for viewers and interchange, not the source of truth or a backup."
What that buys is real. bd ready walks the dependency graph and hands back unblocked work with no network call. Hash IDs stop two agents on two branches minting the same id, and Dolt's cell level merge handles the rest. The dependency graph is a first class object rather than a link type bolted onto a ticket.
If you are one developer with one repo and two or three agents, stop reading. Beads is very likely the right answer and the rest does not apply.
The boundary is the first person who will not clone the repo
The usual argument against a file shaped backlog is that it collapses the moment you run two agents. We made that argument in a shared backlog for AI coding agents, and against Beads it does not hold. Hash IDs, cell level merge, an atomic bd update --claim and a server mode all exist so parallel sessions do not fight. DoltHub is explicit that server mode "allows you to run many coding agent sessions against the same Git repo."
So Beads scales agents. It stops at people, because every read path begins with a clone and a binary.
flowchart LR
agent["Coding agent"] --> db[("Local Dolt database")]
dev["Developer with a clone"] --> db
pm["Product lead"] --> wall["Needs a clone and a binary"]
support["Support engineer"] --> wall
It shows up as a habit rather than an error. Someone asks for a status link, you cannot produce one, so you paste a terminal screenshot. Do that twice a week for a month and you are the reporting layer for your own project. There is no official web UI, and the community ones are local first by design. The nearest thing to a shareable URL is the static site Bead Me Up, Scotty publishes, if someone regenerates it.

Who did it, and who is allowed to
Beads records an actor on every write. Its configuration reference resolves it in a fixed order: the --actor flag, then BEADS_ACTOR, then BD_ACTOR, then git config user.name, then $USER, then the string "unknown".
Nothing in that chain is authenticated. It is a string the caller declares, with an env override and an unknown fallback. You find out the day you open a closed ticket's history and the actor is your own $USER, because the agent ran as you.
Connecting an agent to Taskfolk creates a real user row flagged as an agent, a member row, a profile, and an API key whose creator is that agent's own user id. Everything the key writes carries that identity, so the agent shows up in the assignee picker, in mentions and in the activity log. Its address sits on a subdomain with no mail routing, so the magic link that would sign it in has nowhere to land. More in managing AI agents.

Permissions follow from the same gap: there is no authenticated principal to attach a write policy to. Beadbox, a GUI vendor built on Beads, says this about its own product, and it fits the storage model underneath just as well. "There are no user accounts, no roles, no per-issue visibility restrictions. Everyone with filesystem access to the .beads/ directory (or the Dolt server) can read and write everything." The nearest thing Beads ships is agent.profile, which governs git authority for bd prime, not issue fields. What breaks when a contractor joins is the assumption, not the code.
Ours is a per agent allowlist over fourteen issue fields, enforced at one write choke point covering REST, the transition endpoint and MCP. It is per field, not per value: you decide whether an agent may write status at all, not that it may only move things to In Review. Setup is in setting agent field permissions.

The shared view is per machine, and upgrades are a team event
Beads does cross repo work, and pretending otherwise would be lazy. bd repo add and bd repo sync hydrate other repositories into one read view, every issue carries a source_repo, and external:<project>:<capability> points a dependency at another project.
The catch is where that configuration lives: one machine, one person's config. Two people with different repos registered read different backlogs, and neither can hand the third person anything.
The other cost grows with headcount. When an upgrade crosses a schema migration on a remote backed database, the README says one designated clone runs bd migrate and bd dolt push while everyone else installs the binary and runs bd bootstrap. A version guard refuses to open a database a newer binary migrated. At two people that is a Slack message. At eight it is a scheduled event whose symptom is a teammate whose bd broke after an unrelated brew upgrade.
What actually differs
Both tools track issues with dependencies and both do it well. What decides it is identity, access, audience and hosting.
| Beads | Taskfolk | |
|---|---|---|
| Attribution | Declared string, unknown fallback |
Authenticated user or key |
| Per agent write limits | None | 14 field allowlist |
| Status without a clone | Static export only | A URL, after an invite |
| Cross repo view | Per machine config | Same for everyone |
| Unblocked work | bd ready, offline |
None; list, then links |
| Offline | Every query is local | None |
| Upgrades | One clone migrates | Hosted |
| Cost | Free, MIT, no account | 5 projects free, then $3 a seat |
The migration, worked
Issues first, then the edges, because a link cannot exist until both endpoints do.
flowchart LR
bd["bd export"] --> jsonl["issues.jsonl"]
jsonl --> bulk["POST bulk, 50 per call"]
bulk --> links["Second pass, links"]
links --> ws["Workspace"]
ws --> back["GET issues and links"]
back --> imp["bd import upserts"]
Start with the export. Memories from bd remember are excluded by default, which is what you want.
bd export -o issues.jsonl
Each line is one issue with its labels, dependencies and comments. What carries over is issue_type, priority, status, labels, dependencies, comments, and the external_ref / source_system pair for cross system ids.
{"id":"core-8f2","title":"Rotate the signing key","issue_type":"chore","priority":1,"labels":["auth"],"dependencies":[{"depends_on_id":"core-4a1","type":"blocks"}]}
Three mappings lose information, and choosing the loss beats discovering it in week three. Beads bug, task and epic pass through, feature becomes story, and chore and decision land on task. Priorities run 0 to 4 where 0 is Critical and 4 is Backlog, so the bottom of that ladder is a queue position rather than an urgency; ours are six named levels and 4 becomes lowest. Link types discovered-from, supersedes and replies-to have no equivalent: ours are relates_to, blocks and duplicates, plus parent child.
One trap will cost you an afternoon. parent is accepted on create and ignored on update, so a child created before its parent cannot be reparented over the API. Sort the export so epics and parents go first.
Then create, in batches of 1 to 50. The response is 201 when every item lands and 207 when some fail, with the index that broke.
curl -X POST https://taskfolk.ai/api/v1/workspaces/acme/projects/CORE/issues/bulk \
-H "Authorization: Bearer tfk_live_a1b2..." \
-H "Content-Type: application/json" \
-d '{"items":[{"type":"task","title":"Rotate the signing key","priority":"high"}]}'
await fetch("https://taskfolk.ai/api/v1/workspaces/acme/projects/CORE/issues/bulk", {
method: "POST",
headers: { Authorization: "Bearer tfk_live_a1b2...", "Content-Type": "application/json" },
body: JSON.stringify({ items: batch }), // 50 at a time
});
requests.post(
"https://taskfolk.ai/api/v1/workspaces/acme/projects/CORE/issues/bulk",
headers={"Authorization": "Bearer tfk_live_a1b2..."},
json={"items": batch},
)
{"data":[{"index":0,"ok":true,"data":{"key":"CORE-118","title":"Rotate the signing key"}}]}
Keep a map of Beads id to issue key and replay dependencies[] against it. Links resolve cross project inside a workspace, so a dependency that pointed at another repo still lands. A key allows 600 requests a minute by default, putting a 4,000 issue backlog at 80 create calls plus one per edge.
curl -X POST https://taskfolk.ai/api/v1/workspaces/acme/projects/CORE/issues/CORE-118/links \
-H "Authorization: Bearer tfk_live_a1b2..." \
-d '{"kind":"blocks","direction":"in","target_key":"CORE-104"}'

Skip the CSV importer. It is faster and drops exactly what you came to Beads for: a parsed row carries title, type, status, priority, assignee, labels and description, and no parent, no dependencies, no links. There is no Beads connector; how to import your project covers Jira and Trello.
Your agents keep a command shaped loop
None of this is worth doing if your agents get worse at their job. They keep talking to a tool; it just answers over HTTP now. Our MCP server is one Streamable HTTP endpoint whose tool catalogue is generated from the OpenAPI registry that defines REST, so the two cannot drift: over 180 operations, scope filtered per key. MCP or the REST API has the short version.
The generated skill bundle saves the most setup time. Its SKILL.md is built from your live workspace inventory, so the agent starts with your real project keys, labels, custom fields and mention handles instead of guessing.

Where you lose is bd ready, and it is worth being exact. No single call returns unblocked work. The v1 issue list filters on status, type, priority, assignee, reporter, milestone, sprint, parent, label and a text query, and none of those is "unblocked". Blocked state is derived inside the app for the board and list views, not exposed as a query parameter.
So the agent lists open work, reads /links for the candidates and decides for itself: more calls, more tokens, and a network dependency where there was none. Beads' own FAQ prefers the CLI over MCP for the same reason, lower context overhead, and we have no clean answer. Ticket quality moves an agent's success rate further than transport does, and writing tickets an agent can finish covers that.
What you lose, and how to get back out
Beads gives you one database per repo at no cost. Our free tier caps you at 5 active projects, so a developer with eight repos, each with its own .beads/, hits a wall Beads never had. Pro is $3 per editor seat per month, and connected agents and viewers are not seats.
You also give up offline. There is no offline mode, no local cache and no mobile app, so a dropped connection means no backlog. On a plane, Beads wins.
Leaving is the part most migration guides skip, so here it is. Page your issues and links back over REST with ?limit=200 and the cursor, write one JSON object per line in the shape bd import expects, then import it. Import is an upsert: a row overwrites a local issue only when its updated_at is newer, tombstone rows are skipped, and older rows return as stale_skipped_ids.
curl -s "https://taskfolk.ai/api/v1/workspaces/acme/projects/CORE/issues?limit=200" \
-H "Authorization: Bearer tfk_live_a1b2..." | ./to-beads-jsonl.py > out.jsonl
bd import out.jsonl
Stamp external_ref and source_system on the way out so a second run is idempotent, and park the Beads id in a text custom field on the way in. That is what makes running both side by side workable, though Beads syncs bidirectionally with GitHub, Jira and Linear while ours is a script you maintain.
Rather than argue about the seam, test it. Export one repo's backlog, create the issues in a free workspace, and send the board link to whoever keeps asking you for status. If they stop asking, the seam was real.
Frequently asked questions
Can I run Beads and a hosted tracker at the same time?
Yes, but the effort depends on the target. Beads ships bidirectional sync for GitHub, Jira and Linear (bd github sync, bd jira sync, bd linear sync), so those coexist out of the box. Taskfolk is not one of those connectors, so side by side means a script over the REST API that stamps external_ref and source_system on export and parks the Beads id in a text custom field on import.
What happens to .beads/issues.jsonl after I migrate?
Nothing, and it was never the file that mattered. Since February 2026 the source of truth is an embedded Dolt database at .beads/embeddeddolt/, and the JSONL is a passive export for viewers and interchange. To keep the old backlog around, keep the whole .beads/ directory or run bd backup, not just the JSONL.
Can my agent still work from the command line after moving?
Yes. It talks to an MCP server or the REST API instead of a local binary, and the generated skill bundle hands it your real project keys, labels and custom fields so it stops guessing. The honest gap is bd ready: no single call returns unblocked work, so the agent lists issues and reads their links itself.
How many issues can Beads handle before it slows down?
More than most projects will ever hold. Its own FAQ says commands stay fast at the thousands-of-issues scale, and only suggests splitting into one database per component past roughly 100,000 issues. Volume is not the reason to leave Beads.
Is Beads free, and is Taskfolk?
Beads is MIT licensed, free, and needs no account or server. Taskfolk has a real free tier capped at 5 active projects and 128 MB of storage, with Pro at $3 per editor seat per month; connected agents and viewers are never counted as seats. If cost is the only axis you care about, stay on Beads.
Related reading

A shared backlog for a team of AI coding agents
Task manager for AI coding agents: give three agents one shared backlog with per-agent identity, field permissions, status handoffs, and human review gates.
16 July 2026 · 13 min read

How to manage a team of AI agents without losing track of what they're doing
AI team management day to day: a roster, live sessions, instant delegation, per-field permissions, and verified work when several AI agents run at once.
15 July 2026 · 16 min read

Onboard an AI agent like a new hire: identity, access, and a first task
You already know how to bring on a new hire. Do the same for an AI agent: give it an identity, scoped access, one small task, a review, and an offboarding path.
15 July 2026 · 8 min read

Running a project with AI agents without losing the thread
A practical setup for letting AI agents do real project work, create issues, move the board, draft specs, while your team keeps control of what matters.
11 July 2026 · 5 min read

Keep an audit trail of everything your AI agents change
Once agents can write to your tracker, a shared bot account makes every change anonymous. Here is how per-agent identity keeps the trail readable.
15 July 2026 · 8 min read

Cursor task management: give the agent a shared board over MCP
Cursor task management usually means a local Task Master or .cursor/rules file. Connect Cursor to a shared board over MCP so the agent reads issues, claims work, and reports sessions humans can review.
16 July 2026 · 12 min read

Who decides what: setting decision rights between your team and your AI agents
A simple rule for AI governance: reversible, low-stakes moves are the agent's to make; irreversible or high-stakes ones need a human. How to draw the line.
15 July 2026 · 7 min read

Turn a PRD into epics, stories, and tasks your AI agents can build
Give your AI coding agents a plan they can build. Paste a PRD or FRD, Taskfolk drafts the backlog, then Cursor, Claude Code, and Codex work it through a workflow you control.
19 July 2026 · 9 min read

Claude Code task management: give your agent a real tracker, not a markdown file
Give Claude Code persistent, attributed task management by connecting a real tracker over MCP instead of a markdown file. Honest comparison to Task Master, as of July 2026.
16 July 2026 · 12 min read

How to use AI agents in Taskfolk: connect them, assign work, and follow their sessions
A start-to-finish walkthrough: connect an agent, scope its key, assign it issues, and watch its sessions, without giving up control of the board.
15 July 2026 · 11 min read
Add a comment
Start the conversation.
