Skip to content
ocx
install

Machine Interface

The machine interface is everything a program observes when it calls ocx: the --format json documents, the error document, the exit code, the OCX_* variables and the command grammar. Per-command fields live in the command reference and variables in the environment reference.

Every document --format json writes has one shape at the top level.

RuleMeaning
A root is an objectNo command writes a bare array, string or number
schema_version comes firstAn integer, the version of that root’s shape
A list root is {"schema_version": …, "items": […]}Nested collections inside a root use a plural noun. The key entries is not used
Absent means unsetAn optional field with no value is left out, and null never stands for “unset”. Publisher-supplied JSON, such as package metadata, passes through unchanged and may contain null
Unions carry a type keyAn object that takes one of several shapes names its shape in type, and the other fields belong to that shape
Keys and enum values are snake_caseNo other casing appears in a root
Stdout holds one documentExactly one pretty-printed JSON document per invocation, including after a usage error. --quiet suppresses success reports only
{
"schema_version": 1,
"items": []
}

Two kinds of version exist, and both are plain integers.

VersionWhere it appearsWhat it names
schema_versionFirst key of every report root and of the error documentThe shape of that one document
contractocx --format json versionThe current version of every document and command, in one object
  • contract.errors: the error document’s schema_version.
  • contract.reports: each report root’s schema_version, keyed by root name.
  • contract.commands: each command’s grammar version, keyed by the command path with spaces, such as package sign.
  • A version increases on any of these breaks:
    • a property, root, enum value or union variant is removed or renamed
    • a property changes type
    • a flag, argument, output mode or exit code is removed or renumbered
    • a value keeps its name but changes meaning
  • A version does not change for additions: a new property, root, enum value, union variant, command or flag.
  • A contract ledger in the repository records each break for tooling, and a gate refuses a break missing from the ledger or the version bump. What changed in a release is stated in the changelog.

Enum values and union variants are open: a later release of ocx may emit a value the program has never seen. The published schemas encode this, so a validator accepts an unknown string or an unknown type.

CaseRule
An unknown valueLegal. It is not an error in the document
An unknown statusNot success. Success checks compare against the known success values and fail closed
An unknown union variantIt names itself in type. A program skips an object whose type it does not know and never guesses
statusA named enum on every report that has one. A dry run is a status value, not a separate flag in the document

Every invocation ends in one of three outcomes. The exit code decides which one, and stdout carries the document that goes with it.

OutcomeExit codeStdout
Report0The report root
Report, then failNon-zeroThe report root. No error document follows it
ErrorNon-zeroThe error document
  • A command can finish its work, write its report and still exit non-zero when part of the work failed. A batch with one missing package writes the full report and exits with the code of the failure that decided the outcome.
  • Stdout is never two concatenated JSON values.

A command that fails without writing a report prints one error document on stdout. A refused command line (exit 64) and an invalid OCX_* variable or unreadable config file (exit 78) each print one before any command runs.

{
"schema_version": 1,
"command": "package sign",
"exit_code": 80,
"error": {
"kind": "auth_error",
"detail": "oidc_token_rejected",
"message": "Fulcio rejected OIDC token: issuer not in trust root",
"context": { "identifier": "ocx.sh/cmake:3.28" }
}
}
FieldTypeDescription
schema_versionintegerVersion of the error document’s shape
commandstringThe command’s words, such as package sign. Empty when the command line names no command
exit_codeintegerThe process exit code, the same value the process exits with
error.kindstringThe coarse category, such as not_found, auth_error or usage_error
error.detailstringA stable slug naming the specific cause. Omitted when the failure has no slug
error.messagestringHuman-readable text. Not stable: never match on it
error.contextobjectThe packages the failure is about, as identifier, source or target. Always present, and empty when the failure names no package
  • A detail slug is stable once a release emits it, and a command’s reference entry lists the slugs that command produces.
  • A failure with no slug, such as a plain I/O error, carries only error.kind.
  • A --format json or --json after a bare -- belongs to the child command and asks for nothing.
  • Under --quiet, a failure still prints the error document.
  • A child run by ocx exec is the one case where the exit code is not ocx’s own: the child’s code is forwarded unchanged.

See exit codes.

Each document is described by a JSON Schema published on this site, so a program can validate output or generate types from it.

DocumentSchema
Success reports, every rootreports
Error documenterrors
config.toml, any tierconfig
ocx.toml, project fileproject
ocx.lock, machine-generatedproject-lock
metadata.json, packagemetadata
Patch descriptor (ocx patch publish --descriptor)patch
Execution record ([records] sink)execution-record
  • Editor integration: set $schema to the metadata schema URL at the top of metadata.json. Editors that read JSON Schema (taplo, yaml-language-server, VS Code, Zed) use these for completion and validation.
  • ocx init writes the project schema as a #:schema directive on the first line of every ocx.toml it generates.
  • The project-lock schema carries a top-level $comment marking ocx.lock machine-generated.
  • The reports schema lists each root as a wrapper with schema_version pinned to a constant.
  • The schemas allow unknown properties and encode open values as strings that carry a documented list of known values.
  • Generating locally: task schema:generate writes the schemas to website/src/public/schemas/.
  • Validation: uvx check-jsonschema --schemafile https://ocx.sh/schemas/metadata/v1.json metadata.json (check-jsonschema).

See the command reference for flags, arguments and output modes, and the environment reference for the OCX_* variables.