mdsmith
Esc
    v0.52.0 GitHub

    Word-list files under `.mdsmith/wordlists/`

    Each file under .mdsmith/wordlists/ declares one named word-list: an optional extends: parent and an entries: list of literal strings. A rule pulls a list in through its lists: setting and the entries union with the rule’s own list. No lists ship compiled in; a project declares every list it uses.

    A word-list is a named set of literal strings. A rule names one or more lists in its lists: setting, and the resolved entries union into the rule’s own list. A list lives in a YAML file under .mdsmith/wordlists/ whose basename is the list name. One file per list, no nesting. The directory sits next to .mdsmith.yml at the workspace root.

    .mdsmith.yml
    .mdsmith/
      wordlists/
        house-banned.yaml
        product-names.yaml

    # File shape

    The body has an optional extends: parent and a required entries: list of literal strings. A key outside that set is a config error naming the key and file.

    # .mdsmith/wordlists/house-banned.yaml
    entries:
      - "synergy"
      - "circle back"
      - "it's important to note that"

    Each entry is matched verbatim by the rule that reads it. Quote any entry YAML would otherwise mangle — a trailing comma, a leading symbol.

    # Referencing a list from a rule

    Every rule that takes a list setting also takes a lists: key. The named lists resolve to entries that union with the rule’s own inline list:

    rules:
      forbidden-text:
        lists: [house-banned]
        contains: ["one-off phrase"]

    forbidden-text then flags any paragraph that contains a house-banned entry or the inline phrase. lists: appends across config layers, so a convention’s lists: and a project’s lists: combine rather than replace.

    lists: fills one setting per rule:

    Rulelists: fills
    forbidden-textcontains
    forbidden-paragraph-startsstarts
    proper-namesnames
    required-mentionsmentions
    no-inline-htmlallow
    descriptive-link-textbanned
    callout-typeallow
    no-unused-link-definitionsignored-labels
    the placeholder rulesplaceholders

    The mechanism is neutral about how a rule reads its list. forbidden-text bans each entry; required-mentions requires each entry in every section.

    No lists ship compiled into the binary. Every list a rule names is one a project declares — in a file here or inline in .mdsmith.yml. The no-llm-tells convention is the home for the curated anti-slop vocabulary; it ships those words as the rules' inline presets, not as a named list you extend. To start from that curated set as editable files, run mdsmith init --wordlists . It scaffolds ai-speak.yaml and ai-openers.yaml here for you to own.

    # Extending a list

    A list may name one parent with extends:. The parent’s entries come first, then the list’s own, with duplicates dropped. Chains resolve to the root; a cycle or a missing parent is a config error. Use extends: to share one base list across several denylists:

    # .mdsmith/wordlists/our-slop.yaml
    extends: house-banned
    entries:
      - "best-in-class"
      - "move the needle"

    # Basename rule

    The list name is the basename minus extension. It must match [a-z][a-z0-9-]* — lower case, starting with a letter, with optional hyphen-separated segments. Both *.yaml and *.yml are scanned; the same basename across both extensions is a config error naming both files. Subdirectories and symlinks are rejected. A file over 1 MB is rejected.

    # Composition with .mdsmith.yml

    An inline wordlists: block in .mdsmith.yml is a first-class source — the inline twin of a file:

    wordlists:
      product-names:
        entries: ["mdsmith", "Goldmark"]

    The same name declared in both a file and inline is a config error naming both sources. The two do not merge.

    The no-llm-tells convention ships a curated anti-slop vocabulary as inline rule presets. A project that wants those words selects the convention. It does not name a list here. The convention files page covers the sibling .mdsmith/conventions/ directory.