ST 01 Self-hosted · the build floor for coding agents
Agents write the code. Something has to check it.
VaporBuild is the part of my local AI stack that handles code once an agent has written it. It decides whether this machine can take another agent right now, tests each commit in a throwaway sandbox, checks that a port still behaves like the original, and takes a reviewed pull request through CI, merge and deploy.
Rust · SQLite · rootless Podman sandboxes · MCP server for Claude Code, Codex and Hermes · GPL-3.0-or-later
ST 02 Try it
The build floor, in your browser.
Five small working models of VaporBuild's rules, on sample data. Pick a moment, then press the yellow button. The “What to notice” box says what to look for. Nothing here talks to a server.
01
Can another agent start?
ST 03 What it does
Six stations, one floor.
Each station answers one question an agent, or I, would otherwise answer by guessing. Every page in its web view has a JSON twin, and agents reach the same operations over MCP.
01 · Repo map
What is each repository?
A scan of every repository records its languages, toolchain pins, build system, CI, license, inferred build and test commands, and declared dependencies: Cargo, npm, Python, Go and container images. It rescans every six hours.
02 · Capacity
Can this machine take another agent?
Before VaporAgent starts an agent or a review, it asks for a slot. Free slots are the smallest of a slot limit, available memory and spare CPU. A lease ends when its process exits, so a crashed agent never keeps a slot.
03 · Test runs
Does this exact commit pass?
A fresh rootless Podman sandbox at that commit: setup steps fetch dependencies with network, test steps run without it, in the image the repository's pins ask for. Results are kept by commit, so a second reviewer reads the first run instead of repeating it.
04 · Equivalence
Does the new version behave like the old?
Record what the original does for a set of command-line or HTTP cases, replay them against the candidate, and report every difference as a diff. A step is done only when the report is clean or every difference has a written reason.
05 · Porting
How do we move this to Rust?
Parse the repository, order its modules leaves first by the import graph, and propose a Rust module and crates for each step. Each step becomes a VaporAgent task, and it can only be marked verified with its own passing equivalence report.
06 · Ship queue
How does a reviewed change go live?
Catch the pull request up with its branch, wait for the builds branch protection requires, merge it, mirror the same tree to the code forge, and run the deploy inside a monitoring maintenance window. A restart resumes where it stopped.
ST 04 In the stack
Where it sits in the local AI stack.
VaporAgent tracks the work and VaporMemory holds what the agents know. VaporBuild knows the code. These are the hand-offs between them.
VaporAgent→VaporBuild
Reserves a slot before it starts an agent or a review. No slot, no start: the request waits and says why.
VaporBuild→VaporAgent
Keeps agents on ready issues. Once a minute it works out how many issue workers the budget allows and asks VaporAgent to start them, always leaving a slot for an agent I start myself.
Reviewer agent→VaporBuild
Asks for a test run of the exact commit under review and reads the recorded result, instead of running the suite on its own.
VaporBuild→VaporAgent
Files each porting step as a task with its acceptance written in: a clean or explained equivalence report attached to that step.
Any agent→Ship queue
Queues a reviewed pull request as itself. VaporBuild merges it under that agent's own forge account and deploys it inside a maintenance window, so the outage alerts stay quiet only for the minutes the deploy needs.
Agents→VaporMemory
Recall what they need over MCP, with every result naming its source revision. VaporBuild's own runbooks and decisions are among those sources.
ST 05 House rules
The person at the machine comes first.
The agents share a desktop I also use. While a game is running, builds, tests and sandboxes wait in line with the reason shown, and a running test is stopped and started again later. A killswitch stops everything at once, including merges and pushes.
My own agents never wait on VaporBuild: they use capacity before any background worker is budgeted, and one slot stays free for the next one I start. A full budget only stops new workers starting. A running worker is never stopped to make room.
Writes come only from local tools. The daemon listens on loopback, checks the Host header, refuses any request a browser could send, and keeps recording, comparing and porting writes out of its HTTP API altogether.
Sandbox defaults
Networknone, unless a setup step asks
Capabilitiesall dropped, no-new-privileges
LimitsCPU, memory and process caps
Toolchainimage pinned by digest
Build cacheper repository and image
Afterwardsworkspace deleted
ST 06 Limits
What it does not do.
It does not write code.
Agents write the code. VaporBuild plans, measures, tests and ships, and refuses to call a step done without evidence.
A clean report is not proof.
Equivalence covers the cases someone recorded, plus fuzzed variants of them. Behaviour no case exercises is not compared.
One machine, one operator.
It schedules work on the host it runs on, for one person's repositories. It is not a shared CI service.
Some gaps are still open.
Equivalence runs do not yet take a capacity lease, and HTTP scenarios cannot run in the sandbox yet. Both are tracked follow-ups.
The source is private because it is configured for my own estate. The demo above runs the same rules over sample data.