A record the model can’t edit
Every tool call goes on rufous’s own record: the tool, the path or command, whether it landed and its exit code. Writes you declined go there too.
Alpha · local-first agent · written in Rust
rufous is an agent harness for 2B–12B models on your own machine, in your editor or its own web UI. It keeps a record of every tool call that the model can’t edit, and before a turn ends it checks the model’s report against it: the file you named that never got written, the write you declined, the refusal the model only remembers.
curl -fsSL https://rufous.chat/install.sh | sh
One binary for macOS and Linux, a zip for Windows · Apache-2.0 · No account, no telemetry
How it checks
Give a 4B model one clear instruction and it usually does it. Three turns into a conversation it often does something close to what you asked and reports success, because it follows the most recent text in front of it, not the state of your files. rufous can’t make the model remember. It can check.
Every tool call goes on rufous’s own record: the tool, the path or command, whether it landed and its exit code. Writes you declined go there too.
Which files you named with a write in mind, and where they live. Plain rules, no second model, tested against a labelled set so that every change to them is measured.
Named a file it never wrote? Wrote it in the wrong folder? Wrote the name you declined somewhere else? The reply is held, with the paths that are missing.
A hold says what is missing and fires once per turn. An honest “I couldn’t, because…” always passes. rufous never loops a turn to force an answer.
Measured, not promised
Scripted conversations on two 4B models, qwen3.5:4b and gemma4:e4b, run three to six times each. The samples are small and the numbers are early. The scripts, every run and the changelog are in the repository.
Four turns that each build on the last (write a task list, tick one off, add more): the share of turns qwen3.5:4b gets right, before and after the checks. gemma4:e4b: 0.58 → 0.83.
You deny a write, then say “try again”: how often the model actually tries again. rufous presents its earlier refusal as a record line, not as the model’s own words.
Ten turns that each stand alone, appending a section to a report: both models, every turn.
A rule set in turn one (“start every reply with OK”), kept across five turns by qwen3.5:4b, after turns stopped ending in a status report and started ending in a reply.
Built for small models
A 3B model can't read 20,000 tokens of instructions before it starts. So rufous starts small and lets the model reach for more only when the task needs it.
Every run starts with a short system prompt and nine core tools. That's it.
Web, memory and MCP tools switch on with enable_tools. Skills are listed by name and loaded when used. A SYSTEM.md or AGENTS.md adds per-folder instructions.
The safety gate
Every tool call passes through five rings, each with one job. When you're at the keyboard, rufous asks. When you're not, it refuses.
Where it runs
Sessions, every tool call with its step time, inline permission cards, a live plan and the files it touched.
The same interface in its own window, with voice input transcribed on-device. In development; the alpha ships the web UI, the terminal and the editor agent.
Chat interactively or run a task file unattended. rufous doctor checks your setup.
Zed over the Agent Client Protocol, with diffs, a live plan and the gate as the editor’s permission dialog. Other ACP clients should work; Zed is the one we test.
$ rufous doctor offline mode : false engine : Ollama · http://127.0.0.1:11434 models : 6 $ rufous run qwen3.5:4b task.md ~/code/billing $ rufous acp --model qwen3.5:4b # your editor's agent, over stdio
Ollama, LM Studio, llama-server or any OpenAI-compatible endpoint. Switch to a cloud provider for a hard task and back again; Offline mode switches the cloud, web tools and remote MCP servers off. Per-model profiles tune each family so it behaves.
Why a hummingbird
The rufous hummingbird weighs about three grams, yet it makes one of the longest migrations of any bird for its size: from Mexico to Alaska and back, every year. Small doesn't have to mean limited. That's the bet rufous makes on small models.
And yes, rufous means rust-coloured. It's written in Rust.
The choice of a bird also serves as a nod to the Mingbird paper.
One command puts the rufous binary in ~/.local/bin, after checking its checksum. No sudo, no build. Then point it at a model you already run and give it something to do.
curl -fsSL https://rufous.chat/install.sh | sh