polyclav
A self-contained live piano host for Linux and macOS. Plug in a MIDI
keyboard and an audio interface, run polyclav, pick your keyboard, and you
have a digital piano: keys make piano sound, effects are in the chain, and
(optionally) a Novation Launchkey's knobs, pads, and screen drive the front
panel. No DAW, no recording — just playing. Devices can come and go;
polyclav reconnects automatically and idles at near-zero CPU when nothing
is plugged in.
Picking your keyboard is a one-time step:
[midi].allow_devicesis an allowlist, so nothing sends notes until you name it. Startup prints your connected port names and the exact line to add — or tick a box in the web UI. Seedocs/USER_GUIDE.md.
Status: Linux (PipeWire) is the primary platform — developed and hardware-tested against a Novation Launchkey 61 MK4 + Behringer XR18 over OSC. macOS (Apple Silicon) is supported: releases ship a macOS wheel and a Homebrew formula, though plugin hosting (LV2, CLAP) is Linux-only in this build. Should work with any class-compliant MIDI keyboard and any supported audio interface; Launchkey-specific bits gracefully degrade if the device isn't present.
polyclav is implemented in Go with a thin Rust audio-core for the
real-time audio thread (PipeWire, oxisynth, sfizz). A polyclav-components
CLI is also included for encoding/uploading Launchkey MK4 Custom modes
over SysEx.
What works today
- Live audio out via PipeWire. Any default sink works; an XR18 with
a low-latency WirePlumber rule (see
docs/INSTALL.md) gets ~8 ms round-trip at a 128-frame quantum. - Live MIDI in over ALSA-seq (rtmidi). Notes, CCs, mod wheel, and pitch bend forwarded to the synth end-to-end.
- Four synth backends, picked per patch:
.sf2/.sf3→ oxisynth (pure Rust).sfz→ sfizz (C++ via thin Rust FFI)type = "native"→ built-in pure-Rust analog-style synthtype = "lv2"/type = "clap"→ plugin hosting
- Patches — named presets defined in
[[patches]]in the config. Top-row Launchkey pads select patches live (8 visible). - Per-patch gain matching via
gain_dbso switching a soft EP for a loud grand doesn't blow your ears off. - Soundfont hot-swap — switch patches without dropping audio.
- DSP chain in the audio thread, in order:
synth → drive_pedal → chorus → tremolo → analog_delay → patch_gain → input_comp → reverb → mastering_comp → limiter → master_volume → out. Knobs 1/2/3/4 drive master volume, reverb, the input compressor, and a Tube-Screamer-style drive pedal live — all four work on every patch type, soundfont or native. The chorus, tremolo, and analog-delay pedals are implemented and wired into the chain (default off, bit-exact bypass) but not yet reachable from a Launchkey knob, REST field, or per-patch persistence — seedocs/VISION.md§1b–1d. See alsodocs/OPEN_SOUND_ENGINES.md. - Launchkey knob pages — five pages (MAIN / OSC / FILTER / AMP /
LFO/MOD) on Scene ▲/▼ put the whole native-synth voice on the 8
encoders, with page indicators on the bottom pad row. Code-complete,
pending hardware verification (
docs/HARDWARE_TESTS.md). - Web dashboard — an embedded, localhost-only web UI (
[web]in the config, on by default,127.0.0.1:8666): a Next.js app (static export embedded in the binary —go buildneeds no Node) with patch switching, all live params, mastering, the full native-synth panel, a velocity-curve editor with a live note monitor, validated in-browser config editing, a generic MIDI device probe/reverse-engineering tool, and the audition transport, plus a REST + SSE API. The pre-Next single-file page remains at/legacy. Seedocs/WEB_UI.mdanddocs/MIDI_PROBE.md(the device probe). - Velocity curves — global
[midi.velocity]curve (soft / linear / hard / custom gamma, or 2–16 control points, + output clamp) with per-patch overrides, so every patch responds to your keybed the way you want — editable live from the browser. Seedocs/VELOCITY_CURVES.md. - Audition mode —
polyclav --play <clip> [--loop] [--tempo N]plays one of seven built-in diagnostic clips through the full audio path, no keyboard needed; the web dashboard has the same transport. Seedocs/AUDITION.md. - Native synth — a full Minimoog-style voice: 3 oscillators
(saw/square/pulse, octave, detune, level) + noise + pre-filter drive,
resonant ladder filter with its own ADSR and keyboard tracking, a
runtime amp ADSR, velocity→amp/cutoff routing, a global LFO
(pitch/cutoff/amp), mod-wheel vibrato, pitch bend, glide, optional 2×
oversampling, and up to 8-voice polyphony with live-switchable
voice modes. Every tweak persists per patch in
state.toml. Seedocs/NATIVE_SYNTH.md. - Optional mixer OSC bindings — faders and pads can drive mixer faders
and mute toggles over UDP once explicitly configured. Bindings live in
[osc.mixer](preferred name;[osc.xr18]still works), with a configurable presence-checkheartbeatfor non-X-Air OSC targets. - Launchkey MK4 DAW driver — handshake, knob/pad/screen control,
per-patch knob-value persistence. The
polyclav-componentsCLI also encodes and uploads Custom modes over SysEx.
For the developer-facing rundown of every component, see AGENTS.md.
Install
polyclav ships as prebuilt binaries: a wheel on PyPI (Linux x86_64 + macOS arm64) and a Homebrew formula (Linux x86_64 + macOS arm64). On Linux the binary is dynamically linked against your system's audio libraries — install those from your distro first. On macOS the binary links nothing beyond the system frameworks, so no prerequisites are needed.
1. System libraries (Linux only)
PipeWire, ALSA, and the LV2 host library (lilv):
# Debian / Ubuntu
sudo apt install pipewire libasound2 liblilv-0-0
# Fedora
sudo dnf install pipewire alsa-lib lilv
# Arch
sudo pacman -S pipewire alsa-lib lilv
Optional — sfizz, for .sfz sample libraries (Salamander Grand, etc.). It's
a runtime-loaded optional backend: without it, .sfz patches are silent but
SF2/SF3 soundfonts, the native synth, and LV2/CLAP plugins all work. sfizz isn't
always in a distro's default repos — check your package manager (e.g. the AUR on
Arch) or build it from source. Run polyclav doctor to see what's available.
2. polyclav
uvx polyclav # run without installing (Linux + macOS)
pipx install polyclav # or install it persistently
Both fetch a prebuilt wheel from PyPI; the polyclav-components Launchkey
SysEx CLI ships in the same wheel. Or, with Homebrew (Linux x86_64,
macOS Apple Silicon):
brew install mschulkind-oss/tap/polyclav
On Linux, Homebrew does not provide the §1 system libraries — you still install those from your distro, and the binary needs glibc ≥ 2.39 (Debian 12 / Ubuntu 22.04 are too old; build from source there).
There is no go install path: the binary links a Rust staticlib that
cargo builds next to the Go code, and the Go module proxy can't provide
it — build from source instead.
3. First run
polyclav doctor # report backends + analyse your config
polyclav bootstrap # download free starter soundfonts (~500 MB; prompts for licenses)
polyclav # start playing
Build from source
mise install # Go + Rust toolchains
just build # Rust audio-core + Go binary
just install # or: install both binaries to ~/.local/bin
mkdir -p ~/.config/polyclav
cp polyclav.example.toml ~/.config/polyclav/config.toml
$EDITOR ~/.config/polyclav/config.toml # edit soundfont paths
overmind start -D # run as daemon via Procfile
polyclav ships no soundfonts (license + size). The example config points
at ~/.local/share/polyclav/soundfonts/... — drop your files there or edit
the paths. docs/INSTALL.md lists free starter soundfonts and where to
get them.
If you don't have a Launchkey, the daemon still runs: the audio path and any MIDI keyboard work; the Launchkey-specific code paths just stay idle.
Documentation
| Path | What it covers |
|---|---|
docs/INSTALL.md |
System-level install: build deps, soundfonts, hardware notes. Start here on a fresh machine. |
docs/USER_GUIDE.md |
End-user install / configure / play, including the full config schema. |
docs/HARDWARE_TESTS.md |
Hardware verification checklist (Launchkey MK4 + XR18). |
docs/ROADMAP.md |
Native-synth design record (Phases 2-4, now implemented) + open questions. |
AGENTS.md |
For AI agents and developers working on the code. Build/test workflow, current state, DSP API. |
License
polyclav itself is licensed under the Apache License, Version 2.0 —
see LICENSE.
Transitively used libraries carry their own licenses:
oxisynth— LGPL-2.1sfizz— BSD-2-Clausepipewire-rs— MIT or Apache-2.0rtmidi(via cgo) — MIT-like (see upstream)
If you distribute polyclav (or a derivative), bundle the appropriate notices. Apache 2.0 + LGPL-2.1 (oxisynth) means: dynamic linking is fine, you must permit relinking against modified oxisynth, and you must preserve oxisynth's copyright notices.
Contributing
Patches welcome. The workflow, code layout, and current milestones are
documented in AGENTS.md. Run just check before sending
anything — it gates on cargo build --release, cargo clippy -D warnings,
go vet, cargo test, go test, and go build ./....
Bug reports: please include polyclav --version, the contents of your
config.toml (redact paths if you like), and the relevant slice of
/tmp/polyclav.log (overmind tees there by default).
Metadata
Release files for polyclav 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| polyclav-0.2.0-py3-none-manylinux_2_39_x86_64.whl | Python 3 | none | Linux glibc 2.39+ x86-64 | Details |
| polyclav-0.2.0-py3-none-macosx_11_0_arm64.whl | Python 3 | none | macOS 11.0+ ARM64 | Details |
Total release size: 11.6 MB
Release files / polyclav-0.2.0-py3-none-manylinux_2_39_x86_64.whl
| Download URL | polyclav-0.2.0-py3-none-manylinux_2_39_x86_64.whl |
|---|---|
| Size | 6.1 MB |
| Tags | Linux glibc 2.39+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
a081d259b5c3363a079b5db0a8676a1ba97a3aa36dac3fa3267280673b03b222
|
|
BLAKE2b-256 checksum How to use checksums |
fdc5d0caa50d7102228599b0d4edde53bde052f5eef526bd6827de6254586915
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency logRelease files / polyclav-0.2.0-py3-none-macosx_11_0_arm64.whl
| Download URL | polyclav-0.2.0-py3-none-macosx_11_0_arm64.whl |
|---|---|
| Size | 5.4 MB |
| Tags | Python 3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
5c55473e7b48c8e0e76b4512aff65b5245ae22627886a6945fa4037c6a8d3f34
|
|
BLAKE2b-256 checksum How to use checksums |
5edcf3102ee95f656c26d3ad9f78c4a0e6b223e6c1051323c9c5811d5bcae95e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency log