mdsmith
Esc
    v0.52.0 GitHub

    Glob patterns

    Glob pattern syntax across mdsmith config, directives, and CLI argument expansion, with the supported exclusion semantics for each surface.

    mdsmith uses doublestar as its single glob matcher across all surfaces. These include config (ignore:, overrides:, kind-assignment:), the <?catalog?> directive, and CLI argument expansion. The pattern syntax is identical on every surface; !-exclusion is supported on config and directive surfaces but not on CLI arguments.

    # Surfaces

    SurfaceField name!-exclusion
    ignore:list of stringsyes
    overrides:.globglob:yes
    kind-assignment:.globglob:yes
    <?catalog?>glob:yes
    CLI argument expansionpositionalno

    # Supported syntax

    All config and directive surfaces use doublestar, which supports:

    • * — any sequence of characters, no path separator
    • ** — any sequence of characters, including path separators (recursive match)
    • ? — any single character
    • [abc] — character class
    • {a,b} — brace expansion (matches either a or b)

    On config surfaces, a pattern matches a file if it matches any of the following candidates. This applies to ignore:, overrides:, kind-assignment:, and rule settings such as allowed:, include:, exclude:, budgets[].glob.

    • the raw path as given (docs/foo.md),
    • the cleaned path (docs/./foo.mddocs/foo.md), or
    • the basename (foo.md).

    Basename matching means a pattern like CHANGELOG.md (no slash) matches CHANGELOG.md in any directory.

    The top-level files: key in .mdsmith.yml is not a config pattern surface. It controls which files are discovered when no file arguments are given. It uses doublestar.Match on relative paths — no basename fallback, no !-prefix exclusion.

    CLI argument expansion uses doublestar.FilepathGlob directly — patterns are matched against the filesystem, not candidates derived from the path. A bare filename like CHANGELOG.md on the CLI is a literal path in the working directory, not a basename search.

    The <?catalog?> directive uses doublestar.Glob for include patterns. It matches full relative paths only. A bare filename like CHANGELOG.md finds only files in the catalog file’s directory, not nested paths.

    # Exclusion with !-prefix

    A pattern prefixed with ! is an exclusion pattern. The list matches a file when at least one non-negated pattern matches and no exclusion pattern matches. The order of include and exclude entries does not matter — exclusion always wins.

    overrides:
      - glob: ["docs/security/*.md", "!docs/security/proto.md"]
        rules:
          max-file-length:
            max: 1000

    A list containing only exclusion patterns matches nothing.

    # Config globs (ignore:, overrides:, kind-assignment:)

    Use the canonical glob: key for file patterns in overrides: and kind-assignment: entries:

    overrides:
      - glob: ["docs/**/*.md", "!docs/research/**"]
        rules:
          line-length:
            max: 120
    
    kind-assignment:
      - glob: ["plan/[0-9]*_*.md"]
        kinds: [plan]

    # Migrating from the files: key

    The files: key was the original field name for these patterns. It continues to work but emits a deprecation warning at load time:

    overrides[0]: `files:` is deprecated; rename it to `glob:` — see docs/reference/globs.md

    Replace the files: key inside each overrides: or kind-assignment: entry with glob: in your .mdsmith.yml. The top-level files: discovery key is unrelated and is not deprecated. The deprecated files: key will be removed in a future release.

    Note: the old files: key used a matcher where * crossed path separators. The canonical glob: key uses doublestar semantics where * matches a single path component. Update patterns like docs/guides/*.md to docs/guides/**/*.md if they relied on that behavior.

    # Rule-level glob settings and * behavior

    Rule settings that accept glob patterns now use doublestar semantics. The affected settings are:

    • token-budget.budgets[].glob
    • cross-file-reference-integrity.include / .exclude
    • duplicated-content.include / .exclude
    • directory-structure.allowed

    Update any pattern that relied on * crossing path separators (old gobwas/glob behavior) to use **.

    # Directive globs (<?catalog?>)

    <?catalog?> accepts a glob: parameter whose patterns are split on newlines into a list. A YAML glob: list becomes one pattern per line.

    !-prefix exclusion works the same way as in config: include patterns gather candidates, exclude patterns remove from the result.

    <?catalog
    glob:
      - "plan/*.md"
      - "!plan/proto.md"
    ?>

    The directive requires at least one non-negated include pattern; a glob list of only exclusions is rejected at lint time.

    # CLI argument expansion

    Positional arguments to mdsmith check and mdsmith fix are expanded with doublestar.FilepathGlob. It supports the same ** and brace-expansion syntax as config patterns. !-prefix exclusion is not available on the CLI; use ignore: in .mdsmith.yml instead.

    mdsmith check 'docs/**/*.md'   # works, recurses into subdirs
    mdsmith check '*.{md,markdown}'  # works, brace expansion