capy.

一支住在終端機裡的音樂 CLI。搜尋、遙控播放,把 Spotify 與 Apple Music 的播放清單同步到你自己的 Google Drive。

$ go install github.com/Tai-ch0802/capy-music/cmd/capy@latest
  • macOS
  • Windows
  • 憑證全部是你自己的

開始使用

三個步驟,由下而上:先讓 capy 能碰到你的音樂平台,再決定要不要把清單同步到雲端。

建立你自己的 Spotify app

capy 不代持任何人的憑證,所以 Spotify 那一半要用你自己的 app。到 Spotify Developer Dashboard 建一個,把 redirect URI 設成 http://127.0.0.1:8888/callback。這裡必須是 127.0.0.1,寫 localhost Spotify 會拒絕。

$ capy auth login spotify
# 精靈會問 client ID,然後開瀏覽器完成授權

試第一個命令

不需要其他設定就能開始用。搜尋會直接印出結果,在終端機裡是對齊的表格,在管線裡是乾淨的 TSV。

$ capy search 派對動物
$ capy play 五月天          # 藝人:播熱門歌曲
$ capy now                  # 現在在播什麼

要同步清單才需要 Google

播放清單的正本存在你自己 Google Drive 的應用程式資料夾裡(只有 capy 看得到,你隨時可以清空)。只有這一步需要登入 Google,而且權限只有三個:身分、電子郵件、應用程式資料夾。

$ capy auth login google
$ capy pl link 通勤 spotify:通勤   # 把平台清單連上來
$ capy pl sync 通勤                # 雙向同步

互動式介面

在終端機裡直接輸入 capy,不帶任何參數。開場的水豚會轉轉耳朵、眨眨眼、把嘴邊的牧草吃短再叼一根。終端機夠大(至少 30 行高)的話牠就留在畫面底部繼續過日子——偶爾眨眼、撥耳朵,隔一陣子吃一根草;打 / 開選單時牠先讓位,執行命令時牠也先讓開。終端機比較小的話,牠大約三秒後定格(按任何鍵可以跳過),之後畫面只有底部四行會變動。不想要任何動畫的話設 CAPY_MOTION=never,牠直接定格、之後一格都不動。不管哪一種,上面那一整片都是終端機自己的捲動區——你打過的命令、它們的輸出、發生過的錯誤都留在那裡,可以往回捲、可以複製。放進管線或 cron 時它仍然只印說明,不會變成一個等你按鍵的程式。

                         _
        ________________( )_____
     .-'                    o   `-.
   .'                           .  \
  /                                 |  ,-"
 |                            ____.'--'
  \                       __.-'
   `.|  |`----------'|  |'
     |__|            |__|

capy · spotify

> pl list
ID                名稱              曲數
p.b16G4rbSY0DzME  日本都會之聲      -
p.JL68l7EhogEeXd  冬日暖調          -

------------------------------------------------------
   派對動物 · 1:23 / 4:09 · MacBook Pro · 音量 50
> _
  space 播放/暫停 · ←→ ±10 秒 · / 命令 · ? 按鍵 · q 離開
  pl list   列出我的播放清單
> pl show   顯示清單內容(不帶參數且在終端機裡會開挑選器)
  pl sync   先 pull 再 push 的一輪:一張表、一次確認
------------------------------------------------------
   派對動物 · 1:23 / 4:09 · MacBook Pro · 音量 50
> /pl s_
  ↑↓ 選 · Tab/⏎ 補齊 · Esc 收起

/ 開命令選單:打字即時過濾,Tab 把命令帶進輸入行讓你補參數。打到完整命令(例如 /pl show 冬日暖調)選單就收起, 直接執行,開頭的 / 會自動拿掉。選單向上長、壓在捲動區前面,不會插進你的歷程。清單是直接從命令樹長出來的,不是另外維護的一份。

在那一行輸入的命令會重新執行 capy 自己,不是在同一個行程裡跑。所以每個子命令都保有它原本的樣子:該有表格的有表格,該問你確認的會問。清單名有空白時用雙引號,例如 pl show "上班 通勤"

讀不到播放狀態時,完整的錯誤會印進捲動區留著,底下那行只留一句短的;連續五次讀不到就停止輪詢,按 r 重新連上。命令列在任何情況下都能用——連不上的時候,你最需要的正是它(doctorauth login)。

網頁介面

capy --web 在你這台電腦上起一個只綁 127.0.0.1 的網頁介面,啟動時印一行帶一次性 token 的網址,在終端機裡會順便替你開瀏覽器(放進管線或背景執行時只印網址)。

打開就是「搬家」:把一個平台的播放清單搬到另一個平台,三步做完。選來源與目的地(每個平台的連接狀態一眼看得到,沒連的可以當場連)→ 挑一個清單、決定建新的還是加進既有的 → 看過要搬哪些歌、確認了才寫入。比對每一首歌的時候有真的進度,搬不過去的歌會逐首列出來。不刪來源、只新增、順序不動;不用付費、沒有曲數上限,因為它在你自己的電腦上用你自己的帳號跑。

先說限制:Apple Music 目前只能當來源;能在目的地建新清單的目前只有 Spotify,搬進本機曲庫只能加進既有的 M3U 檔;第一次連接帳號要花幾分鐘(Spotify 要用你自己建的 app、Apple 要自己複製權杖),換來的是沒有人替你代管憑證。硬碟裡的 M3U 播放清單也可以搬到 Spotify。

其他頁面:我的清單、同步、搜尋、帳號;「進階」裡是主控台(跟終端機一樣可以打任何子命令)、ISRC 查詢(一次問三個平台)與診斷。每一頁的底部一直有正在播放列(播放狀態面板):現在放什麼、進度、播放控制,capy now 的內容都在那裡。頁面上的每一個動作背後都是一條 capy 命令,主控台留著完整紀錄;要確認的事一律由命令自己問,頁面不會替你按。

網頁只在你這台電腦上:只綁 127.0.0.1、不是區網服務,每次啟動產生一次性 token,行程結束網址就失效。憑證不會經過頁面 —— 精靈輸入的 secret 只從瀏覽器送進行程再進 keychain,命令回聲裡的 token 值一律遮成 ***。

一次跑一個命令(第二個會被擋),因為它跟終端機共用同一份 Drive 與本機資料。跑著的時候底部多一列執行狀態:現在在做什麼、跑了多久、它最新印的那一行(比對歌曲時是做到第幾首),旁邊的「中止」隨時可以停(在主控台的命令列按 Ctrl-C 也行);已經答應寫入的命令要按兩次,停在一半可能只寫了一部分。有幾個命令在網頁上不提供:debug 群組、--auto、三個 secret flag(請走精靈)、now --watch(看面板就好);capy update 可以跑,但更新完這個網頁行程還是舊版,會要你重啟。

終端機的互動式介面是重新執行 capy 自己,所以每個子命令都保有它原本的樣子;網頁介面則在同一個行程裡跑並由頁面回答提示。兩條路不同是因為終端機已經有 TTY 可以讓給子行程,瀏覽器沒有。

它能做什麼

下面按主題分組。每個命令在終端機裡是給人看的表格(放不下時儲存格換行、不截斷,ID 永遠完整;比終端機還寬時先開一個檢視窗格:每列一行, 橫向、 上下、g G 頭尾、q 離開,Ctrl-C 則是中止整個命令;離開後表格以換行的形式留在捲動區。帶 --yes 的命令不開窗格,CAPY_PAGER=never 一律不開),在管線裡是 TSV,可以直接餵給 cut 與 awk。

搜尋與播放

  • capy search <關鍵字>搜尋曲目。加 --provider apple 換平台,--limit 控制筆數。
  • capy play <關鍵字>一個入口涵蓋曲目、藝人熱門歌曲、你自己的清單。同名時在終端機開挑選器,在腳本裡則回結束碼 2 並印出候選,不會隨便挑一個播。
  • capy play artist:五月天前綴可以指定類型,artist: pl: track: 三種,等同 --type
  • capy pause / next / prev基本遙控。
  • capy seek 1:23跳到曲目內的位置。長一點的內容用 1:05:30,腳本裡用純秒數 83 也可以。
  • capy vol 40音量 0 到 100。手機與部分喇叭不允許遠端調整,這時候會明講是裝置擋的。
  • capy now現在在播什麼。加 --watch 會持續更新並顯示進度條。
  • capy devices列出可以播放的裝置,配合 play --device 指定。

播放清單

  • capy pl list列出平台上的清單。
  • capy pl show <名稱>看某個清單的曲目。
  • capy pl link <名稱> <平台>:<清單>把平台上的清單連到 capy 的正本。只認你明確指定的,不會自動猜同名清單。
  • capy pl link <名稱> spotify --create在 Spotify 建一個跟正本同名的私人空清單,直接連上。把清單從別的平台複製過來時用它,不必先去 app 裡建。Spotify 上已經有你自己的同名清單時會擋下,改成告訴你怎麼連它。
  • capy pl pull平台的變更拉進正本。先列出要改什麼,你確認後才寫。
  • capy pl push反方向:正本推回平台。前提是這台裝置先前 pull 過,而且平台上沒有還沒拉下來的變更。
  • capy pl sync先 pull 再 push,一張表、一次確認。日常用這個就好。
  • capy pl dedup <名稱>去掉正本裡重複的曲目:同平台 id 或同 ISRC 算同一首,保留第一份、其餘順序不動,再推到可寫的平台;沒有重複就什麼都不寫。capy pl dedup apple:冬日暖調 則直接讀平台清單、只印報告(不碰 Drive、不需要連結),Apple 只讀,照表在 app 裡手動刪。
  • capy pl unlink <名稱> <平台>解除連結,正本內容不動。

這一組命令不帶清單名字直接打,在終端機裡會開挑選器讓你選:pl link 問三次(平台 → 那個平台上的哪個清單,在 Spotify 也可以選「建一個新的空清單」 → 連到哪個正本,這一步也可以當場建一個新的),pl unlink 問兩次。接在管線後面或放進 cron 時不會問,照舊要求你把參數寫齊。

跨平台對應

  • capy resolve把正本裡的曲目對應到各平台的 id。先用 ISRC 精準比對,比不到才用模糊比對,分數夠高才自動寫入。
  • capy resolve --review分數不夠的排成佇列,在終端機裡一筆一筆由你裁決。
  • capy resolve pin <cid> <平台>:<id>手動釘死某個對應,給腳本用。釘成 none 表示這首在那個平台沒有。

設定與維護

  • capy auth login / status / logout三個平台各自的授權。憑證只進作業系統的鑰匙圈,不會寫進設定檔或 Drive。
  • capy doctor一站式診斷:設定、憑證、連線各自哪裡有問題,每項都給可以照做的下一步。
  • capy config get / set / list非機密設定,例如預設平台與本機曲庫目錄。
  • capy export把本機快取的正本原樣印到標準輸出。不碰網路、不碰鑰匙圈。
  • capy update更新 capy 自己。
  • capy completion <shell>產生 shell 補全。

三個平台各自能做什麼

能力差異來自平台本身,不是 capy 偷懶。差在哪裡,命令會直接告訴你,而不是靜靜跳過。

能力 Spotify Apple Music 本機曲庫
搜尋 可以 可以 曲庫內比對
播放遙控 Connect 只有 macOS 不支援
讀取清單 可以 可以 M3U 檔案
寫回清單 可以 尚未開放 可以
建立清單 可以 尚未開放 自己建檔
憑證來源 你自建的 app 你從網頁播放器複製的權杖 不需要

把清單複製到另一個平台

一個命令就好。以 Apple Music 的「公路旅行」複製到 Spotify 為例;Spotify、Apple Music、Google 三個都要先登入。

$ capy migrate 公路旅行 --from apple --to spotify              # 在 Spotify 建一個同名的私人清單,把曲目搬過去
$ capy migrate 公路旅行 --from apple --to spotify:開車歌單      # 或加進既有的清單:接在它原本的曲目後面
$ capy migrate                                                # 不帶參數:逐段挑選來源、清單、目標

它先列出要搬什麼,你確認後才動手;需要新清單時也是確認之後才建。目標原本的順序是前綴,來源的曲目依來源的順序接在後面;來源裡目標已經有的(同一首歌,或同一個 ISRC)略過。永遠不動來源,對目標也只新增:目標有還沒同步的移除或換序時會先擋下來,請你先 capy pl sync。沒在目標平台找到的歌這次不推,終端機裡可以當場一首一首裁決,否則結尾會給你補上的命令。完成後只有目標連著正本(來源不連結,一次性複製);想之後跟著來源的變動,結尾也會給 pl linkpl sync 的命令。例外:正本本來就連著來源(手動流程做到一半)時,來源那半也一起拉進正本、以正本為準,結尾會說兩邊都連著。目標不能是 Apple(目前只讀)。

背後在做什麼:讓兩個平台連到同一個正本,再推過去。想讓兩邊持續同步的話,照下面手動做一次,之後就 capy pl sync

兩邊連到同一個正本

先連 Apple 的清單,正本不存在會自動建立。再用 --create 在 Spotify 建一個同名的私人空清單,連到同一個正本。

$ capy pl link 公路旅行 apple:公路旅行
$ capy pl link 公路旅行 spotify --create

兩邊一起拉一次

不要帶 --provider:Apple 那邊把曲目拉進正本;Spotify 那邊是空的,只記下這台裝置看過它的樣子。少了這一步,後面的 push 會被擋下來。

$ capy pl pull 公路旅行

替每一首找 Spotify 上的同一首歌

有 ISRC 的曲目直接精準比對;沒有的靠標題、藝人、時長模糊比對,分數不夠的排進佇列等你裁決。

$ capy resolve 公路旅行 --provider spotify
$ capy resolve --review        # 上一步有列出佇列才需要

先看,再推

表裡的 skip 列是這次複製不過去的曲目:還沒對應到 Spotify 的歌,通常是你自己上傳到 Apple 的,或 Spotify 上根本沒有的。

$ capy pl push 公路旅行 --provider spotify --dry-run
$ capy pl push 公路旅行 --provider spotify

整個過程不會刪到任何東西:Spotify 那邊是第一次拉,推過去的全是新增。之後兩邊保持連結,Apple 清單有變動時跑 capy pl sync 公路旅行 就會帶過去;只想複製一次的話,用上面的 capy migrate,或完成後 capy pl unlink 公路旅行 apple 解開。反方向(Spotify 到 Apple)目前還做不到:Apple 那一側只讀不寫。

Spotify 的寫入還沒在真帳號上驗證過

建清單與推曲目是照 Spotify 2026 年 2 月的官方文件實作的,還沒有在真的帳號上跑過。遇到 404,或建出來的清單在 app 裡是公開的,請回報。

本機曲庫

硬碟裡的 M3U 檔案也可以當成一個平台,跟 Spotify 雙向同步。它綁在這台機器上:換一台電腦,那邊的 capy 會跳過這個連結,不會把它當成清單被刪掉了。

$ capy config set local_root ~/Music/playlists
$ capy pl link 通勤 local:通勤.m3u8
$ capy pl sync 通勤

曲目的中繼資料放在同一個目錄的 library.json 裡,由你自己維護。有填 ISRC 的曲目才能跟串流平台上的同一首歌自動對上,沒填的就是各自獨立的一首。寫回時是整檔重寫,別的工具寫在 M3U 裡的註解與 #EXTINF 會被蓋掉。

幾件先知道比較好的事

你的清單正本在你自己的 Drive

不是在我們的伺服器上,因為沒有伺服器。本機的 SQLite 只是快取:刪掉它,下一次執行會從 Drive 完整重建。

刪除永遠要先看過

任何會刪掉清單曲目的操作都會先列出來讓你確認,而且超過門檻時會直接擋下來,要加 --force 才放行。--dry-run 可以只看不做。

清單順序是你的記憶

capy 沒有任何路徑會排序或打亂清單:同步只在平台自己重排時才跟著動,去重只拿掉後出現的那份,沒動到的曲目相對順序永遠不變。

Apple Music 的權杖是你從網頁複製的

那不是 Apple 官方支援的用法,會過期,風險由你自己承擔。capy 只會指導你怎麼複製,不會去讀你的瀏覽器 cookie,也不會注入任何指令碼。

Apple Music 目前只讀不寫

寫回 Apple 的清單還沒開放,要先驗證過那組 API 真的能移除與重排曲目。在那之前,pl push --provider apple 會明講不支援,--all 則會跳過它並說明原因。

每個命令都能放進管線

不在終端機的時候一律輸出純文字 TSV,沒有顏色也沒有互動提示。結束碼有意義:0 成功,1 錯誤,2 需要你介入,3 是安全閥擋下來了。