Docs

CLI

One binary, a closed verb set, machine-stable outputs. Everything runs in-process on your machine; the only network-touching verb is conformance run --target, and it talks only to the endpoint the descriptor names. This page and the AGENTS.md shipped inside the tarball (node_modules/epcis.dev/AGENTS.md) render from the same typed source, so they cannot disagree.

The contract

  • Verbs (closed set): translate, validate, hash, capture, mcp, conformance run, conformance rejudge, pins, version. Bare npx epcis.dev prints the orientation. Unknown verbs are a typed USAGE refusal with a hint, exit 2.
  • --json on every verb. Deterministic machine JSON — same data, same exit code as text mode. Text mode is token-cheap TSV-style lines, never colored, never wrapped.
  • stdout is payload-only. Errors are typed on stderr: {"error":{"code","message","hint"?}} in json mode, error<TAB>code=…<TAB>message=… in text mode. JSON.parse(stdout) never sees a half-written object.
  • Error code strings are stable across releases — match on code, never on prose: USAGE, PARSE, NOT_FOUND, INTERNAL.

Exit codes (stable)

exitmeaning
0ok
1fail — a negative domain verdict: invalid document, failed translation, rejected capture, failed suite run, rejudge mismatch
2usage
3not-found — unreadable input
4internal

Distinct exits distinguish "the fail-closed path worked" from a crash.

Verb reference (input → output → exit)

verbinputtext output--json output
validate <f> [--project]EPCISDocument or bare event JSONvalid line, or per-path schema-error lines{valid, schema:{artefact,version,sha256}, errors:[{path,keyword,message}]}
hash <f>event, event array, or EPCISDocumenthash line per event with the ni URI{algorithm, count, hashes:[…]}
translate <f.xml> [--out o]EPCIS 1.1/1.2/2.0 XMLsummary line; document JSON on line 2 (or wrote line)full result incl. document, fidelity, schemaErrors
`capture <f.json\f.xml>`document (XML is translated first)accepted + eventID lines, or capture-error lines{accepted, job, events} — events read back through the query door, stamps visible
mcpMCP server on stdio; stdout carries only the wire
`conformance run --self\--target d.json [--out o]`— / target descriptoradvisory notice, per-check verdicts, state line{mode:"advisory", notice, record}
conformance rejudge <run.json> [--signing-key b64]a run file / evidence bundlesignature line, per-check verdicts, rejudge line{signature, replayed, identical, missingChecks, flips, ok}
pinsone pin line per artefact: sha256 + source URLthe PINS record verbatim
versionpackage, EPCIS, CBV and suite versions{package, version, epcis, cbv, suite}

Hazard worth knowing before you pipe: translate in text mode without --out prints the summary first and the full document JSON as line 2 of stdout — use --json or --out when piping.

Proof — the taxonomy, exercised

Real runs against the published epcis.dev@0.1.0, using fixtures shipped in the tarball:

$ npx epcis.dev validate golden-corpus/valid-standard/object-event-shipping.json
valid	schema=epcis-json-schema.json	version=2.0.1
$ echo $?
0

$ npx epcis.dev validate golden-corpus/invalid/object-event-missing-action.json
schema-error	/epcisBody/eventList/0	must have required property 'action'
schema-error	/epcisBody/eventList/0	must match "then" schema
schema-error	/	must match "then" schema
invalid	errors=3
$ echo $?
1

$ npx epcis.dev frobnicate
error	code=USAGE	message=unknown verb "frobnicate"	hint=run `npx epcis.dev` with no arguments for the verb map
$ echo $?
2

$ npx epcis.dev validate no-such-file.json
error	code=NOT_FOUND	message=cannot read document: ENOENT: no such file or directory, open 'no-such-file.json'
$ echo $?
3

The verb table and exit taxonomy above are additionally diffed against the shipped AGENTS.md by the catalog's drift check — the run for this page reported drift: none — aligned.

We answer in writing. We take at most five conversations a month, only when you ask for one, and only after you already have the written read.