CLI reference
LIQ CODE CLI Guide
A coding agent from your terminal. The CLI runs on the same core as the desktop app: the same loop, the same tool set, the same skills and subagents, the same session files. Only the shell differs - a terminal instead of a window.
The command is called liq-code, with liq as the short alias. Install it with npm install -g @liq-code/cli. A standalone binary (liq-windows-x64.exe / liq-linux-x64 / liq-macos-arm64) runs without Node - rename it to whatever suits you. The examples below use liq.
Quick start
The general form: a command (defaults to run), any options, and an optional prompt. Give a prompt to run one task; omit it to open the interactive session.
liq [command] [options] ["<prompt>"]# Interactive session in the current folder (full-screen UI)
liq
# One-off task: streams the answer and exits
liq "add a dark-mode toggle to the settings page"
# Headless (for scripts/CI): -p / --print
liq -p "explain what src/cli/index.ts does" > notes.md
# Context via stdin
cat build.log | liq -p "why did this build fail?"
# Continue the previous session
liq -c "now write tests for that change"With no prompt and a terminal attached, an interactive session starts (the full-screen UI by default, or the line-based REPL with --no-ink). With a prompt - an argument and/or stdin - a single non-interactive turn runs instead. See Interactive vs non-interactive for the full breakdown.
Exit codes: 0 - success; 1 - agent error, unknown flag, missing prompt, or missing key. This is what to rely on in CI.
Interactive vs non-interactive
The CLI picks one of two modes from the way you launch it, and they behave very differently: one keeps a conversation open, the other runs a single task and exits.
| Interactive | Non-interactive (headless) | |
|---|---|---|
| Starts when | No prompt and a terminal (TTY) is attached - just liq. | A prompt is given (argument and/or stdin), or -p is passed. |
| What happens | Opens a session you talk to turn after turn; it stays open until you leave. | Runs a single turn, streams the answer to stdout, then exits. |
| Interface | Full-screen terminal UI by default; --no-ink switches to the plain line-based REPL. | No UI - just the streamed output (colours auto-off outside a TTY). |
| Slash commands | Yes - /help, /new, /model, and the rest. | No - it is one shot. |
| Output | Always the human-readable view. | Pick with --output-format: text, json, or stream-json. |
| Best for | Coding by hand in the terminal. | Scripts, pipes and CI. |
# Interactive: the full-screen UI (default)
liq
# Interactive: the classic line-based REPL instead of the full-screen UI
liq --no-ink
# Non-interactive: one task, streamed to stdout, then exit
liq -p "explain what src/cli/index.ts does"
# Non-interactive is also implied by any prompt (even without -p)
liq "add a dark-mode toggle to the settings page"The -p / --print flag forces non-interactive mode even with no prompt in the arguments - useful when all the input arrives on a pipe.
Authentication and keys
The CLI is account-only - the same as the desktop app.
A LIQ CODE key
A liq_live_… key is created in your account, on the website or in the desktop app (Settings → API keys). It authenticates your account, usage bills against your subscription just as it does in the app, and it is what unlocks the server-mediated tools - web search, page fetching, image analysis and generation (see which tools are available).
export LIQ_API_KEY=liq_live_XXXXXXXXXXXXXXXXXXXX
liq -p "fix the failing test in src/auth"
# or once, as a flag
liq --api-key liq_live_XXXX -p "explain this repo"Precedence: --api-key <token> → LIQ_API_KEY (env). A value beginning with liq_live_ always goes to the LIQ CODE proxy.
Your own provider keys do not work in a public build. This is deliberate: inference goes through the account only, like the desktop app. Bring-your-own OpenAI / OpenRouter keys are enabled only in an eval build, meant for sandbox evals where the harness measures the model on its own credentials. In a normal user build OPENAI_API_KEY / OPENROUTER_API_KEY are ignored.
The run command - the agent
Runs the agent on a prompt. run is the default command, so liq "prompt" is equivalent to liq run "prompt". The prompt may be an argument, piped in on stdin, or both.
liq [run] [options] ["<prompt>"]Options:
| Option | Purpose |
|---|---|
-p, --print | Headless (non-interactive): stream the answer and exit. The prompt can be piped in. |
-m, --model <id> | Model: liq-ai (default) · auto · liq-local. |
-d, --dir <path> | Working directory (defaults to the current one). |
-c, --continue | Continue the most recent session. |
-r, --resume <id> | Resume a session by id. |
--max-effort | Force the strongest tier and highest reasoning effort. |
--verbose | Show the agent's thinking. |
--output-format <fmt> | text (default) · json · stream-json. |
--max-turns <n> | Cap the number of agent turns (only with -p). |
--api-key <token> | A LIQ CODE account key (or a provider key in an eval build). |
-f, --file <path> | Attach a file to the prompt. Repeatable. |
-s, --skill <name> | Load a skill by name before the turn. Repeatable. |
--no-code-index | Do not build the semantic code index for this run. |
--no-session-persistence | Run in memory - the session is not saved and cannot be resumed. |
--no-ink | Interactive only: use the plain line-based REPL instead of the default full-screen UI. |
Models
liq-ai(default) - the family via account/proxy. The main path.auto- the OpenAI tier chain. A provider path, so in a public build it needs an account (a BYO OpenAI key works only in an eval build).liq-local- an offline mock agent. No key needed, deterministic output. Good for checking the pipeline, scripts and tests.
# Strongest tier + highest reasoning on a hard refactor
liq -p -m auto --max-effort "refactor the auth module to remove the callback hell"
# Offline check that the CLI works at all
liq -p -m liq-local "hello"Attach files
--file puts a file into the message context. The core detects the type itself - text, PDF, DOCX, XLSX, an image (images need an account key). A missing path or a directory is an error at startup: better to fail than to silently answer about a file the agent never saw.
liq -p -f error.log -f src/server.ts "why does the server 500 on startup?"
liq -p --file spec.pdf "summarise the API contract in this spec"An attachment is spent on the first turn, not glued onto every subsequent one.
Load a skill
--skill loads a skill by name before the turn begins. See the available ones with liq skills.
liq -p -s code-review "review my staged changes"
liq -s react-app "scaffold a settings page with a dark-mode toggle"A one-off run that leaves no trace
# Writes nothing to the data directory; cannot be resumed
liq -p --no-session-persistence "one-off question - don't save it"Interrupt
Ctrl-C stops the current turn and keeps the session. A second Ctrl-C at an idle REPL prompt exits.
Interactive session
Starts when there is no prompt and a terminal is attached: just liq. By default it is a full-screen terminal UI - a composer, live streaming, and a status line. Prefer a classic line-based prompt? Add --no-ink. Both accept the same slash commands:
/help show help
/new start a new session
/sessions list recent sessions
/rm [id] delete a session (default: the current one)
/model <id> switch model (auto | liq-ai | liq-local)
/effort toggle max-effort
/clear clear the screen
/exit, /quit leaveAny other /name is treated as a skill invocation of that name, the same as liq skills. For example /code-review inside the REPL runs the code-review skill.
To an agent question (AskUserQuestion) in the REPL you reply with the option number or your own text.
Output formats and automation
--output-format controls what goes to stdout.
text (default)
A human-readable rendering: assistant text, tool cards, diffs.
json - a single final object
When the turn finishes, exactly one object is printed - the answer and the totals. Handy for a script that wants the result, not a play-by-play.
liq -p -m auto --output-format json "what does src/cli/index.ts export?" | jq -r .resultObject shape:
{
"type": "result",
"is_error": false,
"session_id": "…",
"num_turns": 3,
"result": "…answer text…",
"usage": { "turns": 3, "inputTokens": 1200, "outputTokens": 340, "…": "…" }
}The usage and error fields are present only when there is something to show - the offline liq-local model, for instance, has no usage. The keys type, is_error, session_id, num_turns and result are always present.
stream-json - an NDJSON stream
A line-by-line stream of events as they happen, one JSON object per line. This is the programmatic contract the eval harness parses.
liq -p -m auto --output-format stream-json "fix the bug" \
| jq -c 'select(.kind=="block")'Event kinds (the kind field): message-start, block, usage, error, message-end.
The --json flag is a legacy alias for --output-format stream-json. It is hidden from --help but still works, since existing scripts depend on it.
Cap the number of turns
# Don't let an unattended run "keep going until it decides to stop"
liq -p --max-turns 8 "investigate and fix the flaky test"--max-turns counts main-loop turns, not subagent calls, and only applies in headless mode.
Fail a CI step on an agent error
# is_error -> a non-zero exit code
liq -p --output-format json "run the tests and fix any failure" \
| jq -e '.is_error | not' > /dev/null || exit 1Sessions
Lists and deletes saved sessions, which are shared with the app through the same data directory.
liq sessions [list | rm <id…>]list (the default, can be omitted) prints recent sessions; rm <id…> deletes one or more by id. To reopen a session, use -c for the latest or -r <id> on run.
# List (list is the default command, can be omitted)
liq sessions
liq sessions list
# Delete one or more by id
liq sessions rm 8d4e82c9-801d-4110-ad5c-15094f2291cd
liq sessions rm <id1> <id2> <id3>
# Continue the latest / resume a specific one
liq -c "and add a test as well"
liq -r 8d4e82c9-801d-4110-ad5c-15094f2291cd "finish this PR"Deleting an unknown id is an error (exit 1), not a silent success.
Skills
Skills are instruction packs, compatible with the Claude Code format. The CLI sees them from several layers: built-ins, ~/.claude/skills/, <data-dir>/skills/, <cwd>/.claude/skills/ and <cwd>/.liq/skills/.
liq skills [--json]Lists the skills visible from the current folder; --json prints them machine-readably. Load one for a run with -s <name>.
# What's available from this folder
liq skills
# Machine-readable
liq skills --json
# Use one in a run
liq -p -s code-review "review the diff on this branch"In the REPL a skill is invoked as /skill-name [args].
Utility commands
| Command | What it does |
|---|---|
liq index [-d dir] [--json] | Build the code index and print stats. |
liq doctor | Check the environment: runtime, ripgrep, tree-sitter, data dir, flags. |
liq open [-d dir] | Launch the desktop app (needs Electron; not in the standalone binary). |
No search / files / parse subcommands. Code search and shell parsing are the agent's internal tools (Grep/Glob and the run-command analyzer), not a CLI utility belt. If you want a raw grep, you already have rg.
Examples:
# Build the code index and print stats
liq index
liq index -d src --json
# Check the environment (runtime, ripgrep, tree-sitter, data-dir, flags)
liq doctor
# Launch the desktop app (needs Electron; not available in the standalone exe)
liq open -d ./my-projectExample doctor output:
✓ runtime node 22.11.0
✓ electron …/node_modules/electron/dist/electron.exe
✓ ripgrep …/@vscode/ripgrep-…/rg.exe
✓ ts runtime …/web-tree-sitter/tree-sitter.wasm
✓ bash grammar …/tree-sitter-bash/tree-sitter-bash.wasm
✓ shell parser tree-sitter
✓ dist build …/dist
✓ data dir …/liq-code
✓ workspace /path/to/project (main)
flags: devtools, telemetry, shell-analysis, context-search, code-index, evalEnvironment variables
Keys and access (public build)
| Variable | Effect |
|---|---|
LIQ_API_KEY | A LIQ CODE account key (liq_live_…). The only key that works in a public build. |
LIQ_PROXY_TOKEN_FILE | Path to an account-token file; re-read on every request, so a long run never sends a stale token. |
LIQ_PROXY_TOKEN | A static account token. |
LIQ_PROXY_BASE_URL | Inference proxy base (default https://api.liqcode.org/v1). |
LIQ_PROXY_TOOLS_URL / LIQ_TOOLS_BASE_URL | Web-tools base (default https://api.liqcode.org/tools). |
BYO provider keys - eval build only
Effective only if the build carries the eval flag. Ignored in a public build.
| Variable | Effect |
|---|---|
OPENROUTER_API_KEY | OpenRouter key for liq-ai (eval). |
OPENAI_API_KEY | OpenAI key for auto (eval). |
OPENROUTER_BASE_URL / OPENAI_BASE_URL | Alternate provider endpoints. |
Behaviour and output
| Variable | Effect |
|---|---|
NO_COLOR | Disable ANSI colours (also auto-off when stdout is not a TTY). |
LIQ_MODEL_FAMILY | Model family override. |
LIQ_NO_PLAN=1 | Disable the planning pass and the parallel subagent fan-out. |
LIQ_PROMPT | Base-prompt A/B arm. |
LIQ_WASM_DIR | Explicit tree-sitter grammar directory (for container runs). |
Where things live
The data directory is shared with the app:
- Windows:
%APPDATA%\liq-code - macOS:
~/Library/Application Support/liq-code - Linux:
$XDG_CONFIG_HOME/liq-code(usually~/.config/liq-code)
Inside: sessions/ (one file per session), settings.json (shared settings), code-index/ (index cache) and skills/ (global skills). The exact path is shown by liq doctor on the data-dir line.
Which tools are available in the CLI
The agent sees the same tool set as the app, minus those that physically cannot run in the current process. Only workable tools are offered to the model, so it does not spend a turn on a call that is bound to fail.
| Tools | When available |
|---|---|
| Read, Write, Edit, Bash, PowerShell, Grep, Glob, Skill, Agent, TodoWrite, AskUserQuestion, documents (pdf/xlsx/docx) | Always |
| outline, symbols, deps (code index) | Index enabled (no --no-code-index, build ships the grammars) |
| WebSearch, WebFetch, analyze_image, generate_image | Account credentials present (a liq_live_… key) |
| verify_web | Desktop app only (needs a browser) |
Practical upshot: on a LIQ CODE key everything is available except verify_web. In an eval build on a BYO provider key, web and vision drop out since they need an account, but the full coding tool set stays.
Docker / CI
Use a glibc base image such as debian - the Linux binary is not built for musl (Alpine).
docker run --rm \
-e LIQ_API_KEY \
-v "$PWD:/work" -w /work \
debian:stable-slim \
./liq-linux-x64 -p "fix the failing test"The binary extracts its embedded ripgrep into the data directory on first run, so no external ripgrep is needed in the container.
An example CI step that fails on an agent error:
liq -p --max-turns 12 --output-format json "make the test suite pass" \
| tee result.json | jq -e '.is_error | not' > /dev/nullTroubleshooting
No credentials for model "…"
No account key is set. Create one in your account (Settings → API keys) and export LIQ_API_KEY=liq_live_…, or pass --api-key. To check without a key, use -m liq-local. A raw OpenAI/OpenRouter key will not do in a public build - only in an eval build.
Web search / images do not work
These need an account key (liq_live_…).
index disabled - use Grep/Glob/Read
The code index is off (--no-code-index, or a build without grammars). The agent still works fully via Grep/Glob/Read.
Colours clutter CI logs
Set NO_COLOR=1 - or just write to a pipe or file, since colours turn off automatically outside a TTY.
liq open says Electron is missing
The command only works next to an installed app; it is absent from the standalone binary.
Get the CLI
Ready to run it in your terminal?
npm install -g @liq-code/cli