---
name: bevy-commands
description: Reference for Bevy Commands — spawning/despawning entities, inserting/removing components, custom commands, trait extensions, and testing.
metadata:
  crate: bevy_ecs
  bevy: "0.19"
---

## Basics

`Commands` is a system parameter that queues mutations into a `CommandQueue`.
Bevy applies them at a **sync point**: an `ApplyDeferred` system inserted after
command-producing systems that others depend on, as well as at the end of every
schedule.

```rust
fn spawn(mut commands: Commands) {
  commands.spawn_empty();
}
```

## Spawning components

```rust
commands.spawn(Player).insert(Transform::default());
// or with a tuple bundle
commands.spawn((Player, Transform::from_xyz(1., 1., 1.)));
```

## Required components

```rust
#[derive(Component)]
#[require(Transform)]
struct Player;
// now: commands.spawn(Player) auto-adds Transform
```

A bare `#[require(Foo)]` uses `Foo::default()`, so `Foo` must implement
`Default`. If you provide a constructor instead, `Default` is not required.
Required components are resolved **recursively**.

## Component lifecycle hooks

Components have five life-cycle hooks for side effects that **must** happen:

1. `#[component(on_add = ...)]`
2. `#[component(on_insert = ...)]`
3. `#[component(on_discard = ...)]`
4. `#[component(on_remove = ...)]`
5. `#[component(on_despawn = ...)]`

The hook systems take a `DeferredWorld` and a `HookContext`:

```rust
use bevy::ecs::lifecycle::HookContext;
use bevy::ecs::world::DeferredWorld;

#[derive(Component, Default)]
#[component(on_add = on_ship_added)]
enum Ship {
  Destroyer,
  Frigate,
  #[default]
  Scout,
}

fn on_ship_added(mut world: DeferredWorld, context: HookContext) {
  world
    .commands()
    .entity(context.entity)
    .insert(Position { x: 0, y: 0 });
}
```

## EntityCommands chaining

`spawn`/`spawn_empty` return `EntityCommands` for chaining:

```rust
commands
  .spawn(Player)
  .insert(Transform::default())
  .insert(Name::new("Player 1"));
```

## Despawning

```rust
for entity in &query {
  commands.entity(entity).despawn();
}
```

## Commands are deferred

Commands don't execute immediately — they're queued until the next sync point,
where Bevy runs its `ApplyDeferred` system.

## Custom commands

Implement the `Command` trait:

```rust
struct SpawnPlanet { radius: f32, position: Vec2 }

impl Command for SpawnPlanet {
  fn apply(self, world: &mut World) {
    let mesh = world.resource_scope(|_w, mut meshes: Mut<Assets<Mesh>>| {
      meshes.add(Circle::new(self.radius))
    });
    // ...
    world.spawn((Planet::new(self.radius), Mesh2d(mesh), Transform::from_translation(self.position.extend(0.))));
  }
}
// usage:
commands.queue(SpawnPlanet { radius: 100., position: Vec2::ZERO });
```

## Extending the Commands API

```rust
trait MyExt {
  fn do_thing(&mut self);
}
impl<'w, 's> MyExt for Commands<'w, 's> {
  fn do_thing(&mut self) { info!("thing done"); }
}
```

## Testing commands

```rust
use bevy::ecs::world::CommandQueue;

let mut world = World::default();
let mut queue = CommandQueue::default();
queue.push(MyCommand);
queue.apply(&mut world);
```
