Skip to content

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.

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::

manni.config.yaml
collections:
- name: pages
paths:
- "docs/**/*.md"
meta:
schemas:
- google:okf:0.1

manni meta finds your config in one of two ways:

  • Discovery. With no --config flag, manni meta looks in the current working directory for manni.config.yaml, then manni.config.yml, and then repeats that in each parent directory. The first file carrying a meta: key or a collections: 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.

A collection is a named set of documents. It is declared once, at the top level, and every manni tool reads the same declaration:

manni.config.yaml
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.

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/#collections

That is exit 2, and there is no alias. Move the globs into a collection and the run works again.

--collection <name> runs over the named collections only. It is repeatable, one name per occurrence, and it never splits on commas:

Terminal window
npx @hawkeyexl/manni meta validate --collection authors
npx @hawkeyexl/manni meta validate --collection authors --collection pages

It 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.

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.

Everything under meta: is the metadata tool’s business: which schemas apply, and how.

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.

manni.config.yaml
meta:
schemas:
- google:okf:0.1

A schema reference can be one of three kinds:

  • A built-in id in vendor:name:version form, such as google:okf:0.1.
  • A local file path to a .json schema, 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.

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.

manni.config.yaml
collections:
- name: pages
paths: ["docs/**/*.md"]
- name: api
paths: ["docs/api/**/*.md"]
meta:
overrides:
- collection: api
schemas:
- google:okf:0.1
- ./schemas/api-reference.json

Overrides 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:.

This config declares two collections, skips drafts, applies the OKF schema everywhere by default, and layers an extra schema onto the articles.

manni.config.yaml
# 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.json

Run it from your repo root:

Terminal window
npx @hawkeyexl/manni meta validate

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.