Domain Modeling
fossasia/eventyay-interpretation
Build and sharpen a project's domain model. An agent skill from fossasia/eventyay-interpretation.
Maintain a project thesaurus (domain glossary) following DDD ubiquitous language principles.
$ npx skills add CodeAlive-AI/ai-driven-development --skill ubiquitous-language -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install CodeAlive-AI/ai-driven-development ubiquitous-language --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/CodeAlive-AI/ai-driven-development.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/ubiquitous-language .claude/skills/ubiquitous-language && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "ubiquitous-language" agent skill from https://github.com/CodeAlive-AI/ai-driven-development/tree/main/skills/ubiquitous-language into .claude/skills/ubiquitous-language/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ubiquitous-language", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/CodeAlive-AI/ai-driven-development/tree/main/skills/ubiquitous-languageType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add CodeAlive-AI/ai-driven-development --skill ubiquitous-language -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install CodeAlive-AI/ai-driven-development ubiquitous-language --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/CodeAlive-AI/ai-driven-development.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/ubiquitous-language .agents/skills/ubiquitous-language && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "ubiquitous-language" agent skill from https://github.com/CodeAlive-AI/ai-driven-development/tree/main/skills/ubiquitous-language into .agents/skills/ubiquitous-language/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ubiquitous-language", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add CodeAlive-AI/ai-driven-development --skill ubiquitous-language -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install CodeAlive-AI/ai-driven-development ubiquitous-language --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/CodeAlive-AI/ai-driven-development.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/ubiquitous-language .cursor/skills/ubiquitous-language && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "ubiquitous-language" agent skill from https://github.com/CodeAlive-AI/ai-driven-development/tree/main/skills/ubiquitous-language into .cursor/skills/ubiquitous-language/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ubiquitous-language", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/CodeAlive-AI/ai-driven-development.git --path skills/ubiquitous-language--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add CodeAlive-AI/ai-driven-development --skill ubiquitous-language -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install CodeAlive-AI/ai-driven-development ubiquitous-language --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/CodeAlive-AI/ai-driven-development.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/ubiquitous-language .gemini/skills/ubiquitous-language && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "ubiquitous-language" agent skill from https://github.com/CodeAlive-AI/ai-driven-development/tree/main/skills/ubiquitous-language into .gemini/skills/ubiquitous-language/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ubiquitous-language", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install CodeAlive-AI/ai-driven-development ubiquitous-languageInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add CodeAlive-AI/ai-driven-development --skill ubiquitous-language -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/CodeAlive-AI/ai-driven-development.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/ubiquitous-language .github/skills/ubiquitous-language && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "ubiquitous-language" agent skill from https://github.com/CodeAlive-AI/ai-driven-development/tree/main/skills/ubiquitous-language into .github/skills/ubiquitous-language/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ubiquitous-language", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add CodeAlive-AI/ai-driven-development --skill ubiquitous-language -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install CodeAlive-AI/ai-driven-development ubiquitous-language --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/CodeAlive-AI/ai-driven-development.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/ubiquitous-language .opencode/skills/ubiquitous-language && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "ubiquitous-language" agent skill from https://github.com/CodeAlive-AI/ai-driven-development/tree/main/skills/ubiquitous-language into .opencode/skills/ubiquitous-language/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ubiquitous-language", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
ubiquitous-languageMaintain a project thesaurus (domain glossary) following DDD ubiquitous language principles.
Ubiquitous Language is an agent skill from CodeAlive-AI/ai-driven-development. Maintain a project thesaurus (domain glossary) following DDD ubiquitous language principles. Use PROACTIVELY when naming anything: variables, functions, classes, modules, database fields, API endpoints, events, files, or directories. Also use when the user asks to "create thesaurus", "update glossary", "add term", "rename to match domain", "check naming consistency", "what should I call this", "domain language", "ubiquitous language", or "naming conventions". Ensures all names in the codebase are consistent…
Its SKILL.md is about 7.4k tokens, which your agent loads only when the skill is triggered. The skill folder holds 7 other files, including scripts and reference files (for example `README.md`, `references/generating-thesaurus.md` and `references/git-history-mining.md`).
It sits in Development, covering Domain-driven design. The repository describes itself as: Practices, protocols, and skills for AI-driven software development. Skills and safety hooks for Claude Code, Codex, OpenCode, Cursor, Antigravity, and any agent supporting the… The licence is MIT.
3 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 25b7b1d. It shows what the files ask for, not the result of running them.
Pre-approves these tools, so the agent can use them without asking each time:
ReadWriteEditGrepGlobBashAgentAskUserQuestionFrom allowed-tools in the SKILL.md frontmatter.
Ships 1 file in scripts/ (Python), which the agent can run.
Shell commands in SKILL.md call:
rgpython3gitFrom the folder's file list and the shell code blocks in SKILL.md.
Links to these hosts (documentation or services it may open):
github.comFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Ubiquitous Language loads about 7.4k tokens when it runs, and up to ~23k if it reads all its reference files. Until then it costs about 199 tokens; SKILL.md has 3,224 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check noted patterns worth knowing about, such as sudo or a known installer.
allowed-tools: Read, Write, Edit, Grep, Glob, Bash, Agent, AskUserQuestionAutomated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.
The full file from CodeAlive-AI/ai-driven-development at commit 25b7b1d, republished under its MIT licence (© CodeAlive-AI). 3,224 words, ~7,374 tokens.
.claude/skills/ubiquitous-language/SKILL.md (or your agent's skills folder). This skill also uses 5 other files; get the full folder from GitHub.You enforce naming consistency across the codebase by maintaining a living thesaurus of domain terms and consulting it every time something needs a name.
Four modes:
## Unresolved items need evidence: which name came first, which replaced which,
which is dying. Offered after generation, or on demand against an existing thesaurus.This skill combines two bodies of knowledge:
"A project should use a single, shared vocabulary. Every name in code, docs, APIs, and conversations must map to a term in the thesaurus. If a concept isn't in the thesaurus — add it before naming anything."
— Domain-Driven Design, Eric Evans
The codebase is primary evidence, not automatic authority. Use code to discover which terms are currently in circulation. Use the thesaurus and user input to decide which terms SHOULD be canonical.
## Legacy lines and use the user's terms as canonicalTacit knowledge: For areas not yet implemented, the most important domain knowledge exists only in experts' heads, not in any artifact.
Locating the thesaurus:
THESAURUS.md already exists somewhere in the repo — use that locationdocs/THESAURUS.mdSingle source of truth for domain vocabulary.
The thesaurus declares its format version and the skill that maintains it in YAML frontmatter — machine-readable, outside the body, still one grep away:
---
thesaurus-format: "2.0"
skill: ubiquitous-language
---
# Project ThesaurusQuote the version — unquoted 2.10 is the YAML float 2.1.
rg -n '^thesaurus-format:' THESAURUS.md → the version in one hit. No key = 1.0
(the pre-index prose layout shipped before skill 2.0) — unless the file already has
- **Term** `Id` kind: Index lines: that is an unstamped 2.0 file from plugin 9.2.0;
just add the stamp.metadata.version in this file's frontmatter). Skill
minor/patch releases never change the format.git log already answers "who wrote this". skill:
is a pointer, so an agent without the skill knows what to install.| Format | Layout | Skill |
|---|---|---|
| 1.0 | ### Term entries with Synonyms to AVOID; ## Legacy Terms entries; ## Forbidden Lexicon table | ≤ 1.x (plugin ≤ 9.1.1) |
| 2.0 | grep-first: ## Index lines with kind:/ctx:/avoid:, use: Forbidden lines, → Legacy lines, SKOS bridges | 2.x |
The file is designed so that one rg/grep for any name answers "what do I do with
this name?" without reading the surrounding text. Five sections, fixed order:
| Section | Shape | One line answers |
|---|---|---|
## Index | one line per concept | "Is there a term for this? Which name is canonical? What is banned?" |
## Terms | ### Term entries | "What exactly does it mean / not mean / relate to?" |
## Forbidden | one line per word | "Is this word banned from domain names?" |
## Legacy | one line per old name | "This old name is in the code — what replaced it?" |
## Unresolved | ### Term — problem entries | "Is this name an open question?" |
Registry invariant: every name known to the project appears in exactly one
registry line — an Index line (as Term, Identifier, or avoid), a Forbidden line, a Legacy
line, or an Unresolved header. Each kind of registry line has its own shape, so the
shape of the hit tells you its status and the line itself tells you the canonical
name. No -B/-A context needed.
Registry lines are bullet lines with labelled tokens, not Markdown tables: tables
need | (an alternation in rg), match by column position, and get re-padded by
formatters. Tokens (kind:, ctx:, avoid:, use:, in:, →) are position-free,
formatter-proof, and need no escaping.
# Project Thesaurus
## Index
- **Order** `Order` kind:aggregate avoid: `Purchase`, `Transaction`, `Buy`
- **Order Line Item** `OrderLineItem` kind:entity avoid: `LineItem`, `OrderItem`, `Item`
- **Order Placed** `OrderPlaced` kind:event avoid: `OrderCreated`, `NewOrder`
## Terms
### Order
- **Definition**: A customer's confirmed request to buy one or more products at agreed prices.
- **NOT**: A payment (that's `Payment`), a shipment, or a draft cart (that's `Cart`).
- **Related**: Order Line Item, Order Placed, Cart
## Forbidden
- `Manager` use: `OrderFulfillment` — hides responsibility; name the activity
## Legacy
- `UserManager` → `Customer` + `CustomerRegistration` in: `src/legacy/` — split in v3
## Unresolved
### Account — one word, two concepts (billing vs auth)
- **Found in**: `billing/Account.ts` (balance), `auth/Account.ts` (login)
- **Question**: Two bounded contexts, or one of them a naming mistake?
- **Impact**: 18 files
- **Options**: `BillingAccount` + `UserAccount`; or contexts Billing / Identity- **<Term>** `<Identifier>` kind:<kind> [ctx:<Context>] [avoid: `<name>`, `<name>`]| Field | Content | Rules |
|---|---|---|
| Term | Human name, as domain experts say it, in **bold** | May be multi-word or non-English. Also the ### header text of the entry |
| Identifier | PascalCase code form, in backticks | The thing you grep in code. All other casings derive from it mechanically (see Casing) |
| kind: | One of aggregate entity value event command query service role process state policy concept | Picks the naming rule below. concept when nothing fits |
| ctx: | Bounded context name | Only present once contexts are confirmed (see generating-thesaurus.md); the header then becomes ### Term (Context) |
| avoid: | Banned synonyms and abbreviations, each in backticks, comma-separated | Last on the line because it is the only variable-length field. Omit when empty |
rg Purchase → "use Order") a single hit.rg '`Order`' is an exact match;
rg Order would also hit OrderLineItem and Reorder. rg -F '**Order**' is the
exact Term.## Terms follow the same order.- `<Word>` use: `<Identifier>`[, `<Identifier>`] — <why>
- `<OldName>` → `<Identifier>`[ + `<Identifier>`] in: <files/modules> — <note>
- `<OldName>` → — (see `<X>`, `<Y>`) in: <files> — retireduse: always points at an Index Identifier. → is the legacy marker: A + B means the
old name was split; → — means retired with no single successor.
### [Term]
- **Definition**: What this concept means in the business domain — one sentence
- **NOT**: What this term does NOT mean; name the neighbouring term it is confused with
- **Related**: Other Index Terms this connects to, written exactly as in the Term fieldOptional lines when they carry real information: **Broader**, **Narrower**,
**Part of**, **Has parts**, **Example**. Write them on one side only — rg gives
the inverse for free, mirrored copies only drift. Minimal viable entry is one line:
- **Definition**: … — the Index line already holds the rest.
Anchor grammar (so lookups are one regex): the header is exactly ### <Term> or
### <Term> (<Context>) — nothing else. Tags, status, and context prefixes belong in
the Index line, not in the header. Find an entry with rg -n '^### Order( \(|$)' —
\b alone is not enough, it would also match ### Order Line Item.
The thesaurus captures concepts, not behavior. It's strong at nouns (entity names, roles, process names) but won't replace behavioral specs for business rules. Don't try to turn the thesaurus into a specification — keep entries short. If a concept has a critical invariant, note it briefly in the definition, not as a separate section.
Non-English domains: If the business domain operates in a non-English language, the
Term uses the original language — the thesaurus should reflect how domain experts
actually speak. The Identifier carries the code form:
- **Счёт-фактура** `Invoice` kind:entity. This is exactly why both fields exist.
Look up before inventing. This is the single most important step. Most naming tasks don't need a new term — the right name is already there.
Locate the thesaurus (see above). If absent, tell the user and offer generation.
Check rg -n '^thesaurus-format:' — no key or 1.x means the old layout: the
protocol below still works by plain text search, but offer migration once, up front.
Read the Index if it has ≤ ~60 lines — it is the entire vocabulary at one line per concept, cheaper than any search. For larger files, search instead.
Search every candidate name you are considering, plus whatever the surrounding
code already calls the thing. Use rg (the Grep tool) or grep -E — same patterns:
rg -n -i 'invoice' docs/THESAURUS.md # any role, any section
rg -n '`OrderLineItem`' docs/THESAURUS.md # exact identifier as seen in code
rg -n -F '**Order**' docs/THESAURUS.md # exact Term (not "Order Line Item")
rg -n 'avoid:.*`Purchase`' docs/THESAURUS.md # is this word a banned synonym?
rg -n 'kind:event' docs/THESAURUS.md # all terms of one kind
rg -n 'ctx:Billing' docs/THESAURUS.md # everything one context owns
rg -n '`Basket` →' docs/THESAURUS.md # legacy name and its replacement
rg -n -A4 '^### Invoice( \(|$)' docs/THESAURUS.md # the entry itselfThe only trap: * and | are regex metacharacters — use -F for **Term**, and
never search for table pipes (there are none).
Act on the shape of the line you hit:
| Hit line looks like | Meaning | Do |
|---|---|---|
- **X** `X` kind:… — your word is the Term or Identifier | Concept exists | Use the Identifier exactly. Stop |
- **X** … avoid: … `your word` | You were about to use a banned synonym | Use that line's Identifier instead |
- `word` use: … | Word is banned from domain names | Pick the Identifier after use: |
- `word` → … | Old name still in code | Use the replacement after → for new code; don't spread the legacy name |
### word — … under ## Unresolved | Open naming question | Don't decide silently — surface it, ask the user, or offer history mining (see below) |
### header / entry text only | Related concept | Read the entry; it may inform composition |
| No hit | New concept | Go to "If the concept is new" |
Check the bounded context if Index lines carry ctx: — the same word may be
canonical in one context and banned in another.
ALWAYS run this before naming: classes, interfaces, types, enums, aggregates, entities, value objects, functions, methods, commands, queries, domain events, variables, constants, fields, parameters, DB tables/columns/collections, API endpoints and response fields, files, directories, modules, packages, feature flags, config keys, environment variables, and commit messages or PR titles that reference domain concepts.
Before minting a new term, try four levers (from FPF F.14 "Name less, express more"):
OrderLineItem reuses Order + LineItemNightOperator — use Operator with a time qualifier## Unresolved
with a [WHITE-SPOT] tag in the header. Don't force a name for an undefined concept.Only after all four fail, mint a new term:
PremiumCustomerTask to Activity to sound universalkind:, avoid: —
omit avoid: when empty) and a ### Term entry with at least a Definition. Keep both sortedWhen existing code uses a term that contradicts the thesaurus:
fetchPurchases() but the Index line says Order, with Purchase under avoid:"When a name lands in ## Unresolved — two spellings for one concept, one spelling for two
concepts, no obvious winner — the current tree can't settle it, but the repository's history
often can: which identifier was born first, which commit removed one while adding the other,
which one is dying.
Offer it, don't run it silently. Whenever you present ## Unresolved items — after
generation, after an audit, or when a naming question hits one — offer once:
"I can mine the git history for these — when each name was born, which replaced which, which is growing vs dying. Temporary index outside the repo, deleted afterwards. Want me to try that before you answer them by hand?"
Skip the offer if there is no .git, history is shorter than ~50 commits or squashed from
an import, or the items are [WHITE-SPOT] tags (an unnamed concept leaves no trace).
If the user accepts, read references/git-history-mining.md and follow it. The short version:
S=<skill-dir>/scripts/git_term_index.py
python3 $S build --repo-dir . --content # throwaway SQLite index in $TMPDIR, never in the repo
python3 $S query Account Customer # birth, dormancy, trajectory, renames, messages
python3 $S pair User Customer # competing names: birth order + swap commits
python3 $S contexts Account # where the name lives — the polysemy check
python3 $S search 'rename account' # BM25 search over commit messages
python3 $S clean # delete the index when doneThe index covers the whole diff history, so "born" means born. Use --pathspec src/
on large repos — it cuts build time and sharpens the signal at once.
pair ends in a labelled verdict — RENAME (strong / probable / possible), DRIFT,
NOT A RENAME, COEXISTENCE — with the direction inferred from evidence, not argument
order. Report the label as given; do not upgrade it. "RENAME — strong" means commits
exchange the names and a subject announces it; everything weaker needs git show first.
For polysemy (one word, two meanings, two modules) use the path split: pair prints
files: A in N, B in M, both in K, and contexts <name> gives the directory breakdown for a
single word. both in 0 — no file ever contained both — is real evidence for two bounded
contexts; shared files mean synonym drift, which history cannot settle. Only claim a path
split when the tool printed one. File-only renames (the file moved, the identifier did not)
appear in query's file-renames section, not in pair — run both.
History is evidence, not authority. It ranks candidates and cites commits; the user
decides. Report proposals in one batch with confidence levels, apply only what is approved,
and record the commit behind each applied decision (— renamed in a41f2c9 on the Legacy
line, or a - **History**: line on the entry).
The Index Kind column selects the rule.
aggregate)Use the business domain term. Singular. No technical suffixes.
GOOD: Order, Invoice, UserAccount, ShoppingCart
BAD: OrderAggregate, OrderRoot, OrderAggregateImpl, OrderEntityentity)Singular noun from the domain. Something with identity.
GOOD: OrderLineItem, PaymentTransaction, Customer
BAD: OrderLineItemEntity, OrderLineItemImpl, OrderLineItemObjvalue)Singular noun describing an immutable concept. Describes what it is, not what it does.
GOOD: Money, Email, PhoneNumber, Address, DateRange
BAD: MoneyValue, EmailValidator, PriceInfo, AmountDataevent)Past tense verb + noun. Something that happened.
GOOD: OrderPlaced, PaymentCaptured, InvoiceSent, InventoryReserved
BAD: OrderEvent, OnOrderPlaced, CreateOrder (that's a command)command)Imperative verb + noun. An action requested.
GOOD: CreateOrder, CancelInvoice, ProcessRefund, ReserveInventory
BAD: OrderCreated (that's an event), NewOrder, OrderCommandquery)Question or retrieval. Verb + object or descriptive name.
GOOD: GetOrderById, FindInvoicesByCustomer, ListPendingOrders
BAD: RetrieveOrderData, OrderQuery, GetterForOrderservice)Named after business activities the domain expert recognizes.
GOOD: InvoiceCalculator, OrderFulfillment, NotificationSender
BAD: OrderManager, GenericService, HelperServiceRepository suffix is acceptable — it's an infrastructure pattern. Repositories are not thesaurus terms; they take the name of the aggregate they store.
GOOD: OrderRepository, InvoiceRepository, CustomerRepository
BAD: OrderStorage, OrderPersistence, OrderFinder, OrderDaoCommands (change state): Imperative verb, no "Get" prefix.
GOOD: order.Cancel(), order.AddLineItem(product, quantity), order.Recalculate()
BAD: order.CancelOrderMethod(), order.GetCancelled(), order.DoCancelOrder()Queries (read-only): Start with Get, Is, Has, Can, or a domain verb.
GOOD: order.GetTotal(), order.IsExpired(), order.CanBeShipped()
BAD: order.FetchInfo(), order.CheckData()## Forbidden sectionThe domain layer must be protected from transient jargon, vague terms, and
implementation details. The thesaurus's ## Forbidden section lists words that MUST NOT
appear in domain names and must always be replaced with a specific domain term.
| Weasel Word | Problem | Fix |
|---|---|---|
Info | Meaningless suffix | Remove it: UserInfo -> User |
Data | Says nothing about the concept | Use domain term: OrderData -> Order |
Manager | Vague, hides responsibility | Split by actual responsibility |
Handler | Generic, unclear intent | Name after what it handles |
Service | Overused catch-all | Use specific domain activity name |
Base | Technical distraction | Remove, use composition |
Item | Too generic | Use domain term: Item -> OrderLineItem, Product |
Util / Helper | Indicates bad design | Move logic to domain objects |
Object / Obj | Never appropriate | Remove suffix |
Record / Model | Database concept leaking into domain | Use domain term |
Config / Settings | Generic container hiding a concept | Config -> LoanProduct, Settings -> NotificationPreferences |
Domain code must be free of implementation details:
BAD: MongoOrder, SqlUserRepository, HttpOrderService, OrderDto, OrderEntity
GOOD: Order, OrderRepository (interface), PaymentGateway, Order (just Order)Technical prefixes/suffixes belong ONLY in the infrastructure layer, and even there the domain role should lead:
INFRASTRUCTURE LAYER (OK): MongoOrderRepository, RedisSessionCache, HttpPaymentClient
DOMAIN LAYER (NEVER): MongoOrder, RedisSession, HttpPayment
NAME THE ROLE, NOT THE TECH: SessionStore not RedisCache, EventPublisher not KafkaProducerFramework caveat: In frameworks that intentionally blend domain and persistence (Active Record pattern, ORM-centric frameworks), the model IS the domain entity. Keep the domain noun clean and let framework coupling live in inheritance, annotations, or metadata — not in the class name. Flag technical jargon only when it becomes part of the business-facing name or leaks outside its boundary.
Same concept called different things in different parts of code:
PROBLEM: "Customer" in auth, "User" in API, "Account" in billing — all mean the same thing
FIX: Pick ONE canonical term per bounded context. Put the others in that line's `avoid:` list.Ban abbreviations in durable, domain-bearing names: types, exported functions, modules, API fields, DB columns, events, config keys.
Allow conventional short-lived local identifiers when meaning is obvious in scope:
i, j, ctx, req, res, err, tx, db, e for events.
Allow industry-standard acronyms when they are the dominant term: SKU, VAT,
URL, ID, OAuth. Do NOT force unnatural expansions if experts use the acronym.
PROBLEM: usr, user, account, acct — competing abbreviations for the same durable concept
FIX: Pick ONE canonical form for domain-bearing names. Short-lived locals are exempt.When different artifacts use different terms for the same concept across the knowledge chain, information is lost at each translation:
SMELL: Domain expert says "Campaign" → PM writes "Promotion" in spec →
Dev codes `marketing_push` → QA tests "advertising effort"
FIX: Same term everywhere: expert, PM, dev, QA all say and write "Campaign"This is worse than synonym drift because each translation also loses nuance and business rules. How to detect: compare terms in requirements/specs/tickets against code names. If they don't match, the ubiquitous language has a translation gap — adopt the domain expert's term everywhere.
The Index Identifier is PascalCase. Every other form is derived from it mechanically
using the project's conventions — never re-worded:
| Context | Convention | Example (Identifier: OrderLineItem) |
|---|---|---|
| Class/Type | PascalCase | OrderLineItem |
| Function/Method | Project convention | addOrderLineItem / add_order_line_item |
| Variable | Project convention | orderLineItem / order_line_item |
| Constant | UPPER_SNAKE | MAX_ORDER_LINE_ITEMS |
| Database table | Project convention | order_line_items |
| API endpoint | kebab-case or convention | /orders/{id}/line-items |
| Event/Message | PascalCase with past-tense verb | OrderLineItemAdded |
| File/Directory | Project convention | order_line_item.py, OrderLineItem.cs |
Key rules:
ord), don't expand (orderObject), don't synonym (purchase)OrderLineItem, not PurchaseLineItemOrderRepository, OrderDTO (in infra layer only)ProcessingStage → processing_stage, never proc_stagetotalAmount not amt, customerEmail not cEmailWhen changing terms, use the least strong relation that tells the truth (from FPF F.13):
| Operation | When | Effect on thesaurus |
|---|---|---|
| Add | New concept | Index line + entry. Minimum: Identifier, kind:, Definition |
| Rename | Wording improved, sense unchanged | Change Term/Identifier in the Index line and header; old Identifier → ## Legacy line `Old` → `New`; grep codebase, suggest renames |
| Split | One term covered two senses | Old line removed; two new lines + entries; old Identifier → ## Legacy line `Old` → `A` + `B`; disambiguation in each NOT |
| Merge | Two terms are really one sense | Keep one line; the other Identifier moves into its avoid: list; entries merged |
| Retire | Term was misleading, no single successor | ## Legacy line `Old` → — (see `X`, `Y`) |
| Deprecate | Concept being phased out | ## Legacy line with → replacement and in: locations |
Key test: Can you point to the same concept before and after the change?
Alias parsimony: keep at most 1 legacy alias per term — the one readers will most
likely encounter in old code. Registry invariant still holds after every edit: a name
is under avoid: or in Legacy, never both.
Old layout? No thesaurus-format frontmatter key (or 1.x) means the pre-index prose layout —
see "Migrating an Existing Thesaurus" in
references/generating-thesaurus.md.
avoid: list?event, imperative for command?If any answer raises a concern — stop and fix before proceeding.
© CodeAlive-AI, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 5 other files (scripts, references) in skills/ubiquitous-language of CodeAlive-AI/ai-driven-development.
Open the folder on GitHubat commit 25b7b1d
Ubiquitous Language next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Ubiquitous Language this skillCodeAlive-AI/ai-driven-development | 155 | — | ~7.4k | Automated safety check: Notes | MIT | |
| Domain Modelingfossasia/eventyay-interpretation | 1.6k | 29 repos | ~821 | Automated safety check: Pass | Apache-2.0 | |
| Architecture Governancezai-org/ZCode | 7.5k | — | ~1.2k | Automated safety check: Pass | Apache-2.0 | |
| Evolutionary Modular Architecturetech-leads-club/agent-skills | 7k | — | ~3.7k | Automated safety check: Pass | CC-BY-4.0 | |
| Domain Modelingbrim-borium/spotify_sdk | 166 | 5 repos | ~806 | Automated safety check: Pass | Apache-2.0 | |
| Domain Modeling and Glossarywindmill-labs/windmill | 18k | — | ~622 | Automated safety check: Pass | Custom licence |
fossasia/eventyay-interpretation
Build and sharpen a project's domain model. An agent skill from fossasia/eventyay-interpretation.
zai-org/ZCode
Apply the repository's architecture policy to code changes by generating a bounded context package, checking module and layer boundaries, and reporting baseline-aware violations.
tech-leads-club/agent-skills
Guides design of modular-monolith platforms with DDD, flat-by-aggregate modules, anti-corruption layers, outbox events and resilience, plus an architecture document with SVG diagrams.
brim-borium/spotify_sdk
Build and sharpen a project's domain model. An agent skill from brim-borium/spotify_sdk.
windmill-labs/windmill
Actively challenges vague or conflicting terminology as you design, and keeps a living domain glossary file up to date in real time.
swamp-club/swamp
Domain Driven Design guidance for TypeScript/Deno codebases.
CodeAlive-AI/ai-driven-development
Investigate GitHub repository history before risky code changes using git blame/log, GitHub PRs, review comments, squash/rebase/cherry-pick/rename heuristics, and cited evidence.
CodeAlive-AI/ai-driven-development
Create, publish, delete, and submit plugins for coding agents (Claude Code, OpenCode, Devin CLI/Desktop).
CodeAlive-AI/ai-driven-development
Deep research over the Semantic Scholar Graph API. An agent skill from CodeAlive-AI/ai-driven-development.
CodeAlive-AI/ai-driven-development
A skill your agent uses when testing Windows 11 desktop apps (WinForms/WPF/UWP) via UFO UIA/Win32 automation MCP.
CodeAlive-AI/ai-driven-development
Audit and improve repositories for reliable agentic work across Codex and Codex App, Claude Code, and OpenCode.
CodeAlive-AI/ai-driven-development
Manage hooks and automation for coding agents (Claude Code, Codex CLI, OpenCode, Devin CLI/Desktop).
Categories
Maintain a project thesaurus (domain glossary) following DDD ubiquitous language principles. Ubiquitous Language is an agent skill from CodeAlive-AI/ai-driven-development. Maintain a project thesaurus (domain glossary) following DDD ubiquitous language principles.
Ubiquitous Language fits situations like: the user asks to create thesaurus; update glossary; rename to match domain; check naming consistency.
Run `npx skills add CodeAlive-AI/ai-driven-development --skill ubiquitous-language -a claude-code`. Or copy the skill folder (skills/ubiquitous-language in CodeAlive-AI/ai-driven-development) into .claude/skills/ubiquitous-language in your project. Claude Code loads it when a task matches its description.
Run `npx skills add CodeAlive-AI/ai-driven-development --skill ubiquitous-language -a codex`. Or copy the skill folder (skills/ubiquitous-language in CodeAlive-AI/ai-driven-development) into .agents/skills/ubiquitous-language in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add CodeAlive-AI/ai-driven-development --skill ubiquitous-language -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/ubiquitous-language, .gemini/skills/ubiquitous-language, .github/skills/ubiquitous-language and .opencode/skills/ubiquitous-language in your project.
Going by SKILL.md and its folder, Ubiquitous Language needs Python for the scripts in its folder and the command-line tools its instructions call (rg, python3 and git). Our summary lists: Python 3. Its frontmatter pre-approves these tools: Read, Write, Edit, Grep, Glob, Bash, Agent, AskUserQuestion.
SKILL.md names 1 domain. As links in the text: github.com. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found notes only (pre-approves every shell command (allowed-tools: bash)), nothing it rates as a warning. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.
Ubiquitous Language is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 7.4k tokens (SKILL.md is roughly 29k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 16k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Ubiquitous Language: Domain Modeling (fossasia/eventyay-interpretation, 1.6k stars), Architecture Governance (zai-org/ZCode, 7.5k stars), Evolutionary Modular Architecture (tech-leads-club/agent-skills, 7k stars) and Domain Modeling (brim-borium/spotify_sdk, 166 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
CodeAlive-AI (a GitHub organization) maintains it in CodeAlive-AI/ai-driven-development, which has 155 GitHub stars. The repository holds 22 skills in this directory. The repository was last updated on October 6, 2026.
Source: CodeAlive-AI/ai-driven-development on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.