Local-first agentic coding harness

Harness is
all you need.

Every harness is built for someone else's model. A frontier lab's, or an API you rent by the token.

Nobody builds for small models, because there is no money in it.

Cerveau does. Enough engineering around a small model that a six‑year‑old gaming card does real work, with no hype, no hidden cost and no telemetry.

$the machine proves us wrong → we change our minds
$the architecture is wrong → we rewrite it
$we get it wrong → we fix it in public
$the stack is never the point
CERVEAU 62%61°
SYSTEMv0.5.0-alpha↑ 4h 12m
CONTEXT96K tokens
MEMORYmanaged sidecar
HARDWARE
GPU62%
VRAM12.4G
CPU18%
RAM39G
Pair a device
Scan from the app, or type the code.
4F2A9C

expires in 2:00 cerveau.local/p/4f2a9c

Paired devices0
pixelthis device now
message cerveau
Pocket · Android

It keeps working
while you are out.

The agent runs on the workstation. The GPU, the RAM, the memory, all of it stays home. The phone is a way in, not a second brain: start a build on the train, watch the tool calls land, answer a question the agent asks, stop it if it goes wrong.

It reaches your machine over your own tailnet. Nothing is relayed through us, because there is no us to relay through. And if the machine is idle when you open the app, a doorbell on the network wakes the whole stack and serves you a waiting screen until it is up.

  1. 01Pairing starts at the console. Your machine prints a six-character code that is good for one use. Physical access to your own hardware is the root of trust, and nothing else can begin this.
  2. 02The phone answers with a key it cannot give away. The private half is minted inside the Android Keystore and never leaves the secure element. The machine registers the device and deletes the code.
  3. 03Every request after that is signed. Token, device signature and a one-shot nonce, so a captured request cannot be replayed. Your token sits encrypted behind your fingerprint, which is the decrypt key rather than a screen you can skip.
What it buys you

The build does not wait for you

Start it before you leave. Check the tool calls over coffee. The work happens on the workstation whether you are sitting at it or not.

You are there when it asks

An agent that needs a decision gets one in a minute instead of six hours, so a whole afternoon is not lost to a question you never saw.

Your desk comes with you

Same session, same memory, same files. A week away from the machine no longer means a week away from the work.

Who it's for

Not the tool for all. The tool for one machine — yours.

  • 01HomelabsThe workstation in the corner that already has more memory than the cloud instance you were about to rent.
  • 02Students in AI and MLOne consumer card and a lot of curiosity. That was always enough; the tooling just stopped believing it.
  • 03Small businessesCode that cannot leave the building, on hardware already sitting inside it. No accounts, no per-seat billing.
  • 04Anyone told to buy more VRAMBefore you spend on a second card rig, make sure you need that EXTRA. instead, spend an afternoon on the configuration.
The cores

Two engines. You pick the one that suits.

Cerveau exists to exploit the machine you already own, not to rent you a bigger one — and that means refusing every mandate: the flagship GPU, the cloud API, even a favourite engine. So at v0.5 the engine stopped being a position and became a Core: a whole inference runtime — engine, quantisation, KV format — behind one OpenAI-compatible URL. llama.cpp stays the default Core. vLLM joined it as the second.

The whole machine

Your CPU and your RAM are not spectators.

The prevailing wisdom is that a model either fits in VRAM or it does not run. That is true of dense models. It is not true of a mixture of experts, where only a fraction of the parameters is active for any given token — and where the rest can live in system memory without the whole thing falling apart. The two cores spend this machine differently, and neither is a compromise: llama.cpp spreads a MoE model across CPU, RAM and GPU; vLLM keeps a dense model resident on the card and batches hard. Same machine, two budgets. And a Core is only an OpenAI-compatible URL — when a third engine earns the job, it joins. We owe allegiance to your machine, not to anyone's runtime.

measured on our workstation · RTX 3090 24 GB · 16-core CPU · 128 GB DDR5
Choose a profile
--n-cpu-moe 34layers
generation 73tok/s
VRAM left 12GB

recommendedMost of the model sits in ordinary system RAM, so the graphics card only holds the part that gets used on every word. That leaves room for the full conversation history, and about half the card free — enough to keep running whatever else you use it for. 73 words a second is faster than you can read.

How it holds together

Memory is the state,
not a feature bolted on.

Latest addition

Recalled memory cannot give orders

Search results re-enter the conversation inside a marked envelope, as text the agent read — never as instructions you gave. Any closing tag inside a stored document is rewritten before it goes in, so a document indexed months ago cannot end the envelope early and have the rest of itself obeyed. Memory is a place text arrives from the outside; prompt injection through it is a real path, and this closes it.

Distillation, compiled not prompted

At every turn close the summary pass runs against a grammar compiled from a JSON schema — the sampler is constrained to it, so prose is not a shape the model can produce. What comes back is four fields: a summary, the decisions made, what is worth promoting, and what is still open. Asking politely for JSON fails eventually; a grammar cannot.

Memory never costs you the answer

If the distill truncates or fails to parse, it degrades to empty and the turn still ships. A failed write logs an error event and carries on. Memory is subordinate to the work, never the other way round.

Demotion, not summarisation

When the window fills, most harnesses summarise — and a summary is lossy the moment it is written. Cerveau swaps the bulky tool output for a pointer to its event ID. The text leaves the window; it does not leave the disk, and the agent can re-read it whenever it wants. And when compaction finally drops the oldest turns, what replaces them is a briefing rebuilt from the log — the original request, the plan, the completed steps, the files on disk — never the model summarising what it just lost.

Memory that corrects itself

New knowledge that contradicts old does not pile up beside it. A close match merges; an explicit correction marks the previous document superseded and links its replacement. Retrieval only ever sees what is still true.

Safety

Compiled in, not politely requested.

Most agents are restrained by their prompt — an instruction not to do the dangerous thing, which holds right up until it doesn't. Ask a jailbroken model to wipe the machine and a prompt is all that stands in the way. Cerveau's guard sits lower down: it is Go code at the dispatch point, reading the actual arguments of every command before anything reaches a shell. A destructive one is refused there, with the reason, and the model is told no — there is no phrasing that gets past it, because nothing is being asked.

It is a safety floor, not a sandbox: it catches the common destructive shapes, but an obfuscated command can slip past it. The file tools are genuinely jailed to the workspace, symlinks included; real containment for bash — a Landlock jail — is on the roadmap.

Local-first

It binds to localhost and stays there.

No cloud, no accounts, no telemetry. A Go core with an embedded Svelte panel, shipped as one binary, bound to 127.0.0.1. On the machine itself the local API is unauthenticated by design — it is a single-user tool sitting there listening only to you.

This is the whole stack. Cerveau never launches an engine or holds a driver — it is handed an OpenAI-compatible URL, which is why llama.cpp and vLLM are interchangeable behind it and why a third engine would need no code.

Beyond the machine, a native Android client earns its way in instead of assuming it: a P-256 key minted inside the Keystore, a token sealed behind your fingerprint, reached over your own tailnet — pairing grants a credential, not a route.

$ crv
http://127.0.0.1:7700
# one binary · no accounts · no telemetry
Patch notes

What changed — and what we changed our minds about.

For people who already know the project. When the machine proves one of our claims wrong, the claim loses; vLLM is the exhibit. This is the record.

v0.5Cores2026-08-19

The engine became a swappable Core: llama.cpp stays the default, vLLM joined it as the second. Context went to 96K — an fp8 KV cache, no speculative decoding, the mid-build failure wall three times further away. The embedder moved to the CPU, because on the shared card it was failing rather than slow. Compaction now hands over a briefing rebuilt from the log, never a gap. check_page runs JavaScript in the page and returns the value.

v0.4Pocket2026-08-18

A native Android shell reaches the harness over your own tailnet. Pairing mints a P-256 key inside the Keystore and seals the token behind your fingerprint; a trusted device can vouch for a new one, and revocation cascades through the chain. The panel was rebuilt to deserve the small screen.

v0.3Guidebook2026-08-03

The core's book of self-fixes: a mechanical failure — a busy port, an invalid regex — is repaired and retried by the registry itself, disclosed as [auto-fixed]. New tools: serve (long-lived static servers that bash used to kill), check_page, web_fetch v2. The turn timer became an idle timeout, and rm -rf is judged against the real workspace boundary.

v0.2.1RFX_UI2026-08-01

Packs ship their own control panels into the chat — declarative widgets, or a full panel in a sandboxed iframe behind an rfx bridge. Guard denials became typed by tier: sensitive means a human can approve it; catastrophic is never approvable, by anyone.

Your whole machine is waiting.

One binary, three local ports, Apache-2.0. Linux x86-64 and ARM64 today; Windows planned.