zyx1121/music-mod
music-mod
/music:在提示列上方用一行顯示 macOS Music.app 正在播放的內容。可點擊的播放/暫停圖示、track · artist · album、帶時間的進度列,以及可點擊的下一首圖示。每 5 秒讀取一次 Music.app,由所有開啟的工作階段共用;其間時鐘繼續跳動。
關於這個 mod
music-mod
/musicfor Claude Code:即時顯示 Music.app 正在播放的內容,位於提示列上方的一行;播放/暫停與下一首都可點擊。
claude-code · mod · function-hooks · macos · music · now-playing
▶️ Tipsy · WANUKA · Greenhorn ████████████░░░░░░░░ 2:43 / 3:39 ⏭️
<sub>在任何版面中,提示列正上方的橫條。顯示時它的時鐘每秒跳動;▶️ 與 ⏭️ 可以點擊。</sub>
長時間的工作階段需要配樂,但開啟 Music.app 查看目前播放內容會打斷流程。這個 mod 讓答案只需一個指令就在眼前,直接顯示在你正在使用的終端機裡:曲目、播放位置,以及兩個可以暫停或跳過的圖示。
這是一個 Claude Code mod:功能位於 TypeScript hooks 模組中的外掛,使用與內建 /diff 面板相同的引擎 API。它繪製在 AbovePrompt 橫條中,因此無論逐字稿是全螢幕或內嵌,都會位於輸入框上方,不會佔用側邊停駐欄。沒有 shell hooks、沒有 MCP server;無論開啟多少工作階段,每 5 秒只呼叫一次 osascript。
安裝
function hooks 目前是搶先體驗,因此只有開啟旗標時引擎才會載入 mod。將它加入 shell 設定檔:
export CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1
接著從 GitHub 或本機 clone 安裝成外掛:
/plugin marketplace add zyx1121/music-mod
/plugin install music-mod@music-mod
也可以不安裝,在一個工作階段中試用:
claude --plugin-dir /path/to/music-mod
互動式工作階段一開始,這一行就會顯示。在工作階段中:
/music 隱藏或再次顯示
上一次選擇會在工作階段之間記住。
僅限 macOS:透過 Apple events 讀取 Music.app。第一次讀取時,終端機可能會詢問你是否允許控制 Music。
讀取操作絕不會啟動 Music.app,即使讀取發生時你正要結束它也一樣:事件會根據進程 ID 傳送給正在執行的進程,已經結束的進程會被視為已關閉。只有點擊狀態圖示或 ⏭️ 時,才會以名稱與 Music.app 通訊。
顯示內容
從左到右的一行:
| 部分 | 內容 |
|------|---------|
| ▶️ ⏸️ ⏩ ⏪ | 播放器狀態。點擊即可播放或暫停。 |
| 標題 | track · artist · album;橫條太窄時會以省略號截斷 |
| 橫條 | 進度會延伸填滿標題留下的寬度(至少 6 個儲存格),接著顯示位置 / 時長 |
| ⏭️ | 點擊跳到下一首。 |
Music.app 關閉或停止時,橫條會改為顯示相應狀態。osascript 失敗時(未授權、逾時),橫條會顯示原因並繼續輪詢。需要佔用橫條的 survey 會讓出位置。
設定
| 欄位 | 類型 | 預設值 | 功能 |
|-------|------|---------|--------------|
| refreshMs | number | 5000 | 橫條顯示時,兩次讀取 Music.app 之間的毫秒數。每個開啟的工作階段每個間隔共用一次讀取,時鐘在間隔中間繼續跳動。最低為 1000。 |
| showOnStart | boolean | true | 互動式工作階段一開始就顯示這一行。使用過 /music 後,你的選擇優先於此項。 |
在任何外掛 userConfig 欄位中設定:使用 /config,或在設定中填寫 music-mod.refreshMs。
建構方式
hooks/register.ts匯出register(on, options)。在session.start時註冊/music並顯示橫條(從$.store讀取上一次的/music選擇,否則使用showOnStart);command.run會切換並記住它;每秒一次的$.clock.everytick 會根據上次讀取重繪時鐘,並在refreshMs已經過去(或曲目播放完)後重新讀取;session.end時取消計時器;點擊圖示會執行其 AppleScript 並立即讀取。hooks/now-playing.ts保存 JXA 腳本(由osascript -l JavaScript執行)、將 JSON 轉成Model的解析器、時鐘與進度列格式化器、讀取之間延續的位置,以及每個圖示背後的一行 AppleScript。腳本只要求橫條要繪製的內容:不讀取系統音量(讀取會喚醒coreaudiod),也不走訪播放清單。hooks/shared-read.ts是所有工作階段共用的讀取機制:位於$TMPDIR/music-mod/now.json的小型 JSON 檔案。讀取夠新時,工作階段會直接取用;否則它會取得檔案、執行osascript並寫回結果,讓其他工作階段等待,而不是各自執行。hooks/views/band-view.tsx在ui.render中使用引擎的Box、Text與Button,為AbovePrompt元件繪製Model。types/claude-code.d.ts是這個 mod 所依據的引擎契約,複製自anthropics/claude-code/mods/types。
bunx -p typescript tsc -p tsconfig.json # typecheck
CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1 claude plugin test . # 35 tests, the engine's own harness
這些 mod 所依據的 API 可能在版本之間無預告地變更。發生變更時,從上游更新 types/claude-code.d.ts,讓型別檢查指出移動了哪些內容。
貢獻
歡迎提交 issue 與 PR。基本規則位於 CONTRIBUTING.md。
授權條款
MIT · now playing: whatever you left on
安裝
請先查看作者 README,確認 marketplace 與外掛名稱;指令可能隨儲存庫結構而變動。
claude plugin marketplace add zyx1121/music-mod claude plugin install music-mod
原文 / README
music-mod
/musicfor Claude Code: what Music.app is playing, in one line above the prompt, live, with play/pause and next a click away.
claude-code · mod · function-hooks · macos · music · now-playing
▶️ Tipsy · WANUKA · Greenhorn ████████████░░░░░░░░ 2:43 / 3:39 ⏭️
<sub>The band directly above the prompt, in any layout. Its clock ticks every second while shown; ▶️ and ⏭️ are clickable.</sub>
Long sessions have a soundtrack, and reaching for Music.app to check what is on breaks the flow. This mod keeps the answer one command away, inside the terminal you are already looking at: the track, where it is, and two glyphs to pause it or skip it.
It is a Claude Code mod: a plugin whose behaviour lives in a TypeScript hooks module, written against the same engine API as the built-in /diff pane. It draws into the AbovePrompt band, so it sits above the input whether the transcript is fullscreen or inline, and never takes a side dock. No shell hooks, no MCP server, and one osascript call every five seconds however many sessions are open.
Install
Function hooks are early access, so the engine loads a mod only with the flag on. Put it in your shell profile:
export CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1
Then install it as a plugin, from GitHub or from a local clone:
/plugin marketplace add zyx1121/music-mod
/plugin install music-mod@music-mod
Or try it for one session without installing:
claude --plugin-dir /path/to/music-mod
The line shows as soon as an interactive session starts. In the session:
/music hide it, or show it again
Your last choice is remembered between sessions.
macOS only: it reads Music.app through Apple events. The first read may ask you to allow your terminal to control Music.
Reading never launches Music.app, not even when a read lands while you quit it: the events go to the running process by its ID, and a process that has gone reads as closed. Only a click on the state glyph or ⏭️ talks to Music.app by name.
What it shows
One line, left to right:
| Part | Content |
|------|---------|
| ▶️ ⏸️ ⏩ ⏪ | The player state. Click it to play or pause. |
| Title | track · artist · album, cut with an ellipsis when the band is narrow |
| Bar | Progress, stretched to fill whatever width the title leaves (6 cells at the least), then position / duration |
| ⏭️ | Click it to skip to the next track. |
When Music.app is closed or stopped the band says so instead. When osascript fails (not authorized, timed out), the band shows the reason and keeps polling. A survey that takes the band is yielded to.
Configuration
| Field | Type | Default | What it does |
|-------|------|---------|--------------|
| refreshMs | number | 5000 | Milliseconds between reads of Music.app while the band is shown. Every open session shares one read per interval, and the clock ticks in between. Floored at 1000. |
| showOnStart | boolean | true | Show the line as soon as an interactive session starts. Once you have used /music, that choice wins over this. |
Set it as any plugin userConfig field: /config, or music-mod.refreshMs in settings.
How it is built
hooks/register.tsexportsregister(on, options). Onsession.startit registers/musicand shows the band (the last/musicchoice from$.store, elseshowOnStart);command.runtoggles it and remembers; a one-second$.clock.everytick redraws the clock from the last reading and, oncerefreshMshas passed (or the track has run out), takes a new one; the timer is cancelled onsession.end; a pressed glyph runs its AppleScript and reads at once.hooks/now-playing.tsholds the JXA scriptosascript -l JavaScriptruns, the parser that turns its JSON into aModel, the clock and progress-bar formatters, the position carried forward between reads, and the one-line AppleScript behind each glyph. The script asks only for what the band draws: no system volume (reading it wakescoreaudiod) and no playlist walk.hooks/shared-read.tsis the reading every session shares: a small JSON file at$TMPDIR/music-mod/now.json. A session takes the reading there when it is recent enough, else claims the file, runsosascriptand writes the result back, so the other sessions wait for it instead of running their own.hooks/views/band-view.tsxdraws theModelwith the engine'sBox,TextandButtononui.renderfor theAbovePromptcomponent.types/claude-code.d.tsis the engine contract this mod is typed against, copied fromanthropics/claude-code/mods/types.
bunx -p typescript tsc -p tsconfig.json # typecheck
CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1 claude plugin test . # 35 tests, the engine's own harness
The API these mods are written against may change between releases without notice. When it does, refresh types/claude-code.d.ts from upstream and let the typecheck point at what moved.
Contributing
Issues and PRs are welcome. Ground rules live in CONTRIBUTING.md.
License
MIT · now playing: whatever you left on

