Tutorial

Quick Start

The full loop in one sitting: project, package, image, run, plan. The later tutorials cover each piece in depth.

1. Initialize a project

airfield project init ./my_robot --ros-distro jazzy

This creates the project marker (airfield.yaml), a packages/ folder, dependency roots for x86_64 and arm64, and a plans/ directory with a ready-to-run example.yaml.

2. Initialize a package

From inside an Airfield project:

cd my_robot
airfield package init nav_stack

A package can also live on its own, outside any project. Run the init from inside the package’s directory:

mkdir nav_stack && cd nav_stack
airfield package init .

3. Wrap an existing ROS package

airfield package init --path /path/to/existing_ros_package --ros-distro jazzy

If package.xml exists, Airfield infers the ROS package name and dependency tags, then writes airfield.yaml (with source_path: .) without rewriting the ROS source files. Dependencies the ROS base image already provides are skipped; for the rest, Airfield generates local manifests under dependencies/xplatform/ that install ros-<distro>-<name> via apt. Review those before the first build, since not every ROS name has a released apt package.

4. Build a package image

airfield package build nav_stack --target-device x86_64

The build streams full Docker output and prints the generated Dockerfile, so there is nothing hidden to debug. The first build downloads the declared apt and pip dependencies; later builds reuse BuildKit cache mounts, which makes dependency-only rebuilds substantially faster. A generated .dockerignore keeps source artifacts and data files out of the build context.

5. Run the package

Define a named run command in packages/nav_stack/airfield.yaml:

run:
  list-packages: ros2 pkg list
airfield package run nav_stack list-packages

Running airfield package run nav_stack with no command name lists the available run commands. You can also open a package container shell:

airfield package shell nav_stack

Or run one command in the package container:

airfield package cmd nav_stack -- ros2 pkg list

6. Launch a plan

airfield project up example

This renders plans/example.yaml into a tmuxinator config at .airfield/example.tmuxinator.yml and launches it as a tmux session, one pane per plan entry. Use --no-launch to only generate the config, or --inspect to print it without writing anything. Tear the session down (and its containers) with:

airfield project down example

airfield project liftoff <plan> is the alternative for plans that define a simple packages: list instead of windows:; it runs each package’s default command sequentially, without tmux, blocking until each exits. The scaffolded example.yaml uses windows:, so launch it with project up.

7. Manage subpackages

If your project contains multiple nested git repositories (under src/ or packages/), the subpackages commands perform batch git operations across all of them:

# Check the git status of all subpackages
airfield subpackages status

# Commit changes in all dirty subpackages
airfield subpackages commit -m "Update parameters"

# Clean and reset all subpackages to discard local changes
airfield subpackages clean --force

To record every present repository in airfield.yaml so a fresh checkout can restore them with airfield subpackages checkout:

airfield subpackages track