# kaze CLI Reference
`kaze` is a Zephyr build companion that orchestrates **configure / build / flash / run** for both **single-image** apps and **sysbuild multi-image** projects, with declarative configuration via `kaze.toml`.
This project is heavily inspired by [zync](https://gitlab.com/byarocks/zync) and should follow it for implementation details such as resulting system commands called.
## Synopsis
```bash
kaze [OPTIONS] <COMMAND> [COMMAND_OPTIONS] [-- <EXTRA_ARGS>...]
```
## Global options
| `-h, --help` | Show help |
| `-V, --version` | Show version |
| `-v..., --verbose` | More logs (repeatable optional) |
| `-c, --clean` | Pre-clean the active build dir before running the command |
| `-a, --all` | Run command for all configured profiles (overrides `--profile` and defaults) |
| `-p, --profile <profile>` | Select a configured profile |
| `-b, --board <board>` | Override resolved board |
| `-r, --runner <runner>` | Override resolved runner |
| `--project <path>` | Explicit project root (otherwise auto-detect by traversal) |
### Notes
- `--all` applies only when profiles exist; otherwise it behaves like normal single build.
- `--clean` pre-cleans **only the active build directory** (profile-specific when profiles are enabled).
## Commands
| `init` | `i` | Initialize project config (`kaze.toml`) |
| `boards` | `bo` | List available Zephyr boards |
| `runners` | `rn` | List available Zephyr runners |
| `profiles` | `p` | List configured profiles |
| `clean` | `c` | Clean build output (root or active profile build dir) |
| `conf` | `cf` | Configure via CMake |
| `build` | `b` | Build via Ninja (auto-configures if needed) |
| `flash` | `f` | Flash using configured/selected runner |
| `run` | `r` | Run simulation (native_sim/qemu), or run target-specific runner behavior |
### Shared command options
All commands support:
- `--board/-b` and `--runner/-r` overrides (precedence over config)
Commands that accept extra args via `--`:
- `conf`, `build`, `flash`, `run`
Example:
```bash
kaze build -- -j 0
kaze conf -- -DOVERLAY_CONFIG=overlay.conf
kaze flash -- --hex-file path/to/other.hex
kaze run -- -flash=../../seed/flash.bin
```
## Sysbuild image selection (flash/run)
`flash` and `run` support sysbuild image selection:
| `--list, -l` | List available sysbuild images |
| `--image, -i <name-or-index>` | Select image to flash/run |
Rules:
- If no image selected, default is **first non-bootloader** image (e.g. prefer `app` over `mcuboot`).
- Indexing is 1-based in CLI output.
Example:
```bash
kaze flash --list
kaze flash --image app
kaze flash --image 1
```
## `run` behavior and `--norebuild`
`kaze run`:
- By default, performs a build first, then runs the simulator binary directly if found.
- If simulator binary is not found, falls back to `ninja run` behavior (extra args after `--` are not appended in that fallback mode).
Options:
- `-n, --norebuild` — skip the pre-run rebuild and run immediately.
---
# `kaze.toml` Configuration Spec
`kaze.toml` is a declarative config located at the **project root**.
## File discovery
`kaze` locates the project by:
1) if `--project <path>` is given, use it
2) else traverse upward from `cwd` until `kaze.toml` is found
3) if run from a build directory, traverse upward to find the owning project root
## Configuration layers and precedence
Resolved configuration is produced by merging layers in this order:
1) **Defaults**
2) **User config (optional)**: `~/.config/kaze/config.toml`
3) **Project config**: `<project>/kaze.toml`
4) **Environment variables**: `KAZE_*`
5) **CLI flags** (`--profile`, `--board`, `--runner`, etc.)
Within the project config:
- global values apply first
- active profile values override global values
- CLI overrides override both
## Top-level schema overview
Recommended top-level tables:
- `[project]` — defaults and profile selection
- `[zephyr]` — workspace and base paths
- `[build]` — build directory rules
- `[args]` — extra args per phase (global)
- `[profile.<name>]` — per-profile board/runner + per-profile args
## `[project]`
| `board` | string | *(none)* | Default Zephyr board |
| `runner` | string | *(none)* | Default Zephyr runner |
| `default_profile` | string | *(none)* | Default profile name |
| `name` | string | *(optional)* | Display name for the project (optional) |
### Profile selection rules
When profiles are defined:
1) if `--all` set → all profiles selected
2) else if `--profile` set → that profile selected
3) else if `default_profile` set → selected
4) else → first profile in config file order (or lexicographic if order isn’t preserved)
When profiles are not defined:
- profile selection is ignored and build is profile-less.
## `[profile.<name>]`
Each profile is a partial override of the global project config.
| `board` | string | Profile board |
| `runner` | string | Profile runner |
| `args` | table | Per-phase args for the profile |
Example:
```toml
[profile.sim]
board = "native_sim"
[profile.prod]
board = "nucleo_f767zi"
runner = "openocd"
```
## `[zephyr]`
| `workspace` | string | auto-detect | Zephyr workspace root |
| `base` | string | `${zephyr_ws}/zephyr` | Zephyr base directory |
Auto-detection order (when not set):
1) `ZEPHYR_BASE` environment variable
2) find `.west/` by traversing upward; if found, treat its parent as workspace
3) (optional) fallback helpers can be added later
## `[build]`
| `root` | string | `"build"` | Root build output directory |
| `layout` | string enum | `"auto"` | Build layout mode: `auto`, `profiles`, `single` |
| `link_compile_commands` | bool | `true` | When profiles enabled, create root `build/compile_commands.json` symlink |
### Build output layout
- Profile-less mode: `./<build.root>/`
- Profiles mode: `./<build.root>/<profile>/`
If profiles mode and `link_compile_commands=true`:
- `./<build.root>/compile_commands.json` is a symlink to the selected default/first profile’s `compile_commands.json`
## `[args]` and per-profile args
Args are configurable for phases:
- `conf` (CMake configure)
- `build` (Ninja)
- `flash` (west flash / runner invocation)
- `run` (simulator binary or fallback command)
Value forms:
- string → treated as a single argument string (split behavior is implementation-defined; recommended to use arrays)
- array of strings → preferred, exact args list
Example:
```toml
[args]
conf = ["-DHG_TEST=ON"]
build = ["-j", "0"]
flash = ["--hex-file", "path/to/other.hex"]
run = ["-flash_mount=../../seed/sd"]
[profile.sim.args]
run = ["-flash=../../seed/flash.bin", "-wait_uart"]
```
### Arg merge order
For a given phase:
1) global `[args.<phase>]`
2) profile `[profile.<name>.args.<phase>]`
3) CLI passthrough args after `--`
---
# Interpolation Spec (`${key}`)
`kaze` supports `${key}` placeholders in string config values (most commonly in args and paths).
## When interpolation runs
Interpolation runs after:
1) config layers are merged
2) active profile is resolved
3) CLI overrides are applied
So `${board}` reflects the **final** resolved board, etc.
## Supported keys
Resolved from the active configuration + runtime context:
- `board` — resolved board
- `runner` — resolved runner
- `profile` — selected profile name (empty if profile-less)
- `build_dir` — active build directory (profile-specific when profiles enabled)
- `project_dir` — project root directory
- `zephyr_ws` — Zephyr workspace
- `zephyr_base` — Zephyr base (usually `${zephyr_ws}/zephyr`)
- `cwd` — current working directory
- `is_build` — `"true"`/`"false"` (whether invoked from build dir context)
- `sysbuild` — `"true"`/`"false"` (whether project detected as sysbuild)
## Rules / limitations
- Missing keys are left unchanged (`${missing}` stays as-is).
- Interpolation applies only to strings (numbers/bools stringify if referenced).
- Cycles are not expanded further (self-references remain `${key}`).
- Interpolation is single-pass (no recursive expansion).
---
# Minimal examples
## 1) Simple project (profile-less)
```toml
[project]
board = "nucleo_f767zi"
runner = "openocd"
```
## 2) Project with profiles
```toml
[project]
runner = "openocd"
default_profile = "sim"
[profile.sim]
board = "native_sim"
[profile.prod]
board = "nucleo_f767zi"
```
## 3) Args + interpolation
```toml
[zephyr]
workspace = "/opt/zephyr"
base = "${zephyr_ws}/zephyr"
[args]
conf = ["-DBOARD=${board}", "-DZEPHYR_BASE=${zephyr_base}"]
build = ["--build-dir", "${build_dir}"]
run = ["-flash_mount=../../seed/sd"]
```