omi-cli is built so an LLM-driven harness can drive it without a wrapper
layer. This page documents the stable contract.
The JSON contract
Pass--json (a global flag, before the subcommand) and the CLI behaves
like a strict tool:
- stdout receives a single JSON document and only a JSON document. No spinners, no progress messages, no decorative output.
- stderr receives any error as a JSON object:
{"error": "...", "detail": "..."}. - exit code signals what happened.
Exit codes
| Code | Meaning |
|---|---|
0 | Success. |
1 | Usage error — bad flag, missing arg, validation rejection. |
2 | Auth error — no creds, expired token, insufficient scope. |
3 | Server error — 5xx after retries exhausted, or connection failure. |
4 | Rate limited — 429 after retries exhausted. detail includes the wait. |
5 | Not found — 404, or client-side scan came up empty. |
Authentication: API key vs browser OAuth
The CLI supports both — but for agents specifically, the API-key path is almost always the right call:| Need | Use this |
|---|---|
| Headless / CI / container runtime | OMI_API_KEY env var |
| Long-running unattended automation | API key |
| Scoped permissions | API key (granular scopes) |
| Interactive use by a human | omi auth login --browser |
omi auth login so a malformed value still fails fast with exit 1.
Retry behavior
Transient failures are retried automatically before the CLI surfaces an error:- 5xx — exponential backoff with jitter (initial 0.5s, cap 8s).
- 429 — honors the server’s
Retry-Afterheader when present (capped at 60s so a misconfigured upstream can’t pin your agent forever); falls back to jitter otherwise. TheRetry-Aftercap means a 429 with a one-hour hint becomes a one-minute wait — your agent gets exit4quickly enough to decide whether to back off itself. - Transport errors (DNS failures, dropped TCP) — retried up to 4 attempts.
detail field for rate-limit errors looks like:
dev:conversations, dev:memories, dev:memories_batch)
matches the backend’s rate-limit policy IDs so you can map them to your own
backoff strategies.
Worked example: Python harness
Handling rate limits in your harness
Tips
- One JSON document per invocation. Don’t try to stream — the CLI doesn’t emit incremental output. Run it again for the next page.
- Use
--profileto isolate environments. A staging profile + a prod profile saves you from accidentally writing to prod with a test script. - Use
--api-base http://localhost:8080for local backend testing. --verboseis safe in JSON mode. Debug output goes to stderr, stdout stays valid JSON.- Pipe stdin with
--text -foromi conversation create— handy when the content is generated by another tool and you don’t want to shell-escape it.