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

  1. Make sure that your inventory has the builder's row. Copy integration/devnodes.example.json to ~/.config/octomy/devnodes.json if you have no inventory. The row needs a builder object:

    "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"
      }
    }
    

    brokerTask names 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.

  2. Make sure that your key opens the builder: ssh -i <key> <user>@<host> hostname.

  3. 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
Topics
howto windows msvc build kiln ssh
See also