Extend CLI
Authentication
extend whoami shows the workspace, environment, and credential in effect. Two credential sources:
export EXTEND_API_KEY=sk_xxx # API key: scripts, CI, agents
extend login # browser OAuth: interactive use
A stored extend login session is used automatically when no API key resolves; an API key always takes precedence. If neither is configured, ask the user to run extend login or supply EXTEND_API_KEY - never invent a key.
export EXTEND_REGION=us|eu # optional, default us
export EXTEND_WORKSPACE_ID=ws_xxx # required only for org-scoped API keys
Per-call equivalents: --region eu, --workspace ws_xxx. For API-version pinning or EXTEND_BASE_URL, run extend help auth.
Pick the right action
| Need | Command |
|---|---|
| Run extraction on a document | extend extract <input> |
| Parse a document into structured text | extend parse <input> |
| Classify a document into a configured category | extend classify <input> |
| Split a multi-document PDF into segments | extend split <input> |
| Fill a PDF form using a schema with values | extend edit <input> |
| Detect form fields and scaffold an edit schema | extend detect-form <input> |
| Start a workflow run on a document | extend workflows run <input> |
<input> is a local file path (auto-uploaded), a file_xxx ID, or an https:// URL. For batches of up to 1,000 inputs, use <verb> batch or workflows run batch.
Every action verb that needs a processor takes --using <id> - the ID prefix tells you the type: ex_* (extractors), cl_* (classifiers), spl_* (splitters), workflow_* (workflows). parse and detect-form run alone (no processor); edit takes --instructions (free-form prose).
When this skill is active
- Documents come from disk, not from messages. When the user references a document ("this contract", "these invoices", "the PDF") without giving a path, glance at the current working directory for matching files (
*.pdf,*.png,*.jpg,*.tif) before asking. Real users say "this PDF" when there's exactly one in cwd. - File uploads always go through
extend files upload. Never substitute a host-tool File API (e.g. an inline file upload tool that returns its ownfile_xxxID). The skill's file IDs are only legitimate when produced byextend files uploador returned in anotherextendresponse. - Run IDs (
exr_/pr_/clr_/splr_/edr_/workflow_run_) are Extend's, not the host's. When the user mentions one, reach for the typed runs commands (extend <verb> runs get|watch|cancel) - not a host-tool task tracker. - "OCR" alone is ambiguous; the user's intent disambiguates. If they want specific values out (totals, line items, dates, names) →
extractwith a configured extractor. If they want raw text or markdown of the page →parse. "OCR this receipt and grab the total" isextract, notparse.
Wait, async, watch
Action verbs (extract/classify/parse/split/edit) wait by default for terminal state and print the result. Pass --wait=false to return the run ID immediately.
extend workflows run is async by default because workflow runs can take minutes to hours. Pass --wait to block on it.
Run inspection is typed per verb; the ID prefix names the owner (exr_ extract, pr_ parse, clr_ classify, splr_ split, edr_ edit, sgr_ detect-form, workflow_run_ workflows):
extend extract runs watch exr_xxx
A wrong-type ID fails fast, naming the right command. Use --exit-status to gate downstream scripts on success:
extend extract runs watch exr_xxx --exit-status && downstream-script.sh
To inspect state without polling: extend <verb> runs get <id>.
Run-type quirks (the things that defy reasonable assumptions):
- Edit runs (
edr_*) are not listable; the API has noLIST /edit_runs. - Parse and edit runs have no cancel command; other run types support best-effort cancel.
- Form detection runs (
sgr_*) support only get and watch. - Workflow batches have no GET endpoint (hence no
workflows batchescommands); track them withextend workflows runs list --batch <id>.
For the per-command wait/profile/failure-status table: extend help lifecycle.
Pagination
List commands return one page by default. Pass --max N to fetch up to N total results - the CLI auto-paginates internally and never makes you handle page tokens:
extend extract runs list --status FAILED --max 100
Use --all only when you genuinely want every result (scripts, not agents). Power users can still cursor explicitly with --page-token.
--jq <expr> filters JSON output before rendering, but cannot combine with -o markdown (markdown is not JSON). Use -o json --jq '...' and select the markdown chunk paths instead.
Common workflows
Stand up an extractor and run it
Author the extractor config. Use a JSON Schema root object; make primitive fields nullable ("type": ["string", "null"]); use clear field names/descriptions; use arrays for repeated rows; use "extend:type" for date/currency/signature fields. Currency fields must be objects with amount and iso_4217_currency_code, not primitive numbers. If extraction misses a value, inspect parse output before over-tuning the schema.
Create the extractor draft from the config body:
extend extractors create --from-file extractor.json --name "Q3 invoices"Returns a new
ex_xxxID. The draft is editable but not yet deployed.Iterate on the draft as needed:
extend extractors update ex_xxx --from-file patch.jsonPublish version 1.0 once the draft is solid:
extend extractors versions create ex_xxx --release-type majorRun extraction against a document:
extend extract invoice.pdf --using ex_xxx
Create, deploy, and run a workflow
Create a workflow draft and capture its ID:
WORKFLOW=$(extend workflows create --from-file '{"name":"Invoice workflow"}' \ --jq '.id' -o raw)The draft is editable. It is not runnable until you deploy a version.
Author the step graph in workflow-steps.json, then update the draft:
extend workflows update "$WORKFLOW" --from-file workflow-steps.jsonEvery graph starts TRIGGER -> PARSE. EXTRACT steps reference an extractor by id and version. CLASSIFY/SPLIT routes use classificationId values and cannot use version "latest"; pin semver or use "draft".
Deploy the draft as an immutable named version:
extend workflows versions create "$WORKFLOW" --name v1Run it asynchronously, or add --wait to block until terminal:
RUN=$(extend workflows run invoice.pdf --using "$WORKFLOW" --version v1 -o id) extend workflows runs watch "$RUN"
Process a folder of inputs and inspect failures
Submit all inputs in one batch and capture the batch ID:
BATCH=$(extend extract batch *.pdf --using ex_xxx --jq '.id' -o raw)Wait for the batch to finish; gate downstream work on success:
extend extract batches watch "$BATCH" --exit-status || echo "batch failed"List runs that failed (or any other status) for inspection:
extend extract runs list --batch "$BATCH" --status FAILED -o jsonPull a specific failed run's full payload:
extend extract runs get exr_yyy -o json
Configure a webhook for workflow completions
Create the receiving endpoint and capture the signing secret (returned only once - store it):
extend webhooks endpoints create --url https://x.com/hook \ --name prod \ --events workflow_run.completed,workflow_run.failed -o json \ | jq -r '.signingSecret' > webhook.secretBind the endpoint to a specific workflow:
extend webhooks subscriptions create \ --endpoint whe_xxx --resource workflow_yyy \ --events workflow_run.completed,workflow_run.failedIn your receiver, verify each incoming payload before trusting it:
extend webhooks verify \ --signature "$X_EXTEND_REQUEST_SIGNATURE" \ --timestamp "$X_EXTEND_REQUEST_TIMESTAMP" \ --secret "$(cat webhook.secret)" \ --body-file payload.json
Fill a PDF form
Simple fills: pass values inline as --instructions and auto-download
the filled PDF. The server detects form fields and applies the prose:
extend edit form.pdf \
--instructions "name is Acme Corp; date is 2026-04-15" \
--output-file filled.pdf
Structured fills (when you already have a populated schema, or want a
repeatable shape): scaffold the schema once, populate values on each
field per the generated shape (extend_edit:value for explicit values;
extend_edit:image for PNG/JPEG signature images), and then run
edit --schema:
extend detect-form form.pdf --jq '.output.schema' -o json > schema.json
# populate values on each field per the generated shape, then:
extend edit form.pdf --schema schema.json --output-file filled.pdf
Combine both for fills that need conditional or formatting guidance the schema cannot express:
extend edit form.pdf --schema schema.json \
--instructions "format dates as MM/DD/YYYY; leave spouse blank if single"
Without --output-file, the filled PDF stays on the server; fetch later
with extend files download <file-id>. If you use the response's
output.editedFile.presignedUrl directly, download it promptly; it expires
after 15 minutes.
Fill a PDF form from values in another document
When the values live in a source document (e.g. fill a 1040 from a W-2):
Extract or parse the source to surface the values you need:
extend parse w2.pdf -o markdown > w2-content.md # or, with a configured extractor: extend extract w2.pdf --using ex_xxx -o json > w2-values.jsonFill the target form with those values via
--instructions,--schema, or both - see "Fill a PDF form" above. Make sure the document you pass toextend editis the target (the form), not the source (the document you read values from).
Iterate an extractor against an evaluation set
Define an evaluation set scoped to the extractor:
extend evaluations create \ --from-file '{"name":"Q3 truth","entityId":"ex_xxx"}'Add ground-truth items in bulk:
extend evaluations items create evs_yyy --from-file items.jsonEach item is
{fileId, expectedOutput}; the response wraps them in{evaluationSetItems: [...]}.Iterate on the extractor draft, then publish a new version (
extend extractors versions createas in workflow 1).Trigger an evaluation run (e.g. against the new version) and capture its ID:
extend evaluations runs create evs_yyy --entity ex_xxx --entity-version 2.0Runs are async; poll for per-item accuracy and metrics once it finishes:
extend evaluations runs get esr_zzz -o json
Command reference
One line per command - invocation plus a summary. Run extend <command> --help for flags, examples, and per-command gotchas.
Action verbs
extend extract <input>- Run extraction on a document.extend extract batch <input>...- Run extraction on up to 1,000 files in one batch.extend extract runs get <run-id>- Fetch a single extract run by ID.extend extract runs list- List extract runs with filters.extend extract runs watch <run-id>- Poll an extract run until it reaches a terminal state.extend extract runs cancel <run-id>- Cancel an extract run by ID.extend extract runs delete <run-id>- Delete an extract run record.extend extract batches get <batch-id>- Show one extract batch run by ID.extend extract batches watch <batch-id>- Poll an extract batch until it reaches a terminal state.extend parse <input>- Parse a document into structured text.extend parse batch <input>...- Parse up to 1,000 files in one batch.extend parse runs get <run-id>- Fetch a single parse run by ID.extend parse runs list- List parse runs with filters.extend parse runs watch <run-id>- Poll a parse run until it reaches a terminal state.extend parse runs delete <run-id>- Delete a parse run record.extend parse batches get <batch-id>- Show one parse batch run by ID.extend parse batches watch <batch-id>- Poll a parse batch until it reaches a terminal state.extend classify <input>- Classify a document into a configured category.extend classify batch <input>...- Run classification on up to 1,000 files in one batch.extend classify runs get <run-id>- Fetch a single classify run by ID.extend classify runs list- List classify runs with filters.extend classify runs watch <run-id>- Poll a classify run until it reaches a terminal state.extend classify runs cancel <run-id>- Cancel a classify run by ID.extend classify runs delete <run-id>- Delete a classify run record.extend classify batches get <batch-id>- Show one classify batch run by ID.extend classify batches watch <batch-id>- Poll a classify batch until it reaches a terminal state.extend split <input>- Split a multi-document PDF into segments.extend split batch <input>...- Run splitting on up to 1,000 files in one batch.extend split runs get <run-id>- Fetch a single split run by ID.extend split runs list- List split runs with filters.extend split runs watch <run-id>- Poll a split run until it reaches a terminal state.extend split runs cancel <run-id>- Cancel a split run by ID.extend split runs delete <run-id>- Delete a split run record.extend split batches get <batch-id>- Show one split batch run by ID.extend split batches watch <batch-id>- Poll a split batch until it reaches a terminal state.extend edit <input>- Fill a PDF form using a schema with values.extend edit templates get <template-id>- Fetch a saved edit template by ID.extend edit runs get <run-id>- Fetch a single edit run by ID.extend edit runs watch <run-id>- Poll an edit run until it reaches a terminal state.extend edit runs delete <run-id>- Delete an edit run record.extend detect-form <input>- Detect form fields and scaffold an edit schema.extend detect-form runs get <run-id>- Fetch a single form detection run by ID.extend detect-form runs watch <run-id>- Poll a form detection run until it reaches a terminal state.
Inspection
extend files upload <path>- Upload a local file and print its file_id.extend files list- List uploaded files.extend files get <file-id>- Show metadata for a file (with presigned download URL).extend files delete <file-id>- Delete an uploaded file.extend files download <file-id>- Download a file to local disk (or stdout with -O -).extend download <id>- Download file artifacts produced by a run, or fetch a file by ID.
Processor resources
Extractors, classifiers, splitters, and workflows share an identical seven-command shape. Substitute <plural> and the corresponding ID prefix (ex_, cl_, spl_, and workflow_):
extend <plural> list- Page through processors of this type.extend <plural> get <id>- Show one processor.extend <plural> create --from-file body.json- New draft.extend <plural> update <id> --from-file patch.json- Edit the draft. Deployed versions are immutable; the draft is the only mutable surface.extend <plural> versions list <id>- List published versions.extend <plural> versions get <id> <version|draft>- Show one version (or the draft).extend <plural> versions create <id> --release-type major|minor- Publish the draft as a new version.
Workflows differ: versions create uses --name <deploy-name> instead of --release-type. The deployed name is what extend workflows run --version references.
Workflows also expose runs: extend workflows run <input> / run batch start runs; extend workflows runs get|list|watch|cancel|delete|update inspect and control them (the action verbs' runs shape, plus update).
Webhooks
extend webhooks endpoints list- List webhook endpoints.extend webhooks endpoints get <endpoint-id>- Show one webhook endpoint.extend webhooks endpoints create- Create a webhook endpoint.extend webhooks endpoints update <endpoint-id>- Update mutable fields on a webhook endpoint.extend webhooks endpoints delete <endpoint-id>- Delete a webhook endpoint.extend webhooks subscriptions list- List webhook subscriptions.extend webhooks subscriptions get <subscription-id>- Show one webhook subscription.extend webhooks subscriptions create- Subscribe an endpoint to events for a specific resource.extend webhooks subscriptions update <subscription-id>- Replace the enabled events on a webhook subscription.extend webhooks subscriptions delete <subscription-id>- Delete a webhook subscription.extend webhooks verify- Verify the HMAC-SHA256 signature on a webhook payload.
Evaluations
extend evaluations list- List evaluation sets.extend evaluations get <evaluation-set-id>- Show one evaluation set.extend evaluations create- Create an evaluation set.extend evaluations items list <evaluation-set-id>- List items in an evaluation set.extend evaluations items get <evaluation-set-id> <item-id>- Show one evaluation item.extend evaluations items create <evaluation-set-id>- Add one or more items to an evaluation set (bulk create).extend evaluations items update <evaluation-set-id> <item-id>- Update an evaluation item.extend evaluations items delete <evaluation-set-id> <item-id>- Delete an evaluation item.extend evaluations runs create <evaluation-set-id>- Start an evaluation set run.extend evaluations runs get <run-id>- Show one evaluation run.
When this skill isn't enough
The body above shows the CLI's shape. For depth, use the help system before guessing:
extend <command> --help- every flag, multiple worked examples, and the full per-command gotcha list.extend help auth- Authentication: env vars, regions, workspace, API version. Use on auth errors, when working with org-scoped API keys, or when picking a region.extend help output- Output formats, --jq, color, pagination, per-command defaults. Use when an output format is unexpected or when writing a non-trivial pagination loop.extend help lifecycle- Run lifecycle: sync vs async, polling, exit codes, watching. Use when reasoning about run states, polling profiles, or when--exit-statusshould fail.extend help errors- Error envelope, request_id, retry/backoff, common codes. Use when interpreting an error envelope, picking up arequest_id, or filing a support ticket.
These commands run offline.