Skip to content

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::run receives an already-built App; getting there is rtb-cli's job.
  • It does not build an App for you in production. App::new exists and is public, but going through it directly skips the logging, error-hook and signal wiring that rtb_cli::Application::builder installs.
  • 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 App in 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.

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

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.

Join the Discord