Virtual MIDI ports, hardware, RTP-MIDI and Bluetooth MIDI for macOS, Linux and Windows.
Find a file
2026-09-28 13:59:10 -05:00
.cargo First commit 2026-09-28 13:59:10 -05:00
.claude/skills First commit 2026-09-28 13:59:10 -05:00
.specify First commit 2026-09-28 13:59:10 -05:00
crates First commit 2026-09-28 13:59:10 -05:00
docs First commit 2026-09-28 13:59:10 -05:00
fuzz First commit 2026-09-28 13:59:10 -05:00
packaging First commit 2026-09-28 13:59:10 -05:00
proto/midiharbor/v1 First commit 2026-09-28 13:59:10 -05:00
scripts First commit 2026-09-28 13:59:10 -05:00
specs First commit 2026-09-28 13:59:10 -05:00
src First commit 2026-09-28 13:59:10 -05:00
tests First commit 2026-09-28 13:59:10 -05:00
.gitignore First commit 2026-09-28 13:59:10 -05:00
.goreleaser.yaml First commit 2026-09-28 13:59:10 -05:00
AGENTS.md First commit 2026-09-28 13:59:10 -05:00
build.rs First commit 2026-09-28 13:59:10 -05:00
Cargo.lock First commit 2026-09-28 13:59:10 -05:00
Cargo.toml First commit 2026-09-28 13:59:10 -05:00
clippy.toml First commit 2026-09-28 13:59:10 -05:00
Icon.svg First commit 2026-09-28 13:59:10 -05:00
LICENSE.txt First commit 2026-09-28 13:59:10 -05:00
Makefile First commit 2026-09-28 13:59:10 -05:00
README.md First commit 2026-09-28 13:59:10 -05:00
rust-toolchain.toml First commit 2026-09-28 13:59:10 -05:00
rustfmt.toml First commit 2026-09-28 13:59:10 -05:00
VERSION First commit 2026-09-28 13:59:10 -05:00

midi-harbor

Midi Harbor manages MIDI connections on macOS, Linux and Windows: virtual ports other applications can use, attached MIDI hardware, RTP-MIDI network sessions to other computers, and Bluetooth LE MIDI devices. A daemon owns every connection and repairs it on its own. A network session that drops is reconnected, hardware that is unplugged and plugged back in picks up where it left off, and notes sounding when a link went away are released rather than left ringing.

The command line and the graphical interface are both clients of the daemon, so closing either changes nothing.

Install

Download a package or archive from the releases, or build this project. midi-harbor-headless leaves out the graphical interface, for machines without a display.

sudo apt install ./midi-harbor_<version>_<arch>.deb    # Debian and Ubuntu
sudo dnf install ./midi-harbor-<version>-1.<arch>.rpm    # Fedora and RHEL

The release builds need glibc 2.35 or newer, so RHEL 9 and its rebuilds must build from source.

The Windows executable is not signed, so it warns the first time it runs; Installation says how to let it run.

On Windows, virtual ports need Windows MIDI Services. Windows 11 includes it from its late-2026 update; before that, install Microsoft's Windows MIDI Services SDK Runtime and Tools.

Building

Building needs Rust 1.96 or newer. On Linux it also needs the ALSA, D-Bus and Avahi development files and libclang, and for the graphical interface the xkbcommon and Wayland development files.

On Debian and Ubuntu:

sudo apt install build-essential pkg-config libasound2-dev libdbus-1-dev \
                 libavahi-client-dev libclang-dev
sudo apt install libxkbcommon-dev libwayland-dev    # for the graphical interface

On Fedora and RHEL (enable CodeReady Builder first on RHEL and its rebuilds):

sudo dnf install gcc pkgconf-pkg-config alsa-lib-devel dbus-devel avahi-devel clang-devel
sudo dnf install libxkbcommon-devel wayland-devel    # for the graphical interface

Then:

cargo build --release                        # with the graphical interface
cargo build --release --no-default-features  # without it

Windows builds are cross-compiled with mingw-w64:

rustup target add x86_64-pc-windows-gnu
cargo build --release --target x86_64-pc-windows-gnu

Release packages for every platform are built with GoReleaser in Docker, through make snapshot and make release.

Running as a service

The daemon registers itself with launchd, a systemd user unit, or Task Scheduler, and runs at every login:

midi-harbor service install --start
midi-harbor service status

Running from the command line

To try things out, or to see more of what the daemon is doing, run it in the foreground:

midi-harbor daemon -vv

Config

The setup lives in one YAML file per user, which the daemon writes as things change. midi-harbor config path prints where it is. It can be written by hand; only names and kinds are required:

endpoints:
  - name: Sequencer Bus
    kind: virtual_port
  - name: Studio
    kind: network_port
routes:
  - from: Sequencer Bus
    to: Studio

Run midi-harbor config reload after editing it while the daemon runs.

Usage

Every command has help:

midi-harbor --help

Run with no command, midi-harbor opens the graphical interface.

A basic setup that sends a local virtual port to another computer:

midi-harbor port create "Sequencer Bus"
midi-harbor network create "Studio"
midi-harbor network discover
midi-harbor network connect "Studio" "Stage Mac"
midi-harbor route create "Sequencer Bus" "Studio"

MIDI played into "Sequencer Bus" now reaches "Stage Mac", and keeps reaching it across sleep, network changes, and either machine restarting.

Testing

make test                # unit tests
make test-integration    # the daemon, CLI and protocols over real files and sockets
make test-live           # tests needing real MIDI, a Bluetooth radio or a session peer