Claude
Skills
Sign in
Back

reverse-architect

Included with Lifetime
$97 forever

Reverse-engineer any software project's design from high-level purpose down to component interactions, producing a knowledge map that enables either contributing to the project or rebuilding your own version in a different tech stack. Use when asked to "understand this codebase", "explain how this project works", "map this architecture", "write docs for this repo", "prepare to contribute", or "rebuild this in my own stack".

Design

What this skill does


# Reverse Architect

Expert assistant for reverse-engineering the *design* of an existing software project — not just reading its code, but reconstructing the reasoning behind it. The output is a layered knowledge map that takes a reader from "why does this exist?" all the way down to "how do these components talk to each other?", deep enough to support two end goals: **contributing** to the project, or **rebuilding** a personal version in a preferred tech stack.

## Core Philosophy

Every analysis is driven by one root question:

> **"If I had to rebuild this from an empty folder, what is the minimum I'd need to understand — and in what order — so that every line I write has a reason?"**

This question is deliberately symmetric. A contributor and a rebuilder need the *same map*; they just stop at different layers and act on it differently. The contributor uses the map to make a small, safe change without breaking an invariant. The rebuilder uses the same map to decide what is load-bearing (must keep) versus what is an accidental implementation choice (free to swap).

The skill works **outside-in and static-to-dynamic**: start from human purpose, descend through structure, then animate the structure by tracing data through it. Understanding is never assumed — each step ends with a **Decision Point**, a sentence the agent must be able to complete before moving deeper. If it cannot complete the sentence, it has skimmed, not understood, and must go back.

**Anti-patterns to avoid:**

- Listing files and folders without explaining *why each boundary exists*
- Reciting the tech stack as a dependency dump instead of grouping it *by the concern each library serves*
- Drawing static box diagrams instead of tracing *data in motion*
- Jumping to "here's how to change it" before the invariants are mapped
- Treating every dependency as essential — failing to separate load-bearing walls from decoration

---

## Thinking Process

When activated, follow these seven steps in order. Steps 1–6 build understanding identically for both end goals; Step 7 forks into the track the user needs.

### Step 1: Find the Pain & the Promise (Why Does This Exist?)

**Goal:** State, in one plain-language sentence, the human problem this project solves — before reading architecture.

**Key Questions to Ask:**
- What does a person do *manually and painfully* without this tool?
- Who is the user, and what is the exact moment they reach for it?
- What is the *promise* — the one outcome that, if removed, makes the whole project pointless?

**Thinking Framework:**
- "Without this, [person] would have to _____."
- "The single most important thing this must get right is _____. Everything else is supporting cast."
- Resist reading the code until you can answer these. If you can't, the code will be noise.

**Actions:**
1. Read the README's first paragraph and the top-level docs — but only for *intent*, not mechanics.
2. State the purpose in one sentence containing no library names.
3. Identify the one promise that defines success.

**Decision Point:** You can complete:
- "This project exists so that [person] does not have to [painful thing], and it succeeds if and only if [the promise]."

**Example (Plannotator):** "This exists so that an engineer does not have to blindly approve an AI agent's plan in a terminal — it succeeds if and only if the user can review, annotate, and approve/deny a plan in a real UI, and that decision flows back to the agent."

---

### Step 2: Map the Topography (What Are the Boundaries, and Why?)

**Goal:** Draw the project's module/package boundaries as a dependency graph, and explain why each boundary exists — what would break if two modules merged.

**Key Questions to Ask:**
- What are the top-level units (packages, apps, services), and which depend on which?
- Which units are *leaves* (pure logic, no internal deps) and which are *roots* (deployables)?
- Why is each boundary drawn here? What single responsibility does it protect?

**Thinking Framework — Leaves to Roots:**
```
Pure-logic leaves (no internal deps, easy to test)
  → Shared infrastructure (servers, UI kits — depend on leaves)
    → Composition layer (app shells — wire infrastructure together)
      → Deployables (the apps users actually run)
```
- "This boundary exists so that [unit A] can change without forcing [unit B] to change."
- A boundary that protects nothing is accidental complexity — note it.

**Actions:**
1. Read the workspace/build manifest (`package.json` workspaces, `go.mod`, `Cargo.toml`, etc.) to find the units.
2. Read each unit's manifest to extract internal dependencies only.
3. Draw the dependency graph as ASCII, ordered leaves → roots.
4. Build a one-line single-responsibility table for each unit.

**Decision Point:** You can complete:
- "The dependency graph flows [leaves] → [infra] → [apps]; the load-bearing boundary is [X] because it isolates [responsibility]."

**Example (Plannotator):** `shared` + `ai` (pure leaves) → `server` + `ui` (infrastructure) → `editor` + `review-editor` (app shells) → `apps/hook`, `apps/opencode-plugin`, etc. The `shared` boundary exists so the same storage/diff/VCS logic runs unchanged under both the Bun server and the Node-based Pi server.

---

### Step 3: Inventory the Tech Stack by Concern

**Goal:** Map the technology choices grouped by the *concern* each one serves, with a note on what could replace it. This is the bridge between "what they used" and "what I'd use."

**Key Questions to Ask:**
- For each concern (UI, parsing, storage, networking, build, etc.), which library owns it?
- *Why* this library — what property made it the choice (performance, ergonomics, ecosystem)?
- Is this choice load-bearing (tied to the promise) or swappable (incidental)?

**Thinking Framework — The Concern Table:**

| Concern | Library chosen | Why this one | Swappable? |
|---------|---------------|--------------|------------|
| UI rendering | … | … | yes/no + with what |
| Data parsing | … | … | … |
| Persistence | … | … | … |
| Transport/server | … | … | … |
| Build/packaging | … | … | … |

- "If I were rebuilding, I could replace [X] with [Y] and lose only [Z]."
- A library that appears in many units is structural; one that appears in one unit is local.

**Actions:**
1. Read the dependency lists from Step 2's manifests.
2. Cluster dependencies by concern, not alphabetically.
3. For each concern, name the owner library and a plausible substitute.

**Decision Point:** You can complete:
- "The stack divides into [N] concerns; the load-bearing choices are [list] because they directly enable the promise; the rest are swappable."

**Example (Plannotator):** UI = React 19 + Tailwind 4; markdown render = `marked`, HTML→MD = `turndown`; plan diff = `diff` npm; **code-review diff = `@pierre/diffs` (load-bearing — its shadow-DOM renderer is the heart of the review UI)**; text annotation = `web-highlighter` (load-bearing); transport = `Bun.serve` (swappable — Pi proves it, using `node:http`); build = Vite + `vite-plugin-singlefile`.

---

### Step 4: Trace the Core Flows End-to-End (Animate the Structure)

**Goal:** For each primary user flow, trace data from the triggering event to the final resolution, naming every component it passes through. This turns the static graph from Step 2 into living behavior.

**Key Questions to Ask:**
- What are the 2–4 *primary* flows (the things users actually do)?
- For each: what triggers it, what transforms the data, where is it stored, how does the result get back?
- At each hop: *what is lost or could break here?*

**Thinking Framework — Follow the Data:**
```
Trigger (user action / external event)
  → Who receives it first?
    → How is the payload parsed / validated?
      → Which component transforms it?
        → Where does it rest (storage / state)?
          → How is the result rendered / returned?
            → How does the loop close (response to trigger)?
```

**Actions:**
1. Identify the entry point of each flow (CLI ar
Files: 4
Size: 31.9 KB
Complexity: 48/100
Category: Design

Related in Design