v2.8.0 — Chases · Tier 2 complete
Highlights
Time-based programming has arrived. QLC+ chases — ordered sequences of saved scenes with per-step timing — are now first-class. Until now every action has been static state; the moment you wanted "slow sunset transition over 30 seconds" or "loop a party chase until I tell you to stop," no tool existed. This release closes that gap.
All four Tier 2 items now complete. Remaining backlog is Tier 3 only.
Closes #4. MCP tool catalog 34 → 40.
The moment
create_chase(
name="Sunset",
steps=["Daylight", "Warm", "Amber", "Off"],
hold_ms=7500,
fade_in_ms=1500,
run_order="Loop"
)
start_chase("Sunset")
That's the whole "build a 30-second sunset transition" workflow.
What's new
Six new tools
| Tool | Effect |
|---|---|
list_chases |
List all chases in the workspace |
describe_chase |
Return a chase's full step list with resolved scene names + per-step timing |
create_chase |
Build a chase from name + ordered list of scene references |
delete_chase |
Remove from workspace |
start_chase |
Begin playback via QLC+'s native chase engine |
stop_chase |
Halt playback; fixtures hold their last step |
Step shapes
create_chase accepts three forms per step:
| Form | Example |
|---|---|
| Scene name string | "Warm Wash" |
| Scene numeric ID | 42 |
| Dict with overrides | {"scene": "Amber", "hold_ms": 4000, "fade_in_ms": 1000} |
Scene refs are resolved server-side. Unknown scenes cause the whole create_chase to fail with a structured 400 listing which steps couldn't resolve.
Run modes
- Direction:
Forward(default) ·Backward - RunOrder:
Loop(default) ·SingleShot·PingPong·Random
All normalized case-insensitively ("loop", "single-shot", "ping_pong" etc all work).
Implementation
- Chase XML follows QLC+ 4.14.x format:
<Function Type="Chaser">with<Speed>,<Direction>,<RunOrder>,<SpeedModes>, and a list of<Step Number="i" Values="<scene_id>">elements. - Playback dispatches over the persistent QLC+ WebSocket via
QLC+API|setFunctionStatus|<id>|<0|1>. - New
get_next_function_id()scans ALL function types (Scene + Chaser + EFX + …) since QLC+ uses a single ID space across them. Existing scene-save paths unaffected.
Composability with the rest of the stack
Chases compose massively with everything we've built:
batch_action([create_chase(...), start_chase(...)])— build and cue in one round trip- Chase + strobe — strobe accent during a chase step
- Chase + scene management — duplicate a scene, tweak it, drop it into a chase as a new step
- Unblocks #8 (scheduling) → "schedule
start_chaseat 9am weekdays" - Unblocks #12 (audio-reactive) → "sync chase BPM to audio input"
Upgrade
git pull
./lightsctl.sh control-restart # picks up the new endpoints
./lightsctl.sh mcp-restart # picks up the new MCP toolsNo package dependency changes.
Compatibility
- No breaking changes. All existing endpoints + MCP tools behave identically.
- New routes live under
/api/chases— a previously-unused path. - Workspace XML format is identical to what QLC+ itself writes — chases created via MCP show up in the QLC+ web UI's function list immediately, and chases created in the QLC+ UI are visible via
list_chases.
Documentation
docs/MCP_SERVER.md— new "Chase management" sectiondocs/CONTROL_SERVER_ARCHITECTURE.md— API surface table extended (6 new rows)mcp-server/README.md+ rootREADME.md— refreshed- Wiki
MCP-Server.md+Control-Server.mdupdated - Marketing site: CueSheet Act II restructured around chase build → start → stop (start_chase is the accent row), AiConversation final exchange demonstrates a
batch_action(create_chase + start_chase)for "30-second sunset", new FAQ entry, tool catalog renders 40
Tier 2 status
🎉 All four Tier 2 items complete: