Skip to main content
skill Claude Code

codebase-design — Claude Code skill: design modules

This skill helps design modules with small interfaces and hidden complexity. Use it when refactoring code, choosing a seam, or making tests easier to write.

Install into Claude Code · Plugin marketplace All methods and platforms ↓
/plugin marketplace add mattpocock/skills
/plugin install mattpocock-skills@mattpocock
Open on GitHub

What codebase-design does

codebase-design gives an agent a shared vocabulary for deep module design. It covers interface, implementation, depth, seam, and adapter, then uses those terms to examine where a seam belongs and which complexity should stay inside a module. The skill applies to new designs and code restructuring.

It prompts the agent to reduce methods and parameter complexity, accept dependencies from callers, and return results instead of producing side effects. It also includes the deletion test, internal seams for module tests, and the rule that two adapters indicate a real seam. Tests should cross the same interface as callers.

Install it when you want consistent architectural language during refactoring or module design. It is unnecessary for a small pass-through change that does not alter the code’s interfaces.

What it helps with

  • design a deep module interface
  • find a seam in an existing codebase
  • hide complex logic behind a small interface
  • make a module easier to test
  • review a module for shallow design

Example prompts for the agent

  • Design an interface for this order-processing module and identify the right seam.
  • Apply the deletion test to this module and tell me what belongs behind its interface.
  • Refactor this code for testability: pass dependencies in and return results.

How to install codebase-design

1Plugin marketplace

/plugin marketplace add mattpocock/skills
/plugin install mattpocock-skills@mattpocock

This installs the whole mattpocock-skills plugin with all its skills

2Skills CLI (Vercel)

npx skills add mattpocock/skills --skill codebase-design -a claude-code

3Manually: put the files in place

~/.claude/skills/codebase-design/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/codebase-design/

From the same set32

The whole set →
grill-me Matt Pocock grill-me interviews you about a plan or design to expose gaps and sharpen decisions. Use it before implementation starts. Claude Code 1,424,476installs grill-with-docs Matt Pocock This skill interviews you about a plan or design and creates ADRs and a glossary along the way. Use it when decisions need sharper definition. Claude Code 1,219,756installs improve-codebase-architecture Matt Pocock This skill scans a codebase for architectural friction, then builds a visual HTML report with refactoring candidates. Use it before a deeper architecture review. Claude Code 1,163,035installs tdd Matt Pocock Guides the red-green TDD loop: ensures tests are written first, keep them at public interfaces, and avoid coupling to implementation details. Claude Code 1,141,062installs setup-matt-pocock-skills Matt Pocock This skill configures a repository for Matt Pocock's engineering skills by setting its issue tracker, triage labels, and domain docs layout. Run it before using the other skills. Claude Code 1,052,851installs handoff Matt Pocock Creates a handoff document from the current conversation so another agent can continue the work. Use it when a task moves to a new session or agent. Claude Code 1,038,491installs triage Matt Pocock This skill moves issues and external PRs through triage states, verification, and agent briefs. It fits maintainers managing an issue queue. Claude Code 990,453installs prototype Matt Pocock Creates throwaway prototypes for checking state logic or exploring UI before committing the decision to the main codebase. Claude Code 986,201installs

Similar

Questions about codebase-design

How do I install codebase-design in Claude Code?

Run npx skills add mattpocock/skills --skill codebase-design -a claude-code. You can also use /plugin marketplace add mattpocock/skills, followed by /plugin install mattpocock-skills@mattpocock.

What does codebase-design do?

It helps the agent design deep modules: a small interface with substantial behaviour behind it. The skill provides terms for discussing seams, adapters, tests, and keeping changes local.

What is the difference between a deep and shallow module?

A deep module has a small interface that hides complex implementation details. A shallow module exposes an interface nearly as complex as its implementation, which makes callers learn more.

Source text

SKILL.md · MIT
---
name: codebase-design
description: Shared vocabulary for designing deep modules. Use when the user wants to design or improve a module's interface, find deepening opportunities, decide where a seam goes, make code more testable or AI-navigable, or when another skill needs the deep-module vocabulary.
---

# Codebase Design

Design **deep modules**: a lot of behaviour behind a small interface, placed at a clean seam, testable through that interface. Use this language and these principles wherever code is being designed or restructured. The aim is leverage for callers, locality for maintainers, and testability for everyone.

## Glossary

Use these terms exactly: don't substitute "component," "service," "API," or "boundary." Consistent language is the whole point.

**Module**: anything with an interface and an implementation. Deliberately scale-agnostic: a function, class, package, or tier-spanning slice. _Avoid_: unit, component, service.

**Interface**: everything a caller must know to use the module correctly: the type signature, but also invariants, ordering constraints, error modes, required configuration, and performance characteristics. _Avoid_: API, signature (too narrow, they refer only to the type-level surface).

**Implementation**: 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 repo) or a large adapter with a small implementation (an in-memory fake). Reach for "adapter" when the seam is the topic; "implementation" otherwise.

**Depth**: leverage at the interface. The amount of behaviour a caller (or test) can exercise per unit of interface they have to learn. A module is **deep** when a large amount of behaviour sits behind a small interface, **shallow** when the interface is nearly as complex as the implementation.

**Seam** _(Michael Feathers)_: a place where you can alter behaviour without editing in that place; the *location* at which a module's interface lives. Where to put the seam is its own design decision, distinct from what goes behind it. _Avoid_: boundary (overloaded with DDD's bounded context).

**Adapter**: a concrete thing that satisfies an interface at a seam. Describes *role* (what slot it fills), not substance (what's inside).

**Leverage**: what callers get from depth. More capability per unit of interface they learn. One implementation pays back across N call sites and M tests.

**Locality**: what maintainers get from depth. Change, bugs, knowledge, and verification concentrate in one place rather than spreading across callers. Fix once, fixed everywhere.

## Deep vs shallow

**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 an interface, 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, it was a pass-through. If complexity reappears across N callers, it 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 means a hypothetical seam. Two adapters means a real one.** Don't introduce a seam unless something actually varies across it.

## Designing for testability

Good interfaces make testing natural:

1. **Accept dependencies, don't create them.**

   ```typescript
   // Testable
   function processOrder(order, paymentGateway) {}

   // Hard to test
   function processOrder(order) {
     const gateway = new StripeGateway();
   }
   ```

2. **Return results, don't produce side effects.**

   ```typescript
   // 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.

## 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.
- An **Adapter** sits at a **Seam** and satisfies the **Interface**.
- **Depth** produces **Leverage** for callers and **Locality** for maintainers.

## Rejected framings

- **Depth as ratio of implementation-lines to interface-lines** (Ousterhout): rewards padding the implementation. We use depth-as-leverage instead.
- **"Interface" as the TypeScript `interface` keyword or a class's public methods**: too narrow: interface here includes every fact a caller must know.
- **"Boundary"**: overloaded with DDD's bounded context. Say **seam** or **interface**.

## Going deeper

- **Deepening a cluster given its dependencies**, see [DEEPENING.md](DEEPENING.md): dependency categories, seam discipline, and replace-don't-layer testing.
- **Exploring alternative interfaces**, see [DESIGN-IT-TWICE.md](DESIGN-IT-TWICE.md): spin up parallel sub-agents to design the interface several radically different ways, then compare on depth, locality, and seam placement.

© Matt Pocock · MIT · mattpocock/skills

See also

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor