Consume results programmatically
A gate that only passes or fails is the floor. Once manni meta is running, the same data behind the pass/fail decision can feed other tools. That means dashboards, PR bots, content catalogs, and custom checks, without re-parsing documents yourself.
manni meta exposes its results three ways, each suited to a different integration style:
--format json: a single structured object per run, for pipelines that shell out and parse stdout.- The
getcommand: pull specific metadata field values out of files, for scripts that need a few values rather than a full validation report. - The TypeScript API: call manni meta’s command cores directly from Node.js, for tools built on top of it.
–format json
Section titled “–format json”manni meta validate --format json prints one JSON object to stdout describing the
whole run. It is the path for any tool that runs manni meta as a subprocess and
reads its output.
npx -y @hawkeyexl/manni meta validate "docs/**/*.md" --format jsonThe object has a summary and a results array:
{ "summary": { "files": 1, "passed": 0, "failed": 1, "errors": 1 }, "results": [ { "file": "bad-timestamp.md", "format": "markdown", "ok": false, "schemas": ["google:okf:0.1"], "errors": [ { "schema": "google:okf:0.1", "instancePath": "/timestamp", "message": "must match format \"date-time\"", "keyword": "format", "subject": "date-time", "line": 4 } ] } ]}The fields:
summary: run-wide counts:fileschecked,passed,failed, and the totalerrorsacross all files.results: one object per file:file(the path as manni meta saw it),format(the extractor that read it),ok,schemas(the resolved schema set), anderrors.- Each error carries
schema, the schema id that produced it, andinstancePath, a JSON Pointer to the field, or""for the document root. It also carriesmessage,keywordandsubject. Finallyline, 1-based, when manni meta can locate it, andcol, 1-based, when the format can supply one.
The output is plain (never colorized) and goes to stdout, so it pipes cleanly
into jq. List the files that failed:
npx -y @hawkeyexl/manni meta validate "docs/**/*.md" --format json \ | jq -r '.results[] | select(.ok == false) | .file'Flatten every error into a file:line message line for a log:
npx -y @hawkeyexl/manni meta validate "docs/**/*.md" --format json \ | jq -r '.results[] | .file as $f | .errors[] | "\($f):\(.line // "?") \(.message)"'Read just the summary counts:
npx -y @hawkeyexl/manni meta validate "docs/**/*.md" --format json | jq '.summary'The get command
Section titled “The get command”When a script needs metadata values rather than a validation verdict (say, to
build an index of every page’s title and type), use manni meta get. It reads
the named fields from each file and prints them. It shares validate’s input
handling: positional paths, directories, globs, - for stdin with --as, the
collections: from config as the fallback, and --collection <name> to narrow
to one of them.
Pass the fields as a single comma-separated argument, then the targets:
npx -y @hawkeyexl/manni meta get title,tags docs/intro.mdFor scripting, add --format json to get a structured array, one object per
file:
npx -y @hawkeyexl/manni meta get title,tags "docs/**/*.md" --format json[ { "file": "docs/intro.md", "present": true, "values": { "title": "Introduction", "tags": ["onboarding", "guide"] } }]Each object reports:
file: the file path.present: whether the file had a metadata block at all (falsefor a document with no frontmatter).values: the requested fields and their values.
Reach into nested metadata
Section titled “Reach into nested metadata”When frontmatter nests objects or arrays, a field reference can address the
inner value instead of pulling the whole parent. Use dot-notation for the
common case, or a JSON Pointer (any reference beginning with /) for keys
that contain a literal .:
# frontmatter: author: { name: Jane }, tags: [intro, setup]npx -y @hawkeyexl/manni meta get author.name,tags.0 docs/intro.md # dot-notationnpx -y @hawkeyexl/manni meta get '/author/name' docs/intro.md # JSON PointerThe JSON Pointer form is the same path validate prints in an error location,
so a pointer copied from a validation failure works verbatim. Requesting the
parent key (author) still returns the whole nested object. See the
get field reference for the full syntax.
Quote a leading-slash pointer ('/author/name') so Git Bash/MSYS2 on Windows
does not rewrite it as a filesystem path. Other shells (PowerShell, cmd, POSIX)
are unaffected, but quoting is harmless everywhere.
Extract one field across a tree into a shell list with jq:
npx -y @hawkeyexl/manni meta get type "docs/**/*.md" --format json \ | jq -r '.[] | "\(.file)\t\(.values.type // "(none)")"'The TypeScript API
Section titled “The TypeScript API”Some tools are built on top of manni meta. Think of a custom reporter, a bespoke gate, or a script that validates and then acts on the results. For those, call the command cores directly instead of shelling out. manni meta ships a programmatic entry point that exports the same cores the CLI is built on. You get structured results without spawning a process or parsing stdout.
The most common call is runValidate, which runs the full validation pipeline
and returns the same { results, summary } structure that backs --format json:
import { runValidate } from "@hawkeyexl/manni";
const { results, summary } = await runValidate({ inputs: ["docs/**/*.md"], cliSchemas: ["google:okf:0.1"],});
console.log(`${summary.passed}/${summary.files} files passed`);
for (const result of results) { if (result.ok) continue; for (const err of result.errors) { console.log(`${result.file}: ${err.instancePath} ${err.message}`); }}runValidate accepts a ValidateOptions object. The fields mirror the CLI:
inputs: files, directories, or globs to validate. When empty, manni meta falls back to thecollections:declared in the config, exactly as the CLI does.collections: collection names to run over, the programmatic equivalent of a repeated--collection. Like the flag, it cannot be combined with a non-emptyinputs.cliSchemas: schema references that override$schemaand config (the programmatic equivalent of--schema).exts,exclude,as,configPath: directory-walk extensions, exclude globs, a forced extractor name, and a config-file path.stdinContent: content for a-(stdin) input, supplied directly rather than read from the process.
It resolves to a ValidateRun of {{ results, summary }}, using the
ValidationResult and RunSummary shapes that the JSON format serializes.
Alongside runValidate, the entry point exports the other command cores,
the schema-resolution and config helpers, the reporters, the extractors, and
every result type they use. The TypeScript API
reference lists all of them.
Which one to reach for
Section titled “Which one to reach for”-
A subprocess in any language? Use
--format jsonand parse stdout. It is language-agnostic and the most stable surface. -
A shell script that needs a few field values? Use
get; it is purpose-built for pulling named fields without a full validation report. -
A Node.js or TypeScript tool? Call the API. You skip process spawning and stdout parsing, and you get typed results.