atagen

roundabout

public
Star0
Watch0
ecc1cf8df0f5b88c6bf2cd07254c98d13827cd26
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
93b435e669a5atagen2026-09-27 03:59 UTC49
## config
93b435e669a5atagen2026-09-27 03:59 UTC50
56a853ebf254atagen2026-09-27 03:59 UTC51
`~/.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 UTC52
93b435e669a5atagen2026-09-27 03:59 UTC53
```toml
93b435e669a5atagen2026-09-27 03:59 UTC54
[budget]
93b435e669a5atagen2026-09-27 03:59 UTC55
ram = "75%"            # of total, or "24GiB"
93b435e669a5atagen2026-09-27 03:59 UTC56
ram_reserve = "4GiB"   # MemAvailable never drops below this on our account
93b435e669a5atagen2026-09-27 03:59 UTC57
cores = "100%"
93b435e669a5atagen2026-09-27 03:59 UTC58
disk_reserve = "20GiB" # per fs, capped at a tenth of it
93b435e669a5atagen2026-09-27 03:59 UTC59
disk_paths = ["/nix/store"]
93b435e669a5atagen2026-09-27 03:59 UTC60
psi_max = 40.0         # memory psi avg10 above this holds heavies back
93b435e669a5atagen2026-09-27 03:59 UTC61
93b435e669a5atagen2026-09-27 03:59 UTC62
[heavy]                # any one of these makes a build heavy
93b435e669a5atagen2026-09-27 03:59 UTC63
ram = "4GiB"
93b435e669a5atagen2026-09-27 03:59 UTC64
cores = "50%"
93b435e669a5atagen2026-09-27 03:59 UTC65
disk = "5GiB"
93b435e669a5atagen2026-09-27 03:59 UTC66
93b435e669a5atagen2026-09-27 03:59 UTC67
[sizes.m]              # s m l xl built in, add your own
93b435e669a5atagen2026-09-27 03:59 UTC68
ram = "2GiB"
93b435e669a5atagen2026-09-27 03:59 UTC69
disk = "1GiB"
93b435e669a5atagen2026-09-27 03:59 UTC70
cores = 4
93b435e669a5atagen2026-09-27 03:59 UTC71
time = "5m"
93b435e669a5atagen2026-09-27 03:59 UTC72
93b435e669a5atagen2026-09-27 03:59 UTC73
[queue]
93b435e669a5atagen2026-09-27 03:59 UTC74
linger = "5s"
93b435e669a5atagen2026-09-27 03:59 UTC75
backfill_max_time = "2m"
93b435e669a5atagen2026-09-27 03:59 UTC76
# max_wait = "30m"
ecc1cf8df0f5atagen2026-09-27 13:36 UTC77
elastic = true         # hand idle cores to whoever's building
ecc1cf8df0f5atagen2026-09-27 13:36 UTC78
intent_ttl = "20m"     # how long a `rabt expect` or a build keeps its claim
93b435e669a5atagen2026-09-27 03:59 UTC79
93b435e669a5atagen2026-09-27 03:59 UTC80
[overrun]
93b435e669a5atagen2026-09-27 03:59 UTC81
ram = "warn"           # or "throttle", systemd-run MemoryHigh on linux
93b435e669a5atagen2026-09-27 03:59 UTC82
ram_slack = 1.25
93b435e669a5atagen2026-09-27 03:59 UTC83
time_grace = 1.5       # overdue at this multiple of --time
93b435e669a5atagen2026-09-27 03:59 UTC84
remind_every = "5m"
93b435e669a5atagen2026-09-27 03:59 UTC85
93b435e669a5atagen2026-09-27 03:59 UTC86
[enforce]
93b435e669a5atagen2026-09-27 03:59 UTC87
unwrapped = "deny"     # "wrap" guesses a size for them, "allow" looks away
93b435e669a5atagen2026-09-27 03:59 UTC88
default_size = "m"
93b435e669a5atagen2026-09-27 03:59 UTC89
93b435e669a5atagen2026-09-27 03:59 UTC90
[artifacts]
93b435e669a5atagen2026-09-27 03:59 UTC91
project_cap = "10GiB"
93b435e669a5atagen2026-09-27 03:59 UTC92
global_cap = "60GiB"
93b435e669a5atagen2026-09-27 03:59 UTC93
idle_after = "24h"
93b435e669a5atagen2026-09-27 03:59 UTC94
size_ttl = "10m"
93b435e669a5atagen2026-09-27 03:59 UTC95
over_cap = "warn"      # "block" refuses new builds until cleaned
93b435e669a5atagen2026-09-27 03:59 UTC96
stop = "nudge"         # "block" "warn" "off"
93b435e669a5atagen2026-09-27 03:59 UTC97
nix_gc = false
93b435e669a5atagen2026-09-27 03:59 UTC98
nix_min_free = "30GiB"
93b435e669a5atagen2026-09-27 03:59 UTC99
# extra_rules = [{ name = "zig-cache", marker = "build.zig" }]
93b435e669a5atagen2026-09-27 03:59 UTC100
93b435e669a5atagen2026-09-27 03:59 UTC101
[nix]
93b435e669a5atagen2026-09-27 03:59 UTC102
inject = true
93b435e669a5atagen2026-09-27 03:59 UTC103
cores_per_job = 4
93b435e669a5atagen2026-09-27 03:59 UTC104
93b435e669a5atagen2026-09-27 03:59 UTC105
[detect]
93b435e669a5atagen2026-09-27 03:59 UTC106
# extra = ["just build"]
93b435e669a5atagen2026-09-27 03:59 UTC107
```
93b435e669a5atagen2026-09-27 03:59 UTC108
93b435e669a5atagen2026-09-27 03:59 UTC109
## license
93b435e669a5atagen2026-09-27 03:59 UTC110
93b435e669a5atagen2026-09-27 03:59 UTC111
EUPL-1.2