using/cli

The lash binary, shipped by the lash-cli crate, runs an interactive terminal UI by default, autonomous single-shot modes under --print, a JSONL event stream under --mode json, an stdin/stdout RPC loop under --mode rpc, and administrative flows like --export and --reset. It is the runtime's reference application and a worked embedding example: a testing bed for the library, not a separate product, and not required to build on lash. The runtime is the crate you embed. This page enumerates the user-visible surface: flags, slash commands, key bindings, the setup wizard, the config file, and the environment variables it reads.

First Run

If ~/.lash/config.json does not exist, lash launches the setup wizard. The wizard provisions an active provider, collects credentials, and writes the config file before dropping you into the TUI.

$ lash
# Setup wizard:
# 1. Choose a provider (Anthropic, OpenAI, OpenAI-compatible, Codex, Google OAuth)
# 2. Paste API key (or run OAuth / device-code flow)
# 3. Optionally paste a Tavily API key for the built-in web-search tool
# 4. Drop into the interactive TUI

Re-run the wizard at any time with lash --provider. Use /provider from inside a session to switch providers without restarting.

Slash Commands

Type a / at the start of the prompt to invoke a command. Tab-completion is available. Skill names registered in ~/.lash/skills/ or .agents/lash/skills/ appear as additional /<skill> commands.

CommandAliasesUsageDescription
/clear/new/clearReset conversation
/compact/compact [focus instructions]Open a compaction Agent Frame seeded by a summary
/controls/controlsShow keyboard shortcuts
/fork/forkOpen a forked session in a new terminal
/tree/treeBrowse and switch branches in the current session
/version/versionShow lash-cli and lash-sansio versions
/info/status/infoShow current session/runtime info
/model/model [name]Show or switch the LLM model
/variant/variant [name]Show or switch the model variant (e.g. high, max)
/mode/mode [name]Show the session's execution mode (standard / rlm); it is locked for the session, so changing it requires a new session started with --execution-mode
/provider/login/providerSwitch, add, or re-authenticate providers
/logout/logoutRemove stored credentials for active provider
/retry/retryReplay the previous turn payload
/resume/continue/resume [id-or-name]Search sessions or resume by id/name (interactive picker if no arg)
/skills/skillsBrowse loaded skills
/help/?/helpOpen the commands and shortcuts overlay
/exit/quit/exitQuit

Keyboard Shortcuts

The TUI uses a small, consistent set of shortcuts. The full list is also available in-session via /controls.

History navigation

PageUp / PageDown
Scroll history or the active document overlay.
/
Cycle the input-draft history when not navigating a suggestion popup.

Prompt editing

Enter
Submit immediately when idle; while a turn is active, inject at the earliest safe runtime boundary.
Tab
Accept an autocomplete suggestion when the popup is open; with a draft, submit immediately when idle or queue a next-turn draft while active.
Ctrl+U
Delete draft text from the cursor to the start of the line.
Ctrl+K
Delete draft text from the cursor to the end of the line.
Ctrl+← / Ctrl+→
Move the cursor by word.
Home / End
Jump to the start / end of the prompt.

Selection & clipboard

Ctrl+Shift+C
Copy the current selection or the last assistant response. Configure via LASH_COPY_BINDING if the default conflicts with your terminal.
Ctrl+C
Close a popup or overlay, cancel the active turn, clear a non-empty draft, or quit from an idle empty prompt.
Esc
Close overlays, pickers, and modal flows.

Command palette

Ctrl+P
Open the command palette settings overlay: a searchable list of Settings actions (theme, model, variant, provider, execution mode, logout) and Session actions (new, resume, tree, fork), each annotated with the equivalent slash command.

Pickers & multi-select

/ or k / j
Move selection.
Space
Toggle a multi-select option when supported.
Tab / BackTab
Add / remove a note on a selection when supported.

Background process dock

Tab / Shift+Tab
With an empty prompt, cycle focus through the dock of background processes. The dock lists only processes granted to the current session.
Enter
Open an overview of the focused process.
Delete
Cancel the focused process.

A running process shows running; a terminal one shows its outcome — success, error, cancelled, or abandoned. abandoned (ADR 0019) means the owner was lost without recording an outcome and renders in the failure style, like error. A detached command (shell.start with detach: true) never appears in the dock: it returns immediately with status: "detached" and is owned by the host/OS, not tracked as a session process.

CLI Flags

Run lash --help for the full list. The most common flags, grouped by purpose:

Provider & model

--provider
Re-run the provider setup wizard.
--model <name>
Override the default model for this session.
--variant <name>
Override the model-native variant (e.g. high, max, xhigh).
--api-key <key>
One-shot API key for OpenAI or OpenAI-compatible providers.
--base-url <url>
Base URL for the LLM API (OpenAI-compatible).
--tavily-api-key <key> (env TAVILY_API_KEY)
Tavily key for the bundled web-search tool.

Execution

--execution-mode <mode>
standard (default) or rlm.
-c, --context-approach <approach>
For standard mode: rolling_history or observational_memory.
--rlm-var name=<json>
Repeatable. Project a read-only bound variable into the RLM autonomous turn.
--rlm-vars-file <path>
Same as above but load the projections from a JSON object file.

Session

--resume <id_or_name>
Resume by session id, name, or legacy .db filename.
--resume-prompt <prompt>
Send a prompt right after resume.

Output modes

-p, --print <prompt>
Autonomous: run the prompt once, write the answer to stdout, exit. See Print mode below.
--mode <interactive|json|rpc>
Select the host surface. interactive is the TUI default; json requires --print and writes JSONL events to stdout; rpc reads LF-delimited requests from stdin and writes LF-delimited records to stdout.
--await-background-work
In autonomous mode, wait for plugin background work before exiting.
--turn-usage-json <path>
In autonomous mode, write per-turn and cumulative usage JSON to a file.

Debug & tracing

--debug
Detailed lifecycle/debug logs plus per-session LLM traces.
--trace-level <standard|extended>
Trace detail. Default standard.
--debug-ui-trace trace.json
Record the live TUI session as a replayable UI trace plus a final snapshot.
--debug-ui-trace-interval-ms <ms>
When recording a UI trace, also capture numbered checkpoint snapshots at the given interval.

Observational memory

--om-observation-message-tokens <tokens>
Observe recent raw history after this many new message tokens.
--om-observation-buffer-tokens <tokens>
Keep this much message-token slack before observation pressure starts.
--om-observation-block-after-tokens <tokens>
Block new turns once unobserved message tokens pass this threshold.
--om-observation-max-tokens-per-batch <tokens>
Cap the raw-history slice sent to one observer pass.
--om-previous-observer-tokens <tokens>
Budget previous observer notes included in a fresh observation pass.
--om-reflection-observation-tokens <tokens>
Target observation-token volume before reflection becomes useful.
--om-reflection-buffer-activation-percent <percent>
Start reflection when the reflection buffer reaches this percentage.
--om-reflection-block-after-tokens <tokens>
Block new turns once pending reflection material passes this threshold.

Admin

--reset
Delete ~/.lash/ and ~/.cache/lash/ and exit.
--info
Print current config / runtime info and exit.
--check-update / --update
Check / install the latest release.
--export <db>
Export a persisted session database. Combine with --export-format html|json, --export-trace <jsonl>, and --export-out <path>.

JSON & RPC Modes

--mode json and --mode rpc are machine-facing CLI surfaces. They do not enter the TUI and they reserve stdout for LF-delimited JSON records. The stream is versioned: the opening turn_start record (and the RPC ready record) carries protocol_version: 1, so a consumer can pin the wire shape before parsing the rest.

$ lash --mode json --print "Summarise this repository."
{"type":"turn_start","protocol_version":1,"stream_id":1}
{"type":"event","stream_id":1,"activity":{"id":"a1","correlation_id":"c1","type":"model_request_started","protocol_iteration":0}}
{"type":"event","stream_id":1,"activity":{"id":"a2","correlation_id":"call-3","type":"tool_call_completed","call_id":"call-3","name":"exec_command","args":{"...":"..."},"output":{"...":"..."},"duration_ms":41}}
{"type":"turn_finish","stream_id":1,"ok":true,"cancelled":false,"assistant_text":"...","outcome":{...},"usage":{...},"children_usage":[],"errors":[],"execution":{...},"tool_calls":[...]}

Each event wraps one TurnActivity: an id, a correlation_id, and a flattened TurnEvent tagged by type. Tool events report the runtime tool name (exec_command), not the shell.exec surface path; for the full event vocabulary and stability contract see Reporting channels.

RPC mode starts a reusable session and reads one JSON object per line from stdin. It opens with a ready record ({"type":"ready","protocol_version":1,"protocol":"lash.rpc.v1","methods":["prompt","ping","shutdown"]}). A prompt request streams turn_start, event, and turn_finish records tagged with the request id, then writes a final response.

{"id":1,"method":"prompt","params":{"prompt":"List the top-level crates."}}
{"id":2,"method":"shutdown"}

Config File

Configuration lives at ~/.lash/config.json (overridable via the LASH_HOME environment variable). The schema is defined by LashConfig in lash-cli and uses serde(deny_unknown_fields), so unknown top-level fields are rejected to catch typos.

{
  "active_provider": "openai",
  "providers": {
    "openai": { "type": "openai", "api_key": "sk-..." },
    "anthropic": {
      "type": "anthropic",
      "api_key": "sk-ant-...",
      "options": {
        "cache_retention": "long",
        "max_output_tokens": 16384
      }
    }
  },
  "auxiliary_secrets": {
    "tavily_api_key": "tvly-..."
  },
  "mcp_servers": {
    "docs": {
      "transport": "stdio",
      "command": "uvx",
      "args": ["mcp-server-docs"]
    }
  },
  "agent_models": {},
  "model_defaults": {
    "openai": { "model": "openai/gpt-5.5", "variant": "medium" }
  }
}
FieldTypePurpose
active_providerstringKey of the currently active provider; must exist in providers.
providersmapPer-provider credentials and metadata, keyed by provider kind. Shared provider tuning lives under options, including cache_retention (none | short | long) and max_output_tokens.
auxiliary_secretsobjectSecrets for non-LLM services. Currently tavily_api_key.
mcp_serversmapMCP server configs by name. Discriminated by transport: stdio, streamable_http, or sse.
agent_modelsmapUser-overridable model names per subagent capability.
model_defaultsmapFresh-session model + variant default per provider kind. Session resumes ignore this and use the persisted head.

Environment Variables

The CLI reads a small set of environment variables; most are overrides for paths or behavior the config file doesn't cover.

VariablePurpose
LASH_HOMEOverride the root data directory (defaults to ~/.lash/).
OPENAI_API_KEY / OPENAI_COMPATIBLE_API_KEYProvider API keys used during setup or one-shot sessions when no stored key is configured.
TAVILY_API_KEYTavily API key for the bundled web search tool. Alternative to --tavily-api-key and the config file.
LASH_GOOGLE_CLIENT_ID / LASH_GOOGLE_CLIENT_SECRETOverride the OAuth client credentials used by the Google / Code Assist provider.
CODE_ASSIST_ENDPOINT / CODE_ASSIST_API_VERSIONOverride the Google Code Assist API endpoint and version for provider integration testing.
LASH_COPY_BINDINGOverride the copy keystroke: ctrl-shift-c (default) or ctrl-y. Ctrl+C stays reserved for cancel semantics, so ctrl-c falls back to the default.
LASH_LOGtracing-subscriber log filter (e.g. debug, warn, lash=trace).
LASH_NO_OSC52Disable OSC 52 clipboard escape sequences.
LASH_INSTALL_DIROverride the install dir used by --update.
LASH_REPOOverride the GitHub repo used by --check-update / --update.
LASH_TOKIO_STACK_BYTESOverride the worker-thread stack size used by the CLI Tokio runtime.
GOOGLE_CLOUD_PROJECT[_ID]Google Cloud project ID for the Gemini / Code Assist provider.

Resume & Fork

Every session has a UUID and a generated human-readable name. --resume <id_or_name> accepts either, plus the legacy .db filename for old sessions. Without an argument, /resume opens an interactive picker showing the 50 most recent sessions sorted by recency. The picker hides zero-turn sessions when any non-empty session exists; direct /resume <id-or-name> may still target any session.

/fork branches the current session at the current message and opens the fork in a new terminal window. Lash resolves the launcher from the running executable and falls back to finding lash on $PATH if that binary isn't launchable. The launched fork runs lash --resume <new-session-id> in the new terminal.

read on ·