agentleFS
ZunoSmartLabsZunoSmartLabs/zsl-superpowers/skills/engineering/codebase-design/SKILL.md

codebase-design

Skill2 starsChanged 52 days agoMITView on GitHub

Shared vocabulary and refinements for reasoning about module depth, interfaces, seams, and adapters — the deep-module design language. Use when discussing module/interface design, whether a module is deep or shallow, where to place a seam, how to design an interface for testability, or when exploring alternative interfaces for a module. Composed by /improve-codebase-architecture and /tdd.

194 other projects use a version of this, 170 of them edited.

Adopted by

Most recently taken up by

Used with

Projects with it also use setup-ts-deep-modules, loop-me and 9 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • liufeng1976Skill

    setup-ts-deep-modules

    Wire dependency-cruiser into a TypeScript repo so each package is a deep module — implementation hidden in subfolders, reachable only through its entry-point files. User-invoked.

    Also in 43 projects that use this

  • RoentekSkill

    loop-me

    Grill me about specs for the workflows I want to build, within this workspace.

    Also in 55 projects that use this

  • LesaniSkill

    writing-beats

    Shape an article as a journey of beats, choose-your-own-adventure style. The user picks a starting beat from the raw material, you write only that beat, then offer options for where to pivot next, beat by beat, until the article reaches a natural end. Use when the user has raw material and wants to assemble it as a narrative rather than an argument.

    Also in 58 projects that use this

  • AWSSkill

    to-questionnaire

    Turn a decision you can't fully answer into a questionnaire for someone else to fill in.

    Also in 90 projects that use this

  • LesaniSkill

    writing-shape

    Take a markdown file of raw material and shape it into an article through a conversational session — drafting candidate openings, growing the piece paragraph by paragraph, arguing about format (lists, tables, callouts, quotes) at each step. Use when the user has a pile of notes, fragments, or a rough draft and wants help turning it into something publishable.

    Also in 58 projects that use this

  • AWSSkill

    wizard

    Generate an interactive bash wizard that walks a human through steps only they can perform. Use when provisioning infrastructure, setting up credentials or CI secrets, walking an unfamiliar third-party dashboard, or running a one-off migration or cutover. Don't invoke this for steps the agent can perform itself.

    Also in 122 projects that use this

  • +2 more from aws
  • +1 more from Lesani

The file

We split this skill into the rules it gives an agent

5 rules. 0 are common, 4 are distinctive, and 1 is very specific to this project.

  • 0

    Common

    Most of the 181 edited versions we read keep these.

  • 4

    Distinctive

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    When designing interfaces, ask:

    line 131
  2. Distinctive:

    One adapter = hypothetical seam. Two adapters = real one: Don't introduce a seam unless something actually varies across it.

    line 148
  3. Very specific:

    When the user wants to explore alternative interfaces for a chosen module (e.g.

    line 200
  4. Distinctive:

    Before spawning sub-agents, write a user-facing explanation of the problem space for the chosen candidate:

    line 210
  5. Distinctive:

    After comparing, give your own recommendation: which design you think is strongest and why.

    line 255

“Common” is measured: kept by at least 6 in 10 of the 181 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Codebase Design

The shared design language for module depth, interfaces, seams, and adapters. One home for the deep-module vocabulary so the terms mean the same thing in every skill that reasons about architecture — /improve-codebase-architecture, /tdd, and anything else that touches interface design composes this skill instead of carrying its own copy.

Most terms come from two books — A Philosophy of Software Design (Ousterhout, "APoSD") and Clean Architecture (Martin) — bundled as decision-pressure rules into the skills that consume this vocabulary. When we use a book's term, we use it the way the book uses it. A few terms are ours, added where the books don't have a precise name for what we mean.

Vocabulary

Module (both books) Anything with an interface and an implementation. Scale-agnostic — applies equally to a function, class, package, or tier-spanning slice. APoSD: a deep module has a small interface hiding a large body of behaviour; a shallow module has an interface nearly as wide as its implementation. Avoid: unit, component, service.

Interface (both books) Everything a caller must know to use the module correctly. Includes the type signature, but also invariants, ordering constraints, error modes, required configuration, and performance characteristics. Clean Architecture calls inward-owned interfaces ports (see below). Avoid: API, signature (too narrow — those refer only to the type-level surface).

Implementation (APoSD) What's inside a module — its body of code. Distinct from adapter: a thing can be a small adapter with a large implementation (a Postgres repository) or a large adapter with a small implementation (an in-memory fake).

Depth (APoSD) Leverage at the interface: a lot of behaviour behind a small interface. Deep = high leverage. Shallow = interface nearly as complex as the implementation.

Boundary (Clean Architecture) A line across which source dependencies cross in one direction only. Enforces the dependency rule: dependencies point inward toward higher-level policy. A boundary is a particular kind of seam — one that also enforces a dependency direction.

Layer (Clean Architecture) A horizontal stack of modules at the same level of policy. The inward direction is upward in policy (more general, more stable). Not interchangeable with module — a layer is the stack; a module is a unit within it.

Port (Clean Architecture) An interface owned by an inner layer, implemented by an outer-layer adapter. Use "port" when the dependency-direction property is the point; otherwise just interface.

Adapter (Clean Architecture) A concrete thing that satisfies an interface at a seam or boundary. Describes role (what slot it fills), not substance (what's inside). Humble adapters do only translation between external formats and the use-case call — no business decisions.

Cognitive load / Change amplification / Hidden dependencies / Temporal coupling (APoSD) The dimensions a deep module reduces. Use these names when describing why a deepening helps:

  • Cognitive load — total facts a reader must hold at once.
  • Change amplification — one conceptual change requiring many code changes.
  • Hidden dependencies — knowledge required to use the module that isn't visible at the interface.
  • Temporal coupling — operations that must be called in a specific order; almost always a sign of a shallow module exposing its phases.

Our additions

Where the bundled books don't have a precise term, we've added these.

Seam (from Michael Feathers, Working Effectively with Legacy Code — also bundled in /tdd's rules) A place where behaviour can be altered without editing in that place. The location at which a module's interface lives. Choosing where to put the seam is its own design decision, distinct from what goes behind it.

A boundary in Clean Architecture's sense is a particular kind of seam — one that also enforces a dependency direction. Prefer seam when the topic is testability and substitution; boundary when the topic is policy/detail separation.

Depth-as-leverage We measure depth as behaviour per unit of interface a caller has to learn. APoSD also frames depth as a ratio of implementation lines to interface lines; we don't use the ratio because it rewards padding the implementation. Both framings agree on what makes a module shallow.

Leverage What callers get from depth. More capability per unit of interface they have to learn. One implementation pays back across N call sites and M tests. Not a book term — added because the concept is useful enough to name.

Locality What maintainers get from depth. Change, bugs, knowledge, and verification concentrate at one place rather than spreading across callers. Fix once, fixed everywhere. Not a book term — same reason.

Deep vs shallow modules

Deep module = small interface + lots of implementation

┌─────────────────────┐
│   Small Interface   │  ← Few methods, simple params
├─────────────────────┤
│                     │
│                     │
│  Deep Implementation│  ← Complex logic hidden
│                     │
│                     │
└─────────────────────┘

Shallow module = large interface + little implementation (avoid)

┌─────────────────────────────────┐
│       Large Interface           │  ← Many methods, complex params
├─────────────────────────────────┤
│  Thin Implementation            │  ← Just passes through
└─────────────────────────────────┘

When designing interfaces, ask:

  • Can I reduce the number of methods?
  • Can I simplify the parameters?
  • Can I hide more complexity inside?

Principles

  • Depth is a property of the interface, not the implementation. A deep module can be internally composed of small, mockable, swappable parts — they just aren't part of the interface. A module can have internal seams (private to its implementation, used by its own tests) as well as the external seam at its interface.
  • The deletion test. Imagine deleting the module. If complexity vanishes, the module wasn't hiding anything (it was a pass-through). If complexity reappears across N callers, the module was earning its keep.
  • The interface is the test surface. Callers and tests cross the same seam. If you want to test past the interface, the module is probably the wrong shape.
  • One adapter = hypothetical seam. Two adapters = real one. Don't introduce a seam unless something actually varies across it.
  • Information hiding (APoSD) and the dependency rule (Clean Architecture) are the two pressures to apply. The bundled rule sets in the consuming skills (/improve-codebase-architecture, /tdd) are the canonical source for both.

Relationships

  • A module has exactly one interface (the surface it presents to callers and tests).
  • Depth is a property of a module, measured against its interface.
  • A seam is where a module's interface lives.
  • A boundary is a seam that also enforces a dependency direction (Clean Architecture's term).
  • An adapter sits at a seam and satisfies the interface.
  • A port is an interface owned by an inner layer.
  • Depth produces leverage for callers and locality for maintainers.

Designing interfaces for testability

Good interfaces make testing natural:

  1. Accept dependencies, don't create them

    // Testable
    function processOrder(order, paymentGateway) {}
    
    // Hard to test
    function processOrder(order) {
      const gateway = new StripeGateway();
    }
  2. Return results, don't produce side effects

    // Testable
    function calculateDiscount(cart): Discount {}
    
    // Hard to test
    function applyDiscount(cart): void {
      cart.total -= discount;
    }
  3. Small surface area
    • Fewer methods = fewer tests needed
    • Fewer params = simpler test setup

Designing it twice — exploring alternative interfaces

When the user wants to explore alternative interfaces for a chosen module (e.g. a deepening candidate from /improve-codebase-architecture), use this parallel sub-agent pattern. Based on "Design It Twice" (Ousterhout) — your first idea is unlikely to be the best.

Uses the vocabulary above — module, interface, seam, adapter, leverage.

1. Frame the problem space

Before spawning sub-agents, write a user-facing explanation of the problem space for the chosen candidate:

  • The constraints any new interface would need to satisfy
  • The dependencies it would rely on, and which category they fall into (see DEEPENING.md)
  • A rough illustrative code sketch to ground the constraints — not a proposal, just a way to make the constraints concrete

Show this to the user, then immediately proceed to Step 2. The user reads and thinks while the sub-agents work in parallel.

2. Spawn sub-agents

Spawn 3+ sub-agents in parallel using the Agent tool. Each must produce a radically different interface for the module.

Prompt each sub-agent with a separate technical brief (file paths, coupling details, dependency category from DEEPENING.md, what sits behind the seam). The brief is independent of the user-facing problem-space explanation in Step 1. Give each agent a different design constraint:

  • Agent 1: "Minimize the interface — aim for 1–3 entry points max. Maximise leverage per entry point."
  • Agent 2: "Maximise flexibility — support many use cases and extension."
  • Agent 3: "Optimise for the most common caller — make the default case trivial."
  • Agent 4 (if applicable): "Design around ports & adapters for cross-seam dependencies."

Include both this vocabulary and CONTEXT.md vocabulary in the brief so each sub-agent names things consistently with the architecture language and the project's domain language.

Each sub-agent outputs:

  1. Interface (types, methods, params — plus invariants, ordering, error modes)
  2. Usage example showing how callers use it
  3. What the implementation hides behind the seam
  4. Dependency strategy and adapters (see DEEPENING.md)
  5. Trade-offs — where leverage is high, where it's thin

3. Present and compare

Present designs sequentially so the user can absorb each one, then compare them in prose. Contrast by depth (leverage at the interface), locality (where change concentrates), and seam placement.

After comparing, give your own recommendation: which design you think is strongest and why. If elements from different designs would combine well, propose a hybrid. Be opinionated — the user wants a strong read, not a menu.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.