What Is Pair Programming?
Traditional pair programming involves two developers working at one machine. One plays the Driver — hands on keyboard, writing code. The other plays the Navigator — thinking strategically, spotting issues, and guiding direction. They swap roles regularly.
When you program with AI, the dynamic is similar but the roles shift:
Traditional Pair Programming
- Driver — writes the code
- Navigator — thinks strategically
- Both are human, both understand the domain
- Communication is natural and bidirectional
AI Pair Programming
- You — the architect and decision-maker
- AI — the fast, knowledgeable assistant
- You own the vision; AI executes rapidly
- Communication requires deliberate structure
The key insight is that AI doesn't write all the code for you. It means you collaborate — you think, AI generates, you evaluate, AI refines. The quality of output depends directly on the quality of your guidance.
Three Effective Working Modes
Different tasks benefit from different modes. The three modes below provide a practical starting toolkit; adapt them to the risk and evidence required by the task.
1. Brainstorming Mode
Before writing a single line of code, ask AI to explore the solution space. This is where you generate options, compare approaches, and think through trade-offs — all before committing to an implementation direction.
Give me three different approaches to implement
real-time activity syncing in a React family planner.
For each approach, describe:
- How it works
- Pros and cons
- When you'd choose it
2. Implementation Mode
Once you've decided on an approach, switch to implementation mode. Here you give AI specific, focused instructions to write code. Keep each request small — one component, one function, one feature at a time.
Implement approach #2 — WebSocket-based syncing.
Use TypeScript and React hooks.
Create a custom useActivitySync hook that:
- Connects to ws://localhost:3001
- Handles reconnection on disconnect
- Returns { activities, isConnected, error }
3. Review Mode
After generating code, switch AI into reviewer mode. Ask it to critique its own output — or your existing code — with the eye of a senior developer. This catches issues that generation mode often misses.
Review this code as a senior React developer.
Focus on:
- Performance issues (unnecessary re-renders)
- Error handling gaps
- TypeScript type safety
- Edge cases I might have missed
Be critical. I want honest feedback, not validation.
Pro Tip: Name Your Modes Explicitly
Naming the task mode can help set the expected output. Starting with "We're brainstorming — don't write code yet" or "Review this implementation" distinguishes exploration from implementation without relying on the model to infer your intent.
The Iterative Loop
The core rhythm of AI pair programming is not "ask once, get answer." It is a loop of generation, testing, review, and refinement, with a stopping condition based on acceptance criteria.
A feature may need several iterations before it is ready for review or release. Later cycles can fix bugs, add edge cases, improve types, and refine the design. The number and duration of those cycles depend on the task and the quality gates involved.
Prefer reviewable progress over prompt perfection. Provide enough context to make the first result testable, evaluate it, and refine only where the evidence shows a gap. High-risk tasks may require more requirements work before generation.
Work in Small Steps
A common mistake is to combine several dependent decisions in one request without defining interfaces or checks.
⚠️ Common Mistake
Build me a complete family
planner app with authentication,
database, real-time sync, and
a calendar view.
Result: chaotic, incomplete code that tries to do everything and does nothing well.
✅ Better Approach
- First: build the calendar grid component
- Then: add state management for activities
- Then: connect to API
- Then: add authentication
- Then: add real-time sync
Result: each piece works correctly before you move on.
A focused task is easier to review. Large requests create more interacting assumptions; smaller coherent steps reduce that risk, provided you keep the relevant system context visible.
Ask for a Plan and Rationale
Before asking for code, ask for a concise plan, assumptions, and trade-offs. This can expose a weak design early and gives you something concrete to review.
Before writing any code, describe your plan:
- What components will you create?
- How will state flow between them?
- What are the potential edge cases?
- Are there any trade-offs in your approach?
Then implement the plan.
When the model states a plan, assumptions, and trade-offs, you can evaluate the approach before evaluating the code. Catching a flawed direction at this point can reduce later rework.
When AI Gets It Wrong
AI-generated code can be wrong even when it looks plausible. Plan checks for failure modes such as:
- Wrong imports — referencing packages or modules that don't exist in your project
- Incorrect API calls — using methods or parameters that don't match the actual API
- Outdated syntax — using patterns from older versions of frameworks
- Hallucinated functions — inventing methods that look plausible but don't exist
- Subtly wrong logic — code that looks correct but has off-by-one errors or wrong comparisons
Always test AI-generated code yourself. Never ship code you haven't run. Never assume correctness because "it looks right." The most dangerous bugs are the ones in code that appears perfectly reasonable. AI pair programming only works if you maintain your role as the quality gate.
AI as Instant Documentation
AI can help you navigate documentation by explaining terminology or suggesting what to look up. Treat the answer as a starting point, then verify version-sensitive APIs and behavior in the official documentation.
Explain the difference between useMemo and useCallback
in React.
When should I use each one?
Give me a concrete example where using the wrong one
would cause a performance problem.
Follow-up questions can help you identify the relevant concept or documentation section. For a question such as whether useMemo helps when filtering 500 activities, verify the current React guidance and measure the actual component before applying the suggestion.
AI as Debug Companion
When you hit an error, AI excels at rapid diagnosis — especially when you give it proper context. Here's the pattern:
Here is my code:
[paste the relevant function or component]
Error message:
TypeError: Cannot read properties of undefined (reading 'map')
at ActivityList (ActivityList.tsx:23:18)
What I'm trying to do:
Render a list of activities passed as props.
What happens instead:
Crashes on initial render before data loads.
What's the most likely cause?
Notice the structure: code, exact error message, intent, and observed behavior. This gives AI everything it needs for accurate diagnosis. We'll go much deeper into debugging strategies in Chapter 5.
Real-World Conversation Flow
To make this concrete, here's what an actual pair programming session looks like in practice. Notice how the developer stays in control while leveraging AI's speed.
FilterBar component with two dropdown selectors. State would live in the parent via a callback. I'd use a FilterState interface with member: string | null and day: string | null. The parent applies filters to the activity list before passing to the calendar grid...Notice the pattern: the developer directed each step, evaluated the output, and guided refinement. The model proposed; the developer decided and continued until the stated criteria were met.
Effective Communication Patterns
Over time, certain communication patterns consistently produce better results when pair programming with AI. These are worth making habitual:
- Share relevant, permitted context — A sanitized excerpt, interface, failing test, or minimal reproduction is often more useful than a verbal summary. Do not send secrets, personal data, private logs, or code you are not permitted to disclose.
- Include error messages verbatim — Copy the full error, including stack traces. Don't paraphrase or summarize errors.
- State your intent explicitly — "I'm trying to make this component re-render only when the activity list changes" is far more useful than "this re-renders too much."
- Ask for alternatives — When you're unsure about an approach, ask for two or three options with trade-offs rather than a single solution.
- Give feedback on outputs — "This works but the naming is confusing" or "The approach is right but add error handling" helps AI learn what you need within the session.
Take a function or component you've recently written. Run through all three modes with AI:
- Brainstorm: Ask AI for three alternative approaches to the same problem. Compare with your implementation.
- Implement: Pick the most interesting alternative and ask AI to implement it.
- Review: Ask AI to review both versions — yours and the generated one — and identify strengths and weaknesses of each.
This exercise trains you to fluidly switch between modes, which is the foundation of effective AI pair programming.
Key Takeaways
- AI pair programming means collaboration — you direct, AI executes, you verify
- Use three modes deliberately: brainstorming, implementation, and review
- The iterative loop (generate → test → improve → repeat) is the core workflow
- Work in small steps — one component, one function, one feature at a time
- Ask AI to explain its plan before writing code to catch design flaws early
- Always test AI output yourself — never trust code you haven't run
- Use AI as instant documentation and debug companion to stay in flow
Related Guides
VS Code and Cursor with AI
Put pair-programming patterns into practice inside an editor.
CLI-First AI Development
Work with coding agents from the terminal on real projects.