Skip to content

Command-line control

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:

Terminal window
cargo build --bin feather-cli
target/debug/feather-cli --help
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
Terminal window
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.

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:

    Terminal window
    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:

    Terminal window
    feather-cli --workspace ./my-game --project project.feather.json command project.inspect
  4. Pass larger arguments through standard input:

    Terminal window
    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.

Start the editor with an automation session, or enable one from Tools → Automation (MCP); see MCP setup. Then connect with the session file:

Terminal window
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.

Every command prints one JSON object and exits:

{"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 for error codes and revisions.

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

Terminal window
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.

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.

Terminal window
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.

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.

Terminal window
feather-cli --workspace ./my-game --project project.feather.json mcp

See MCP setup for client configuration.