bmdctl commands¶
Generated from the command table (internal/table); do not edit. After
changing a table, run go generate ./cmd/bmdctl.
A command's required arguments follow its words, in the order they're
said (<name>; [name] may be left out); everything optional is a
--name value flag, which may be shortened to any unambiguous prefix.
Unverified commands have a pinned wire format that nobody has confirmed on a
switcher; destructive ones are hard to undo or drop connections. The
echo is the state the device reports back once it has applied the
command; a command without one can't be confirmed. Its key names the
state as the device's library does, so an ATEM's indexes in it count
from 0.
The command line¶
bmdctl [HOST] [--host H] [--json|--quiet] [--yes] [atem] <command> [arguments] [--flag value ...]
Flags, accepted anywhere on the line¶
--host H: The device: a name or alias frombmdctl hostsin any case, any unambiguous start of one, or host[:port] (UDP 9910 by default). Without it: $BMDCTL_HOST, else the host the last --host named, else the default host.--json: Print the engine's JSON response as it is: {ok, confirmed, result, took_ms} or {ok:false, code, error}, one per line.--quiet, -q: Print nothing on stdout; the exit status tells. Errors still go to stderr.--yes, -y: Allow a destructive command.--dry-run: Print a wire command's bytes, header included, and send nothing.--fps N: The frame rate for rates given as seconds:frames (default: the switcher's display rate; 25 with --dry-run).--timeout D: How long to wait for the switcher's echo (default 5s), or for a transfer to finish (default: the library's).--no-color: No colour, even on a terminal.--timestamps, -t: At a terminal, start each result line with the time of day (HH:MM:SS), dim.--help, -h: Help for the command line so far.
Built-in commands¶
bmdctl: Show the engine (running or not, its sessions, the git commit it runs) and a line per host: its alias, its model, video mode, how long its session has been open and idle (or that a watch or a subscription is using it), whether it is pinned or stale (idle past its timeout, not yet closed), and which is the default, where a command that names no host goes now. At a terminal: bmdctl's version, then a line per switcher, the default's marked *. Never starts the engine.bmdctl help: Print the help.bmdctl version: Print bmdctl's version; at a terminal also the commit it was built from, the hosts file and the engine.bmdctl engine [--log-level L]: Run the background engine in the foreground, for systemd or Docker, logging to stderr and its log file. Any command starts one in the background when none is running, and restarts one it started from another build of bmdctl; one run with bmdctl engine answers every build.bmdctl engine --serve [--listen ADDRESS]: Run the engine in the foreground and serve every command over HTTP/JSON from its process, as bmdctl serve does (127.0.0.1:8880 unless --listen says otherwise): a container's command.bmdctl engine stop: Stop the running engine; its sessions say goodbye to their switchers.bmdctl engine status: Show the engine's version, build, pid, socket, log, how long a pinned session may go idle, and its sessions: each one's age, idle time, whether pinned, and when it closes, or stale.bmdctl hosts [list]: List the hosts.bmdctl hosts add ADDRESS [--as NAME] [--device D]: Add the device at ADDRESS by the name it gives itself, as the device that answers there (an ATEM, HyperDeck, Videohub or Ultimatte; --device says it instead): an ATEM's name as set in ATEM Setup, else its model; the others' as they report it. --as gives it another, for two devices with one name. An address added again is asked again.bmdctl hosts discover [--for D]: Add every switcher that announces itself on the network (Bonjour, _switcher_ctrl._udp) within D (2s), by its own name.bmdctl hosts rm NAME: Forget a host.bmdctl hosts alias NAME SHORT: Give a host a short name it goes by as well as its own, wherever a name is taken: one word, not a command's, not another host's name or alias. Another alias replaces it; --rm instead of SHORT takes it away.bmdctl hosts default [NAME]: Show the default host, or make NAME the default and the host commands go to now.bmdctl use HOST: Make HOST the default, the host commands that name none go to from now on, without opening a session (connect HOSTpins one too):hosts default HOSTin two words. HOST is a host's name or alias in any case, the start of either, or its address. $BMDCTL_HOST, when set, still wins, and it says so.bmdctl exec FILE|- [--continue]: Run one command per line, in order, to one host. Every line is checked before the first is sent; it stops at the first failure unless --continue.bmdctl completion bash|zsh|fish: Print a shell completion script: commands, flags, host names and, while the engine runs, the switcher's input names and the indexes it has, counted from 1.bmdctl man [--dir DIR]: Print the bmdctl(1) manual page, or write it to DIR/bmdctl.1.bmdctl doctor: Check the engine, its socket and log, the hosts file and that each host answers, and say what is misconfigured. Exit 1 for a misconfiguration, 2 when a host only didn't answer.bmdctl mcp: Run a Model Context Protocol server on stdin and stdout for an AI agent: a tool per command group (atem_switching, atem_media, hyperdeck_transport, ...) whose subcommand argument is the command and whose other arguments are its, plus list_hosts, wait_for_change (a long poll for the next change, with a cursor so none is missed), and each host's state as a resource to subscribe to. Results say confirmed, sent, already or rejected, with what changed. A destructive subcommand does nothing without confirm: true and says what it would affect. docs/AGENTS.md says how to add it to Claude Code and Claude Desktop.bmdctl serve [--listen ADDRESS]: Serve every command over HTTP/JSON until interrupted, through the engine: GET /hosts, GET /hosts/{host}/state, POST /hosts/{host}/{command} (the command's words as the path, its arguments a JSON object, multipart/form-data for a file; ?yes=true for a destructive one), GET /hosts/{host}/events (server-sent events: watch's frames) and GET /openapi.json. The answer is the engine's, as --json prints it. It listens on 127.0.0.1:8880 unless --listen says otherwise, and has no authentication: whoever can reach it controls the devices.
Conventions¶
- Host: A first word that isn't a command names the host, for that command alone:
bmdctl bc cutisbmdctl --host bc cut, except that it doesn't become the host commands go to after (bmdctl use HOSTdoes that). It is a host's name or alias in any case, the start of either, the name it had before a rename, its address, or any IP address; a word that is a command (a built-in, a device's word, any device's command) is always the command, and --host, given too, wins. A first word that is neither is refused, listing the hosts. After a device's word (bmdctl atem bc cut,hdctl deck play) the next word is taken the same way. - Arguments: A command's required arguments follow its words in the order they're said:
program 5,usk 1 fill cam3,media upload 10 logo.png. Optional ones are --name flags, which may be shortened to any unambiguous prefix (--sat for --saturation);[file]in a syntax may be left out. - Devices: A command without a device word goes to the device type of its host, an ATEM for an address no host has; a command that device doesn't have says what the host is (
DECK 1 is a HyperDeck; bmdctl hyperdeck --help).bmdctl atem ...,bmdctl hyperdeck ...,bmdctl videohub ...andbmdctl ultimatte ...name the device.connect ADDRESSasks what answers there, an ATEM (UDP 9910), a HyperDeck (TCP 9993), a Videohub (TCP 9990) or an Ultimatte (TCP 9998), all at once for 2 s, and saves it by its own name; --type says it instead.bmdctl helplists the device groups hosts.yml has a host of. - Aliases: Run as atemctl, hdctl, vhctl or ultctl, bmdctl is that device's command:
hdctl playisbmdctl hyperdeck play,atemctl cutisbmdctl atem cut, and help lists that device's commands alone. Built-ins (version, hosts, exec, doctor, ...) are bmdctl's. Releases ship them as symlinks to bmdctl (copies on Windows), and install.sh links them. - Hosts: A host goes by the name its switcher gives itself, unless --as gave it one, and by its alias as well, if it has one. When a switcher is renamed in ATEM Setup, the next command to it renames its host in hosts.yml and says so; --host still takes the name it had.
- Output: A command that changes something prints one line: the switcher as
name (address), the command and where (ME1,usk 2), what changed as before → after,confirmed(the switcher reported it back) orsent(it has no such report), and the time. A command that reads prints a line naming the switcher, its model and video mode, then what it read. Opening a session printsconnecting to ...and then the model and video mode on stderr. --json, --quiet and a pipe get exactly that. At a terminal the switcher is named once, in a bold header that also says what is on program and preview (and, when the command opened the session, the model, video mode and how long connecting took); each result is indented under it as the verb, before → after and the time, right-aligned;confirmedis never printed, andsent,rejected(the switcher kept what it held) take the time's place. Nothing is wider than 72 columns. Repeats collapse (aux 1–6 PGM, empty slots counted, not listed; --all lists them), an error iserrorthen the message and, under it, what to do next, a wait of more than 200 ms shows a spinner on stderr that the result replaces (a transfer of known size, a progress bar; a profile, a line per step as it finishes), and a destructive command says what it would affect and asks [y/N] when stdin is a terminal too; -t starts each result with the time of day. Colour only on a terminal, in red, green, bold and dim alone: the value now on program (and a keyer on air) red, on preview green, the switcher's name and bmdctl's own lines bold, ids, times, hints and empty slots dim. - Indexes: M/Es, upstream and downstream keyers, aux outputs, media and macro slots, media players, colour generators, multiviewers and their windows, SuperSources and their boxes, HyperDeck slots and EQ bands count from 1, as ATEM Software Control and the panels count them: on the command line, in --help and in results, --json included. The atem library counts them from 0, and so do the switcher state
stateandwatchprint (andstate --pathreads) and the index attributes of ATEM Software Control's XML files. - Sources: A source is found in this order, case ignored: a number is that input (or source id); cam2, camera 2, in2 and input 2 are input 2, and mp1, bars, black (blk), col1, pgm, pvw, cf1 and aux3 the switcher's fixed sources, whatever their names; else an input's short or long name; else the one input whose name starts so. Where an alias is also an input's name the alias wins, and a terminal says so once. A source nothing names is an error listing the first inputs.
- Rates: A rate is a frame count or seconds:frames at the switcher's display rate (half the field rate from 48 fps up).
Exit status¶
- 0: Done.
- 1: A usage error, or any other failure.
- 2: The switcher or the engine is unreachable.
- 3: Sent, but the switcher did not confirm it in time.
- 4: The switcher refused it (a transfer, a lock), or a profile restore recorded errors.
- 5: Destructive, and --yes was not given.
Environment¶
BMDCTL_HOST: The host a command goes to when --host doesn't name one.BMDCTL_PIN_IDLE: How long a sessionconnectpinned may go without a command before the engine closes it: a duration (90m, 2h) or seconds, 0 for never; an hour unless set. Read when the engine starts.BMDCTL_SOCKET: The engine's socket (a pipe name on Windows), instead of $XDG_RUNTIME_DIR/bmdctl.sock.BMDCTL_STILL_CACHE_MB: How much of the media pool's stills the engine keeps for profile saves, in megabytes: 1024 unless set, 0 for none. Read when the engine starts.XDG_CONFIG_HOME, XDG_STATE_HOME, XDG_CACHE_HOME, XDG_RUNTIME_DIR: Where hosts.yml, the engine's log and last host, the still cache, and the socket live.NO_COLOR: Set to anything: no colour, even on a terminal, as --no-color.TERM:dumb: no colour and no spinner.
Files¶
~/.config/bmdctl/hosts.yml: The named hosts and the default.~/.local/state/bmdctl/engine.log: The engine's log, rotated at 5 MiB, three old files kept.~/.local/state/bmdctl/last-host: The host the last --host named.~/.cache/bmdctl/stills: The media pool's stills at full size, one PNG per picture named by the switcher's MD5, which a profile save writes without downloading them again. The least recently used go past the size ($BMDCTL_STILL_CACHE_MB), and a still no save has used for 30 days. Safe to delete.$XDG_RUNTIME_DIR/bmdctl.sock: The engine's socket; a lock file beside it.
atem¶
switching¶
What is on program, preview and the aux outputs: program, preview, cut, auto, the T-bar, fade to black, undo.
auto · aux · cut · ftb enable · ftb rate · ftb toggle · preview · program · tbar · undo
transition¶
The next transition: its style and rate, each style's settings (mix, dip, wipe, DVE, stinger), what it takes, preview.
transition dip · transition dve · transition mix · transition next · transition preview · transition rate · transition settings · transition stinger · transition style · transition wipe
usk¶
Upstream keyers: fill and key, type (luma, chroma, pattern, DVE) and its settings, mask, fly keyframes, on air.
usk chroma · usk chroma-sample · usk dve · usk fill · usk key · usk keyframe-run · usk keyframe-set · usk luma · usk mask · usk on-air · usk pattern · usk toggle · usk type
dsk¶
Downstream keyers: fill and key, gain, mask, rate, tie, on air, auto.
dsk auto · dsk fill · dsk gain · dsk key · dsk mask · dsk on-air · dsk rate · dsk tie · dsk toggle
audio¶
The audio mixer: Fairlight strips, EQ, dynamics, the master and meters; the classic mixer's (classic-audio ...).
audio compressor · audio eq · audio expander · audio levels · audio limiter · audio master · audio master-compressor · audio master-eq · audio master-limiter · audio meters · audio strip · classic-audio input · classic-audio levels · classic-audio master · classic-audio meters · classic-audio monitor
media¶
The media pool and players: stills uploaded to and downloaded from slots, cleared, what each player shows.
media capture · media clear · media clear-unlocked · media download · media list · media player · media upload
macro¶
Macros: run, stop, record, list, upload and download, decode and encode.
macro action · macro decode · macro delete · macro download · macro encode · macro list · macro record · macro run · macro sleep · macro stop · macro upload
profile¶
ATEM Software Control profiles: save the switcher's setup, restore one, download its stills.
profile images · profile restore · profile save
sources¶
Inputs and sources: the list, renames, colour generators, camera control, HyperDeck slots.
camera · color · hyperdeck-slot · input rename · inputs
outputs¶
Multiviewers, SuperSource, recording and streaming.
multiviewer input · multiviewer properties · recording settings · recording state · streaming audio-bitrate · streaming service · streaming state · supersource box · supersource properties
system¶
The switcher itself: what it is, its video mode, startup state, time.
auto-video-mode · info · startup clear · startup save · time · time-of-day · time-request · video-mode · video-modes
session¶
The session and reads: connect, disconnect, status (what is on air), show one area, the raw state, watch changes.
connect · disconnect · show · state · status · watch
hyperdeck¶
transport¶
The transport: play, pause, stop, record, loop, next and previous clip, goto a clip or a timecode, the active slot.
goto · loop · next · pause · play · prev · record · slot · stop
setup¶
The deck's setup: remote control on or off, and its configuration (inputs, file format, record prefix, timecode): show and set.
configuration set · configuration show · remote
session¶
The session and reads: status (transport, timecode, clip, slots, time left), the timeline's or a disk's clips and editing the timeline, the raw state, watch changes, connect, disconnect.
clips · connect · disconnect · state · status · timeline add · timeline clear · timeline remove · watch
ultimatte¶
profile¶
Archive and restore: the presets and settings to a Smart Remote 4 zip, and back.
network¶
The network interface: read it, or set its address, mask, gateway, DNS or DHCP.
session¶
Reads: status (label, presets, network), the presets, the control values, the prelude, connect.
connect · controls · prelude · presets · status
videohub¶
routing¶
Routing and labels: route an input to an output, rename an input or an output.
input rename · output rename · route
session¶
The session and reads: status (the routing, with labels and locks), the inputs, the outputs, the raw state, watch changes, connect, disconnect.
connect · disconnect · inputs · outputs · state · status · watch