
Design Principles
- 1 installs
- Updated July 8, 2026
- madebymlai/agentstack
Pick structural design rules (module depth, hiding, Demeter) and paste the chosen principles into AGENTS.md before agents implement features.
About
Design Principles is an architecture catalog from AgentStack that helps developers and small teams document structural choices agents should follow before and during implementation. Instead of mechanical checks, it offers named patterns—deep modules, information hiding, tell-don't-ask, Law of Demeter, and related coupling guidance—each with a short “pick when” signal so you apply judgment consistently. The intended output lands in AGENTS.md under Design Principles, giving Claude Code, Cursor, and similar agents stable boundaries while they write or refactor. Use it when wrappers multiply, the same schema leaks across files, or callers interrogate object state instead of issuing commands. It pairs naturally with planning and review phases when you want architectural intent written down once, not rediscovered in every PR.
- Architecture decision catalog for judgment-heavy rules not covered by linters
- Module boundary patterns: deep modules, information hiding, tell-don't-ask
- Coupling guidance including Law of Demeter and when to apply each principle
- Explicit destination: AGENTS.md Design Principles section
- Pick-when cues for classitis, duplicated format knowledge, and feature envy
Design Principles by the numbers
- 1 all-time installs (skills.sh)
- Ranked #14,102 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Jul 9, 2026 (Skillselion catalog sync)
npx skills add https://github.com/madebymlai/agentstack --skill design-principlesAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1 |
|---|---|
| Last updated | July 8, 2026 |
| Repository | madebymlai/agentstack ↗ |
What it does
Pick structural design rules (module depth, hiding, Demeter) and paste the chosen principles into AGENTS.md before agents implement features.
Files
<purpose> A design principles writer. Probe the codebase, propose principles one menu at a time, let the user accept or reject each, then append the accepted set to AGENTS.md. These are pre-implementation design decisions that require judgment — they shape how work is structured before and while it is written. Line-level coding style lives elsewhere (the coding-standards skill / CODING_STANDARDS.md), enforced at diff-review time. </purpose>
<rules>
- All user interaction via direct questions — one catalog section at a time.
- Accumulate accepted items in memory; write the file only at the end.
- Explain what you found in the codebase before each recommendation.
- Recommend, don't gatekeep: surface the full menu, flag the items the code argues for, but let the user pick freely (including items you didn't flag, and skipping ones you did).
- Principles are judgment calls a designer applies — not mechanically checkable lint rules. If a tool can enforce it, it does not belong here.
</rules>
<phase name="locate"> The target is an agent-managed block at the bottom of AGENTS.md at the repo root, bounded by <design-principles> … </design-principles> tags. The tags mark the block as managed by this skill so it can be located and rewritten on later runs without disturbing the rest of AGENTS.md.
- If the `<design-principles>` block exists — read it. Treat its current principles as already-decided: do not re-propose them. The session is then an update — you are adding to (or, if the user asks, revising) the existing set.
- If it is missing — this is a fresh write; you will append a new
<design-principles>…</design-principles>block at the end of AGENTS.md at the end of the session. If AGENTS.md itself does not exist, create it.
Tell the user whether you're creating the block or updating it. </phase>
Catalogs
Read both for the full menu. Each item carries a one-line definition and a > Pick when: signal describing the design smell it addresses.
- catalogs/ARCHITECTURE.md — module boundaries, coupling
- catalogs/DESIGN.md — SOLID, simplicity, domain modeling, robustness
<phase name="present"> Show the user each catalog's items, grouped by section, with the name and its one-line definition. Skip any item already present in the target section (from the locate phase). Keep it scannable — the user is choosing from a menu, not reading an essay. </phase>
<phase name="recommend"> Probe the codebase before recommending. Use the codebase-memory MCP tools first (get_architecture, search_code, search_graph). Flag the catalog items whose > Pick when: signal matches evidence you actually found — and say what evidence. Do not hide the items you didn't flag. </phase>
<phase name="select"> The user picks which principles they want. They may pick items you didn't recommend, or skip ones you did. Confirm the final set before writing. </phase>
<phase name="write"> Write the selected principles into a <design-principles> … </design-principles> block at the bottom of AGENTS.md. Inside the tags, the principles sit directly under the same ## section headers as the catalogs, each as - **Name** — definition in 1–2 sentences.. Do not include the > Pick when: signals or source links — only the principle and its definition.
<design-principles>
## Module Design
- **SRP** — A module should have one, and only one, reason to change.
...
</design-principles>When updating, rewrite the existing block in place — merge new items under their sections without disturbing the tags, the rest of AGENTS.md, or the items already inside. </phase>
<phase name="summary"> Report what was written: the path, whether the <design-principles> block was created or updated, and the list of principles grouped by section. Note that this block guides design decisions at planning time, not the diff-review loop. </phase>
Architecture Catalog
Structural design decisions that require judgment, applied before and while code is written, not mechanically checkable.
→ Destination: AGENTS.md (# Design Principles section)
Module Boundaries
- Deep Modules → Prefer modules with simple interfaces that hide substantial implementation; depth, not a thin pass-through, is what earns a module its interface.
Pick when: classes are mostly thin wrappers, the interface is nearly as wide as the implementation, or many tiny single-method classes ("classitis") fragment the logic.
- Information Hiding → A design decision (file format, schema, protocol, algorithm) lives in exactly one module; the same knowledge must not surface in modules that then have to change together.
Pick when: the same format or assumption is duplicated across modules, or one conceptual change forces edits in several places that each "know" the detail.
- Tell, Don't Ask → Tell an object what to do and let it act on its own state, rather than querying its state and deciding on its behalf.
Pick when: callers inspect an object's fields to decide what to do, logic that belongs inside a type leaks into its consumers, or feature envy appears across boundaries.
Coupling
- Law of Demeter → Talk only to immediate collaborators: call methods on self, parameters, owned fields, or objects you created; never on objects returned by other calls.
Pick when: chains of three or more calls reach through object graphs ("train wrecks"), or a change in a distant class breaks unrelated callers.
Sources
- Deep Modules → John Ousterhout, "A Philosophy of Software Design" (2018)
- Information Hiding → David Parnas (1972); revived as "information leakage" by Ousterhout (2018)
- Tell, Don't Ask → Martin Fowler; origin Andy Hunt & Dave Thomas, "The Pragmatic Programmer"
- Law of Demeter → Karl Lieberherr et al., Demeter Project (1987)
Design Catalog
Pre-implementation design decisions that require judgment, not mechanically checkable.
→ Destination: AGENTS.md (# Design Principles section)
Module Design
- SRP → A module should have one, and only one, reason to change: responsible to one actor.
Pick when: modules mix unrelated concerns, a change in one feature breaks another, or a class serves multiple actors.
- OCP → Software entities should be open for extension but closed for modification.
Pick when: adding features requires editing existing working code, switch statements grow with each new variant, or plugin/strategy patterns would eliminate modification.
- LSP → Objects of a supertype shall be replaceable with objects of a subtype without altering program correctness.
Pick when: subclasses override behavior in ways that surprise callers, downcasts appear in consuming code, or inheritance hierarchies violate parent expectations.
- ISP → No client should be forced to depend on methods it does not use; prefer many client-specific interfaces over one general-purpose interface.
Pick when: interfaces have methods most implementors stub out, consumers depend on large objects but only use a fraction, or mock setup is painful because of unused surface area.
- DIP → High-level modules should not depend on low-level modules. Both should depend on abstractions; abstractions should not depend on details.
Pick when: business logic imports infrastructure directly, swapping a database or API client requires touching core code, or testing requires standing up real dependencies.
- Composition Over Inheritance → Default to composition; use inheritance only when the subtype genuinely satisfies LSP and the hierarchy is closed to further extension.
Pick when: class hierarchies deepen beyond two levels, subclasses override parent behavior in surprising ways, or reuse is achieved by inheriting from a concrete class.
- Command-Query Separation → Every method should either be a command that performs an action or a query that returns data, but never both.
Pick when: methods both mutate state and return values, calling a getter produces side effects, or asking a question changes the answer.
Meta
- KISS → Every system works best when simplicity is a key goal and unnecessary complexity is avoided.
Pick when: abstractions exist without concrete need, code is clever instead of clear, or three simple lines would replace a generic framework.
- YAGNI → Do not introduce abstractions, parameters, or code paths that serve no current caller. If no concrete use case exercises it today, delete it.
Pick when: speculative features sit unused, parameters exist "just in case," or abstractions have a single implementation with no planned second. Note: Forward-First wins for contract surfaces (APIs, schemas, wire formats); YAGNI wins for internal implementation.
- Forward-First → Design for the current and next contract version; never introduce backward-compatibility shims or legacy code paths that increase maintenance surface.
Pick when: deprecated code paths accumulate, backward-compat shims outnumber active code, or migration cost grows with each deferred cleanup. Note: applies to contract surfaces; for internal implementation, defer to YAGNI.
Domain Modeling
- No Primitive Obsession → Represent domain concepts as named types rather than raw strings, numbers, or booleans. A customer ID is not a string; a price is not a float.
Pick when: functions accept raw strings/ints that represent domain concepts, type signatures don't distinguish between an email and a username, or invalid values pass type checks silently.
Robustness
- Define Errors Out of Existence → Design APIs so that routine edge cases are not errors at all (return empty, clamp, no-op) rather than pushing exceptions onto every caller.
Pick when: callers must wrap ordinary calls in try/catch for non-exceptional cases, the same null/empty special-case is repeated everywhere, or an "error" is really just an uninteresting boundary condition.
Sources
- SRP → Robert C. Martin, "Design Principles and Design Patterns" (2000)
- OCP → Bertrand Meyer, "Object-Oriented Software Construction" (1988)
- LSP → Barbara Liskov, "Data Abstraction and Hierarchy" (1987)
- ISP → Robert C. Martin, SOLID principles
- DIP → Robert C. Martin, SOLID principles
- Composition Over Inheritance → Gang of Four, "Design Patterns" (1994)
- Command-Query Separation → Bertrand Meyer, "Object-Oriented Software Construction" (1988)
- KISS → U.S. Navy design principle (1960), attributed to Kelly Johnson
- YAGNI → Ron Jeffries, Extreme Programming (1999)
- Forward-First → general engineering principle
- No Primitive Obsession → Martin Fowler, "Refactoring" (1999)
- Define Errors Out of Existence → John Ousterhout, "A Philosophy of Software Design" (2018)