--json gives a single JSON object on stdout, errors are a JSON envelope on stderr, and exit codes are a stable contract.
Branch on exit codes, parse only JSON
--jsonon every call. Human output is not a stable interface — its wording and layout can change between releases. Errors arrive on stderr as{"error": {"code": "...", "message": "...", "hint": "..."}}(hintonly when present); all fields are snake_case.- Exit codes are the contract, not output text:
0success,2bad input,3auth,4API error,5timeout. The full table is on CLI usage. -ofor artifact capture. It writes the payload to the file and suppresses stdout entirely, so nothing competes with the file and output limits can’t truncate JSON mid-parse. Upload the file as a CI artifact, parse it withjq.
Configuration precedence
Resolution order, highest first:
The general rule is flag over env over config file over built-in default. In CI, prefer a masked
CAESAR_API_KEY secret over the config file — nothing to provision on disk, and caesar-search auth status --json will confirm key_source is env.
Let one layer own retries
By default the CLI retries HTTP 429 and 5xx up to 3 times (4 attempts total) with exponential backoff capped at 8 seconds. Caesar rate limits useX-RateLimit-Reset; if a numeric Retry-After header is present, the CLI honors it. If your scheduler or workflow engine already handles retries, disable the CLI’s so attempts aren’t multiplied:
--no-retry, a 429 or 5xx fails immediately with exit 4 and the error envelope on stderr — your outer retry policy takes it from there.
The api escape hatch
caesar-search api <method> <path> makes an authenticated raw call against the API — same key resolution, retries, and timeout — for endpoints the CLI doesn’t wrap:
GET, POST, PUT, PATCH, DELETE. The path must start with /. --input <file> (or --input - for stdin) supplies a JSON body. Output is always JSON — api ignores --json — and still honors -o. The endpoint catalog lives in the API reference.
Pin versions; check for drift
Auto-updating mid-pipeline makes builds unreproducible. Instead:- Pin the CLI in CI:
npm install -g caesar-search-cli@0.2.0, or fetch a specific release archive and verify it againstchecksums.txt. - Detect drift with the read-only check and surface it — don’t act on it automatically:
- Upgrade deliberately with
caesar-search update; it picks the right channel (npm, brew, standalone). Nevernpm update -gorbrew upgradeby hand.
update --check works on every channel, including source (dev) builds. Only the actual update refuses on dev builds (exit 2).For agents
- Always pass
--json; parse stdout only. Errors are a JSON envelope on stderr. - Branch on exit codes (
0/2/3/4/5), never on output text. - Prefer
-o /tmp/<name>.jsonthencatthe file —-osuppresses stdout so harness output limits can’t truncate JSON. - Exit 3 means auth: set
CAESAR_API_KEYor runcaesar-search auth loginbefore retrying. - Pass
--no-retryonly when your own loop handles retries; otherwise let the CLI back off.