For months we kept a TODOS.md (and a BACKLOG.md) in the repo. They were always a little wrong. Someone finished a thing and forgot to tick it. A priority changed in the tracker but not in the file. The file said "next up" about work that shipped last week. A hand-maintained mirror of your real task list is a second source of truth, and second sources of truth rot.
We deleted both files. What replaced them is a single idea: generated views, not a hand-maintained mirror.
The board is the source; the repo holds generated views
We use Linear for tracking, and our coding agent talks to it directly — it can read and write issues itself (over MCP, if you want the acronym). Once the agent can read the live board in one call, there's no reason to keep a stale copy in the repo. The board is the truth.
So instead of a file we hand-edit, we have a script that pulls the board and writes read-only views to a gitignored scratch dir:
.local/board/launch.md # the tight launch gate (one label)
.local/board/todo.md # in progress + up next
.local/board/backlog.md # deferred
.local/board/v2.md # forward initiatives, by milestone
These are generated, never hand-edited. At the start of a session the agent regenerates them and reads launch.md to see what actually gates launch. Drift is impossible — there's nothing to keep in sync, because nothing is maintained by hand.
Three small scripts, one rule each
Once the board is the source of truth, a few boring scripts cover the whole loop:
- snapshot — regenerate the local views from the live board. Read-only. Run it whenever.
- import — the inverse. When we approve a plan, the agent writes the issues as a small structured file and one command bulk-creates them on the board (resolving project/label/milestone names to IDs). Approved work goes into the tracker immediately, instead of living in a doc nobody reopens.
- prune — delete done/cancelled issues older than two weeks. The tracker's trash keeps them recoverable for another couple of weeks, so a finished issue has a ~30-day life before it's gone for good. The permanent record of shipped work is the changelog, not the board.
The rule we kept repeating to ourselves: the board is for live work; the changelog is the history. Once those two have clear jobs, the repo doesn't need a task file at all.
Why the MCP connection is the unlock
You could do a version of this with the tracker's REST API and a cron job. What MCP adds is that the agent itself operates the board as part of normal work — it moves an issue to In Progress when it starts, to Done when it ships, files a follow-up when it spots one, all in the same breath as writing code. The board stays current because keeping it current is no longer a separate chore a human has to remember. It's a side effect of doing the work.
The "approved plans → import file → board" path matters for the same reason: it closes the gap where good ideas die in a doc. If a plan is real, it becomes issues. If it's not worth an issue, it's not worth tracking.
What we'd tell you
If you maintain a TODOS.md by hand and it's ever lied to you, that's the signal. Wire your agent to the tracker, generate your views instead of mirroring them, and let the file go. Here's the test: delete the file. If nothing breaks, it was never the source of truth — it was just a copy that drifted.