Roon Controller

v1.0.3

Control Roon music player through Roon API with automatic Core discovery and zone filtering. Supports play/pause, next/previous track, and current track query. Automatically finds Muspi zones. Supports Chinese commands.

3· 2.2k·4 current·4 all-time
Security Scan
VirusTotalVirusTotal
Benign
View report →
OpenClawOpenClaw
Benign
high confidence
Purpose & Capability
Name and description (Roon control, zone filtering, basic playback) align with the included code and SKILL.md. The package depends only on the roonapi library and operates against a Roon Core on the local network. No unrelated services, binaries, or credentials are requested.
Instruction Scope
SKILL.md instructs installing roonapi and using the provided API/CLI to discover the local Roon Core, control playback, and persist settings. All instructions are scoped to Roon Core discovery, zone selection, token storage, and playback control. The instructions do reference creating/saving a local config file (~/clawd/roon_config.json), which is necessary for persistent Roon authorization.
Install Mechanism
No packaged install spec is included; SKILL.md recommends pip install roonapi and a requirements.txt is present. This is low-risk: the only dependency is a public Python package (roonapi). There are no downloads from arbitrary URLs or extract steps.
Credentials
The skill requests no environment variables or external credentials (good). It does persist an authorization token and selected zone to ~/clawd/roon_config.json; this is proportionate to the purpose (the token is how the extension authenticates to the Roon Core) but means the token is stored on disk and could be used to control the user's Roon system if the file is accessed by others.
Persistence & Privilege
The skill writes a persistent config directory in the user's home (~/.clawd) and auto-saves the Roon token and selected zone, so it retains the ability to reconnect without reauthorization. always is false and the skill does not modify other skills or system-wide settings. Persistent token storage is expected for this use case but increases the importance of securing the config file.
Assessment
This skill appears to do what it says: discover a local Roon Core and control playback. Before installing, consider: (1) The skill will create ~/clawd/roon_config.json and save the Roon authorization token there in plaintext — anyone with access to that file can control your Roon Core, so set restrictive file permissions or run under a dedicated account. (2) The skill operates on your local network only (it uses roonapi); it does not request cloud API keys or contact third-party endpoints according to the provided files. (3) The code includes a small bug (a truncated return name seen in the provided snippet) — running the tool in a controlled environment first is wise. (4) If you want stronger isolation, run the skill in a VM or dedicated user account. If you need any part of the code reviewed in full (the file was truncated in the listing), provide the complete source and I can re-check for problematic patterns.

Like a lobster shell, security has layers — review code before you run it.

latestvk971kat17zhjk16kcpjy6ct22h804nsmmusicvk971kat17zhjk16kcpjy6ct22h804nsmroonvk971kat17zhjk16kcpjy6ct22h804nsm
2.2kdownloads
3stars
4versions
Updated 1mo ago
v1.0.3
MIT-0

Roon Control Skill

Control the Roon music player with Chinese command support.

Quick Start

Install Dependencies

pip install roonapi

Usage Examples

from roon_controller import RoonController

# Create controller (token will be saved automatically)
controller = RoonController(verbose=True)

# Play/Pause
result = controller.play_pause()

# Next track
result = controller.next()

# Get current track
track_info = controller.get_current_track()
print(f"Now playing: {track_info['track']}")

Core Features

1. Automatic Discovery and Connection

  • Automatic Roon Core discovery
  • Token automatically saved to ~/clawd/roon_config.json
  • Auto-reconnect after restart, no re-authorization needed

2. Zone Selection and Switching

  • Supports switching between any available zone
  • Selected zone is saved in config and persists across restarts
  • If no zone is selected, defaults to zones ending with "[roon]"
  • Use set_zone() to switch zones programmatically

Switch Zone

result = controller.set_zone("Living Room")
# {"success": True, "message": "Switched to zone: Living Room", "zone": "Living Room"}

Get Current Zone

zone = controller.get_current_zone()
# Returns zone info dict with zone_id and zone_data

3. Playback Control

Play

result = controller.play()
# {"success": True, "message": "Playback started", "zone": "Living Room Muspi"}

Pause

result = controller.pause()
# {"success": True, "message": "Paused", "zone": "Living Room Muspi"}

Play/Pause Toggle

result = controller.play_pause()

Previous Track

result = controller.previous()

Next Track

result = controller.next()

4. Get Current Track

track_info = controller.get_current_track()
# Returns:
# {
#   "success": True,
#   "is_playing": True,
#   "zone": "Living Room Muspi",
#   "track": "Bohemian Rhapsody",
#   "artist": "Queen",
#   "album": "A Night at the Opera",
#   "seek_position": 12345,  # milliseconds
#   "length": 354000        # milliseconds
# }

5. List All Zones

zones = controller.list_zones()
# ["Living Room Muspi", "Kitchen", "Bedroom"]

Command Line Tool

The script can be used as a command line tool:

# Play
python roon_controller.py play

# Pause
python roon_controller.py pause

# Previous track
python roon_controller.py prev

# Next track
python roon_controller.py next

# View current track
python roon_controller.py status

# List all zones
python roon_controller.py zones -v

# switch zone
python roon_controller.py switch zonename

Chinese Command Support

The skill supports the following Chinese trigger words:

CommandMeaningExample
音乐播放 / 播放音乐Start playback"音乐播放"
暂停 / 暂停播放Pause playback"暂停一下"
下一曲 / 切歌Next track"下一曲"
上一曲Previous track"上一曲"
当前曲目 / 正在放什么View current track"当前曲目"

Error Handling

All methods return a unified dictionary structure:

{
    "success": True/False,
    "message": "Operation result description",
    "zone": "Zone name (optional)"
}

Common Errors

  • Muspi zone not found: Check if the Roon zone name ends with "muspi"
  • Failed to connect to Roon: Ensure Roon Core is running and network-accessible
  • Token load failed: First run requires authorization, ensure authorization completes successfully

Notes

  1. First Run: Extension authorization required in Roon, check for the extension authorization prompt in Roon interface
  2. Zone Naming: Muspi zone names must end with "muspi" (case-insensitive)
  3. Token Storage: Token is saved in ~/clawd/roon_config.json, ensure secure file permissions
  4. Network Requirements: The device running the script must be on the same network as Roon Core

Technical Details

Dependencies

  • roonapi>=0.1.6: Official Roon API Python library

Token Management

  • Token storage path: ~/clawd/roon_config.json
  • Auto-load: Automatically loaded on each startup
  • Auto-save: Automatically saved on first authorization or update

Zone Finding Algorithm

# Find all zones
zones = roon.zones

# Filter zones with muspi suffix
muspi_zones = [
    (zone_id, zone_data)
    for zone_id, zone_data in zones.items()
    if zone_data['display_name'].lower().endswith('muspi')
]

# Use the first matching zone
zone_id, zone_data = muspi_zones[0]

Comments

Loading comments...