The Creature CLI is my Swiss Army knife for working with the Creature Server. It’s a command-line tool built in Swift as part of the same package as the Creature Console, so it shares all the same networking and model code. The code is on GitHub in the Common package.
I use it mostly for debugging and testing, but it’s also handy for quick one-off tasks where I don’t want to open the full console. Need to play an animation, check server metrics, or monitor WebSocket traffic? The CLI is faster than clicking through a GUI.
Commands
The CLI is organized into command groups, each focused on a different part of the system.
animations
List, play, rename, and delete animations on the server. You can also trigger lip sync generation and inspect ad-hoc animations. The play and interrupt commands are great for testing — I can fire off an animation from the terminal without touching the Console.
creatures
List creatures, view their details, and toggle idle loops on and off. The validate command is particularly useful — it reads a creature definition JSON file and checks that all the referenced animations actually exist on the server. Catches broken references before they cause problems at runtime.
sounds
Manage sound files on the server — list them, play them, download them, and generate lip sync data. The generate-lipsync-from-file command can take a local WAV file, upload it, and output the lip sync JSON, which is handy for offline work.
voice
Interface with ElevenLabs through the server. List available voices, check subscription status, and generate speech. The ad-hoc subcommands (play, prepare, trigger) do the same thing as the Console’s ad-hoc animation feature but from the command line — type some text, and a creature says it.
dialog
Author and render multi-character dialog scenes from the terminal — the command-line side of the Console’s dialog feature. list, detail, create, update, and delete manage the dialog scripts saved on the server, and validate checks a script JSON file before you commit it. render turns a script (or an inline JSON file) into a multi-track animation as an async job, with options for permanent or ad-hoc storage, a title, a specific cached voice generation, and autoplay on the hardware.
The two export commands are the ones I reach for when I want to work on the audio by hand: export-mono writes the mono preview WAV for a scene, and export-multichannel writes the full 17-channel WAV so every character lands on its own track when I open it in Audacity.
playlists
Start and stop playlists on a universe. Simple but useful when I want to kick off a playlist without opening the Console.
fixtures
Manage DMX fixtures on the server. list, detail, upsert, and delete handle the fixture records, validate sanity-checks a fixture JSON file before saving, and universe assigns or clears the persisted E1.31 universe a fixture lives on.
The two I lean on when I’m bringing up a new light are live and trigger: live drives raw DMX channel values slider-style so I can dial a fixture in by hand, and trigger manually fires one of a fixture’s saved patterns — handy for testing a fixture without building a whole animation around it.
storyboards
Manage storyboards — the cards of programmable tiles I tap to run a show discreetly from an iPad — from the command line. list shows every saved board with its tile count, detail prints a board’s tiles and actions (or the raw JSON with --json), and rename, copy, and delete do what they say. copy is handy for spinning up a variant of a board without rebuilding it tile by tile.
The pair I reach for most is backup and restore: storyboards detail <id> --json > board.json dumps a board to a file, and storyboards import board.json uploads it back — updating the board in place if it still exists, or recreating it if it’s gone. create and update are there too for when I want to force one path or push a board I wrote as JSON by hand.
websocket
This is where the debugging really shines. The monitor command connects to the server’s WebSocket and displays all the messages flowing through — sensor data, animation events, status updates, everything. You can filter by message type and output as raw JSON. It’s like tcpdump for the creature network.
There’s also stream-test for sending fake streaming frames to a creature, and inject for pushing test messages into the server. Both are invaluable when I’m working on new features and need to simulate traffic without having a physical creature connected.
metrics
Pulls server performance counters — how many frames have been processed, events scheduled, DMX packets sent, and so on. Quick way to sanity-check that the server is humming along.
network
The sacn-listen command exposes a TCP port that streams sACN frame data, which lets the Console visualize what’s being sent over the network even when it’s not on the same machine as the server. This was really helpful when I was debugging E1.31 issues from my laptop while the server was running on another machine.
debug
Cache invalidation commands for when things get stale — animations, creatures, playlists, and sounds each have their own cache that can be flushed independently. Also has a test command for simulating playlist update messages.
Distribution
The CLI is packaged as a Debian package and distributed to all of my Linux machines, so it’s always available wherever I need it. I also keep the macOS build on my Macs. Having the CLI a quick creature-cli away on every machine in the workshop makes it easy to poke at the server from wherever I happen to be.
Usage
For development, you can build and run it from the Swift package:
cd Common && swift run creature-cli
It connects to the Creature Server over the same RESTful API and WebSocket that the Console uses. You can point it at any server with --host and --port, or use --proxy-host and --proxy-api-key to go through the external proxy.
It also supports bash completions — run ./create_completions.sh to generate them.