subs — SaaS 訂閱支出分析器
分析使用者從銀行/信用卡 CSV 匯出檔和電子郵件收據中的重複性訂閱支出。產出支出摘要、標記浪費、追蹤續約,並推薦節省方案。
帳本是主幹
工作區中的 subscriptions.yaml 是單一事實來源。每次執行都會將新資料調節(reconcile)進去——絕不從頭重新推導。這是實現續約追蹤和跨執行一致性的關鍵,也讓「浪費」可計算(一個訂閱連續扣款數月後突然消失 = 已失效或值得取消)。切勿整體覆寫帳本;應進行調節。
帳本條目結構(每項訂閱一個條目):
- vendor: GitHub # 規範名稱
amount: 4.00 # 最近一筆扣款
currency: USD
cycle: monthly # weekly | monthly | quarterly | semiannual | annual
category: Dev tools
first_seen: 2025-01-12 # 最早已知扣款的 ISO 日期
last_seen: 2026-06-03 # 最近一筆扣款的 ISO 日期
next_renewal: 2026-07-03 # last_seen + 一個週期
status: active # active | price_hike | lapsed? | cancelled
notes: "自註冊以來一直為 4.00"
先決條件:Gmail 連接器
此技能透過Gmail 連接器/MCP(例如 Claude Code 的 Gmail 連接器)讀取來自 Gmail 的訂閱收據,該連接器需可供您的程式碼代理使用。在步驟 1 之前,請確認您的代理具備 Gmail 搜尋/讀取工具(一組 search_threads / get_thread 或等效功能)。如果沒有可用的 Gmail 整合,請停止並告知使用者啟用一組,然後重新執行此技能。詳細資訊和查詢方式請參閱 email-receipts.md。
流程
請依序執行以下步驟。在步驟 5 完成前請勿做報告。
0. 定位工作區
使用目前的工作目錄作為工作區。確保 data/statements/、data/receipts/ 和 reports/ 存在(若缺少則建立)。如果 subscriptions.yaml 存在則載入它;否則將帳本視為空白。
完成條件: 工作區目錄已存在且帳本已載入(可能為空白)。如果 data/statements/ 為空且尚無 subscriptions.yaml,且使用者未使用 Plaid(下一節),請告知使用者將他們的銀行/信用卡 CSV 匯出檔放入 data/statements/ 並停止——CSV 是重複性偵測的主幹。
1. 收集輸入
透過 Plaid CLI 取得銀行資料(首選——無需手動 CSV 匯出):確保 CLI 已就緒,並將交易記錄拉取到 data/statements/plaid-transactions.csv,操作方式參考 plaid.md。否則依賴使用者放入 data/statements/ 的 CSV。
然後列出 data/statements/ 中的每個 CSV。從 Gmail 中提取訂閱收據,操作方式參考 email-receipts.md,並同時讀取 data/receipts/ 中任何補充的 .eml/.txt 檔案。
完成條件: data/statements/ 中的每個 CSV 都已枚舉,且 Gmail 收據搜尋已返回(或在缺少連接器時停止執行)。
2. 偵測重複性扣款
對每個對帳單 CSV(包括從 Plaid 匯出的)執行確定性偵測器——請不要手動檢查列。 是此技能本身的目錄(在 Claude Code 中:~/.claude/skills/subs/):
python3 <skill-dir>/scripts/detect_recurring.py data/statements/*.csv
對於 低 信心的候選項目以及商家名稱標準化的邊緣情況,請參考 recurrence-detection.md。將這些候選項目與步驟 1 中收集的 Gmail 收據結合——收據可以捕捉短期對帳單遺漏的年度訂閱,並識別模糊的描述。
完成條件: 每個重複性候選項目都有商家、頻率、金額和最後出現日期。
3. 調節至帳本
將候選項目調節到 subscriptions.yaml 中:
- 新商家 → 新增一個條目;透過 categories.md 進行分類。
- 已有商家 → 更新
last_seen和next_renewal;如果金額上漲,將status: price_hike並在notes中記錄舊金額。 - 存在於帳本但近期資料中未出現(距離今天約 1.5 個週期內無扣款)→ 設定
status: lapsed?。
完成條件: 每個帳本條目的 status 皆為 active | price_hike | lapsed? | cancelled 之一,且每個候選項目對應到恰好一個帳本條目。
4. 分析
從調節後的帳本計算以下四項:
- (a) 支出摘要 — 月度總額和年化總額,按類別、商家和計費週期分組。將每個條目標準化為月度金額($/月):年繳 ÷ 12,半年繳 ÷ 6,季繳 ÷ 3,月繳 × 1,雙週繳 × 2.17,週繳 × 4.33,半月繳 × 2。報告會重複使用此 $/月(單一事實來源)。
- (b) 浪費 — 重複(同一服務兩次)、重疊工具(同一類別中做相同事情的兩個產品)、價格上漲(
status: price_hike)以及已失效/未使用(status: lapsed?)。 - (c) 即將到來的續約 —
next_renewal在未來 60 天內的條目,按時間從近到遠排列。 - (d) 節省建議 — 年繳 vs 月繳切換、降級、整合及取消。每項建議必須引用一個帳本條目和具體的金額影響。
完成條件: 所有四項都已產出,且每個建議都引用了一個條目 + 一個金額數字。
5. 報告
儲存帳本,然後從中寫入兩種報告:
- Markdown 報告
reports/<YYYY-MM-DD>-subscriptions.md,格式參考 report-template.md; - 一份自包含的 HTML 儀表板
reports/<YYYY-MM-DD>-subscriptions.html,格式參考 html-report.md,並將其開啟(open <path>)。
然後在聊天中呈現簡潔摘要(總金額 + 前三項行動建議)。
完成條件: 兩種報告都包含支出摘要、浪費標記、即將到來的續約和排序後的建議,且 subscriptions.yaml 已儲存。