CLI
Run Perception's document tools from the shell with the drex command.
drex-cli installs the drex command, which calls https://console.nace.ai from your shell. It is built on the Python SDK and covers Perception's five tools, uploads, jobs and saved schemas, plus drex decide for Drex's decision endpoint — see the CLI's Drex page for that.
pipx install drex-cli # or: uv tool install drex-cli
drex logindrex login asks for a key and checks it against Drex. It then saves the key to ~/.drex/config.toml, readable only by you. DREX_API_KEY and DREX_BASE_URL take precedence over the file.
Sources
Every tool below takes a SOURCE argument, which is any of these:
- An
https://URL. - A local file. It is uploaded to your workspace first.
ws:<workspace_id>/<file_id>, the valuedrex uploadprints.job:<id>, a finished parse job. Use it to reuse the parse instead of parsing again.
drex upload invoice.pdf --path invoices/invoice.pdf
# ws:0f8b7c2e-.../3a91c5...| Command | Flag | What it does |
|---|---|---|
upload FILE | --path PATH | Path in the workspace (default: the file's own name). |
Flags every tool shares
Parse, Split, Classify, Extract and Ground all take these, on top of each tool's own flags below:
| Flag | What it does |
|---|---|
-p, --pages SPEC | 1-based pages to read, e.g. 3 or 1-5,8. Default: all pages. |
--option KEY=VALUE | Any other request field. Repeatable; dotted keys nest (output.formats=markdown), JSON values parse. |
--options JSON | Request fields as a whole JSON object, @FILE, or a path, instead of repeated --option. |
--wait-seconds N | Hold the create open up to N seconds (max 60) to get the result in the same call. |
--idempotency-key KEY | A retry-safe key; the same key and body return the same job, never billed twice. |
--json | Print the raw response JSON (the same as -o json below). |
--timeout SECONDS | Per-request HTTP timeout (default 120). |
Waiting and output
| Flag | What it does |
|---|---|
--async | Print the job id and return at once, without waiting. |
--wait-timeout SECONDS | How long to keep polling for the job client-side (default 60s). The job keeps running past it. |
--watch | Print progress events to stderr while waiting. |
-o, --output {auto,md,json,result,id} | What to print: auto (default) is Markdown for a parse, the result JSON otherwise; md forces Markdown (error if there isn't any); json is the whole job; result is only result; id is just the job id. |
--save PATH | Write the output to this file instead of stdout. |
Status messages go to stderr, so stdout holds only the result; drex parse doc.pdf > doc.md captures only the document. drex exits with 0 on success, 1 when an API call or job fails, and 2 on a usage or configuration error. An error message shows the error type, the code and the request_id. See Errors.
Parse
drex parse https://example.com/report.pdf --pages 1-3 --format markdown,blocks > report.md| Flag | What it does |
|---|---|
--format FORMATS | Comma list of markdown, text, blocks (default markdown). |
--mode {low,medium,high} | Parse quality/effort. |
See Parse.
Split
drex split https://example.com/packet.pdf \
--class invoice:Invoice:"A supplier invoice" \
--class receipt:Receipt:"A payment receipt"| Flag | What it does |
|---|---|
--class ID:LABEL[:DESCRIPTION] | One class. Repeatable; at least one --class or --classes is required. |
--classes JSON | Classes as a JSON array, @FILE, or a path, instead of repeated --class. |
See Split.
Classify
drex classify https://example.com/invoice.pdf \
--class invoice:Invoice:"A supplier invoice" \
--class contract:Contract:"A signed agreement between two parties" \
--granularity pageTakes the same --class / --classes flags as Split, plus:
| Flag | What it does |
|---|---|
--granularity {document,page} | Score the whole file once, or once per page (default document). |
See Classify.
Extract
drex extract https://example.com/invoice.pdf --schema invoice.schema.json| Flag | What it does |
|---|---|
-s, --schema FILE|@FILE|JSON | The fields to extract, as a JSON Schema. Required. |
--instructions TEXT | Extra guidance for filling the declared fields. |
Where invoice.schema.json is:
{
"type": "object",
"properties": {
"invoice_number": { "type": "string" },
"total": { "type": "number" }
},
"required": ["invoice_number", "total"]
}Point it at a finished parse instead to avoid parsing and paying for the document twice:
drex parse https://example.com/invoice.pdf -o id
# 6f1a2b3c-...
drex extract job:6f1a2b3c-... --schema invoice.schema.jsonSee Extract. --schema only takes an inline JSON Schema; using a saved schema's id isn't exposed by this command yet (see Save a reusable extraction schema).
Ground
drex ground https://example.com/report.pdf \
--target "total=1,200.50" \
--target "signer=Jane Smith"| Flag | What it does |
|---|---|
--target ID=TEXT | One quote to find: ID is your own label, TEXT is the quote. Repeatable; at least one --target or --targets is required. |
--targets JSON | Targets as a JSON array, @FILE, or a path, instead of repeated --target. |
See Ground.
List, read and delete jobs
drex jobs --operation parse
drex job <id> --wait
drex file <id> parse-images/<ref> --save page-1.png
drex cancel <id>| Command | Flag | What it does |
|---|---|---|
jobs | --operation {parse,split,classify,extract,ground} | Only jobs of one operation. |
--status {queued,running,succeeded,failed,cancelled} | Only jobs in one status. | |
--limit N | Jobs to show (default 20). | |
--all | Every job, across every page, ignoring --limit. | |
job JOB_ID | --wait | Wait until the job finishes before printing it. |
--wait-timeout, --watch, -o, --save | Same as Waiting and output, used only with --wait. | |
file JOB_ID PATH | --save PATH | Where to write the file (default: its last path segment). PATH is the link from the job's result, or the part after the job id (parse-images/<ref>). |
--link | Print the five-minute signed download link instead of downloading. | |
cancel JOB_ID | — | Cancels a running job and drops it from the list; already-billed work stays charged. |
See Jobs and results.
Save a reusable extraction schema
Save a JSON Schema once, then reuse it across extracts without sending it inline. Saved schemas can't be edited; add a version instead.
drex schema-create invoice --schema invoice.schema.json --description "Invoice header fields"
drex schemas
drex schema <schema_id>
drex schema-version-add <schema_id> --schema invoice-v2.schema.json
drex schema-versions <schema_id>
drex schema-version <schema_id> 2| Command | Flag | What it does |
|---|---|---|
schema-create NAME | -s, --schema FILE|@FILE|JSON | The JSON Schema. Required. |
--description TEXT | An optional description. | |
schema-version-add SCHEMA_ID | -s, --schema FILE|@FILE|JSON | The new version's JSON Schema. Required. |
--name TEXT | Rename the schema; omit to keep its current name. | |
--description TEXT | Omit to keep the current description. | |
schemas, schema-versions SCHEMA_ID | --limit N | Items to show (default 20). |