Most developers using AI coding tools are burning money on the wrong model tier. Every code generation task—whether it's architecting a new feature or fixing a typo—gets routed to the most capable (and most expensive) model available. That's like hiring a senior architect to write boilerplate CRUD endpoints.
The fix isn't to stop using powerful models. It's to stop using them for work they don't need to do.
The Cost Problem Nobody Talks About
AI coding assistants like Cursor, Claude Code, and Codex CLI make it easy to delegate work to large language models. The default behavior in most of these tools is to send every request to the most capable model—typically GPT-4-class or Claude Opus-class. That works, but it's wasteful.
Consider what happens in a typical coding session. You ask the AI to:
- Audit your codebase for potential issues
- Write implementation plans
- Generate boilerplate code
- Fix small bugs
- Refactor variable names
Two of those tasks benefit from deep reasoning and broad context awareness. The other three require competence but not genius. Yet all five hit the same expensive endpoint.
The pricing models for these services amplify the problem. Per-token pricing means every prompt and every completion costs money proportional to the model's capability tier. If you're running agentic workflows—where the AI loops through multiple steps autonomously—the cost multiplies with each iteration.
The solution isn't to use cheaper models for everything. That produces bad output. The solution is to be deliberate about which model handles which task.
What Is the Planner-Executor Pattern
The planner-executor pattern splits AI work into two distinct roles:
- Planner: A high-capability model that reasons about what needs to be done, audits code, identifies problems, and writes detailed instructions
- Executor: A cheaper, faster model that follows those instructions to produce code
The planner thinks. The executor does. Both are good at their jobs, but they're not the same job.
This pattern isn't new in software engineering. Tech leads write detailed specifications. Junior developers implement them. The spec doesn't need to be brilliant—it needs to be specific enough that someone with less experience can follow it correctly.
Applied to AI coding, the pattern looks like this:
- Send your codebase or problem to the planner model
- The planner audits the code and writes a step-by-step implementation plan
- Send that plan to the executor model
- The executor writes the actual code changes following the plan
The key insight: the planner's output is instructions, not code. The executor never needs to understand the big picture—it just needs to follow directions well.
How shadcn/improve Implements This
The shadcn/improve repository is a concrete implementation of this pattern. Its purpose is straightforward: use your most capable model to audit your codebase and write plans, then let cheaper models execute those plans.
The workflow is intentionally minimal:
Most capable model → audits code, writes detailed plan
Cheaper model → reads plan, writes code changes
The repository provides the scaffolding to make this work. You point it at your codebase, and the planner model analyzes what needs improvement. It doesn't just flag problems—it writes granular, step-by-step instructions that a less capable model can follow without needing to understand the full context.
This matters because context is expensive. Loading an entire codebase into a model's context window costs tokens. Running that context through deep reasoning layers costs more tokens. If you're paying for Opus-level reasoning on every file change, you're paying for the model to re-derive architectural understanding it already produced in the audit step.
shadcn/improve avoids that redundancy. The planner model sees the full picture once, produces a plan that encodes its understanding, and the executor model operates on that compressed representation.
Separating Planning From Execution
Splitting these roles requires thinking about what each model actually needs to produce good output.
What the planner needs
- Full context of the codebase or relevant sections
- Understanding of project conventions and patterns
- Ability to identify subtle bugs or architectural issues
- Capacity to write clear, unambiguous instructions
The planner's output must be self-contained. When it writes a plan like "Refactor the authentication middleware to use the existing session utility instead of direct cookie access," it needs to specify which file, which function, what the new implementation should look like, and what edge cases to handle. Vague instructions produce bad code regardless of which model executes them.
What the executor needs
- The plan (obviously)
- Just enough surrounding context to understand where changes go
- No need for the full codebase—just the files it's modifying
The executor's job is translation, not interpretation. If the executor has to make architectural decisions, the plan wasn't detailed enough. Go back to the planner.
The handoff point
The critical moment in this pattern is the handoff between planner and executor. A bad handoff produces one of two failures:
- Underspecified plan: The executor makes wrong assumptions and produces code that doesn't fit the architecture
- Overspecified plan: The plan is so rigid it's essentially code, and you've gained nothing from splitting the work
Good plans sit in the middle. They're specific about what to do and why, but they leave the syntax and implementation details to the executor.
Matching Model Tier to Task Complexity
Not every task needs the planner-executor split. Some things are fine to send directly to a cheaper model. Others need the full power of a frontier model and can't be decomposed.
Here's a practical framework for choosing:
Send directly to the planner (expensive model):
- Architecture decisions
- Cross-cutting refactor design
- Security audits
- Complex debugging requiring deep context understanding
Send through planner → executor pipeline:
- Feature implementation (planner designs, executor writes code)
- Large-scale refactoring (planner identifies what changes, executor makes changes)
- Codebase improvement tasks (planner audits, executor fixes)
Send directly to the executor (cheap model):
- Writing boilerplate from clear specs
- Simple bug fixes with known solutions
- Formatting and style changes
- Test generation from well-defined interfaces
The decision factors are straightforward: does the task require understanding the full context? Does it require nuanced reasoning? If both answers are yes, use the planner. If both are no, use the executor directly. If it requires reasoning but produces repetitive or predictable output, use the pipeline.
Implementation Details
Implementing the planner-executor pattern doesn't require a custom framework. You can approximate it with any AI coding tool that lets you choose models.
Manual approach with Claude Code or Cursor
The simplest implementation is to manually switch models based on task type:
- Open your most capable model (Claude Opus, GPT-4o, etc.)
- Ask it to audit the code or write a plan
- Copy that plan
- Switch to a cheaper model (Claude Sonnet, GPT-4o-mini, etc.)
- Paste the plan and ask it to implement
This works but is tedious. It's fine for testing the pattern before committing to automation.
Using shadcn/improve directly
The repository at shadcn/improve provides tooling to automate this flow. You can configure which models act as planner and executor, then run the pipeline against your codebase.
Building your own pipeline
For a custom implementation, the core loop looks like this:
def plan_and_execute(codebase_path, task_description):
# Step 1: Planner audits and writes plan
planner_prompt = f"""
Audit the codebase at {codebase_path}.
Task: {task_description}
Write a detailed, step-by-step implementation plan.
Include specific file paths, function names, and expected behavior.
"""
plan = call_model(tier="capable", prompt=planner_prompt)
# Step 2: Executor implements the plan
executor_prompt = f"""
Follow this implementation plan exactly.
Write the code changes described.
Plan:
{plan}
"""
result = call_model(tier="fast_cheap", prompt=executor_prompt)
return result
The actual implementation needs error handling, context management, and probably iterative refinement. But the structure is this simple.
One important detail: maintain the plan as a first-class artifact. Save it, version it, review it. The plan is the bridge between comprehension and execution. If something goes wrong, the plan is where you debug—not the code output.
When This Pattern Works (And When It Doesn't)
The planner-executor pattern works well when:
- Tasks are decomposable: You can separate understanding from doing
- The codebase is large: Context costs become significant, making single-model approaches expensive
- You're running agentic workflows: Each step in an agent loop can be planned once and executed cheaply
- You need consistency: Plans encode architectural decisions so the executor doesn't reinvent approaches file by file
The pattern struggles when:
- Tasks require tight iteration between reasoning and coding: Some problems require you to write code, see what breaks, and reason about the breakage in a tight loop. Splitting planner and executor adds latency to this cycle.
- The plan can't be written without seeing execution results: If the planner needs to see what the executor produces to refine its plan, you need a feedback loop that partially defeats the purpose of splitting.
- Tasks are trivial: For one-line fixes, the overhead of planning isn't worth it. Just use the cheap model directly.
There's also a quality tradeoff to acknowledge. The planner-executor pattern produces good output, but not always as good as having the most capable model do everything end-to-end. The question is whether that marginal quality difference is worth the marginal cost difference. For most production code, plans executed by competent models are sufficient.
Getting Started
If you're currently spending more than you'd like on AI coding tools, try this:
- Audit your current usage: Look at what you're sending to your most expensive model. Categorize each request as planning, execution, or trivial.
- Try the manual split for a week: Use your best model for planning only. Copy plans to a cheaper model for implementation. Track the cost difference and quality of output.
- Automate if it works: If the manual approach saves money without killing quality, set up an automated pipeline. Use shadcn/improve as a starting point or build your own.
- Iterate on plan quality: The most common failure mode is underspecified plans. If executor output is bad, improve the planner's instructions before blaming the executor model.
The planner-executor pattern isn't about being cheap. It's about being deliberate. Expensive models should do expensive work. Cheap models should do cheap work. Right now, most AI coding workflows treat every task like it requires a senior engineer. Most tasks don't.