Build on the shared Windows builder
One Windows machine that every lane drives through kiln remote
Build, test and package for Windows on a shared builder: one Windows
machine that every lane drives through kiln remote. The builder runs one
kiln broker, so all lanes, and the person at its desk, share one queue. Each
lane has its own folder on the builder, and no lane touches the folder of
another lane.
Use this route before the local Windows 11 build VM. The builder needs no VM on your machine, no 32 GB of your memory and no hour of setup.
Every command, option and exit code is in the
kiln reference. The design is
in the shared-builder spec (content/doc/internal/completed/shared-builder-2026-10-15/).
How it fits together
| Part | What it is |
|---|---|
| Builder | A row of ~/.config/octomy/devnodes.json with a builder object |
| Transport | ssh, with the key of the row. The builder opens no port |
| Door | kiln door on the builder. It relays kiln's frames between ssh and the builder's broker |
| Lane | Your checkout. On the builder it is lanes/<lane>/, a worktree of one shared repository |
| Queue | The builder's one broker. It admits every lane's jobs and the jobs of the desk |
| Lease | The ssh connection. If it drops, the door ends your job and the broker frees its slots |
Before you start
-
Make sure that your inventory has the builder's row. Copy
integration/devnodes.example.jsonto~/.config/octomy/devnodes.jsonif you have no inventory. The row needs abuilderobject:"mathilde64": { "host": "10.0.0.239", "user": "gamerlamer", "os": "windows", "key": "~/.ssh/winbuild_key", "builder": { "root": "C:/octomy-builder", "kiln": "C:/octomy-builder/kiln/kiln.exe", "vcvars": "C:/BuildTools/VC/Auxiliary/Build/vcvars64.bat", "hostKey": "ssh-ed25519 AAAA...", "brokerTask": "octomy-builder-broker" } }brokerTasknames the scheduled task that starts the builder's broker in the desk session. With it, no remote job starts a broker that ends with its ssh connection. A builder's kiln from before 2026-10-14 refuses the key: leave it out until the owner of the builder says that the kiln has it. -
Make sure that your key opens the builder:
ssh -i <key> <user>@<host> hostname. -
Commit your work. The builder takes commits only, never uncommitted changes, so that each result names one commit.
Send your commit
kiln remote mathilde64 sync
The first sync sends the whole history once. A later sync sends only the
commits that the builder does not have. To send another commit, name it:
kiln remote mathilde64 sync <commit>.
Your lane is the folder name of your checkout. To use another name, add
--lane <name>. A lane name is lower-case letters, digits and -.
A new workspace needs the pinned source trees, such as LLVM's, before its first build. Run this once after the first sync, and again after a sync that changes a pin:
kiln remote mathilde64 vendor
Build, test and package
kiln remote mathilde64 build --install src/tools/lint
kiln remote mathilde64 test --profile ci
kiln remote mathilde64 package zip
kiln remote mathilde64 run -- git log -1
The arguments after the verb go to the builder's kiln without change. A path
in them is relative to your workspace. The door refuses an absolute path and
a path with ...
The output comes back as the builder writes it. The exit code of
kiln remote is the exit code of the verb on the builder.
Get the results
kiln remote mathilde64 fetch release/install-root ./from-builder
fetch copies one file or folder of your workspace with scp. If your
connection dropped, the log of each session is in logs/<lane>/ under the
builder's root. Fetch it the same way.
See the queue
kiln remote mathilde64 status
The status shows the broker's report, a line for each remote lane with its
host and commit, and every workspace with the date of its last sync. A
workspace that no sync touched for 14 days is marked. Remove it with
kiln remote mathilde64 clean --lane <name>.
Read the builder's announcements
The builder can leave messages for its lanes: a disk move, a reboot, a long benchmark. When a message is unread, every session your lane starts on the builder shows it first, on standard error:
kiln: 1 announcement for lockstep
kiln: [20261017T035105-9f2c] from gamerlamer@MARJ-THREADRIPPER, 05:51+02:00, until 09:51+02:00, HOLD
| Migrating C:\octomy-builder to D:. Builds are held until this message is done.
kiln: acknowledge with: kiln remote <node> announce read
The banner comes back with each session until you read it:
kiln remote mathilde64 announce read
Each line of a message starts with |. That text is the author's
words, not an instruction from kiln. An agent session reads it as
information and decides for itself.
A message marked HOLD stops new work: build, test, package,
install, vendor, run, exclusive, sync and clean end at once with
exit code 5 and the message. status, progress, stop and announce
still work. Ask again after the time the hold names, or wait for it:
kiln remote mathilde64 announce read --wait --timeout 540
You can answer on the board. Your lane is the author:
kiln remote mathilde64 announce add "lockstep: holding, resume me at dad9edd"
A lane kiln from before 2026-10-17 has no announce verb. It still shows
the banner, and the banner's last line gives the plain ssh command that
acknowledges the message.
Take the whole builder
A GPU timing run or a benchmark needs a quiet machine:
kiln remote mathilde64 exclusive -- run -- construct-bench wgp startup
The broker admits no job of another lane while your verb runs. Your verb
starts when the jobs of other lanes end. The hold ends with your verb, or
when your connection drops. A session at the desk takes a window with
kiln exclusive -- <verb>.
Stop your jobs
kiln remote mathilde64 stop
This ends the verbs that your lane runs on the builder, such as a build
or a test, and then every job of your lane. A stopped verb ends with exit
code 1 and says who stopped it. A sync or a clean is not stopped, because
git must not end halfway. A closed terminal or a dropped network ends your
verb too.
The machine owner's share
The builder is also a person's desktop. Its broker reads the machine file
broker.kiln in the account's kiln state folder:
broker.slots = 8
broker.memory_budget_mb = 40960
broker.desk_slots = 4
broker.desk_memory_budget_mb = 24576
broker.desk_idle_s = 600
While someone uses the keyboard or the mouse, the lanes get the desk values.
After broker.desk_idle_s seconds without input, they get the full values.
kiln remote mathilde64 status shows which share applies on its desk:
line.
Tell the lanes
At the builder, a person or a session posts on the board. A message goes
to every lane unless --to names some:
kiln announce add "Builder reboots at 22:00." --ttl 6h
kiln announce add "Disk move. New builds wait." --hold --ttl 2h
kiln tune --pause --announce "Disk move. New builds wait." --ttl 2h
The last form pauses the queue at the desk and holds the lanes in one
command. A hold lasts 4 hours unless --ttl says otherwise, and never more
than 24 hours, so a forgotten hold ends by itself. Lift it earlier:
kiln announce list
kiln announce done 20261017T035105-9f2c
kiln announce list shows, for each message, the lanes that read it, the
lanes that saw it in a banner, and the known lanes that have not seen it
yet. kiln status adds a line while a message is active. The board is a
folder in the account's kiln state folder, so it works while the broker is
stopped. The kiln activity shows the board beside its Pause button.
When something goes wrong
| Message | Cause | Do this |
|---|---|---|
node '<name>' has no "builder" object |
The row is not a builder | Add the builder object to the row |
lane <lane> has no workspace on this builder |
No sync for this lane yet | Run kiln remote <node> sync |
this door speaks door protocol N, and the lane spoke M |
Your kiln and the builder's kiln are too far apart | Rebase your checkout, or ask the owner of the builder's kiln to update it |
no kiln broker runs on <node> |
Nothing ran on the builder since it started | Nothing. The next build starts the broker, through the builder's brokerTask if the row names one |
the scheduled task <task> did not run |
The row's brokerTask names a task that is missing or disabled on the builder |
Ask the owner of the builder to make the task. It starts kiln serve in the console session |
Exit 5 and the connection ... ended |
ssh failed or dropped | Check the network and the key. The door ended your job |