@lookio/cli
The Lookio CLI: import your documents, build assistants and ask them questions from a terminal, a CI job, or an AI agent. Homepage: https://lookio.app
npm install -g @lookio/cli
# or, without installing:
npx @lookio/cli account
The binary is called lookio. Requires Node 20 or later.
Not on npm yet. The package is still private ("private": true), so the
install lines above will work once it is published.
What costs credits
lookio askspends credits on every question, whatever the answer's length: Flash 30 (the default), Eco 10, Deep 80 (--mode), even when nothing is found. An assistant that reads no resource is refused first (assistant_has_no_resources), before any credit is held.lookio searchcosts 1 credit a search, whatever it finds. A public assistant is asked like your own, with its id (lookio ask,lookio search), paid by your workspace. Managing accesses, access keys and publications is free.- Importing is free: texts, URLs, files and sites, and re-indexing them.
- Everything else (listing, reading, creating assistants, members, accesses) is free.
Getting started
lookio auth login # opens a browser, stores the token in your keychain
lookio account # workspace, plan, credit balance
lookio resources add-url https://example.com/pricing --tags pricing
lookio resources get <resource_id> # repeat until status is ready or failed
lookio assistants create --name "Support" --follow-tags pricing
lookio ask <assistant_id> "How much does the pro plan cost?"
For CI, use an API key created in the app's developer settings:
export LOOKIO_API_KEY="sk_live_..."
lookio account
An API key belongs to the WORKSPACE and does not expire when a person leaves, which is what makes it the right credential for a job rather than a person.
Imports are asynchronous
Every import (add-text, add-url, add-file, sites add, reindex) returns
immediately with a resource in queued. Lookio reads and indexes it in the
background: seconds for a page or a short file, minutes for a site. Poll
lookio resources get <id> until status is ready (searchable) or failed
(see status_detail, fix the cause, then lookio resources reindex <id>).
Commands
# Resources: what assistants answer from. All free.
lookio resources list --type url --tag pricing --status ready --query refund --limit 50
lookio resources get <id>
lookio resources add-text --title "Refund policy" --from-file policy.md --tags legal,faq
lookio resources add-url https://example.com/pricing --title "Pricing"
lookio resources add-file ./handbook.pdf --tags hr # streamed from disk
lookio resources update <id> --title "New title" --tags a,b
lookio resources delete <id> --force
lookio resources content <id> --offset 0 --limit 20000 # the text as indexed, in pieces
lookio resources reindex <id>
# Sites: imports use no credits; recurring updates require a paid plan.
lookio sites preview https://example.com/docs # nothing is created
lookio sites add https://example.com --include "/docs/**" --exclude "/blog/**" --schedule every_3_days
lookio sites pages <id> --status failed --limit 100 # paginated, --cursor for the next page
lookio sites rules <id> --include "/docs/**" # replaces all rules; keeps the current schedule
lookio sites retry <id>
# Assistants. Free.
lookio assistants list
lookio assistants create --name "Support" --context "You are the help center assistant of Acme, talking to customers" --resources id1,id2 --follow-tags faq
lookio assistants update <id> --knowledge all
lookio assistants delete <id> --force
# Widgets: a chat box that shows one assistant to anonymous visitors on a website.
# Free to manage; visitors' answers are charged to your workspace, in the widget's mode.
lookio widgets list
lookio widgets create --assistant <assistant_id> --domain docs.acme.com --setting theme=dark
lookio widgets update <id> --domain docs.acme.com --domain "*.acme.com" # replaces the whole domain list
lookio widgets update <id> --status paused --monthly-credits 5000
lookio widgets duplicate <id> # a copy, with its images
lookio widgets set-image <id> launcher ./logo.png # or favicon; paid plans, 256 KB
lookio widgets clear-image <id> launcher
lookio widgets snippet <id> --format bubble # the install snippet, as plain text
lookio widgets conversations <id> # what visitors asked; add a conversation id for one
lookio widgets delete <id> --force
# Accesses: share assistants with people outside the workspace, by MCP and HTTP. Admins only, free to manage;
# the workspace pays for what callers spend, capped by the ceilings.
lookio accesses list
lookio accesses create --name "Acme docs" --assistant <assistant_id>="Answers from the docs" --modes flash,deep --passages true --monthly-credits 200000
lookio accesses update <id> --status paused # --assistant replaces the whole list; none removes a ceiling
lookio accesses get <id> # URLs to hand out, ceilings, keys, spending
lookio accesses delete <id> --force
lookio accesses keys create <access_id> --name Globex --daily-credits 3000 # prints the secret ONCE
lookio accesses keys update <access_id> <key_id> --monthly-credits 50000
lookio accesses keys revoke <access_id> <key_id> --force
# Publishing: ask Lookio to list an assistant in the public directory (reviewed first). Admins only, free.
lookio assistants publish <assistant_id> --description "Answers questions on German employment law from the statutes, with citations."
lookio assistants publication <assistant_id> # private, pending, public or rejected (with the reason)
lookio assistants unpublish <assistant_id> --force
# The public directory. Browsing is free; ask one like your own assistants, paid by YOUR workspace,
# the conversation kept in your workspace.
lookio public list --q "employment law" --limit 10
lookio public get <assistant_id>
lookio ask <public_assistant_id> "How long is the notice period?" --mode eco
# Passages of an assistant (yours or a public one), without an answer, for your own model to read. SPENDS 1 CREDIT per search.
lookio search <assistant_id> "refund window" --limit 5
# Asking. SPENDS CREDITS (Flash 30, Eco 10, Deep 80 per question).
lookio ask <assistant_id> "What is the refund window?"
lookio ask <assistant_id> "And for annual plans?" --conversation <conversation_id> # the history is read server-side
lookio ask <assistant_id> "What is the refund window?" --end-user user_42 # API keys: your own id for the person asking
lookio ask <assistant_id> "A private question" --no-store # API keys: keep nothing
lookio ask <assistant_id> "And for annual plans?" --history-file turns.json # you keep the conversation yourself
lookio ask <assistant_id> "Summarise the handbook" --stream
# Your conversations: your personal chats after 'lookio auth login', or the
# conversations of your API key (--end-user narrows to one of your users).
lookio conversations list --assistant <assistant_id> --end-user user_42 --limit 20
lookio conversations get <conversation_id>
lookio conversations rename <conversation_id> New title
lookio conversations delete <conversation_id> --force # an API key's conversation leaves the logs too
lookio conversations feedback <conversation_id> <answer_id> down --comment "Out of date" # your user's thumb (API keys)
# Logs, four kinds, all free. Add --stats to any of the first three for its figures.
# conversations: what people OUTSIDE the workspace asked (widget visitors, your product's
# users through an API key or the MCP). Kept 90 days after the last message; members'
# own chats are not in them.
lookio logs conversations --rating down --channel widget,api --from 2026-10-01
lookio logs conversations --stats --widget <widget_id>
lookio logs get <conversation_id>
# answers: every answer from any channel, metadata only (no question or answer text)
lookio logs answers --channel widget,api
lookio logs answers --stats --from 2026-10-01
# indexing: every file, page or text read and indexed, with its status and any error
lookio logs indexing --status failed
lookio logs indexing --stats --resource <resource_id>
# activity: who changed what, through which door (admins), kept a year
lookio logs activity --origin cli,mcp --action assistant --from 2026-10-01
# Tags (rename and delete: workspace admins).
lookio tags list
lookio tags rename <from> <to>
lookio tags delete <tag> --force
# Members (workspace admins, signed in with 'lookio auth login'). Permissions:
# resources_list, resources_create, resources_edit, resources_delete,
# assistants_create, assistants_edit, assistants_delete, api, mcp
# (the old camelCase names, such as resourcesCreate, are still accepted).
lookio members list
lookio members set <user_id> --allow resources_create,api --deny mcp --assistants all
# Account, escape hatches.
lookio account # plan, balance, seats, word allowance, query modes with prices, scopes
lookio credits
lookio usage --from 2026-01-01 # totals, by day, by mode and assistant, words stored
lookio api GET /resources --query type=url
lookio doctor
lookio mcp
Streaming an answer
lookio ask --stream shows the answer as it is written. In a terminal you see
the text arrive, then the sources. When stdout is not a terminal you get one
JSON object per line, one per server event:
{"event":"status","data":{"phase":"searching"}}
{"event":"delta","data":{"text":"The refund window is "}}
{"event":"done","data":{"answer":"...","citations":[...],"conversation_id":"…","message_id":"…","credit_cost":30,"credits_remaining":970,"simulated":false}}
The done data is the same snake_case answer the non-streaming call returns. An
error event carries the standard error envelope
({"error":{"type","code","message",...},"request_id"}): it is printed on
stderr and the command exits with the exit code of its code, the same table as
an HTTP error (so a stream insufficient_credits exits 7). A stream that ends
with neither done nor error exits 1. Keep-alive comment lines (: keep-alive)
are ignored.
Widgets
A widget is a chat box that shows one assistant to anonymous visitors on your
website. Create one with lookio widgets create --assistant <id> --domain docs.acme.com, then install what lookio widgets snippet <id> prints: the
bubble before </body>, the embed where the chat should sit, the hosted
link, or the iframe for builders that refuse scripts. List the websites that
show it with --domain: the browser refuses the bubble and the embed on any
site not listed, and update --domain replaces the whole list. Managing widgets
is free; visitors' answers are charged to your workspace, in the widget's
--mode, so cap them with --limit-per-visitor-hour, --limit-per-visitor-day
and --monthly-credits. Use --monthly-credits-enabled false to pause the monthly ceiling without losing its amount, and true to restore it. Appearance and words are --setting key=value
(theme, accent, radius, bubbles, position, launcher, launcher_label, launcher_icon, header_icon, title, subtitle,
greeting, placeholder, suggestions, disclaimer, language,
sources, memory, visitor_history, feedback, branding, bubble, embed,
hosted_page). The last three turn the three formats on or off: bubble is on
by default, embed and hosted_page are off.
Output
JSON automatically when stdout is not a terminal. Piping into jq just
works, and no command needs a --json flag added in CI. At a terminal you get a
table. Force either with --output json|table|ndjson.
List commands print the whole envelope in JSON (data, has_more,
next_cursor, limit). Pass next_cursor back as --cursor for the next page.
Exit codes
A script can branch without parsing a message:
| Code | Meaning |
|---|---|
| 0 | success |
| 1 | an unexpected failure |
| 2 | bad usage, or a request the server rejected as invalid |
| 3 | authentication or permission |
| 4 | not found |
| 5 | rate limited |
| 6 | conflict |
| 7 | out of credits (insufficient_credits) |
insufficient_credits has its own code on purpose: a job that runs out of
credits must stop and tell a human, not retry.
Scopes
account:read, usage:read, resources:read, resources:write,
resources:delete, assistants:read, assistants:write, assistants:delete,
query, admin. lookio auth login requests the Editor set (account:read,
usage:read, resources:read, resources:write, assistants:read,
assistants:write, query), which deletes nothing: pass --scope to add
resources:delete, assistants:delete or admin. widgets delete needs assistants:delete. Renaming and deleting a
conversation, and sending feedback on an answer, need query; logs conversations and logs get need assistants:write, logs answers needs usage:read, logs indexing needs resources:read and logs activity needs admin.
For agents
lookio help --json
Prints the whole command tree, the exit codes, the retry policy and the error
envelope as one machine-readable document. An agent that reads it first stops
guessing at flags. See AGENTS.md for the longer reference.
Retries
429 is retried for every command. 408 and 5xx are retried for idempotent
requests (RFC 9110 §9.2.2) and for every POST: each POST carries an
Idempotency-Key header (a random UUID per request, repeated unchanged by the
CLI's automatic retries), so the API applies it once however many times it
arrives. Only PATCH (resources update, assistants update, widgets update, members set, conversations rename)
is reported rather than repeated after a 5xx; re-read the resource before
retrying it yourself.
Disable retries with --no-retry.