Codex Micro Chroma is a local, audio-reactive lighting daemon for macOS, written in Rust. It extracts a representative colour from the artwork or thumbnail shown in macOS Now Playing and uses it to light the outer LED ring of the Work Louder Codex Micro.
It is not tied to Apple Music, Spotify, or any other service. Any music player, video player, or browser that publishes its current media and artwork through macOS Now Playing can use the same integration.
Lighting effects and brightness respond dynamically to the audio's musical dynamics, frequency balance, timbre, transients, rhythmic pulse, and stereo width. Everything is processed on your Mac: there is no OpenAI or Codex model usage, no Spotify or Apple Music API, no API key, no OAuth flow, and no external server.
macOS Now Playing (Music / Spotify / browser / other players)
-> macOS MediaRemote
-> Apple-signed /usr/bin/perl + mediaremote-adapter
-> media-remote Rust crate
-> local image decoding and representative-colour extraction
-> artwork colour
macOS system output
-> public Core Audio Process Tap
-> local Rust DSP (loudness / bands / centroid / flatness / flux / onset /
stereo width / pulse / tempo confidence)
-> LightingComposer (effect state machine / smoothing / hysteresis)
-> persistent hidapi session
-> Codex Micro v.oai.rgbcfg RPC
MediaRemote is a private Apple framework. Its behaviour may change after a macOS update, and this architecture is not suitable for App Store distribution. If a player does not publish artwork to Now Playing, Codex Micro Chroma cannot derive a colour from it.
- macOS 14.2 or later for reactive mode;
--mode staticdoes not require a Process Tap - A music player, video player, or browser that publishes artwork to macOS Now Playing
- A connected Work Louder Codex Micro
- Rust 1.88 or later
- Xcode Command Line Tools
- The standard macOS
/usr/bin/perl
The integration is service-agnostic, but artwork compatibility ultimately depends on each player publishing an image to macOS Now Playing. The browser/Helium path has been verified. Apple Music and Spotify artwork and colour output still require validation on the target Mac, as do long-running reconnect behaviour and final effect calibration on physical Codex Micro hardware.
Reactive analysis listens to the complete mixed macOS system output. If several applications play audio at once, the effects respond to that combined output while the base colour continues to come from the application selected by Now Playing.
Exactly one HID interface matching the Codex Micro is required. No matching device, more than one matching interface, or missing Input Monitoring access leaves run waiting for the controller and causes one-shot commands such as probe or set to report an error.
The current release is v0.1.0. Download the universal macOS archive and its SHA-256 checksum from GitHub Releases:
VERSION=0.1.0
BASE_URL="https://github.com/hauntedfail/Codex-Micro-Chroma/releases/download/v${VERSION}"
ARCHIVE="codex-micro-chroma-v${VERSION}-macos-universal.tar.gz"
curl -LO "${BASE_URL}/${ARCHIVE}"
curl -LO "${BASE_URL}/${ARCHIVE}.sha256"
shasum -a 256 -c "${ARCHIVE}.sha256"
tar -xzf "${ARCHIVE}"
cd "codex-micro-chroma-v${VERSION}-macos-universal"
./codex-micro-chroma --versionThe release binary supports both Apple Silicon and Intel Macs. It is ad-hoc signed but is not Developer ID signed or notarised, so macOS may ask you to confirm the first launch in System Settings > Privacy & Security.
To install the downloaded binary as a per-user LaunchAgent:
./codex-micro-chroma installBuild the release binary from the project root:
cargo build --releaseCheck the local MediaRemote and HID connections, inspect the current artwork colour, and verify system-audio analysis:
./target/release/codex-micro-chroma probe
./target/release/codex-micro-chroma status
./target/release/codex-micro-chroma audio-probe --seconds 15macOS privacy permissions cannot be granted by the installer or from the command line. You must approve them in System Settings. Permissions are associated with the executable that requests access, so a command run from Terminal and the installed background worker may need separate approval.
- Connect one Codex Micro to the Mac.
- Run
./target/release/codex-micro-chroma probe. - If HID access is reported as
not permitted, open System Settings > Privacy & Security > Input Monitoring, add and enable the terminal application you are using, then runprobeagain. - Start some media so that macOS Now Playing contains a current item and artwork, then run
status. - Run
audio-probe --seconds 15or startrunin reactive mode. When macOS asks, approve Screen & System Audio Recording, or System Audio Recording Only, depending on your macOS version.
The embedded NSAudioCaptureUsageDescription explains that system audio is analysed locally to animate the LED ring. Audio is converted into feature values in memory; it is never recorded, saved, or sent over the network.
run retries HID access every two seconds until the device and Input Monitoring permission become available. In reactive mode it also retries the Process Tap every two seconds until System Audio Recording permission is available, so you do not normally need to restart it after granting access. audio-probe, probe, status, set, and off are one-shot commands; correct the permission or device problem and run the command again.
Use --mode static if you do not want to grant system-audio access. Static mode still needs HID access and Now Playing artwork, but it does not start a Core Audio Process Tap.
Install and start the per-user LaunchAgent:
./target/release/codex-micro-chroma installThe command copies the release binary into Application Support, gives it an ad-hoc signature with the fixed identifier com.local.codex-micro-chroma, and registers an Aqua-session LaunchAgent. The installed worker is located at:
~/Library/Application Support/CodexMicroChroma/codex-micro-chroma
If the system-audio permission prompt appears immediately after installation, grant it. If you dismiss it, add and enable the worker shown above in System Settings > Privacy & Security > Screen & System Audio Recording, then run install again.
The LaunchAgent cannot approve its own privacy prompts. If the background worker is waiting, manually add and enable this installed executable for both permissions that are required on your Mac:
- Input Monitoring, for Codex Micro HID access
- Screen & System Audio Recording or System Audio Recording Only, for reactive audio analysis
After changing a permission, check ~/Library/Logs/CodexMicroChroma/worker-error.log. The worker normally resumes through its built-in retry loop. If macOS does not apply the change to the running worker, run install again to restart the LaunchAgent.
An ad-hoc signature's designated requirement includes the binary's CDHash. After rebuilding and reinstalling, macOS may therefore ask you to approve Input Monitoring or System Audio Recording again. If necessary, switch the installed worker's permission off and on. A distribution build signed with a Developer ID or local code-signing certificate can avoid this repeated approval.
Worker and track logs are stored in ~/Library/Logs/CodexMicroChroma/.
To stop the LaunchAgent and remove the installed copy:
~/Library/Application\ Support/CodexMicroChroma/codex-micro-chroma uninstalluninstall removes the LaunchAgent plist and installed executable, but preserves diagnostic logs.
Start the default reactive mode:
./target/release/codex-micro-chroma run- When the player or media changes, the new artwork is analysed automatically.
- A thumbnail fingerprint is used as the content identity when no title is available, and artwork changes are detected even when the title remains the same.
- White backgrounds and transparent pixels are excluded before the dominant colour is adjusted to be brighter and more vivid on the LEDs.
- The previous media colour is cleared while new artwork is pending.
- Relative loudness controls brightness, combined musical motion controls speed, and spatial width and change control the device's
magicparameter. - Brief onset, flux, pulse, and bass events are held with attack-and-release envelopes so that they can pass the 650 ms candidate dwell. Hysteresis preserves close-scoring candidates, allowing a beat to trigger a dynamic effect such as
snakeeven if it has disappeared by the next audio frame. - Effects have a two-second minimum hold to prevent flicker. If the same pattern remains the strongest candidate for more than 12 seconds, a semantically close runner-up may take over at a phrase boundary to avoid becoming stuck on a single effect such as
breath.rainbowhas a 12-second cooldown. - Speed and
magicuse effect-specific profiles:solidremains still,snakefollows the beat,gradientreflects stereo width,rainbowmarks a climax, and the two breathing effects use different depths. A brief rest does not switch the ring off. - A persistent HID connection is reused and updated every 100 ms by default. If the device or Input Monitoring permission is unavailable at start-up, the worker waits rather than exiting. It automatically reconnects once after a disconnection, response timeout, or other transport failure.
- If Process Tap frames stop for three seconds during playback, or remain completely zero-filled for 15 seconds, the tap and aggregate device are rebuilt with a 30-second recovery cooldown.
- Control-C or SIGTERM stops the process and switches the LEDs off.
The default values can be set explicitly:
./target/release/codex-micro-chroma run \
--mode reactive \
--brightness 1.0 \
--poll-ms 250 \
--device-ms 100To follow artwork while keeping one fixed effect:
./target/release/codex-micro-chroma run \
--mode static \
--effect breath \
--brightness 1.0 \
--speed 0.85 \
--magic 0.0 \
--refresh-ms 750Set a colour without reading Now Playing, then switch the lighting off. The default effect for both set and run is breath.
./target/release/codex-micro-chroma set --color '#33AAFF'
./target/release/codex-micro-chroma set --color '#33AAFF' --effect snake
./target/release/codex-micro-chroma offoff clears both the key lighting and ambient-ring lighting controlled by this tool.
audio-probe does not write to the LEDs. It prints AudioFeatureFrame values calculated from the Process Tap as JSON Lines, which is useful for permission checks and algorithm tuning.
./target/release/codex-micro-chroma audio-probe --seconds 15All currently known Codex Micro effects can be selected.
| CLI name | Device value | Role in reactive mode |
|---|---|---|
off |
0 | Sustained silence or stopped playback |
solid |
1 | Speech or direct, centre-panned sound |
snake |
2 | Strong bass, pulse, or rhythmic periodicity |
rainbow |
3 | A climax combining high level, strong flux, and pronounced onsets |
breath |
4 | Smooth, sustained, tonal material |
gradient |
5 | Wide stereo material |
shallow-breath |
6 | Quiet passages, introductions, and outros |
The shared --brightness, --speed, and --magic parameters each accept values from 0 to 1. Their visible behaviour and useful combinations depend on the device firmware's implementation of each effect.
run follows the Now Playing elapsed_time, duration, and playback_rate values and automatically writes one JSON Lines log per track:
~/Library/Logs/CodexMicroChroma/tracks/<timestamp>-<title>.jsonl
track_start: media metadata, source application, duration, and observed starting positioneffect_transition: position, effect, colour, brightness, speed,magic, and all audio features at that momenttrack_summary: time and percentage per effect, transition count, observed time, and completion reason
complete_track is true only when observation began within the first two seconds, ended within the final two seconds, and covered at least 85% of the media's duration. Accounting pauses with playback and resumes in the same log when the same media continues.
If a repeat or crossfade causes the position to jump backwards to within the first five seconds, the current pass is finalised with position_restarted and the next pass is written to a separate log. The previous pass still counts as complete if at least 85% of its duration was observed. Records are flushed on every transition, so a live log can be inspected with tail -f.
MediaRemote elapsed time is anchored to a local monotonic clock when each event arrives. This prevents time spent paused from being added to the media position if MediaRemote returns an old timestamp after a long pause.
- No OpenAI, Codex, Spotify, Apple Music, or other external API is used.
- No network connection is made at runtime.
- System Integrity Protection is not changed.
- Root access,
sudo, and code injection are not used. - Process Tap PCM is not written to a file.
- Playback is observed but never controlled.
- HID access opens exactly one interface matching the Codex Micro VID, PID, and usage page.
- An inter-process lock serialises concurrent LED writes.
- The installed worker uses a fixed identifier and an ad-hoc signature, not a Developer ID certificate.
CATapDescription is an Objective-C API, so only Process Tap and aggregate-device creation and destruction are isolated in a small Objective-C bridge. After the bridge delivers Float32 PCM, the FFT, feature extraction, relative normalisation, effect scoring, state transitions, and HID control are implemented in Rust.
The audio callback sends fixed-size packets to a bounded channel with try_send; FFT work and locking never run on Core Audio's real-time thread.
cargo fmt --all --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all-targets --all-featuresThe Release macOS binary GitHub Actions workflow builds an ad-hoc-signed universal binary, creates a checksum, and publishes both files in a new GitHub Release. The requested version must match the version in Cargo.toml.
To publish manually, open Actions > Release macOS binary > Run workflow and enter a version without the leading v, such as 0.1.0. Alternatively, push a matching tag such as v0.1.0.
An existing release or manually supplied existing tag is never overwritten. Update Cargo.toml and the version shown in the Download section before publishing the next version.
Codex Micro Chroma is available under the MIT Licence.