Skip to main content

Command Line Interface (CLI)

note

The CLI is subject to redesign, and is expected to stabilize in v1.0.

The desktop EZPlayer application (Windows, macOS, Linux) accepts an optional verb followed by command-line flags when launched from a terminal, shortcut, or service script:

EZPlayer.exe [<verb>] [--flags...]

With no verb, EZPlayer starts the windowed player as always. Flags control the show folder, LAN web server ports, and first-run behavior.

Verbs

The first non-flag argument decides what EZPlayer does:

First argumentWhat happens
(none)Launch the desktop app (the normal GUI).
A leading-dash flag (--show-folder, --web-port, …)Launch the desktop app, configured by that flag and any others.
headlessRun the full player with no windows — it still plays the show and serves the web API.
play, stats, discover, interfaces, controller, shell, files, helpRun a text-only command and exit without opening a window or starting the show.
Any other barewordError: EZPlayer prints unknown command '…' and the usage text, then exits with code 64. It does not fall through to the GUI.

Note the distinction between the two window-less modes: headless is the player running without a UI, while the text-only commands are diagnostic/management tools that print and exit before the app ever bootstraps.

note

The text-only commands are also available from the pure-Node CLI entry used in development and CI (node dist/cli.js <command>), which has no GUI to launch.

Everything from Launch flags onward describes the flags that configure the desktop app. The next section describes the text-only commands.

Text-only commands

These commands print plain text and exit; they never open a window or start the show. They are useful for setup, network diagnostics, and scripting.

CommandPurpose
playPlay a sequence on a running player and report playback statistics while it runs.
statsPrint a running player's playback statistics.
discoverScan LAN networks for lighting controllers.
interfacesList this host's networks (the CIDRs to feed discover).
controllerInspect and manage lighting controllers — see its four subcommands below.
shellSet the password that enables the remote terminal.
filesSet the password that enables the file manager.
helpPrint the command list. Also --help, -h.

discover, interfaces, controller status, and controller action talk to devices directly and need no running player. play, stats, controller list and controller upload query/drive a running EZPlayer over its LAN API (--host, default 127.0.0.1:3000, honoring EZPLAYER_WEB_PORT) — playback, the reconcile state and the xLights upload intent only exist inside the app.

Everything that acts on a lighting controller is a subcommand of controller, which keeps the plain names free for what they sound like — the player's own status, or uploading show content:

SubcommandPurpose
controller listShow the controller reconcile state from a running player.
controller statusDeep-read one controller and print its detail report.
controller actionRun a management action (e.g. reboot) on a controller.
controller uploadUpload xLights-derived config to a controller (via the app).

Get top-level help or per-command help:

EZPlayer help # list commands
EZPlayer discover --help # options for one command
EZPlayer controller # list the controller subcommands

play

Play one sequence on a running player — windowed or headless — and report the playback engine's statistics while it runs. This is the tool for "it drops frames" questions: it resets the cumulative counters, starts the sequence as an immediate jukebox play, prints one trace line per sample to stderr, and ends with a summary on stdout.

EZPlayer play <sequence> [--host <host[:port]>] [--show-folder <dir>] [--duration <s>]
[--interval <s>] [--no-output] [--keep-playing] [--json] [--quiet]

<sequence> is the sequence's id, its title, or its .fseq file name (with or without the extension), matched against the player's loaded sequence list.

OptionAliasDescription
--host <host[:port]>The running player's LAN API. Without it, the local player's port is read from the show folder's lock file (see --show-folder), then EZPLAYER_WEB_PORT, then 127.0.0.1:3000.
--show-folder <dir>-sShow folder whose lock file names the running local player. Default: the current directory, when it is a show folder.
--duration <s>-dSeconds to run. Default: the sequence length plus two seconds; the run also ends early when the sequence finishes.
--interval <s>-iSeconds between samples. Default 1.
--no-outputSuppress controller output for the run: frames are still produced, timed and shown in the preview, but nothing is sent to the controllers. Lets you benchmark a show on a machine that cannot reach its controllers. Output is re-enabled when the run ends.
--keep-playingLeave the sequence playing at the end (by default it is ended, like a jukebox skip).
--jsonMachine-readable { sequence, summary, samples } on stdout instead of the text summary.
--quiet-qNo per-sample trace on stderr.

Each trace line shows what changed since the previous sample — frames sent, skipped (the frame was late by more than the skip threshold) and missed (its data was not in the FSEQ cache when it was due) — plus the worst lag, average controller send time, how idle the playback loop was, the playback thread's event-loop delay, the FSEQ chunk cache state (ready / pending / fetching), and the read and decompress time spent in that interval.

The summary rolls that up: delivery ratio, worst lag, send times, loop delay, FSEQ cache fetches / hits / misses / evictions, read + decompress time per fetch, and audio chunks. The loop delay (p99 / max) is the number to look at when the read or decompress times look impossibly high: the playback loop runs the prefetch's completions, so anything that hogs it — most often sending many thousands of packets per frame — shows up as inflated read time and, past a point, as missed frames.

A typical benchmark run needs no controllers at all:

EZPlayer headless --show-folder=D:\Shows\2025 --web-port=3123
EZPlayer play "Jingle Bells" --host 127.0.0.1:3123 --no-output
Playing "Jingle Bells" on 127.0.0.1:3123 for 38s (controller output suppressed); sampling every 1s
t= 1s sent=+2 skip=+0 miss=+0 lag=1.0ms send=0.0ms idle=0.0% loop(p99/max)=73.5ms/73.7ms cache=8r/35p/2f fetch=+8 read=+162ms decomp=+249ms
t= 2s sent=+40 skip=+0 miss=+0 lag=5.4ms send=0.0ms idle=25.4% loop(p99/max)=30.7ms/30.7ms cache=63r/0p/0f fetch=+55 read=+814ms decomp=+484ms

Sequence finished.

Run: 37.4s, 38 samples
Frames: 1429 sent, 2 skipped (late), 0 missed (no data) → delivery ≈ 99.9%
Timing: worst lag 36.7ms, worst advance 0.0ms; send avg 0.00ms / max 0.0ms; loop idle 87.5%; loop delay p99 73.5ms / max 82.5ms
FSEQ: 711 chunk fetches (0 errors), 1431 hits / 0 misses, 483 evicted, 0 expired; read 2.01s + decompress 2.08s = 5.8ms per fetch (wall, incl. queueing); cache 997 / 1000 MB
Audio: 0 chunks sent, 0 skipped; read 0.00s + decode 0.00s

Exit code 0 when the run completed (regardless of how well it played), 1 if the player could not be reached, the sequence is unknown, or it never started playing, 2 for a usage error.

stats

Print the running player's playback statistics — the same counters as the Status screen's statistics dialog — once, or repeatedly.

EZPlayer stats [--host <host[:port]>] [--show-folder <dir>] [--reset] [--watch [<s>]] [--json]
OptionAliasDescription
--host <host[:port]>The running player's LAN API; defaults like play (lock file, then EZPLAYER_WEB_PORT, then 127.0.0.1:3000).
--show-folder <dir>-sShow folder whose lock file names the running local player. Default: the current directory, when it is a show folder.
--resetReset the cumulative counters first.
--watch [<s>]-wKeep sampling every <s> seconds (default 1), one trace line per sample, until interrupted.
--jsonRaw { stats, pStatus, serverNow } JSON (GET /api/ezp/playback-stats) on stdout.
EZPlayer stats # one snapshot of the local player
EZPlayer stats --reset --watch 2 # zero the counters, then a line every 2s

discover

Scan one or more networks for lighting controllers and print what is found.

EZPlayer discover [--networks <cidr[,cidr…]>] [--depth sweep|identify|full] [--fpp-proxy]
OptionAliasDescription
--networks <cidr>-nComma-separated CIDRs to scan (e.g. 192.168.1.0/24,10.0.0.0/24). Omit to scan every external host network (run interfaces to see them).
--depth <level>-dHow hard to look — see the table below. Default: identify.
--fpp-proxyRecurse one level through FPP proxies to find controllers behind them. Needs identify or full; ignored (with a warning) on sweep.

Depth levels

DepthWhat you get
sweepLiveness only — IP, MAC/OUI, mDNS hostname, and detected protocols.
identify(default) Everything in sweep, plus driver-confirmed vendor, model, and firmware.
fullEverything in identify, plus a per-device detail tree.

Output adapts to where it is going:

  • Interactive terminal (sweep/identify): a live table redraws in place as devices resolve, ending with a summary line.
  • Piped or redirected output: progress goes to stderr; the final table is printed once to stdout. This makes EZPlayer discover … > devices.txt clean.
  • full: a detail tree is printed per device at the end; progress stays on stderr.

Every run ends with N device(s), M identified. Exit code is 0 on success, or 2 for a usage error (an invalid --depth, an unrecognized argument, or no scannable network found).

# Scan the whole LAN at default depth
EZPlayer discover

# Two specific subnets, confirm models, follow FPP proxies
EZPlayer discover -n 192.168.1.0/24,192.168.2.0/24 -d identify --fpp-proxy

# Full detail, captured to a file
EZPlayer discover --depth full > controllers.txt
note

Discovery scans the network actively (ARP/mDNS/driver probes). Only run it on networks you are authorized to scan.

interfaces

List this host's external IPv4 networks as CIDRs, ready to pass to discover --networks. Internal and link-local (169.254.x.x) addresses are excluded.

EZPlayer interfaces
INTERFACE ADDRESS NETWORK
Wi-Fi 192.168.1.154 192.168.1.0/24
Ethernet 10.0.0.12 10.0.0.0/24

Exit code is 0. If no external IPv4 interface exists, it prints (no external IPv4 interfaces).

controller list

Print the running player's controller reconcile state: known controllers (xLights ∪ EZPlayer records) versus what the network scan found, plus recent operations and network policies.

EZPlayer controller list [--host <host[:port]>] [--json]
OptionDescription
--host <host[:port]>The running player's LAN API. Default 127.0.0.1:3000 (EZPLAYER_WEB_PORT honored).
--jsonEmit the raw state as JSON instead of tables.
EZPlayer controller list # local player
EZPlayer controller list --host pi5:3000 # a player elsewhere on the LAN

controller status

Deep-read one controller and print its detail report (identity, health, per-port config). Talks to the device directly — no running player needed. A bare name (instead of an IP) is resolved through the running player's known controllers.

EZPlayer controller status <ip-or-name> [--host <host[:port]>] [--json]
EZPlayer controller status 192.168.11.61
EZPlayer controller status "Mega Tree" --json

controller action

Run a management action against one controller, or list the actions its driver offers. Talks to the device directly.

EZPlayer controller action <ip-or-name> <actionId> [--host <host[:port]>]
EZPlayer controller action <ip-or-name> --list

Action ids are driver-specific — --list shows them (e.g. FPP offers restart for a quick daemon restart and reboot for a full OS reboot; most pixel controllers offer reboot only).

EZPlayer controller action 192.168.11.63 --list
EZPlayer controller action 192.168.11.63 reboot

controller upload

Push the xLights-derived configuration (input universes and/or string outputs) to one controller, by known-record name. Runs through the running player: the upload intent comes from the show's xLights files, and the app performs a post-upload read-back so every UI reflects the device's new state.

EZPlayer controller upload <name> [--scope inputs|strings|full] [--full-control] [--host <host[:port]>]
OptionDescription
--scopeinputs (universes), strings (port outputs), or full (both — the default).
--full-controlSettings xLights doesn't specify are reset to the controller defaults (brightness/gamma/color order), wiping per-port tweaks made on the device.
EZPlayer controller upload "Mega Tree" --scope strings
EZPlayer controller upload GarageF16 --full-control
warning

Uploads rewrite the controller's port configuration. There is no undo beyond uploading again.

Remote access: terminal and file manager setup

EZPlayer optionally offers two features:

  • Shell — a terminal on the player machine.
  • Files — a file manager for the show folder: browse, upload, download, rename, move and delete.

Both are off by default. The only way to turn either on is to establish a password via these commands, run on the player machine itself:

# Read the password from a file (recommended form)
EZPlayer files --show-folder "D:\Shows\MyShow" --password-file secret.txt

# Or inline (see the caution below)
EZPlayer files --show-folder "D:\Shows\MyShow" --password "correct horse battery"

# Or inline (see the caution below)
EZPlayer files --show-folder "D:\Shows\MyShow" --stdin # Read from console

EZPlayer files --show-folder "D:\Shows\MyShow" --status # is it enabled?
EZPlayer files --show-folder "D:\Shows\MyShow" --clear # disable it entirely
caution

For Windows, use ezplayer.cmd, not EZPlayer.exe. EZPlayer.exe is a GUI-subsystem binary, with limited ability to use the console. --stdin does not work directly with EZPlayer.exe.

The Windows installer therefore places a small console launcher, ezplayer.cmd, next to it. Use that for every text-only command.

There are separate passwords for files and shell; each is independently on or off.

Until a password is set for a feature there is no tile in Settings and no endpoint on the network. Once one is set, the matching tile appears in that show's Settings screen; opening it asks for that password. See Shell and Files for what each one does.

Password reset commands work whether or not a player is running; if one is running locally it is nudged over loopback so the change takes effect without a restart.

warning

Enabling shell access on a machine provides siginificant power over both that machine, and anything reachable over the attached networks. You should only enable this if the diagnostic benefits of full remote access outweigh the potential for damage or loss of sensitive information.

Enabling remote file access also has the potential to allow remote reading or update of sensitive files.

Ensure that your passwords are appropriately secure.

There is deliberately no way to set either password from any UI. Enabling remote access requires the ability to run commands on the player already, which keeps the decision with whoever owns the machine.

OptionMeaning
--show-folderWhich show to set the password for. Defaults to the current directory when that is already a show folder (it has a .ezplayer/ directory); otherwise required.
--password-fileRead the password from the first line of a file (recommended option).
--passwordThe new password, given inline. Convenient, but see the caution below.
--stdinRead the password from stdin. (Requires ezplayer.cmd on Windows.)
--clearRemove the password. Anything open at the time is closed immediately.
--statusReport whether the feature is enabled for this show, and the file in use.
--portLoopback port of the running player. (Defaults to checking the lockfile)
caution

--password puts the password in your shell history, and on most systems it is visible to other users in the process list for as long as the command runs. Prefer --password-file on a machine you share — the value never reaches either.

Passwords are stored salted and hashed (scrypt) in <show folder>/.ezplayer/remote-access.json, alongside the other per-show settings. That makes remote access a property of the show, not the machine: move the show folder to another player and the settings travel with it, and two shows on one machine can differ. Switching a running player to a different show folder closes any terminal or file-manager session that was open, since it belonged to the previous show.

Things worth knowing before you enable either:

  • Only one terminal at a time, player-wide. Opening a second closes the first, and it is told why rather than just going quiet. Closing the window kills the shell. The file manager has no such limit.
  • The file manager cannot leave the show folder, and cannot see the player's own .ezplayer/ settings directory at all — that is where these password hashes and your cloud credentials live. xlights_rgbeffects.xml and xlights_networks.xml are visible but cannot be renamed, moved or deleted.
  • Cloud security: All cloud transport, if enabled, is encrypted. A fully remote user/attacker needs the cloud URL, the player token, and the relevant password.
  • LAN security: The LAN UI is plain HTTP, so someone sniffing your local network while you log in could capture a password. That matches the rest of the LAN surface, which has no authentication at all — but it is worth knowing if your LAN is not trusted.
  • Repeated wrong guesses lock the endpoint out for escalating periods, per feature, so the password rather than the network is what an attacker has to beat.

Exit codes

CodeMeaning
0Success, or a help request.
2Usage error within a command — bad option or invalid argument.
64Unknown verb (rejected by the launcher before the app starts).
1Unexpected failure (an uncaught error while running the command).

Launch flags

The remaining sections describe launch-flag mode — the flags that configure the desktop app when it opens. These are leading-dash arguments, so they never collide with the verbs above.

CLI arguments take priority over environment variables when both configure the same setting (for example --web-port= beats EZPLAYER_WEB_PORT).

On Windows, append flags after the executable path. On Linux AppImage/deb packages, executableArgs may include --no-sandbox automatically — see Platform notes.

Quick reference

Verb / FlagPurpose
headlessRun the full player with no windows (details)
--show-folder=<path>Open the given show folder on launch
--web-port=<n>LAN HTTP server port (default 3000)
--kiosk-port=<n>Kiosk web server port (default 3001)
--kiosk-port=0Disable the kiosk server
--user-data-dir=<p>Isolate all persisted app state to the given directory
--resetClear persisted state, then quit (cloud welcome on next launch)
--reset-nocloudClear persisted state, pin local-only welcome, then quit
--no-update-checkSkip automatic update checks (startup and idle pre-download)

Show folder

Point EZPlayer at a specific show folder without using the folder picker:

EZPlayer.exe --show-folder=C:\Shows\MyDisplay
./EZPlayer --show-folder=/home/user/shows/my-display

The path must exist as a directory. If it is valid, EZPlayer saves it as the persisted show folder and loads sequences, playlists, schedule, and layout from there.

If the folder is missing required files (for xLights-managed shows: xlights_rgbeffects.xml and xlights_networks.xml), EZPlayer warns you and offers to pick another folder.

Only one EZPlayer instance can lock a given show folder at a time. A second instance using the same folder is prompted to choose a different path or quit.

Headless mode

The headless verb runs the full player with no windows: scheduled and API-driven playback, light output, the LAN web/API server, kiosk server, and cloud connectivity all behave exactly as in the windowed app. Audio is still decoded and streamed to the web UI and cloud listeners; it is simply not played out on the machine's local speakers (no hidden audio window is created).

EZPlayer.exe headless --show-folder=D:\Shows\2025 --web-port=3000

Anything that would normally raise a dialog fails fast instead:

Exit codeMeaning
2No show folder configured, or the folder is missing/invalid
3The show folder is locked by another EZPlayer instance
64Unrecognized verb

A headless run never modifies persisted preferences — the show folder and ports passed on the command line apply to that run only, so it can coexist with an interactive install on the same machine. Headless also does not check for or install EZPlayer updates without explicit user intervention.

To fully isolate state (e.g. for automated testing, or a second independent player), add --user-data-dir=:

EZPlayer.exe headless --show-folder=C:\Shows\Test --web-port=8090 ^
--kiosk-port=0 --user-data-dir=C:\Temp\ezp-test-profile

Stop a headless player with Ctrl-C (SIGINT) or SIGTERM; it stops playback, releases the show-folder lock, and exits cleanly. EZPLAYER_HEADLESS=1 in the environment is equivalent to the verb for service scripts that cannot alter arguments.

On headless Linux boxes (no X server), pass --ozone-platform=headless on the command line (it must come before EZPlayer's own arguments):

./EZPlayer --ozone-platform=headless headless --show-folder=/home/user/show

LAN and kiosk ports

EZPlayer starts a Koa HTTP server for the LAN web interface and optionally a second kiosk listener. Configure ports at launch:

EZPlayer.exe --web-port=8080 --kiosk-port=8081
FlagDefaultDescription
--web-port=<n>3000Main LAN UI, REST API, and WebSocket (/ws)
--kiosk-port=<n>3001Simplified public UI (jukebox/player only)
--kiosk-port=0Do not start the kiosk server

Valid ports: 1024–65535.

Port resolution order

For each port setting, EZPlayer resolves the value in this order:

  1. CLI flag (--web-port= / --kiosk-port=)
  2. Environment variable (EZPLAYER_WEB_PORT / EZPLAYER_KIOSK_PORT)
  3. Stored preference (saved from a prior launch)
  4. Built-in default (3000 / 3001)

If the chosen port is already in use, EZPlayer tries up to ten consecutive ports. Check Show Status → HTTP Listener Status on the desktop app for the actual Port, Source, and Listening state.

Equivalent environment variables are documented in Environment Variables.

Reset and first-run flags

Reset flags clear persisted startup state and exit immediately — they do not start a show. Use them to recover from a bad folder choice or to re-run the welcome flow.

FlagWhat is clearedNext launch welcome screen
--resetShow folder pointer, renderer localStorageCloud option shown (default)
--reset-nocloudSame as --resetLocal/xLights only (cloud CTA hidden)

--reset-cloud is an alias of --reset.

Example:

EZPlayer.exe --reset-nocloud

After running a reset flag, start EZPlayer normally. You will see the welcome screen again and can pick a new show folder.

warning

Reset flags quit the app after clearing state. They do not delete your show folder files — only EZPlayer's stored pointer to that folder.

Debugging and logging

These are standard Chromium/Electron switches useful when diagnosing problems. They are not required for normal operation.

FlagDescription
--enable-loggingEnable Chromium logging to stderr/log files
--v=1Verbose log level (often used with --enable-logging)

Example from the project's package.json scripts:

./release/win-unpacked/EZPlayer.exe --enable-logging --v=1

Log files are written under the platform log directory (on Windows, typically under %APPDATA%\EZPlayer\logs via Electron's app.getPath('logs')).

To open DevTools in a packaged build, use the environment variable EZP_OPEN_DEVTOOLS instead of a CLI flag — see Environment Variables.

Updates

Installed versions of EZPlayer check for updates as set in Settings → Software Update.

To suppress automatic checks without opening the UI — for example on a locked-down or offline show machine:

FlagDescription
--no-update-checkSkip the automatic checks. (Check for Updates in Settings still works.)

Headless mode does not run the updater at all. Development (unpackaged) runs do not either.

Certificates and TLS

EZPlayer talks to the EZRGB cloud over HTTPS. It automatically trusts the operating-system certificate store, so an OS-trusted corporate proxy or self-signed root that works in your browser works here too. To add a CA that isn't in the OS store, set the standard Node.js variable NODE_EXTRA_CA_CERTS (path to a PEM file). As a last-resort debugging step only, NODE_TLS_REJECT_UNAUTHORIZED=0 disables verification entirely (insecure). See Environment Variables → Certificates and TLS.

Sandbox, GPU, and proxy

These are standard Electron/Chromium switches (not EZPlayer-specific) that pass through to the underlying runtime. They are occasionally useful for troubleshooting startup, rendering, or networking:

FlagWhen to use
--no-sandboxApplied automatically on Linux (see Platform notes). Rarely needed elsewhere; can work around sandbox-related launch failures.
--disable-gpuForce software rendering to work around GPU/driver glitches (blank window, flicker, artifacts).
--proxy-server=host:portRoute EZPlayer's traffic through an explicit HTTP/HTTPS proxy. Pair with a trusted CA (above) if the proxy intercepts TLS.

Platform notes

Linux

  • EZPlayer appends --no-sandbox on Linux at startup (Ubuntu 24.04+ AppArmor and older distros without a setuid sandbox helper).
  • Linux packages in electron-builder config also list --no-sandbox in executableArgs for AppImage/deb/tar.gz targets.

macOS

  • Use quoted paths if the show folder contains spaces: --show-folder="/Users/me/My Show".

Windows

  • Paths with spaces work with --show-folder=C:\My Shows\Display or quoted forms in batch files.

Examples

Production show PC — fixed LAN port, known folder

"C:\Program Files\EZPlayer\EZPlayer.exe" --show-folder=D:\Shows\2025 --web-port=3000

Dedicated kiosk tablet browser target — disable main port change, custom kiosk

./EZPlayer --kiosk-port=3001

Guests open http://<show-pc-ip>:3001.

Development (from repository)

pnpm dev

Prompts for a web port and sets EZPLAYER_WEB_PORT before starting Electron. Additional flags can be passed through pnpm dev:direct / electron . when needed.

Factory reset before handing off a machine

EZPlayer.exe --reset

Internal flags (not for operators)

The main process may pass these to the renderer via Electron additionalArguments. They are not part of the public operator CLI:

FlagPurpose
--show-welcome=true / --show-welcome=falseControls whether the welcome screen appears on that process launch

Use --reset* or remove an invalid show folder rather than passing --show-welcome manually.