Create your manni.config.yaml
A manni.config.yaml stores what “valid” means for your repo: which documents exist, and which schema set they must satisfy. With it committed at your repo root, both you and CI can run a bare manni meta validate and get a consistent, repeatable result.
The file has two halves. A top-level collections: list says which documents exist, and every manni tool reads it. A meta: section says how the metadata tool judges them. This page covers where manni looks for the file, then each half in turn. It then gives a complete worked example, and shows how command-line flags combine with what you configure.
Where manni meta looks for the config
Section titled “Where manni meta looks for the config”manni.config.yaml is one file shared by every tool under manni. collections: sits at the top level, and each tool owns one top-level key of its own; the metadata tool’s is meta::
collections: - name: pages paths: - "docs/**/*.md"
meta: schemas: - google:okf:0.1manni meta finds your config in one of two ways:
- Discovery. With no
--configflag, manni meta looks in the current working directory formanni.config.yaml, thenmanni.config.yml, and then repeats that in each parent directory. The first file carrying ameta:key or acollections:list wins, and the search stops at your repo root. That is the first directory containing.git. If no parent is a repository, only the current directory is checked. - Explicit path. Pass
-c <path>(or--config <path>) to point at a specific file. If that file does not exist, manni meta exits with an error rather than falling back to discovery.
A file with collections: and no meta: is still the metadata tool’s config. That is deliberate. One file describes the repository, so a repo that declares its documents has declared them for every tool. That holds whether or not it has tuned that tool yet.
Two older file names are still read, each with a warning on stderr. moose.config.yaml is the family file under its previous name. docmeta.config.yaml holds the meta: section as its whole document, with no wrapper key. A legacy file has no top-level, so it cannot carry collections; rename it to manni.config.yaml and split its keys across the two halves. The configuration reference has the full order.
Because the search walks up, manni meta validate gives the same verdict from your repo root as it does from docs/ or from a package subdirectory. When a config governs a run, manni meta prints a line naming it, such as Using manni.config.yaml (../..). To run against the built-in defaults instead, pass --no-config.
collections:, the document sets
Section titled “collections:, the document sets”A collection is a named set of documents. It is declared once, at the top level, and every manni tool reads the same declaration:
collections: - name: pages paths: - "docs/**/*.md" - "articles/**/*.md" exclude: - "**/drafts/**" - name: authors paths: - "authors/**"With this in place, a bare manni meta validate reads every collection, in declaration order. Pass paths explicitly and they take priority, so manni meta validate README.md validates only README.md.
The keys of one collection:
| Key | Type | Required | Meaning |
|---|---|---|---|
name |
string | yes | What --collection, an override’s collection: and a query’s FROM <name> refer to. Unique, compared case-insensitively. |
paths |
list | yes | Files, directories, or globs, relative to the config file’s directory. |
exclude |
list | no | Globs that remove files from paths. **/node_modules/** and **/.git/** are always excluded. |
url |
string | no | Where the collection is published. manni a11y check seeds its crawl from it. |
externalMetadata |
list | no | Manifests supplying frontmatter values that live outside the document. |
The configuration reference has the types, the defaults, and every parse error in full.
Why this is not a meta: key
Section titled “Why this is not a meta: key”collections: is the one top-level key that belongs to no tool. Which documents exist is a fact about the repository, not about the validator, and more than one tool needs it. That is clearest in url:, which the metadata tool never reads at all: it is where manni a11y check starts crawling when you give it no URLs. One declaration, several tools.
If you are upgrading from a config with meta.paths or meta.exclude, manni refuses those keys and the message names their new home:
manni: manni.config.yaml: "paths" is no longer a meta key. Document sets are declared once for every tool, under a top-level collections: list. See https://hawkeyexl.github.io/manni/meta/reference/configuration/#collectionsThat is exit 2, and there is no alias. Move the globs into a collection and the run works again.
Narrowing a run to one collection
Section titled “Narrowing a run to one collection”--collection <name> runs over the named collections only. It is repeatable, one name per occurrence, and it never splits on commas:
npx @hawkeyexl/manni meta validate --collection authorsnpx @hawkeyexl/manni meta validate --collection authors --collection pagesIt selects from the config, so it cannot be combined with positional paths (--collection selects a configured collection; it cannot be combined with paths.), and it needs a config to select from. It is most useful as a CI gate over one part of a docs set. One thing it turns off: corpus checks: read the whole corpus or nothing, so a scoped run skips them with a notice on stderr.
Metadata that lives outside the document
Section titled “Metadata that lives outside the document”A collection can declare external metadata: manifests that supply frontmatter values the documents do not carry. It is how a lean docset keeps a source: or jira: field out of every page, and how private values ride alongside public pages.
The meta: keys
Section titled “The meta: keys”Everything under meta: is the metadata tool’s business: which schemas apply, and how.
schemas
Section titled “schemas”The default schema set applied to every matched file. Each file must satisfy all schemas in the list: they are validated against the set, not against the first match.
meta: schemas: - google:okf:0.1A schema reference can be one of three kinds:
- A built-in id in
vendor:name:versionform, such asgoogle:okf:0.1. - A local file path to a
.jsonschema, such as./schemas/article.json. - An
http(s)URL to a remotely hosted schema.
If you omit schemas entirely, manni meta falls back to the built-in google:okf:0.1 schema, which requires a type field.
overrides
Section titled “overrides”A list of rules that assign a different schema set to a subset of files. Each entry carries a schemas list, plus exactly one of two ways to say which files it governs:
collection: <name>points at a declared collection. Use it when the subset is a real document set the whole family cares about.files: <glob>takes globs, or a list of them. Use it for a one-off subset that only affects schema choice.
The first override whose files match wins, and its schema set replaces the default schemas for that file.
collections: - name: pages paths: ["docs/**/*.md"] - name: api paths: ["docs/api/**/*.md"]
meta: overrides: - collection: api schemas: - google:okf:0.1 - ./schemas/api-reference.jsonOverrides are how you require stricter metadata for one area of the repo without affecting the rest. They are not the last word, though: a file’s own $schema field and the CLI --schema flag both take precedence over them. The dedicated overrides guide walks through the full resolution order, and when to reach for collection: rather than files:.
A complete example
Section titled “A complete example”This config declares two collections, skips drafts, applies the OKF schema everywhere by default, and layers an extra schema onto the articles.
# Which documents exist. Every manni tool reads this.collections: - name: pages paths: - "docs/**/*.md"
- name: articles paths: - "articles/**/*.md" # Files these globs remove are not in the collection. exclude: - "**/drafts/**"
# How the metadata tool judges them.meta: # The schema set every matched file must satisfy by default. schemas: - google:okf:0.1
# Per-subset overrides (first match wins). overrides: - collection: articles schemas: - google:okf:0.1 - ./schemas/article.jsonRun it from your repo root:
npx @hawkeyexl/manni meta validateHow CLI flags combine with the config
Section titled “How CLI flags combine with the config”Some command-line flags layer onto the config; others replace it. Keep the distinction in mind when you run manni meta locally with extra flags:
| Flag | Effect relative to config |
|---|---|
positional [paths...] |
Replaces the collections as the run’s targets. A typed file is still tested for collection membership, which is what its external metadata attaches to. |
--collection <name> |
Narrows the run to the named collections. Cannot be combined with positional paths. |
--exclude <glob> |
Adds to the built-in ignores for this run. It is the only exclusion that filters a typed path. |
-s, --schema <ref> |
Overrides all schema resolution. Config schemas, overrides, and file $schema are ignored. |