{
  "schemaVersion": "1.0",
  "item": {
    "slug": "roon-controller",
    "name": "Roon Controller",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/puterjam/roon-controller",
    "canonicalUrl": "https://clawhub.ai/puterjam/roon-controller",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/roon-controller",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=roon-controller",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "requirements.txt",
      "SKILL.md",
      "roon_controller.py"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "slug": "roon-controller",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-05-08T06:28:00.483Z",
      "expiresAt": "2026-05-15T06:28:00.483Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=roon-controller",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=roon-controller",
        "contentDisposition": "attachment; filename=\"roon-controller-1.0.3.zip\"",
        "redirectLocation": null,
        "bodySnippet": null,
        "slug": "roon-controller"
      },
      "scope": "item",
      "summary": "Item download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this item.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/roon-controller"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/roon-controller",
    "agentPageUrl": "https://openagent3.xyz/skills/roon-controller/agent",
    "manifestUrl": "https://openagent3.xyz/skills/roon-controller/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/roon-controller/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Roon Control Skill",
        "body": "Control the Roon music player with Chinese command support."
      },
      {
        "title": "Install Dependencies",
        "body": "pip install roonapi"
      },
      {
        "title": "Usage Examples",
        "body": "from roon_controller import RoonController\n\n# Create controller (token will be saved automatically)\ncontroller = RoonController(verbose=True)\n\n# Play/Pause\nresult = controller.play_pause()\n\n# Next track\nresult = controller.next()\n\n# Get current track\ntrack_info = controller.get_current_track()\nprint(f\"Now playing: {track_info['track']}\")"
      },
      {
        "title": "1. Automatic Discovery and Connection",
        "body": "Automatic Roon Core discovery\nToken automatically saved to ~/clawd/roon_config.json\nAuto-reconnect after restart, no re-authorization needed"
      },
      {
        "title": "2. Zone Selection and Switching",
        "body": "Supports switching between any available zone\nSelected zone is saved in config and persists across restarts\nIf no zone is selected, defaults to zones ending with \"[roon]\"\nUse set_zone() to switch zones programmatically\n\nSwitch Zone\n\nresult = controller.set_zone(\"Living Room\")\n# {\"success\": True, \"message\": \"Switched to zone: Living Room\", \"zone\": \"Living Room\"}\n\nGet Current Zone\n\nzone = controller.get_current_zone()\n# Returns zone info dict with zone_id and zone_data"
      },
      {
        "title": "3. Playback Control",
        "body": "Play\n\nresult = controller.play()\n# {\"success\": True, \"message\": \"Playback started\", \"zone\": \"Living Room Muspi\"}\n\nPause\n\nresult = controller.pause()\n# {\"success\": True, \"message\": \"Paused\", \"zone\": \"Living Room Muspi\"}\n\nPlay/Pause Toggle\n\nresult = controller.play_pause()\n\nPrevious Track\n\nresult = controller.previous()\n\nNext Track\n\nresult = controller.next()"
      },
      {
        "title": "4. Get Current Track",
        "body": "track_info = controller.get_current_track()\n# Returns:\n# {\n#   \"success\": True,\n#   \"is_playing\": True,\n#   \"zone\": \"Living Room Muspi\",\n#   \"track\": \"Bohemian Rhapsody\",\n#   \"artist\": \"Queen\",\n#   \"album\": \"A Night at the Opera\",\n#   \"seek_position\": 12345,  # milliseconds\n#   \"length\": 354000        # milliseconds\n# }"
      },
      {
        "title": "5. List All Zones",
        "body": "zones = controller.list_zones()\n# [\"Living Room Muspi\", \"Kitchen\", \"Bedroom\"]"
      },
      {
        "title": "Command Line Tool",
        "body": "The script can be used as a command line tool:\n\n# Play\npython roon_controller.py play\n\n# Pause\npython roon_controller.py pause\n\n# Previous track\npython roon_controller.py prev\n\n# Next track\npython roon_controller.py next\n\n# View current track\npython roon_controller.py status\n\n# List all zones\npython roon_controller.py zones -v\n\n# switch zone\npython roon_controller.py switch zonename"
      },
      {
        "title": "Chinese Command Support",
        "body": "The skill supports the following Chinese trigger words:\n\nCommandMeaningExample音乐播放 / 播放音乐Start playback\"音乐播放\"暂停 / 暂停播放Pause playback\"暂停一下\"下一曲 / 切歌Next track\"下一曲\"上一曲Previous track\"上一曲\"当前曲目 / 正在放什么View current track\"当前曲目\""
      },
      {
        "title": "Error Handling",
        "body": "All methods return a unified dictionary structure:\n\n{\n    \"success\": True/False,\n    \"message\": \"Operation result description\",\n    \"zone\": \"Zone name (optional)\"\n}"
      },
      {
        "title": "Common Errors",
        "body": "Muspi zone not found: Check if the Roon zone name ends with \"muspi\"\nFailed to connect to Roon: Ensure Roon Core is running and network-accessible\nToken load failed: First run requires authorization, ensure authorization completes successfully"
      },
      {
        "title": "Notes",
        "body": "First Run: Extension authorization required in Roon, check for the extension authorization prompt in Roon interface\nZone Naming: Muspi zone names must end with \"muspi\" (case-insensitive)\nToken Storage: Token is saved in ~/clawd/roon_config.json, ensure secure file permissions\nNetwork Requirements: The device running the script must be on the same network as Roon Core"
      },
      {
        "title": "Dependencies",
        "body": "roonapi>=0.1.6: Official Roon API Python library"
      },
      {
        "title": "Token Management",
        "body": "Token storage path: ~/clawd/roon_config.json\nAuto-load: Automatically loaded on each startup\nAuto-save: Automatically saved on first authorization or update"
      },
      {
        "title": "Zone Finding Algorithm",
        "body": "# Find all zones\nzones = roon.zones\n\n# Filter zones with muspi suffix\nmuspi_zones = [\n    (zone_id, zone_data)\n    for zone_id, zone_data in zones.items()\n    if zone_data['display_name'].lower().endswith('muspi')\n]\n\n# Use the first matching zone\nzone_id, zone_data = muspi_zones[0]"
      }
    ],
    "body": "Roon Control Skill\n\nControl the Roon music player with Chinese command support.\n\nQuick Start\nInstall Dependencies\npip install roonapi\n\nUsage Examples\nfrom roon_controller import RoonController\n\n# Create controller (token will be saved automatically)\ncontroller = RoonController(verbose=True)\n\n# Play/Pause\nresult = controller.play_pause()\n\n# Next track\nresult = controller.next()\n\n# Get current track\ntrack_info = controller.get_current_track()\nprint(f\"Now playing: {track_info['track']}\")\n\nCore Features\n1. Automatic Discovery and Connection\nAutomatic Roon Core discovery\nToken automatically saved to ~/clawd/roon_config.json\nAuto-reconnect after restart, no re-authorization needed\n2. Zone Selection and Switching\nSupports switching between any available zone\nSelected zone is saved in config and persists across restarts\nIf no zone is selected, defaults to zones ending with \"[roon]\"\nUse set_zone() to switch zones programmatically\n\nSwitch Zone\n\nresult = controller.set_zone(\"Living Room\")\n# {\"success\": True, \"message\": \"Switched to zone: Living Room\", \"zone\": \"Living Room\"}\n\n\nGet Current Zone\n\nzone = controller.get_current_zone()\n# Returns zone info dict with zone_id and zone_data\n\n3. Playback Control\n\nPlay\n\nresult = controller.play()\n# {\"success\": True, \"message\": \"Playback started\", \"zone\": \"Living Room Muspi\"}\n\n\nPause\n\nresult = controller.pause()\n# {\"success\": True, \"message\": \"Paused\", \"zone\": \"Living Room Muspi\"}\n\n\nPlay/Pause Toggle\n\nresult = controller.play_pause()\n\n\nPrevious Track\n\nresult = controller.previous()\n\n\nNext Track\n\nresult = controller.next()\n\n4. Get Current Track\ntrack_info = controller.get_current_track()\n# Returns:\n# {\n#   \"success\": True,\n#   \"is_playing\": True,\n#   \"zone\": \"Living Room Muspi\",\n#   \"track\": \"Bohemian Rhapsody\",\n#   \"artist\": \"Queen\",\n#   \"album\": \"A Night at the Opera\",\n#   \"seek_position\": 12345,  # milliseconds\n#   \"length\": 354000        # milliseconds\n# }\n\n5. List All Zones\nzones = controller.list_zones()\n# [\"Living Room Muspi\", \"Kitchen\", \"Bedroom\"]\n\nCommand Line Tool\n\nThe script can be used as a command line tool:\n\n# Play\npython roon_controller.py play\n\n# Pause\npython roon_controller.py pause\n\n# Previous track\npython roon_controller.py prev\n\n# Next track\npython roon_controller.py next\n\n# View current track\npython roon_controller.py status\n\n# List all zones\npython roon_controller.py zones -v\n\n# switch zone\npython roon_controller.py switch zonename\n\nChinese Command Support\n\nThe skill supports the following Chinese trigger words:\n\nCommand\tMeaning\tExample\n音乐播放 / 播放音乐\tStart playback\t\"音乐播放\"\n暂停 / 暂停播放\tPause playback\t\"暂停一下\"\n下一曲 / 切歌\tNext track\t\"下一曲\"\n上一曲\tPrevious track\t\"上一曲\"\n当前曲目 / 正在放什么\tView current track\t\"当前曲目\"\nError Handling\n\nAll methods return a unified dictionary structure:\n\n{\n    \"success\": True/False,\n    \"message\": \"Operation result description\",\n    \"zone\": \"Zone name (optional)\"\n}\n\nCommon Errors\nMuspi zone not found: Check if the Roon zone name ends with \"muspi\"\nFailed to connect to Roon: Ensure Roon Core is running and network-accessible\nToken load failed: First run requires authorization, ensure authorization completes successfully\nNotes\nFirst Run: Extension authorization required in Roon, check for the extension authorization prompt in Roon interface\nZone Naming: Muspi zone names must end with \"muspi\" (case-insensitive)\nToken Storage: Token is saved in ~/clawd/roon_config.json, ensure secure file permissions\nNetwork Requirements: The device running the script must be on the same network as Roon Core\nTechnical Details\nDependencies\nroonapi>=0.1.6: Official Roon API Python library\nToken Management\nToken storage path: ~/clawd/roon_config.json\nAuto-load: Automatically loaded on each startup\nAuto-save: Automatically saved on first authorization or update\nZone Finding Algorithm\n# Find all zones\nzones = roon.zones\n\n# Filter zones with muspi suffix\nmuspi_zones = [\n    (zone_id, zone_data)\n    for zone_id, zone_data in zones.items()\n    if zone_data['display_name'].lower().endswith('muspi')\n]\n\n# Use the first matching zone\nzone_id, zone_data = muspi_zones[0]"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/puterjam/roon-controller",
    "publisherUrl": "https://clawhub.ai/puterjam/roon-controller",
    "owner": "puterjam",
    "version": "1.0.3",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/roon-controller",
    "downloadUrl": "https://openagent3.xyz/downloads/roon-controller",
    "agentUrl": "https://openagent3.xyz/skills/roon-controller/agent",
    "manifestUrl": "https://openagent3.xyz/skills/roon-controller/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/roon-controller/agent.md"
  }
}