
FH Coder: a local coding agent that works while you sleep, and never merges unread
An interactive agent needs you in front of it. FH Coder does not. You write one intention, the work happens on the graphics cards while you sleep, and in the morning a pull request waits, tested, with its record. Nothing reaches the main branch without being read. FH stands for FreedzHost: the chain is open source, built to run entirely on local models.
What you get. A queue of small development tasks done by local models, each one isolated, verified and published as a pull request, with every run (successes included) written to a searchable journal. Short, well-framed tasks come back clean; that is the whole art of writing them.
A bit of history
The project started in summer 2026 as a "majordomo": an API that receives a request and drives an agent on its own repository. Running it day after day taught the rules that now shape it: give the agent the text, not a file path (a 9B model handed a path stopped in one turn, ten runs out of eleven); create the branch in code before the agent starts; fix the style deterministically instead of spending an agent turn on lint; and keep the publishing rights in a different account from the one that writes code.
1. Three accounts, never merged
| Account | What it does | What it holds |
|---|---|---|
| control workstation | decides, launches, reads | no token, no key on the forge |
| service account | produces code | a push key, no API token |
| publishing account | opens the pull requests, publishes | the forge token |
The account that runs the model holds nothing that could hurt you if the model went astray (see agents and authority).
2. The chain, from intention to pull request
fh-dev owner/repo "intention, closed file list, commit subject"
→ a JSON file in a shared queue directory (group-writable: no sudo needed)
→ a systemd path unit wakes the queue service, in the service account
→ the runner clones, runs the agent on a local model, verifies, pushes a branch
→ a record per run
fh-report (every 5 minutes, publishing account)
→ opens the pull request, writes the run to the knowledge base, counts failure signatures
The runner's agent is Claude Code pointed at a local model through the gateway. Before each verification, the gate runs the formatter and the linter's automatic fixes and commits them: a red lint no longer costs an agent turn.
A failure signature seen three times becomes an issue on the knowledge-pack repository: the fleet stops diagnosing the same thing twice (see knowledge packs).
3. The majordomo API
POST /v1/tasks {"intent": "...", "files": ["src/a.py", "tests/test_a.py"]} → 202 {task_id}
GET /v1/tasks/{id} → state and links
GET /v1/tasks/{id}/events → live journal (SSE)
With files, the agent's writes are physically limited to that list by a firewall. Writes through the shell are not covered: keep the sandbox too.
4. The same doctrine, interactive: the fh-coder agent in OpenFox
For the days you want to watch, OpenFox runs an agent defined in one Markdown file. Ours, fh-coder, is OpenFox's default agent here:
---
id: fh-coder
name: FH Coder
description: Writes under the FH Coder doctrine: deterministic tools decide, a test
executes, nothing superfluous in the context.
allowedTools: [read_file, write_file, edit_file, run_command, ask_user,
load_skill, web_fetch, web_search, workspace, mcp_config]
---
# Act first, then answer
When a tool can give a fact or a decision, call it first ...
Its instructions say: call the tool before writing; send every small decision to the local judge; answer in a fixed shape (the next action first, numbered steps, one concrete thing to do at the end). The shape is not decoration: it is written for a reader with ADHD, and it makes answers shorter for everyone.
5. Writing an intention that lands
- Four deliverables at most; split anything bigger.
- A closed list of files, and the commit subject.
- The data itself, pasted, not a description of where to find it.
- Always a test that runs what was written, however small.
- Read the pull request: models write plausible code that sometimes never ran.
Traps
fh-task talks to the majordomo, which only works on its own repository; fh-dev takes any repository. Sent to the wrong one, an intention makes the agent search for files that do not exist.
Start nothing when no model is loaded on a card: a run on an empty card fails after minutes. Ask the GPU grid first (see the GPU grid).
Sources
Found this useful? Tell us what to measure next.