OE openextract

CLI stdout, stderr, and exit codes

This page is the contract for the openextract command. Successful results go to stdout. Errors, warnings, and progress go to stderr. Exit codes are stable for automation.

Streams

Stream Contents
stdout Successful extraction payloads (json, jsonl, or repr)
stderr error: ... messages, a warning: ... line for partial batch failures, and progress: ... lines when --progress is set

Never parse stderr for successful results. Never treat stdout as empty when exit code 7 is returned — the batch output is still written.

Exit codes

Code Meaning Typical cause
0 Success Single-file or full-batch success
1 Usage / setup error Missing or bad --schema / --model, stdin without --media-type, invalid manifest, invalid concurrency/retry/size/swarm options, unloadable --agent, argparse failures
2 URL fetch error UrlFetchError (network failure, HTTP error, SSRF refusal)
3 Schema validation error SchemaValidationError
4 Model API error ModelError
5 Other extraction error InputTooLargeError and other ExtractionError subclasses
6 Missing provider SDK ProviderNotInstalledError
7 Partial batch failure --continue-on-error with one or more per-item failures
8 Remote agent failure RemoteAgentError from a --agent / --agents HTTP endpoint
130 Interrupted Ctrl-C / SIGINT; outstanding batch work is cancelled
141 Broken pipe stdout closed by the consumer (e.g. head); exits silently

These mappings live in src/openextract/_cli.py and are covered by tests/test_cli.py.

CLI option values are validated before any model call: invalid --max-concurrency, --max-retries, --retry-backoff, --retry-max-backoff, --max-input-bytes, or manifest contents exit 1 without contacting a provider.

Successful single-file output

openextract ./reports/q4.pdf \
  --schema mypkg.schemas:Invoice \
  --model xai:grok-4.3 \
  --output json

Successful batch output

openextract ./invoices/a.pdf ./invoices/b.pdf \
  --schema mypkg.schemas:Invoice \
  --model xai:grok-4.3 \
  --max-concurrency 8

JSONL output for large batches

openextract ./invoices/*.pdf \
  --schema mypkg.schemas:Invoice \
  --model xai:grok-4.3 \
  --output jsonl --continue-on-error

--output jsonl writes one JSON record per line as each input completes, flushed immediately, so large batches emit useful output long before the batch finishes. Records arrive in completion order; index is the zero-based input position, so consumers can reorder or join back to their inputs.

{"index": 1, "input": "./invoices/b.pdf", "result": {"total": 42.0}}
{"index": 0, "input": "./invoices/a.pdf", "error": "...", "error_type": "ModelError"}

Progress reporting

openextract ./invoices/*.pdf \
  --schema mypkg.schemas:Invoice \
  --model xai:grok-4.3 \
  --output jsonl --progress 2>progress.log

--progress writes one line per completed batch item to stderr only:

progress: 3/10 completed (1 failed): ./invoices/c.pdf

stdout stays machine-readable. Progress lines are human-oriented; do not parse them. The flag is a no-op for single-input runs.

Manifest input

openextract --manifest inputs.jsonl \
  --schema mypkg.schemas:Invoice \
  --model xai:grok-4.3 \
  --output jsonl

--manifest FILE reads inputs from a JSONL file instead of positional arguments, so heterogeneous batches can set per-input media types:

{"source": "./invoices/a.pdf", "media_type": "application/pdf", "name": "invoice-a"}
{"source": "https://example.com/report", "media_type": "text/html"}
{"source": "./notes.txt"}

--usage output

Single input:

openextract ./reports/q4.pdf \
  --schema mypkg.schemas:Invoice \
  --model xai:grok-4.3 \
  --usage
{
  "result": { "...": "schema fields" },
  "usage": {
    "input_tokens": 0,
    "output_tokens": 0,
    "total_tokens": 0
  }
}

Batches run through the richer result API and report per-item and aggregate usage:

openextract ./invoices/a.pdf ./invoices/b.pdf \
  --schema mypkg.schemas:Invoice \
  --model xai:grok-4.3 \
  --usage
{
  "results": [
    { "input": "./invoices/a.pdf", "result": { "...": "..." }, "usage": { "...": 0 } },
    { "input": "./invoices/b.pdf", "error": "...", "error_type": "ModelError" }
  ],
  "usage": { "input_tokens": 0, "output_tokens": 0, "total_tokens": 0 }
}

The aggregate sums successful items only. With --output jsonl, usage appears on each success record and in the final summary line instead.

--output json, --output jsonl, and --output repr

Flag Behavior
--output json (default) Pretty-printed JSON (indent=2), buffered until the run finishes. Single-file non-usage results use model_dump_json. Batch arrays are in input order.
--output jsonl One compact JSON record per completed input, written incrementally in completion order.
--output repr Python repr(...) of the same payload object as json.

All formats write only to stdout on success.

Stdin input

cat ./reports/q4.pdf | openextract - \
  --schema mypkg.schemas:Invoice \
  --model xai:grok-4.3 \
  --media-type application/pdf

--continue-on-error partial failures

openextract ./ok.pdf ./missing.pdf \
  --schema mypkg.schemas:Invoice \
  --model xai:grok-4.3 \
  --continue-on-error
{
  "input": "./missing.pdf",
  "error": "...",
  "error_type": "ModelError"
}

Cancellation and broken pipes

Retry policy

--max-retries enables retries for transient model failures only. --retry-backoff controls exponential backoff with up to 25% additive jitter, and --retry-max-backoff caps both calculated delays and provider Retry-After values. Authentication, permission, and invalid-request failures exit immediately with code 4.

Input size limit

--max-input-bytes N sets the maximum bytes loaded for each input. Without the flag, the CLI uses OPENEXTRACT_MAX_INPUT_BYTES or the 50 MiB default. Values must be positive integers. Oversized inputs fail before a model call and exit 5; URL bodies and stdin remain bounded even without a reliable length header.

Swarms and agents

--swarm N runs N copies of one model over a single input. --models a,b runs one agent per model. --reduce folds the outputs: merge (default), vote, or first.

openextract ./invoices/q4.pdf \
  --schema mypkg.schemas:Invoice \
  --models openai:gpt-5,anthropic:claude-opus-4-8 \
  --reduce vote

--agent SPEC extracts with an agent — a directory, a Python file, or module:attribute. --agents SPEC,SPEC runs several. An agent that declares an output_schema makes --schema optional:

openextract ./invoices/q4.pdf --agent ./agents/invoices

Extraction styles

--style direct (default) sends the resolved media to the model in one shot. --style search and --style code are text-only: search gives the model sandboxed file tools (read, regex search, glob), and code lets it write Python against a workspace copy of the document via Pydantic AI Harness. Missing extras exit 6 (ProviderNotInstalledError). Non-text inputs raise ValueError (exit 1).