layering
Decide where code goes and which way its dependencies point — inward-pointing source dependencies, what the domain, application, adapter and infrastructure…
Skill by kasofsk
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/kasofsk-layering
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: devops
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/layering
What's inside
- Skill name
layering- Description
- Decide where code goes and which way its dependencies point — inward-pointing source dependencies, what the domain, application, adapter and infrastructure layers each own, what may cross a boundary, and ports and adapters. Use when structuring a codebase or module, adding a layer or port, deciding which layer a piece of logic belongs in, reviewing a change that crosses a boundary, or diagnosing over- and under-layering.
- License
- MIT
- Instructions
- 75 lines in SKILL.md · view on GitHub
Files (1)
- SKILL.md
SKILL.md (first lines)
# Layering Where code goes, and which way its dependencies point. ## The rule: dependencies point inward Source dependencies point only inward. Nothing in an inner layer knows anything at all about an outer one. Four things follow. **Control flow may point outward; the dependency may not.** The core reaches the world constantly, through an interface the core declares and something outside implements. That inversion is the entire mechanism. **A type is a dependency, and so is a name.** A core function whose parameter is a vendor's handle is coupled to that vendor without importing it, and a field named after their concept has taken their vocabulary. **The rule is about the graph, not the file.** Enforce reachability over the module graph rather than per-file imports: every per-file check passes on a small path-joining utility that touches the filesystem and is called by the core. **Inward is a direction, not a folder count.** Two layers with an enforced boundary beat five with nominal ones; a boundary nothing checks forbids nothing. ## The layers | Layer | Owns | |---|---| | **Domain** | business concepts, rules and decisions, and the state that reflects them — with the technical details of storing it delegated outward | | **Application** | the jobs the software does: gather, call into the domain, commit, dispatch. Thin, and holding no business rules | | **Adapters** | translation in both directions, one per external system, and no rules of its own | | **Infrastructure** | the world itself — databases, queues, clocks, other people's services | **The application layer decides nothing.** A conditional there that inspects domain state is a decision in the wrong place: invisible to whatever tests the domain, and duplicated the day a second caller appears. **Adapters hold no rules.** Protocol, encoding, transport-level retry, translation — nothing a domain expert would recognise as a decision. **A layer is logical; a tier is physical.** Whether two layers share a process, a host or neither is a deployment question, and it moves no boundary here. ## Strict, not relaxed Each layer depends only on the one below it. Three forms the violation actually takes: - the domain imports no adapter, no framework, no I/O library, and no ambient capability — clock, randomness, environment, network; - an adapter never imports another adapter: two adapters that need each other are either one adapter or a coordination belonging above both; - nothing reaches the world except through the layer that owns that boundary. Relaxed layering — anything may call anything below it — is not a weaker rule but the absence of one: the import graph becomes the only statement of the structure, and nobody reads it. ## What crosses a boundary **Plain data.** A live object carries behaviour, identity and lazily-reachable state across a seam the reader cannot audit. **Parsed, not validated.** Get data into its most precise representation at the boundary, before any of it is acted upon. A re-check deep inside is both a duplicate and an admission that the type does not say what the code believes. **One mapping site per boundary.** Mapping scattered across call sites drifts one call site at a time, so the bug appears in the path nobody changed. **Never a foreign model.** Where an external system's shape would reach inward, the boundary translates it. An imported schema is an imported design, and it is one you do not control. **A refusal is not an error.** A refusal to serve *this work now* is an input to a decision; a missing precondition for serving a *kind* of work at all is a failure at start-up. ## Ports and adapters A port is an interface named for a contract the core needs. An adapter implements it for one concrete external system. - **The inner layer declares the port; the outer implements it.** A port declared beside its only implementation is a header file: the dependency still points outward and only the file count changed. - **Name the port for its contract**, not for the vendor, protocol or library that arrived first. The name is what stops the second implementation from being a fight. - **A port per contract, not per class.** An interface with one implementation, no test double and no prospect of a second is ceremony. - **Substitution happens at the port**, and that is where testability comes from. If a unit test needs a running broker, the boundary is somewhere other than where the diagram says. ## What layering costs The reason to layer is a reduced scope of attention: each part can be thought about without the others. Testability and substitutability are the bonus, not the justification. It is a small-granularity technique. Once a layer grows too big, the top-level split becomes domain-oriented modules that are internally layered — not more layers. Both failure modes are real. Under-layering puts business rules in request handlers and leaves a core that cannot be tested without infrastructure. Over-layering leaves ports with no second side, records mapped to structurally identical records, and a folder per noun. If adding one field routinely touches four files that differ only in the name of the type, that boundary is not carrying a decision. Collapse it.
From kasofsk/blessed-practices, MIT.
More from kasofsk/blessed-practices
- 0.524score
comments-describe-the-code
kasofsk
Write comments about the code itself, never about the prompt, conversation, or moment that produced it — and treat a long justifying comment as a signal the…
SkillBFreshness: BClaude Code +9 - 0.524score
design-with-known-limits
kasofsk
Design systems with explicit correctness limits, failure modes, and operational assumptions instead of automatically engineering every weakness away.
SkillBFreshness: BClaude Code +9 - 0.524score
diminishing-returns
kasofsk
Pursue the highest-value work first and stop when the expected value of the next improvement no longer justifies its full cost.
SkillBFreshness: BClaude Code +9 - 0.524score
domain-modelling
kasofsk
Shape the contents of the domain core — ubiquitous language, aggregates as consistency boundaries, entities versus value objects, making illegal states…
SkillBFreshness: BClaude Code +9 - 0.524score
fix-the-assumption-not-the-hack
kasofsk
When a new feature invalidates an assumption the current design rests on, rethink the pattern rather than land a tweak that technically satisfies the request.
SkillBFreshness: BClaude Code +9 - 0.524score
idiomatic-by-default
kasofsk
Take the community-standard path for the language, framework, or ecosystem unless there is an articulable reason not to, and don't escalate a decision the…
SkillBFreshness: BClaude Code +9 - 0.524score
illegal-states-unrepresentable
kasofsk
Make illegal states unrepresentable with precise types, discriminated variants, and boundary parsing.
SkillBFreshness: BClaude Code +9 - 0.524score
modular-and-layered-code
kasofsk
Architect so a future agent can act at a single layer — strict tested contracts between layers, testing concentrated at domain boundaries, pure logic kept…
SkillBFreshness: BClaude Code +9 - 0.524score
push-back-and-verify-assumptions
kasofsk
Treat the operator as a fellow engineer — challenge naive or wrong premises, state assumptions explicitly, keep asking until they are right, and stop rather…
SkillBFreshness: BClaude Code +9 - 0.524score
write-the-present-not-the-diff
kasofsk
Write prose that states what is true now, without narrating the correction, the superseded claim, or the path that got there.
SkillBFreshness: BClaude Code +9 - 0.494score
dependencies
kasofsk
Add, remove, upgrade, or pin a dependency with the ecosystem's package manager instead of hand-editing the manifest.
SkillBFreshness: BClaude Code +9
Signals
- Stars
- 0
- Forks
- 1
- Open issues
- 0
- Last commit (this folder)
- Aug 20, 2026 (2 months ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/kasofsk/blessed-practices
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from kasofsk
- 0.524score
comments-describe-the-code
kasofsk
Write comments about the code itself, never about the prompt, conversation, or moment that produced it — and treat a long justifying comment as a signal the…
SkillBFreshness: BClaude Code +9 - 0.524score
design-with-known-limits
kasofsk
Design systems with explicit correctness limits, failure modes, and operational assumptions instead of automatically engineering every weakness away.
SkillBFreshness: BClaude Code +9 - 0.524score
diminishing-returns
kasofsk
Pursue the highest-value work first and stop when the expected value of the next improvement no longer justifies its full cost.
SkillBFreshness: BClaude Code +9 - 0.524score
domain-modelling
kasofsk
Shape the contents of the domain core — ubiquitous language, aggregates as consistency boundaries, entities versus value objects, making illegal states…
SkillBFreshness: BClaude Code +9 - 0.524score
fix-the-assumption-not-the-hack
kasofsk
When a new feature invalidates an assumption the current design rests on, rethink the pattern rather than land a tweak that technically satisfies the request.
SkillBFreshness: BClaude Code +9 - 0.524score
idiomatic-by-default
kasofsk
Take the community-standard path for the language, framework, or ecosystem unless there is an articulable reason not to, and don't escalate a decision the…
SkillBFreshness: BClaude Code +9
Cite this page
layering skill. Agent Mart. https://agentmart.dev/skills/kasofsk-layering (last updated 2026-10-24)