Agent Skill Kit

Explaining Code

A skill that helps users understand code, diffs, and the changes an agent made. It picks the output format that fits: plain prose, a diagram, or a self-contained HTML explainer.

Purpose

To make complex code accessible and understandable by breaking down technical concepts into relatable analogies, visual representations, and clear explanations. This skill is triggered when users ask questions like “How does this work?”, “Explain this code”, “Explain this diff”, or “What did you change?”

Agents now write more of the code, so more of our work is reading and checking what they produced. The format ladder below follows Andrej Karpathy’s post on this: prose is often not the easiest format to understand, and an LLM can cheaply build a diagram or a one-off web page instead.

Output formats

Use the lowest step that makes the explanation clear. Go up a step when the reader asks or is still lost.

Step Format Use it for
1 Prose One function or one small concept
2 Diagram (ASCII inline, Mermaid if it renders) Flow, state, call stacks, module structure
3 Self-contained HTML file Multi-part systems, large diffs, before/after comparisons, or when asked
4 Explainer video Only when the user asks. It needs external tools or API keys

Prose follows the ask-ste-writing rules (about 80% ASD-STE100): short sentences, active voice, one meaning per word. ask copy ask-explaining-code installs that skill as a dependency.

HTML explainers are disposable:

Lay an HTML explainer out as a reference sheet: labelled panels (A, B, C…) with one topic each, annotations on real lines from the code or diff, tables instead of paragraphs, ✓/✗ columns for before/after, and a title block that names the source files and the commit or branch.

Core Principles

  1. Use Multiple Analogies — Different analogies resonate with different people
  2. Pick the Right Format — Prose, diagram, or HTML page, by complexity (see Output formats)
  3. Step-by-Step Walkthroughs — Break complex flows into digestible chunks
  4. Conversational Tone — Explain like you’re talking to a friend, not writing documentation
  5. Highlight Misconceptions — Address common misunderstandings proactively

Usage

When asked to explain code, follow this approach:

1. Start with the Big Picture

Begin with a high-level analogy that captures the essence:

"Think of this function like a restaurant kitchen:
- Orders come in (input parameters)
- Chefs process them (business logic)
- Dishes go out (return values)"

2. Create Visual Diagrams

Use ASCII art to show structure, flow, or relationships:

┌─────────────┐
│   Request   │
└──────┬──────┘
       │
       ▼
┌─────────────┐
│ Validation  │
└──────┬──────┘
       │
       ▼
┌─────────────┐
│  Database   │
└──────┬──────┘
       │
       ▼
┌─────────────┐
│  Response   │
└─────────────┘

3. Walk Through Step-by-Step

Break down the execution flow with numbered steps and inline comments:

# Step 1: Receive the user's data
def process_user(user_data):
    # Step 2: Check if the data is valid (like checking ID at a club entrance)
    if not validate(user_data):
        return "Invalid data"
    
    # Step 3: Transform the data (like formatting a letter before mailing)
    cleaned = sanitize(user_data)
    
    # Step 4: Save to database (like filing a document)
    save_to_db(cleaned)
    
    # Step 5: Send confirmation (like a receipt)
    return "Success!"

4. Use Relatable Analogies

Connect technical concepts to everyday experiences:

Technical Concept Analogy
Variables Labeled boxes that hold things
Functions Vending machines (input → process → output)
Loops Assembly line workers repeating tasks
Conditionals Forks in the road with signs
Classes Cookie cutters (template for objects)
APIs Restaurant menu (you order, kitchen handles it)
Caching Keeping frequently used items on your desk
Recursion Russian nesting dolls
Async/Await Ordering food delivery while doing other things
Database indexes Book index (quick lookup)

5. Address Common Misconceptions

Proactively clarify confusing points:

⚠️ Common Misconception:
"Does this loop run forever?"

No! The loop stops when i reaches 10. Think of it like climbing stairs:
you start at step 0 and stop when you reach step 10.

Response Structure

When explaining code, use this format:

  1. Quick Summary (1-2 sentences)
  2. Big Picture Analogy (relatable comparison)
  3. Diagram or HTML path (chosen from the output formats)
  4. Step-by-Step Walkthrough (numbered explanation)
  5. Common Pitfalls (what could go wrong)

Examples

Example 1: Explaining a Simple Function

User: “How does this work?”

def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

AI Response:

Quick Summary: This calculates Fibonacci numbers using recursion.

Analogy: Think of this like a family tree working backwards. To find out how many ancestors you have at generation N, you need to count ancestors from both your parents’ sides (N-1 and N-2), then add them together.

Visual Flow:

fibonacci(4)
    ├─ fibonacci(3)
    │   ├─ fibonacci(2)
    │   │   ├─ fibonacci(1) → 1
    │   │   └─ fibonacci(0) → 0
    │   └─ fibonacci(1) → 1
    └─ fibonacci(2)
        ├─ fibonacci(1) → 1
        └─ fibonacci(0) → 0

Step-by-Step:

  1. Base case check: If n is 0 or 1, just return n (these are the “leaves” of our tree)
  2. Recursive split: Otherwise, split into two smaller problems
  3. Combine results: Add the results from both branches

Key Concept: Each call spawns two more calls, creating a tree of calculations that eventually hit the base cases and bubble back up.

⚠️ Common Pitfall: This is elegant but slow! It recalculates the same values many times. For fibonacci(4), it calculates fibonacci(2) twice. For larger numbers, this becomes exponentially wasteful.

Example 2: Explaining a Complex Pattern

User: “What’s happening in this decorator?”

def retry(max_attempts=3):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for attempt in range(max_attempts):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    if attempt == max_attempts - 1:
                        raise
            return None
        return wrapper
    return decorator

AI Response:

Quick Summary: This is a decorator that automatically retries a function if it fails.

Analogy: Think of this like a persistent salesperson:

Nesting Structure:

┌─────────────────────────────────────┐
│ retry(max_attempts=3)               │  ← Policy setter
│  ┌───────────────────────────────┐  │
│  │ decorator(func)               │  │  ← Training manual
│  │  ┌─────────────────────────┐  │  │
│  │  │ wrapper(*args, **kwargs)│  │  │  ← Actual worker
│  │  │  • Try the task         │  │  │
│  │  │  • If fail, retry       │  │  │
│  │  │  • Give up after N tries│  │  │
│  │  └─────────────────────────┘  │  │
│  └───────────────────────────────┘  │
└─────────────────────────────────────┘

Step-by-Step:

  1. Outer function (retry): Sets the retry policy (how many attempts)
  2. Middle function (decorator): Receives the function to be wrapped
  3. Inner function (wrapper): Does the actual work:
    • Loops up to max_attempts times
    • Tries to run the original function
    • If it succeeds, returns immediately
    • If it fails, catches the error and tries again
    • On the last attempt, lets the error bubble up

Usage:

@retry(max_attempts=3)
def fetch_data():
    # This will auto-retry up to 3 times if it fails
    return requests.get(url)

⚠️ Common Misconception: “Why three nested functions?”

Each level serves a purpose:

Best Practices

Do’s ✅

Don’ts ❌

Tone Guidelines

Visual Elements to Use

Flow Diagrams

Start → Check → Process → Save → End
          ↓
        Error? → Retry

State Transitions

[Idle] --request--> [Loading] --success--> [Done]
                         |
                       error
                         ↓
                     [Error]

Data Structures

Array: [1, 2, 3, 4, 5]
       ↑        ↑
     index 0  index 4

Tree:     10
         /  \
        5    15
       / \
      2   7

Call Stacks

main()
  └─ processData()
      └─ validate()
          └─ checkEmail()  ← Currently executing

Notes