IQ CLI
The IQ CLI is the local terminal for the gateway. Running iq with no
arguments drops you into an interactive shell; everything else is a
one-shot subcommand:
iq/iq shell-- interactive REPL. Type a prompt, get a response with routing telemetry, repeat.iq prompt "..."-- single-prompt round-trip with a routing telemetry box (tier, model, focus mode, cache, latency split, cost).iq batch prompts.txt-- run a prompt file end-to-end with a per-prompt line and an aggregate table at the close.iq smoketest-- drive a canned routing-correctness corpus through the gateway and check which tier each prompt landed on.iq agent "..."-- a dry-run planner. Proposes a plan; executes nothing.iq generate-prompts-- emit a synthetic prompt file at the requested difficulty mix.iq costlab-- score the CLI's local cost predictions against your own bills.
iq login and iq logout handle credentials -- see Sign in, below.
Install
Download the signed binary for your platform from the release assets
shared with your account. Pick the latest release and grab the asset
matching your OS and architecture. Each release ships a checksums file
and a detached signature. Verify the download against the published
checksum, then make it executable and put it on your PATH:
# After verifying the checksum:
chmod +x iq
sudo mv iq /usr/local/bin/iq
On Windows, download the .exe asset from the same release, verify its
checksum, and move it onto your PATH.
Sign in
iq login
iq login opens the dashboard's CLI access tokens page in your default
browser. Issue a token under Settings → CLI access tokens, paste it
back at the prompt. The CLI stores the token at
~/.config/iq-routing/credentials.toml (%APPDATA%\iq-routing\credentials.toml
on Windows) at mode 0600.
CLI access tokens carry the prefix iqp_. The CLI also accepts an
org API key (prefix gw_live_) issued from the dashboard's Keys page,
so either credential class works. The gateway verifies each class
separately on the prefix, and a personal access token is scoped
narrower than an org-level API key.
Single-prompt mode
$ iq prompt "Summarise the last quarter's earnings call in three bullets"
Routing
Tier: medium
Complexity: 6.2 / 10
Chosen model: gpt-5.6-luna
Focus mode: balanced (no bias)
Cache: miss (new prompt)
Latency
Total: 1842 ms
Gateway-side: 34 ms
LLM-side: 1808 ms
Tokens
Prompt: 17
Completion: 142
Cost
This request: $0.000482
Response
─────────────────────────────────────────────────────────────────────────
- Revenue grew 12 percent YoY, driven by the AI gateway segment.
- Margins compressed 80 bps as inference costs outpaced price increases.
- Guidance trims FY26 EPS by 3 percent to reflect the launch ramp.
─────────────────────────────────────────────────────────────────────────
Flags:
--raw-- print only the response body. No telemetry box. Useful for piping into another tool.--json-- print the full response as JSON with the telemetry inlined underx_iq_routing.--model-- pin a routing alias (auto, the default, pluscheap,frontier, anddefault) or a concrete provider/model string.--timeout-- request timeout in seconds. Default 60.--no-cost-line-- suppress the cost-prediction line printed under the telemetry box. The turn is still recorded; see Cost prediction, below, for the difference between this flag and turning the lab off entirely.
Interactive shell
Running iq with no arguments is the default entry point, and it is
identical to iq shell. Each line you type is sent through the
gateway as a new turn: the shell renders the same telemetry box as
iq prompt, a cost-prediction line (see Cost prediction, below), and
the response body, then prompts again. Turns are numbered (iq[1]>, iq[2]>, ...) and prior
turns re-render dimmed above the active one so a screen recording
shows which turn is live. Ctrl-D or Ctrl-C exits cleanly.
iq
# or start on a different routing alias:
iq shell --model frontier
$ iq
Connected to https://gateway.iq-routing.com. Model: auto
Type :help for commands, :exit to leave.
iq[1]> Summarise the last quarter's earnings call in three bullets
── turn 1 (14:02:07) ────────────────────────────────────────────
Routing
Tier: medium
Chosen model: gpt-5.6-luna
Cache: miss (new prompt)
...
Response
────────────────────────────────────────────────────────────────
- Revenue grew 12 percent YoY, driven by the AI gateway segment.
...
────────────────────────────────────────────────────────────────
iq[2]> What was the margin figure again?
── turn 2 (14:02:41) ────────────────────────────────────────────
Routing
Tier: simple
Chosen model: gpt-5.6-luna
Cache: miss (new prompt)
...
cost pred $0.000391* -> act $0.000348 -11.0% in 9->9 tok out 187->165 tok gpt-5.6-luna as predicted
in 9 tok below the 1024-token cache floor, no discount to keep or forfeit (*local fallback, gateway estimate unavailable)
Response
...
iq[2]> :exit
Meta-commands (anything starting with :):
| Command | Effect |
|---|---|
| :help | List every meta-command. |
| :exit, :quit, :q | Leave the shell. |
| :key <api-key> | Use a different key for this session only. :key alone shows the masked current key; :key clear reverts to the credentials-file token. |
| :gateway <url> | Point this session at a different gateway. :gateway alone shows the current URL; :gateway clear reverts. |
| :model <alias> | Switch the routing alias mid-session (auto, default, cheap, frontier, or a literal provider/model). :model alone shows the current value. |
| :cost, :cost off, :cost on | Show cost-line state plus predictor accuracy, or toggle the line. Recording continues regardless -- see Cost prediction, below. |
| :reset | Clear the screen and reset the turn counter to 1. Does not touch credentials or cost history. |
| :smoke [N] [--model alias] [--limit N] | Run the smoketest harness without leaving the shell. The positional N and --limit are interchangeable; passing both with different values is an error. |
| :testkey | Print a reminder of how to paste a real key. Does not itself change the active key. |
Dropping a file to batch
Paste or drag a .txt, .md, .prompt, or .prompts file path into
the prompt -- as the only token on the line, resolving to a file that
exists -- to dispatch every line in it as a batch, at concurrency 4,
without leaving the shell:
iq[3]> ~/Desktop/support-queue.txt
dropped file support-queue.txt (23 prompts, model=auto, concurrency=4, 6 match canonical corpus)
1/23 ✓ exp=- obs=cheap gpt-5-nano cache-miss 0.61s $0.00009
complexity=simple (1.8/10) focus=balanced tokens=22→64 req=a1b2c3d4
> "How do I reset my password?"
...
Aggregate
Total prompts: 23
...
The gateway's per-team rate limit is 240 requests per minute; the shell
warns when a dropped file's prompt count would exceed that, since rows
past the cap are likely to come back 429. Re-dropping the same file
replays every row from cache in a fraction of the original time.
exp= shows an expected tier only for prompts that match the built-in
smoketest corpus verbatim; anything else shows exp=- and only the
observed tier.
Batch mode
$ iq batch prompts.txt --concurrency=4 --out=results.jsonl
Reading prompts.txt: 20 prompts loaded
Concurrency: 4
1/20 ✓ simple gpt-5-nano cache-miss 0.84s $0.00012
2/20 ✓ medium gpt-5-mini cache-miss 1.92s $0.00048
3/20 ✓ simple gpt-5-nano cache-hit 0.04s $0.00000
...
20/20 ✓ complex opus-4-8 cache-miss 3.41s $0.00284
Aggregate
Total prompts: 20
Successes: 20
Failures: 0
Cache hit rate: 35%
Tier mix: simple 8 · medium 9 · complex 3
Latency p50: 1.42s
Latency p99: 4.18s
Total spend: $0.0341
Avg cost / prompt: $0.00171
Wrote results.jsonl with 20 rows.
Flags:
--concurrency=N-- in-flight requests. Defaults to 4. Caps at 16 (the safe per-org ceiling); higher values clamp with a stderr warning.--out=results.jsonl-- write one JSONL row per prompt with the full response body and the telemetry inlined underx_iq_routing.--model,--timeout-- same semantics asiq prompt.
The exit code goes non-zero when at least one prompt fails (any 5xx, timeout, or transport error). Failed prompts do not abort the run; the aggregate reports successes and failures together.
Prompt-file format
One prompt per line. Blank lines and #-prefixed lines ignored.
# easy
What is the capital of France?
Translate "good morning" to Spanish.
# medium
Given this CSV row, output a JSON object with the columns as keys: 1,Alice,30
Prompt generator
iq generate-prompts --difficulty=mixed --count=20 --out=prompts.txt
Difficulty bands:
easy-- single-sentence factual lookups, single-step instructions. Target tiersimple.medium-- multi-step reasoning, structured output, short code snippets. Target tiermedium.hard-- long-context, ambiguous instructions, cross-domain synthesis. Target tiercomplex.mixed-- 40% easy, 45% medium, 15% hard. Matches the observed production traffic distribution.
Counts cap at 1000 per file. The generator does not call the gateway; it is a pure offline emitter.
Smoketest
iq smoketest
iq smoketest --limit 10 --model frontier
iq smoketest drives a canned corpus of 100-plus prompts through the
gateway and checks that each one landed in its expected tier's band
(cheap, default, or frontier). It is a routing-correctness check, not
a synthetic dry run: every prompt is a real request against your
provider keys, so a full run has a real, if small, cost. Prompts
dispatch sequentially, so the full corpus takes several minutes.
$ iq smoketest --limit 3
iq smoketest 3 prompts gateway=https://gateway.iq-routing.com model=auto
PASS sp-cheap-01 expected=cheap model=gpt-5-nano 84ms
> What is the capital of France?
PASS sp-default-01 expected=default model=gpt-5.6-luna 1204ms
> Write a Python function that takes a list of integers and returns the second largest. Handle ties and empty lists.
FAIL sp-frontier-01 expected=frontier model=gpt-5-mini 932ms (routed to 'default' tier; expected 'frontier' (model: gpt-5-mini))
> Design the architecture for a multi-tenant SaaS analytics product handling 50 million events per day. Cover ingestion...
Routing distribution (expected tier x observed tier)
...
totals: 2 pass 1 fail 3 distinct chosen-model values runtime 14.2s
Flags:
--limit N/-n N-- cap the run at the first N prompts (a head-of-list subset) instead of driving the full corpus.--model/-m-- band-map alias for the whole run:auto(default),frontier,cheap, or a literalprovider/modelstring. Same alias semantics asiq prompt --model.--timeout-- per-request timeout in seconds. Default 60.
The run fails (exit code 1) if any prompt's response is empty, missing
telemetry, missing a chosen model, non-positive latency, missing cost
on a non-cache-hit, or routed outside its expected tier's band -- or
if the whole run produced fewer than four distinct chosen-model
values. A 429 mid-run waits for the suggested retry window once and
resumes rather than failing the prompt outright, since a full run can
brush against the gateway's 240 RPM per-team cap.
:smoke [N] [--model alias] [--limit N] runs the same harness inside
the interactive shell without spawning a separate process; see
Interactive shell, above.
Agent (dry-run planner)
iq agent "Find every TODO comment in the src/ directory and summarise them"
iq agent "Check whether api.example.com is up" --tools http_fetch
iq agent is a single-turn, dry-run planner. It sends your
instruction plus a small catalog of advisory tool schemas
(read_file, http_fetch) to the gateway and prints the model's
proposed plan: either a numbered list of tool calls or a prose
explanation.
The agent never executes anything. No file is read, no URL is fetched, no code runs. The tool schemas exist so the model can propose concrete, well-formed steps -- the operator reads the plan and runs whatever looks right by hand. Do not build automation on top of this command expecting the proposed steps to have actually happened; nothing downstream of the plan is real until you make it real.
$ iq agent "Find every TODO comment in the src/ directory and summarise them"
iq agent (planner / dry-run) session=iqa_4f9c2e1a08b7c391 model=auto tools=http_fetch,read_file
instruction: Find every TODO comment in the src/ directory and summarise them
Routing telemetry
model=gpt-5-mini cache-miss 0.81s $0.00031 complexity=medium (5.1/10) tokens=41→96
Proposed plan (advisory only -- nothing executed)
1. read_file(path='src/index.ts')
2. read_file(path='src/utils.ts')
Model commentary:
Run these two reads, then grep the results for "TODO" and summarise
each hit with its surrounding context.
Run any of these steps yourself if they look right; the agent never
executes tools.
Flags:
--model/-m-- routing alias or literalprovider/model. Same semantics asiq prompt --model.--tools-- comma-separated list of tool names the planner may propose. Built-ins:read_file,http_fetch. Defaults to both.--theme--light(default) ordark.
Every turn carries an X-IQ-Session-Id header
(iqa_<16-hex-chars>), so the dashboard's Sessions view rolls the
telemetry under one row even though the agent itself never loops.
Cost prediction
iq costlab report
iq costlab params
The cost lab predicts, before a turn is dispatched, what it is about
to cost, then scores that prediction against the bill once it lands.
The prediction comes entirely from your own historical usage --
the rates and output lengths the lab has already measured from your
past turns -- not from a live price quote from the gateway. Every
prediction the lab can currently produce is labelled local_fallback
(rendered with a trailing *) for that reason: it is the CLI's own
model of what a turn will cost, built by watching your bills, and it
is honest about being an estimate rather than a quote.
Because the predictor learns from your own history, it has nothing to say on a fresh install, or the first time it sees a given model: it needs at least one billed turn on a model before it can predict the next one.
The cost line
iq prompt and iq shell print one line under the telemetry box for
every turn, once the lab has enough history to say something:
- Nothing at all when there's no prediction to make (fresh install, or a model with no prior billed turn) or no bill to score it against.
- A one-line cache-hit note --
cost cache hit, $0.000000 served-- when the turn was served from cache. Classification is skipped on a cache replay, so there is nothing to predict. - Otherwise, a line showing the predicted cost, the actual cost, the signed percentage they differ by, the input/output token counts predicted vs. observed, and whether the model that ran matches the model the prediction assumed. A second, indented line follows when it applies, carrying up to three notes: the router switched models (what staying would have cost, if known), the prompt fell under the 1024-token cache-write floor (so there was no cache discount to report either way), and -- today, always -- the local-fallback marker.
cost pred $0.000391* -> act $0.000348 -11.0% in 9->9 tok out 187->165 tok gpt-5.6-luna as predicted
in 9 tok below the 1024-token cache floor, no discount to keep or forfeit (*local fallback, gateway estimate unavailable)
Two independent ways to quiet it down:
iq prompt --no-cost-lineor:cost offin the shell -- turns off the display only. The turn is still recorded, so the history stays complete.IQ_COSTLAB=off(env var), orenabled = falseunder[costlab]in the lab'sconfig.toml-- turns off the whole lab. No line, and no row gets recorded either.
iq costlab run
iq costlab run --limit 12
iq costlab run --input my-prompts.txt --model cheap
Drives a corpus through the gateway live, predicting each turn before
it dispatches and recording a residual row after. Without --input it
uses the first 12 prompts of the built-in smoketest corpus. Like
iq smoketest, this dispatches real requests against your provider
keys -- it is not a simulation. Turns run one at a time on purpose:
the predictor assumes the previous turn's model is still the
incumbent, so concurrent dispatch would race that assumption and
corrupt the accuracy numbers that come out of it.
Flags:
--input/-i-- a prompt file (one per line). Omit for the built-in corpus.--limit/-n-- cap at the first N prompts.--model/-m-- routing alias or literalprovider/model.--timeout-- per-request timeout in seconds. Default 60.
The lab must be enabled (see above) for run to record anything; it
prints an accuracy table for the rows it just recorded when it
finishes.
iq costlab report
iq costlab report
iq costlab report --trend --worst 5 --rates
Scores every residual row recorded so far -- from iq prompt,
iq shell, and iq costlab run alike, since they all write to the
same local log -- against the bills that came in.
Residuals
Rows: 142
Scoreable: 118
Cache replays (excluded): 24
Switched away from incumbent: 9
Inside disclosed band: 81%
Mean signed error: +4.2%
Median absolute error: 9.6%
Predicted total: $0.048210
Actual total: $0.051006
Flags:
--last N-- score only the most recent N rows.--trend-- MAPE by calibration epoch, calibrated vs. the seed vector, so you can see whether calibration actually helped.--worst N-- the N worst mispredictions and what each one assumed.--rates-- measured vs. assumed per-model rates, with the drift between them.--json-- emit the same stats as JSON.
iq costlab params
iq costlab params
iq costlab params --history output_len_multiplier
Shows the parameter vector currently in force -- every tunable's
current value, its bounds, which calibration epoch last moved it, and
how much evidence backed that move. --history <param> shows every
recorded change to a single parameter.
--pin <epoch> freezes resolution on a specific past epoch without
touching anything else in the log -- the rollback path after a bad
calibration. --unpin releases the pin so the highest epoch wins
again. Both are pure appends: nothing already on disk is ever
rewritten or deleted, so the epoch that caused the problem stays
there to be inspected.
iq costlab calibrate
iq costlab calibrate
iq costlab calibrate --param output_len_multiplier --since 2026-08-01
Fits one calibration epoch from the residual rows recorded since the parent epoch's window ended, and appends it to the local parameter log. It never re-reads rows an earlier epoch already consumed, and it computes exactly one epoch per invocation -- there is no loop-to- convergence mode, so every fit is a single, readable, auditable step. A parameter with too little evidence in the window is left unmoved and the epoch records why, rather than silently keeping its old value with no explanation.
Flags:
--dry-run-- print the exact epoch that would be appended, without appending it. Nothing is sent anywhere; this only previews the local file write.--param <name>-- fit only the named parameter this epoch.--since <date>-- override the window start (YYYY-MM-DDor an ISO timestamp, read as UTC).--include-fallback-- also admit rows whose own prediction came from the local fallback. Off by default, since that would be the predictor grading its own homework.
iq costlab reset and diff
iq costlab reset --confirm re-seeds every parameter back to its
built-in default by appending a reset row -- it does not delete
anything, but it does open a fresh resolution scope, so calibration
epochs written before the reset stop influencing the vector currently
in force (they stay on disk and stay readable). Running reset
without --confirm just prints a warning and does nothing.
iq costlab diff V1 V2 compares two calibration epochs parameter by
parameter, showing which cells changed and by how much (--json for
the same diff as JSON).
Where it's stored
The lab's state lives under the same per-user config directory as
your credentials, honouring IQ_CONFIG_DIR if you set it:
~/.config/iq-routing/costlab/residuals.jsonl-- one row per completed turn.~/.config/iq-routing/costlab/params.jsonl-- the calibration history.
(%APPDATA%\iq-routing\costlab\ on Windows.) Both files are
append-only JSONL, so they are safe to tail or feed into your own
analysis. iq logout does not touch this directory -- signing out
does not cost you your calibration history.
Tokens, scopes, and revoke
The CLI authenticates with a personal access token issued from Settings → CLI access tokens. Default scopes:
read:routing-- view routing decisions.write:prompt-- send prompts via the CLI.
Wider scopes (read:audit, write:settings) are opt-in at issue time.
Tokens display the plaintext exactly once at issue. The dashboard
shows only the prefix on subsequent reads.
iq logout removes the local credentials file. To revoke server-side,
open Settings → CLI access tokens and click Revoke on the token row.
Bundle mode (Enterprise)
There is no self-hosted distribution on the self-serve plans. The
standalone gateway bundle is the Enterprise on-prem option, arranged
with us rather than downloaded, and it ships the CLI as part of the
single-binary install. iq-gateway prompt "..." posts to the local
gateway at http://localhost:8000; the same telemetry box renders.
iq-gateway serve # boots the gateway + opens the dashboard
iq-gateway prompt "..." # uses the local gateway
Some of the bundle's deeper analytics surfaces render a Limited mode
banner, because they depend on reporting queries the bundle's embedded
storage does not support. Routing, caching, and per-request telemetry
all run end to end in the bundle; only the aggregate analytics views
are reduced.
Troubleshooting
Token in {path} is not a recognised IQ credential-- the saved value carries no known prefix. Re-runiq loginand paste an org API key (gw_live_...) or a CLI access token (iqp_...).Credentials file is group- or world-readable-- POSIX safety check. Runchmod 0600 ~/.config/iq-routing/credentials.toml.Gateway returned 401-- the token expired or was revoked. Runiq loginto reissue.- Telemetry box shows
telemetry unavailable-- the gateway you are pointed at is older than the telemetry header, or telemetry has been turned off for that deployment. Update to a current gateway version, or re-enable the telemetry header on the deployment you are calling.
See also
/docs/quickstart-- SDK integration via OpenAI/Anthropic clients./docs/api-reference-- REST surface details./integrate-- drop-in code snippets and aUse the IQ CLIpanel.