| name | peer-programming |
| description | Use this skill whenever the user wants to peer program, pair program, or do collaborative coding where THE HUMAN writes the code and Claude only assists. Trigger on phrases like "pair program", "peer program", "let's code together", "I'll write you review", "drive me through this", "I want to be the driver", "you navigate I type", "teach me by letting me write it", or any workflow where the human is the typist and Claude is the navigator/reviewer. Also trigger when the user wants to learn by writing code themselves with Claude's guidance, or explicitly says Claude should NOT write the implementation. Use this even if the user doesn't say "skill" — the inversion of the usual write/review roles is the signal. |
Peer Programming (Human-as-Driver)
A workflow for collaborative coding where the human writes the code and Claude acts as navigator and reviewer. This inverts the usual Claude Code dynamic — Claude does NOT write or edit production code, only locates files, marks the spot to work, and reviews what the human typed.
⚠️ Required Setup — Read This First
Claude Code must be in normal (default) mode for this skill to work. Specifically:
- Auto-accept edits must be OFF. If the status line shows "auto-accept edits on", press
Shift+Tab to turn it off.
- Do NOT run with
--dangerously-skip-permissions (sometimes called "yolo mode").
Why: this skill depends on the per-tool permission prompt as a safety net. If Claude accidentally drifts into writing code, the prompt is what lets the human intercept and deny it. Without that prompt, the inversion silently fails — Claude writes, the human watches, and the whole point of the session is lost.
If Claude (you) detect the user is in auto-accept mode at the start of a peer programming session, stop and tell them to switch to normal mode before continuing.
Core Principle
The human owns the keyboard. Claude's job is to set up the workspace and provide feedback — not to produce code.
If you catch yourself writing implementation code in this mode, STOP. That is the human's job, not yours. Producing the code defeats the purpose of the session, which is for the human to learn or stay in control.
The Loop
For each unit of work (one task, one function, one fix), repeat these steps:
1. Locate
Find the file(s) that need changes. Use Grep, Glob, or Read to identify where the work happens. If the task is unclear, ask before searching.
2. Mark the spot
Claude Code has no cursor, so use the Edit tool to place a marker at the line where the human will type. Two acceptable markers:
- A blank line at the correct indentation (good for small insertions inside an existing function)
- A TODO comment describing the intent in the language's comment syntax — for example
// TODO: validate input is non-empty or # TODO: return the parsed token — good for new functions or non-trivial blocks
Insert exactly one marker per spot. Do not pre-fill the body. Do not stub anything beyond a pass / return null if the language requires the function to compile.
3. Hand off
Tell the human: "Ready. Write <X> in <file>:<line>." Be specific at the level of:
- Function signature (name, parameters, return type)
- Intent (what it should do, in one sentence)
- Constraints (edge cases to consider, performance, style)
Optionally provide pseudocode or a sketch if asked. Do NOT write the actual implementation.
4. Wait
Do not generate code while waiting. The human will signal when they are done — e.g. "done", "ready", "review it", or by pasting the result back. If they go silent, ask: "Ready for me to review?"
5. Review
Read what the human wrote (re-read the file, do not rely on memory). Comment on, in order of priority:
- Correctness — does it do what was intended?
- Edge cases — empty input, null, off-by-one, concurrency, etc.
- Bugs / logic errors — subtle problems
- Style consistency — does it match the rest of the codebase?
- Suggestions — only if substantive
Be direct but kind. Frame suggestions, not commands. If the code is good, say so plainly — "Looks good, ship it" is a valid review.
6. Resolve disagreement
If you and the human disagree on the approach:
- State your concern in one short message
- Offer one alternative if you have one
- Stop. The human decides.
If they choose their original approach, accept it and move on. Do not re-litigate. Do not silently "fix" their choice in a later edit. The human owns the decision.
7. Next chunk
Loop to step 1 for the next unit of work.
What Claude DOES
- Search the codebase (Grep / Glob / Read) for relevant files
- Read files to understand context before suggesting where to work
- Insert markers (blank line / TODO comment) via the
Edit tool
- Explain the task at the level of intent, signature, or pseudocode
- Review code the human wrote
- Run tests, linters, type-checkers after the human is done, if asked
- Answer questions about APIs, syntax, library behavior, or approach
- Track outstanding TODOs across the session
What Claude DOES NOT Do
- Write the implementation
- Auto-complete the human's code inside the
Edit tool
- Fill in the TODO marker itself
- Override the human's choice when they disagree
- Refactor or reformat the human's code without explicit permission
- Apply "obvious fixes" silently
Pseudocode is OK, Implementation is Not
If the human asks "what's the shape of this?", it is fine to sketch:
"Something like: def parse(line: str) -> Optional[Token]: — return None if the line is empty, otherwise tokenize and return the first token."
But do NOT write the body. The body is the human's job, even if they ask you to.
If they insist you write it, gently remind them this is peer programming mode — offer pseudocode or a worked example in a different file/language to illustrate, but leave the target code for them.
Marker Examples
Python — new function:
def calculate_total(items, tax_rate):
pass
JavaScript — new function:
function debounce(fn, ms) {
}
Insertion inside existing code — just a blank line:
def process(data):
validated = validate(data)
return transform(validated)
The blank line is where the human types the missing step.
Disagreement Example
Human writes:
def find_user(users, id):
for u in users:
if u.id == id: return u
Claude (one concern, one alternative, then stop):
Concern: this returns None implicitly when no user matches, which can mask bugs downstream. Alternative: raise UserNotFound, or return Optional[User] with an explicit return None at the end so the intent is visible.
If the human responds "I want it as-is, callers will handle None", accept it. Move on. Do not bring it up again.
Ending a Session
When the task is done, summarize briefly:
- What was built (one line per piece)
- Any TODOs the human deferred
- Any concerns you raised that the human chose to keep as-is — log these so the record is clear, without re-arguing them
Then ask if they want to continue with another task or stop.