Every CLI command, every config knob, every environment variable, every slash command.
EvoClaw ships two identical binaries with different names:
evoclaw— long-form, project-named (recommended for scripts and docs)evo— 3-letter alias (terser; same code, same behaviour)
Both call into evo_cli::entry(). Pick whichever you like.
Run with no subcommand to enter the interactive REPL — banner, status panel, slash commands, just like claude or codex:
evoclaw # interactive
# or equivalently:
evoclaw shellRun with a subcommand for one-shot non-interactive operation:
evoclaw run "..." # one task and exit
evoclaw doctor # health check and exit
evoclaw skill tree # render tree and exitThe first time you run evoclaw with no config, the onboarding wizard appears automatically. After that, the banner shows up immediately.
evoclaw [subcommand] [args]
| Subcommand | Purpose |
|---|---|
(none) / shell |
Enter interactive REPL |
onboard |
First-run setup; pick provider, write ~/.evoclaw/config.toml |
login |
Switch provider / re-enter API key (interactive wizard) |
run <input> |
Run a one-shot task; full agent loop + reflection + skill save |
doctor |
Health check: config, model, fs, api_key |
doctor-of tokens |
7-day / 30-day cost & cache stats |
doctor-of closure |
Audit recent session JSONLs against PRD §39 closure matrix |
replay [path] |
Pretty-print a session JSONL (defaults to most recent) |
skill list |
List every skill with state / score / version |
skill show <id> |
Print a skill's full YAML |
skill tree |
Rebuild & print the skill tree, grouped by kind |
memory search <query> [--limit N] |
Grep memory L1/L2/L3 |
agent ... |
External ACP agents (Claude / Codex / Cursor / Copilot) — see agents.md |
mcp ... |
MCP servers (filesystem / github / fetch / time / brave / postgres / slack) — see mcp.md |
secret ... |
Local secret vault — values never reach the model (PRD §13.4) |
gateway [--bind X --token Y] |
Spawn evo-gateway HTTP daemon |
When inside evoclaw>, type any of:
| Slash | Equivalent subcommand | Notes |
|---|---|---|
/help or /? |
(no equivalent) | Print slash command list |
/login |
evoclaw login |
Switch provider |
/agent [list/catalog/add/remove/test <id>] |
evoclaw agent ... |
ACP agent management |
/mcp [list/catalog/add/remove/test <id>] |
evoclaw mcp ... |
MCP server management |
/secret [list/add/remove/test ...] |
evoclaw secret ... |
Secret vault management |
/skill [list/tree/show <id>] |
evoclaw skill ... |
Skill management |
/memory <query> |
evoclaw memory search <query> |
Memory grep |
/tokens |
evoclaw doctor-of tokens |
Cost stats |
/closure |
evoclaw doctor-of closure |
Closure audit |
/replay [path] |
evoclaw replay [path] |
Session replay |
/doctor |
evoclaw doctor |
Health check |
/clear |
(no equivalent) | Clear screen |
/exit /quit /q |
(no equivalent) | Exit (also Ctrl-D / EOF) |
Anything not starting with / is treated as a task and runs through the agent loop, identical to evoclaw run "...".
evoclaw run "your natural-language task here"What the runtime does, in order:
- Scrub user input through the redactor (PRD §13.4) — vault values become
${SECRET:NAME}, pattern matches become[REDACTED:<kind>:<fp>]. The unscrubbed string never re-enters the pipeline. - Build system prompt (PROMPTS §1, exactly 6 lines, cached as
persistent). - Compose user message with
<history>block (last 40<summary>records) +<user_input>. - Append
TaskRecordto the per-task JSONL log under~/.evoclaw/logs/. - Loop until the model emits zero tool calls or
max_turnsis hit:- Apply tag-level compression every 5 turns.
- Pre-flight cost-budget check.
- Build
ChatRequestwithToolFingerprintshort-circuit. - Stream model events; collect tool calls and assistant text.
- Scrub assistant text and tool args through the redactor.
- Dispatch tool calls via
ToolRegistry::invoke. Built-in tools run inline; MCP-bridged tools invokemcp__<server>__<tool>against the appropriate spawned subprocess. - Scrub each tool result, append
TurnRecord, send tool results back to the model.
- Reflection round (PROMPTS §4 →
ReflectionRecord). - Distillation (PROMPTS §5 →
SkillDRAFT, saved to~/.evoclaw/skills/). - Memory L3 write (one record per task).
- EndRecord (
COMPLETEDorFAILED).
Hard caps:
max_turns = 25max_tokens = 1024per responsetemperature = 0.2
Tune via RuntimeConfig if you embed the runtime; the CLI defaults are deliberate.
| Sub | Effect |
|---|---|
add <name> [value] |
Insert/overwrite. Without a value the CLI prompts for it; with --stdin the value is read from one stdin line. |
list |
Show entries — only name, kind, fingerprint, created_at. Raw values are never printed. |
remove <name> |
Delete by name. |
test <text> |
Run the redactor on a sample string and print the scrubbed output. |
Inside the REPL the same operations are available as /secret list, /secret add NAME VALUE (or /secret add NAME for prompted entry), /secret remove NAME, /secret test TEXT….
The vault file ~/.evoclaw/secrets/vault.json is written chmod 600 on Unix:
{
"version": 1,
"entries": [
{ "name": "github_pat",
"value": "ghp_actual_value",
"kind": "github_pat",
"fingerprint": "b4824fbd",
"created_at": "2026-05-02T17:52:00Z" }
]
}What the redactor catches even without a vault entry:
| Pattern | Example | Replaced with |
|---|---|---|
sk-ant-* |
Anthropic API key | [REDACTED:anthropic_key:<fp>] |
sk-* (≥20 chars) |
OpenAI API key | [REDACTED:openai_key:<fp>] |
ghp_/gho_/ghu_/ghs_/ghr_* |
GitHub PAT | [REDACTED:github_pat:<fp>] |
AKIA* (20 alnum) |
AWS key id | [REDACTED:aws_key_id:<fp>] |
eyJ*.*.* |
JWT | [REDACTED:jwt:<fp>] |
| any 32+ char string with Shannon entropy ≥ 4 bits/char | unspecified | [REDACTED:high_entropy:<fp>] |
<fp> is a stable 8-character SHA-256 prefix — same secret always gets the same fingerprint, useful for cross-referencing without ever leaking the value.
See docs/agents.md for the dedicated guide. Quick reference:
evoclaw agent catalog # show built-in agents
evoclaw agent add claude # write profile to ~/.evoclaw/agents/claude.toml
evoclaw agent test claude # spawn `claude --acp` and run initialize handshake
evoclaw agent list
evoclaw agent remove claudeTo route the loop through an ACP agent, set provider = "acp:<id>" in ~/.evoclaw/config.toml (the wizard's "External ACP agent" option does this automatically).
See docs/mcp.md for the dedicated guide. Quick reference:
export GITHUB_PERSONAL_ACCESS_TOKEN=ghp_xxx # captured into the profile by `add`
evoclaw mcp add github
evoclaw mcp test github # spawn + initialize + tools/list
evoclaw mcp listOn every evoclaw run (and every prompt inside the REPL), the runtime walks ~/.evoclaw/mcp/, spawns each server, and registers each advertised tool as mcp__<server>__<tool> in the same ToolRegistry the built-ins live in.
If path is omitted, EvoClaw picks the most recently modified *.jsonl under ~/.evoclaw/logs/. Sections:
[TASK] <id>— task record (input, source, model, started_at)[TURN N]— per-turn summary, tool calls, usage with cache-hit %[END]— final state (COMPLETED/FAILED)
Because every text field has already been scrubbed before write, the JSONL log is safe to share for debugging.
| Sub | Effect |
|---|---|
list |
Tabular view of every *.yaml under ~/.evoclaw/skills/ |
show <id> |
Cat-style dump of one skill's YAML |
tree |
Re-scan all skills, rebuild index.json, render grouped by SkillKind |
Skills aging through the EWMA state machine:
Draft → Candidate → Active → Degraded → Deprecated
(sandbox) (≥3 wins) (score<0.7) (5 fails or score<0.3)
Only Active skills are auto-loaded into the planner. Candidate can be opted in.
evoclaw memory search "ssh timeout" --limit 10Searches L1 (preferences), L2 (env facts), L3 (task records) by case-insensitive substring on content or tags. Newest-first. Memory is append-only; deletion happens via Phase 6 GC.
evoclaw gateway --bind 127.0.0.1:7878 --token mychatSpawns the evo-gateway binary with two env vars set:
EVO_GATEWAY_BIND— TCP listen addressEVO_GATEWAY_ALLOWLIST— comma-separated bearer tokens
Routes:
| Method / Path | Auth | Action |
|---|---|---|
GET / |
none | Static WebChat HTML |
GET /healthz |
none | 200 ok |
POST /chat |
Authorization: Bearer <token> |
Body {"input": "..."}, returns {task_id, turns, final_text} |
Local-only by design. No TLS. Bind to 0.0.0.0 only on a trusted network.
[model]
provider = "deepseek" # picks the API key file + provider adapter
default = "deepseek-chat"
base_url = "https://api.deepseek.com/v1"
fallback = ["qwen-plus", "kimi-k2"]
[budget]
per_task_usd = 0.50
per_day_usd = 5.0
per_month_usd = 100.0
[security]
default_permission = "P1"
high_risk_intercept = true| Field | Type | Default | Notes |
|---|---|---|---|
model.provider |
string | deepseek |
Drives both API-key resolution and provider adapter (or acp:<id> for ACP) |
model.default |
string | deepseek-chat |
Sent as model to provider |
model.base_url |
URL | https://api.deepseek.com/v1 |
Any OpenAI-compat endpoint; ignored for ACP providers |
model.fallback |
array | [] |
(Phase 3+) used when primary fails |
budget.per_task_usd |
float | 0.50 | HardStop trigger (PRD §35) |
budget.per_day_usd |
float | 5.0 | SoftWarn (3-tier; hard cap is 4× this) |
budget.per_month_usd |
float | 100.0 | HardStop |
security.default_permission |
enum | P1 |
P0..P8 ladder |
security.high_risk_intercept |
bool | true |
Force ask_user on P5+ ops |
Permission ladder (PRD §13.1):
P0 read-only P1 workspace write P2 local-safe shell
P3 network P4 browser P5 user-dir write
P6 system P7 credentials P8 production
Channel senders are hard-capped at P4 even when default_permission is higher.
provider value |
Meaning | Where the auth lives |
|---|---|---|
deepseek kimi qwen openai openrouter |
OpenAI-compat HTTP | ~/.evoclaw/secrets/<provider>.key (chmod 600) |
anthropic |
Native Anthropic Messages API | ~/.evoclaw/secrets/anthropic.key |
copilot |
GitHub Copilot via OAuth Device Flow | ~/.evoclaw/secrets/copilot.key (refresh token) |
ollama (or other local) |
OpenAI-compat at http://localhost:11434/v1 |
(no key) |
acp:claude acp:codex acp:cursor acp:copilot |
External CLI via ACP | The CLI's own login (claude login, gh auth login, …) |
custom |
Any OpenAI-compat endpoint you set | Your own key |
| Var | Required by | Purpose |
|---|---|---|
EVO_API_KEY |
evoclaw run, evoclaw gateway, evo-gateway |
Bearer for the model provider — overrides the on-disk key |
EVO_GATEWAY_BIND |
evo-gateway |
Override 127.0.0.1:7878 |
EVO_GATEWAY_ALLOWLIST |
evo-gateway |
Comma-separated bearer tokens |
RUST_LOG |
all | tracing filter, e.g. RUST_LOG=evo_core=debug |
NO_COLOR / EVO_NO_COLOR |
evoclaw |
Suppress ANSI in the welcome banner |
API keys captured by the wizard are persisted under ~/.evoclaw/secrets/ (chmod 600). Vault entries — separate from provider keys — are stored in ~/.evoclaw/secrets/vault.json and used exclusively for redaction.
| # | Name | Permission | Purpose |
|---|---|---|---|
| 1 | read_file |
P0 | Read with line numbers |
| 2 | write_file |
P1 | Workspace-bounded write |
| 3 | patch_file |
P1 | Replace unique substring (must match exactly once) |
| 4 | list_dir |
P0 | Directory listing, excludes node_modules/.git/target |
| 5 | run_shell |
P2 | Sandboxed sh -c, 30s default timeout |
| 6 | web_fetch |
P3 | HTTPS only, cookies excluded from LLM context |
| 7 | ask_user |
P0 | High-risk / ambiguous / missing-param confirmation |
MCP-bridged tools (e.g. mcp__github__list_issues) live in the same registry but do not count against the 10-tool cap. They are wrapped as McpToolWrapper with Permission::P3 (network).
~/.evoclaw/
├── config.toml # this file
├── workspace/ # tools sandboxed here
├── logs/{task-id}.jsonl # one log per task
├── skills/{skill-id}.yaml # one YAML per skill
├── skills/index.json # skill tree summary
├── memory/{L0..L5}.jsonl # one file per memory layer
├── secrets/<provider>.key # API key per provider, chmod 600
├── secrets/vault.json # named secret vault, chmod 600
├── agents/<id>.toml # ACP agent profiles
├── mcp/<id>.toml # MCP server profiles
├── plugins/ # reserved
├── cache/ # transient
└── cost.jsonl # one cost event per turn
JSONL records are typed via kind: "task" | "turn" | "end" (evo_core::session::SessionRecord). Schemas are stable from v0.4.
| Code | Cause |
|---|---|
| 0 | success |
| 1 | runtime error (model 4xx/5xx, tool error, IO, missing key) |
| 2 | budget hard-stop (Budget(...) in error chain) |
| 130 | Ctrl-C |
# the loop
evoclaw run "..." # do work
evoclaw replay # see what just happened
evoclaw doctor-of tokens # how much it cost
evoclaw doctor-of closure # session integrity audit
# the brain
evoclaw skill list # what we've learned
evoclaw skill tree # by domain
evoclaw memory search "..." # find a fact
# the integrations
evoclaw agent catalog # ACP agents
evoclaw mcp catalog # MCP servers
evoclaw secret add github_pat # local-only key vault
# the hub
evoclaw gateway --bind 127.0.0.1:7878 # WebChat for browser users