AI Tools

Use the Research-Plan-Annotate Workflow to Ship Features with Claude Code

A disciplined, plan-first approach to Claude Code that separates thinking from typing.

Trần Quang Hùng
Trần Quang HùngChief Explainer of Things
February 23, 202610 min read
Share:
A split-screen workspace showing a markdown plan document on the left with inline annotations and a terminal running Claude Code on the right

QUICK INFO

DifficultyIntermediate
Time Required20 minutes to learn, ongoing to practice
Prerequisites
  • Working familiarity with a terminal and git
  • An existing codebase you actively develop in
  • Basic comfort giving instructions to an LLM
Tools Needed
  • Claude Code (CLI, installed via npm)
  • A code editor (VS Code, Cursor, Neovim, etc.)
  • Node.js 18+

What You'll Learn:

  • How to structure a research-plan-implement pipeline in Claude Code
  • How to use markdown plan files as shared mutable state with the agent
  • How to annotate and iterate on plans before any code is written
  • When this workflow is overkill and when it pays for itself

This guide covers a structured workflow for using Claude Code on non-trivial features: the kind where jumping straight to code generation usually ends in a mess. The approach comes from Boris Tane (founder of Baselime, now leading Workers Observability at Cloudflare), who has been using Claude Code as his primary dev tool for roughly nine months. If you only use AI coding tools for small bug fixes or one-off scripts, this will feel heavy. That's fine. It's aimed at feature work where you'd normally spend an hour or more thinking before writing anything.

The Core Idea

Don't let the agent write code until you've reviewed and approved a written plan. That's the whole thing. Research the codebase first, generate a plan as a markdown file, annotate that plan with your own corrections and constraints, iterate until it's right, and only then tell Claude to implement. The separation between planning and execution is what makes this work. Most people skip it, and most people end up fighting their agent halfway through implementation because it made a wrong assumption in the first 30 seconds.

Phase 1: Research

Every task starts by telling Claude to read the relevant part of your codebase and write its findings into a file. Not a chat summary. A file.

read this folder in depth, understand how it works deeply, what it does
and all its specificities. when that's done, write a detailed report of
your learnings and findings in research.md

The specific wording matters more than you'd expect. Words like "deeply," "in great detail," and "intricacies" aren't decoration. Without them, Claude tends to skim: it reads function signatures, notes the general shape of things, and moves on. You need to signal that surface-level reading isn't acceptable. Think of it like telling a junior engineer to actually read the code, not just grep for the function name.

The output file (research.md) is your review surface. You read it, verify Claude understood the system correctly, and catch misunderstandings before they propagate into the plan. If the research is wrong, everything downstream will be wrong too. This is the most expensive failure mode in AI-assisted coding, and it's not syntax errors. It's implementations that work in isolation but break surrounding systems: a function that ignores an existing caching layer, a migration that doesn't follow ORM conventions, an endpoint that duplicates logic already handled elsewhere.

For bug hunting specifically, you can push harder:

go through the task scheduling flow, understand it deeply and look for
potential bugs. keep researching until you find all the bugs, don't
stop until all the bugs are found. write a detailed report in research.md

Phase 2: Write the Plan

Once the research checks out, ask for an implementation plan in a separate markdown file.

I want to build a new feature [name] that extends the system to perform
[business outcome]. write a detailed plan.md document outlining how to
implement this. include code snippets

One thing to note: this deliberately avoids Claude Code's built-in plan mode. The built-in plan mode doesn't give you a persistent artifact you can edit in your own editor, annotate inline, or refer back to across sessions. A markdown file does. It lives in your project, you can open it side by side with the codebase, and it survives context window compaction (more on that later).

The plan should include the approach, code snippets showing actual changes, file paths to be modified, and relevant trade-offs. If you've seen a good implementation of something similar in another repo, paste that code as a reference alongside your request. Claude works noticeably better when it has a concrete example to work from rather than designing from scratch. For instance: "this is how [project X] does sortable IDs, write a plan.md explaining how we can adopt a similar approach."

The Annotation Cycle

This is the part that makes the whole workflow click, and where your judgment as the developer matters most.

How It Works

After Claude writes the plan, you open plan.md in your editor and add inline notes directly into the document. These notes correct assumptions, reject approaches, add constraints, or inject domain knowledge Claude doesn't have. Then you send Claude back to the document:

I added a few notes to the document, address all the notes and update
the document accordingly. don't implement yet

That last phrase, "don't implement yet," is a guard rail. Without it, Claude will start writing code the moment it thinks the plan looks reasonable. You need to hold it in planning mode explicitly.

This cycle repeats one to six times depending on the complexity of the feature. Your notes can be anything. Sometimes two words: "not optional" next to a parameter Claude marked as optional. Sometimes a paragraph explaining a business constraint. Sometimes a code snippet showing the data shape you expect. Some examples of the kinds of corrections you might make: telling Claude to use your ORM's migration generator instead of raw SQL, switching a PUT to a PATCH, removing an entire section that proposes unnecessary caching, or restructuring a schema because Claude put a field on the wrong entity.

Why Markdown Instead of Chat

The plan file acts as shared mutable state between you and the agent. You can think at your own pace, point at the exact spot where something is wrong, and re-engage without losing context. Chat conversations are things you have to scroll through to reconstruct decisions. The plan is a structured spec you can review holistically. Three rounds of annotation can transform a generic implementation plan into one that fits your existing system precisely.

Once you're satisfied with the plan, request a granular task breakdown:

add a detailed todo list to the plan, with all the phases and individual
tasks necessary to complete the plan - don't implement yet

This creates a checklist Claude will mark off during implementation, so you can glance at the plan mid-session and see exactly where things stand.

Phase 3: Implementation

When the plan is approved, you issue the implementation command. This is the prompt Tane uses almost verbatim every time:

implement it all. when you're done with a task or phase, mark it as
completed in the plan document. do not stop until all tasks and phases
are completed. do not add unnecessary comments or jsdocs, do not use
any or unknown types. continuously run typecheck to make sure you're
not introducing new issues.

Each instruction serves a purpose. "Implement it all" means don't cherry-pick. "Mark it as completed" keeps the plan as a live progress tracker. "Do not stop" prevents Claude from pausing mid-flow to ask for confirmation. The typecheck instruction catches problems incrementally rather than dumping a wall of errors at the end. By this point, every decision has already been made and validated. The implementation should be mechanical, not creative. That's the goal: boring execution of a good plan.

Giving Feedback During Implementation

Once Claude is executing, your role shifts from architect to supervisor. Prompts get shorter. Where a planning note might be a paragraph, an implementation correction is often one sentence: "You didn't implement the deduplicateByTitle function" or "You built the settings page in the main app when it should be in the admin app, move it."

Frontend work tends to be the most iterative. You test in the browser and fire off rapid corrections: "wider," "still cropped," "there's a 2px gap." Screenshots help too. A screenshot of a misaligned table communicates the problem faster than describing it in words.

Referencing existing code is another useful pattern. Instead of describing a design from scratch, point at something that already exists: "this table should look exactly like the users table, same header, same pagination, same row density." In a mature codebase, most new features are variations on existing patterns, and Claude does well when it can copy from a concrete reference.

When something goes off the rails, don't try to patch it with increasingly specific prompts. Revert the git changes and re-scope: "I reverted everything. Now all I want is to make the list view more minimal, nothing else." Narrowing scope after a revert almost always produces better results than incremental fixes on a bad approach.

Staying in Control

The plan document is where you do most of your active steering, but some decisions come up during implementation too. A few patterns that come up often: cherry-picking from proposals ("for the first one, just use Promise.all, don't make it overly complicated; ignore the fourth and fifth ones"), trimming scope ("remove the download feature from the plan, I don't want this now"), protecting interfaces ("the signatures of these three functions should not change, the caller should adapt, not the library"), and overriding technical choices ("use this model instead of that one").

Something that isn't obvious from the workflow description: Tane runs the entire pipeline, research through implementation, in a single long session rather than splitting across conversations. He reports not seeing the context degradation that others complain about past 50% of the context window. The plan document, being a persistent file, survives Claude Code's auto-compaction in full fidelity. You can point Claude back to it at any time.

When This Is Overkill

I should be upfront: this workflow is not for everything. A two-line bug fix doesn't need a research.md and three rounds of plan annotation. If you can describe the change in one sentence and the fix touches one or two files, just tell Claude what to do directly. The research-plan-annotate cycle pays for itself on work that would normally take you an hour or more of thinking before writing code. Feature work, significant refactors, anything that touches multiple systems or has architectural implications. For quick fixes, it's overhead.

There's also a question of codebase maturity. In a greenfield project with no existing patterns to reference, the research phase has less to work with. The workflow gets stronger as your codebase grows, because there are more existing patterns for Claude to study and replicate.

Troubleshooting

Claude skims the codebase instead of reading deeply. Add more forceful language: "in great detail," "study every function," "don't stop until you understand all the edge cases." The words genuinely affect how thoroughly it reads. I'm not entirely sure why the phrasing matters this much, but it does.

Claude starts writing code before the plan is approved. Always include "don't implement yet" or "do not write any code" in your planning prompts. Without an explicit guard, it defaults to action.

The plan looks good but implementation diverges from it. Check whether the plan is specific enough. Vague steps like "add error handling" leave too much room for interpretation. Annotate with the exact behavior you want: which errors, what the response should look like, whether to retry or fail.

Context seems to degrade in long sessions. Point Claude back to plan.md explicitly: "re-read plan.md and continue from where you left off." The file persists even when chat context gets compacted.

Implementation introduces type errors or test failures. Make sure your implementation prompt includes "continuously run typecheck" (or your equivalent linting/test command). Claude catches issues much more reliably when told to check incrementally rather than at the end.

What's Next

You now have the full research-plan-annotate-implement pipeline. Try it on your next feature branch, and read Tane's original post for the exact prompts and more detailed examples of annotation notes.

Tags:claude codeai codingdeveloper workflowagentic codingcode planningprompt engineeringsoftware developmentCLI tools
Trần Quang Hùng

Trần Quang Hùng

Chief Explainer of Things

Hùng is the guy his friends text when their Wi-Fi breaks, their code won't compile, or their furniture instructions make no sense. Now he's channeling that energy into guides that help thousands of readers solve problems without the panic.

Related Articles

Stay Ahead of the AI Curve

Get the latest AI news, reviews, and deals delivered straight to your inbox. Join 100,000+ AI enthusiasts.

By subscribing, you agree to our Privacy Policy. Unsubscribe anytime.

How to Use Claude Code with a Plan-First Workflow | aiHola