Reference: CLI
led-ticker exposes one console script (led-ticker) with a default
“run the display” mode and validate, plugin, and webui subcommands. Day-to-day
development is wrapped in make targets that drive uv, pytest,
ruff, and the docs site. The console
script is registered in pyproject.toml as
led-ticker = "led_ticker.app:main".
led-ticker (default)
Section titled “led-ticker (default)”Runs the display loop against a TOML config. With no subcommand, the CLI loads the config, builds the playlist, opens the panel, and starts rendering until interrupted.
| Flag | Default | Notes |
|---|---|---|
--config / -c | config.toml | Path to the TOML configuration file. Resolved relative to the working dir. |
--backend | (config) | Override the display backend (e.g. headless). Takes precedence over [display] backend in the config. Unknown names fail with a clear registry error. Primarily used by the make try Docker flow to run headless without modifying your deploy config. |
The LED_TICKER_BACKEND environment variable is the env equivalent of
--backend (the flag wins when both are set) — it’s how compose.try.yaml
selects the headless backend.
If the config path doesn’t exist, the CLI prints a hint pointing at
config.example.toml and exits with status 1.
led-ticker --config config/config.tomlled-ticker --config config/config.toml --backend headlessled-ticker validate
Section titled “led-ticker validate”Validates a TOML config without opening the panel — checks every widget builds, every transition resolves, and every reference (font names, image paths, color shapes) is well-formed. Useful in CI and as a pre-flight check before deploying a config to a Pi.
led-ticker validate config/config.tomlled-ticker validate config/config.toml --jsonled-ticker validate --strict config/config.toml| Flag | Default | Notes |
|---|---|---|
path | — | Path to the config file. Required unless --list-fields is given. |
--json | off | Emit machine-readable JSON instead of human-readable text. Used by the creating-a-config skill. |
--strict | off | Promote all warnings to errors. Also checks that gif/image path fields exist on disk. Use in CI to enforce a warning-clean config. |
--fix | off | Apply auto-fixable migrations (key renames) to the config file in-place. Comments in the TOML file are not preserved. |
--list-fields | — | Print all valid fields for a widget type and exit (e.g. --list-fields message). No path argument required. |
Exits 0 on a clean config, 1 on validation errors (or promoted warnings with --strict), 2 if the
config file isn’t found. See Tools: validate for
the full output format (human + JSON), exit codes, and CI examples.
led-ticker plugin
Section titled “led-ticker plugin”Manage plugins. Two pairs of verbs: add / remove edit the manifest
(config/requirements-plugins.txt) only — the Docker path, where a
docker compose restart triggers a startup reconcile that installs from the
manifest (no rebuild) — and install / uninstall also run pip, for
dev / source-checkout installs. (The old led-ticker plugins is a deprecated alias of
plugin status.)
# Docker: edit the manifest, then restartled-ticker plugin add pool # + line in requirements-plugins.txt (no pip)led-ticker plugin remove pool # − line (no pip)docker compose restart # installs/uninstalls on the next start — no rebuild
# Dev / source checkout: also pip-install nowled-ticker plugin install pool # add + pip installled-ticker plugin uninstall pool # remove + pip uninstall
led-ticker plugin status # plugins loaded/failed for the configled-ticker plugin list # the catalog ([declared] / [installed])led-ticker plugin search pool # search the catalogAll four management verbs accept a catalog name or a raw pip spec (a
git+https://… URL or a PyPI requirement, like pip), default the manifest to
config/requirements-plugins.txt (run from your project root; --config <path>
for a non-standard layout, warned if it’d write outside config/), and dedup by
plugin while preserving comments. add/install take --source git|pypi and
--unpinned; all take --dry-run.
Run these on the host, not inside the container — they edit a host file, and
the container mounts ./config read-only, so docker compose exec led-ticker led-ticker plugin add … fails. If you run led-ticker purely via Docker and have
no host led-ticker command, edit config/requirements-plugins.txt by hand
(cp config/requirements-plugins.example.txt config/requirements-plugins.txt)
and restart — docker compose restart. It’s the same manifest.
plugin add / plugin remove (manifest only — Docker)
Section titled “plugin add / plugin remove (manifest only — Docker)”add resolves the name to a pip requirement and writes it to
config/requirements-plugins.txt (pinned to the catalog’s recommended ref by
default; a typo close to a catalog name gets a “did you mean …?”). Re-adding the
same plugin is idempotent (“already declared” if unchanged). remove drops the
matching line (idempotent — “not in …” if absent). Neither runs pip — they only
edit the manifest. Run docker compose restart to apply: a startup reconcile
installs/uninstalls from the manifest on the next start (no rebuild needed). The
container is read-only at runtime; plugins install onto the ticker-plugins
volume, not into the image.
The bundled pool/baseball/crypto entries currently pin to @main, so the default
(“pinned”) and --unpinned write the same @main reference today — pass a tagged
pip spec (e.g. …@v1.2.0) for a fixed production pin until the catalog ships tags.
plugin install / plugin uninstall (manifest + pip — dev / source checkout)
Section titled “plugin install / plugin uninstall (manifest + pip — dev / source checkout)”install does what add does and pip-installs the requirement under
led-ticker’s core dependency constraints (a plugin can pull new libraries but
can’t move a version core pins). uninstall does what remove does and
pip uninstalls the distribution. install --save-only is a deprecated alias of
add. Exits with pip’s exit code on a failed install (the manifest is still
updated).
| Flag | Default | Notes |
|---|---|---|
--source | first source | (add/install) git or pypi — which catalog source to use. |
--unpinned | off (pinned) | (add/install) Write @main / a bare PyPI name instead of the catalog ref. (Bundled refs are @main today, so this is a no-op for them — see above.) |
--dry-run | off | Print the plan without changing anything. |
--config / -c | (none) | Non-standard layout only: use requirements-plugins.txt next to this config instead of ./config/. |
plugin status
Section titled “plugin status”Lists the plugins discovered for a config — both the ones that loaded and
any that failed — without opening the panel. For each loaded plugin it
prints the namespace, its source, and the surfaces it contributes
(widgets, transitions, fonts, or hooks only); failed plugins are listed
with their load error. Handy for confirming a freshly installed plugin is
being picked up before you deploy. --config / -c selects the config
(defaults to the top-level). Exits 0 — printing No plugins found. when
the config is absent or lists no plugins — and 2 only if a config that
exists can’t be parsed.
plugin list / plugin search <query>
Section titled “plugin list / plugin search <query>”list prints the bundled catalog — each plugin’s name, summary, and the
widgets/transitions it provides — marking each [declared] (present in
requirements-plugins.txt, so it installs on the next restart) and/or
[installed] (importable in this environment now). search filters that
catalog by a case-insensitive substring over the name, summary, and provided
names. --config / -c locates the manifest for the [declared] check.
Make targets
Section titled “Make targets”The repo’s Makefile wraps the common dev commands so you don’t have
to remember the underlying uv / pnpm / docker invocations. Run
make help to print the same list straight from the Makefile.
Development & quality
Section titled “Development & quality”| Target | What it does |
|---|---|
make dev | uv sync --extra dev plus install the pre-commit and pre-push hooks. |
make hooks | (Re)install just the pre-commit and pre-push git hooks. |
make test | Run pytest with coverage (no Docker or hardware needed). |
make lint | Run ruff check over src/ and tests/. |
make typecheck | Run pyright over src/. |
make format | Run ruff format over src/ and tests/. |
make clean | Remove build artifacts and caches. Does not stop containers — use make down for that. |
Deploy lifecycle
Section titled “Deploy lifecycle”The everyday ladder for running a sign, in roughly the order you use it:
setup → build → up → update → restart → down, with logs
alongside. None of these hard-code a Compose profile — set
COMPOSE_PROFILES=webui in .env to include the web UI.
| Target | What it does |
|---|---|
make setup | One-command bootstrap: check Docker, seed config/ + .env, and bring the sign up. Usage: make setup [MODE=try|deploy]. |
make build | Build the production Docker image only — no start; single image runs on both Pi 4 and Pi 5. Prerequisite for the *-docker diagnostics below. |
make up | Start the sign from the existing image without rebuilding. |
make update | Update a running deploy after git pull: rebuild the image at the real version and recreate the services. |
make restart | Restart the sign without rebuilding. |
make down | Stop and remove the sign’s containers. |
make logs | Follow the sign’s logs (Ctrl-C to stop). |
Try it with no hardware
Section titled “Try it with no hardware”| Target | What it does |
|---|---|
make try | Run led-ticker with no hardware: headless engine plus web-UI preview at http://localhost:8080. |
make try-down | Stop and remove the try-it containers (and their tmpfs volume). |
Config & hardware diagnostics
Section titled “Config & hardware diagnostics”| Target | What it does |
|---|---|
make validate | Run led-ticker validate against a config TOML. Usage: make validate CONFIG=config/config.toml. |
make panel-test | Cycle the panel through full-frame R/G/B/White/Black to diagnose hardware/wiring/driver issues. Usage: make panel-test [CONFIG=config/config.longboi.toml] [HOLD=2]. See panel-test. |
make panel-test-docker | Same as make panel-test, but runs inside the production Docker image. Stop the running ticker first (docker compose stop). Usage: make panel-test-docker [CONFIG=…] [HOLD=…]. |
make panel-map-reveal | Paint the chain-calibration pattern (no mapper applied) so physical chain order and panel orientation are visible. Usage: make panel-map-reveal [CONFIG=…] [HOLD=2]. See panel-map. |
make panel-map-reveal-docker | Same as make panel-map-reveal, but runs inside the production Docker image. Stop the running ticker first. |
make panel-map-derive | Generate a Remap: mapper string from a layout file (no hardware needed). Usage: make panel-map-derive LAYOUT=layout.txt [CONFIG=…]. See panel-map. |
make panel-map-derive-docker | Same as make panel-map-derive, but runs inside the production Docker image. Stop the running ticker first. Usage: make panel-map-derive-docker CONFIG=… LAYOUT=/tmp/grid.txt. |
make panel-map-verify | Paint a coherent full-canvas diagnostic to verify a mapper string. Usage: make panel-map-verify [CONFIG=…] [MAPPER="Remap:…"] [HOLD=2]. See panel-map. |
make panel-map-verify-docker | Same as make panel-map-verify, but runs inside the production Docker image. Stop the running ticker first. |
Docs site
Section titled “Docs site”| Target | What it does |
|---|---|
make docs-dev | Start the Astro Starlight dev server at http://localhost:4321/ (also rebuilds demo gifs). |
make docs-build | Build the docs site to docs/site/dist/. |
make docs-check-llms | Build the docs and verify the llms.txt Markdown export. |
make docs-lint | Lint the docs site (prettier --check plus astro check). |
make docs-format | Auto-format the docs site with prettier. |
Demos & asset generation
Section titled “Demos & asset generation”| Target | What it does |
|---|---|
make render-demo | Render a single demo gif. Usage: make render-demo CONFIG=path/to.toml OUT=out.gif. |
make plan-gif | Recommend a render --duration for a demo and flag a # render-duration: header that would clip. Usage: make plan-gif CONFIG=path/to.toml. See gif-plan. |
make render-emoji-previews | Re-generate the per-slug emoji preview PNGs in docs/site/public/emoji/. |
make render-long-demos | Render every long-running widget demo (data-fetch widgets) into docs/site/public/demos-long/. |
make render-long-demo | Render one long-running demo by name. Usage: make render-long-demo NAME=widget-weather. |
make render-pinned-demos | Render every pinned short-render demo into docs/site/public/demos-pinned/. |
make derive-phoenix | Re-derive config/assets/phoenix.* from the vendored CC0 source. |
make derive-pride | Re-generate config/assets/pride.* (CC0 rainbow flag). |
make derive-heart-tunnel | Re-generate config/assets/heart-tunnel-opaque.jpg (CC0 heart-tunnel source). |
make setup-demo-fonts | Download the Atkinson Hyperlegible fonts into docs/site/demos-long/fonts/. |
The render-long-demos target only runs locally — the demos make
live HTTP calls and some need API keys that aren’t available in CI.
Source TOMLs live in docs/site/demos-long/; rendered output is
committed to docs/site/public/demos-long/. The render-pinned-demos
target also runs locally for the same reason — pinned gifs are stable
showcases on widget pages, intentionally not regenerated on every
deploy. Source TOMLs live in docs/site/demos-pinned/; rendered
output is committed to docs/site/public/demos-pinned/. Both targets
are fail-soft: a single broken TOML doesn’t block the rest from
rendering — failures get listed at the end and the target exits non-
zero.
Running with Docker Compose
Section titled “Running with Docker Compose”The production deployment uses docker compose. With the repo cloned
on a Pi and a config/config.toml in place, the standard invocation is:
docker compose up -dThe compose file mounts ./config read-only into the container so
you edit the TOML on the host and the container picks it up on
restart. Its restart: unless-stopped policy brings the ticker back
up automatically on boot and after a crash.
Sharp edges
Section titled “Sharp edges”--led-* flags belong to the rgbmatrix library, not led-ticker
Section titled “--led-* flags belong to the rgbmatrix library, not led-ticker”The led-ticker CLI accepts --config / -c, --backend, and the validate
subcommand’s path, --json, --strict, --fix, and --list-fields. Hardware
tuning — panel geometry, GPIO mapping, brightness, RP1 mode — is configured
through the [display] block in your TOML, not via command-line flags. The
rgbmatrix library’s own --led-* CLI flags exist (and [display] maps onto
them internally) but you don’t pass them to led-ticker. See
Reference: Config options for the [display] field list.
The test suite runs without a real Pi
Section titled “The test suite runs without a real Pi”The repo ships test stubs for the C-only rgbmatrix module so the entire suite runs on macOS / CI without hardware. The stubs are found automatically: pyproject.toml sets [tool.pytest.ini_options] pythonpath = ["tests/stubs"], so both make test and a direct pytest (e.g. from your editor’s test runner) put the stub rgbmatrix on the import path — no PYTHONPATH env var to set yourself.