Why I Built My Own Agent Harness (and Then a Desk for It)

Posted by Ray Thurman on 08/27/2026

Why I Built My Own Agent Harness (and Then a Desk for It)

I did not set out to write a coding agent. I set out to stop running other people's agents on a machine I actually care about.

For a while the pattern was the same. A new harness would show up, it would look useful, I would give it a repo and a token, and then something about it would feel off. Not "the model wrote a bad function" off. The other kind.

Grok Build was the first shove. In July it got caught uploading entire repositories to a cloud storage bucket, including files the agent was told not to open. That was a public incident, not something I personally intercepted. I still read it the same way everybody else did: I do not want my git history living in someone else's bucket because a CLI thought that was helpful. I unplugged it for a while. I have since gone back to Grok Build when I actually need a beefier harness. It is a capable tool. I just do not want it as the thing that sits on my laptop all day.

OpenCode was next. It is a serious open-source agent and I am not going to pretend otherwise, I still reach for it A LOT. On my machine it just used a stupid amount of memory. I run a homelab. I notice when a "helpful" process starts acting like it owns the RAM. OpenCode version 2 is also supposed to fix a lot of the memory issues that V1 had so I’ll end up giving it a shot once again.

Then Hermes. I installed it on my laptop. Later I noticed a GitHub auth token getting pinged for fourteen hours. I tracked it down to Copilot trying to authenticate for models inside Hermes. I never turned Copilot on in that install. I never used it there. It still tried. That was enough. Uninstalled the same day.

So I built Raven.

What Raven is

Raven is a small coding-agent harness in Rust. One binary. It talks to Ollama on the machine by default, or any OpenAI-compatible endpoint when I actually need a bigger model. It has a real agent loop: tools, plan mode, verification, workspace isolation.

What it does not have is the rest of the product.

No cloud auth layer. No MCP marketplace. No telemetry. No personality file pretending to be a soul. Sessions live on disk as JSONL under `.raven/sessions/`. Memory is a Markdown file I can open in any editor. If I do not put it in `.raven/MEMORY.md`, it is not remembered. That is the whole trick.

I built it to learn Rust and to have a harness that only contains the pieces I use. It is small enough to read end to end. It runs fine on a Raspberry Pi. I review everything it produces. That last part is not a disclaimer. It is the product.

Default mode is plan mode: it proposes, I approve or revise, then it runs. Agent mode exists for small edits. `--yolo` exists and I treat it like a power tool with the guard off.

On Linux it confines work with Landlock and seccomp. Shell commands go through a denylist plus an allowlist, and the denylist is not a security boundary. I wrote that in the docs on purpose. A regex is not a fortress. The point is layers plus me looking at the diff.

Work has started letting AI-assisted development through the door. Copilot is still blocked on the network. Most of the fancy stuff is blocked. Kiro and Ollama are not. Raven stays local-first and I can read the source, which is the only reason I am comfortable putting it next to real work.

Repo: Raven

Why Rust, not another Go tool

I have been Go-pilled for a while. Straw is Go. A lot of the homelab glue is Go, and I technically made an agent harness in Go…..I just did not like it. So think this as a rust rewrite and V2 maybe…. Rust is what I reached for when I wanted the harness itself to be boring in the right ways: one static binary, no runtime surprises, and a type system that complains before a tool call writes to the wrong path.

I am still early on the Rust side. That is fine. Raven is the project I am using to get good at it. If a function is uglier than it should be, that is on me, and the file is right there.

Then I needed a desk

A harness in a terminal is enough for a lot of nights. It is not always enough when I want a session list, a diff pane, and more than one agent without juggling tmux like it is 2014.

That is Hearth. It is pretty much the daily driver now. I still drop into Zed when I actually need to put my hands on the files. Raven speaks ACP, so that path works. Hearth is where the sessions live.

Hearth is a local-first control surface for coding agents. Raven, Codex, Grok. Rust and GPUI. Ravenwood colors because I already live in that palette with my Omarchy installs across pretty much everything that can run it.

Hearth is not the agent. That sentence matters. Raven owns the tools, the sandbox, and the model endpoint. Hearth starts the process, streams the events, and keeps the chat. A bare `hearth` run does not dial the edge. Sync exists, but it is opt-in over Tailscale. The tailnet is the trust boundary. If you never set `HEARTH_TAILNET_HOST`, you never talk to a hub.

Credit where it is due

Hearth is a fork of Zeron or Comet, whatever the name is truly for it zeronsh/comet. That project is excellent open source and MIT licensed. Native Rust, GPUI, local-by-default engine, optional multi-device sync. When Raven was ready enough to live outside a terminal, Zeron was the first control plane I looked at and thought, yes, this is the shape. It was using GPUI that Zed had created for their editor and I had been wanting to build something with it, I had started my own baby notebook just to try it out…but this project was at a nice point I could strip what I didn’t need or want and continue building and experiencing GPUI for myself.

I still wanted a lot of changes. Raven first-class instead of being one more harness in a list. No hosted account on the default path. Tailscale as the sync boundary instead of the cloud login. The Ravenwood theme. Less of the multi-app surface I was never going to ship. I am still working through a pile of those changes. Forking was the honest move. If you want the upstream product, use Zeron. If you want my opinionated desk on top of Raven, that is Hearth.

It has to run on the junk I already own

I do not have a rack of new workstations. Outside the homelab server, most of what I type on is old or cheap on purpose.

Hearth runs headless on two Raspberry Pis. One is a Pi 500+ with 16GB of RAM. The other is a Pi 400 with 4GB. Those boxes stay up as engines. I attach a UI when I need one.

The server is the hub. 128GB of RAM. That is where the heavier local models and the always-on piece live.

The laptop I actually carry is a 2012 15-inch MacBook Pro with 16GB of RAM. It is fourteen years old. It still works. It is also exactly the kind of machine that falls over if your "lightweight" agent thinks 8GB of overhead is a rounding error.

That constraint is the design. Raven is a single binary that is happy on a Pi. Hearth can run headed on the MacBook or headless on the Pis and talk to the hub over the tailnet when I opt into sync. I wanted the stack to stay fast on hardware I already paid for, not hardware a landing page assumes I will buy next quarter.

How I use them together

1. Install Raven so `raven` is on PATH.
2. Run `hearth`.
3. Pick harness Raven.
4. Set mode to Agent when I want full tools. Leave it on plan when the change is not cheap to undo, or just chat if I’m feeling a bit chatty with my codebase.

I am not trying to replace every agent on the internet. Grok Build still comes out when a task is bigger than I want Raven to chew. Zed still comes out when I need an editor. What I wanted was two pieces I would let near a GitHub token on a normal day: a loop I can audit, and a window that does not phone home unless I ask. And when I actually need to use a MCP server Grok or OpenCode will pop back up…for now anyways.

What this is not

It is not an autonomous "finish the company" loop. I have seen those demos. They look great until you read the git log.

It is not a marketplace. If I need a skill, it is a `SKILL.md` in the repo.

It is not finished. Raven is the harness I trust. Hearth is the desk I am still bending toward my workflow. Both will move.

Short version: I built my own coding harness after I stopped trusting the ones on my machine. One got caught shipping repos to a bucket. Another sat on a GitHub token for fourteen hours because Copilot wanted in. A third ate memory for breakfast. Raven is small and local-first. Hearth is the room I sit in while it works.

If you try them and something is dumb, open an issue. I would rather hear that than another screenshot of a chatbot with a cape.

- Raven
- Hearth
- Zeron

Sponsored
Check out these great products!

If you find my content valuable, please consider supporting me by buying me a coffee or checking out one of my recommended books on software development. Your support is greatly appreciated!