Alpha · local-first agent · written in Rust

Small models say “done”. rufous checks.

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

A small model’s report is a claim. rufous treats it like one.

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.

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.

A cheap reading of your instruction

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.

Checks when the turn ends

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.

One hold, then it lets go

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.

0.25 → 1.00

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.

33 of 36

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.

1.00

Ten turns that each stand alone, appending a section to a report: both models, every turn.

0.33 → 0.73

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

Most agents assume a frontier model. rufous assumes a laptop.

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.

Tiny prefill

Every run starts with a short system prompt and nine core tools. That's it.

  • read_file
  • create_file
  • edit_file
  • list_dir
  • run_bash
  • skills
  • todo
  • enable_tools
  • finish

Progressive disclosure

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.

  • web_search
  • web_fetch
  • memory_store
  • memory_recall
  • batch_tools
  • mcp_call
  • skills/
  • SYSTEM.md
  • AGENTS.md

The safety gate

Small models make mistakes. Yours won't become permanent.

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.

  1. Child sandboxParallel sub-agents run default-deny, write only inside their own folder and leave an audit log.
  2. Refused outrightIrreversible, system-level commands never run. There is no override.
  3. Ask before changing the environmentUninstalls and environment changes need your yes. Recursive deletes stay inside the workspace.
  4. Stay inside the boundaryPaths outside the workspace, system folders and sensitive files go to you for a decision.
  5. Keep it reversibleDeletes go to a trash folder and overwrites leave a backup, so what slips through can be undone.

Where it runs

Four ways to run rufous

rufous serve

Web UI

Sessions, every tool call with its step time, inline permission cards, a live plan and the files it touched.

desktop app · not in the alpha

Native window

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.

rufous chat · run

Terminal

Chat interactively or run a task file unattended. rufous doctor checks your setup.

rufous acp

Your editor

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

Bring your own model.

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.

  • Ollama
  • LM Studio
  • llama-server
  • OpenAI-compatible
  • Cloud providers
  • MCP servers
A rufous hummingbird perched on a bare branch, with an orange back and a red-orange throat

Why a hummingbird

Three grams. Four thousand miles.

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.

Your machine already has what it needs.

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