One Wave at a Time
Why I stopped driving coding agents one PR at a time, how I batch parallel work into waves, and why the human role narrows to Step 0.
Nathan Clement · October 27, 2026 · 11 min read
For most of my career, I worked in a single straight line. I would pick the next ticket, open a branch, write the code, merge the pull request, and move on to the next one.
When I first started using coding agents heavily in one of my personal projects, I kept that exact same single-threaded habit. I handed an agent one task, waited for it to finish, reviewed the diff, and then figured out what to do next.
Eventually I tried to speed things up the obvious way by opening four or five terminal sessions across separate git worktrees.
On paper, running five worktrees in parallel sounds awesome. In practice, I was still working one ticket at a time inside each session and actively babysitting every single PR myself. One tab would be blocked on a clarifying question, another would be halfway through a refactor, and a third would hit a weird test failure. I spent my evening alt-tabbing between terminals trying to hold four different mental models in my head at once. My own attention was still the bottleneck, just fractured into four pieces.
So lately I have stopped driving pull requests one by one. Instead, I finish the core design idea up front, build on a feature branch in parallel waves of tasks that go out at once, run a compression pass between waves to keep the code clean, and let an agent slice the finished branch into small production PRs at the end (Figure 1).
Step 0. Finish the idea first (the human seed)
Before you launch a single parallel wave, a human still has to finish the core idea.
A few years ago I wrote an essay called Plato would love TypeScript Generics! about the ancient tension between Form and implementation. Plato's point was that before you fret over the material for a keyboard, you have to settle what the thing actually is, why it exists, and what it ought to accomplish for the user.
That distinction matters ten times more with coding agents. If you do not know what you are building yet and you dispatch five subagents in parallel, you are not exploring faster. Five agents will happily run in five different directions, invent five incompatible shapes for the problem, and four of their branches will end up in the trash.
So Step 0 is always defining the Form first. You can hash that initial design out in a doc or back-and-forth with a single agent, settling what the feature is supposed to do, where the boundaries sit, and how the pieces fit together. Once the idea itself is finished, I can step out of the single-threaded driver's seat and start running waves.
1. Build in waves (batches of tasks that go at once)
Instead of worrying about production blast radius on every commit, I build inside an isolated feature branch one wave at a time.
I look at the settled design from Step 0, pick a batch of three to six tasks whose design assumptions do not depend on each other, and launch subagents on the entire wave at once. When they finish, they fold their work into the feature branch, I see what the next layer of the problem looks like in real working code, and I kick off the next wave.
Most of the conversation around parallel coding agents gets stuck on local workspace plumbing, like how to juggle git worktrees, terminal tabs, notification hooks, and spawn scripts. As Thorsten Ball pointed out on X, all of that manual worktree and tab choreography quickly turns into procrastination disguised as productivity.
I just wish everyone would try orbs so they can see that all the fiddling with worktrees, with custom tab management, and notifications systems, and agent spawn wrappers is as productive as someone changing colorschemes in Vim eighteen times per day.
Open on X
Giving each agent its own isolated workspace is table stakes, not the workflow. Once your agents can run in parallel without you babysitting five terminal tabs, the real question is what happens when a wave finishes and those branches come back together.
A lot of engineers wince at running a wave on the same feature branch because of git merge conflicts. In one of my personal projects, two agents in the same wave will routinely edit the same routes.ts registry, package.json, or schema.prisma file. To be fair, mechanical merge conflicts used to be miserable human busywork. When two engineers touched the same route table, someone had to sit down and untangle the diff by hand. Turns out coding agents are pretty darn good at rebasing a branch and resolving overlapping imports or route registrations on their own.
Overlapping work in a wave only hurts when one task forces a design change on another (Figure 2).
Say Agent A is building a separate Azure sync worker and Agent B is building a webhook retry queue. If both agents add a table to schema.prisma and register a handler in routes.ts, an agent can resolve that file overlap cleanly. But if Agent A discovers halfway through that an upstream API requires a pagination cursor token while Agent B is already building a stateless retry loop on the old interface, no git rebase can save Agent B's branch.
When a wave does hit a real design surprise like that, the right move is not letting an agent quietly hack around it. The wave pauses and triggers a design interrupt back to Step 0. I step back in, adjust the design in one place, and re-launch the wave on solid ground.
Which means the only question that defines a wave boundary is whether finishing Task A could change how we design Task B.
2. Compress between waves (organic coding, a la @poteto)
When five subagents finish a wave in parallel, the feature works and the tests pass, but the branch has expanded. Agent A wrote a custom retry wrapper, Agent B invented a slightly different error normalizer, and Agent C added defensive checks for a state that cannot actually happen.
If you launch Wave 2 right on top of that raw diff, the next batch of subagents will treat all three wrappers as established conventions and copy them everywhere.
That is why I run a dedicated compression pass between waves. Lauren Tan (@poteto) has written about this kind of continuous pruning as organic architecture and in her Complete Guide to pstack Pt. 2, and her open-source pstack engineering principles (like Subtract Before You Add, Laziness Protocol, and Minimize Reader Load) are a great example of how to codify that cleanup pass.
organic architecture good codebases have always had strong foundations and constraints. these files go here. this kind of code goes there. the codebase is held together either by catering to the lowest common denominator developer using conventional frameworks and languages, or by strict adherence to a style guide enforced by code review. the arrival of an infinite number of monkeys armed with keyboards have obsoleted the latter. codebases designed for agents need hard constraints so that even the dumbest agent (and pilot) can contribute meaningfully. the chaos must be tamed. refactoring your codebase and choosing a tech stack with strong type systems/compiler diagnostics has far greater impact than AGENTS.md and tweaking your skills. hard constraints and well thought out architecture guide agents to do the right thing by default. the best rules are in your code. invest accordingly.
Open on X
Whether you use a skill set like pstack, your own refactoring prompt, or stricter linter and compiler rules, no new features get added during compression. I hand an agent the expanded feature branch with one job, which is to collapse one-caller wrappers, delete duplicate adapters, simplify tangled control flow, and shrink the net diff while keeping every behavior test green.
Waves expand the branch to discover what works. Compression prunes the branch back down so the next wave builds on clean ground.
3. Slice for deployment (why old feature-branch dogma flips)
For the last fifteen years, continuous-delivery orthodoxy has warned that building on a long-lived feature branch and trying to slice it into safe production PRs at the end is a trap.
When humans were doing the slicing by hand, that advice was dead right. Once an engineer had 2,500 lines of working code on a feature branch, untangling it backwards into three or four self-contained deployment PRs was tedious and error-prone. People got tired, merged the giant branch all at once on a Thursday afternoon, and hoped production would not page them.
With coding agents, deploy deconstruction is cheap too.
Once a feature branch has been built in waves and compressed into a verified target state, an agent can slice that finished diff backwards into ordered pull requests for main.
- PR 1 (Foundation). Additive schema migrations, internal types, and dark-launched plumbing that land with zero user impact.
- PR 2 (Services). Background workers, dual-reads, or feature-flagged endpoints.
- PR 3 (Cutover). The user-facing route cutover and removal of the old path.
Because AI makes both merging into a feature branch and deconstructing out to main cheap, your exploration loop no longer has to match your deployment loop.
Could a wave splitter run automatically?
You can already see pieces of this workflow showing up in open-source agent tooling, from Steve Yegge's beads (which gives coding agents a dependency-aware task graph via bd ready) to Diego Haz's topological task-splitting skill, where an agent breaks a large task into topological units before spawning concurrent sessions.
I wrote a skill for this if anyone is interested: https://gist.github.com/diegohaz/ff1573a520292ca136aedd6991688e33 You give it a big task. It'll break it down into units in topological order, then ask how you want it to proceed. It asks about the max number of concurrent sessions, whether to work through the task to the end or in chunks, where to save the progress record, follow-ups, etc. I've already tested it, and it's cutting my usage by at least 30% compared to using subagents. Ah, this is for the CLI. I haven't tested it on Claude Desktop.
Open on X
The missing piece in most task splitters today is knowing the difference between file overlap and design coupling. Once an orchestrator can group unblocked tasks into waves by shared design assumptions, let agents resolve mechanical git conflicts, run a compression pass between waves, and slice the finished branch into staged deployment PRs, the entire middle of the loop can run without a human babysitting every commit.
What stays human when the middle of the loop is cheap
Stepping back, that flips a constraint we have taken for granted for decades. Historically, a single human-sized pull request had to do three different jobs at once: it was our unit of exploration, our unit of code cleanup, and our unit of production deployment. We bundled all three into one PR simply because rebasing messy branches and re-slicing diffs by hand cost too much to separate them.
When agents make both merging and deconstructing cheap, those three jobs finally come apart. And once parallel waves, compression passes, and deployment slicing can largely run themselves, the human engineer's job narrows down to the two moments that still require real judgment: Step 0, finishing the core idea and its Form at the start, and stepping back in when a wave hits a design surprise that forces a new call.
Maybe that is what the future of software engineering (and knowledge work more broadly) actually looks like. We spend way less time acting as human compilers and git conflict resolvers, and way more time doing the architectural thinking Plato cared about in the first place.
How are you batching parallel agent work in your own projects? And if you are already running waves, when do you find yourself stepping back into the loop?