3 releases (breaking)

0.3.0 Feb 19, 2024
0.2.0 Feb 10, 2024
0.1.0 Dec 28, 2023

#233 in Procedural macros

39 downloads per month


651 lines

Crates.io Docs

A macro for creating bevy Commands and EntityCommands methods from functions.


use bevy_commandify::*;

fn foo(world: &mut World, n: usize) {
    // Bear in mind that Commands *defer* work
    // This function will not be called immediately
    // It will be executed at the end of the current schedule 
    // Or when `apply_deferred` is next called within the current schedule
    let mut bar = world.resource_mut::<Bar>();
    **bar -= n;

/// Regular bevy systems can be used as commands, too
fn irony(mut commands: Commands) {

/// Commands may optionally return `&mut Self` to allow chaining command calls
fn bar(world: &mut World, entity: Entity, n: usize) -> &mut Self {
    let mut component = world
        .query::<&mut Bar>()
        .get_mut(world, entity)
    **component -= n;

fn commands(mut commands: Commands) {
    // Fire our command directly
    // call it via the generated extension trait
    CommandsFooExt::foo(&mut commands, 10);
    // Add the command as a struct
    commands.add(FooCommand { n: 10 });

// Commands may also run against the world directly
fn exclusive_commands(world: &mut World) {
    CommandsFooExt::foo(world, 10);

fn entity_commands(mut commands: Commands) {
    let entity = commands.spawn(Bar::default()).id();
    commands.entity(entity).bar(10).insert(Foo); // We can chain calls to other commands
    EntityCommandsBarExt::bar(&mut commands.entity(entity), 10);
    commands.entity(entity).add(BarEntityCommand { n: 10 });

fn exclusive_entity_commands(world: &mut World) {
    let entity = world.spawn(Bar(0)).id();
    EntityCommandsBarExt::bar(&mut world.entity_mut(entity), 10);

See also the example and tests


The following attributes apply equally to #[command] and #[entity_command]

  • #[command(no_trait)] prevents generating a trait method for Commands, but will still generate a Command struct you can add:
fn foo(world: &mut World) { }

commands.foo(); // This will throw an error
commands.add(FooCommand); // This will still work
  • #[command(no_world)] prevents generating a trait implementation against World or EntityWorldMut
fn foo(world: &mut World) { }

world.foo(); // This will throw an error
commands.foo(); // This will still work
  • #[command(name = T)] will use T for the generated method and related struct/trait names:
#[command(name = "bar")]
fn foo(world: &mut World) { }

CommandsBarExt::bar(&mut commands);
  • #[command(struct_name = T)] will use this name for the generated struct:
#[command(struct_name = "Bar")]
fn foo(world: &mut World) { }

CommandsFooExt::foo(&mut commands);
  • #[command(trait_name = T)] will use this name for the generated trait:
#[command(trait_name = "BarExt")]
fn foo(world: &mut World) { }

BarExt::foo(&mut commands);
  • #[command(ecs = T)] or #[command(bevy_ecs)] to point the macro to the correct bevy crate if you don't use bevy directly.


Bevy Crate
0.13 0.3
0.12 0.1, 0.2


~21K SLoC