A fast, interactive terminal client for chat completions with tool execution. Built primarily as the command line interface for AURA by Mezmo, but works with any OpenAI-compatible API — plug in your own models, agents, or LLM endpoints.
# Default build (standalone + HTTP — builds agents in-process from TOML config)
cargo build -p aura-cli --release
# HTTP-only mode (lightweight, no agent/MCP dependencies)
cargo build -p aura-cli --release --no-default-featuresThe binary will be at target/release/aura.
# Using environment variables
export AURA_API_URL="https://api.example.com"
export AURA_API_KEY="your-api-key"
aura
# Or pass flags directly
aura --api-url "https://api.example.com" \
--api-key "your-api-key"Standalone mode is enabled by default. The CLI loads agent configs directly and runs without an HTTP server. When --api-url is not set, standalone mode activates automatically:
# Uses config.toml in the current directory by default
aura
# Single TOML config file
aura --config path/to/agent.toml
# Directory of TOML configs (enables /model switching between agents)
aura --config configs/
# One-shot query in standalone mode
aura --config agent.toml --query "hello"
# Select a specific agent from a config directory
aura --config configs/ --model "Math Agent"In standalone mode, the CLI builds agents in-process using the same code paths as aura-web-server. MCP tools from the TOML config are available. CLI local tools (Shell, Read, Update, ...) become available when both sides opt in — pass --enable-client-tools and set [agent].enable_client_tools = true in the loaded TOML config (single-agent configs only; orchestrated configs drop client tools). See Client-Side Tools for details. The /model command works identically — it lists all loaded configs and lets you switch between them.
New to AURA? aura init walks you through creating a ready-to-run config.toml — no hand-editing TOML required.
aura init # interactive; writes ./config.toml
aura init -o my.toml # choose the output pathIt will:
- Sense your environment for a provider API key (
OPENAI_API_KEY,ANTHROPIC_API_KEY, …) and suggest that provider. - Pick a provider from a validated list (openai, anthropic, bedrock, gemini, ollama, openrouter).
- Handle the API key: if the provider's conventional env var is already set it asks whether to use it; otherwise it prompts for the key (input is masked). The generated config references the key by its native env var (
api_key = "{{ env.OPENAI_API_KEY }}") — secrets are never written intoconfig.toml. - Verify & list models: it queries the provider's live model list and shows a short, curated shortlist (newest per family — pick by number, accept the default, or type any id). For Ollama it lists whatever you have installed.
- Write
config.toml, plus a.envonly when you enter a new key that isn't already in your environment. The.envholds a secret — add it to your.gitignore.
aura-web-server and the standalone CLI load .env automatically at startup, so a config generated here runs as-is.
| Flag | Description |
|---|---|
-o, --output <PATH> |
Output config path (default config.toml). |
--provider <P> |
Provider: openai, anthropic, bedrock, gemini, ollama, openrouter. |
--model <ID> |
Model id (skips the model picker). |
--api-key-env <VAR> |
Env var to read the key from (default per provider). |
--region <R> |
AWS region (bedrock only). |
--base-url <URL> |
Base URL (ollama only; default http://localhost:11434). |
--name <NAME> |
Agent name written to the config (default assistant). |
--offline |
Skip live model-list verification. |
--non-interactive |
Fail on missing values instead of prompting (automatic when stdin isn't a TTY). |
--force |
Overwrite an existing config without asking. |
For scripted/CI use, supply the required values as flags:
aura init --provider openai --model gpt-4o --non-interactiveAURA CLI supports two backends, selected by the presence of --api-url:
| Backend | When | Dependencies | Tools |
|---|---|---|---|
| Direct (standalone, default) | No --api-url flag |
Full AURA stack (agents, MCP, providers) | MCP tools from TOML config; CLI local tools when --enable-client-tools is set |
| HTTP | --api-url <URL> |
Lightweight — just HTTP client | Server-side MCP tools always; CLI local tools when both sides opt in (see below) |
Both backends produce identical SSE event streams and share the same stream parser (process_sse_events), so all CLI features (stream panel, tool display, orchestration events, etc.) work identically regardless of backend.
The standalone-cli Cargo feature is enabled by default. It includes the full agent framework, MCP integration, and provider support. To build a lightweight HTTP-only client with no agent or MCP dependencies, disable default features:
# Default build — standalone + HTTP
cargo build -p aura-cli
# HTTP-only — small binary, fast compile, no agent dependencies
cargo build -p aura-cli --no-default-features- Interactive REPL with conversation history, streaming responses, and markdown rendering
- One-shot mode for scripting and pipelines (
--query) — stdout is the raw assistant response, no markers or markdown rendering - Local tool execution — the model can read files, search code, list directories, run shell commands, and edit files on your behalf
- Standalone mode (default) — run agents directly from TOML config without a web server
- Conversation persistence — pick up where you left off with
--resumeor/resume - Tab completion — cycle through matching models and conversations with
Tab/Shift+Tab - Model selection — browse and select models from the server (or loaded configs in standalone mode)
- Permission system — control which local tools are allowed, denied, or prompted before execution
- SSE streaming — real-time token-by-token output with a toggleable event panel
- Auto-compaction — automatic context management when conversations grow large
- Mid-stream commands — execute slash commands while the model is still streaming
- Works with any OpenAI-compatible API — not locked to a single provider
| Variable | Description | Default |
|---|---|---|
AURA_API_URL |
Base API URL (paths like /v1/chat/completions are appended automatically) |
http://localhost:8080 |
AURA_API_KEY |
Bearer token for authentication | (none) |
AURA_MODEL |
Model name to use (in standalone mode, selects agent by name/alias) | (none — omitted from request, server picks default) |
AURA_EXTRA_HEADERS |
Additional HTTP headers as comma-separated key:value pairs (e.g. x-chat-session-id:foo,authorization:Bearer …); overrides the auto-injected x-chat-session-id |
(none) |
AURA_ENABLE_FINAL_RESPONSE_SUMMARY |
Generate a one-line LLM-based title for each final response (adds an extra round-trip per turn). Set to true or 1 to enable. |
false |
AURA_ENABLE_CLIENT_TOOLS |
Advertise CLI local tools to the model and execute them locally (see Client-Side Tools) | false |
AURA_LOG_FILE |
Path to a file for diagnostic tracing logs. Unset → no logging. Set → events are appended to the file in both REPL and one-shot mode (see Logging) | (none — no logging) |
aura [OPTIONS]
| Flag | Env Equivalent | Description |
|---|---|---|
--api-url <URL> |
AURA_API_URL |
Base API URL |
--api-key <KEY> |
AURA_API_KEY |
Bearer token for authentication |
--model <MODEL> |
AURA_MODEL |
Model name (HTTP: starting model; standalone: selects agent by name/alias) |
--system-prompt <PROMPT> |
— | System prompt (HTTP: see note below; standalone: append/replace agent prompt) |
--query <QUERY> |
— | Run a single query and exit (one-shot mode) |
--resume <ID> |
— | Resume a previous conversation by ID or prefix |
--force |
— | Bypass warnings and non-critical errors (useful in one-shot/query mode) |
--enable-client-tools[=<bool>] |
AURA_ENABLE_CLIENT_TOOLS |
Advertise CLI local tools to the model (default: disabled — see Client-Side Tools) |
--enable-final-response-summary[=<bool>] |
AURA_ENABLE_FINAL_RESPONSE_SUMMARY |
Generate a one-line LLM title for each final response (adds an extra round-trip per turn; default: disabled) |
--standalone |
— | Force standalone mode (default when --api-url is absent; mutually exclusive with --api-url flag, but overrides AURA_API_URL env var) |
--config <PATH> |
— | Path to TOML agent config file or directory (standalone mode; defaults to config.toml) |
--log-file <PATH> |
AURA_LOG_FILE |
Append diagnostic tracing logs to this file. Omit for no logging (see Logging) |
Precedence: CLI flags > environment variables > project cli.toml > global cli.toml > defaults.
The CLI looks for a TOML preferences file in two places, with the project file overriding the global one on a per-field basis:
| File | Purpose |
|---|---|
~/.aura/cli.toml |
Global defaults (across all projects) |
<project>/.aura/cli.toml |
Project-local override, found by walking up from $PWD |
The project lookup walks up from the current working directory until it finds a
.aura/ directory (the same convention used by .git, .editorconfig, etc.).
Run the CLI from anywhere inside your project tree and the closest .aura/cli.toml
wins. $HOME is explicitly skipped so the global file is never picked up twice.
Renamed from
config.toml. Older versions read~/.aura/config.toml. The file is still read with a one-time deprecation warning — rename it tocli.tomlat your convenience. The old name collided with AURA agent config TOMLs and will stop being read in a future release.
# ~/.aura/cli.toml or <project>/.aura/cli.toml
api_url = "https://api.example.com"
api_key = "your-api-key"
model = "gpt-4o"
system_prompt = "You are a helpful assistant."
enable_client_tools = true # opt in to local tool execution; default is false
log_file = "/tmp/aura.log" # append-only; see Logging section belowNote on system prompts: In HTTP mode,
--system-promptis intended for OpenAI-compatible backends that support system messages. AURA's server ignores system role messages — the CLI will prompt you to confirm whether you're connecting to AURA or another service. In standalone mode,--system-promptcan append to or replace the agent's TOML-configured system prompt (you'll be asked which). In one-shot mode (--query), standalone silently appends; HTTP mode requires--force.
Don't commit secrets. A project
cli.tomlchecked into source control will shareapi_keywith everyone who clones the repo. Keep secrets in~/.aura/cli.toml, inAURA_API_KEY, or pass them with--api-key.
Any value set here is overridden by environment variables or CLI flags.
--query <text> runs a single round of the conversation and exits. The
output contract is strict: stdout contains only the raw assistant
response — exactly what the model produced, with no bullet markers, no
themed headers, no tool-execution summaries, no markdown rendering, and no
trailing response-summary line.
Anything that isn't the response goes to stderr:
- Diagnostic logs from
--log-file/AURA_LOG_FILE(file destination unchanged; the file is the same destination in REPL and one-shot mode) - Permission prompts for local tools (interactive, on TTY)
- Errors and warnings (with
error:/warning:prefixes, no markers) - The "no result for server tool X — set
AURA_CUSTOM_EVENTS=true" hint
This means typical pipe usage works without scrubbing:
aura --query "summarize the README" > summary.md
aura --query "list three ideas as JSON" | jq .
aura --query "what's the version?" 2>/dev/null | tee log.txtExit code follows the standard contract: 0 ⇒ stdout is the complete
response; non-zero ⇒ stderr explains why and stdout is empty.
The REPL retains its rich formatting (bullet markers, markdown rendering,
tool-call summaries, animated headers). The strict-output rules above
apply only to --query mode.
Once inside the REPL, the slash commands below are available. All slash commands can be executed while output is streaming.
| Command | Description |
|---|---|
/help |
Show available commands and keyboard shortcuts |
/clear |
Start a new conversation (saves the current one first) |
/expand |
Toggle expanded/compact tool call view |
/stream |
Toggle SSE event stream panel |
/conversations |
List saved conversations |
/resume <filter> |
Resume a saved conversation by ID prefix or name |
/rename <name> |
Rename the current conversation |
/model <filter> |
Browse and select a model (see Model Selection) |
/style [name] |
Switch visual style: normal, high-contrast, no-colors |
/quit or /exit |
Exit the REPL |
| Key | Action |
|---|---|
Enter |
Submit input |
Ctrl+C |
Cancel the current streaming request, or exit if idle |
Ctrl+L |
Clear the current input line; if the line is empty, clear the screen |
Tab |
Cycle forward through matches (in /model and /resume) |
Shift+Tab |
Cycle backward through matches |
Esc |
Cancel tab-completion selection, or exit stream panel focus |
Up / Down |
Navigate input history |
Page Up / Page Down |
Jump 10 entries through input history |
When the stream panel is visible, arrow keys and page keys scroll through SSE events instead. Press Esc to exit stream panel focus.
Use /model to browse and select which model to use for requests.
/model # list all available models
/model gpt # filter models matching "gpt"
/model gpt-4o # select "gpt-4o" if it matches exactly or uniquely
In HTTP mode, the model list is fetched from the server's /v1/models endpoint. In standalone mode, it comes directly from the loaded TOML configs (each config's alias or name becomes a selectable model).
Enabling client-side tools gives an LLM the ability to execute commands on your machine. That includes running shell commands, reading and modifying files, and searching your filesystem — with the same privileges as the user running
aura. Treat--enable-client-toolsas functionally equivalent to handing the model a shell prompt.The risks are real:
- Prompt injection. Anything the model reads — a file, a tool output, an MCP response, a webpage retrieved by another tool — can contain instructions that hijack the model into running destructive commands (
rm -rf, exfiltrating secrets, modifying source code, etc.).- Hallucination. The model can confidently call the wrong tool with the wrong arguments. There is no undo for a
Shell("rm ...")call.- No sandbox. Tools run directly on the host. There is no container, no chroot, no syscall filter. If you can run it from your shell, the model can run it through the CLI.
- The permission system reduces blast radius but is not a security boundary. Globs are easy to over-grant (
Shell(*)allows anything). Treat allow-rules conservatively and prefer prompt-on-execute for anything sensitive.Only enable when:
- You trust the model and provider.
- You trust every input the model can read (configs, MCP servers, vector stores, URLs).
- You are running in a workspace where worst-case loss (deleted files, leaked credentials, modified source) is acceptable or recoverable from version control / backups.
Disabled by default. Opting in is your decision and your responsibility.
By default, AURA CLI is a pure chat client — no local tools are advertised to the model and the REPL never executes anything on the host. Pass --enable-client-tools (or set AURA_ENABLE_CLIENT_TOOLS=true) to opt in to local tool execution, at which point the model can call tools like Shell, Read, and Update and the REPL runs them locally with permission checks.
# Disabled (default) — chat only
aura
# Enabled — local tools available, gated by the permission system
aura --enable-client-tools
AURA_ENABLE_CLIENT_TOOLS=true aura
# Explicitly disable (overrides config file)
aura --enable-client-tools=falseWhen enabled, the CLI sends a tools field on every request describing the local tools (Shell, Read, Update, ListFiles, FindFiles, SearchFiles, FileInfo). The server registers them as passthrough tools — the LLM sees them as callable, but instead of executing server-side, the stream terminates with finish_reason: "tool_calls". The CLI then executes the tool locally (after permission checks), appends the result to the conversation as a role: "tool" message, and submits a follow-up request. This keeps the permission system, Update grouping, and other interactive UX firmly in the REPL.
Single-agent configurations only. Client-side tools are not supported when the selected config has
[orchestration].enabled = true. Tools advertised to an orchestrated config are dropped with a warning. Use a single-agent config (no[orchestration], orenabled = false) to enable local tools.
Both halves of the system gate this independently — and both must opt in for local tools to fire, in HTTP mode and standalone mode alike. Standalone is not a special case: it uses the same handler path as aura-web-server, so the agent's [agent].enable_client_tools = true is required there too. The CLI side has a single switch (--enable-client-tools) that turns advertisement on or off. The server side is per-agent in TOML — [agent].enable_client_tools = true opts the single-agent config in, with an optional client_tool_filter = ["..."] glob list. There is no server-wide --enable-client-tools flag.
| Mode | TOML side ([agent].enable_client_tools) |
CLI side (--enable-client-tools) |
Effective |
|---|---|---|---|
| Standalone, single-agent, both on | true |
required | Local tools fully enabled |
| Standalone, single-agent, TOML off | absent / false |
(any) | Tools advertised but the in-process server silently drops them; CLI prints a startup warning |
| HTTP, single-agent, both on | true |
required | Local tools fully enabled |
| HTTP, single-agent, agent off | absent / false |
(any) | Tools advertised but server silently drops them — no local tools |
| Standalone or HTTP, orchestrated | any orchestrated config | (any) | Tools advertised but server drops with warning — orchestration unsupported |
| Both off | absent / false |
CLI without flag | Pure chat |
Precedence for resolving the CLI flag: --enable-client-tools argument or AURA_ENABLE_CLIENT_TOOLS env var > <project>/.aura/cli.toml > ~/.aura/cli.toml (enable_client_tools = true|false) > default (false). The CLI arg and env var sit at the same tier — either one will override values set in cli.toml.
If local tools never fire when you expect them to, check that both sides are opted in: the agent's TOML has enable_client_tools = true (and the config is single-agent), and --enable-client-tools is set on the CLI. In standalone mode the CLI prints a startup warning when the flag is set but no loaded config opts in.
AURA CLI includes a permission system that controls which local tools the model is allowed to execute. Permission rules only matter when client-side tools are enabled (see Client-Side Tools). Configure permissions by creating a .aura/permissions.json file in your project directory:
{
"permissions": {
"allow": ["ListFiles(*)", "Read(*)", "FindFiles(*)", "SearchFiles(*)"],
"deny": ["Shell(*)"]
}
}- Allow rules — matching tools execute immediately without prompting.
- Deny rules — matching tools are blocked with a guidance message.
- No match — tools with no matching rule prompt you for approval.
The CLI walks up from the current working directory to find the closest
.aura/permissions.json, the same way it finds cli.toml. Permissions are
project-scoped only — there is no ~/.aura/permissions.json. Running the
CLI from outside any project directory means no permissions are loaded, and
every local tool call prompts.
Renamed from
settings.json. Older versions read.aura/settings.json. The file is still read with a one-time deprecation warning; new "always allow" rules accepted at the prompt are written topermissions.json, migrating any existing rules forward.
| Tool | Description |
|---|---|
Read |
Read file contents (supports chunked reading with offset and limit) |
ListFiles |
List directory contents |
SearchFiles |
Search file contents with regex or literal patterns |
FindFiles |
Find files recursively by glob pattern |
FileInfo |
Get file or directory metadata |
Shell |
Execute shell commands (last resort) |
Update |
Signal intent to modify or create files |
CompactContext |
Compact conversation history by discarding older messages |
Conversations are automatically saved to ~/.aura/conversations/ and can be resumed:
aura --resume abc123 # from the CLI
/conversations # list saved conversations
/resume abc123 # resume by ID prefix
/rename my chat # name the current conversationThe CLI is silent by default — no tracing events are emitted unless you opt
in by pointing the CLI at a log file. When set, fmt events are written to that
path in both REPL and one-shot mode so stdout (and any pipe consuming it)
stays untouched.
Three places can supply the path, in precedence order:
| Source | Form |
|---|---|
| CLI flag | --log-file /tmp/aura.log |
| Environment | AURA_LOG_FILE=/tmp/aura.log |
cli.toml |
log_file = "/tmp/aura.log" |
The file is opened in append mode and created if missing. The default
filter mirrors aura-web-server's verbose mode (info-level for aura crates
and rig request handling); override it with RUST_LOG if you need different
levels.
Log rotation, truncation, and pruning are your responsibility. The CLI appends indefinitely — it never truncates, rotates, or compresses the file. Use
logrotate, a cron job,truncate -s 0, or a shell wrapper to keep the file from growing unbounded.
When running in standalone mode (the default when --api-url is absent), the
CLI runs the agent in-process. Set OTEL_EXPORTER_OTLP_ENDPOINT and the CLI
will install an OpenTelemetry layer alongside (or instead of) the file fmt
layer — the same trace structure (agent.stream → agent.turn →
mcp.tool_call, with orchestration.* between them in orchestration mode)
that aura-web-server exports. The CLI mirrors the server's
.instrument(info_span!("agent.stream")) wrapper around execute_completion
in crates/aura-cli/src/backend/direct.rs, so input/output attributes,
token counts, and tool spans all land in the right place.
The CLI omits the chat_completions / streaming_completion infrastructure
spans because there is no HTTP layer in standalone mode — those live on a
separate trace in the server. HTTP-mode CLIs skip OTel entirely: your
traces come from the server process.
OTel init is independent of --log-file; you can run with traces only
(no log file), logs only (no OTel endpoint), or both. The CLI builds a
single tokio runtime in main and threads it into Backend::from_config,
run_oneshot, and run_repl — logging::init runs inside that runtime's
context so the OTLP gRPC exporter can grab Handle::current() during
construction, and the BatchSpanProcessor worker lives on the same
runtime that drives the request loop. main flushes via
aura::logging::shutdown_tracer() before the runtime drops so trailing
spans aren't lost.
Other relevant OTel env vars (read by the aura crate, unchanged from the
server):
| Variable | Purpose |
|---|---|
OTEL_EXPORTER_OTLP_ENDPOINT |
OTLP collector endpoint (gRPC). When unset, no OTel layer is installed even in standalone mode. |
OTEL_SERVICE_NAME |
Resource attribute (defaults to aura). |
OTEL_LOG_LEVEL |
Override the OTel layer's filter. Default captures aura=trace, aura_cli=info, and rig spans. |
OTEL_RECORD_CONTENT |
When true, prompt/completion/tool args/results are recorded as span attributes. |
OTEL_CONTENT_MAX_LENGTH |
Max bytes for content attributes (default 1000, rounded down to UTF-8 boundary). |
Toggle with /stream to see raw SSE events in real time. Supported event types:
aura.tool_requested/aura.tool_start/aura.tool_completeaura.usage/aura.tool_usageaura.progress/aura.session_info/aura.reasoningaura.orchestrator.*— multi-agent orchestration events
Events are shared types from the aura-events crate, ensuring identical parsing between HTTP and standalone modes.
AURA CLI speaks the standard OpenAI Chat Completions API and works with any compatible backend:
- AURA by Mezmo
- OpenAI API / Azure OpenAI
- Local models via Ollama, LM Studio, vLLM, etc.
- Any service implementing
/v1/chat/completions
When client-side tools are enabled, both backends execute server-side tools (MCP, RAG) within the agent's stream and pause for client-side tools (Shell, Read, ...) to be executed in the REPL with permission checks. The CLI follows up with a role: "tool" result and the agent resumes. Server-side tool results arrive via aura.tool_complete SSE events; the CLI uses those rather than executing locally.
When --enable-client-tools is off, the CLI only sees server-side tool execution. See Client-Side Tools for the full flow.
# Build (default — standalone + HTTP)
cargo build -p aura-cli
# Build (HTTP-only — lightweight, no agent dependencies)
cargo build -p aura-cli --no-default-features
# Run tests
cargo test -p aura-cli # default (standalone + HTTP)
cargo test -p aura-cli --no-default-features # HTTP-only path
# Clippy
cargo clippy -p aura-cli --all-targets
cargo clippy -p aura-cli --no-default-features --all-targets
# Run directly
cargo run -p aura-cli -- --config agent.toml # standalone (default)
cargo run -p aura-cli -- --api-url "http://localhost:8080" # HTTP mode