Skip to content

MegaManSec/wiz-light-controller

Repository files navigation

WiZ Light Controller app icon

WiZ Light Controller

Fast, local, cloud-free control for Philips WiZ smart bulbs. It talks to bulbs directly over your LAN (UDP) — no account, no cloud round-trip, no telemetry. At its heart is one small, dependency-free JavaScript engine (wiz-light-core) that is reused by two front-ends: a wiz CLI and a native macOS menu-bar app (Swift), which runs the engine's pure colour and light-state logic via JavaScriptCore — so both share a single, tested implementation.

Features

Mirrors the original app's capabilities, and adds more:

  • Discovery — find WiZ bulbs on your network (UDP broadcast), keyed by MAC.
  • Saved lights — remember bulbs by MAC with a friendly name; the IP is re-resolved on discovery, so it survives DHCP changes.
  • Colour — a colour wheel plus direct RGB / HSV / hex entry, with per-device colour memory and an optional "Brighter colours" white-LED blend.
  • White temperature — tunable white over the bulb's own negotiated range (e.g. 2200–6500 K).
  • Warm Glow — a one-knob cosy mode: set brightness and the temperature auto-follows the bulb's dim-to-warm curve (warmer as you dim), with one-tap glow levels.
  • Scenes — run a bulb's built-in dynamic scenes (Party, Ocean, Fireplace, …) with adjustable speed, on bulbs that support them.
  • Brightness — 0–100% (clamped to the firmware-valid floor; see below).
  • Presets — seeded RGB + white presets, with apply / match.
  • Sync from light — read a bulb's current state (getPilot) back into the UI, and reflect changes made elsewhere (e.g. the phone app).
  • Settings — auto-sync on launch; turn the light off when the Mac sleeps or shuts down — and optionally restore it on wake / startup; open at login; update checks. Persisted locally.

Screenshots

The native macOS app: a menu-bar dropdown for quick changes, and a full controls window with four modes — RGB, White, Warm Glow, and Scenes. Each shot is annotated — the numbered callouts are explained beneath it.

Menu-bar dropdown — click the bulb for instant control, no window needed:

Menu-bar dropdown (annotated)

Controls — colour (RGB) — colour wheel, RGB / HSV / hex entry, and the white-LED "Brighter colours" blend:

RGB colour controls (annotated)

Controls — white — tunable colour temperature with one-tap white presets:

White temperature and presets (annotated)

Controls — Warm Glow — one knob: brightness leads, and the temperature follows the dim-to-warm curve:

Warm Glow controls (annotated)

Controls — Scenes — a bulb's built-in dynamic scenes, with adjustable speed (on bulbs that support them):

Scenes grid (annotated)

Discover — scan the LAN, then save a new bulb or manage a saved one:

Discovery sheet (annotated)

Settings — device info, auto-sync, sleep / shutdown power behaviour, open-at-login, and updates:

Settings tab (annotated)

Install

macOS app

  1. Download WiZ-Light-Controller-macOS.zip from the latest release and unzip it.
  2. Move WiZ Light Controller.app to /Applications.
  3. The build may be unsigned, so macOS blocks it on first launch — right-click → Open, or launch it and choose Open Anyway under System Settings → Privacy & Security. (If macOS calls the app "damaged", clear the download quarantine: xattr -dr com.apple.quarantine "/Applications/WiZ Light Controller.app".)
  4. Approve Local Network access when prompted — it's required to reach the bulbs over your LAN. (You can grant it later under System Settings → Privacy & Security → Local Network.)

It lives in the menu bar with no Dock icon: click the bulb for the quick dropdown, or the controls button in its header for the full window.

CLI and engine (npm)

Published to npm; the CLI needs Node ≥ 24.

pnpm add -g wiz-light-cli      # install the `wiz` command globally
wiz discover                   # find bulbs on your LAN — then `wiz --help`

Or use the engine as a library in your own project:

pnpm add wiz-light-core

(Both also install with npm: npm i -g wiz-light-cli / npm i wiz-light-core.)

Monorepo layout

A pnpm workspace:

packages/core   wiz-light-core   Pure engine: WiZ UDP protocol, broadcast discovery, colour maths, light-state model, persisted stores. Zero runtime dependencies.
packages/cli    wiz-light-cli    Dependency-free `wiz` CLI on top of wiz-light-core.
apps/macos                       Native macOS menu-bar app (SwiftPM). Runs wiz-light-core's pure logic in JavaScriptCore; UDP/persistence/UI in Swift.
legacy/                          Original GPL-3.0 Python app (wiz.py), preserved as-is.
scripts/                         Repo tooling (build-jscore.mjs, release-notes.mjs).

Build from source

For hacking on the project — the prebuilt app and published packages are under Install above. Requires Node 24 and pnpm 10 (via Corepack — corepack enable).

pnpm install              # integrity-checked: pnpm install --frozen-lockfile

Engine

pnpm test:core            # run the engine's node:test suite

CLI

pnpm --filter wiz-light-cli start -- discover     # find bulbs on your LAN
pnpm --filter wiz-light-cli start -- --help       # all commands

(To install the published wiz command, see Install. From a checkout, link it instead: pnpm --filter wiz-light-cli exec npm link.)

macOS app

Needs Xcode (Swift toolchain) on macOS 13+. The JavaScriptCore bundle is generated from wiz-light-core, so build it first:

pnpm build:jscore             # generate the JSCore bundle from wiz-light-core
make -C apps/macos app        # assemble + ad-hoc-sign "WiZ Light Controller.app"
make -C apps/macos run        # build (if needed) and launch it

For a signed, distributable build, set CODESIGN_IDENTITY to your Developer ID Application identity (see apps/macos).

Security

Local-only by design, with a deliberately small surface:

  • Zero-dependency engine. wiz-light-core and wiz-light-cli use Node built-ins only — nothing third-party at runtime.
  • Supply chain. CI installs with a frozen lockfile; pnpm 10 blocks dependency lifecycle (postinstall) scripts except an explicit pnpm.onlyBuiltDependencies allowlist.
  • Native app. Runs under the App Sandbox with only the two LAN networking entitlements it needs (network.client / network.server) and a clear Local-Network usage description. There is no bundled browser or Node — JavaScriptCore is a hardened Apple system framework. CI builds ad-hoc signed by default; tagged releases are Developer ID signed and notarized when the signing secrets are present.

See apps/macos for the app's full security, signing, and notarization model.

Requirements

  • Node 24 and pnpm 10 (pinned; use Corepack).
  • macOS app: Xcode 15+ on macOS 13+ (Apple frameworks only — no third-party Swift dependencies).
  • Your machine on the same LAN as the bulbs.

Packages

  • packages/corewiz-light-core, the engine (protocol, discovery, colour, model, stores).
  • packages/cliwiz-light-cli, the wiz command-line interface.
  • apps/macos — the native macOS menu-bar app.

License

GPL-3.0-or-later. Originally a Python app by Eshaan Pisal (GPL-3.0), preserved under legacy/.

About

Local, cloud-free control for Philips WiZ smart lights — a native macOS menu-bar app and a CLI, sharing one zero-dependency engine.

Topics

Resources

License

Stars

Watchers

Forks

Contributors