Guide 10
CLI
Run the whole list, table, enrich and push flow from a terminal (early access).
Last updated from API version 2026-10-06 at (live spec, refreshed hourly). openapi.json
The owlbound CLI runs the whole flow from a terminal: build a list into a table, enrich a column under a hard cap, push the rows. It only calls the public API v1.
Early access
The CLI is in early access and not published to npm yet. Contact us to get it; this page will show the install command once it ships. Everything it does is also available through the API and MCP.
Log in
owlbound auth login # hidden prompt for the owl_sk_ key
pbpaste | owlbound auth login --key -
owlbound auth status # workspace, scopes, API version
owlbound auth logoutThe key is checked with GET /me and stored in the macOS Keychain or the Linux Secret Service when available, else in ~/.config/owlbound/credentials (mode 0600). It is never printed. OWLBOUND_API_KEY always wins (CI). --api-version <date> sends Owlbound-Version.
How it behaves
- Dry run by default. Anything that spends or writes prints a plan first and runs only with
--apply.--apply --plan <planId>runs exactly what you reviewed; if anything changed it exits 10 and prints the new plan. - Safe retries. Every write sends an
Idempotency-Key, printed first, reused on automatic retries, and echoed in--jsonoutput. - Bounded waits.
--wait <seconds>polls and stops at the bound with exit 12. It never waits forever. - Stable output. Tables by default,
--jsoneverywhere,--quietfor ids only.
The whole flow
1. Build a list into a new table
owlbound lists sales-nav \
--url 'https://www.linkedin.com/sales/search/people?query=...' \
--max-results 200 --table new:'FR SaaS heads of sales' --max-credits 700
# then run exactly that plan, and wait (bounded)
owlbound lists sales-nav --url '...' --max-results 200 \
--table new:'FR SaaS heads of sales' --max-credits 700 \
--apply --plan plan_... --wait 9002. Enrich a column under a hard cap
owlbound tables columns add tbl_... --name "Work email" --type enrichment \
--config '{"provider":"blitzapi","field":"workEmail","inputs":{"linkedinUrl":"linkedinUrl"}}'
owlbound tables run tbl_... --column col_... # estimate only
owlbound tables run tbl_... --column col_... --apply --max-credits 600 --wait 9003. Push to contacts
echo '{"column":"workEmail","op":"notEmpty"}' > has-email.json
owlbound tables push tbl_... --filter @has-email.json --confirm-count 143 # dry run
owlbound tables push tbl_... --filter @has-email.json --confirm-count 143 --apply4. Follow, export, check credits
owlbound events tail --follow --types action.completed
owlbound tables export tbl_... --format csv --out leads.csv
owlbound approvals list # open = the app page; people approve there
owlbound credits balanceExit codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Anything else: 5xx; an action that ended failed, rejected or expired under --wait |
| 2 | Usage: bad flags, 400 validation, 422 unprocessable |
| 3 | Auth: no key, 401, 403 |
| 4 | 429 RATE_LIMITED after honouring Retry-After |
| 5 | Network, or 503 UPSTREAM_UNAVAILABLE / STORE_UNAVAILABLE |
| 6 | 404 not found |
| 7 | 402 INSUFFICIENT_CREDITS (retry with a new --idempotency-key after a top-up) |
| 8 | Approval required: the action is pending_approval |
| 9 | 429 CAP_EXCEEDED |
| 10 | Conflict: PLAN_STALE (new plan printed), PLAN_ALREADY_APPLIED, IDEMPOTENCY_IN_PROGRESS, 412, IDEMPOTENCY_KEY_REUSED |
| 11 | 503 API_V1_NOT_ENABLED |
| 12 | --wait ran out; the action keeps running |
Run owlbound help for every command and owlbound help --json for a machine-readable spec of commands, flags, operations and exit codes.