crates/but/agents.md
gitbutler--prefixed crates, and prefer code from but- prefixed crates as long as it's not in the legacy module.Usable output goes to out: &mut OutputChannel
if let Some(out) = out.for_human() { writeln!(out, “{…}")?; }if let Some(out) = out.for_shell() { writeln!(out, “{…}")?; }if let Some(out) = out.for_json() { out.write_value(json)?; }let _ = ...; with ....ok();, but ensure the statement remains on a single line after formatting._ = instead of let _ = and keep the rest unchanged.std::io::stdin() directly in command/business logic and human input.out.can_prompt() or collect input via out.prepare_for_terminal_input().cli-prompts for preset choices.read: impl std::io::Read parameter and parse from that reader so tests can inject input.stdin().lock() usage at the top-level CLI wiring only (for example in lib.rs), and pass readers downward.ctx.repo.get()?
and passed as parameter.repo APIs (for example repo.rev_parse_single(...)) over shelling out to git; only shell out when there is no equivalent API.std::time::SystemTime::now(), instead pass the current time as argument.snapbox::str![] to assert with .stdout_eq(str![]) and stderr_eq(str![]) respectively,
and auto-update expectations with SNAPSHOTS=overwrite cargo test -p but..stdout_eq(snapbox::file!["snapshots/<test-name>/<invocation>.stdout.term.svg"]), and update it
with SNAPSHOT=overwrite cargo test -p but.crates/but/tests/, prefer env.but(...).assert().success()/failure().stdout_eq(str![...]).stderr_eq(str![...]) for CLI output checks.crates/but/tests/, avoid std::process::Command::new("git"); use sandbox helpers instead.env.invoke_bash(...) usages with env.invoke_git(...).env.invoke_bash(...) (this is the preferred form).env.invoke_git("...") only for single git commands, particularly if their output is asserted on.env.but(...).output() followed by direct stdout/stderr assertions (for example, String::from_utf8_lossy(&output.stdout) with assert_*).snapbox::str! wildcards (..) to ignore unstable sections.anyhow::ensure! in tests; use panicking assertions (assert!, assert_eq!, assert_ne!) so failures are test panics.cargo fmt --check --all to check for formatting issues.cargo clippy --all-targets --fix --allow-dirty to auto-fix clippy errors.crates/but/skill/ so AI agents stay currentbut skill install --detect (auto-detects installation location)