atagen

roundabout

public
Star0
Watch0
4e5ca2e2040139a56cdd8bc50993e0f82ceab09a
1
ssh://brewery@pls.lobotomise.me:33/atagen/roundabout.git

Blame: README.md

93b435e669a5atagen2026-09-27 03:59 UTC1
# roundabout
93b435e669a5atagen2026-09-27 03:59 UTC2
93b435e669a5atagen2026-09-27 03:59 UTC3
five agents, one machine, one youtube video. roundabout makes the builds take turns.
93b435e669a5atagen2026-09-27 03:59 UTC4
93b435e669a5atagen2026-09-27 03:59 UTC5
agents say roughly how big a build is. a tiny daemon, started on demand and gone once idle, lets it run when there's room. two heavy builds never overlap, nothing gets promised disk that isn't there, and small stuff keeps slipping through while the big one grinds. roundabout doesn't run anything itself, it just holds the door.
93b435e669a5atagen2026-09-27 03:59 UTC6
93b435e669a5atagen2026-09-27 03:59 UTC7
## use
93b435e669a5atagen2026-09-27 03:59 UTC8
93b435e669a5atagen2026-09-27 03:59 UTC9
the cli is `rabt`, short enough that agents don't mind typing it
93b435e669a5atagen2026-09-27 03:59 UTC10
93b435e669a5atagen2026-09-27 03:59 UTC11
```
93b435e669a5atagen2026-09-27 03:59 UTC12
rabt run --size m -- cargo build
93b435e669a5atagen2026-09-27 03:59 UTC13
rabt run --ram 6G --cores 8 --time 10m -- nix build .#thing
93b435e669a5atagen2026-09-27 03:59 UTC14
rabt status
93b435e669a5atagen2026-09-27 03:59 UTC15
rabt suggest -- cargo build --release
ecc1cf8df0f5atagen2026-09-27 13:36 UTC16
rabt expect --size l   # building soon, save me a seat
93b435e669a5atagen2026-09-27 03:59 UTC17
rabt watch 7        # exits when lease 7 is done or overdue
93b435e669a5atagen2026-09-27 03:59 UTC18
rabt kill 7
93b435e669a5atagen2026-09-27 03:59 UTC19
rabt extend 7 10m
93b435e669a5atagen2026-09-27 03:59 UTC20
rabt artifacts check | list | gc [--cap] | pin <path>
93b435e669a5atagen2026-09-27 03:59 UTC21
```
93b435e669a5atagen2026-09-27 03:59 UTC22
93b435e669a5atagen2026-09-27 03:59 UTC23
`run` exits with the build's code, 124 if `--deadline` killed it, 75 if `--max-wait` ran out.
93b435e669a5atagen2026-09-27 03:59 UTC24
ecc1cf8df0f5atagen2026-09-27 13:36 UTC25
a granted build gets `CARGO_BUILD_JOBS`, `MAKEFLAGS`, `CMAKE_BUILD_PARALLEL_LEVEL` and a `NIX_CONFIG` with `cores`/`max-jobs` to match its grant, so it actually uses the cores it got and no more.
ecc1cf8df0f5atagen2026-09-27 13:36 UTC26
ecc1cf8df0f5atagen2026-09-27 13:36 UTC27
the grant can be bigger than the ask. idle cores go to whoever's building, minus what other sessions have said they'll want via `rabt expect`. spare cores never hold up admission, oversubscribing cpu only slows things down, but each one is charged ram at the build's own ram per core since more jobs eat more memory. a session's build counts as an `expect` too, so agents that forget still leave a mark. `--exact` opts out.
93b435e669a5atagen2026-09-27 03:59 UTC28
93b435e669a5atagen2026-09-27 03:59 UTC29
## claude code
93b435e669a5atagen2026-09-27 03:59 UTC30
93b435e669a5atagen2026-09-27 03:59 UTC31
```
93b435e669a5atagen2026-09-27 03:59 UTC32
nix build .#plugin
93b435e669a5atagen2026-09-27 03:59 UTC33
claude plugin marketplace add ./result
93b435e669a5atagen2026-09-27 03:59 UTC34
claude plugin install roundabout@roundabout
93b435e669a5atagen2026-09-27 03:59 UTC35
```
93b435e669a5atagen2026-09-27 03:59 UTC36
052a1a49371catagen2026-09-27 03:59 UTC37
or on nixos
052a1a49371catagen2026-09-27 03:59 UTC38
052a1a49371catagen2026-09-27 03:59 UTC39
```nix
052a1a49371catagen2026-09-27 03:59 UTC40
imports = [ roundabout.nixosModules.default ];
052a1a49371catagen2026-09-27 03:59 UTC41
programs.roundabout.enable = true;
052a1a49371catagen2026-09-27 03:59 UTC42
programs.roundabout.settings.budget.ram = "16GiB";   # lands in /etc/roundabout/config.toml
052a1a49371catagen2026-09-27 03:59 UTC43
```
052a1a49371catagen2026-09-27 03:59 UTC44
052a1a49371catagen2026-09-27 03:59 UTC45
that installs roundabout and a socket-activated systemd user unit for the daemon (`socketActivation = false` to let clients spawn it instead). `programs.roundabout.claude` has read-only `hooks`, `skill` and `plugin` for whatever writes your claude config, e.g. `settings.hooks = config.programs.roundabout.claude.hooks`.
052a1a49371catagen2026-09-27 03:59 UTC46
93b435e669a5atagen2026-09-27 03:59 UTC47
the plugin brings a skill and hooks. unwrapped builds get bounced back with instructions, overdue builds get mentioned to the agent that started them, and agents over their artifact cap get told to tidy up before they stop. `rabt` needs to be on PATH for the agent too, so install `.#roundabout` alongside.
93b435e669a5atagen2026-09-27 03:59 UTC48
4e5ca2e20401atagen2026-09-28 11:42 UTC49
## codex
4e5ca2e20401atagen2026-09-28 11:42 UTC50
4e5ca2e20401atagen2026-09-28 11:42 UTC51
```
4e5ca2e20401atagen2026-09-28 11:42 UTC52
nix build .#codex-plugin
4e5ca2e20401atagen2026-09-28 11:42 UTC53
codex plugin marketplace add ./result
4e5ca2e20401atagen2026-09-28 11:42 UTC54
codex plugin add roundabout@roundabout
4e5ca2e20401atagen2026-09-28 11:42 UTC55
```
4e5ca2e20401atagen2026-09-28 11:42 UTC56
4e5ca2e20401atagen2026-09-28 11:42 UTC57
restart codex and review the plugin hooks with `/hooks` before using them. install `.#roundabout` as well so `rabt run` and `rabt expect` are on PATH. codex can also load the hooks directly from `~/.codex/hooks.json` or a trusted project's `.codex/hooks.json` using the `hooks` object in `result/plugins/roundabout/hooks/hooks.json`. use one installation route to avoid duplicate reminders.
4e5ca2e20401atagen2026-09-28 11:42 UTC58
4e5ca2e20401atagen2026-09-28 11:42 UTC59
on nixos, `programs.roundabout.codex` exposes read-only `hooks`, `skill` and `plugin`, alongside the claude options. the codex hooks deny unwrapped builds and suggest `rabt run` instead of silently rewriting the command, which keeps the normal tool approval flow intact even when `enforce.unwrapped` is set to `wrap`. `rabt run` and `rabt expect` associate builds with the current codex session, and session-end hooks release its expectation.
4e5ca2e20401atagen2026-09-28 11:42 UTC60
4e5ca2e20401atagen2026-09-28 11:42 UTC61
## omp
4e5ca2e20401atagen2026-09-28 11:42 UTC62
4e5ca2e20401atagen2026-09-28 11:42 UTC63
```
4e5ca2e20401atagen2026-09-28 11:42 UTC64
nix build .#omp-plugin
4e5ca2e20401atagen2026-09-28 11:42 UTC65
omp plugin link ./result
4e5ca2e20401atagen2026-09-28 11:42 UTC66
```
4e5ca2e20401atagen2026-09-28 11:42 UTC67
4e5ca2e20401atagen2026-09-28 11:42 UTC68
restart omp after linking. install `.#roundabout` on PATH for the agent's bash tool, or set `ROUNDABOUT_CLI` to the `rabt` binary for the extension. the plugin bundles the skill and checks shell builds before they run. it also delivers overdue reminders, checks artifact caps before the main agent stops, and releases expectations when a session closes or switches. wrapped builds and `rabt expect` inherit the omp session id through the bash tool's environment. on nixos, `programs.roundabout.omp` exposes read-only `plugin` and `skill` options.
4e5ca2e20401atagen2026-09-28 11:42 UTC69
93b435e669a5atagen2026-09-27 03:59 UTC70
## config
93b435e669a5atagen2026-09-27 03:59 UTC71
56a853ebf254atagen2026-09-27 03:59 UTC72
`~/.config/roundabout/config.toml`, falling back to `/etc/roundabout/config.toml`, or `$ROUNDABOUT_CONFIG` over both. the daemon picks up edits on save, on linux anyway. a broken config gets complained about and ignored rather than taking every agent down with it. everything's optional, these are the defaults
93b435e669a5atagen2026-09-27 03:59 UTC73
93b435e669a5atagen2026-09-27 03:59 UTC74
```toml
93b435e669a5atagen2026-09-27 03:59 UTC75
[budget]
93b435e669a5atagen2026-09-27 03:59 UTC76
ram = "75%"            # of total, or "24GiB"
93b435e669a5atagen2026-09-27 03:59 UTC77
ram_reserve = "4GiB"   # MemAvailable never drops below this on our account
93b435e669a5atagen2026-09-27 03:59 UTC78
cores = "100%"
93b435e669a5atagen2026-09-27 03:59 UTC79
disk_reserve = "20GiB" # per fs, capped at a tenth of it
93b435e669a5atagen2026-09-27 03:59 UTC80
disk_paths = ["/nix/store"]
93b435e669a5atagen2026-09-27 03:59 UTC81
psi_max = 40.0         # memory psi avg10 above this holds heavies back
93b435e669a5atagen2026-09-27 03:59 UTC82
93b435e669a5atagen2026-09-27 03:59 UTC83
[heavy]                # any one of these makes a build heavy
93b435e669a5atagen2026-09-27 03:59 UTC84
ram = "4GiB"
93b435e669a5atagen2026-09-27 03:59 UTC85
cores = "50%"
93b435e669a5atagen2026-09-27 03:59 UTC86
disk = "5GiB"
93b435e669a5atagen2026-09-27 03:59 UTC87
93b435e669a5atagen2026-09-27 03:59 UTC88
[sizes.m]              # s m l xl built in, add your own
93b435e669a5atagen2026-09-27 03:59 UTC89
ram = "2GiB"
93b435e669a5atagen2026-09-27 03:59 UTC90
disk = "1GiB"
93b435e669a5atagen2026-09-27 03:59 UTC91
cores = 4
93b435e669a5atagen2026-09-27 03:59 UTC92
time = "5m"
93b435e669a5atagen2026-09-27 03:59 UTC93
93b435e669a5atagen2026-09-27 03:59 UTC94
[queue]
93b435e669a5atagen2026-09-27 03:59 UTC95
linger = "5s"
93b435e669a5atagen2026-09-27 03:59 UTC96
backfill_max_time = "2m"
93b435e669a5atagen2026-09-27 03:59 UTC97
# max_wait = "30m"
ecc1cf8df0f5atagen2026-09-27 13:36 UTC98
elastic = true         # hand idle cores to whoever's building
ecc1cf8df0f5atagen2026-09-27 13:36 UTC99
intent_ttl = "20m"     # how long a `rabt expect` or a build keeps its claim
93b435e669a5atagen2026-09-27 03:59 UTC100
93b435e669a5atagen2026-09-27 03:59 UTC101
[overrun]
93b435e669a5atagen2026-09-27 03:59 UTC102
ram = "warn"           # or "throttle", systemd-run MemoryHigh on linux
93b435e669a5atagen2026-09-27 03:59 UTC103
ram_slack = 1.25
93b435e669a5atagen2026-09-27 03:59 UTC104
time_grace = 1.5       # overdue at this multiple of --time
93b435e669a5atagen2026-09-27 03:59 UTC105
remind_every = "5m"
93b435e669a5atagen2026-09-27 03:59 UTC106
93b435e669a5atagen2026-09-27 03:59 UTC107
[enforce]
93b435e669a5atagen2026-09-27 03:59 UTC108
unwrapped = "deny"     # "wrap" guesses a size for them, "allow" looks away
93b435e669a5atagen2026-09-27 03:59 UTC109
default_size = "m"
93b435e669a5atagen2026-09-27 03:59 UTC110
93b435e669a5atagen2026-09-27 03:59 UTC111
[artifacts]
93b435e669a5atagen2026-09-27 03:59 UTC112
project_cap = "10GiB"
93b435e669a5atagen2026-09-27 03:59 UTC113
global_cap = "60GiB"
93b435e669a5atagen2026-09-27 03:59 UTC114
idle_after = "24h"
93b435e669a5atagen2026-09-27 03:59 UTC115
size_ttl = "10m"
93b435e669a5atagen2026-09-27 03:59 UTC116
over_cap = "warn"      # "block" refuses new builds until cleaned
93b435e669a5atagen2026-09-27 03:59 UTC117
stop = "nudge"         # "block" "warn" "off"
93b435e669a5atagen2026-09-27 03:59 UTC118
nix_gc = false
93b435e669a5atagen2026-09-27 03:59 UTC119
nix_min_free = "30GiB"
93b435e669a5atagen2026-09-27 03:59 UTC120
# extra_rules = [{ name = "zig-cache", marker = "build.zig" }]
93b435e669a5atagen2026-09-27 03:59 UTC121
93b435e669a5atagen2026-09-27 03:59 UTC122
[nix]
93b435e669a5atagen2026-09-27 03:59 UTC123
inject = true
93b435e669a5atagen2026-09-27 03:59 UTC124
cores_per_job = 4
93b435e669a5atagen2026-09-27 03:59 UTC125
93b435e669a5atagen2026-09-27 03:59 UTC126
[detect]
93b435e669a5atagen2026-09-27 03:59 UTC127
# extra = ["just build"]
93b435e669a5atagen2026-09-27 03:59 UTC128
```
93b435e669a5atagen2026-09-27 03:59 UTC129
93b435e669a5atagen2026-09-27 03:59 UTC130
## license
93b435e669a5atagen2026-09-27 03:59 UTC131
93b435e669a5atagen2026-09-27 03:59 UTC132
EUPL-1.2