Configuration reference¶
dddlint reads dddlint.yaml from the project root. Every key is optional; an
empty file is valid and produces no findings.
Top-level keys¶
| Key | Type | Default | Description |
|---|---|---|---|
similarity_threshold |
float | 0.85 |
Ratio above which two domain/context names are flagged as duplicates |
enforce_canonical |
bool | true |
Flag alias terms in addition to forbidden ones |
name_uniqueness |
bool | true |
Flag a name claimed by more than one definition in the same context. Set false to let a variable and a method share a name |
forbidden |
list[str] | [] |
Terms that must never appear in a definition name |
exclude |
list[str] | [] |
Paths to skip, see exclude patterns |
directional |
list[str] | [to, from, before, after, src, dst] |
Tokens whose sides carry direction, exempting reordered names from drift |
synonyms |
list[SynonymGroup] | [] |
Canonical terms and their aliases |
domains |
list[Scope] | [] |
Path-scoped rules for high-level business domains |
contexts |
list[Scope] | [] |
Path-scoped rules applied after domains, win on conflict |
embeddings |
Embeddings | see below | Model and thresholds for dddlint map |
Exclude patterns¶
exclude takes gitignore syntax, matched against each file's path relative to
the directory holding the config file, not relative to the directory you point
the CLI at. So the same patterns hold whether you run dddlint lint or
dddlint lint src/billing.
A .gitignore beside the config file is honoured on top of these, as are the
always-skipped directories listed in the CLI reference.
SynonymGroup¶
| Key | Type | Default | Description |
|---|---|---|---|
canonical |
str | required | The one true term |
aliases |
list[str] | [] |
Terms that should be renamed to canonical |
Scope¶
domains and contexts share the same shape. Both add their rules to the
global rules for any file whose path matches an include glob.
| Key | Type | Default | Description |
|---|---|---|---|
name |
str | required | Identifier for the scope, shown in config-rule messages |
include |
list[str] | required | fnmatch globs matched against each file path |
forbidden |
list[str] | [] |
Banned terms within this scope |
synonyms |
list[SynonymGroup] | [] |
Scope-specific canonical terms |
Precedence: global → domains → contexts. Contexts are applied last, so a context can override a domain's alias mapping. See how checking works.
Embeddings¶
Read only by dddlint map. lint and lsp never embed anything.
| Key | Type | Default | Description |
|---|---|---|---|
model |
str | sentence-transformers:all-MiniLM-L6-v2 |
pydantic-ai embedding model, provider:name |
dimensions |
int | None | None |
Truncate vectors to this width, None keeps the model's native size |
batch_size |
int | 128 |
Names embedded per request |
cache |
Path | .dddlint/embeddings.json |
Vector cache, relative paths resolve against the config's directory |
threshold |
float | 0.6 |
Cosine similarity above which names cluster |
outlier_margin |
float | 0.05 |
How much closer a name must sit to another scope before it is called an outlier |
The cache is keyed by model and dimensions, so changing either invalidates it rather than mixing vector spaces. Unchanged names are never re-embedded.
threshold is a cosine on embedding vectors, a different scale from
similarity_threshold, which compares scope names as strings. On this codebase
the default model puts the median name pair at 0.20 and the closest pair at 0.86,
so 0.6 groups genuine pairs while 0.5 starts chaining unrelated names together.
Raise it if the map reports noise, lower it if every name sits alone.
Full example¶
similarity_threshold: 0.85
enforce_canonical: true
forbidden:
- util
- helper
- manager
synonyms:
- canonical: customer
aliases: [client, user, accountholder]
- canonical: order
aliases: [purchase, transaction]
domains:
- name: commerce
include: ["**/commerce/**"]
synonyms:
- canonical: order
aliases: [purchase]
contexts:
- name: billing
include: ["**/billing/**"]
forbidden: [discount]
synonyms:
- canonical: invoice
aliases: [bill, statement]
Loading config in Python¶
from pathlib import Path
from tempfile import mkdtemp
from dddlint.config import load_config
path = Path(mkdtemp()) / "dddlint.yaml"
path.write_text("forbidden: [manager]\n")
config = load_config(path)
assert config.forbidden == ["manager"]
assert config.enforce_canonical is True
assert config.similarity_threshold == 0.85