Files
soundcraft/docs/cli.md
T
JonRC f46ea7d70c soundcraft-cli: print logged warnings and errors to stderr
The CLI installed no logger, so every log::warn! and log::error! was
dropped: a plugin that failed to load just vanished from
engine.clap_plugins with no reason. A small logger now writes warnings
and errors to standard error as `warning: <message>` and
`error: <message>`, like the CLI's own errors. The level is fixed:
RUST_LOG stays a desktop app variable.

Fixes #1304.
2026-11-02 23:48:01 -03:00

146 lines
7.9 KiB
Markdown

# Command-line tool
`soundcraft-cli` runs SoundCraft without a window: it converts and inspects audio, runs engine
commands on a session, serves MCP, and calls a running app. Follows
[RFC-0012](https://github.com/storytold/craft-contrib/pull/18) (command-line conventions for the
Craft apps).
`soundcraft-cli --help` and `soundcraft-cli <subcommand> --help` are the source of truth for
flags, values and defaults. This page does not repeat them.
| Subcommand | What it does |
|---|---|
| `info` | Prints an audio file's format as JSON, or a `.scraft` session's summary |
| `convert` | Converts an audio file: resample, change the bit depth, normalize |
| `run` | Runs engine commands on a new, demo or saved session; can bounce, save and inspect |
| `script` | Runs a file of engine commands, one `ID JSON` per line |
| `commands` | Lists the engine commands |
| `describe` | Prints one engine command's details as JSON |
| `app` | Calls a running app's control channel (see [the control protocol](control-protocol.md)) |
| `mcp` | Serves MCP on stdin and stdout (see [the MCP guide](mcp.md)) |
| `parity` | Prints the parity report as markdown |
| `plugins` | Lists the built-in plugins |
```sh
soundcraft-cli --version # also -V; there is no `version` subcommand
soundcraft-cli help convert # the same as `convert --help`
soundcraft-cli info session.scraft
soundcraft-cli convert in.wav out.flac --bit-depth 16 --rate 44100
soundcraft-cli run --demo --cmd 'mix.volume={"track":"Kick","db":-6}' --bounce mix.wav
soundcraft-cli script steps.txt --demo --keep-going --save out.scraft
soundcraft-cli commands bounce
soundcraft-cli describe file.bounce_mix
```
## Output and exit codes
Results go to standard output, as JSON where a program is meant to read them. `info` (on an audio
file), `describe`, `app` and the `--inspect` output of `run` and `script` pretty-print it; `--compact`
prints the same JSON on one line. The result lines of `run` and `script` (`ID: JSON`) and the
`--bounce` and `--save` results are always one line each. `commands`, `plugins`, `parity` and the
`.scraft` summary of `info` are text. Errors go to standard error as `error: <message>`, and so do the warnings and errors SoundCraft and the plugin hosts log (`warning: <message>`, `error: <message>`), such as a plugin that fails to load. `mcp` writes only the protocol
to standard output.
| Exit code | Meaning |
|---|---|
| 0 | Success |
| 1 | The command failed (a missing file, an unknown engine command, an app that is not running) |
| 2 | Usage error |
Arguments are checked before any work starts. These are usage errors (exit 2): a flag the
subcommand does not take (`--fromat`), a flag given twice (only `--cmd` and the two automation
root flags repeat), a value of the wrong type or out of range, flags that conflict
(`--dither` with `--no-dither`, `--connect` with a root flag or `--demo`) and a missing value. A value flag
never takes the next flag as its value: write a value that starts with `-` as `--bounce=-x.wav`, or
give a file as `./-x.wav`. File names that are not valid Unicode reach the command unchanged.
The engine writes bounces and saved sessions through commands whose parameters are JSON text, so
those paths must be valid Unicode (`--bounce`, `--save`, and the `--in` session with
`--in-place`: exit 1).
An output that is one of the inputs is a usage error too, however the path is spelt (`a.wav`,
`./a.wav`, a symbolic or hard link):
| Subcommand | Inputs | Outputs | `--in-place` lets an output replace |
|---|---|---|---|
| `convert` | `IN` | `OUT` | `IN` |
| `run` | `--in` | `--bounce`, `--save` | the `--in` session, by `--save` only |
| `script` | `FILE`, `--in` | `--bounce`, `--save` | the `--in` session, by `--save` only; never `FILE` |
`run` and `script` take `--in-place` only with `--in`. A `--bounce` naming the `--in` session, and
`--bounce` and `--save` naming one file, are refused with or without `--in-place`. With
`--in-place`, an output that is a symbolic link to the input replaces the file it links to; the
link stays. An existing file that is not an input is replaced without asking.
## Environment variables
| Variable | Flag | Notes |
|---|---|---|
| `SOUNDCRAFT_CONTROL_PORT` | `app --port` (CLI), `--control` (desktop app) | A port or `host:port`, an IPv6 host in brackets (`[::1]:7979`). The desktop app takes the port of a loopback `host:port` (`127.0.0.1`, `localhost`). Its control server listens on `127.0.0.1` only, so it ignores another host from the variable, with a log warning, and starts no control server; given to `--control`, another host is a usage error |
- A flag wins over its variable.
- An empty variable counts as unset.
- A bad value is a usage error that names the variable.
- `<subcommand> --help` lists the variable.
- The automation roots (`--automation-read-root`, `--automation-write-root`) are flags only. No
variable grants file access.
`SOUNDCRAFT_CONFIG_DIR`, `SOUNDCRAFT_NO_PREFS`, `SOUNDCRAFT_NO_SYSTEM_FONTS`, `SOUNDCRAFT_WAYLAND`
(Linux) and `RUST_LOG` configure the desktop app (see the [README](../README.md#logs) and
[the control protocol](control-protocol.md)), not the CLI. `soundcraft --help` lists them.
An empty variable counts as unset (RFC-0012 rule 1.7), except `SOUNDCRAFT_CONFIG_DIR`: empty means
no settings folder.
`SOUNDCRAFT_NO_PREFS`, `SOUNDCRAFT_NO_SYSTEM_FONTS` and `SOUNDCRAFT_WAYLAND` are on/off switches with
one rule: `1/on/true/yes` is on, `0/off/false/no` is off (any case, spaces ignored), and unset or
blank is the default (off). A value that isn't one of these spellings is ignored (the default applies) and logs a warning that
names the variable.
## Desktop app launch flags
`soundcraft [OPTIONS] [FILES]...` takes the same strict parsing and exit codes.
`soundcraft --help` lists the flags:
| Flag | Meaning |
|---|---|
| `FILES` | Sessions, audio and MIDI files to open; put `--` before a name that starts with `-` |
| `--demo` (alias `--sample`) | Start with the demo session |
| `--no-audio` | Don't open an audio device |
| `--control <PORT>` | Start the control server on this port (`0` picks a free port and prints it); falls back to `SOUNDCRAFT_CONTROL_PORT` |
| `--version`, `-V` | Print the version |
| `--help`, `-h` | Print the flags and the environment variables |
## Man pages and completions
The Linux `.deb` and `.rpm` packages install `man soundcraft-cli` (plus a page per subcommand, such
as `man soundcraft-cli-convert`) and completions for bash, zsh and fish. The Linux and FreeBSD
tarballs carry the same files. The pages list each flag's environment variable, as `--help` does.
The desktop app has neither.
Without a package, generate them from a source checkout:
```sh
cargo run -p soundcraft-cli --example man-and-completions -- out/
```
`out/` then holds `soundcraft-cli.bash`, `_soundcraft-cli` (zsh), `soundcraft-cli.fish`,
`soundcraft-cli.elv` (elvish), `_soundcraft-cli.ps1` (PowerShell) and the `.1` man pages. Copy
`soundcraft-cli.bash` to `~/.local/share/bash-completion/completions/soundcraft-cli`,
`soundcraft-cli.fish` into `~/.config/fish/completions/`, `_soundcraft-cli` into a directory on
zsh's `$fpath`, and read a page with `man -l out/soundcraft-cli.1`.
## RFC-0012
soundcraft-cli follows [RFC-0012](https://github.com/storytold/craft-contrib/pull/18): clap derive
types, thiserror errors, `run(args, out, err)` behind `main`, environment variables declared on
their flags, generated completions and man pages, tests that pin help and every usage error, no
output replacing an input without `--in-place`, and the ast-grep rules in `lint/ast-grep`. The shared automation flags are declared once in
`crates/automation/src/args.rs`.
Rules not followed yet:
- **JSON flag (rule 1.3).** `commands`, `plugins`, `parity` and the `info` summary of a `.scraft`
session print text and have no `--json` flag. Whether such listings need one is an open question
in the RFC itself.
- **`string-error` rule (section 3).** Its ast-grep rule is on for the CLI code and the shared flags,
not yet for the rest of the workspace.