# Command-line control

> Use feather-cli to discover commands, author projects headlessly and control a running editor.

Source: https://feather-engine.com/docs/agents/cli/

`feather-cli` runs any command in the Feather 2 catalog from a terminal or script. It never starts a
renderer. It can work on a project in memory (headless) or send commands to a running editor (live),
and it can serve the same catalog to AI clients over MCP.

Build it from a source checkout, or use the copy inside the macOS app bundle at
`Feather v2.app/Contents/MacOS/feather-cli`:

```bash
cargo build --bin feather-cli
target/debug/feather-cli --help
```

## Usage

```text
feather-cli --workspace DIR [--project FILE] command NAME [--json JSON] [--expected-revision N] [--save FILE]
feather-cli --workspace DIR [--project FILE] mcp
feather-cli --connect SESSIONFILE command NAME [--json JSON] [--expected-revision N]
feather-cli --connect SESSIONFILE mcp
feather-cli --workspace DIR --project FILE build [--platform P] [--output DIR] [--player FILE]
            [--profile release|development] [--archive] [--version X.Y.Z] [--build-number N]
            [--name NAME] [--sign-identity ID]
feather-cli catalog
```

| Option | Description |
| --- | --- |
| `--workspace DIR` | The folder that file operations may use. Project, asset, export and capture paths resolve inside it. It must already exist |
| `--project FILE` | Load a saved project (`.feather` or `.feather.json`) for a headless command, build or MCP session. Relative to the workspace |
| `--connect SESSIONFILE` | Send commands to a running editor through its session file. Uses the editor's workspace and project; cannot be combined with `--project` or `--save` |
| `--json JSON` | Command arguments as a JSON object. Defaults to `{}`. Use `--json -` to read up to 16 MiB from standard input |
| `--expected-revision N` | Reject the command if the document revision has changed |
| `--save FILE` | After a successful headless command, save the project to this workspace path |

## Discover commands

```bash
feather-cli catalog
```

`catalog` prints `{"tools":[...]}`. Each entry has a `name`, a `description` that lists fields, units
and valid values, a JSON `inputSchema`, and `annotations` including `readOnlyHint`. The same list is
published as MCP tools and summarised in the [command reference](/docs/agents/commands/).

## Run commands headlessly

Each headless `command` invocation opens a new document session and exits after one command. Load a
project with `--project`, and persist the result with `--save` or the `project.save` command.

1. Create a folder to use as the workspace.
2. Add an object and save a new project:

   ```bash
   feather-cli --workspace ./my-game command scene.add \
     --json '{"kind":"Cube","name":"My cube","position":[0,2,0]}' \
     --save project.feather.json
   ```

3. Read the project back:

   ```bash
   feather-cli --workspace ./my-game --project project.feather.json command project.inspect
   ```

4. Pass larger arguments through standard input:

   ```bash
   cat patch.json | feather-cli --workspace ./my-game --project project.feather.json \
     command scene.update --json - --save project.feather.json
   ```

To apply several edits as one undoable step, use `scene.batch` with up to 64 commands.

:::caution
Paths that contain `..` or point outside the workspace are rejected. Keep every file a command
reads or writes inside the workspace folder.
:::

## Control a running editor

Start the editor with an automation session, or enable one from **Tools → Automation (MCP)**; see
[MCP setup](/docs/agents/mcp/). Then connect with the session file:

```bash
feather-cli --connect .feather-session.json command engine.status
feather-cli --connect .feather-session.json command runtime.play --json '{"playing":true}'
feather-cli --connect .feather-session.json command runtime.logs
feather-cli --connect .feather-session.json command runtime.play --json '{"playing":false}'
```

Live commands edit the open project directly and appear in the editor immediately, with undo. Save
with the `project.save` command; `--save` is not available live. Authoring commands are rejected
with the `playing` error code while the editor is in Play.

## Responses and exit codes

Every command prints one JSON object and exits:

```json
{"ok":false,"revision":2,"data":null,"error":{"code":"not_found","message":"Object 99 does not exist."}}
```

| Field | Description |
| --- | --- |
| `ok` | `true` if the command succeeded |
| `revision` | The document revision after the command |
| `data` | The command's result, or `null` on failure |
| `error` | `null`, or `{code, message}` |

The process exits with status 0 on success and 1 on failure, so commands can be chained in shell
scripts. See [Agents overview](/docs/agents/overview/) for error codes and revisions.

## Conditional edits

Read the revision, then make the edit depend on it:

```bash
feather-cli --connect .feather-session.json command project.inspect   # note "revision"
feather-cli --connect .feather-session.json command scene.update \
  --json '{"id":1,"patch":{"name":"Gate"}}' --expected-revision 12
```

If someone changed the project in between, the command fails with `revision_conflict` and nothing
changes.

## Build a game

The `build` mode builds the project as a standalone game, using the same pipeline as the editor's
**Build** window. It runs `game.export` and prints its report; against a running editor it waits for
the build job to finish.

```bash
feather-cli --workspace . --project game/project.feather.json build --platform windows --archive
```

| Option | Description |
| --- | --- |
| `--platform P` | `macos`, `windows`, `linux` or `host` (the default). Other platforms need `--player` or a player runtime; run `game.platforms` to check |
| `--output DIR` | Folder in the workspace that receives the build. Default: the project's `build.output_dir`, `builds` |
| `--player FILE` | A prebuilt `feather-player` for the platform, inside the workspace. Skips compiling |
| `--profile P` | `release` (default) or `development` |
| `--archive` | Also write a `.zip` (`.tar.gz` for Linux) next to the build |
| `--version`, `--build-number`, `--name` | Override the build settings. Headless, they apply to this build only and are not saved. Handy for CI tags |
| `--sign-identity ID` | macOS signing identity; `-` signs ad hoc (the default) |

See [Build a game](/docs/shipping/export/).

## Run an MCP server

The `mcp` mode serves the catalog over MCP on standard input and output. A headless MCP session keeps
its document in memory until the client disconnects. Standard output carries only protocol messages;
startup errors go to standard error.

```bash
feather-cli --workspace ./my-game --project project.feather.json mcp
```

See [MCP setup](/docs/agents/mcp/) for client configuration.
