TRANSMISSION // 2026-07-16

Forgehand: the harness that lets AI agents ship my code

AUTHOR // Marcus Braun READ // 5 MIN TAGS // AI coding · Agents · Forgejo · Self-hosting
Abstract neopunk artwork: a glowing hexagonal core orbited by small geometric agent drones connected by light filaments

These days I type very little of the code that actually ships on my infrastructure. Agents do the planning, the writing, the reviewing, the merging, even the deploy — on my own Forgejo instance, start to finish. What's left for me is writing the rules they follow, and being the person they call when something genuinely needs a human.

This is a walk through how that harness works. There's a repo at the end too: I pulled out everything specific to my setup and put it up as forgehand (MIT), so you can wire the same loop into your own forge.

The shape of it

Pipeline diagram: issue, AI plan review, implement, pull request, CI checks, AI code review, auto-merge, live — with two feedback loops
The pipeline. Magenta boxes are gates; the two dashed arcs are the loops where all the back-and-forth happens.

The whole thing rests on one observation. Once agents are writing the code, the thing that slows you down isn't typing — it's waiting for someone to review it. So I made the reviewer an AI too. It never sleeps, it's stricter than most humans I've worked with, and it sits on every stage of the pipeline. A change can travel from "issue opened" all the way to "running live on staging" without me touching it once. What keeps that from being terrifying is that every hop has a gate, a cap, and something watching it.

Planning happens in the open

Anything bigger than a one-liner starts life as a Forgejo issue with a fixed skeleton: Overview, Goals, Architecture, Phases, Risks, and my personal favourite, Out of scope. A minute or two later the reviewer bot leaves an advisory note — is this viable, what looks good, where's the scope creeping, is there a simpler way. The agent cleans up the mechanical stuff and rewrites the issue; anything that feels like a real design decision gets kicked over to me. There's a hard cap of five rounds. If an issue can't settle in five, it was never crisp enough to begin with, and me reading it will be quicker than a sixth pass.

Here's the part I enjoyed. While I was putting together this very release, the reviewer got handed the plan for publishing itself — and immediately found a real problem:

"Treat this Forgejo repository as public now, not only after the GitHub mirror: an anonymous read-only clone succeeds. Sanitization therefore has to happen before the first seed commit, not as a later mirror gate."

It was right, and a little embarrassing. That sanitization check now lives in CI and runs on every pull request.

Approval alone never merges

On a pull request the reviewer stops suggesting and starts blocking. Its default answer is "request changes," which I did on purpose — I'd rather it be a grump than a rubber stamp. So most of the loop is just this: apply the notes, push, CI runs again, the reviewer looks at the new commit again. When it finally says APPROVED, the agent merges on its own. But only after it's cleared the guard array:

Guard array diagram: CI status, no human objection, no hold label, no conflict, blast radius — all must pass before auto-merge
Five checks stand between an approval and a merge. Miss any one and it lands on a human instead, with a reason attached.

The escape hatches are built for people, not config files. Say "hold this," drop a hold label on it, or just leave a comment — the second a real human speaks up on a PR, it falls out of the automated path and waits. And a handful of files never auto-merge at all: the canonical workflow doc, the CI gates themselves. Get one of those wrong and the damage isn't one repo, it's all of them, so those always wait for someone to look.

Abstract neon artwork: translucent panels flowing through a glowing hexagonal gate

A merge is not a ship

This is the rule that's saved me the most grief: the pipeline isn't finished at "merged," it's finished at "I watched it work." After a merge the agent follows the deploy to the end, then actually calls the service to make sure the new thing is really there — the new route answers 200, the new field turns up in the JSON, the new asset is being served. It exists because of one bad night. Everything was green. CI passed, the PRs merged, and the new endpoints kept 404-ing on staging — the deploy had quietly carried a stale build through and nobody was watching that last step. Now something always is.

One doc rules the fleet

Fleet diagram: agents in isolated clones feed a central forge with AI reviewer; one canonical workflow doc cascades to every repo as sync PRs
Every issue gets its own disposable clone. One canonical doc cascades out to every repo — as ordinary PRs, through the same gate as everything else.

All those rules live in one markdown file, and both engines I run — Claude Code and opencode — read it at the start of every session. I change it in one place, a sync job opens a PR on every repo in the org, and those PRs go through the reviewer and auto-merge like any other change. Even the plumbing has to pass the gate. There's a quiet read-only auditor rounding it out, running every night: it goes through each repo looking for docs that have drifted away from the code, dead code, security bits that look off, and issues that got quietly finished but never closed — then files one findings issue per repo.

Take it

All of this is public now, as forgehand — the same harness with my hostnames and org names swapped out for placeholders, under an MIT licence:

  • the workflow doc itself — issue shape, labels, both review loops, the whole auto-merge guard list, the deploy watch;
  • the reviewer prompts for issues and PRs, plus the webhook contract so you can point them at whatever LLM runtime you already run;
  • agentwork, the little script that hands every issue its own throwaway clone — sharing one working tree is exactly how two agents end up clobbering each other;
  • Forgejo Actions templates for the doc-sync cascade, the CI gate, and the nightly audit;
  • and an honest label on every piece — runnable, template, or contract — since the reviewer's actual runtime is the one part you'll want to bring yourself.

One thing I learned the hard way: a setup like this is only as good as the moments it decides to stop. The caps, the guards, the "if the same thing fails twice, quit guessing and ask a human" rule — that's the part that actually took thought. Hand an agent the keys with none of that and you haven't built automation, you've built a faster way to page yourself at 2am. Get the stopping conditions right first. The speed turns up on its own after that.

// END_TRANSMISSION

// COMMS