Skill Vault · Plan and decide
Agree on what your project terms mean
Clarify confusing language and record definitions and lasting decisions.
A project where your agent can read code and write documentation.
Skill name /domain-modeling
Your next step
Try it for yourself
You’ll need: A project where your agent can read code and write documentation.
Paste into your coding agent with the relevant project open.
This is a one-off starter for the approach. Installing the full Skill adds its complete instructions.
Challenge the overloaded or fuzzy terms in this project. Stress-test each term with edge cases, update the glossary only when a definition is settled, and record hard-to-reverse decisions separately.
What happens nextSettled definitions enter the glossary; lasting tradeoffs are recorded separately.
Use it again
Add the full Skill.
The starter lets you try the approach. Installation adds the complete instructions to your AI coding tool.
Copy the setup instructionsFor Codex or Claude Code on your computer
Your next step
Ask your agent to help you install it
You’ll need: Node.js with npx, Git, and the agent you choose. A project folder where you want the Skill available.
Paste this into Codex or Claude Code with your project open. Your agent will help you review and install the package.
Review files and permissions before accepting an install. Adding a Skill does not run it.
Help me install /domain-modeling from MattEspo23/skills v0.1.2 in this project.
Review the package instructions and supporting files first. Include these Skills: domain-modeling.
Use the command for the agent I am using:
Add to Codex:
npx skills@latest add 'MattEspo23/skills#v0.1.2' --skill domain-modeling --agent codex --copy
Add to Claude Code:
npx skills@latest add 'MattEspo23/skills#v0.1.2' --skill domain-modeling --agent claude-code --copy
Show me where the files will go before making changes. Preserve existing Skills and customizations. Stop if the release, supporting Skills, or target agent cannot be verified. Do not run the Skill or change external services during setup.
After installation, explain how I can use /domain-modeling and what access it needs.
What happens nextYour agent should review and add /domain-modeling, then explain how to use /domain-modeling. Stop if a dependency or version cannot be verified.
No additional supporting Skill is required by this package. Source version: v0.1.2.
Prefer a terminal command?
Add to Codex
npx skills@latest add 'MattEspo23/skills#v0.1.2' --skill domain-modeling --agent codex --copy
Add to Claude Code
npx skills@latest add 'MattEspo23/skills#v0.1.2' --skill domain-modeling --agent claude-code --copy
Installing copies the instructions into your chosen agent. It does not run the Skill or configure project tools.
Keep the package’s supporting files, LICENSE and NOTICE together with the Skill instructions.
Full notes & source materialThe complete original text, examples and reference details.
These are the complete original notes. Planned videos and services mentioned here may not be available yet; the actions above reflect what you can use on this site now.
Sharpen a project’s vocabulary and record domain terms and durable decisions when they become settled.
Watch

Skill Vault video planned · Video planned
Install
Public release v0.1.2 — install the latest source or pin the tested release.
Install latest
npx skills@latest add MattEspo23/skills --skill domain-modeling
Reproducible install
npx skills@latest add 'MattEspo23/skills#v0.1.2' --skill domain-modeling
Clean installs are verified for Codex and Claude Code. The installer copies editable files into the selected agent; review every Skill before giving it tool access.
This is the public, editable adapted baseline. Its deeper Espo-specific revision and Skill Vault video are planned; the released source can be installed now.
What it does
domain-modeling builds and sharpens a project's ubiquitous language while you are designing — challenging a term that conflicts with the glossary, forcing a precise word where you used a vague one, and stress-testing a relationship with a concrete scenario until the boundaries are exact.
It is the active discipline, not the passive one. Reading CONTEXT.md to borrow its vocabulary is a one-line habit any skill can do; this skill is for when you are changing the model. That is what makes it interrupt. It writes a resolved term into CONTEXT.md at the moment it is resolved, in the middle of the conversation, rather than producing a tidy glossary at the end — because the batched version is a summary of a session, and the inline version is the session's actual output.
When to reach for it
Type /domain-modeling, or the agent reaches for it automatically when a task fits. In practice, automatic invocation is the weakest part of the skill: when grill-with-docs or wayfinder say to load it, models frequently load grilling and skip this one. If a grilling session runs and CONTEXT.md is untouched at the end, that is what happened — invoke it by name alongside the other skill.
Reach for it when the words are the problem:
| The situation | The move |
|---|---|
| Two people mean different things by "cancellation" | domain-modeling — pick the canonical term, list the other under _Avoid_ |
| "Account" is doing three jobs in three files | domain-modeling — split it into Customer and User |
| You just made a hard-to-reverse architectural choice | domain-modeling — it offers an ADR, if the choice clears the bar |
| The module's shape is the problem — where the seam goes, how deep the interface is | codebase-design |
| You want the whole plan interrogated before you build | grill-with-docs, which drives this skill underneath |
| You want a term looked up, not changed | Nothing. Read CONTEXT.md. It is a file. |
Prerequisites
None up front. The skill writes into two places and creates both lazily:
CONTEXT.mdat the repo root, created by the first resolved term. In a repo with aCONTEXT-MAP.mdat the root, terms go into the per-contextCONTEXT.mdthe map points at instead.docs/adr/, created by the first ADR that clears the bar.
Nothing needs to exist before you start, and nothing is created speculatively.
Two artifacts, two bars
The glossary and the ADR are held to different standards, and conflating them is where most of the trouble in this skill comes from.
CONTEXT.md | docs/adr/NNNN-slug.md | |
|---|---|---|
| Holds | Terms. What a thing is, in one or two sentences, with rejected synonyms under _Avoid_ | One decision, in one to three sentences: context, choice, reason |
| Bar to write | A vague term became canonical | All three: hard to reverse, surprising without context, the result of a real trade-off |
| Written | Inline, the moment the term is settled | Offered, not assumed |
| Never holds | Implementation details, a spec, a scratch pad, general programming concepts | A diary of every choice made this session |
Miss any one of the ADR's three tests and there is no ADR. An easily-reversed decision will just get reversed; an unsurprising one is nobody's question; one with no real alternative records that you did the obvious thing.
The CONTEXT.md rule is the one to actually hold onto, because it is the one that breaks in the field. It is a glossary and nothing else. Left unchecked, models treat "write to CONTEXT.md" as permission to persist every answer you give, and the file turns into a running spec — this is the most-reported problem with the skill, across several models.
Cross-referencing, and where it stops
The move that makes the skill click: when you state how something works, it checks the code and surfaces the contradiction. "Your code cancels entire Orders, but you just said partial cancellation is possible — which is right?" The language and the code are made to agree, out loud, before either is changed.
The limit is worth knowing. It cross-references code and the committed CONTEXT.md/ADRs, and nothing else. It does not search your issue tracker, so a naming collision that was argued out and deliberately settled in a closed issue months ago gets surfaced as if it were new. There is an open request to fix this; until then, the workaround is to put the instruction in your own docs/agents/domain.md, which the skills already read.
Common questions
My CONTEXT.md is 500 lines. 1,000. 3,000. What do I do?
The size is a symptom, not the disease — the file has absorbed implementation detail and decisions that were never glossary material. The fix is a direct instruction: /grill-with-docs make my CONTEXT.md more concise and remove any implementation details from it. Run it against a bloated file and most of it goes. Only reach for a CONTEXT-MAP.md split once the file is genuinely lean and still covers two domains that a reader would not want to hold at once; splitting a bloated file just gives you several bloated files. The skill's guidance here is not yet strong enough to prevent the growth in the first place, and the issue tracking that is still open.
Why is it CONTEXT.md and not GLOSSARY.md?
This is the most-argued naming question in the whole skill set and it has no settled answer. The case against the current name is good: if it is "a glossary and nothing else", GLOSSARY.md says so, and — as one reader put it — "with ai agents everything is context". The case for it is the map: CONTEXT-MAP.md pointing at several CONTEXT.md files reads naturally in a way GLOSSARY-MAP.md does not, and context is the standing DDD word for a bounded area of the model. At least one person maintains a local fork purely to rename the file. You can do the same, but every other skill in the set looks for CONTEXT.md, so a rename means patching all of them.
Where did /ubiquitous-language go?
It was removed, and it was not deprecated. Its job moved into domain-modeling, which maintains the whole model continuously rather than dumping a glossary out of one conversation. Vocabulary enforcement got more load-bearing, not less — it now runs underneath grilling, triage and mapping rather than as a separate pass you remember to do.
How do I get a glossary for a codebase that has none?
Ask for it explicitly rather than waiting for it to accumulate. /grill-with-docs help me scaffold my existing repo with a CONTEXT.md is the documented route; expect a long interrogation — one user reported 50+ questions before the file was in shape. Incidental use builds the glossary far too slowly on a brownfield repo.
Can I keep the domain model and use my own ADR format? Not cleanly today. The glossary half and the ADR half ship in one skill, so a team with an established ADR convention — different template, different location, different naming — gets instructions that conflict with its house style. The current options are to copy the skill locally and edit it, or to override the ADR conventions in your repo's own agent docs. Splitting the two apart is an open request.
Does a glossary actually earn its keep? It is one more artifact to review, and it can go stale. Sometimes it does not, and it is worth being honest about where. DDD gets less useful the closer it gets to the implementation — the payoff is upstream, in naming and concept alignment, not in aggregates and layer ceremony. Synonym control matters at naming boundaries: module names, table names, status enums, issue titles, CLI commands. It matters much less in ordinary prose. There is also a live objection that domain terms compress communication between humans who already share them, and that an agent responds the same way to the plain-English description — on that reading, the glossary's value is keeping you and your reviewers aligned with what the agent is doing, not making the agent better. On a one-day build, skip it. And an unreviewed, agent-authored glossary is worse than none: it becomes confident-sounding lore that later sessions treat as truth.
Can it turn my vague prompts into domain language for me? No, and there is no plan for a skill that does. A domain language you do not understand yourself becomes meaningless drivel once written down. This skill enforces precision once you have the understanding — it does not manufacture vocabulary you do not have. The related trap is using domain words without doing the modelling: right nouns over the wrong conceptual structure produce output that reads correct and is not.
It's working if
- It stops you mid-sentence to ask which of two things you meant, instead of picking one and moving on.
CONTEXT.mdchanges during the conversation, not in a burst at the end.- It refuses to write an ADR for something you could undo tomorrow — and says which of the three tests failed.
- New entries define what a thing is in one or two sentences and name the words you are giving up under
_Avoid_. - It quotes your code back at you when your code and your sentence disagree.
CONTEXT.mdgets shorter as often as it gets longer.
Where it fits
domain-modeling is a model-invoked reference that runs underneath other skills more often than it runs on its own. grill-with-docs drives it through a grilling session, wayfinder loads it while charting a map, triage uses it to keep tickets in the project's own words, and improve-codebase-architecture calls it as decisions crystallise. Its closest sibling is codebase-design: the two are the vocabulary layer under everything else, this one for the domain, that one for the module's shape. It is also reachable directly, when you want the discipline without committing to the steps of whatever skill would normally pull it in. When you are unsure which skill fits, ask-espo routes you.
Try it once
Use the core behavior in one conversation before installation. The repeatable Skill package is the primary path when you want the behavior available across future work.
Challenge the overloaded or fuzzy terms in this project. Stress-test each term with edge cases, update the glossary only when a definition is settled, and record hard-to-reverse decisions separately.
Source & license
Released in EspoAI Skills v0.1.2; adapted from mattpocock/skills v1.2.3. The released package is skills/engineering/domain-modeling/SKILL.md.
The public package is MIT-licensed and pinned here to the exact release commit. View the released EspoAI source
The adapted baseline preserves the upstream copyright, MIT permission notice, and pinned provenance. View the original pinned source
Skill package files
The full Skill text as copied from content/skill-vault/skills/domain-modeling/. Supporting agent configuration files stay in that folder.
SKILL.md
---
name: domain-modeling
description: Build and sharpen a project's domain model. Use when the user wants to pin down domain terminology or a ubiquitous language, record an architectural decision, or when another skill needs to maintain the domain model.
---
# Domain Modeling
Actively build and sharpen the project's domain model as you design. This is the *active* discipline — challenging terms, inventing edge-case scenarios, and writing the glossary and decisions down the moment they crystallise. (Merely *reading* `CONTEXT.md` for vocabulary is not this skill — that's a one-line habit any skill can do. This skill is for when you're changing the model, not just consuming it.)
## File structure
Most repos have a single context:
```
/
├── CONTEXT.md
├── docs/
│ └── adr/
│ ├── 0001-event-sourced-orders.md
│ └── 0002-postgres-for-write-model.md
└── src/
```
If a `CONTEXT-MAP.md` exists at the root, the repo has multiple contexts. The map points to where each one lives:
```
/
├── CONTEXT-MAP.md
├── docs/
│ └── adr/ ← system-wide decisions
├── src/
│ ├── ordering/
│ │ ├── CONTEXT.md
│ │ └── docs/adr/ ← context-specific decisions
│ └── billing/
│ ├── CONTEXT.md
│ └── docs/adr/
```
Create files lazily — only when you have something to write. If no `CONTEXT.md` exists, create one when the first term is resolved. If no `docs/adr/` exists, create it when the first ADR is needed.
## During the session
### Challenge against the glossary
When the user uses a term that conflicts with the existing language in `CONTEXT.md`, call it out immediately. "Your glossary defines 'cancellation' as X, but you seem to mean Y — which is it?"
### Sharpen fuzzy language
When the user uses vague or overloaded terms, propose a precise canonical term. "You're saying 'account' — do you mean the Customer or the User? Those are different things."
### Discuss concrete scenarios
When domain relationships are being discussed, stress-test them with specific scenarios. Invent scenarios that probe edge cases and force the user to be precise about the boundaries between concepts.
### Cross-reference with code
When the user states how something works, check whether the code agrees. If you find a contradiction, surface it: "Your code cancels entire Orders, but you just said partial cancellation is possible — which is right?"
### Update CONTEXT.md inline
When a term is resolved, update `CONTEXT.md` right there. Don't batch these up — capture them as they happen. Use the format in [CONTEXT-FORMAT.md](./CONTEXT-FORMAT.md).
`CONTEXT.md` should be totally devoid of implementation details. Do not treat `CONTEXT.md` as a spec, a scratch pad, or a repository for implementation decisions. It is a glossary and nothing else.
### Offer ADRs sparingly
Only offer to create an ADR when all three are true:
1. **Hard to reverse** — the cost of changing your mind later is meaningful
2. **Surprising without context** — a future reader will wonder "why did they do it this way?"
3. **The result of a real trade-off** — there were genuine alternatives and you picked one for specific reasons
If any of the three is missing, skip the ADR. Use the format in [ADR-FORMAT.md](./ADR-FORMAT.md).
ADR-FORMAT.md
# ADR Format
ADRs live in `docs/adr/` and use sequential numbering: `0001-slug.md`, `0002-slug.md`, etc.
Create the `docs/adr/` directory lazily — only when the first ADR is needed.
## Template
```md
# {Short title of the decision}
{1-3 sentences: what's the context, what did we decide, and why.}
```
That's it. An ADR can be a single paragraph. The value is in recording *that* a decision was made and *why* — not in filling out sections.
## Optional sections
Only include these when they add genuine value. Most ADRs won't need them.
- **Status** frontmatter (`proposed | accepted | deprecated | superseded by ADR-NNNN`) — useful when decisions are revisited
- **Considered Options** — only when the rejected alternatives are worth remembering
- **Consequences** — only when non-obvious downstream effects need to be called out
## Numbering
Scan `docs/adr/` for the highest existing number and increment by one.
## When to offer an ADR
All three of these must be true:
1. **Hard to reverse** — the cost of changing your mind later is meaningful
2. **Surprising without context** — a future reader will look at the code and wonder "why on earth did they do it this way?"
3. **The result of a real trade-off** — there were genuine alternatives and you picked one for specific reasons
If a decision is easy to reverse, skip it — you'll just reverse it. If it's not surprising, nobody will wonder why. If there was no real alternative, there's nothing to record beyond "we did the obvious thing."
### What qualifies
- **Architectural shape.** "We're using a monorepo." "The write model is event-sourced, the read model is projected into Postgres."
- **Integration patterns between contexts.** "Ordering and Billing communicate via domain events, not synchronous HTTP."
- **Technology choices that carry lock-in.** Database, message bus, auth provider, deployment target. Not every library — just the ones that would take a quarter to swap out.
- **Boundary and scope decisions.** "Customer data is owned by the Customer context; other contexts reference it by ID only." The explicit no-s are as valuable as the yes-s.
- **Deliberate deviations from the obvious path.** "We're using manual SQL instead of an ORM because X." Anything where a reasonable reader would assume the opposite. These stop the next engineer from "fixing" something that was deliberate.
- **Constraints not visible in the code.** "We can't use AWS because of compliance requirements." "Response times must be under 200ms because of the partner API contract."
- **Rejected alternatives when the rejection is non-obvious.** If you considered GraphQL and picked REST for subtle reasons, record it — otherwise someone will suggest GraphQL again in six months.
CONTEXT-FORMAT.md
# CONTEXT.md Format
## Structure
```md
# {Context Name}
{One or two sentence description of what this context is and why it exists.}
## Language
**Order**:
{A one or two sentence description of the term}
_Avoid_: Purchase, transaction
**Invoice**:
A request for payment sent to a customer after delivery.
_Avoid_: Bill, payment request
**Customer**:
A person or organization that places orders.
_Avoid_: Client, buyer, account
```
## Rules
- **Be opinionated.** When multiple words exist for the same concept, pick the best one and list the others under `_Avoid_`.
- **Keep definitions tight.** One or two sentences max. Define what it IS, not what it does.
- **Only include terms specific to this project's context.** General programming concepts (timeouts, error types, utility patterns) don't belong even if the project uses them extensively. Before adding a term, ask: is this a concept unique to this context, or a general programming concept? Only the former belongs.
- **Group terms under subheadings** when natural clusters emerge. If all terms belong to a single cohesive area, a flat list is fine.
## Single vs multi-context repos
**Single context (most repos):** One `CONTEXT.md` at the repo root.
**Multiple contexts:** A `CONTEXT-MAP.md` at the repo root lists the contexts, where they live, and how they relate to each other:
```md
# Context Map
## Contexts
- [Ordering](./src/ordering/CONTEXT.md) — receives and tracks customer orders
- [Billing](./src/billing/CONTEXT.md) — generates invoices and processes payments
- [Fulfillment](./src/fulfillment/CONTEXT.md) — manages warehouse picking and shipping
## Relationships
- **Ordering → Fulfillment**: Ordering emits `OrderPlaced` events; Fulfillment consumes them to start picking
- **Fulfillment → Billing**: Fulfillment emits `ShipmentDispatched` events; Billing consumes them to generate invoices
- **Ordering ↔ Billing**: Shared types for `CustomerId` and `Money`
```
The skill infers which structure applies:
- If `CONTEXT-MAP.md` exists, read it to find contexts
- If only a root `CONTEXT.md` exists, single context
- If neither exists, create a root `CONTEXT.md` lazily when the first term is resolved
When multiple contexts exist, infer which one the current topic relates to. If unclear, ask.
Keep going