rtb-app¶
rtb-app is the structural heart of the phpboyscout Rust toolkit. It defines the
application context a command handler receives, the static description of a tool,
the runtime feature set that decides which built-in commands are visible, and the
link-time registry commands register themselves into.
It is deliberately small. There is no I/O in it, no clap, no spawned tasks, and no
runtime service registry. Parsing arguments, installing hooks and actually running a
CLI all live in consumer crates — rtb-cli primarily.
What is in this repository¶
Two crates share one version line and are released together.
| Crate | What it is | Where it goes in your Cargo.toml |
|---|---|---|
rtb-app |
App, ToolMetadata, Features, Command, BUILTIN_COMMANDS, compile_bounded |
[dependencies] |
rtb-test-support |
TestAppBuilder — builds an App for a test without the full rtb-cli wiring |
[dev-dependencies] |
Install it¶
[dependencies]
rtb-app = "0.9"
linkme = "0.3" # required if you register commands — see below
[dev-dependencies]
rtb-test-support = "0.9"
linkme has to be a direct dependency of any crate that registers a command,
because the #[distributed_slice] attribute expands to ::linkme::… paths. The
rtb_app::linkme re-export does not remove that requirement on its own. There is a
one-line escape hatch if you would rather not add the dependency —
Register a command covers both.
Minimum supported Rust version is 1.82, and the repository pins an exact stable
toolchain in rust-toolchain.toml rather than tracking the floating stable
channel.
What rtb-app does not do¶
Reading this before the feature list saves time.
- It does not parse command-line arguments.
Command::runreceives an already-builtApp; getting there isrtb-cli's job. - It does not build an
Appfor you in production.App::newexists and is public, but going through it directly skips the logging, error-hook and signal wiring thatrtb_cli::Application::builderinstalls. - It does not read configuration files. It stores whatever
Config<C>it was handed and hands it back, type-erased. - It does not resolve credentials. It stores a provider and enumerates what that provider reports.
- It does not enforce ordering between registered commands or pre-run hooks. Link-time registration order across crates is not deterministic.
The full list, with the consequences spelled out, is in What rtb-app does not do.
Where to go next¶
- New to the crate? Write your first command takes about twenty minutes and ends with a passing test.
- Doing a specific job? The how-to guides cover registering
commands, reporting your own version, reading typed config, wiring self-update and
building an
Appin tests. - Looking up a field, a default or an error? The reference covers every public type, every field and what happens when a value is wrong.
- Wondering why it is shaped this way? The
explanation pages cover the container-free
App, link-time registration, type-erased configuration, and the crate's limits.
Where this sits in the toolkit¶
rtb-app was extracted from — and is still exercised by —
rust-tool-base. It depends on four
sibling toolkit crates and on no framework crate above it: rtb-error,
rtb-config, rtb-assets and rtb-credentials. A dependency back onto
rust-tool-base or rtb-cli-bin is denied outright in deny.toml, which is what
makes the "framework-free" claim enforceable rather than aspirational.
- API reference: https://docs.rs/rtb-app · https://docs.rs/rtb-test-support
- Crates: https://crates.io/crates/rtb-app · https://crates.io/crates/rtb-test-support
- Source: https://gitlab.com/phpboyscout/rust/app
Further reading¶
The blog carries a curated route through this subject: Rust, and what survived the port collects everything written about it, ordered so you can start at the beginning rather than newest-first.
Ask phpbotscout

He answers questions about the projects over on the Discord, citing the docs where they already cover it, and offering to raise an issue where they don't. Bring a bug, an idea, or a questionable engineering decision.