xschema

Adapter Protocol

How adapters communicate with the xschema CLI

Adapters are standalone CLIs that communicate with the xschema CLI via stdin/stdout JSON. This page documents the protocol specification.

Overview

xschema CLI --[JSON array]--> stdin --> adapter --> stdout --[JSON array]--> xschema CLI

The CLI handles all preprocessing before calling adapters:

CLI handlesAdapter handles
Config discoveryParse IR to code
Schema fetchingRender validation library syntax
$ref resolutionGenerate import statements
Draft normalizationReturn type expressions
Bundling $defs
Validation against meta-schema

By the time an adapter receives a schema, it's:

  • Normalized to a single draft (2020-12)
  • Self-contained (all $refs point to local $defs)
  • Already validated against the meta-schema

You probably don't need the details below unless you're building an adapter or debugging. But if you want to know what happens under the hood, here it is.

Input Format

The CLI sends a JSON array of objects with the following fields:

FieldTypeDescription
namespacestringLogical grouping from the config file. Defaults to filename without extension.
idstringSchema identifier, unique within namespace.
varNamestringSafe variable name derived from namespace + id.
schemaobjectThe JSON Schema to convert. Already bundled and normalized to draft 2020-12.

Example:

[
  {
    "namespace": "user",
    "id": "Profile",
    "varName": "userProfile",
    "schema": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "age": { "type": "integer", "minimum": 0 }
      },
      "required": ["name"]
    }
  }
]

Output Format

Adapters return a JSON array of objects with the following fields:

FieldTypeRequiredDescription
namespacestringyesEcho back from input.
idstringyesEcho back from input.
varNamestringyesEcho back from input.
importsstring[]yesImport statements needed by the generated code.
schemastringone of schema/typeThe generated validator code.
typestringone of schema/typeType expression for the schema.
validatestringnoStandalone validation function.
validationImportsstring[]noImports needed by validation function.

Example:

[
  {
    "namespace": "user",
    "id": "Profile",
    "varName": "userProfile",
    "imports": ["import { z } from \"zod\""],
    "schema": "z.object({ name: z.string(), age: z.number().int().min(0).optional() })",
    "type": "z.infer<typeof userProfile>"
  }
]

What Adapters Never See

Unresolved References

The CLI resolves all $ref and embeds definitions in $defs. Adapters never receive external references—only local #/$defs/... refs pointing to definitions within the same schema.

Old Draft Syntax

All schemas are normalized to draft 2020-12. Adapters don't need to handle:

  • definitions (converted to $defs)
  • items as array (converted to prefixItems)
  • additionalItems (converted to items)
  • Boolean exclusiveMinimum/exclusiveMaximum (converted to numeric)

Dynamic Features

The CLI blocks schemas using features that can't be statically compiled:

  • $dynamicRef / $dynamicAnchor
  • $recursiveRef / $recursiveAnchor

Error Handling

Adapters should write errors to stderr. The CLI captures stderr and displays it to users.

For unrecoverable errors, exit with a non-zero status code.

See Also

On this page