Codebase Design logo

Codebase Design

Community
citypaul
codebase-design

Design and evaluate deep modules: cohesive responsibility behind a small, stable caller-facing contract, with information hiding, justified seams, explicit effects, dependency strategy, and behavior-focused tests. Use when designing or changing an in-process module or package contract, consolidating shallow pass-through modules, deciding what to hide, comparing alternative interfaces, or asking whether code should be combined or split for leverage and locality. For physical layout use structure-codebase; for public compatibility use api-design; for a repository-wide scan use improve-codebase-architecture. For an already-selected whole-path requirement to support a calibrated net-mechanism-reduction claim, use reduce-system-complexity.

Overview

Publishercitypaul
Repository.dotfiles
Skill namecodebase-design
Stars
740
Forks
96
Bundled files
4
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 4 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by citypaul on GitHub. Read the source before you install it.

Installation

Install the Codebase Design AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/citypaul/.dotfiles/tree/main/claude/.claude/skills/codebase-design
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/citypaul/.dotfiles.git /tmp/.dotfiles
mkdir -p .claude/skills
cp -r /tmp/.dotfiles/claude/.claude/skills/codebase-design .claude/skills/codebase-design
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Codebase Design in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Codebase Design on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Codebase Design is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Codebase Design

Design coherent deep modules: substantial, related behavior and design decisions hidden behind a small, stable caller-facing contract. Optimize for leverage for callers and locality for maintainers without creating a god module.

Use this skill for logical responsibility and contract shape. Use structure-codebase for physical paths, packages, exports, dependency direction, enforcement, and folder migration. Use reduce-system-complexity when the selected objective is an evidence-backed net-reduction claim over whole-path mechanism rather than a deeper contract. Use evaluate-existing-solutions for a consequential unresolved library, tool, application, service, framework, or platform choice.

When improve-codebase-architecture loads this skill during an unselected audit, use only its vocabulary, principles, evidence tests, and thin-edge safeguards. Do not run the contract-design workflow or propose an exact interface until the user selects a candidate.

Read the relevant reference before proposing a consequential design:

Vocabulary

TermMeaning
ModuleA cohesive unit with an implementation and one or more role-shaped caller contracts: a function, object, package, or capability. Scale alone does not make it a module.
Interface / public contractEverything a caller must know to use the module correctly: operations, types, invariants, errors, ordering, configuration, lifecycle, effects, and relevant performance characteristics. This is broader than a TypeScript interface or a type signature.
ImplementationThe decisions and behavior hidden behind the caller-facing contract. Private functions may be small and numerous without becoming public modules.
DepthHow much coherent capability and decision-making a caller gains for the contract burden it must learn. Do not measure depth by lines of code.
LeverageThe caller benefit of depth: one learned contract applies useful behavior consistently across many scenarios.
LocalityThe maintainer benefit of depth: related knowledge, changes, bugs, and verification concentrate in one owner.
SeamPer Michael Feathers, a place where behavior can be changed without editing at that place; every seam has an enabling point. Not every module contract is a seam.
AdapterA concrete translator or implementation selected at a seam. In hexagonal architecture, retain that skill's driving, driven, and test-interactor distinctions.

Use these terms to disambiguate, not to erase useful established vocabulary. API, component, service, signature, boundary, port, and bounded context remain valid when they name those specific concepts.

Design Principles

Hide decisions, not merely code

Place a responsibility behind a module when callers should not each know its policy, sequencing, representation, error recovery, or provider mechanics. A private helper extraction does not deepen a module if the same knowledge still leaks through its parameters and call order.

Keep depth cohesive

A tiny contract over an incoherent implementation is a god module, not a good deep module. Combine behavior only when it shares meaning, invariants, ownership, lifecycle, or a real axis of change. Preserve separate modules when they evolve, fail, deploy, or authorize independently. An extraction earns its boundary when the reader can name the decision or responsibility it owns and understand the caller with less cross-file reconstruction; a file per helper or a chain of trivial forwarding functions does not establish ownership.

Apply the behavior-preserving inlining test

Imagine inlining the module into every caller while preserving behavior:

  • If policy, sequencing, error handling, or representation knowledge spreads across callers, the module earns its place.
  • If callers become simpler because a pass-through disappears and no knowledge is duplicated, the module is shallow or misplaced.

This is the useful form of the deletion test. Do not imagine deleting the behavior itself.

Pull complexity downward deliberately

Make the common call simple. Accept complexity inside the implementation when doing so removes configuration, ordering, special cases, or provider knowledge from callers. Keep effects, failure modes, resource ownership, and performance costs explicit enough that callers can use the module safely.

Justify seams with evidence

Create a seam for a concrete need: substitution, independent testing, volatility isolation, ownership, trust, runtime failure, or deployment. Adapter count is evidence, not a rule. A production adapter plus a faithful test interactor may justify a seam; two accidental wrappers do not.

Test at the stable contract

Make caller-observable behavior the primary test surface. Do not export private helpers or expose internal seams solely to test them. A private subsystem may have focused tests when it is itself a coherent module or when an algorithm needs precise failure localization; those tests must not freeze incidental orchestration.

Preserve intentionally thin edges

Do not diagnose a route leaf, CLI command, adapter, generated client, or composition root as shallow merely because it is thin. Translation and wiring should often be thin. Judge whether policy is hidden in the correct inside module and whether the edge leaks provider or transport knowledge across its contract.

Workflow

1. Define the job and callers

State the behavior the module owns, its current and expected callers, the common case, and what must remain outside. Read project instructions, architecture decisions, glossary conventions, and relevant tests before naming anything new.

2. Inventory the full contract burden

List what each caller must know today:

  • operations and data shapes;
  • invariants and preconditions;
  • call ordering and lifecycle;
  • configuration and dependency construction;
  • errors, retries, partial failure, and effects;
  • latency, throughput, consistency, and transaction expectations.

Do not confuse a short type signature with a small interface.

3. Map hidden and leaked knowledge

Trace callers and collaborators. Identify duplicated decisions, pass-through chains, provider types, repeated orchestration, co-changing files, and tests that must reconstruct internals. Record counterevidence: independent ownership, different failure domains, or callers that genuinely need separate policy.

4. Choose responsibility before the seam

Write one sentence defining the module's coherent responsibility. Decide what knowledge belongs behind it. Only then place seams and select dependency strategies. Read references/deepening.md for existing clusters.

When a material generic dependency or subsystem is not already prescribed, feed this responsibility, caller scenarios, effects, and constraints into evaluate-existing-solutions before finalizing a dependency-shaped contract. Keep the chosen provider or library behind local application language when doing so preserves a useful change boundary; do not wrap every stable primitive by reflex or copy a vendor API into the module contract.

5. Design the contract from use scenarios

Design from representative caller examples, including invalid input, partial failure, cancellation, retries, and lifecycle where relevant. Specify types, invariants, ordering, errors, effects, and performance expectations—not methods alone.

For consequential choices, read references/design-it-twice.md and compare genuinely different designs before recommending one.

6. Test the depth claim

Ask:

  • Does the common caller learn less and coordinate less?
  • Did implementation knowledge move behind the contract, or merely change names?
  • Would a policy change concentrate here rather than fan out?
  • Are effects and failures still honest?
  • Can behavior be tested through the contract with faithful dependencies?
  • Did the design avoid speculative flexibility and a generic command-shaped god interface?

7. Route delivery to the owning skills

  • Use api-design for public HTTP and contracts published or versioned across an ownership boundary. Ordinary in-process component props remain with this skill and the applicable framework/design-system guidance.
  • Use structure-codebase for file/package placement and mechanical dependency enforcement.
  • Use render-code-shape first when the current composition is not yet visible: it returns cited boundaries, signatures, and a call graph, which is the evidence this skill's judgements need.
  • Use reduce-system-complexity when the accepted outcome must remove total branches, states, dependencies, layers, or operational moving parts rather than only improve caller leverage.
  • Use evaluate-existing-solutions when a material generic implementation choice remains unresolved after the responsibility and constraints are known.
  • Use hexagonal-architecture only for an opted-in ports-and-adapters system with purposeful actor conversations.
  • Use finding-seams when existing hard-coded dependencies block a test harness.
  • Use characterisation-tests before restructuring untested behavior.
  • Use tdd, testing, and refactoring during implementation according to whether behavior changes and whether the safety net is trustworthy. At PR readiness, follow the repository's mutation policy; where mutation is not meaningful, record proportionate alternate evidence.
  • Use ubiquitous-language when a domain term must be proposed or changed; never coin it silently.

Design Output

Produce:

  1. The module's one-sentence responsibility and explicit exclusions.
  2. Callers and representative usage scenarios.
  3. The complete proposed contract, including non-type obligations.
  4. Knowledge and behavior hidden behind it.
  5. Dependencies, seams, adapters or test interactors, and their fidelity strategy.
  6. Alternatives considered and why the recommendation wins.
  7. Compatibility and incremental migration constraints.
  8. Behavior tests that should survive implementation changes.
  9. Assumptions, risks, and evidence still needed.

Completion Check

  • Is the contract simpler than the coherent behavior it provides?
  • Does it hide decisions rather than expose orchestration knobs?
  • Is the common case obvious without making uncommon cases impossible?
  • Are cohesion, ownership, failure, and runtime boundaries still honest?
  • Are seams justified by real variation or isolation needs?
  • Can callers and behavior tests use the same stable contract?
  • Are thin edges still thin and policy-free?
  • Does every compatibility or migration claim have a verification path?

Attribution

Adapted from Matt Pocock's MIT-licensed codebase-design skill and linked resources, with deep-module and Design It Twice concepts credited to John Ousterhout and seam terminology credited to Michael Feathers. See references/source-notes.md and LICENSE for pinned provenance and license terms.

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Codebase Design AI skill do?

Design and evaluate deep modules: cohesive responsibility behind a small, stable caller-facing contract, with information hiding, justified seams, explicit effects, dependency strategy, and behavior-focused tests. Use when designing or changing an in-process module or package contract, consolidating shallow pass-through modules, deciding what to hide, comparing alternative interfaces, or asking whether code should be combined or split for leverage and locality. For physical layout use structure-codebase; for public compatibility use api-design; for a repository-wide scan use improve-codebas...

Why use Codebase Design on TypingMind?

Because you install it once and use it with any model. Codebase Design is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Codebase Design in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/citypaul/.dotfiles/tree/main/claude/.claude/skills/codebase-design. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Codebase Design?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Codebase Design?

As many as you like. As long as a model supports skills, you can use Codebase Design with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Codebase Design AI skill free?

It is published on GitHub by citypaul. Check the repository for licensing terms. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇