Guide / Learn

When Markdown Todos Stop Working

Replace proliferating agent plan files with queryable work state, explicit dependencies, atomic claims, and durable recovery.

Last reviewed:

A Markdown todo is fine until a second file disagrees with it.

Once agents leave behind PLAN.md, TODO.md, session notes, and a handoff document, the next worker has to reconstruct state before it can act. Beads replaces that reconstruction with a query: inspect the durable work record, its relationships, its history, and what is ready now.

Use Markdown for explanations people should read. Use Beads for state agents must change without ambiguity.

Three conflicting Markdown files leave a new agent reconstructing status after a crash, while a Beads graph records that the bad account row was discovered during verification and now blocks it, leaving the mismatch as the only ready recovery work.

The 9:17 a.m. failure

At 9:17, an agent working on a database migration loses its session. The repository contains:

  • PLAN.md, where “write backfill” is unchecked;
  • TODO.md, where “backfill complete” is checked;
  • handoff-notes.md, which says the backfill is running but the verification query failed.

The code includes a half-written verification script. Git shows changes, but it cannot say whether “complete” meant the script, the data run, or the review. A new agent can read all of this and make a reasonable guess. It cannot retrieve an authoritative answer because the repository never contained one.

This is the actual cost of Markdown task state. Writing is easy. Reconstructing truth after divergence is expensive.

With Beads, the migration, backfill, and verification are separate durable work records. The backfill can be closed while verification remains open and blocked on a discovered production mismatch. Those are two relationships: the mismatch was discovered-from verification, and it now blocks verification until it is resolved. The session can vanish; the records do not become mutually inconsistent prose.

Informal Markdown has no transaction

A checkbox combines several unstated facts:

- [x] Run the account backfill

Who ran it? Which code revision? Did it finish or merely start? What work did it unblock? What failure did it reveal? Did another agent already take the next step?

Writers can add more prose, headings, timestamps, and conventions. Eventually an informal plan file becomes a database designed through prompt instructions, without transactions or a query language. Deliberate Markdown-native work managers can add schema and graph queries; the warning here is about plans and todo files being pressed into service as shared mutable state.

Beads gives those facts separate places:

Needed factMarkdown conventionBeads state
Stable identityHeading text or list positionBead ID
Current stateCheckbox or prose labelStructured status
OwnershipA name written in the lineClaim and assignee state
ScopeNested bulletsParent/child edge
Execution order”After X” in proseBlocking edge
Origin of new workNarrative notediscovered-from edge
What can start nowAgent rereads and infersbd ready
What changedGit diff if committedVersion-controlled database history

The medium is secondary. Operational facts need to be individually addressable and enforceable.

Flat prose makes every agent a scheduler

Suppose two tasks are unchecked:

- [ ] Add the new schema
- [ ] Deploy the code that reads the new schema

A human recognizes the likely order. An agent can infer it too. Every worker must make the same inference, though, and the checkbox format cannot stop both tasks from being selected at once.

In Beads, a blocks edge keeps the deploy task out of bd ready until the schema task closes. Parent/child edges can place both under the same migration without implying sibling order. The graph distinguishes “belongs to” from “must happen before.”

That distinction also preserves parallelism. Documentation and test-fixture work can remain ready while the production deploy waits. A nested checklist often makes the whole group look sequential or leaves order to interpretation.

Two agents can obey the file and still collide

Prompt rules often say:

  1. Read TODO.md.
  2. Pick the first unchecked item.
  3. Mark it in progress.

Two agents can follow those instructions perfectly. They both read before either writes, choose the same line, and begin. Git may catch a later text conflict; it cannot refund the duplicated work.

Beads makes taking work a state operation. An atomic claim allows one winner rather than relying on the timing between a read and a subsequent edit. The losing agent can query the frontier again.

If only one agent ever writes the plan, this distinction may not matter. A single-worker, one-hour task does not need distributed coordination. The problem begins when the todo file is used as if it were a shared queue.

Git history solves a narrower problem

Markdown advocates are right about one thing: committed files survive sessions, and Git provides excellent history. That already beats keeping the plan only in chat.

The limitation appears during recovery. Git tells you which bytes changed. It does not inherently know that one record blocks another, that a claimed item has gone stale, or that a discovered bug came from a failed verification task. Those semantics remain embedded in prose and commit timing.

Beads stores work in Dolt, a version-controlled SQL database. The next agent can query current state and history as structured data. Cross-machine work moves through bd dolt push and bd dolt pull, while server mode supports the multi-writer case.

JSONL export is useful for interchange and inspection, but it is not the current Beads source of truth or backup plan. Durable recovery comes from Dolt.

Keep Markdown where it shines

Beads should not replace every planning document. Markdown remains the right medium for:

  • a design argument with tradeoffs and alternatives;
  • an architecture decision a person will review;
  • onboarding material and runbooks;
  • a short, disposable checklist inside one session;
  • acceptance criteria whose nuance needs paragraphs.

Link those documents from the relevant bead. The bead carries lifecycle and relationships; the document carries the long explanation.

If what you want is a deliberate Markdown-native work manager, evaluate one as a product rather than confusing it with stray todo files. ticket/tk is a direct example: it adds stable IDs, structured fields, parents, dependencies, and ready-work queries while keeping one Markdown file per ticket.

When to migrate

Move work from Markdown into Beads when you see any of these symptoms:

  • agents create a new plan instead of updating the old one;
  • two files disagree about status;
  • “what can start?” requires rereading the whole plan;
  • task identity changes when a heading is renamed;
  • simultaneous workers need a claim protocol;
  • a crash turns the next session into an archaeology exercise.

Do not convert the prose line by line. Identify durable units of work, give each one a clear outcome, then add only the relationships that affect scope, execution, or provenance. Keep the original document as background if it still helps.

Move one real plan, not the entire repository. Create stable beads for the work that can change independently, add the blocker that controls the next step, and keep the Markdown document as background. Then ask a clean agent session what is ready without showing it the old checklist.