atagen

roundabout

public
Star0
Watch0

Commit fdad58f8133a

tarball

atagen <boss@atagen.co>2026-10-25 23:16 UTC

16 files changed+84-84
treewide: rename rabt to roundabout
Modified file: Cargo.toml+1 additions−1 deletions
@@ -8,7 +8,7 @@ license = "EUPL-1.2"
88 rust-version = "1.91"
99
1010 [[bin]]
11-name = "rabt"
11+name = "roundabout"
1212 path = "src/main.rs"
1313
1414 [dependencies]
Modified file: README.md+17 additions−17 deletions
@@ -6,27 +6,27 @@ agents say roughly how big a build is. a tiny daemon, started on demand and gone
66
77 ## use
88
9-the cli is `rabt`, short enough that agents don't mind typing it
9+the cli is `roundabout`, short enough that agents don't mind typing it
1010
1111 ```
12-rabt run --size m -- cargo build
13-rabt run --ram 6G --cores 8 --time 10m -- nix build .#thing
14-rabt status
15-rabt suggest -- cargo build --release
16-rabt expect --size l # building soon, save me a seat
17-rabt watch 7 # exits when lease 7 is done or overdue
18-rabt kill 7
19-rabt extend 7 10m
20-rabt artifacts check | list | gc [--cap] [--project] | pin <path>
12+roundabout run --size m -- cargo build
13+roundabout run --ram 6G --cores 8 --time 10m -- nix build .#thing
14+roundabout status
15+roundabout suggest -- cargo build --release
16+roundabout expect --size l # building soon, save me a seat
17+roundabout watch 7 # exits when lease 7 is done or overdue
18+roundabout kill 7
19+roundabout extend 7 10m
20+roundabout artifacts check | list | gc [--cap] [--project] | pin <path>
2121 ```
2222
2323 `run` exits with the build's code, 124 if `--deadline` killed it, 75 if `--max-wait` ran out.
2424
2525 a granted build gets `CARGO_BUILD_JOBS`, `MAKEFLAGS`, `CMAKE_BUILD_PARALLEL_LEVEL` and a `NIX_CONFIG` with `cores`/`max-jobs` to match its grant.
2626
27-on linux, `rabt` creates a transient scope through the systemd user manager's D-Bus `StartTransientUnit` method. the command waits until its scope is active, then runs with its original environment and terminal I/O. `CPUQuotaPerSecUSec` caps CPU time at the granted core count, and `MemoryMax` caps the whole build at its granted RAM multiplied by `overrun.ram_slack`, with at least the granted RAM available. these limits cover descendants too, even when a tool ignores the job-count environment variables. linux requires a running systemd user manager and user bus, a failed scope refuses the build rather than running it without limits. other platforms retain the job-count environment variables without cgroup enforcement.
27+on linux, `roundabout` creates a transient scope through the systemd user manager's D-Bus `StartTransientUnit` method. the command waits until its scope is active, then runs with its original environment and terminal I/O. `CPUQuotaPerSecUSec` caps CPU time at the granted core count, and `MemoryMax` caps the whole build at its granted RAM multiplied by `overrun.ram_slack`, with at least the granted RAM available. these limits cover descendants too, even when a tool ignores the job-count environment variables. linux requires a running systemd user manager and user bus, a failed scope refuses the build rather than running it without limits. other platforms retain the job-count environment variables without cgroup enforcement.
2828
29-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.
29+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 `roundabout 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.
3030
3131 ## claude code
3232
@@ -46,7 +46,7 @@ programs.roundabout.settings.budget.ram = "16GiB"; # lands in /etc/roundabout/
4646
4747 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`.
4848
49-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.
49+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. `roundabout` needs to be on PATH for the agent too, so install `.#roundabout` alongside.
5050
5151 ## codex
5252
@@ -56,9 +56,9 @@ codex plugin marketplace add ./result
5656 codex plugin add roundabout@roundabout
5757 ```
5858
59-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.
59+restart codex and review the plugin hooks with `/hooks` before using them. install `.#roundabout` as well so `roundabout run` and `roundabout 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.
6060
61-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.
61+on nixos, `programs.roundabout.codex` exposes read-only `hooks`, `skill` and `plugin`, alongside the claude options. the codex hooks deny unwrapped builds and suggest `roundabout run` instead of silently rewriting the command, which keeps the normal tool approval flow intact even when `enforce.unwrapped` is set to `wrap`. `roundabout run` and `roundabout expect` associate builds with the current codex session, and session-end hooks release its expectation.
6262
6363 ## omp
6464
@@ -67,7 +67,7 @@ nix build .#omp-plugin
6767 omp plugin link ./result
6868 ```
6969
70-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.
70+restart omp after linking. install `.#roundabout` on PATH for the agent's bash tool, or set `ROUNDABOUT_CLI` to the `roundabout` 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 `roundabout expect` inherit the omp session id through the bash tool's environment. on nixos, `programs.roundabout.omp` exposes read-only `plugin` and `skill` options.
7171
7272 ## config
7373
@@ -98,7 +98,7 @@ linger = "5s"
9898 backfill_max_time = "2m"
9999 # max_wait = "30m"
100100 elastic = true # hand idle cores to whoever's building
101-intent_ttl = "20m" # how long a `rabt expect` or a build keeps its claim
101+intent_ttl = "20m" # how long a `roundabout expect` or a build keeps its claim
102102
103103 [overrun]
104104 ram = "warn" # or "throttle", MemoryHigh at granted RAM on linux
Modified file: nix/omp-plugin.nix+1 additions−1 deletions
@@ -9,5 +9,5 @@ runCommand "roundabout-omp-plugin-${roundabout.version}" { } ''
99 cp ${../plugin/omp/package.json} $out/package.json
1010 cp ${../plugin/omp/index.js} $out/index.js
1111 cp -r ${../plugin/skills}/. $out/skills/
12- ln -s ${lib.getExe roundabout} $out/bin/rabt
12+ ln -s ${lib.getExe roundabout} $out/bin/roundabout
1313 ''
Modified file: nix/omp-tests.nix+1 additions−1 deletions
@@ -17,7 +17,7 @@ let
1717 };
1818 mockCli = writeScript "roundabout-test-cli" ''
1919 #!${lib.getExe nushell} --stdin
20- ${builtins.readFile ../tests/mock-rabt.nu}
20+ ${builtins.readFile ../tests/mock-roundabout.nu}
2121 '';
2222 in
2323 runCommand "roundabout-omp-tests"
Modified file: nix/package.nix+1 additions−1 deletions
@@ -18,7 +18,7 @@ rustPlatform.buildRustPackage {
1818
1919 meta = {
2020 description = "build admission for agents that can't share";
21- mainProgram = "rabt";
21+ mainProgram = "roundabout";
2222 license = lib.licenses.eupl12;
2323 platforms = lib.platforms.unix;
2424 };
Modified file: nix/plugin.nix+1 additions−1 deletions
@@ -42,5 +42,5 @@ runCommand "roundabout-plugin-${roundabout.version}" { } ''
4242 cp ${plugin} $p/.claude-plugin/plugin.json
4343 cp ${hooks} $p/hooks/hooks.json
4444 cp -r ${../plugin/skills}/. $p/skills/
45- ln -s ${lib.getExe roundabout} $p/bin/rabt
45+ ln -s ${lib.getExe roundabout} $p/bin/roundabout
4646 ''
Modified file: plugin/omp/index.js+2 additions−2 deletions
@@ -2,10 +2,10 @@ import { spawn } from "node:child_process";
22 import { existsSync } from "node:fs";
33 import { fileURLToPath } from "node:url";
44
5-const packagedCli = fileURLToPath(new URL("./bin/rabt", import.meta.url));
5+const packagedCli = fileURLToPath(new URL("./bin/roundabout", import.meta.url));
66
77 function cli() {
8- return process.env.ROUNDABOUT_CLI || (existsSync(packagedCli) ? packagedCli : "rabt");
8+ return process.env.ROUNDABOUT_CLI || (existsSync(packagedCli) ? packagedCli : "roundabout");
99 }
1010
1111 function invoke(event, context, input = {}) {
Modified file: plugin/skills/roundabout/SKILL.md+15 additions−15 deletions
@@ -5,26 +5,26 @@ description: use before running any build, test suite or other heavy command (ca
55
66 # roundabout
77
8-this box is shared with other agents and a human who'd like their video to keep playing. builds queue through roundabout, whose cli is `rabt`, and only run when there's room.
8+this box is shared with other agents and a human who'd like their video to keep playing. builds queue through roundabout, whose cli is `roundabout`, and only run when there's room.
99
1010 ## first, say you're coming
1111
1212 when you pick up a task that'll involve building, before you start editing
1313
1414 ```
15-rabt expect --size m
15+roundabout expect --size m
1616 ```
1717
18-sized like the biggest build you expect to run. idle cores get handed out to whoever's building, and this is how the others know to leave you some. it lapses 20 minutes after your last build or `expect`, so one call covers an edit-compile loop. `rabt expect --done` if the plan changes.
18+sized like the biggest build you expect to run. idle cores get handed out to whoever's building, and this is how the others know to leave you some. it lapses 20 minutes after your last build or `expect`, so one call covers an edit-compile loop. `roundabout expect --done` if the plan changes.
1919
2020 ## running something
2121
2222 ```
23-rabt run --size m -- cargo build
24-rabt run --ram 6G --cores 8 --time 10m --disk 4G -- nix build .#thing
23+roundabout run --size m -- cargo build
24+roundabout run --ram 6G --cores 8 --time 10m --disk 4G -- nix build .#thing
2525 ```
2626
27-wrap the build, not the whole pipeline. `cd x && rabt run -s m -- cargo test 2>&1 | tail` is fine.
27+wrap the build, not the whole pipeline. `cd x && roundabout run -s m -- cargo test 2>&1 | tail` is fine.
2828
2929 sizes out of the box
3030
@@ -35,7 +35,7 @@ sizes out of the box
3535 | l | 6G | 5G | half | 15m | release builds, big workspaces, nix closures |
3636 | xl | 12G | 20G | all | 45m | rebuilding the world |
3737
38-`rabt suggest -- <cmd>` has numbers from previous runs of that command in this project. use them.
38+`roundabout suggest -- <cmd>` has numbers from previous runs of that command in this project. use them.
3939
4040 guess honestly. under-asking is how the box ooms, and an honest `--time` is what lets small jobs slip past big ones. it tells you afterwards if you were off.
4141
@@ -46,12 +46,12 @@ you may get more cores than you asked for when the box is quiet, `CARGO_BUILD_JO
4646 a queued build prints its place and why to stderr. for anything likely over a couple of minutes
4747
4848 1. run the build with `run_in_background`
49-2. read the lease id from `rabt: lease N go`
50-3. also start `rabt watch N` with `run_in_background`. it exits when the build finishes or goes overdue, which wakes you up
49+2. read the lease id from `roundabout: lease N go`
50+3. also start `roundabout watch N` with `run_in_background`. it exits when the build finishes or goes overdue, which wakes you up
5151
52-in codex, use `exec_command` with a short `yield_time_ms` for the build, then poll its `session_id` with `write_stdin`. use another `exec_command` for `rabt watch N` if the build is likely to take longer. don't launch the build a second time while polling.
52+in codex, use `exec_command` with a short `yield_time_ms` for the build, then poll its `session_id` with `write_stdin`. use another `exec_command` for `roundabout watch N` if the build is likely to take longer. don't launch the build a second time while polling.
5353
54-in omp, use the bash tool's `async` option for the build and `omp ps` to follow its output. use another bash call for `rabt watch N` if you need an overdue reminder.
54+in omp, use the bash tool's `async` option for the build and `omp ps` to follow its output. use another bash call for `roundabout watch N` if you need an overdue reminder.
5555
5656 `--max-wait 10m` gives up queueing after that (exit 75). `--deadline 30m` kills the build if it's still going (exit 124). only use a deadline when a late result is useless.
5757
@@ -59,14 +59,14 @@ in omp, use the bash tool's `async` option for the build and `omp ps` to follow
5959
6060 you'll get told when a build is well past its time estimate. decide, don't ignore it
6161
62-- `rabt kill N` if it's stuck or not worth it
63-- `rabt extend N 15m` if it's making progress
62+- `roundabout kill N` if it's stuck or not worth it
63+- `roundabout extend N 15m` if it's making progress
6464
65-`rabt status` shows everything running and queued.
65+`roundabout status` shows everything running and queued.
6666
6767 ## artifacts
6868
69-build output is capped per project and in total. `rabt artifacts check` compares, `list` shows the offenders, `gc` clears idle stuff, `gc --cap` keeps going until under, `--project` leaves everyone else's stuff alone. `pin <path>` protects something you need.
69+build output is capped per project and in total. `roundabout artifacts check` compares, `list` shows the offenders, `gc` clears idle stuff, `gc --cap` keeps going until under, `--project` leaves everyone else's stuff alone. `pin <path>` protects something you need.
7070
7171 if told you're over, clean up before you finish. scratch dirs full of `target/` and `result` links count too.
7272
Modified file: src/artifacts.rs+2 additions−2 deletions
@@ -178,9 +178,9 @@ impl Report {
178178
179179 pub const fn remedy(&self) -> &'static str {
180180 if self.over_global {
181- "rabt artifacts gc --cap"
181+ "roundabout artifacts gc --cap"
182182 } else {
183- "rabt artifacts gc --project --cap"
183+ "roundabout artifacts gc --project --cap"
184184 }
185185 }
186186
Modified file: src/cli.rs+13 additions−13 deletions
@@ -13,7 +13,7 @@ use crate::{
1313
1414 /// one build at a time, please
1515 #[derive(Parse)]
16-#[pound(name = "rabt", version = env!("CARGO_PKG_VERSION"))]
16+#[pound(name = "roundabout", version = env!("CARGO_PKG_VERSION"))]
1717 pub enum Rabt {
1818 /// wait your turn, then run the thing
1919 Run {
@@ -167,7 +167,7 @@ fn artifacts(cfg: &Config, action: Artifacts) -> i32 {
167167 );
168168 }
169169 for f in &g.failed {
170- eprintln!("rabt: {f}");
170+ eprintln!("roundabout: {f}");
171171 }
172172 println!(
173173 "{} {}",
@@ -177,7 +177,7 @@ fn artifacts(cfg: &Config, action: Artifacts) -> i32 {
177177 i32::from(!g.failed.is_empty())
178178 }
179179 Artifacts::Pin { path } | Artifacts::Unpin { path } if !path.exists() => {
180- eprintln!("rabt: {} doesn't exist", path.display());
180+ eprintln!("roundabout: {} doesn't exist", path.display());
181181 1
182182 }
183183 Artifacts::Pin { path } => report(artifacts::pin(&path, true)),
@@ -188,7 +188,7 @@ fn artifacts(cfg: &Config, action: Artifacts) -> i32 {
188188 fn report(r: Result<(), String>) -> i32 {
189189 r.map_or_else(
190190 |e| {
191- eprintln!("rabt: {e}");
191+ eprintln!("roundabout: {e}");
192192 1
193193 },
194194 |()| 0,
@@ -207,16 +207,16 @@ fn reply(ev: io::Result<Option<Event>>) -> i32 {
207207 match ev {
208208 Ok(Some(Event::Ok)) => 0,
209209 Ok(Some(Event::Err { msg })) => {
210- eprintln!("rabt: {msg}");
210+ eprintln!("roundabout: {msg}");
211211 1
212212 }
213213 Ok(None) => {
214- eprintln!("rabt: nothing running");
214+ eprintln!("roundabout: nothing running");
215215 1
216216 }
217217 Ok(Some(_)) => 1,
218218 Err(e) => {
219- eprintln!("rabt: {e}");
219+ eprintln!("roundabout: {e}");
220220 1
221221 }
222222 }
@@ -237,7 +237,7 @@ fn agent_session(session: Option<String>) -> Option<String> {
237237
238238 fn expect(cfg: &Config, session: Option<String>, done: bool, a: &run::Args) -> i32 {
239239 let Some(session) = session.filter(|s| !s.is_empty()) else {
240- eprintln!("rabt: no agent session id, use --session to name one");
240+ eprintln!("roundabout: no agent session id, use --session to name one");
241241 return 2;
242242 };
243243 let need = if done {
@@ -246,7 +246,7 @@ fn expect(cfg: &Config, session: Option<String>, done: bool, a: &run::Args) -> i
246246 match run::need(cfg, a) {
247247 Ok(n) => Some(n),
248248 Err(e) => {
249- eprintln!("rabt: {e}");
249+ eprintln!("roundabout: {e}");
250250 return 2;
251251 }
252252 }
@@ -254,12 +254,12 @@ fn expect(cfg: &Config, session: Option<String>, done: bool, a: &run::Args) -> i
254254 let mut s = match client::connect_or_spawn() {
255255 Ok(s) => s,
256256 Err(e) => {
257- eprintln!("rabt: can't reach the daemon: {e}");
257+ eprintln!("roundabout: can't reach the daemon: {e}");
258258 return 1;
259259 }
260260 };
261261 if let Err(e) = proto::send(&mut s, &Request::Expect { session, need }) {
262- eprintln!("rabt: {e}");
262+ eprintln!("roundabout: {e}");
263263 return 1;
264264 }
265265 reply(Reader::new(&s).and_then(|mut r| r.recv()))
@@ -335,7 +335,7 @@ fn suggest(cfg: &Config, cmd: &[String]) -> i32 {
335335 let base = match run::base(cfg) {
336336 Ok(b) => b,
337337 Err(e) => {
338- eprintln!("rabt: {e}");
338+ eprintln!("roundabout: {e}");
339339 return 2;
340340 }
341341 };
@@ -361,7 +361,7 @@ fn watch(lease: u64) -> i32 {
361361 Reader::new(&s).and_then(|mut r| r.recv::<Event>()),
362362 Ok(Some(Event::Fired { overdue: true }))
363363 ) {
364- println!("lease {lease} is overdue, `rabt kill {lease}` or `rabt extend {lease} <dur>`");
364+ println!("lease {lease} is overdue, `roundabout kill {lease}` or `roundabout extend {lease} <dur>`");
365365 3
366366 } else {
367367 println!("lease {lease} is done");
Modified file: src/hook.rs+14 additions−14 deletions
@@ -99,8 +99,8 @@ fn head(seg: &[String]) -> &[String] {
9999 }
100100 }
101101
102-fn is_rabt(word: &str) -> bool {
103- word == "rabt" || word.ends_with("/rabt")
102+fn is_roundabout(word: &str) -> bool {
103+ word == "roundabout" || word.ends_with("/roundabout")
104104 }
105105
106106 fn matches_pattern(seg: &[String], pattern: &str) -> bool {
@@ -124,7 +124,7 @@ fn scan(cfg: &Config, cmd: &str) -> Scan {
124124 let mut found = Vec::new();
125125 for seg in segments(cmd) {
126126 let seg = head(&seg);
127- if seg.first().is_some_and(|w| is_rabt(w)) {
127+ if seg.first().is_some_and(|w| is_roundabout(w)) {
128128 continue;
129129 }
130130 if cfg.detect_patterns().any(|p| matches_pattern(seg, p)) {
@@ -186,9 +186,9 @@ fn pre_tool_use(cfg: &Config, input: Input) {
186186 let hint = guess(cfg, &cwd, &first);
187187 let reason = format!(
188188 "builds go through roundabout here so parallel agents don't oom the box. wrap each build \
189- in `rabt run <size> -- <cmd>`, e.g. `rabt run {hint} -- {}`. sizes are {}, or \
189+ in `roundabout run <size> -- <cmd>`, e.g. `roundabout run {hint} -- {}`. sizes are {}, or \
190190 give --ram/--disk/--cores/--time yourself. for anything long use \
191- run_in_background and start `rabt watch <lease>` in the background too so you \
191+ run_in_background and start `roundabout watch <lease>` in the background too so you \
192192 hear if it drags. see the roundabout skill",
193193 found[0],
194194 cfg.sizes.keys().cloned().collect::<Vec<_>>().join("/"),
@@ -204,7 +204,7 @@ fn pre_tool_use(cfg: &Config, input: Input) {
204204 (Scan::Unwrapped(_), Unwrapped::Wrap) => {
205205 let hint = guess(cfg, &cwd, std::slice::from_ref(&cmd));
206206 tool_input["command"] =
207- Value::String(format!("rabt run {hint} -- bash -c {}", shell_quote(&cmd)));
207+ Value::String(format!("roundabout run {hint} -- bash -c {}", shell_quote(&cmd)));
208208 // no permissionDecision on purpose. allow would skip the user's
209209 // prompt for whatever the agent wrote, rewriting shouldn't
210210 emit(&json!({
@@ -232,7 +232,7 @@ fn codex_pre_tool_use(cfg: &Config, input: Input) -> Option<Value> {
232232 let first: Vec<String> = found[0].split_whitespace().map(Into::into).collect();
233233 let hint = guess(cfg, &cwd, &first);
234234 let reason = format!(
235- "builds go through roundabout here so parallel agents don't oom the box. run `rabt run {hint} -- {}` instead. see the roundabout skill",
235+ "builds go through roundabout here so parallel agents don't oom the box. run `roundabout run {hint} -- {}` instead. see the roundabout skill",
236236 found[0]
237237 );
238238 Some(json!({
@@ -267,7 +267,7 @@ fn overdue(session: &str) -> Vec<LeaseInfo> {
267267 }
268268 }
269269
270-/// same source `rabt run` reads. after `--continue` the env var can keep the
270+/// same source `roundabout run` reads. after `--continue` the env var can keep the
271271 /// startup id while the json moves on, and we need both ends to agree
272272 fn session(input: &Input, codex: bool) -> String {
273273 if codex {
@@ -307,8 +307,8 @@ fn remind(event: &str, input: &Input, codex: bool) {
307307 .iter()
308308 .map(|l| {
309309 format!(
310- "roundabout lease {} (`{}`) has run {} against a {} estimate. `rabt kill {}` to stop it, \
311- `rabt extend {} <dur>` if it's worth the wait",
310+ "roundabout lease {} (`{}`) has run {} against a {} estimate. `roundabout kill {}` to stop it, \
311+ `roundabout extend {} <dur>` if it's worth the wait",
312312 l.id,
313313 l.cmd.join(" "),
314314 Dur::secs(l.elapsed),
@@ -336,7 +336,7 @@ fn stop(cfg: &Config, event: &str, input: &Input) {
336336 return;
337337 }
338338 let msg = format!(
339- "{}. run `{}`, or `rabt artifacts list` and clear out what you don't need",
339+ "{}. run `{}`, or `roundabout artifacts list` and clear out what you don't need",
340340 report.describe(cfg),
341341 report.remedy()
342342 );
@@ -373,7 +373,7 @@ pub fn main(cfg: &Config, event: &str) -> i32 {
373373 "post-tool-use" => remind("PostToolUse", &input, false),
374374 "prompt-submit" => remind("UserPromptSubmit", &input, false),
375375 "session-end" => session_end(&input, false),
376- other => eprintln!("rabt: unknown hook {other}"),
376+ other => eprintln!("roundabout: unknown hook {other}"),
377377 }
378378 0
379379 }
@@ -400,7 +400,7 @@ mod tests {
400400 output["hookSpecificOutput"]["permissionDecisionReason"]
401401 .as_str()
402402 .unwrap()
403- .contains("rabt run")
403+ .contains("roundabout run")
404404 );
405405 }
406406
@@ -416,7 +416,7 @@ mod tests {
416416 #[test]
417417 fn codex_ignores_other_tools_and_wrapped_builds() {
418418 assert!(
419- codex_pre_tool_use(&Config::default(), bash("rabt run -s m -- cargo build")).is_none()
419+ codex_pre_tool_use(&Config::default(), bash("roundabout run -s m -- cargo build")).is_none()
420420 );
421421 let mut input = bash("cargo build");
422422 input.tool_name = Some("apply_patch".into());
Modified file: src/main.rs+1 additions−1 deletions
@@ -25,7 +25,7 @@ fn main() {
2525 // a typo must not exit 2, that's a blocking pretooluse verdict and would
2626 // wall off every bash call in every session
2727 let cfg = config::Config::load().unwrap_or_else(|e| {
28- eprintln!("rabt: bad config, using defaults. {e}");
28+ eprintln!("roundabout: bad config, using defaults. {e}");
2929 config::Config::default()
3030 });
3131 std::process::exit(cli::dispatch(&cfg, cli::Rabt::parse()));
Modified file: src/run.rs+2 additions−2 deletions
@@ -52,7 +52,7 @@ extern "C" fn forward(sig: libc::c_int) {
5252 }
5353
5454 fn say(msg: &str) {
55- eprintln!("rabt: {msg}");
55+ eprintln!("roundabout: {msg}");
5656 }
5757
5858 pub fn need(cfg: &Config, a: &Args) -> Result<Need, String> {
@@ -209,7 +209,7 @@ pub fn run(cfg: &Config, a: &Args) -> i32 {
209209 if a.size.is_none() && a.ram.is_none() {
210210 let sizes: Vec<_> = cfg.sizes.keys().map(String::as_str).collect();
211211 say(&format!(
212- "how big is it? pass --size {} or --ram and friends. `rabt suggest -- <cmd>` has a guess",
212+ "how big is it? pass --size {} or --ram and friends. `roundabout suggest -- <cmd>` has a guess",
213213 sizes.join("|")
214214 ));
215215 return 2;
Modified file: src/systemd.rs+1 additions−1 deletions
@@ -247,7 +247,7 @@ pub fn exec() -> Option<i32> {
247247 };
248248 let error = Command::new(&program).args(arguments).exec();
249249 eprintln!(
250- "rabt: couldn't start {}: {error}",
250+ "roundabout: couldn't start {}: {error}",
251251 program.to_string_lossy()
252252 );
253253 Some(127)
Modified file: tests/omp.test.mjs+7 additions−7 deletions
@@ -42,14 +42,14 @@ function input() {
4242 }
4343
4444 test("maps build guards and preserves wrapped command arguments", async () => {
45- output({ hookSpecificOutput: { permissionDecision: "deny", permissionDecisionReason: "use rabt run" } });
46- assert.deepEqual(await handlers.get("tool_call")(bash, context), { block: true, reason: "use rabt run" });
45+ output({ hookSpecificOutput: { permissionDecision: "deny", permissionDecisionReason: "use roundabout run" } });
46+ assert.deepEqual(await handlers.get("tool_call")(bash, context), { block: true, reason: "use roundabout run" });
4747 assert.equal(input().event, "omp-pre-tool-use");
4848 assert.equal(input().input.tool_name, "Bash");
49- output({ hookSpecificOutput: { updatedInput: { command: "rabt run -s m -- cargo build" } } });
49+ output({ hookSpecificOutput: { updatedInput: { command: "roundabout run -s m -- cargo build" } } });
5050 const result = await handlers.get("tool_call")({ ...bash, input: { ...bash.input, cwd: "/project" } }, context);
5151 assert.equal(input().input.cwd, "/project");
52- assert.equal(result.input.command, "rabt run -s m -- cargo build");
52+ assert.equal(result.input.command, "roundabout run -s m -- cargo build");
5353 assert.equal(result.input.async, true);
5454 assert.deepEqual(result.input.env, { KEEP: "yes", ROUNDABOUT_SESSION_ID: "omp-session" });
5555 });
@@ -60,7 +60,7 @@ test("fails open for malformed output, nonzero exits and missing CLI", async ()
6060 output({ hookSpecificOutput: { permissionDecision: "deny" } });
6161 process.env.ROUNDABOUT_TEST_EXIT = "1";
6262 assert.equal((await handlers.get("tool_call")(bash, context)).block, undefined);
63- process.env.ROUNDABOUT_CLI = join(temporary, "missing-rabt");
63+ process.env.ROUNDABOUT_CLI = join(temporary, "missing-roundabout");
6464 assert.equal((await handlers.get("tool_call")(bash, context)).block, undefined);
6565 });
6666
@@ -80,7 +80,7 @@ test("maps artifact policies and bounds advisory continuations", async () => {
8080 });
8181
8282 test("the CLI tracks OMP sessions ahead of inherited agent identities", () => {
83- const rabt = process.env.ROUNDABOUT_TEST_RABT;
83+ const roundabout = process.env.ROUNDABOUT_TEST_RABT;
8484 const config = join(temporary, "config.toml");
8585 writeFileSync(config, '[queue]\nlinger = "1s"\n');
8686 const env = {
@@ -93,7 +93,7 @@ test("the CLI tracks OMP sessions ahead of inherited agent identities", () => {
9393 CODEX_THREAD_ID: "inherited-codex",
9494 };
9595 function run(args, payload) {
96- const result = spawnSync(rabt, args, { env, input: payload, encoding: "utf8", timeout: 10000 });
96+ const result = spawnSync(roundabout, args, { env, input: payload, encoding: "utf8", timeout: 10000 });
9797 assert.equal(result.status, 0, result.stderr);
9898 return result.stdout;
9999 }
Modified file: tests/systemd.rs+5 additions−5 deletions
@@ -18,7 +18,7 @@ fn gated_command(program: &str, arguments: &[&str]) -> (Child, OwnedFd) {
1818 let read = unsafe { OwnedFd::from_raw_fd(descriptors[0]) };
1919 let write = unsafe { OwnedFd::from_raw_fd(descriptors[1]) };
2020 let descriptor = read.as_raw_fd();
21- let mut command = Command::new(env!("CARGO_BIN_EXE_rabt"));
21+ let mut command = Command::new(env!("CARGO_BIN_EXE_roundabout"));
2222 command
2323 .args(["__roundabout_exec", &descriptor.to_string(), program])
2424 .args(arguments)
@@ -39,7 +39,7 @@ fn gated_command(program: &str, arguments: &[&str]) -> (Child, OwnedFd) {
3939
4040 #[test]
4141 fn command_waits_for_scope_setup() {
42- let (mut child, gate) = gated_command(env!("CARGO_BIN_EXE_rabt"), &["--version"]);
42+ let (mut child, gate) = gated_command(env!("CARGO_BIN_EXE_roundabout"), &["--version"]);
4343 let mut output = libc::pollfd {
4444 fd: child.stdout.as_ref().unwrap().as_raw_fd(),
4545 events: libc::POLLIN,
@@ -53,13 +53,13 @@ fn command_waits_for_scope_setup() {
5353 assert!(
5454 String::from_utf8(output.stdout)
5555 .unwrap()
56- .starts_with("rabt ")
56+ .starts_with("roundabout ")
5757 );
5858 }
5959
6060 #[test]
6161 fn failed_scope_setup_never_executes_the_command() {
62- let (child, gate) = gated_command(env!("CARGO_BIN_EXE_rabt"), &["--version"]);
62+ let (child, gate) = gated_command(env!("CARGO_BIN_EXE_roundabout"), &["--version"]);
6363 drop(gate);
6464 let output = child.wait_with_output().unwrap();
6565 assert_eq!(output.status.code(), Some(1));
@@ -118,7 +118,7 @@ fn transient_scope_enforces_the_grant() {
118118 "[overrun]\nram = \"throttle\"\n[queue]\nlinger = \"0s\"\n",
119119 )
120120 .unwrap();
121- let output = Command::new(env!("CARGO_BIN_EXE_rabt"))
121+ let output = Command::new(env!("CARGO_BIN_EXE_roundabout"))
122122 .args([
123123 "run", "--ram", "64M", "--disk", "0", "--cores", "1", "--time", "5s", "--exact", "--",
124124 ])