DEV Community

Cover image for I Run Coding Agents in Parallel. A Markdown File Is Their Manager.
Ibrahima D.
Ibrahima D.

Posted on Edited on Originally published at ibrahimadansoko.fr

I Run Coding Agents in Parallel. A Markdown File Is Their Manager.

On October 11, I opened GitHub and counted four pull requests. I was expecting two.

453 and #456 fixed the same thing. So did #454 and #452. Different branches, different code, same task. Two of my coding agents had each done the work perfectly, in two separate sessions, without knowing the other one existed.

Nobody had made a mistake. That's what bothered me.

Agent A had picked the tasks and started coding. Agent B, in another terminal, had looked at the list, seen two tasks nobody had claimed, and done the reasonable thing. If two human developers did this, you'd say "they should talk to each other". Agents don't talk to each other. They don't even remember yesterday.

So I did what you do with a team that doesn't communicate: I gave them a manager. It's a Markdown file.

Two agents, one task list: with no mark, both pick the same task. With the IN PROGRESS mark, the second one moves on.

An employee with amnesia

Picture a brilliant developer who joins your team every morning with no memory of the day before. Doesn't know what was decided. Doesn't know what was tried and abandoned. Doesn't know who's working on what.

That's a coding agent. With one of them, you compensate: you explain again. With four in parallel, each in its own git worktree, you become a full-time switchboard operator, and the agents still step on each other.

I build i18n Support Plus, an open source JetBrains plugin, this way. As I write this, the repository is past pull request #950, and more than 500 task entries have gone through two files at its root:

  • TODO.md: what's left to do
  • TODO-DONE.md: what's finished

No ticketing tool. Nothing to install. Nothing tied to one agent: anything that can read a file can join the team.

It works because of five rules. I didn't design them. I collected them, one accident at a time.

Rule 1: write the task for someone who knows nothing

Here's a real one, archived on November 8 (translated from French, shortened):

#### [TASK-CADRAGE-CONFIG-KEYSTROKE-REBUILD] Every letter typed in an open
     `i18n-check.json` setting rebuilds the whole usage index

- **Added:** 2026-11-08
- **Exclusive scope:**
  - `.../settings/Settings.kt`
  - `.../usages/CodeUsageIndexService.kt`
  - `.../usages/CodeUsageIndexServiceTest.kt`
  - `CHANGELOG.md`
- **Context:** measured by #926. Typing `node_modules` in the excluded
  directories field triggers twelve full rebuilds, about 18 s each on
  300 files, with the CPU spinning.
- **Expected:** unsaved content is only read after a typing pause;
  a rebuild in progress is cancelled when the state changes again.
- **Expected tests:** a burst of ten keystrokes = one rebuild.
Enter fullscreen mode Exit fullscreen mode

Look at the title: it's the defect, in one sentence. Look at the context: a measurement, not an impression. An agent can pick this up cold and never ask me a question.

It's also, I realized later, just a well-written ticket. Agents didn't need anything exotic. They needed what my human colleagues had been asking for all along.

Rule 2: one task, one territory

This is the rule that makes everything else possible.

Two tasks of the same priority never touch the same files. That's the "exclusive scope" line above. If two file lists overlap, one task moves to another priority level.

Once that's true, parallel work stops being a coordination problem. I say "work through priority 2", the agents leave in a wave, each on its own files, and there is nothing to arbitrate because there is nothing to collide on.

The parallelism isn't decided when the agents start. It's decided when the tasks are written.

Rule 3: say "mine" before you touch anything

An agent that takes a task writes IN PROGRESS in front of its title. The others skip it.

You already know how I learned that the timing matters. The mark is worthless if it goes on after the first line of code. It has to be the very first thing the agent does, the way you say "I'll take it" in a meeting before opening your laptop.

Since October 11, there's a second check before any wave: look at the open branches and pull requests. Trust, but verify.

Rule 4: finished means gone

The natural reflex is to leave a completed task in the file with a nice green check mark. It feels good. Look at all that progress.

Now look at what that feeling costs. Every agent reads TODO.md at the start of every session. Every finished task still sitting there gets reread, by every agent, every time, forever. You end up spending tokens so that machines can admire your check marks.

Now a finished task leaves. Its whole section moves to the end of TODO-DONE.md, and it keeps one line in a table at the top of TODO.md: what changed, which PR, what date. The archive is append-only. Agents write at the end of it and never read it.

TODO.md stays at 24 KB while the archive grows to 1.28 MB

Today TODO.md weighs 24 KB. The archive weighs 1.28 MB. Every session starts by reading 52 times less than the project's real history, and nothing was thrown away.

Rule 5: you see a bug, you write it down, you walk away

Agents are helpful to a fault. Ask one to fix a typo, and if it notices a questionable function on the way, it will "also fix" it. That's how a ten-line task becomes a four-hundred-line pull request that conflicts with three others.

So the rule is the one you'd give an eager intern. An out-of-scope problem doesn't get fixed. It gets an entry in a "to be framed" section: what you saw, which files, a possible approach, a rough cost. Then you go back to your task.

I decide what happens next. Anything marked "awaiting decision" stays untouched. That section has turned into a bug tracker of its own, with one advantage: every entry comes from someone who was looking at the code when they wrote it.

The days it failed anyway

The day my own rule blocked me. At one point, 10 tasks out of 13 needed to touch plugin.xml or the label files. Strict exclusive scopes spread them over 10 priority levels. One task at a time: I had built a very sophisticated queue. But two tasks that each add a line to the same file only create a trivial conflict. So on October 6 the rule got an exception, written at the top of the file: those files can be shared, as long as every task only adds lines.

A rule that's too strict fails as surely as no rule. It just fails slowly.

The day the agents fought over the machine. Scopes protect files. They don't protect the computer. Two worktrees share one Gradle cache, so their builds collide. And one agent's ./gradlew --stop kills the other agent's daemon in the middle of its tests.

The second agent then sees a failure that looks exactly like a regression, while its code is fine. And an agent that believes it broke something will try to fix it. Now test runs are serialized, or each agent gets its own GRADLE_USER_HOME.

The day of the four pull requests. You were there.

What I can and can't tell you

What I can tell you: more than 500 task entries, 24 KB to read at startup against 1.28 MB of history, waves of agents that don't need me to referee.

What I can't tell you: how much faster this is than no file at all. I never ran the comparison. These numbers describe how the project runs. They don't prove a gain, and I'd be suspicious of anyone who gave you one.

Here's what I believe after all this:

  • An agent's memory should live in the repository, not in its session.
  • Parallel work is prepared when the tasks are written. The number of agents matters less than the shape of the backlog.
  • What gets read at every startup must stay small. Keep everything else, but out of sight.
  • Most of what makes agents effective is what makes a team effective. We just never had to write it down this precisely.

One question before you go. If two of your agents started right now, on the same repo, with the same instruction, what would stop them from doing the same task twice?

If the answer is "me", you're the manager. Consider delegating to a text file.


This article was first published as a case study on my site, where I write about frontend architecture and coding agents in practice.

Top comments (1)

Collapse
 
aiapikey profile image
于侃 •

The structure is right, but the duplicate PRs point at the claim primitive, not the file. Two agents read "unclaimed", then both wrote. A Markdown file has no atomic claim step, so it cannot be a manager - it can only be a shared workspace.

What makes a claim safe is something the filesystem already gives you: create the lock with O_EXCL, or mkdir todo/ which fails if the directory exists, or git update-ref refs/claims/ which fails on conflict. Whoever loses the race moves to the next task and never sees the loser's branch.

Without that, collisions grow with the square of the agent count: fine at two, broken at four - which matches your four PRs.

I would keep the Markdown as the human-readable index and make the claim a side effect the reader cannot fake.