CLI automation
Use the lookio CLI in scripts, CI and agents, with automatic JSON output, ndjson, polling for imports, safe retries and destructive commands.
The CLI is designed to be driven by a script or an AI agent as much as by a person.
JSON by default off a terminal
When stdout is not a terminal, every command prints JSON. A piped command, a CI job and an agent never have to remember --json, and can never receive a table by mistake.
| Mode | When | Output |
|---|---|---|
json | Default off a terminal | The whole result, indented. |
table | Default in a terminal | A table or a list of fields, with colour. |
ndjson | --output ndjson | One JSON object per line. For a list, one per row. |
LOOKIO_NO_TUI forces JSON in a terminal. NO_COLOR removes colour and nothing else.
List commands print the whole API envelope in JSON: data, has_more, next_cursor and limit. Pass next_cursor back as --cursor for the next page.
lookio resources list --limit 100 | jq -r '.data[] | select(.status == "failed") | .id'Progress notes go to stderr, and only in a terminal. Warnings always go to stderr.
Errors
A failure prints one JSON envelope on stderr and exits with a code you can branch on. It is the API’s own error format, plus the same shape for failures that never reached the server, with request_id set to null.
{
"error": {
"type": "not_found_error",
"code": "resource_not_found",
"message": "Resource not found.",
"docs_url": "https://lookio.app/docs/api/errors#resource_not_found"
},
"request_id": "req_0123456789abcdef0123456789abcdef"
}Branch on the exit code or on error.code, never on the message. See Exit codes.
Wait for an import
An import returns queued at once. Poll until the resource is final, and stop there.
#!/usr/bin/env bash
set -euo pipefail
id=$(lookio resources add-url https://example.com/pricing --tags pricing | jq -r '.id')
for _ in $(seq 1 60); do
status=$(lookio resources get "$id" | jq -r '.status')
case "$status" in
ready) echo "ready"; break ;;
failed) lookio resources get "$id" | jq -r '.status_detail' >&2; exit 1 ;;
esac
sleep 5
doneA site takes minutes, not seconds, so allow a longer loop. A resource that is not ready cannot answer questions yet.
Retries
The CLI retries by itself, up to 3 times with jittered backoff, and honours Retry-After:
429is retried for every command.408and5xxare retried for reads,PUTandDELETE, and for everyPOST.- A
PATCH(resources update,assistants update,members set) is not retried after a5xx, because the change may already have landed. Re-read the resource before you try again.
Every POST carries an Idempotency-Key, a random UUID chosen once per command and reused by each automatic retry. A retried lookio ask is not charged twice, and a retried import does not create two resources. Running the command again yourself is a new request with a new key.
Do not add your own blind retry loop around a command. Use --no-retry if you want to take over.
An out-of-credits failure is never retried. It exits with code 7 so a job can stop and alert a human.
A single request gives up after 60 seconds. Change it with --timeout.
Destructive commands
resources delete, assistants delete and tags delete ask for confirmation in a terminal. With no terminal, they do not wait: they exit with code 2 and an error that names --force. Add --force when you mean it.
CI example
name: Refresh Lookio resources
on:
schedule:
- cron: "0 6 * * 1"
jobs:
refresh:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v4
with:
node-version: 22
- name: Re-index the docs site
env:
LOOKIO_API_KEY: ${{ secrets.LOOKIO_API_KEY }}
run: npx @lookio/cli resources reindex "$RESOURCE_ID"Use an API key with only the scopes the job needs: resources:write here.
For AI agents
lookio help --jsonprints the whole command tree, every flag, the exit codes, the retry policy and the error format as one JSON document. An agent that reads it first stops guessing at flags.
- Call
lookio accountbefore assuming a capability.credential.scopeslists what the credential may do. - Do not pass
--json. It is already the output whenever stdout is not a terminal. - Use
lookio apifor anything that has no command yet.