LIQ CODE

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.

Usageliq [command] [options] ["<prompt>"]
terminal
# 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.

InteractiveNon-interactive (headless)
Starts whenNo prompt and a terminal (TTY) is attached - just liq.A prompt is given (argument and/or stdin), or -p is passed.
What happensOpens 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.
InterfaceFull-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 commandsYes - /help, /new, /model, and the rest.No - it is one shot.
OutputAlways the human-readable view.Pick with --output-format: text, json, or stream-json.
Best forCoding by hand in the terminal.Scripts, pipes and CI.
terminal
# 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).

bash
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.

Usageliq [run] [options] ["<prompt>"]

Options:

OptionPurpose
-p, --printHeadless (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, --continueContinue the most recent session.
-r, --resume <id>Resume a session by id.
--max-effortForce the strongest tier and highest reasoning effort.
--verboseShow 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-indexDo not build the semantic code index for this run.
--no-session-persistenceRun in memory - the session is not saved and cannot be resumed.
--no-inkInteractive 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.
bash
# 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.

bash
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.

bash
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

bash
# 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:

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       leave

Any 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.

bash
liq -p -m auto --output-format json "what does src/cli/index.ts export?" | jq -r .result

Object shape:

json
{
  "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.

bash
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

bash
# 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

bash
# 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 1

Sessions

Lists and deletes saved sessions, which are shared with the app through the same data directory.

Usageliq 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.

bash
# 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/.

Usageliq skills [--json]

Lists the skills visible from the current folder; --json prints them machine-readably. Load one for a run with -s <name>.

bash
# 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

CommandWhat it does
liq index [-d dir] [--json]Build the code index and print stats.
liq doctorCheck 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:

bash
# 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-project

Example doctor output:

liq doctor
✓ 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, eval

Environment variables

Keys and access (public build)

VariableEffect
LIQ_API_KEYA LIQ CODE account key (liq_live_…). The only key that works in a public build.
LIQ_PROXY_TOKEN_FILEPath to an account-token file; re-read on every request, so a long run never sends a stale token.
LIQ_PROXY_TOKENA static account token.
LIQ_PROXY_BASE_URLInference proxy base (default https://api.liqcode.org/v1).
LIQ_PROXY_TOOLS_URL / LIQ_TOOLS_BASE_URLWeb-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.

VariableEffect
OPENROUTER_API_KEYOpenRouter key for liq-ai (eval).
OPENAI_API_KEYOpenAI key for auto (eval).
OPENROUTER_BASE_URL / OPENAI_BASE_URLAlternate provider endpoints.

Behaviour and output

VariableEffect
NO_COLORDisable ANSI colours (also auto-off when stdout is not a TTY).
LIQ_MODEL_FAMILYModel family override.
LIQ_NO_PLAN=1Disable the planning pass and the parallel subagent fan-out.
LIQ_PROMPTBase-prompt A/B arm.
LIQ_WASM_DIRExplicit 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.

ToolsWhen 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_imageAccount credentials present (a liq_live_… key)
verify_webDesktop 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).

bash
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:

bash
liq -p --max-turns 12 --output-format json "make the test suite pass" \
  | tee result.json | jq -e '.is_error | not' > /dev/null

Troubleshooting

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

Start free