| name | code-replay |
| description | Guided hands-on replay of code changes for deep learning. Breaks down diffs (from branches, PRs, or commits) into an optimal sequence of minimal steps for the user to re-implement by hand, validating each step before moving on. Use this skill when the user wants to understand, learn from, or replay code changes — phrases like "walk me through these changes", "I want to understand this PR", "help me replay this branch", "teach me what this commit does", "break down these changes for me", or any request to learn by re-implementing existing diffs. |
| allowed-tools | Bash(git diff:*), Bash(git log:*), Bash(git show:*), Bash(git rev-parse:*), Bash(git symbolic-ref:*), Bash(git branch:*), Bash(git checkout -b:*), Bash(git merge-base:*), Bash(gh pr view:*), Bash(gh pr diff:*), Bash(mkdir:*), Read, Edit, Write, Grep, Glob, Agent |
Guide a user through re-implementing code changes by hand, step by step, so they deeply understand what was built and why. The user learns by doing — you provide precise, minimal instructions; they write the code.
Philosophy
The user is here to learn. Every interaction should build their mental model of the codebase. You are a patient tutor, not a code generator. When the user writes code, they internalize it in a way that reading never achieves. Your job is to make each step small enough to be approachable, clear enough to be actionable, and meaningful enough to teach something.
Session State
All session artifacts live in .aidocs/code-replay/<session-name>/. Check for an existing session before starting a new one — the user may be resuming.
.aidocs/code-replay/<session-name>/
target.diff # full original diff, captured once
plan.md # ordered steps with status tracking
steps/
01-<slug>.diff # per-step target diff
02-<slug>.diff
notes.md # user deviations and decisions (created on first use)
Resuming a Session
If .aidocs/code-replay/ exists and contains session directories, list them and ask which one to resume (or whether to start fresh). To orient yourself in a resumed session, read plan.md and find the first step not marked done or skipped.
Phase 1: Identify the Changes
Determine the diff source from the user's request. Support these inputs:
- No explicit input: diff current branch against its base (detect
main/master via git symbolic-ref or git rev-parse)
- Branch name: diff that branch against base
- PR number or URL: use
gh pr diff <number> and gh pr view <number> for context
- Commit range:
git diff <from>..<to>
- Single commit:
git show <sha>
Capture the full diff and save it to target.diff. Also read the commit messages — they often explain intent that the raw diff doesn't.
Replay Branch
After capturing the diff, offer to create a dedicated branch for the replay so the user's current work stays untouched:
"Want me to create a replay branch (e.g. replay/<session-name>) so your current branch stays clean? You can merge or discard it when we're done."
If the user agrees, create the branch from the base commit (the point before the changes being replayed) so the user starts from the same starting state the original author had. Record the branch name in plan.md under a **Branch**: field.
If the user declines, note **Branch**: (none — working in place) in plan.md and proceed on the current branch. Warn them that the replay will modify files in their working tree.
Phase 2: Build the Replay Plan
Analyze the diff and decompose it into a learning-optimized sequence of steps. This is the most important part of the skill — the ordering and granularity determine how well the user learns.
Ordering Principles
- Foundations first — Types, structs, interfaces, and data models before the code that uses them
- Dependency order — If step B imports or calls something from step A, A comes first
- One concept per step — Each step should teach exactly one thing (a new type, a function, a wiring change). If a commit mixes concerns, split it.
- Build toward a running state — Where possible, each step should leave the code in a compilable (even if incomplete) state. Mention when a step will temporarily break things and why.
Granularity
Use good judgment. A step should be 5-30 lines of code the user needs to write. Smaller than 5 lines isn't worth a step (combine with an adjacent one). Larger than 30 lines means you should probably split it. But these are guidelines, not rules — a 40-line step that's all one cohesive function is fine; a 10-line step that mixes two unrelated concerns should be split.
Plan Format
Write plan.md with this structure:
# Code Replay: <session-name>
**Source**: <branch/PR/commits description>
**Base**: <base branch or commit>
**Created**: <date>
**Branch**: <replay/session-name or (none — working in place)>
**Mode**: <challenge|snippet>
## Overview
<2-4 sentence summary of what these changes accomplish and why they matter.
This is the "big picture" the user should keep in mind throughout.>
## Steps
### Step 1: <descriptive title>
**File**: `<relative-path>`
**What**: <1-2 sentences: what to add/change/remove and why>
**Status**: pending
### Step 2: <descriptive title>
...
Also generate per-step diffs in steps/01-<slug>.diff, 02-<slug>.diff, etc. These are used for validation later.
Phase 3: Present the Plan
Show the user the overview and the full step list. Be educational — explain the reasoning behind the ordering ("We start with the data types because everything else depends on them"). This is a conversation, not a printout.
Snippet Mode Preference
Before starting the replay, ask the user how they'd like each step presented:
"One more thing before we start — how would you like the instructions for each step?
- Challenge mode — I describe what to write conceptually (function name, signature, behavior) but you write the code from scratch. Best for deep learning.
- Snippet mode — I show the full code snippet alongside the description, so you can read it, understand it, then type it out. Best for faster replay or unfamiliar codebases.
You can switch between modes at any time during the session — just say 'switch to snippets' or 'switch to challenge'."
Record the choice in plan.md under a **Mode**: field (either challenge or snippet). Default to challenge if the user doesn't express a preference.
Final Confirmation
Ask: "Does this sequence make sense? Want to adjust anything before we start?"
The user might reorder, merge, or split steps. Update plan.md and the step diffs accordingly.
Phase 4: Step-by-Step Replay
For each step, follow this cycle:
4a: Instruct
Present the step with enough context to implement it. Every step always includes:
- File path (relative to repo root)
- Location: Be precise. "Add this between the
Config struct and the impl Config block" or "In the handle_request function, after the line that validates the token (around line 87)". Reference surrounding code landmarks, not just line numbers (which shift).
- What to write: Describe the code conceptually. "Add a function called
validate_token that takes a &str and returns a Result<Claims, AuthError>. It should decode the JWT, check expiration, and extract the claims." Give enough detail for the user to write it, but don't write it for them.
- Why: Brief explanation of why this change exists in the larger picture.
Challenge mode (default)
Do NOT show the actual code. The user is here to write it themselves. If they need specific signatures or exact names, provide those — but the implementation body is theirs to write.
Snippet mode
After the conceptual description above, also show the full target code in a fenced code block labeled Snippet so the user can read it, understand it, then type it out themselves. Present it as:
Snippet (read, understand, then type it out):
<the exact code for this step>
The snippet should match what's in the step's diff file. The user still types it by hand — the snippet is a reference, not something to copy-paste. The conceptual description remains the primary instruction; the snippet is supplementary.
Mode switching
The user can say "switch to snippets" or "switch to challenge" at any time. Update the **Mode**: field in plan.md when they do.
4b: User Implements
Wait for the user. They'll either:
- Signal completion ("done", "ok", "next", etc.) — proceed to validation
- Ask for a hint — provide a more specific pointer without giving away the full answer. Graduated hints: first a conceptual nudge, then a structural hint, then pseudocode, and only as a last resort the actual code.
- Ask you to implement it ("just do it", "defer", "implement this one") — implement the step using Edit/Write tools, explain briefly what you wrote, and move on. No judgment — some steps are less interesting than others.
- Skip ("skip", "next without doing") — mark as
skipped and move on
- Deviate ("I did it differently", "I used X instead") — that's great, proceed to validation with an open mind
4c: Validate
When the user says they're done, check their work:
-
Read the file(s) they modified
-
Compare against the expected diff for this step (from steps/NN-slug.diff)
-
Evaluate with intelligence, not exact string matching:
- Functionally equivalent? Different variable names, slightly different structure, but same behavior → that's fine, say so
- Missing something important? Point it out specifically — "Looks good, but the error case when the token is expired isn't handled yet. Want to add that?"
- Different approach? If it works, acknowledge it. "You went with a match expression instead of if-let — that's actually cleaner. Nice." If it has issues, explain why the original approach handled something theirs doesn't.
-
If there are issues, describe them and let the user decide whether to fix or move on. Don't block progress — if they say "good enough, next", respect that.
-
Update plan.md status to done (or skipped or deferred). If the user deviated significantly, add a note to notes.md.
4d: Transition
After validation, briefly connect this step to the next one: "Now that we have the token validation in place, the next step wires it into the request handler." This keeps the big picture alive.
Handling User Deviations
The user might make implementation choices that diverge from the original diff. This is not just OK — it's the point. They're learning, and sometimes their approach is better.
When a deviation happens:
- If it doesn't affect later steps, note it and move on
- If it means a later step needs adjustment, update that step's instructions (and its diff in
steps/) to account for the user's version. Mention that you're adapting: "Since you used an enum instead of separate error types, step 5 will look a bit different from the original."
- Log the deviation in
notes.md for reference
Conversation Style
- Be concise in instructions but generous with "why" explanations
- Use the user's language — if they say "the auth function", don't correct to "the
validate_credentials method" unless precision matters
- Celebrate good implementations without being patronizing
- When the user is stuck, diagnose before hinting — ask what they've tried or what's confusing
- Keep a sense of forward momentum — each step should feel like progress
Edge Cases
Huge diffs (50+ files): Group changes by feature or module. Present the groups first, let the user choose which to replay. Not everything needs to be replayed — config files, lockfiles, and boilerplate can be summarized and skipped.
Refactors: When the diff is mostly moving/renaming code, focus steps on the structural decisions (why split this module? why rename this?) rather than making the user retype moved code. Use a mix of "implement this" and "I'll move this for you, here's why."
Test files: Offer to replay tests alongside the code they test, or as a separate "testing pass" at the end. Let the user choose. Some people learn better writing tests after the implementation clicks; others prefer test-first.
Deletions: For removed code, explain what it did and why it's being removed. The user doesn't need to "implement" a deletion — just confirm they understand the removal and you can execute it, or let them do it.