roon-rs
Rust SDK and tools for Roon's proprietary protocols (SOOD discovery + MOO RPC).
roon-api— Standalone SDK. Any Rust program can add it as a dependency to discover, connect to, and control a Roon Core.roon-cli— Command-line tool (roon) for controlling Roon from a terminal.roon-mcp— MCP server exposing Roon as tools for AI assistants (Claude Code, etc.).roon-hub— MQTT bridge binary (not published to crates.io).
Install the CLI
From crates.io
From GitHub Releases (pre-built binaries)
# roon-cli (the `roon` command)
|
# roon-mcp (MCP server)
|
# Windows (PowerShell)
Supported targets: x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu, x86_64-apple-darwin, aarch64-apple-darwin, x86_64-pc-windows-msvc.
Install the MCP server
# or grab a pre-built binary from GitHub Releases (see above).
Run roon-mcp --transport stdio (default) or --transport sse --http-port 8080 for SSE/HTTP. See crates/roon-mcp/ for details.
Quick Start
# 1. Discover Roon Cores on your network and set the default server.
# Approve "roon-rs CLI" in Roon Settings > Extensions when prompted.
# 2. Pick a default zone.
# 3. (Optional) Pick a default output. Used by volume/mute when --output is omitted.
# If skipped, volume/mute fall back to the default zone's output when the zone has only one.
# 4. Play.
# 5. Inspect.
Full command list: roon --help.
Machine-readable integration (watch / browse / search / play-item)
These four commands emit JSON and are designed to be driven by another program (for example, a Neovim plugin or a TUI). The non-trivial idea is that browse/search state lives on the Roon Core and is keyed by a --session string you choose. Pass the same session key to successive calls to navigate a cursor; use different keys for independent cursors (telescope-style incremental search vs. neo-tree-style expand, for example).
roon watch — streaming zone/output changes
Emits one JSON object per line (NDJSON). Default output:
Schema ("schema": 1):
event |
fields (besides schema + ts) |
meaning |
|---|---|---|
initial |
zones: [Zone], outputs: [Output] |
one-shot on start |
zone_added |
zone: Zone |
|
zone_changed |
zone: Zone |
|
zone_removed |
zone_id: String |
|
zone_seeked |
zone_id, seek_position, queue_time_remaining |
throttled per --seek-hz |
output_added |
output: Output |
|
output_changed |
output: Output |
|
output_removed |
output_id: String |
Ctrl-C and a broken pipe both exit 0. A stdout write error (other than broken pipe) exits 2.
roon browse — one-shot browse+load pair
Each invocation does browse followed by load against the given session and prints the loaded list:
Roon requires a hierarchy on every browse/load call. The first call that establishes a hierarchy caches it in ~/.config/roon-rs/sessions/<session>.toml, so later drills on the same session do not need --hierarchy.
roon search — thin wrapper
Uses the search hierarchy with pop_all=true so each call returns fresh results. Output schema is identical to browse. The Roon search hierarchy returns header items (hint: "header") mixed with result items; filter them client-side if you want a flat list.
roon play-item — play / queue / start-radio
<key> is an item_key from a preceding browse/search call in the same session — typically an action_list-hint item such as "Play Album". play-item drills into it to get the action list, then invokes Play Now / Queue / Start Radio per --action (default auto prefers Play Now). The Roon Core needs a zone target, so pass --zone / --zone-id or rely on the default roon zone. Output on success:
On no matching action, exit code 3 and:
Session semantics
- Pick your own session keys. One cursor per key; use different keys when you want independent cursors.
- Item keys are only valid within the session that produced them. Pass the same
--sessionto the follow-upbrowse/play-itemcall. - The session's hierarchy is cached on disk; delete
~/.config/roon-rs/sessions/<key>.tomlto reset.
Use the SDK
[]
= "0.1"
= { = "1", = ["full"] }
use ;
async
Build from source
Protocol Documentation
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT License (LICENSE-MIT)
at your option.
Disclaimer
This project is not affiliated with or endorsed by Roon Labs. "Roon" is a trademark of Roon Labs LLC.