lazyclaw
v6.9.3
Published
Lazy, elegant terminal CLI for chatting with Claude / OpenAI / Gemini / Ollama, orchestrating multi-step LLM workflows, and running multi-agent Slack teams with cross-task memory. Banner-on-launch, slash-command ghost autocomplete, persistent sessions, lo
Downloads
1,905
Maintainers
Readme
lazyclaw
A terminal agent that learns on your Claude subscription — for $0 — and reaches you on every channel.
Chat in the terminal. Let the background learning loop distil your conversations into reusable skills on claude-cli (your Pro/Max subscription — no API bill). Wire it to Slack, Telegram, Discord, Matrix, Email, Signal, WhatsApp, or Voice. Fan a hard task out to a planner + workers. One small, auditable Node core — no daemon you can't read.
npx lazyclaw # first run walks you through setup, then drops into chat한국어: README.ko.md
What it is
lazyclaw is a single-binary-feel Node CLI in the "claw" family (Hermes → OpenClaw → nanoclaw). It is TUI-first: lazyclaw with no arguments opens a chat REPL with a sloth splash, slash commands, and ghost-text autocomplete. Underneath, every turn feeds a learning loop, and the same agent answers from any messaging channel you connect.
You can read the whole thing. No hosted service, no telemetry, config in plain JSON at ~/.lazyclaw/, secrets in ~/.lazyclaw/.env (0600).
Quick start
npm install -g lazyclaw # or: npx lazyclaw
lazyclaw # fresh install → guided setup, then chatThe first run is a phased wizard (Hermes-style — get one clean chat working first, then layer the rest):
- Provider + model — arrow-key picker (
claude-cliis keyless; gemini/openai/anthropic take an API key). - Verify — a one-token ping confirms the provider answers.
- Context window — how much history to keep per turn (optional).
- Channel — Slack / Telegram / Matrix / HTTP built in; Discord / Email / Voice / WhatsApp ship in-tree (need a runtime dep via
lazyclaw channels install <name>), Signal needssignal-cli(optional). - Workspace / skills / webhook (optional).
- Orchestration — turn on the planner + workers pipeline (optional).
Re-run it any time with lazyclaw setup, or /config from inside chat.
$0 self-learning
lazyclaw splits two provider slots: provider (chat — the hot path) and trainer (the learning loop — skill synthesis, reflection, the user model). They are independent, so a Claude Pro/Max subscription can power the learning while chat runs anywhere — or both run on one backend.
After every turn, a fire-and-forget loop records the trajectory and distils reusable skills, tagged trained_by. With trainer: { provider: "auto" } it auto-detects your claude-cli session and runs the loop for free; otherwise it mirrors the chat provider.
// ~/.lazyclaw/config.json
{
"provider": "openai", // chat: pay-per-token (or claude-cli, ollama, …)
"model": "gpt-4.1",
"trainer": { "provider": "auto" } // learning: $0 on your Claude subscription
}| Setup | provider | trainer | Cost |
|---|---|---|---|
| Subscription only | claude-cli | auto | $0 |
| Hybrid (recommended) | openai / any | auto | chat only |
| Pure API | openai / any | openai | both metered |
Talk to it anywhere
Connect a channel and the same agent answers there — every listener forwards into the always-on daemon's shared session store, so chat, the dashboard, and all channels are one agent with one memory (and context follows across channels). Slack, Telegram, Matrix, and HTTP are built in; Discord, Email, Voice, and WhatsApp ship in-tree and run once their runtime dependency is installed into the config dir (lazyclaw channels install <name>), and Signal needs the external signal-cli binary on your PATH.
lazyclaw service install # 1) the always-on daemon (the shared brain)
# 2) point a listener at it (Slack Socket Mode: SLACK_BOT_TOKEN + SLACK_APP_TOKEN in ~/.lazyclaw/.env)
lazyclaw slack listen # forwards inbound to the daemon, replies in-thread
lazyclaw slack listen --provider orchestrator # …and orchestrate the reply
lazyclaw slack listen --daemon-url http://127.0.0.1:19600 # non-default daemon
lazyclaw channels # view configured channels
lazyclaw channels enable|disable slack
lazyclaw channels install discord # installs discord.js into ~/.lazyclaw and enables the channelA listener is a thin forwarder: it owns the channel socket (Slack Socket Mode needs no public URL, just an app-level xapp- token) and POSTs each message to the daemon's /inbound, which binds the conversation to a persistent session and runs the provider. It needs a reachable daemon (lazyclaw service install, or lazyclaw daemon); override the target with --daemon-url / LAZYCLAW_DAEMON_URL. Set it all up from the wizard's channel step, or /channels in chat.
Run it always-on
One process, every channel: lazyclaw gateway runs the daemon core and your configured channel transports (Slack Socket Mode / Telegram long-poll / Matrix sync) in a single process — and because the channels live in-process, /handoff can notify the target channel with a resume marker (a failed notify rolls the handoff back).
lazyclaw gateway # daemon core + every enabled channel, one process
lazyclaw gateway --channels slack # explicit channel set
lazyclaw service install gateway # …and keep it alive across rebootsThe gateway is authenticated by default: it mints a bearer token on first run and persists it to ~/.lazyclaw/gateway.token (0600, never logged). Its own channels use it automatically; external callers read it from the file (--auth-token/--no-auth to override).
Or run pieces separately: the daemon is the agent core — one provider path and one session/memory store on 127.0.0.1 — and * listen commands are standalone single-channel forwarders.
lazyclaw service install # daemon only: launchd (macOS) · systemd user unit (Linux) · pidfile fallback
lazyclaw service status
lazyclaw service uninstallThe backend is auto-detected (override with --backend launchd|systemd|fallback); flags pass through, e.g. lazyclaw service install gateway --port 19600 --auth-token "$TOK" --channels slack.
Inbound channel messages are idempotent: each message's native id (Slack channel:ts, Telegram chat:message_id, Matrix event_id) is deduplicated by the daemon — a redelivery or listener-restart replay returns the recorded reply instead of running the provider twice. And every session-bound channel turn feeds the same post-task learning loop as the chat REPL (trainer auto → your Claude subscription, $0).
[!NOTE] A channel listener or the daemon refuses to start while
security.allowUnattendedSensitive=true— that flag bypasses the fail-closed tool-approval gate for every inbound message, so an always-on surface plus that flag is a remote-code-execution path. Keep sensitive-tool approval interactive.
Multi-agent orchestration
Set the provider to orchestrator and a hard request becomes Plan → Delegate → Synthesise: a planner decomposes the task, workers run the subtasks in parallel, then the planner merges the results. Workers are real agents with the tool registry.
lazyclaw orchestrator set-planner claude-cli:claude-sonnet-4-6
lazyclaw orchestrator workers add claude-cli:claude-sonnet-4-6
lazyclaw orchestrator on # route chats through the pipelineFrom chat: /orchestrator opens an on/off picker, or /orchestrator on|off|planner <spec>|worker add <spec>. Details: docs/multi-agent.md.
Drive it from chat
The REPL has slash commands for everything you'd otherwise edit config for — point-and-pick, no JSON:
| Slash | Does |
|---|---|
| /config | change one setting in-chat (provider/model/context/channel creds/webhook/…); /setup re-runs the whole wizard |
| /provider · /model | pick provider / model from a searchable list |
| /trainer [set\|fallback] · /agent edit <name> | pick the trainer / an agent's provider+model from the same list (with an auto and a custom-id row) |
| /channels [<name> on\|off\|setup] | view / toggle channels; setup sets the bot token & credentials in-chat |
| /orchestrator [on\|off\|…] | view / toggle multi-agent (picker on bare call) |
| /context [turns N\|tokens N] | resize the chat history window |
| /agentic [on\|off] · /plan [on\|off] | let chat run tools (approval-gated); plan mode is read-only "propose first" |
| /skill · /personality · /memory · /loop · /goal | skills, personas, memory, loops, goals |
/help lists them all. Autocomplete works as you type: command names (/...) and, after a command, its arguments — /login → codex-cli/gemini-cli, /hud → on/off, /channels → channel names, subcommands for /task /team /agent /personality /trainer /orchestrator, and more — appear in a popup (↑/↓ select, Enter fill). The 2-step provider→model picks (/model, /trainer set, /orchestrator planner) show a ↹ pick hint; press Tab to open the drill-in modal. CJK/Hangul input composes inside the box.
The dashboard
lazyclaw dashboard # local web UI on http://127.0.0.1:19600A framework-free SPA over the daemon's JSON API: Chat, Sessions, Workflows, Skills, Providers, Rates, Metrics, Doctor, Config, Status, Agents, Teams, Tasks, Team Live, Trainer, Recall, Sandbox, Channels — 18 tabs, dark amber theme. The Team Live tab is a real-time org view: avatar tiles with status rings + harness badges (provider · model), live agent-A→B delegation, and click-to-drill-down (harness, current task, recent activity), streamed over Server-Sent Events (GET /events).
Providers
| Chat / trainer | Auth |
|---|---|
| claude-cli | subscription (Pro/Max) — keyless |
| anthropic · openai · gemini | API key |
| ollama | local, no key |
| nim · openrouter · groq · together · xai · deepseek · mistral · fireworks | OpenAI-compatible API key |
| custom | any OpenAI-compatible v1 endpoint (your base URL + key) |
| orchestrator | meta-provider — planner + workers over any of the above |
What else it ships
- Tool registry — 12 categories (
agents,browser,coding,exec,fs,git,iot,learning,media,net,os,scheduling) plus stdio MCP. Sensitive tools (shell, write, network) are fail-closed behind an approval hook by default. - Skills — markdown instruction bundles composed into the system prompt.
lazyclaw skills starterinstalls the bundled pack (concise·korean·commit-message·code-review·channel-style·summarize·explain·debug-coach);lazyclaw skills install <user>/<repo>pulls more from GitHub;/skillspicks one in chat. - Durable recall — one SQLite + FTS5 index over sessions, skills, trajectories, and memory; rebuildable from the corpus (
lazyclaw index rebuild). Optionally blend in embedding similarity (cfg.recall.embeddings, off by default; OpenAI/Gemini key or a local Ollama model — the $0 path stays pure FTS5);lazyclaw index embedbackfills the vectors. - Loops & goals — durable foreground/
--detachloops and cron-scheduled goals that survive restart. - Personas — layered SOUL / workspace / personality / role / user-model / skills compose into the system prompt.
- Agent teams, live — build a hierarchy (a planner agent with sub-agents on different harnesses, e.g. a data-engineer on
gemini-cliand a backend onclaude-cli) via each agent'smanager; a Slack message to a team's channel auto-routes into the multi-agent loop, and the Team Live dashboard tab shows who is doing what, on which harness, and the real-time A→B delegation as it happens. - Default-on confinement — sensitive tools (
bash,python_exec/node_exec,git_*, theostools) run confined by default: writes are limited to the workspace + temp, secret dirs (~/.ssh,~/.aws, the config dir, …) are unreadable, and the secret-scrubbed env still applies. macOS usesseatbelt, Linux usesbubblewrap/firejail(auto-detected). Network is allowed; opt out withcfg.sandbox.confine=false. Runlazyclaw sandbox statusto see the effective posture. - Sandboxes —
local/docker/ssh/singularity/modal/daytonabehind one API; pluggable backends for heavier isolation (containers, remote hosts) layered on top of the default local confinement. - MCP — stdio MCP servers in
cfg.mcp.serversboot with the daemon; their tools register asmcp:<server>:<tool>(always approval-gated). Manage them from the CLI:lazyclaw mcp list/mcp add <name> --command <cmd> [--args "…"] [--allow-glob <glob>]/mcp remove <name>/mcp call <server> <tool> [--args-json '{…}'](spawns the server, runs one tool, tears it down). - Daemon lifecycle —
lazyclaw daemon status | stop | logsover a pidfile;maxTokensin config raises the output cap;LAZYCLAW_REQUEST_TIMEOUT_MSsets the per-provider idle timeout (default 120s).
Configuration & security
Config is plain JSON at ~/.lazyclaw/config.json — parsed with JSON.parse, no shell or code execution; channel + provider secrets live in ~/.lazyclaw/.env (written 0600, never logged). Move the dir with LAZYCLAW_CONFIG_DIR=/path.
Sensitive tools deny by default unless an approval hook grants them; config.json and workflow state are written owner-only; secrets are scrubbed from the bash tool's child env and redacted from trajectories and synthesised skills.
Install / hack
npm install -g lazyclaw # install
git clone https://github.com/cmblir/lazyclaw && cd lazyclaw && npm install && npm link # hack
node --test tests/*.test.mjs # run the suiteRequires Node 18+ (Node 22+ for Slack Socket Mode). macOS / Linux / WSL are first-class.
Docs
- docs/multi-agent.md — orchestrator pipeline + Slack teams
- docs/trainer-recipes.md — $0, hybrid, and
autotrainer configs - docs/persona-cookbook.md — persona compose stack
- docs/loop-goal-preflight.md — loops + scheduled goals
- CHANGELOG.md — release notes · README.ko.md — Korean
License
MIT · Source & issues: cmblir/lazyclaw
