skills/ubiquitous-language/SKILL.md
Use when evaluating the ubiquitous language in a codebase - produces a glossary of domain terms with references and commentary on inconsistencies, awkward names, or overlapping concepts
npx skillsauth add mattwynne/yaks ubiquitous-languageInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
The ubiquitous language is the shared vocabulary a team uses for domain concepts — in conversation, code, tests, and docs. When the language is consistent, the code communicates clearly. When it drifts, misunderstandings hide in plain sight.
This skill produces a docs/terms.md glossary and a
commentary on the health of the language.
Scan the codebase for domain terms. Focus on these layers, in order of authority:
| Layer | Where to look | Why | |-------|--------------|-----| | Domain model | Domain types, enums, enum variants, struct fields, constants, naming conventions, validation rules | The core vocabulary — highest authority | | Events | Event types and their payloads | Capture what happened in domain language | | Commands / Use cases | Application layer, command handler | The verbs — what users can do | | CLI surface | CLI commands, flags, help text | How users encounter the language | | Feature files | See detailed guidance below | The richest source of natural-language domain terms | | Other tests | Unit test names, integration test names | How developers talk about behaviour | | Documentation | README, ADRs, design docs | How the team explains the system |
Feature files deserve special attention. They are scenarios written in natural language — the closest thing to how the team talks about the domain. Read them carefully, extracting terms from:
Also ask: "For each noun in the glossary, are there named subcategories?" Many domain concepts have subtypes that aren't in the type system but live in conventions, validation rules, or feature file Rules. "Reserved field" vs "custom field" is a classification within the Field concept. These boundaries matter.
Look for "negative space" terms — concepts the team uses
in conversation that have no name in the code. If a
feature file says "reserved fields" but the code has no
ReservedField type or even a comment using that phrase,
that's a gap worth flagging.
Feature files should use declarative style — they describe what the system does using domain language, not how the user interacts with the UI or implementation.
Declarative (good): Steps express business intent.
Given a yak "make the tea" with state "done"
When I prune
Then "make the tea" should be removed
Imperative (bad): Steps spell out mechanics.
Given I run "yx add make the tea"
And I run "yx state make the tea done"
When I run "yx prune"
Then I run "yx ls" and the output does not contain
"make the tea"
Signs of imperative Gherkin:
| Smell | What it looks like | Why it's bad |
|-------|--------------------|-------------|
| Shell commands in steps | When I run "yx add ..." | Steps are coupled to CLI implementation, not domain |
| Output parsing | Then the output contains "..." | Tests the rendering, not the behaviour |
| Multi-step mechanics | Many steps to set up one domain state | Business rule is buried in noise |
| UI/CLI navigation | "I type", "I press", "I see" | Not domain language |
| No domain nouns | Steps use generic terms like "output", "command", "result" | The ubiquitous language is absent |
When reviewing feature files for this glossary, flag:
The test is: "Would this wording need to change if the implementation changed?" If yes, the step is imperative and the domain language is being bypassed.
Separate nouns and verbs. Domain nouns are the things the system talks about. Domain verbs are the operations performed on them. This separation matters because nouns tend to have multiple representations (structs, views, snapshots) while verbs tend to have multiple expressions (CLI commands, use cases, events).
For each term, record:
Look for these specific problems:
Different words for the same concept. Example: "task" in docs but "yak" in code. Pick one. Synonyms cause people to wonder whether the two words mean subtly different things.
Same word meaning different things in different contexts. Example: "state" meaning both "yak lifecycle state" and "application state". Flag these even if the context usually disambiguates — they trip up newcomers.
Implementation terms in the domain layer. The domain model should speak the language of the problem, not the solution. Examples: "aggregate" in a CLI message, "projection" in a feature file, "store" where "repository" or a domain term would be clearer.
Terms that don't convey their meaning without explanation. A name is awkward if you'd need a comment or a conversation to understand it. Abbreviations, inside jokes, and legacy names that no longer match the concept all qualify.
Places where the code uses generic language ("item", "thing", "data", "info") instead of a domain-specific term. Also look for concepts that exist in conversation but have no name in the code.
Some terms are very specific while related terms are vague.
Example: detailed lifecycle states (todo, wip, done)
alongside a vague update event that covers many things.
Gherkin steps that describe how (shell commands, output parsing, UI mechanics) instead of what (domain operations and outcomes). Imperative steps bypass the ubiquitous language — they test the implementation without exercising the vocabulary. Flag specific steps and suggest declarative rewrites using domain terms.
For each domain concept, list every type, struct, enum, or alias in the code that represents it. Do not gloss over the fact that one concept may have multiple representations. Name each one, say where it lives, explain why it exists, and note what it relates to.
For example, if the concept "Yak" appears as YakView,
YakEntry, YakSnapshot, YakTreeNode, and YakChildView,
list all five. Explain: YakView is the read-model DTO,
YakEntry is the aggregate's internal state, YakSnapshot
is used for compaction, etc. This is the inventory — no
smoothing over, no "the code calls this a Yak".
Ask for each representation:
Create or update docs/terms.md with this structure:
# Ubiquitous Language — Glossary
> This glossary defines the shared vocabulary for this
> project. When naming things in code, tests, CLI, or
> docs, use these terms consistently.
>
> Last reviewed: YYYY-MM-DD
## Nouns
### Term Name
Definition in one sentence.
**Representations in code:**
| Type | File | Role |
|------|------|------|
| `TypeName` | `path/to/file.rs:42` | Why this one exists |
| `OtherType` | `path/to/other.rs:10` | Why this one exists |
- **Used in**: `features/foo.feature`, `docs/bar.md`
- **Related to**: Other Term, Another Term
- **Aliases**: (list any synonyms — flag if problematic)
## Verbs
### Term Name
Definition in one sentence.
| Expression | Where | Form |
|------------|-------|------|
| `yx command` | CLI | User-facing command |
| `UseCaseName` | `src/application/file.rs:1` | Use case |
| `EventName` | `src/domain/event.rs:14` | Domain event |
- **Used in**: `features/foo.feature`
- **Related to**: Other Term
## Commentary
### Strengths
What the codebase does well with its language.
### Issues Found
#### Issue Title
- **Type**: Synonym / Homonym / Technical Leak / Awkward
Name / Missing Term / Inconsistent Granularity
- **Where**: files and lines
- **Problem**: what's wrong
- **Suggestion**: how to fix it
A healthy ubiquitous language has these properties:
| Property | Check | |----------|-------| | One term per concept | No synonyms | | One concept per term | No homonyms | | Domain speaks for itself | No technical leak | | Self-documenting | No awkward names | | Complete | No missing terms | | Consistent depth | No granularity gaps | | Aligned across layers | Same words in code, CLI, tests, docs | | Declarative tests | Feature files use domain language, not implementation mechanics |
testing
Use when writing or reviewing Gherkin features, especially after discovering examples or edge cases that reveal a new business rule
databases
Use when running yx commands that create, modify, or delete yaks outside of real project work — provides an isolated temp environment
documentation
Use when starting work on a yak - sets up an isolated git worktree, reads yak context, and guides the full cycle from claiming through merge and cleanup
development
Use when planning work by approaching goals and discovering blockers, before creating comprehensive plans