The Human-AI Pair Dynamic
Traditional pair programming has a driver (typing) and a navigator (guiding). AI pair programming has a similar dynamic, but the roles are fluid. Sometimes you drive and AI navigates ("What should I consider before refactoring this?"). Sometimes AI drives and you navigate ("Implement this feature, I will review your approach"). The best AI-native engineers switch between these modes instinctively.
When to Lead vs When to Follow
| You Lead (AI Assists) | AI Leads (You Review) |
|---|---|
| Defining requirements and acceptance criteria | Implementing well-defined features |
| Making architecture decisions with business context | Writing boilerplate code and tests |
| Designing user experiences and workflows | Refactoring and migrating code patterns |
| Evaluating tradeoffs that involve team/org context | Generating documentation from code |
| Reviewing and approving AI-generated changes | Finding and fixing mechanical bugs |
Establishing Context Efficiently
The most common frustration with AI pair programming is "it does not understand my project." This is almost always a context problem, not an AI capability problem. Here is how to establish context efficiently:
# Layer 1: Project context (CLAUDE.md — written once)
# Covers: tech stack, architecture, conventions
# See the CLAUDE.md lesson for details
# Layer 2: Session context (first message in a session)
> I am working on the billing module today. The key files are
app/lib/billing.ts, app/api/billing/, and app/components/billing/.
We use Stripe for payments and our own invoice generation.
# Layer 3: Task context (each specific request)
> Add a "retry failed payment" feature. When a subscription payment
fails, we should show a banner on the dashboard with a "Retry
Payment" button. Clicking it calls Stripe's retry endpoint.
Reference the existing PaymentFailedEmail handler in
app/lib/email-handlers.ts for the failure detection logic.
Working in Flow with AI
The biggest productivity gains come when you achieve a flow state with AI — a rhythm where you direct, AI implements, you review, and the cycle continues without interruption.
Tips for Maintaining Flow
- Batch your requests: Instead of one tiny change at a time, describe 3-4 related changes and let Claude do them all at once.
- Review diffs, not files: Focus on what changed, not re-reading the whole file. Use git diff to see only the changes.
- Use /compact between tasks: Keep context fresh. Summarize after each major task to avoid context pollution.
- Trust but verify: Run tests after AI changes, not just reading code. If tests pass, trust the implementation.
- Have a clear task list: Know your next 3 tasks before starting. Switch to the next immediately after completing one.
The "Yes, And" Pattern
Borrowed from improv comedy: instead of rejecting AI output and re-prompting from scratch, build on what AI gave you. Say "yes, and adjust X" instead of "no, do it differently."
# BAD: Rejection and re-prompt (breaks flow)
> [AI generates a component]
> No, that is not what I wanted. Start over. Make it...
# GOOD: Build on what was generated (maintains flow)
> [AI generates a component]
> Good start. Three adjustments:
1. Use our existing Button component instead of a raw button element
2. Add loading state for the async action
3. Move the inline styles to Tailwind classes
Keep everything else as is.
# Why this works:
# - AI retains context of what it already built
# - You only change what needs changing
# - Much faster than regenerating from scratch
# - The AI learns your preferences within the session
Rubber-Ducking with AI
# Use AI to think through problems before coding
> I need to design a notification system. Before writing any code,
help me think through these questions:
1. What notification channels do we need? (in-app, email, push?)
2. Should notifications be real-time or polled?
3. How do we handle notification preferences per user?
4. What is the data model for notifications?
5. How do we handle notification grouping (e.g., "5 new comments"
instead of 5 separate notifications)?
Give me your thoughts on each question with pros/cons.
# This is 10x better than rubber-ducking with an actual rubber duck
# because the AI actually responds with useful analysis
A Day in the Life of an AI-Native Engineer
| Time | Activity | Tool Used |
|---|---|---|
| 9:00 | Review overnight PR comments, triage bugs | GitHub + Claude Code (/review-pr) |
| 9:30 | Architecture discussion for new feature | Claude.ai for brainstorming |
| 10:00 | Implement feature — plan, then execute | Claude Code (plan mode + execution) |
| 10:45 | Review AI output, request adjustments | Claude Code (iterative refinement) |
| 11:00 | Write tests for new feature | Claude Code (generate + run tests) |
| 11:30 | Quick bug fixes (2-3 small bugs) | Cursor (Cmd+K for inline fixes) |
| 12:00 | Lunch | — |
| 13:00 | Code review for 2 teammate PRs | Claude Code (AI first pass + human review) |
| 14:00 | Refactoring: extract shared components | Claude Code (large-scale refactor) |
| 15:00 | Technical writing: update API docs | Claude Code (generate from code) |
| 15:30 | Explore solution for tomorrow's feature | Claude.ai (design exploration) |
| 16:00 | Clean up commits, write PR descriptions | Claude Code (git workflows) |
The Key to Great AI Pairing
The best AI pair programmers share three traits: (1) they communicate clearly — they know how to describe what they want in a way AI can act on, (2) they review critically — they read every diff and think about whether it is correct, not just whether it compiles, (3) they maintain momentum — they build on AI output rather than rejecting and restarting. These are the same skills that make great human pair programmers, just applied to a different partner.
Summary
AI pair programming is a skill that improves with practice. Learn when to lead and when to follow. Establish context efficiently with layered information. Maintain flow by building on AI output rather than rejecting it. Use AI for rubber-ducking and solution exploration before committing to an approach. The daily rhythm of an AI-native engineer alternates between directing AI and reviewing output, with different tools for different tasks throughout the day.