Expand description
§bevy_fairy
An agentic debugger for Bevy games. It has two halves, and a game uses one of them while an agent uses the other.
- The plugin (
plugin) is what a game links. It registers BRP methods (bevy_fairy/status,commands,screenshot,capture,input,scene,guide,quit) and lets the game register its own typed commands. - The server (
server) is thebevy-fairybinary. It speaks the Model Context Protocol to a coding agent and the Bevy Remote Protocol to a running game.
The two halves do not depend on each other. A game that has never heard of this crate can still be inspected with Bevy’s own BRP methods, and a game that links the plugin can be driven by any BRP client, not only this one.
§Which feature do I want?
| you are | you want | your dependency |
|---|---|---|
| a game | the plugin | bevy_fairy = { version = "0.2", default-features = false, features = ["plugin"] } |
| an agent | the server | cargo install bevy_fairy |
A game that takes the plugin as a dependency compiles none of the server’s
dependencies. That is not a promise about the future; tests/plugin_leaf.rs fails the
build if it stops being true.
§Quick start: a game
[dependencies]
bevy = { version = "0.20", features = ["default"] }
bevy_fairy = { version = "0.2", default-features = false, features = ["plugin"] }This example belongs to the game, not to this crate: it uses bevy, which this crate
only depends on when the plugin feature is on, so it is shown rather than compiled.
use bevy::prelude::*;
use bevy::remote::http::RemoteHttpPlugin;
use bevy_fairy::plugin::DebuggerPlugin;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
// Owns the BRP RemotePlugin. Never add a second RemotePlugin next to it.
.add_plugins(DebuggerPlugin::default())
.add_plugins(RemoteHttpPlugin::default())
.run();
}DebuggerPlugin needs bevy::input::InputPlugin in the app. DefaultPlugins includes it;
MinimalPlugins does not.
§Quick start: an agent
cargo install bevy_fairy
bevy-fairy --helpThen point it at a running game. The game listens on 127.0.0.1:15702 by default; set
BEVY_BRP_HOST and BEVY_BRP_PORT to change that.
§The tool contract
Every tool’s advertised schema is generated from the same Rust type its handler parses, so the two cannot drift apart. Every result carries the frame it was observed on. A value that cannot be measured is refused with a reason, never answered with a plausible number.
Re-exports§
pub use plugin::apply_pending_input;pub use plugin::cursor_position;pub use plugin::handle_input;pub use plugin::ClockRequest;pub use plugin::logical_for;pub use plugin::typed;pub use plugin::DebugCommandInfo;pub use plugin::DebugCommands;pub use plugin::DebugCommandsAppExt;pub use plugin::DebugCursor;pub use plugin::DebugReady;pub use plugin::DebuggerPlugin;pub use plugin::InputAction;pub use plugin::InputCommand;pub use plugin::InputKind;pub use plugin::PendingInput;pub use plugin::SceneLog;pub use plugin::ScenePlayback;pub use plugin::SceneStep;pub use server::prelude;pub use server::brp as brp_messages;