xeroctl batches
Submit a JSONL file, get a batch id, poll to completion, pull the output. --input-prefix fans one batch out per pre-uploaded file under a stored path. Endpoint slug is non-negotiable; chat completions only today.
Overview
The xeroctl batches command wraps the Batch API
for use from the command line. Every operation requires the
--endpoint <slug> flag.
The typical workflow is:
- Prepare a JSONL file where each line is a single inference request.
- Run
xeroctl batches --endpoint <slug> --input requests.jsonlto upload the file and create the batch in one step. - Poll status with
--wait, or check manually usingxeroctl batches <id> --endpoint <slug>. - Download the output JSONL once the batch completes.
Back to xeroctl CLI overview or the Batch API reference.
JSONL Format
Each line in the input file is a self-contained JSON object representing one inference request. The format mirrors the OpenAI Batch API JSONL specification.
Required Fields
| Field | Type | Description |
|---|---|---|
custom_id |
string | Unique identifier for this request. Echoed back in the output file to correlate results. |
method |
string | HTTP method. Must be "POST". |
url |
string | Target API path, e.g. "/v1/chat/completions" or "/v1/embeddings". |
body |
object | The full request body for the target endpoint. Must include model and the required body fields for that endpoint. |
Example, Chat Completions Batch
{"custom_id": "req-1", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "my-model", "messages": [{"role": "user", "content": "What is the capital of France?"}], "max_tokens": 64}}
{"custom_id": "req-2", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "my-model", "messages": [{"role": "user", "content": "Summarize the Pythagorean theorem."}], "max_tokens": 128}}
{"custom_id": "req-3", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "my-model", "messages": [{"role": "user", "content": "Write a haiku about the ocean."}], "max_tokens": 64}}
xeroctl scope: The xeroctl batches command today only targets /v1/chat/completions. The CLI hardcodes that endpoint on the batch row regardless of the url values inside the JSONL, so embeddings or responses batches submitted via xeroctl will be routed as chat completions and fail. For non-chat batches, submit the batch directly via the Batch API.
Note: Each line must be a complete, valid JSON object. Blank lines are not permitted. The custom_id must be unique within the file. The input file must not exceed 100 MB after upload; larger files upload successfully but fail at batch validation.
Create Batch
Provide an --input path to upload the JSONL file and submit the
batch in a single command. The CLI uploads the file first (printing the file ID),
then creates the batch job.
# Create and return immediately
xeroctl batches --endpoint my-llm --input requests.jsonl
# Create and wait for completion
xeroctl batches --endpoint my-llm --input requests.jsonl --wait
# Attach metadata, one flag per pair
xeroctl batches --endpoint my-llm \
--input requests.jsonl \
--metadata project=finance \
--metadata run_id=batch-2026-04-09
# Attach metadata, multiple pairs after a single --metadata flag
xeroctl batches --endpoint my-llm \
--input requests.jsonl \
--metadata project=finance run_id=batch-2026-04-09
# Preview without uploading or creating
xeroctl batches --endpoint my-llm --input requests.jsonl --dry-run
Create Options
| Option | Description |
|---|---|
--input <file.jsonl> |
Path to the JSONL input file. Triggers batch creation. |
--input-prefix <path> |
Resolve already-uploaded files under this relative_path prefix and create one batch per match. See the next section. |
--metadata <k=v> [<k=v> ...] |
Attach metadata. Either repeat the flag once per pair, or pass multiple key=value tokens after a single --metadata (parsed up to the next flag). Serialized metadata must not exceed 16 KB; oversized values return HTTP 400 "Metadata exceeds maximum size of 16KB". |
--wait |
After creating, poll until the batch reaches a terminal state. Can also be combined with an existing batch ID. |
Create Batches From Prefix
Use --input-prefix <path> to fan out one batch per already-uploaded file
whose relative_path begins with the given prefix. The CLI queries the
Files API for files with purpose=batch matching the
prefix and submits a batch for each. This avoids re-uploading inputs that were staged
earlier through xeroctl files upload.
# Submit one batch per file under prefix "experiments/2026-05/"
xeroctl batches --endpoint my-llm --input-prefix experiments/2026-05/
# Combine with metadata and wait for terminal state on each batch
xeroctl batches --endpoint my-llm \
--input-prefix experiments/2026-05/ \
--metadata run_id=may-sweep \
--wait
# Preview which files would be submitted
xeroctl batches --endpoint my-llm --input-prefix experiments/2026-05/ --dry-run
The Files API list call caps at 100 results per page, so chunk the prefix if more
files need to be submitted in a single invocation. --input-prefix cannot
be combined with a positional batch ID, and is mutually exclusive with
--input, --cancel, --download, and
--errors. Each per-file submission prints [OK] <relative_path> -> <batch_id>
or [FAIL] <relative_path> (<error>); the command exits non-zero if any
submission failed.
List Batches
List all batch jobs for the specified endpoint. The table shows ID, Status, Total requests, Completed, Failed, and Created time.
# List batches for an endpoint
xeroctl batches --endpoint my-llm
# Limit results
xeroctl batches --endpoint my-llm --limit 20
# Paginate using a cursor (batch ID to start after)
xeroctl batches --endpoint my-llm --after batch_abc123
# JSON output
xeroctl batches --endpoint my-llm -o json
When more results exist beyond the current page, a hint is printed showing the
last batch ID to use as the --after cursor. List sort order is not
guaranteed by this page; do not assume .data[0] is the most-recent
batch, match by id or created_at in callers.
Get Batch
Show full details for a specific batch job.
xeroctl batches batch_abc123 --endpoint my-llm
# JSON output
xeroctl batches batch_abc123 --endpoint my-llm -o json
The detail view includes: ID, Status, Endpoint, Input File ID, Output File ID, Error File ID, Completion Window, Total / Completed / Failed request counts, Created, Started At, Expires, Completed At, Cancelled At, and any metadata.
Cancel Batch
Cancel an in-progress batch. The batch transitions to cancelling
and then cancelled. Requests that were already processed will
have results in the partial output file.
# Cancel with confirmation
xeroctl batches batch_abc123 --endpoint my-llm --cancel
# Preview without cancelling
xeroctl batches batch_abc123 --endpoint my-llm --cancel --dry-run
Download Output
Download the output JSONL file from a completed batch. The output file contains
one result object per successful request, keyed by custom_id.
# Download to default filename (<batch-id>-output.jsonl)
xeroctl batches batch_abc123 --endpoint my-llm --download
# Specify output path (long-only flag; -o is the global format selector)
xeroctl batches batch_abc123 --endpoint my-llm --download --output-file results.jsonl
If no output file is available (the batch has not yet completed, or all requests failed), an error message is printed along with the current batch status.
Download Errors
Download the error JSONL file for a batch. The error file contains one entry
per failed request, including the custom_id and error details.
# Download error file to default filename (<batch-id>-errors.jsonl)
xeroctl batches batch_abc123 --endpoint my-llm --errors
# Specify output path (long-only flag; -o is the global format selector)
xeroctl batches batch_abc123 --endpoint my-llm --errors --output-file batch-errors.jsonl
Wait for Completion
Poll a batch every 2 seconds until it reaches a terminal state:
completed, failed, cancelled, or
expired. An inline progress bar is printed when request counts
are available.
# Wait on an existing batch
xeroctl batches batch_abc123 --endpoint my-llm --wait
# Create and immediately wait
xeroctl batches --endpoint my-llm --input requests.jsonl --wait
On completion, the terminal status, request counts, and file IDs are printed.
Use -o json to receive a machine-readable summary on completion.
Options Reference
Every flag xeroctl batches accepts, role-grouped. The Role column tells you why it exists; the Requires Batch ID column tells you when it applies.
Mutual exclusivity: --input, --input-prefix, --cancel, --download, and --errors are action flags. Pass exactly one per invocation. --input-prefix additionally cannot be combined with a positional batch ID. --wait is the only action flag that composes (with --input or with a batch ID).
| Option | Role | Requires Batch ID | Description |
|---|---|---|---|
--endpoint <slug> |
required | n/a | Endpoint slug. Required for every batch operation. |
--input <file.jsonl> |
action | No | Upload and create a new batch from the given JSONL file. |
--input-prefix <path> |
action | No (cannot be combined with a batch ID) | Resolve already-uploaded files under the given relative_path prefix and submit one batch per match. |
--cancel |
action | Yes | Cancel a running batch. |
--download |
action | Yes | Download the output JSONL file. |
--errors |
action | Yes | Download the error JSONL file. |
--wait |
action | Yes (or use with --input) | Poll until the batch reaches a terminal state. Composes with --input. |
--dry-run |
modifier | Depends on action | Preview the action without uploading, creating, or cancelling. |
--output-file <path> |
modifier | Yes | Destination file path for --download or --errors. Defaults to <batch-id>-output.jsonl or <batch-id>-errors.jsonl. Long-only; -o is reserved for the global format selector (-o json, -o table, ...). |
--metadata <k=v> [<k=v> ...] |
modifier | No (creates only) | Metadata to attach when creating a batch. Repeat once per pair, or pass multiple key=value tokens after a single --metadata (parsed up to the next flag). Serialized metadata must not exceed 16 KB. |
--limit <n> |
modifier | No (list only) | Maximum number of results when listing. |
--after <id> |
modifier | No (list only) | Pagination cursor: batch ID to start results after. |
Common Errors
Real messages the CLI surfaces, what they mean, and what to change.
| Message | Meaning | Fix |
|---|---|---|
HTTP 400 Metadata exceeds maximum size of 16KB |
Serialized JSON of all --metadata key=value pairs exceeds the 16 KB cap. |
Drop the largest value, or move bulky context into the request body inside the JSONL. |
HTTP 413 Input file exceeds 100 MB |
Upload succeeded but batch validation rejects files larger than 100 MB. | Split the JSONL and submit multiple batches; combine results with --output-file + jq. |
[FAIL] <relative_path> (no files found for prefix) |
--input-prefix matched zero files with purpose=batch. |
Run xeroctl files --purpose batch to confirm the prefix; the Files list call caps at 100 results per page. |
Output file not yet available |
Batch is not in a terminal state, or every request failed and only the error file exists. | Use --wait first, then --download; pull failed-request detail with --errors. |
--input-prefix cannot be combined with --input / --cancel / --download / --errors |
Two action flags passed in one invocation. | Pick exactly one; see the mutual-exclusivity callout above. |
Examples
End-to-End Batch Workflow
#!/bin/bash
ENDPOINT="my-llm"
INPUT="requests.jsonl"
# Create batch and wait for it to finish
xeroctl batches --endpoint "$ENDPOINT" --input "$INPUT" --wait
# Retrieve the batch ID from the list
BATCH_ID=$(xeroctl batches --endpoint "$ENDPOINT" -o json \
| jq -r '.data[0].id')
# Download output
xeroctl batches "$BATCH_ID" --endpoint "$ENDPOINT" --download --output-file output.jsonl
# Download any errors
xeroctl batches "$BATCH_ID" --endpoint "$ENDPOINT" --errors --output-file errors.jsonl
Monitor an Existing Batch
# Check current status
xeroctl batches batch_abc123 --endpoint my-llm
# Block until done
xeroctl batches batch_abc123 --endpoint my-llm --wait
Create with Metadata Tags
xeroctl batches \
--endpoint my-llm \
--input prompts.jsonl \
--metadata env=production \
--metadata team=data-science \
--metadata version=1.2.0