← Docs

scenelight

CLI for direct BLE-Mesh control of studio lights (amaran Ray series today, more brands later). Sub-100 ms latency once the background daemon is running.

Install (per machine, ~5 seconds)

curl -fsSL https://releases.daslab.dev/scenelight/install.sh | sh

Drops the binary at ~/.local/bin/scenelight. Apple Silicon Macs only for now.

Setup (per user, once)

Requires the amaran iOS-on-Mac app installed and signed into the user's Aputure account, with at least one light paired. Then:

scenelight setup    # extracts mesh keys from amaran's local SQLite
scenelight start    # background daemon for fast subsequent calls

Commands

scenelight color <spec> [-b <0-100>] [<light>]
scenelight on  [<light>]
scenelight off [<light>]
scenelight brightness <0-100> [<light>]
scenelight lights              # list configured lights
scenelight status [<light>]    # current state
scenelight raw <dst> <opcode> <hex-payload>   # lowest-level mesh PDU
scenelight stream [--retries N] [--rate FPS]   # animation pipe

<spec> accepts

formexamples
Hex#ff8800, ff8800, f80
Named chromaticred, orange, amber, yellow, lime, green, spring, teal, cyan, sky, blue, indigo, purple, violet, magenta, pink, rose, white
Named white CCTcandle, tungsten (= warm), bulb, halogen, fluorescent, daylight, cool

<light> accepts

  • A key like ray3 — see scenelight lights
  • A mesh address like 0x0004
  • Omit (or all) — broadcasts to every configured light

Examples

scenelight color warm -b 70           # warm tungsten at 70%
scenelight color "#003355" -b 50      # deep navy at 50%
scenelight color daylight ray3        # only ray3 to daylight white
scenelight off                        # all lights off

stream — animation pipe

scenelight stream reads commands from stdin, one per line, and dispatches them against the running daemon over a single persistent socket (no per-frame reconnect). Each line is a bare CLI subcommand with the scenelight prefix dropped.

Special directives:

  • sleep <seconds> — pause without dropping the socket
  • lines starting with # are comments

Defaults --retries 1 (vs 3 for one-shot commands) — animation streams tolerate per-frame packet loss because the next frame corrects it visually, and lower retries means 3× higher effective frame rate.

# Hand-written
printf 'color warm -b 70\nsleep 0.2\ncolor blue\nsleep 0.2\noff\n' | scenelight stream

# Generated — sea waves (cyan ↔ deep blue, breathing brightness)
awk 'BEGIN {
  for (t = 0; t < 150; t++) {
    sec = t / 10.0
    h = 220 + int(45 * sin(sec * 0.6))
    b = 60 + int(35 * sin(sec * 0.4))
    print "hsi " b " " h " 100"
    print "sleep 0.1"
  }
}' | scenelight stream --retries 1

# Optional rate cap so a runaway generator doesn't oversaturate
scenelight stream --rate 20 < animation.lights

The grammar is the existing CLI minus the binary name. Any shell tool that can emit lines into a pipe — awk, python3, tail -f, a Daslab agent emitting via shell asset — can drive lights.

Notes

  • Latency: first call after scenelight start is ~5 s (BLE connect + filter). Subsequent calls are <100 ms.
  • Exclusivity: the BLE mesh proxy accepts one client at a time. Close the amaran app before scenelight takes over; reopen amaran whenever you want — scenelight releases the connection on exit.
  • Available lights: run scenelight lights to see what's configured on this machine.
  • raw is the protocol escape hatch: opcode 0x26 with a 10-byte Telink vendor payload covers HSI/CCT/RGB/effects. Use this when the convenience commands don't expose what you need.
  • Stream mode default retries = 1: for one-shot commands the daemon defaults to 3 retries (reliability over speed); stream flips that trade.