ℹ️ See my write-plan and implement-plan skills.
I spent the first 10 years or so of my career (going back to the 90s here, folks) in the Waterfall/BDUF era: long meetings discussing endless hypothetical scenarios, big planning documents covering months of work, missed deadlines, and deliverables that typically ended up misaligned with actual needs. The reasons for this frequent misalignment are now obvious, since our industry has matured since then:
This is what spawned the Agile movement, which started to gain traction in the early 2000s, and at the time it felt revolutionary. It turned Waterfall on its head, with short development and deliverable cycles and frequent feedback (Agile has unfortunately accreted its own layers of bureaucracy since then, but that’s another story).
In our new era of AI-assisted coding, BDUF is back: we can now generate planning documents and code faster and cheaper, so why not? You can develop your plan, walk away while AI works on it for a few hours, and then deliver. If what you delivered ends up needing changes, repeat the process. This is how the popular Superpowers skill for executing plans works (and most other AI planning skills I’ve seen): “Load plan, review critically, execute all tasks, report when complete.”
There are two aspects to feedback: customer feedback, and technical feedback. Faster delivery with AI-assisted coding means you can get customer feedback sooner, even with BDUF. But critically, technical feedback is still missing. If it turns out something was poorly designed in step 1 of your 12 step plan, its effects cascade through the rest of the work, making it difficult to unwind later. And when you dutifully do your code review of the AI generated code in a giant pull request, you’re almost certainly going to miss things (this has always been true: see The Paradox of Code Reviews: Why Small PRs Get More Comments Than Large Ones).
One answer to this is to try to flush out any problems in the plan by iterating on the plan itself. Boris Tane takes this approach: “Read deeply, write a plan, annotate the plan until it’s right, then let Claude execute the whole thing without stopping.” It looks like this:
While this does help catch problems, in my experience no amount of up front planning and research is going to catch all the problems. This is especially true if you’re working in a large legacy codebase: until your new code is actually written and run, there are likely to be interactions and complications that are hard to foresee (and just staring harder at the pre-existing code while planning won’t get you there, even with AI assistance).
My approach to AI-assisted plan implementation is to stop and review at the end of each step. This means you’re reviewing much smaller change sets, so you’re less likely to miss things, and you can correct and refine the plan as you go. It looks like this:
See my earlier post Pairing with AI #1: brainstorming for how I do the initial research/brainstorming phase before writing a plan. I then handoff to my write-plan skill. I do a hard stop after the plan is written, and then compact or clear the session before using my implement-plan skill. You can follow those links to see the skills in full, but here are the “Steps” sections of each:
Steps that tell a story, each building on the one before it.
- Each step is small, and focused on one logical and cohesive change. It may span several files.
- Tests for new or changed behavior belong in the step that changes the behavior, not in a later step. Skip them where they do not apply, as for a Rake task, a script, or trivial config.
- A finished step is marked ✅.
Run this at the end of every step that produces code to commit.
- Run the checks. Run the tests and the linters over the changed files. The project’s CLAUDE.md names the commands.
- Ask for a review. Ask the user to review the code. Name where the code departed from the plan. Wait for them to confirm that the review is finished and the code is approved. Until they confirm, leave the plan unchanged and draft no commit message.
- Update the plan document. Mark the step ✅. Where the implementation departed from the plan, edit the step to match what you built. Edit every later step the departure changes. The plan holds no historical record.
- Commit. Draft the message with the commit-messages skill, which also covers the approval the message needs before `git commit` runs. Include the updated plan document in the commit.
A key thing to note in step 2: “Name where the code departed from the plan.” I iterated on this and found that the implicit permission this gives to the agent to deviate from the plan is more effective than trying to codify a bunch of rules for when deviation is permitted. Note my experience here is with Claude Code only. I’ve found it does a good job at understanding the intent of a planned code change, and deciding when to deviate from the planned implementation details when it discovers a problem. I find it misjudges rarely with the current Opus model, since each step is tightly focused. Since it’s also instructed to tell me about the deviation, I’ll check it carefully when reviewing the code from that step.
I typically compact the session after completing each step, to stay in the smart zone.
That’s right, and that’s part of the point. You have to stay engaged with the work. Many developers have understandably become despondent, as they now feel more like project managers than developers (just telling Claude what to do and feeling removed from the actual work). I actually enjoy my approach, as it feels much more like a traditional pairing session, with Claude as the driver and me as the navigator. While most of the time I don’t jump in to edit code myself, I can and sometimes do, because Claude stops at the end of each step to get my feedback before committing the code.
So give this approach a try. I think you’ll find it results in higher quality and a more enjoyable coding experience.
This is the third post in a series on coding with AI. It’s inspired by the talk I gave at RubyConf in July (video should be available soon). The previous post was Pairing with AI #2: fixing Opus 5’s unintelligible output.