{"owner":"darknessomi","repo":"musicbox","hasSkills":true,"totalSkillsCount":3,"totalTokensCount":3397,"categories":["cursor-rule","root-instruction","anthropic-skill"],"hasMcp":false,"mcpConfig":null,"found":[".cursor/rules/pre-commit-validation.mdc","AGENTS.md","skills/musicbox/SKILL.md"],"skills":{".cursor/rules/pre-commit-validation.mdc":"---\ndescription: 提交前本地跑与 CI 相同的检查，不等 CI 报错\nalwaysApply: true\n---\n\n# 提交前本地验证\n\n每次 `git commit` 前，必须先在本机跑完与 `.github/workflows/ci.yml` 等价的检查；任一失败则先修复再提交。\n\n```bash\nuv run ruff check\nuv run ruff format --check   # 失败则先 uv run ruff format 再重跑\nuv run ty check\nuv run pytest -s\n```\n\n格式问题优先用 `uv run ruff format` 自动修复，不要只改代码却跳过 format。\n\n若已安装 pre-commit hook（`uv run pre-commit install`），`git commit` 会自动跑 ruff 与 ty；仍应在提交前手动跑完整 pytest。\n","AGENTS.md":"# AGENTS.md\n\n## Cursor Cloud specific instructions\n\nNetEase-MusicBox is a Python 3.10+ command-line/curses TUI music player, managed with\n[`uv`](https://docs.astral.sh/uv/). There is a single package (`NEMbox`) and one product\n(the `musicbox` CLI/TUI). Dependencies are refreshed automatically by the startup update\nscript (`uv sync --frozen`); you do not need to reinstall them.\n\n### Running the app\n- Interactive TUI: `uv run musicbox` — this uses `curses` and requires a real interactive\n  terminal (TTY). It will not render in a non-TTY/headless shell; use the CLI subcommands\n  below for scripted/agent verification instead.\n- Agent/CLI mode (no TTY needed): `uv run musicbox <command>`, e.g.\n  `search`, `song url`, `play`, `pause`, `status`, `queue`, `daemon`, `auth`.\n  Add `--json` for machine-readable output. See `README.md` for the full command list.\n- Playback runs through a background daemon; `musicbox play --id <id>` auto-starts it and\n  `musicbox daemon stop` stops it.\n\n### Audio backends (system deps, NOT in update script)\n- `mpg123` (MP3) and `mpv` (FLAC / Hi-Res) are OS packages installed via `apt-get`\n  (`sudo apt-get install -y mpg123 mpv`). They are pre-installed in the snapshot; reinstall\n  only if `musicbox play` reports a missing backend. Playback selects `mpg123` by default.\n\n### Network / API note\n- Song search and playable URLs come from NetEase's public API, which only accepts\n  China-region access. From other regions requests can fail or return empty; set an HTTP\n  proxy (see README \"配置\") if search stops returning results. In this environment the API\n  was reachable and returned live results.\n- Login is QR-code scan only (renders a QR block in the terminal); there is no\n  username/password login and no test-login secret is required for search/playback.\n\n### Lint / test / build\nStandard commands (already documented in `.cursor/rules/pre-commit-validation.mdc` and\n`.github/workflows/ci.yml`); run them via `uv run`:\n- `uv run ruff check`\n- `uv run ruff format --check`\n- `uv run ty check` — emits ~11 diagnostics that are configured as `warn` in\n  `pyproject.toml`; it exits 0 and is not a failure.\n- `uv run pytest -q --tb=short`\n- `uv build`\n","skills/musicbox/SKILL.md":"---\nname: musicbox\ndescription: Use when the user wants to play/pause/skip music, control volume, seek,\n  search songs/playlists, query NetEase Music data, or operate NetEase MusicBox.\n  Drives MusicBox through the `musicbox` CLI + daemon; never simulates terminal\n  keypresses to the curses TUI.\n---\n\n# musicbox 控制规则\n\n## 黄金法则\n\n- 通过 `musicbox <cmd> --json` 操作，**绝不**向 curses TUI 模拟按键。\n- 重要动作后调 `musicbox status --json` **读回真实状态**再回复用户，不要\"发完命令就假设成功\"。\n- `play` / `next` / `prev` 的即时返回值常滞后（先 `stopped` 或旧进度）；**sleep 1–2 秒后再 `status`** 再下结论。\n- 数据类命令（search/artist/album/playlist/toplist/...）无状态，直接调，**不需要** daemon。\n\n## 命令速查\n\n| 类别 | 命令 |\n| --- | --- |\n| 播放控制 | `play [--id <id>\\|--playlist <id>\\|--index <n>\\|--artist <id>\\|--album <id>\\|--songs <ids...>]` / `pause` / `resume` / `toggle` / `stop` |\n| 切歌/进度 | `next [n]` / `prev [n]` / `seek <秒\\|+n\\|-n>` |\n| 音量/模式 | `volume <0-100\\|+n\\|-n>` / `mode <ordered\\|ordered-loop\\|single-loop\\|random\\|random-loop>` |\n| 状态/歌词 | `status` / `lyrics --current` |\n| 队列 | `queue list` / `queue add <id...>` / `queue play <index>` / `queue clear --yes` |\n| 守护进程 | `daemon start\\|stop\\|status\\|restart` |\n| 搜索 | `search <keyword> --type song\\|artist\\|album\\|playlist\\|dj` |\n| 歌曲/歌单 | `song info <id>` / `song url <id> [--quality lossless]` / `playlist show <id>` |\n| 榜单/推荐 | `toplist [--index n]` / `recommend songs\\|playlists`（需登录） / `fm`（需登录） |\n| 评论/喜爱 | `comments <id>` / `like <id>`（需登录） |\n| 查询歌手/专辑 | `artist <id>` / `album <id>` |\n| 下载 | `download --artist/--album/--songs/--playlist` |\n| 认证/配置 | `auth status\\|login\\|logout` / `config get <key>` / `config list` |\n\n## 任务配方\n\n### 搜歌并播放\n\n```bash\nmusicbox search <关键词> --type song --json   # 取 data[0].song_id\nmusicbox play --id <song_id> --json\n# sleep 1–2s\nmusicbox status --json\n```\n\n### 暂停 / 继续\n\n| 当前 `state` | 命令 |\n| --- | --- |\n| `paused` | `musicbox resume --json` → `status` |\n| `stopped` | **不要** `resume`；用 `play --id <id>`、`play --index <n>`，或队列非空时 `play` |\n| 换歌/换歌手 | 用 `play --id`，不要假设 `resume` 能接上之前的暂停 |\n\n### 今日推荐（需登录）\n\n```bash\nmusicbox auth status --json                  # exit 3 则走 login split-flow\nmusicbox recommend songs --limit 20 --json   # 收集 data[].song_id → ids[]\nmusicbox play --id <ids[0]> --json\nmusicbox queue add <ids[1]> <ids[2]> ... --json   # 每个 ID 独立 argv\nmusicbox mode ordered --json\nmusicbox status --json\n```\n\n`queue add` 在 shell 里勿把多个 ID 拼成一个字符串；可用 `queue add $(printf '%s\\n' \"${ids[@]:1}\")` 或从 JSON 解析后逐个传参。\n\n### 歌单播放\n\n```bash\nmusicbox play --playlist <playlist_id> --json\nmusicbox mode ordered --json    # 列表类意图默认顺序播放\nmusicbox status --json\n```\n\n切歌后用 `queue_index` / `queue_size` 确认当前第几首。\n\n\n### 搜歌手并播放热门歌曲\n\n```bash\nmusicbox search <关键词> --type artist --json   # 取 data[0].id\nmusicbox artist <artist_id> --json            # 查看热门歌曲\nmusicbox play --artist <artist_id> --limit 20 --json   # 播放前 20 首\nmusicbox status --json\n```\n\n### 搜专辑并播放\n\n```bash\nmusicbox search <关键词> --type album --json    # 取 data[0].id\nmusicbox album <album_id> --json              # 查看专辑歌曲列表\nmusicbox play --album <album_id> --json       # 播放整张专辑\nmusicbox status --json\n```\n\n### 播放多首指定歌曲\n\n```bash\nmusicbox play --songs <id1> <id2> <id3> --json   # 清队列 + 添加歌曲 + 播放第一首\nmusicbox queue list --json                    # 确认队列内容\nmusicbox status --json\n```\n\n### 下载歌曲\n\n```bash\nmusicbox download --playlist <playlist_id> --path ./music --json\nmusicbox download --artist <artist_id> --limit 20 --path ./music --json\nmusicbox download --album <album_id> --path ./music --json\nmusicbox download --songs <id1> <id2> --path ./music --json\n```\n\n每首歌曲下载为 `<artist>-<song>{ext}`，扩展名取决于音源（`.mp3` 或 `.flac`），结果输出 JSON 数组，每项包含 `ok`/错误信息。\n## 输出约定\n\n- Agent 调用时**始终加 `--json`**，解析 stdout 的 `{ok, data}` 信封。\n- 错误在 stderr：`{ok: false, error: {type, message, hint}}`。\n- 管道取值可用 `--quiet`（只输出关键值）。\n- `--dry-run`：只打印将发送的 RPC，不产生副作用，用于预演控制命令。\n\n## daemon 生命周期\n\n- 播放是**有状态本地会话**，由常驻 `musicboxd` 守护进程持有；控制类命令经它通信。\n- 控制类命令默认**自动拉起 daemon**；若遇 `exit 4`（daemon 未运行），先 `musicbox daemon start` 再重试。\n- `--no-daemon-autostart` 可禁用自动拉起（不在跑则直接 `exit 4`）。\n- daemon 与 curses TUI **互斥**：TUI 在跑时 daemon 无法启动，反之亦然。\n- 本地改过播放/daemon 代码后，先 `musicbox daemon restart`，否则仍是旧进程逻辑。\n\n## status 是你的眼睛\n\n```json\n{ \"ok\": true, \"data\": {\n  \"state\": \"playing|paused|stopped\",\n  \"song\": {\"id\": 33894312, \"name\": \"...\", \"artist\": \"...\", \"album\": \"...\", \"duration\": 273},\n  \"position\": 41.2, \"length\": 273, \"volume\": 60,\n  \"mode\": \"ordered\", \"backend\": \"mpv\", \"queue_index\": 3, \"queue_size\": 20\n}}\n```\n\n## 登录（split-flow，必须分两轮）\n\n1. **本轮**：`musicbox auth login --no-wait --json` → 取 `qr_ascii` / `unikey` → 把二维码发给用户 → 明确告知「用网易云音乐 App 扫码并确认后回来告诉我」→ **结束本轮**。\n2. **下一轮**：用户回复后执行 `musicbox auth login --check <unikey> --json`。\n\n纪律：\n\n- **禁止**输出 URL 让用户打开登录；必须使用网易云音乐 App 扫二维码。\n- **禁止**同轮展示二维码后立刻阻塞轮询。\n- **禁止**跨会话缓存 `unikey`（过期即重新 `login --no-wait`）。\n\n## 退出码分支\n\n| code | 含义 | Agent 应对 |\n| --- | --- | --- |\n| 0 | 成功 | 继续 |\n| 1 | 通用失败 | 读 `error.message` |\n| 2 | 参数错误 | 按 `hint` 修正 argv 重试 |\n| 3 | 未登录 | 走 `auth login` split-flow |\n| 4 | daemon 未运行 | `musicbox daemon start` 后重试（控制类默认会自动拉起） |\n| 5 | 操作不支持 | 读 `error.message`（如 mpg123 后端不支持 `seek`） |\n| 10 | 高风险写操作需确认 | **先问用户**，再在 argv 末尾追加 `--yes` 重试；绝不静默加 `--yes` |\n\n## 注意事项\n\n- `seek` 仅在 mpv 后端可用；mpg123 后端会返回 `not_supported`（`exit 5`），可提示用户播放无损或将 `player_backend` 设为 `mpv`。\n- `queue clear`、`auth logout` 是高风险写操作，遇 `exit 10` 先向用户确认。\n- **版权失败**：`state` 为 `stopped` 且日志/通知含 copyright；单曲或无可切下一首时会停止，**不要**对同一首反复 `play`/`next` 重试，直接告知用户换歌。\n- 播列表、今日推荐、歌单时，未指定模式则设 `mode ordered`，避免残留 `random-loop` 打乱顺序。\n"},"files":{".cursor/rules/pre-commit-validation.mdc":"---\ndescription: 提交前本地跑与 CI 相同的检查，不等 CI 报错\nalwaysApply: true\n---\n\n# 提交前本地验证\n\n每次 `git commit` 前，必须先在本机跑完与 `.github/workflows/ci.yml` 等价的检查；任一失败则先修复再提交。\n\n```bash\nuv run ruff check\nuv run ruff format --check   # 失败则先 uv run ruff format 再重跑\nuv run ty check\nuv run pytest -s\n```\n\n格式问题优先用 `uv run ruff format` 自动修复，不要只改代码却跳过 format。\n\n若已安装 pre-commit hook（`uv run pre-commit install`），`git commit` 会自动跑 ruff 与 ty；仍应在提交前手动跑完整 pytest。\n","AGENTS.md":"# AGENTS.md\n\n## Cursor Cloud specific instructions\n\nNetEase-MusicBox is a Python 3.10+ command-line/curses TUI music player, managed with\n[`uv`](https://docs.astral.sh/uv/). There is a single package (`NEMbox`) and one product\n(the `musicbox` CLI/TUI). Dependencies are refreshed automatically by the startup update\nscript (`uv sync --frozen`); you do not need to reinstall them.\n\n### Running the app\n- Interactive TUI: `uv run musicbox` — this uses `curses` and requires a real interactive\n  terminal (TTY). It will not render in a non-TTY/headless shell; use the CLI subcommands\n  below for scripted/agent verification instead.\n- Agent/CLI mode (no TTY needed): `uv run musicbox <command>`, e.g.\n  `search`, `song url`, `play`, `pause`, `status`, `queue`, `daemon`, `auth`.\n  Add `--json` for machine-readable output. See `README.md` for the full command list.\n- Playback runs through a background daemon; `musicbox play --id <id>` auto-starts it and\n  `musicbox daemon stop` stops it.\n\n### Audio backends (system deps, NOT in update script)\n- `mpg123` (MP3) and `mpv` (FLAC / Hi-Res) are OS packages installed via `apt-get`\n  (`sudo apt-get install -y mpg123 mpv`). They are pre-installed in the snapshot; reinstall\n  only if `musicbox play` reports a missing backend. Playback selects `mpg123` by default.\n\n### Network / API note\n- Song search and playable URLs come from NetEase's public API, which only accepts\n  China-region access. From other regions requests can fail or return empty; set an HTTP\n  proxy (see README \"配置\") if search stops returning results. In this environment the API\n  was reachable and returned live results.\n- Login is QR-code scan only (renders a QR block in the terminal); there is no\n  username/password login and no test-login secret is required for search/playback.\n\n### Lint / test / build\nStandard commands (already documented in `.cursor/rules/pre-commit-validation.mdc` and\n`.github/workflows/ci.yml`); run them via `uv run`:\n- `uv run ruff check`\n- `uv run ruff format --check`\n- `uv run ty check` — emits ~11 diagnostics that are configured as `warn` in\n  `pyproject.toml`; it exits 0 and is not a failure.\n- `uv run pytest -q --tb=short`\n- `uv build`\n","skills/musicbox/SKILL.md":"---\nname: musicbox\ndescription: Use when the user wants to play/pause/skip music, control volume, seek,\n  search songs/playlists, query NetEase Music data, or operate NetEase MusicBox.\n  Drives MusicBox through the `musicbox` CLI + daemon; never simulates terminal\n  keypresses to the curses TUI.\n---\n\n# musicbox 控制规则\n\n## 黄金法则\n\n- 通过 `musicbox <cmd> --json` 操作，**绝不**向 curses TUI 模拟按键。\n- 重要动作后调 `musicbox status --json` **读回真实状态**再回复用户，不要\"发完命令就假设成功\"。\n- `play` / `next` / `prev` 的即时返回值常滞后（先 `stopped` 或旧进度）；**sleep 1–2 秒后再 `status`** 再下结论。\n- 数据类命令（search/artist/album/playlist/toplist/...）无状态，直接调，**不需要** daemon。\n\n## 命令速查\n\n| 类别 | 命令 |\n| --- | --- |\n| 播放控制 | `play [--id <id>\\|--playlist <id>\\|--index <n>\\|--artist <id>\\|--album <id>\\|--songs <ids...>]` / `pause` / `resume` / `toggle` / `stop` |\n| 切歌/进度 | `next [n]` / `prev [n]` / `seek <秒\\|+n\\|-n>` |\n| 音量/模式 | `volume <0-100\\|+n\\|-n>` / `mode <ordered\\|ordered-loop\\|single-loop\\|random\\|random-loop>` |\n| 状态/歌词 | `status` / `lyrics --current` |\n| 队列 | `queue list` / `queue add <id...>` / `queue play <index>` / `queue clear --yes` |\n| 守护进程 | `daemon start\\|stop\\|status\\|restart` |\n| 搜索 | `search <keyword> --type song\\|artist\\|album\\|playlist\\|dj` |\n| 歌曲/歌单 | `song info <id>` / `song url <id> [--quality lossless]` / `playlist show <id>` |\n| 榜单/推荐 | `toplist [--index n]` / `recommend songs\\|playlists`（需登录） / `fm`（需登录） |\n| 评论/喜爱 | `comments <id>` / `like <id>`（需登录） |\n| 查询歌手/专辑 | `artist <id>` / `album <id>` |\n| 下载 | `download --artist/--album/--songs/--playlist` |\n| 认证/配置 | `auth status\\|login\\|logout` / `config get <key>` / `config list` |\n\n## 任务配方\n\n### 搜歌并播放\n\n```bash\nmusicbox search <关键词> --type song --json   # 取 data[0].song_id\nmusicbox play --id <song_id> --json\n# sleep 1–2s\nmusicbox status --json\n```\n\n### 暂停 / 继续\n\n| 当前 `state` | 命令 |\n| --- | --- |\n| `paused` | `musicbox resume --json` → `status` |\n| `stopped` | **不要** `resume`；用 `play --id <id>`、`play --index <n>`，或队列非空时 `play` |\n| 换歌/换歌手 | 用 `play --id`，不要假设 `resume` 能接上之前的暂停 |\n\n### 今日推荐（需登录）\n\n```bash\nmusicbox auth status --json                  # exit 3 则走 login split-flow\nmusicbox recommend songs --limit 20 --json   # 收集 data[].song_id → ids[]\nmusicbox play --id <ids[0]> --json\nmusicbox queue add <ids[1]> <ids[2]> ... --json   # 每个 ID 独立 argv\nmusicbox mode ordered --json\nmusicbox status --json\n```\n\n`queue add` 在 shell 里勿把多个 ID 拼成一个字符串；可用 `queue add $(printf '%s\\n' \"${ids[@]:1}\")` 或从 JSON 解析后逐个传参。\n\n### 歌单播放\n\n```bash\nmusicbox play --playlist <playlist_id> --json\nmusicbox mode ordered --json    # 列表类意图默认顺序播放\nmusicbox status --json\n```\n\n切歌后用 `queue_index` / `queue_size` 确认当前第几首。\n\n\n### 搜歌手并播放热门歌曲\n\n```bash\nmusicbox search <关键词> --type artist --json   # 取 data[0].id\nmusicbox artist <artist_id> --json            # 查看热门歌曲\nmusicbox play --artist <artist_id> --limit 20 --json   # 播放前 20 首\nmusicbox status --json\n```\n\n### 搜专辑并播放\n\n```bash\nmusicbox search <关键词> --type album --json    # 取 data[0].id\nmusicbox album <album_id> --json              # 查看专辑歌曲列表\nmusicbox play --album <album_id> --json       # 播放整张专辑\nmusicbox status --json\n```\n\n### 播放多首指定歌曲\n\n```bash\nmusicbox play --songs <id1> <id2> <id3> --json   # 清队列 + 添加歌曲 + 播放第一首\nmusicbox queue list --json                    # 确认队列内容\nmusicbox status --json\n```\n\n### 下载歌曲\n\n```bash\nmusicbox download --playlist <playlist_id> --path ./music --json\nmusicbox download --artist <artist_id> --limit 20 --path ./music --json\nmusicbox download --album <album_id> --path ./music --json\nmusicbox download --songs <id1> <id2> --path ./music --json\n```\n\n每首歌曲下载为 `<artist>-<song>{ext}`，扩展名取决于音源（`.mp3` 或 `.flac`），结果输出 JSON 数组，每项包含 `ok`/错误信息。\n## 输出约定\n\n- Agent 调用时**始终加 `--json`**，解析 stdout 的 `{ok, data}` 信封。\n- 错误在 stderr：`{ok: false, error: {type, message, hint}}`。\n- 管道取值可用 `--quiet`（只输出关键值）。\n- `--dry-run`：只打印将发送的 RPC，不产生副作用，用于预演控制命令。\n\n## daemon 生命周期\n\n- 播放是**有状态本地会话**，由常驻 `musicboxd` 守护进程持有；控制类命令经它通信。\n- 控制类命令默认**自动拉起 daemon**；若遇 `exit 4`（daemon 未运行），先 `musicbox daemon start` 再重试。\n- `--no-daemon-autostart` 可禁用自动拉起（不在跑则直接 `exit 4`）。\n- daemon 与 curses TUI **互斥**：TUI 在跑时 daemon 无法启动，反之亦然。\n- 本地改过播放/daemon 代码后，先 `musicbox daemon restart`，否则仍是旧进程逻辑。\n\n## status 是你的眼睛\n\n```json\n{ \"ok\": true, \"data\": {\n  \"state\": \"playing|paused|stopped\",\n  \"song\": {\"id\": 33894312, \"name\": \"...\", \"artist\": \"...\", \"album\": \"...\", \"duration\": 273},\n  \"position\": 41.2, \"length\": 273, \"volume\": 60,\n  \"mode\": \"ordered\", \"backend\": \"mpv\", \"queue_index\": 3, \"queue_size\": 20\n}}\n```\n\n## 登录（split-flow，必须分两轮）\n\n1. **本轮**：`musicbox auth login --no-wait --json` → 取 `qr_ascii` / `unikey` → 把二维码发给用户 → 明确告知「用网易云音乐 App 扫码并确认后回来告诉我」→ **结束本轮**。\n2. **下一轮**：用户回复后执行 `musicbox auth login --check <unikey> --json`。\n\n纪律：\n\n- **禁止**输出 URL 让用户打开登录；必须使用网易云音乐 App 扫二维码。\n- **禁止**同轮展示二维码后立刻阻塞轮询。\n- **禁止**跨会话缓存 `unikey`（过期即重新 `login --no-wait`）。\n\n## 退出码分支\n\n| code | 含义 | Agent 应对 |\n| --- | --- | --- |\n| 0 | 成功 | 继续 |\n| 1 | 通用失败 | 读 `error.message` |\n| 2 | 参数错误 | 按 `hint` 修正 argv 重试 |\n| 3 | 未登录 | 走 `auth login` split-flow |\n| 4 | daemon 未运行 | `musicbox daemon start` 后重试（控制类默认会自动拉起） |\n| 5 | 操作不支持 | 读 `error.message`（如 mpg123 后端不支持 `seek`） |\n| 10 | 高风险写操作需确认 | **先问用户**，再在 argv 末尾追加 `--yes` 重试；绝不静默加 `--yes` |\n\n## 注意事项\n\n- `seek` 仅在 mpv 后端可用；mpg123 后端会返回 `not_supported`（`exit 5`），可提示用户播放无损或将 `player_backend` 设为 `mpv`。\n- `queue clear`、`auth logout` 是高风险写操作，遇 `exit 10` 先向用户确认。\n- **版权失败**：`state` 为 `stopped` 且日志/通知含 copyright；单曲或无可切下一首时会停止，**不要**对同一首反复 `play`/`next` 重试，直接告知用户换歌。\n- 播列表、今日推荐、歌单时，未指定模式则设 `mode ordered`，避免残留 `random-loop` 打乱顺序。\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/darknessomi/musicbox/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# AGENTS.md\n\n## Cursor Cloud specific instructions\n\nNetEase-MusicBox is a Python 3.10+ command-line/curses TUI music player, managed with\n[`uv`](https://docs.astral.sh/uv/). There is a single package (`NEMbox`) and one product\n(the `musicbox` CLI/TUI). Dependencies are refreshed automatically by the startup update\nscript (`uv sync --frozen`); you do not need to reinstall them.\n\n### Running the app\n- Interactive TUI: `uv run musicbox` — this uses `curses` and requires a real interactive\n  terminal (TTY). It will not render in a non-TTY/headless shell; use the CLI subcommands\n  below for scripted/agent verification instead.\n- Agent/CLI mode (no TTY needed): `uv run musicbox <command>`, e.g.\n  `search`, `song url`, `play`, `pause`, `status`, `queue`, `daemon`, `auth`.\n  Add `--json` for machine-readable output. See `README.md` for the full command list.\n- Playback runs through a background daemon; `musicbox play --id <id>` auto-starts it and\n  `musicbox daemon stop` stops it.\n\n### Audio backends (system deps, NOT in update script)\n- `mpg123` (MP3) and `mpv` (FLAC / Hi-Res) are OS packages installed via `apt-get`\n  (`sudo apt-get install -y mpg123 mpv`). They are pre-installed in the snapshot; reinstall\n  only if `musicbox play` reports a missing backend. Playback selects `mpg123` by default.\n\n### Network / API note\n- Song search and playable URLs come from NetEase's public API, which only accepts\n  China-region access. From other regions requests can fail or return empty; set an HTTP\n  proxy (see README \"配置\") if search stops returning results. In this environment the API\n  was reachable and returned live results.\n- Login is QR-code scan only (renders a QR block in the terminal); there is no\n  username/password login and no test-login secret is required for search/playback.\n\n### Lint / test / build\nStandard commands (already documented in `.cursor/rules/pre-commit-validation.mdc` and\n`.github/workflows/ci.yml`); run them via `uv run`:\n- `uv run ruff check`\n- `uv run ruff format --check`\n- `uv run ty check` — emits ~11 diagnostics that are configured as `warn` in\n  `pyproject.toml`; it exits 0 and is not a failure.\n- `uv run pytest -q --tb=short`\n- `uv build`\n","isInternal":false,"tokens":578,"sizeBytes":2201},{"name":"SKILL.md","path":"skills/musicbox/SKILL.md","rawUrl":"https://raw.githubusercontent.com/darknessomi/musicbox/HEAD/skills/musicbox/SKILL.md","title":"musicbox","category":"anthropic-skill","format":"markdown","content":"---\nname: musicbox\ndescription: Use when the user wants to play/pause/skip music, control volume, seek,\n  search songs/playlists, query NetEase Music data, or operate NetEase MusicBox.\n  Drives MusicBox through the `musicbox` CLI + daemon; never simulates terminal\n  keypresses to the curses TUI.\n---\n\n# musicbox 控制规则\n\n## 黄金法则\n\n- 通过 `musicbox <cmd> --json` 操作，**绝不**向 curses TUI 模拟按键。\n- 重要动作后调 `musicbox status --json` **读回真实状态**再回复用户，不要\"发完命令就假设成功\"。\n- `play` / `next` / `prev` 的即时返回值常滞后（先 `stopped` 或旧进度）；**sleep 1–2 秒后再 `status`** 再下结论。\n- 数据类命令（search/artist/album/playlist/toplist/...）无状态，直接调，**不需要** daemon。\n\n## 命令速查\n\n| 类别 | 命令 |\n| --- | --- |\n| 播放控制 | `play [--id <id>\\|--playlist <id>\\|--index <n>\\|--artist <id>\\|--album <id>\\|--songs <ids...>]` / `pause` / `resume` / `toggle` / `stop` |\n| 切歌/进度 | `next [n]` / `prev [n]` / `seek <秒\\|+n\\|-n>` |\n| 音量/模式 | `volume <0-100\\|+n\\|-n>` / `mode <ordered\\|ordered-loop\\|single-loop\\|random\\|random-loop>` |\n| 状态/歌词 | `status` / `lyrics --current` |\n| 队列 | `queue list` / `queue add <id...>` / `queue play <index>` / `queue clear --yes` |\n| 守护进程 | `daemon start\\|stop\\|status\\|restart` |\n| 搜索 | `search <keyword> --type song\\|artist\\|album\\|playlist\\|dj` |\n| 歌曲/歌单 | `song info <id>` / `song url <id> [--quality lossless]` / `playlist show <id>` |\n| 榜单/推荐 | `toplist [--index n]` / `recommend songs\\|playlists`（需登录） / `fm`（需登录） |\n| 评论/喜爱 | `comments <id>` / `like <id>`（需登录） |\n| 查询歌手/专辑 | `artist <id>` / `album <id>` |\n| 下载 | `download --artist/--album/--songs/--playlist` |\n| 认证/配置 | `auth status\\|login\\|logout` / `config get <key>` / `config list` |\n\n## 任务配方\n\n### 搜歌并播放\n\n```bash\nmusicbox search <关键词> --type song --json   # 取 data[0].song_id\nmusicbox play --id <song_id> --json\n# sleep 1–2s\nmusicbox status --json\n```\n\n### 暂停 / 继续\n\n| 当前 `state` | 命令 |\n| --- | --- |\n| `paused` | `musicbox resume --json` → `status` |\n| `stopped` | **不要** `resume`；用 `play --id <id>`、`play --index <n>`，或队列非空时 `play` |\n| 换歌/换歌手 | 用 `play --id`，不要假设 `resume` 能接上之前的暂停 |\n\n### 今日推荐（需登录）\n\n```bash\nmusicbox auth status --json                  # exit 3 则走 login split-flow\nmusicbox recommend songs --limit 20 --json   # 收集 data[].song_id → ids[]\nmusicbox play --id <ids[0]> --json\nmusicbox queue add <ids[1]> <ids[2]> ... --json   # 每个 ID 独立 argv\nmusicbox mode ordered --json\nmusicbox status --json\n```\n\n`queue add` 在 shell 里勿把多个 ID 拼成一个字符串；可用 `queue add $(printf '%s\\n' \"${ids[@]:1}\")` 或从 JSON 解析后逐个传参。\n\n### 歌单播放\n\n```bash\nmusicbox play --playlist <playlist_id> --json\nmusicbox mode ordered --json    # 列表类意图默认顺序播放\nmusicbox status --json\n```\n\n切歌后用 `queue_index` / `queue_size` 确认当前第几首。\n\n\n### 搜歌手并播放热门歌曲\n\n```bash\nmusicbox search <关键词> --type artist --json   # 取 data[0].id\nmusicbox artist <artist_id> --json            # 查看热门歌曲\nmusicbox play --artist <artist_id> --limit 20 --json   # 播放前 20 首\nmusicbox status --json\n```\n\n### 搜专辑并播放\n\n```bash\nmusicbox search <关键词> --type album --json    # 取 data[0].id\nmusicbox album <album_id> --json              # 查看专辑歌曲列表\nmusicbox play --album <album_id> --json       # 播放整张专辑\nmusicbox status --json\n```\n\n### 播放多首指定歌曲\n\n```bash\nmusicbox play --songs <id1> <id2> <id3> --json   # 清队列 + 添加歌曲 + 播放第一首\nmusicbox queue list --json                    # 确认队列内容\nmusicbox status --json\n```\n\n### 下载歌曲\n\n```bash\nmusicbox download --playlist <playlist_id> --path ./music --json\nmusicbox download --artist <artist_id> --limit 20 --path ./music --json\nmusicbox download --album <album_id> --path ./music --json\nmusicbox download --songs <id1> <id2> --path ./music --json\n```\n\n每首歌曲下载为 `<artist>-<song>{ext}`，扩展名取决于音源（`.mp3` 或 `.flac`），结果输出 JSON 数组，每项包含 `ok`/错误信息。\n## 输出约定\n\n- Agent 调用时**始终加 `--json`**，解析 stdout 的 `{ok, data}` 信封。\n- 错误在 stderr：`{ok: false, error: {type, message, hint}}`。\n- 管道取值可用 `--quiet`（只输出关键值）。\n- `--dry-run`：只打印将发送的 RPC，不产生副作用，用于预演控制命令。\n\n## daemon 生命周期\n\n- 播放是**有状态本地会话**，由常驻 `musicboxd` 守护进程持有；控制类命令经它通信。\n- 控制类命令默认**自动拉起 daemon**；若遇 `exit 4`（daemon 未运行），先 `musicbox daemon start` 再重试。\n- `--no-daemon-autostart` 可禁用自动拉起（不在跑则直接 `exit 4`）。\n- daemon 与 curses TUI **互斥**：TUI 在跑时 daemon 无法启动，反之亦然。\n- 本地改过播放/daemon 代码后，先 `musicbox daemon restart`，否则仍是旧进程逻辑。\n\n## status 是你的眼睛\n\n```json\n{ \"ok\": true, \"data\": {\n  \"state\": \"playing|paused|stopped\",\n  \"song\": {\"id\": 33894312, \"name\": \"...\", \"artist\": \"...\", \"album\": \"...\", \"duration\": 273},\n  \"position\": 41.2, \"length\": 273, \"volume\": 60,\n  \"mode\": \"ordered\", \"backend\": \"mpv\", \"queue_index\": 3, \"queue_size\": 20\n}}\n```\n\n## 登录（split-flow，必须分两轮）\n\n1. **本轮**：`musicbox auth login --no-wait --json` → 取 `qr_ascii` / `unikey` → 把二维码发给用户 → 明确告知「用网易云音乐 App 扫码并确认后回来告诉我」→ **结束本轮**。\n2. **下一轮**：用户回复后执行 `musicbox auth login --check <unikey> --json`。\n\n纪律：\n\n- **禁止**输出 URL 让用户打开登录；必须使用网易云音乐 App 扫二维码。\n- **禁止**同轮展示二维码后立刻阻塞轮询。\n- **禁止**跨会话缓存 `unikey`（过期即重新 `login --no-wait`）。\n\n## 退出码分支\n\n| code | 含义 | Agent 应对 |\n| --- | --- | --- |\n| 0 | 成功 | 继续 |\n| 1 | 通用失败 | 读 `error.message` |\n| 2 | 参数错误 | 按 `hint` 修正 argv 重试 |\n| 3 | 未登录 | 走 `auth login` split-flow |\n| 4 | daemon 未运行 | `musicbox daemon start` 后重试（控制类默认会自动拉起） |\n| 5 | 操作不支持 | 读 `error.message`（如 mpg123 后端不支持 `seek`） |\n| 10 | 高风险写操作需确认 | **先问用户**，再在 argv 末尾追加 `--yes` 重试；绝不静默加 `--yes` |\n\n## 注意事项\n\n- `seek` 仅在 mpv 后端可用；mpg123 后端会返回 `not_supported`（`exit 5`），可提示用户播放无损或将 `player_backend` 设为 `mpv`。\n- `queue clear`、`auth logout` 是高风险写操作，遇 `exit 10` 先向用户确认。\n- **版权失败**：`state` 为 `stopped` 且日志/通知含 copyright；单曲或无可切下一首时会停止，**不要**对同一首反复 `play`/`next` 重试，直接告知用户换歌。\n- 播列表、今日推荐、歌单时，未指定模式则设 `mode ordered`，避免残留 `random-loop` 打乱顺序。\n","frontmatter":{"name":"musicbox","description":"Use when the user wants to play/pause/skip music, control volume, seek, search songs/playlists, query NetEase Music data, or operate NetEase MusicBox. Drives MusicBox through the `musicbox` CLI + daemon; never simulates terminal keypresses to the curses TUI."},"isInternal":false,"tokens":2609,"sizeBytes":7338},{"name":"pre-commit-validation.mdc","path":".cursor/rules/pre-commit-validation.mdc","rawUrl":"https://raw.githubusercontent.com/darknessomi/musicbox/HEAD/.cursor/rules/pre-commit-validation.mdc","title":"Cursor Rule: pre-commit-validation","category":"cursor-rule","format":"mdc","content":"---\ndescription: 提交前本地跑与 CI 相同的检查，不等 CI 报错\nalwaysApply: true\n---\n\n# 提交前本地验证\n\n每次 `git commit` 前，必须先在本机跑完与 `.github/workflows/ci.yml` 等价的检查；任一失败则先修复再提交。\n\n```bash\nuv run ruff check\nuv run ruff format --check   # 失败则先 uv run ruff format 再重跑\nuv run ty check\nuv run pytest -s\n```\n\n格式问题优先用 `uv run ruff format` 自动修复，不要只改代码却跳过 format。\n\n若已安装 pre-commit hook（`uv run pre-commit install`），`git commit` 会自动跑 ruff 与 ty；仍应在提交前手动跑完整 pytest。\n","frontmatter":{"description":"提交前本地跑与 CI 相同的检查，不等 CI 报错","alwaysApply":true},"isInternal":false,"tokens":210,"sizeBytes":644}],"systemPromptSnippet":"<yakaai_skills repo=\"darknessomi/musicbox\">\n<!-- File: AGENTS.md (Tokens: ~578 | Category: root-instruction) -->\n# AGENTS.md\n\n## Cursor Cloud specific instructions\n\nNetEase-MusicBox is a Python 3.10+ command-line/curses TUI music player, managed with\n[`uv`](https://docs.astral.sh/uv/). There is a single package (`NEMbox`) and one product\n(the `musicbox` CLI/TUI). Dependencies are refreshed automatically by the startup update\nscript (`uv sync --frozen`); you do not need to reinstall them.\n\n### Running the app\n- Interactive TUI: `uv run musicbox` — this uses `curses` and requires a real interactive\n  terminal (TTY). It will not render in a non-TTY/headless shell; use the CLI subcommands\n  below for scripted/agent verification instead.\n- Agent/CLI mode (no TTY needed): `uv run musicbox <command>`, e.g.\n  `search`, `song url`, `play`, `pause`, `status`, `queue`, `daemon`, `auth`.\n  Add `--json` for machine-readable output. See `README.md` for the full command list.\n- Playback runs through a background daemon; `musicbox play --id <id>` auto-starts it and\n  `musicbox daemon stop` stops it.\n\n### Audio backends (system deps, NOT in update script)\n- `mpg123` (MP3) and `mpv` (FLAC / Hi-Res) are OS packages installed via `apt-get`\n  (`sudo apt-get install -y mpg123 mpv`). They are pre-installed in the snapshot; reinstall\n  only if `musicbox play` reports a missing backend. Playback selects `mpg123` by default.\n\n### Network / API note\n- Song search and playable URLs come from NetEase's public API, which only accepts\n  China-region access. From other regions requests can fail or return empty; set an HTTP\n  proxy (see README \"配置\") if search stops returning results. In this environment the API\n  was reachable and returned live results.\n- Login is QR-code scan only (renders a QR block in the terminal); there is no\n  username/password login and no test-login secret is required for search/playback.\n\n### Lint / test / build\nStandard commands (already documented in `.cursor/rules/pre-commit-validation.mdc` and\n`.github/workflows/ci.yml`); run them via `uv run`:\n- `uv run ruff check`\n- `uv run ruff format --check`\n- `uv run ty check` — emits ~11 diagnostics that are configured as `warn` in\n  `pyproject.toml`; it exits 0 and is not a failure.\n- `uv run pytest -q --tb=short`\n- `uv build`\n\n<!-- File: skills/musicbox/SKILL.md (Tokens: ~2609 | Category: anthropic-skill) -->\n---\nname: musicbox\ndescription: Use when the user wants to play/pause/skip music, control volume, seek,\n  search songs/playlists, query NetEase Music data, or operate NetEase MusicBox.\n  Drives MusicBox through the `musicbox` CLI + daemon; never simulates terminal\n  keypresses to the curses TUI.\n---\n\n# musicbox 控制规则\n\n## 黄金法则\n\n- 通过 `musicbox <cmd> --json` 操作，**绝不**向 curses TUI 模拟按键。\n- 重要动作后调 `musicbox status --json` **读回真实状态**再回复用户，不要\"发完命令就假设成功\"。\n- `play` / `next` / `prev` 的即时返回值常滞后（先 `stopped` 或旧进度）；**sleep 1–2 秒后再 `status`** 再下结论。\n- 数据类命令（search/artist/album/playlist/toplist/...）无状态，直接调，**不需要** daemon。\n\n## 命令速查\n\n| 类别 | 命令 |\n| --- | --- |\n| 播放控制 | `play [--id <id>\\|--playlist <id>\\|--index <n>\\|--artist <id>\\|--album <id>\\|--songs <ids...>]` / `pause` / `resume` / `toggle` / `stop` |\n| 切歌/进度 | `next [n]` / `prev [n]` / `seek <秒\\|+n\\|-n>` |\n| 音量/模式 | `volume <0-100\\|+n\\|-n>` / `mode <ordered\\|ordered-loop\\|single-loop\\|random\\|random-loop>` |\n| 状态/歌词 | `status` / `lyrics --current` |\n| 队列 | `queue list` / `queue add <id...>` / `queue play <index>` / `queue clear --yes` |\n| 守护进程 | `daemon start\\|stop\\|status\\|restart` |\n| 搜索 | `search <keyword> --type song\\|artist\\|album\\|playlist\\|dj` |\n| 歌曲/歌单 | `song info <id>` / `song url <id> [--quality lossless]` / `playlist show <id>` |\n| 榜单/推荐 | `toplist [--index n]` / `recommend songs\\|playlists`（需登录） / `fm`（需登录） |\n| 评论/喜爱 | `comments <id>` / `like <id>`（需登录） |\n| 查询歌手/专辑 | `artist <id>` / `album <id>` |\n| 下载 | `download --artist/--album/--songs/--playlist` |\n| 认证/配置 | `auth status\\|login\\|logout` / `config get <key>` / `config list` |\n\n## 任务配方\n\n### 搜歌并播放\n\n```bash\nmusicbox search <关键词> --type song --json   # 取 data[0].song_id\nmusicbox play --id <song_id> --json\n# sleep 1–2s\nmusicbox status --json\n```\n\n### 暂停 / 继续\n\n| 当前 `state` | 命令 |\n| --- | --- |\n| `paused` | `musicbox resume --json` → `status` |\n| `stopped` | **不要** `resume`；用 `play --id <id>`、`play --index <n>`，或队列非空时 `play` |\n| 换歌/换歌手 | 用 `play --id`，不要假设 `resume` 能接上之前的暂停 |\n\n### 今日推荐（需登录）\n\n```bash\nmusicbox auth status --json                  # exit 3 则走 login split-flow\nmusicbox recommend songs --limit 20 --json   # 收集 data[].song_id → ids[]\nmusicbox play --id <ids[0]> --json\nmusicbox queue add <ids[1]> <ids[2]> ... --json   # 每个 ID 独立 argv\nmusicbox mode ordered --json\nmusicbox status --json\n```\n\n`queue add` 在 shell 里勿把多个 ID 拼成一个字符串；可用 `queue add $(printf '%s\\n' \"${ids[@]:1}\")` 或从 JSON 解析后逐个传参。\n\n### 歌单播放\n\n```bash\nmusicbox play --playlist <playlist_id> --json\nmusicbox mode ordered --json    # 列表类意图默认顺序播放\nmusicbox status --json\n```\n\n切歌后用 `queue_index` / `queue_size` 确认当前第几首。\n\n\n### 搜歌手并播放热门歌曲\n\n```bash\nmusicbox search <关键词> --type artist --json   # 取 data[0].id\nmusicbox artist <artist_id> --json            # 查看热门歌曲\nmusicbox play --artist <artist_id> --limit 20 --json   # 播放前 20 首\nmusicbox status --json\n```\n\n### 搜专辑并播放\n\n```bash\nmusicbox search <关键词> --type album --json    # 取 data[0].id\nmusicbox album <album_id> --json              # 查看专辑歌曲列表\nmusicbox play --album <album_id> --json       # 播放整张专辑\nmusicbox status --json\n```\n\n### 播放多首指定歌曲\n\n```bash\nmusicbox play --songs <id1> <id2> <id3> --json   # 清队列 + 添加歌曲 + 播放第一首\nmusicbox queue list --json                    # 确认队列内容\nmusicbox status --json\n```\n\n### 下载歌曲\n\n```bash\nmusicbox download --playlist <playlist_id> --path ./music --json\nmusicbox download --artist <artist_id> --limit 20 --path ./music --json\nmusicbox download --album <album_id> --path ./music --json\nmusicbox download --songs <id1> <id2> --path ./music --json\n```\n\n每首歌曲下载为 `<artist>-<song>{ext}`，扩展名取决于音源（`.mp3` 或 `.flac`），结果输出 JSON 数组，每项包含 `ok`/错误信息。\n## 输出约定\n\n- Agent 调用时**始终加 `--json`**，解析 stdout 的 `{ok, data}` 信封。\n- 错误在 stderr：`{ok: false, error: {type, message, hint}}`。\n- 管道取值可用 `--quiet`（只输出关键值）。\n- `--dry-run`：只打印将发送的 RPC，不产生副作用，用于预演控制命令。\n\n## daemon 生命周期\n\n- 播放是**有状态本地会话**，由常驻 `musicboxd` 守护进程持有；控制类命令经它通信。\n- 控制类命令默认**自动拉起 daemon**；若遇 `exit 4`（daemon 未运行），先 `musicbox daemon start` 再重试。\n- `--no-daemon-autostart` 可禁用自动拉起（不在跑则直接 `exit 4`）。\n- daemon 与 curses TUI **互斥**：TUI 在跑时 daemon 无法启动，反之亦然。\n- 本地改过播放/daemon 代码后，先 `musicbox daemon restart`，否则仍是旧进程逻辑。\n\n## status 是你的眼睛\n\n```json\n{ \"ok\": true, \"data\": {\n  \"state\": \"playing|paused|stopped\",\n  \"song\": {\"id\": 33894312, \"name\": \"...\", \"artist\": \"...\", \"album\": \"...\", \"duration\": 273},\n  \"position\": 41.2, \"length\": 273, \"volume\": 60,\n  \"mode\": \"ordered\", \"backend\": \"mpv\", \"queue_index\": 3, \"queue_size\": 20\n}}\n```\n\n## 登录（split-flow，必须分两轮）\n\n1. **本轮**：`musicbox auth login --no-wait --json` → 取 `qr_ascii` / `unikey` → 把二维码发给用户 → 明确告知「用网易云音乐 App 扫码并确认后回来告诉我」→ **结束本轮**。\n2. **下一轮**：用户回复后执行 `musicbox auth login --check <unikey> --json`。\n\n纪律：\n\n- **禁止**输出 URL 让用户打开登录；必须使用网易云音乐 App 扫二维码。\n- **禁止**同轮展示二维码后立刻阻塞轮询。\n- **禁止**跨会话缓存 `unikey`（过期即重新 `login --no-wait`）。\n\n## 退出码分支\n\n| code | 含义 | Agent 应对 |\n| --- | --- | --- |\n| 0 | 成功 | 继续 |\n| 1 | 通用失败 | 读 `error.message` |\n| 2 | 参数错误 | 按 `hint` 修正 argv 重试 |\n| 3 | 未登录 | 走 `auth login` split-flow |\n| 4 | daemon 未运行 | `musicbox daemon start` 后重试（控制类默认会自动拉起） |\n| 5 | 操作不支持 | 读 `error.message`（如 mpg123 后端不支持 `seek`） |\n| 10 | 高风险写操作需确认 | **先问用户**，再在 argv 末尾追加 `--yes` 重试；绝不静默加 `--yes` |\n\n## 注意事项\n\n- `seek` 仅在 mpv 后端可用；mpg123 后端会返回 `not_supported`（`exit 5`），可提示用户播放无损或将 `player_backend` 设为 `mpv`。\n- `queue clear`、`auth logout` 是高风险写操作，遇 `exit 10` 先向用户确认。\n- **版权失败**：`state` 为 `stopped` 且日志/通知含 copyright；单曲或无可切下一首时会停止，**不要**对同一首反复 `play`/`next` 重试，直接告知用户换歌。\n- 播列表、今日推荐、歌单时，未指定模式则设 `mode ordered`，避免残留 `random-loop` 打乱顺序。\n\n<!-- File: .cursor/rules/pre-commit-validation.mdc (Tokens: ~210 | Category: cursor-rule) -->\n---\ndescription: 提交前本地跑与 CI 相同的检查，不等 CI 报错\nalwaysApply: true\n---\n\n# 提交前本地验证\n\n每次 `git commit` 前，必须先在本机跑完与 `.github/workflows/ci.yml` 等价的检查；任一失败则先修复再提交。\n\n```bash\nuv run ruff check\nuv run ruff format --check   # 失败则先 uv run ruff format 再重跑\nuv run ty check\nuv run pytest -s\n```\n\n格式问题优先用 `uv run ruff format` 自动修复，不要只改代码却跳过 format。\n\n若已安装 pre-commit hook（`uv run pre-commit install`），`git commit` 会自动跑 ruff 与 ty；仍应在提交前手动跑完整 pytest。\n</yakaai_skills>"}