ccstory · GTM 教材
把你的 Claude Code 一週,
翻成一份能讀的故事。
ccusage 告訴你花了多少;ccstory 告訴你花在什麼上。
這份教材帶你看一遍:第一次安裝 → 初始化 → 日常使用 → 改類別 → 匯出,
每個指令對應到什麼、預期長怎樣、想改的時候怎麼改。
PAIR WITH
ccusage — 這週你花了 $1,608
→
YOU ARE HERE
ccstory — 那 $1,608 是花在 coding 53% / writing 30% / research 17%
00 · 一個週日晚上的故事
場景
晚上 9 點半。週日。你開啟筆電,想寫週報。
回頭翻 git log 也沒用,提交訊息只寫了「fix」。Slack 訊息太雜,
Claude Code 的 scrollback 滾不完。你只記得:好像有花一整個下午搞一個 bug,
還有一篇沒寫完的 newsletter 草稿 ⋯⋯ 但講不清楚這週的時間到底花在哪。
你打開 terminal,跑 ccstory week。
8 秒後,一份 「coding 53%, writing 30%, research 17%」
的 recap 跳出來,每個 bucket 還有 2-3 句總結你這週實際做了什麼。
週報十分鐘寫完。
↑ 這份教材會把你帶到「跑完那 8 秒、看著結果就能交差」的狀態。
01 · 整體用戶流程圖
ccstory 的整個生命週期可以縮成 5 個階段。前 2 個只做一次,後 3 個你每週都會跑。
1
Install
pipx install ccstory
一次
2
Init
Quick / Deep / Skip
選一個分類策略
一次
3
Run
ccstory week
ccstory month
每週 / 每月
4
Read & React
看 recap,發現有 bucket 分錯
不定期
5
Customize
category set / unset
--refresh
改完規則同步
↓↓↓↑ 回到 3
關鍵設計:步驟 3 平均 5-10 秒就跑完(瞬時 fallback 模式)。
只有當你主動加 --llm-narrative 才會走到 ~40 秒/session 的 polish 路徑。
這是 ccstory 故意保留「打開即用」與「願意等 polish」兩條路。
02 · 安裝 + 第一次跑
前置需求
| Python 3.11+ | 標準庫的 tomllib 在 3.11 才有 |
| pipx | brew install pipx |
| Claude Code CLI | 可選;只有 LLM 旁路需要 |
沒有 claude 在 PATH 上也能跑,只是 --llm-narrative
/ --classify content 會自動降級成 fallback 路徑。
三行裝起來
~ — zsh
$ pipx install ccstory
installed package ccstory 0.x.x
$ ccstory init
Set up classification:
[Y] Quick — Infer from folder names + samples (~10s)
[n] Deep — Classify recent sessions individually (~1 min)
[s] Skip — Use built-in keyword defaults only (no LLM)
$ ccstory week
第一次跑就會看到「First run — default bucket preview」表格,
告訴你目前 ~/.claude/projects/ 下的資料夾在 built-in 規則底下被分到哪些 bucket。
這張表只在第一次出現,目的是讓你立刻看出哪些 folder 名稱沒匹配到、需要手動 pin。
第一次跑會生出哪些檔案
讀
Claude Code 的 session log
~/.claude/projects/**/*.jsonl
只讀本機,不送出任何東西。
寫
設定 + 快取
~/.ccstory/config.toml
~/.ccstory/cache.db
SQLite,session summary 快取。
產出
Markdown 報告
~/.ccstory/reports/recap-2026-W19.md
每跑一次蓋掉同期間的舊報告。
03 · init 三模式選擇
ccstory init 是一次性步驟,三種模式對應三種使用者狀態。
不確定就選 Quick,事後可以隨時重跑換模式。
Quick
[Y] / --quick
~10s
看 folder name + 樣本訊息,丟給 claude -p 跑一次,產出 bucket → [folders] 規則。
適合誰
folder 名稱本身就有意義
stock-dashboard、rednote-analysis、news_analysis
產出
→ ~/.ccstory/config.toml
Deep
[n] / --deep
~1-3 min
取樣最近 7 天、最多 200 個 session,每個 session 都丟給 LLM 看內容分類;最後 majority vote 寫回 folder 規則。
適合誰
folder 是品牌名 / catch-all
ccstory、personal-os、~/scratch
產出
→ config.toml + cache.db (per-session)
Skip
[s] / --skip
瞬時
不打 LLM,只 scaffold 一份空的 config.toml。後續完全靠 built-in keyword 規則。
適合誰
不想連 Claude Code、想完全離線、或之後再手動編 config
產出
→ ~/.ccstory/config.toml (template)
Init 互動的真實樣子
ccstory init
$ ccstory init
Set up classification:
[Y] Quick — Infer categories from folder names + sample messages (~10s)
[n] Deep — Classify recent sessions individually (~1 min, last 7d, cap 200)
[s] Skip — Use built-in keyword defaults only (no LLM)
Choose [Y/n/s]: Y
Scanning past 30 days of sessions…
✓ Found 12 unique projects with sample messages.
Asking claude -p to suggest category buckets (one shot, ~10s)…
┌─ Proposed category buckets ─────────────────────────────────────┐
│ Bucket │ Count │ Projects │
├──────────────┼───────┼───────────────────────────────────────────┤
│ coding │ 6 │ ccstory, mcp, n8n, food-detect, … │
│ writing │ 3 │ rednote-analysis, crewai_xhs, … │
│ investment │ 2 │ stock, options-research │
│ other │ 1 │ playground │
└──────────────┴───────┴───────────────────────────────────────────┘
✓ Wrote /Users/you/.ccstory/config.toml
Re-run `ccstory week` to see your sessions categorized.
--dry-run 先看不寫:如果你怕被覆蓋舊 config,加
ccstory init --quick --dry-run 會跑完整提案但不寫檔。
Quick / Deep 都會自動備份舊 config 到 config.toml.bak-timestamp。
04 · 日常指令對照表
每一條都標出:你會打什麼 / 預期看到什麼 / 如果結果不喜歡,怎麼改。
主流程:產報告
| 指令 |
預期看到 |
不喜歡的話可以怎麼改 |
ccstory |
當月至今的 recap(預設窗口) |
改成 ccstory week / ccstory 2026-04 換時間窗口 |
ccstory week |
過去 7 天的 recap + vs 上週對比 |
對比覺得多餘:--no-compare;只想要數字差不要旁白:--no-compare-narrative |
ccstory month |
當月 recap + vs 上月對比 |
同上 |
ccstory 2026-04 |
指定月份 recap(含對比上月) |
查歷史專用,YYYY-MM 格式 |
ccstory all |
全歷史總覽(不含對比) |
看自己跑了多久、累積花了多少 |
ccstory trend |
近 8 週的 sparkline + 燃燒率 |
--weeks 12 或 --months 6 自訂範圍 |
調整輸出 flag
| Flag | 作用 | 什麼時候用 |
--minimal |
純數字 card,不要 per-session 旁白 |
你只想看「這週多忙」,不需要故事 |
--llm-narrative |
每個 session 都丟給 claude -p 潤稿(~40s/session) |
要寫年度回顧、想要每一行都是完整一句話 |
--no-aggregate |
跳過「每 bucket 一段 2-3 句總結」 |
覺得 AI 總結太囉嗦、只要 per-session 行 |
--no-compare |
不跑「vs 上一期」對比區塊 |
剛裝、上週還沒資料;或不想看燃燒對比 |
--for=obsidian |
輸出 YAML frontmatter + [[wikilinks]] |
把 recap 直接拖進 Obsidian / PKM vault |
--reports-dir PATH |
覆寫 ~/.ccstory/reports/ 預設位置 |
想存到 iCloud / Dropbox 同步 |
典型輸出長這樣
ccstory week
$ ccstory week
Window: 2026-05-12 → 2026-05-19 (2026-W20)
✓ 74 sessions · 3,692 turns
╭──────────────── Claude Code Recap · May 12 – 19, 2026 ────────────────╮
│ │
│ ★ Top focus coding 10.9h (53% of active time) │
│ ↳ Built /show-routine slash command using bash+python to fetch… │
│ │
│ Active 20.6h Sessions 74 Output 2.92M │
│ Turns 3,692 Cache 96% Cost $1,608 │
│ │
│ Time by category │
│ coding ███████████████░░░░░░░░░░░░░ 10.9h 53% │
│ writing █████████░░░░░░░░░░░░░░░░░░░ 6.2h 30% │
│ research █████░░░░░░░░░░░░░░░░░░░░░░░ 3.5h 17% │
│ │
│ Full report → ~/.ccstory/reports/recap-2026-W20.md │
│ │
╰────────────────────────────── ccstory ────────────────────────────────╯
Bucket looks wrong? `ccstory category set <bucket> <keyword>` to pin a project,
then re-run with `--refresh`.
終端機卡片只是預覽;完整版含 per-bucket 2-3 句 synthesis 和 per-session 一行記錄,
都在 markdown 報告裡。卡片底下那行 「Bucket looks wrong?」
breadcrumb 是故意放的——多數人是看到 bucket 分錯,才會想起來去改規則。
05 · 資料流:jsonl → recap
跑一次 ccstory week,底下發生的 7 個動作:
[1] Parse
Read ~/.claude/projects/**/*.jsonl
→ 切出每個 session 的 (start, end, project, turns, tokens)
[2] Window filter
留下 [since, until] 區間內的 session(本地時區、午夜對齊)
[3] Backfill summaries
每個 session 一行旁白:預設用第一句 user message;--llm-narrative 才走 claude -p
[4] Resolve buckets
按 hybrid / folder / content 策略,把每個 session 指派到一個 bucket
[5] Rollup
把 sessions 依 bucket 加總,算出 active hours、cost、turns
[6] Synthesis (optional)
一次 claude -p 寫出整段「3 句 overall narrative」
[7] Render
終端機卡片 + markdown 報告寫進 ~/.ccstory/reports/recap-*.md
關鍵時間計算:5 分鐘 gap heuristic。連續訊息間隔 ≤ 5 分鐘才算「還在鍵盤前」,
跳過去太久就斷成下一段 active block。並行 session 用 wall-clock dedup 不會重複計入。
這個演算法不精準但 跨期可比較,這是 ccstory 報告能拿來做 vs-previous 對比的基礎。
06 · 類別錯了怎麼改
這是用戶第一次發現 ccstory 「有沒有靈魂」的時刻。預設規則沒命中你的專案、品牌名 folder 被丟進 coding,
這時你會去改規則——分兩條路:
路徑 A:CLI 改(推薦)
ccstory category
$ ccstory category list
No user-defined rules yet. Built-in defaults apply.
$ ccstory category set research ai-project
✓ Added `ai-project` → research
Invalidated 2 per-bucket narrative(s) + 1 vs-previous narrative(s)
$ ccstory category set work company-repo internal-tool
✓ Added `company-repo`, `internal-tool` → work
$ ccstory category list
┌─ User rules · ~/.ccstory/config.toml ──────────────┐
│ Bucket │ Keywords │
├───────────┼─────────────────────────────────────────┤
│ research │ ai-project │
│ work │ company-repo, internal-tool │
└───────────┴─────────────────────────────────────────┘
適合:偶爾改一兩條 keyword
路徑 B:直接編 config.toml
~/.ccstory/config.toml
# ccstory category overrides
# Built-in defaults: coding, investment, writing, other.
default_bucket = "coding"
monthly_quota_usd = 3500
[categories]
"work" = ["company-repo", "internal-tool"]
"writing" = ["blog", "newsletter", "xhs"]
"research" = ["ai-project", "reading-notes"]
[prices.opus]
input = 15.0
output = 75.0
適合:一次重排所有 bucket、要設客製定價
match 順序很重要:
user 自訂規則 優先匹配,沒命中才回退到 built-in 預設(coding / investment / writing / other),
全部都沒中才掉到 default_bucket(預設 coding)。
所以你只要寫「不在預設範圍內」的東西就好——不需要重抄一份 coding 關鍵字。
改完之後一定要做的事:--refresh
apply rule changes retroactively
$ ccstory category set research ai-project
✓ Added `ai-project` → research
# 注意:剛剛這條會清掉 narrative 快取,但 per-session bucket 快取
# 不會自動清——因為那些是用 session_id 當 key 存的,
# 用舊 LLM 結果不會錯,只是不會反映你新加的規則。
$ ccstory week --refresh
Refreshed 74 cached bucket(s) in this window, 1 aggregate(s)
# 想清光整個快取就用 --refresh-all(一般不需要)
$ ccstory month --refresh-all
| Flag | 清掉什麼 | 什麼時候用 |
--refresh |
本次窗口的 per-session bucket 快取 + 該期間的 aggregate |
改完 category 規則、看本週/本月 |
--refresh-all |
整個 content-classification 快取 |
大改規則、懷疑快取整體有問題 |
07 · 三種分類策略(--classify)
決定「一個 session 屬於哪個 bucket」的演算法,三種選擇。
日常用 hybrid(預設)就好;遇到品牌名 folder 多的情況再換。
folder
--classify folder
只看 folder 名稱 + config 規則。
完全離線,最快。
適合
folder 命名都很清楚的人;不想呼叫 claude -p
缺點
ccstory、scratch 這種 folder 名只能歸到 default_bucket
content
--classify content
每個 session 都看內容,丟給 claude -p 重判。
會用快取,重複跑免費。
適合
「我這個 folder 什麼都做」、混雜情況多
缺點
第一次跑要等 batch LLM;user 規則的覆寫也被無視
hybrid
--classify hybrid DEFAULT
user 規則命中 → 用 folder bucket;沒命中 → fallback 到 content。
適合
99% 的人;兼顧速度與精準
邏輯
你 pin 的,永遠優先;其餘混雜的,交給 LLM 判斷
記得 trend / week / month 要一致:
ccstory trend 跟 ccstory week 都接受 --classify,
兩邊用不同模式會讓 vs-previous 對比變奇怪。預設 hybrid 已經夠好,建議不要亂改。
08 · config.toml 全解
所有客製都集中在這個檔案:~/.ccstory/config.toml。
分四個區塊。
~/.ccstory/config.toml — annotated
# ──────────── ① 全域設定 ────────────
default_bucket = "coding" # 沒命中任何規則時的 fallback
monthly_quota_usd = 3500 # trend 的 burn% 基準(Max 20x ≈ $3500/mo)
# 設 0 隱藏 burn% 那一行
# ──────────── ② 自訂分類規則 ────────────
[categories]
"work" = ["company-repo", "internal-tool"]
"writing" = ["blog", "newsletter", "xhs"]
"research" = ["ai-project", "reading-notes"]
# 注意:keyword 是「folder 名稱的子字串」,
# 不是 regex。"xhs" 會命中 "rednote-xhs"、"xhs-mcp"。
# ──────────── ③ 價格 snapshot ────────────
[prices]
snapshot_date = "2026-04" # 寫進報告 footer,避免價格漂移悄悄發生
[prices.opus]
input = 15.0
output = 75.0
cache_write = 18.75
cache_read = 1.5
[prices.sonnet]
input = 3.0
output = 15.0
# ──────────── ④ 新模型(自己加) ────────────
[prices.custom]
input = 5.0
output = 25.0
# 沒寫的 key 會預設 $0 並印警告——是故意的,
# 因為「悄悄變 0」是 ccstory 過去踩過的雷。
| 區塊 | 什麼時候改 |
default_bucket |
你不是工程師、不希望雜項都掉進 coding;改成 "other" 或自訂 bucket |
monthly_quota_usd |
你用的是 Max 5x(≈ $875)或 Pro(≈ $175),調這個讓 burn% 反映真實額度 |
[categories] |
folder 名沒被 built-in 規則命中、要 pin 專案到自訂 bucket |
[prices.*] |
Anthropic 改價、你用第三方 proxy 有不同價格、想模擬 future pricing |
09 · 快取 / 重整流程
ccstory 用 SQLite 在 ~/.ccstory/cache.db 存三種東西。理解快取邊界 → 知道什麼時候要重整。
Session summaries
每個 session 一行旁白。Key = session_id。改規則 不會 失效。
手動清:刪 cache.db 重跑。
Per-session buckets
LLM 內容分類的結果。Key = session_id。改規則 不會自動失效。
手動清:--refresh / --refresh-all
Aggregate narratives
「per-bucket 3 句總結」、「vs 上週 1-2 句旁白」。Key = 時期 + 規則指紋。改規則會自動失效。
下次跑就會重生。
決策樹
剛改完 category 規則,下一個指令是?
├─ 你的改動會影響「品牌名 / 含混 folder」?
│ ├─ 是 → ccstory week --refresh (清本週快取,下次跑會走 LLM 重判)
│ └─ 否 → ccstory week (folder rule 命中是即時的,不用清快取)
├─ 改了一大堆規則,懷疑全亂掉?
│ └─ ccstory month --refresh-all (保險起見全清)
└─ 想避開 LLM 路徑?
└─ ccstory week --classify folder (不碰快取,只看 folder)
10 · 匯出到 Obsidian / PKM 工作流
一行加 --for=obsidian,markdown 自動戴上 YAML frontmatter +
[[wikilinks]],丟進 Obsidian vault 立刻能用 Dataview / Bases 查。
--for=obsidian
$ ccstory week --for=obsidian --reports-dir ~/Obsidian/recaps
✓ 74 sessions · 3,692 turns
Full report → ~/Obsidian/recaps/recap-2026-W20.md
recap-2026-W20.md (頭部)
---
date_start: 2026-05-12
date_end: 2026-05-19
active_hours: 20.6
top_focus: coding
buckets: [coding, writing, research]
cost_usd: 1608.42
output_tokens: 2920000
---
## coding
Shipped the [[show-routine]] slash command end-to-end —
bash+python wrapper to surface scheduled-task output, plus a
routine-detail bookmark flow after the live debug session on Wednesday.
- 2026-05-10 03:24 · 123m · 212 msg — Built [[show-routine]] slash …
- 2026-05-08 12:30 · 67m · 294 msg — Debugged hook race condition …
Obsidian Dataview 例:
WHERE top_focus = "coding" AND active_hours > 15 →
篩出「主力 coding 且該週超忙」的紀錄。Bucket 名含特殊字元(如 client: acme)會自動 JSON 引號化,frontmatter 不會壞。
11 · 常見問題排查
跑出來 bucket 都是 coding,看不出差別
兩種可能。①你 folder 命名都用品牌名(ccstory、my-app),built-in keyword 沒命中 → fallback 到 coding。
改法:ccstory init --deep 讓 LLM 看內容分;或手動 ccstory category set writing my-app。
②你 default_bucket = "coding",把 fallback 改成 "other" 就會立刻看出差別。
改了 config.toml 但 recap 還是舊樣子
per-session bucket 快取沒清。跑 ccstory week --refresh。
如果連 narrative 都沒換(顯示舊的 3 句總結),那是 aggregate 快取,
不過改 category 會自動 invalidate aggregate,正常下次跑就會重生。
--llm-narrative 很慢,ETA 顯示要 30 分鐘
這是正常的(~40s/session cold start)。三條解法:
①Ctrl+C 取消,改用預設的瞬時 fallback;
②先跑 ccstory week --minimal 看數字;
③晚上睡前讓它跑,把 markdown 報告當隔天的素材。
claude 不在 PATH 上,--llm-narrative 沒效果
ccstory 會印 「claude not on PATH — fallback to first user message」 警告然後降級。
不會 crash,只是每行 session 旁白變成「第一句 user 講啥」。要完整功能,裝 Claude Code CLI。
想看某個專案到底被分到哪
看終端機卡片只能知道整體比例,看 markdown 報告才有 per-session 列表。
cat ~/.ccstory/reports/recap-*.md | grep -i my-project
最快。或直接 ccstory week --classify folder 把 LLM 旁路關掉,純看 folder 規則匹配結果。
報告裡的 cost 跟 ccusage 對不起來
兩種差異來源。①ccstory 跨期對比用 output tokens(不用 total_tokens,因為 96% 是 cache_read,會隨輪數膨脹失真)。
②價格 snapshot 不同。看報告 footer 「Prices as of 2026-04」確認你的 snapshot;
改 [prices.opus] / [prices.sonnet] 對齊 ccusage 取的價就會一致。
想自動化每週日跑一次
cron 一條:0 21 * * 0 ccstory week --for=obsidian --reports-dir ~/Obsidian/recaps。
所有 LLM 呼叫都用你本機的 claude -p,不需要 API key、不會跑出網路。
12 · GTM 重點 / 為什麼這個工具會被傳
上面是用戶角度的教學;下面是給你做推廣決策時的彈藥。
三句話定位
① 跟 ccusage 配對:「ccusage 是帳單,ccstory 是故事。」
這是最容易讓 ccusage 用戶轉介的鉤子——你已經告訴他花了多少,自然會想知道花在哪。
② 週日反思 / 週報場景:所有 Knowledge worker 共通的「我這週幹嘛了」的問題。
每週重複觸發的場景,不是一次性 novelty。
③ 本機跑、無遙測:
「verify in session_summarizer.py」 的直球邀請審查。
隱私焦慮的工程師會自己驗,驗完會傳。
三個流量入口
① ccusage README 互引——這是已知最大流量源。
ccusage 用戶通常是 power user,會去看 sibling tool。
② Sunday-night reflection 內容——
部落格、Twitter「Claude Code week in review」這種貼文配截圖,
ccstory 的 recap card 自帶截圖友好的視覺。
③ Obsidian / PKM 圈——
--for=obsidian + YAML frontmatter +
Dataview 查詢的組合,是 PKM 社群最容易上手的 hook。
傳給朋友時的 30 秒 demo 腳本
30s demo
「你不是常常週日寫不出週報嗎?看,pipx install ccstory。」裝 10 秒。
「ccstory init,選 Quick。」讀完你的 folder,10 秒生出規則。
「ccstory week。」跳出一張卡片,告訴你這週 coding 53% / writing 30% /
research 17%,每塊還有 2-3 句總結你實際幹了啥。週報自動寫完。」
→ 全程不到 1 分鐘,全部跑在本機,不送任何資料出去。
競品差異(README 已有但放這裡好引用)
| ccusage | ccstory |
| 角色 | 帳單 | 故事 |
| Active hours(5 分鐘 gap) | — | ✓ |
| 類別分桶(folder + 內容) | — | ✓ |
| Per-session 旁白 | — | ✓ via 本機 claude -p |
| Per-bucket 總結 | — | ✓ |
| 跨期對比旁白 | — | ✓ |
| 本機 / 無遙測 | ✓ | ✓ |
roadmap 提示(README 已列)
- 更多匯出格式(Logseq、Notion)
- PNG card 匯出(直接做成截圖貼社群)
ccstory year——年度回顧,Spotify Wrapped 風格
- Git commit / PR 跟 session 關聯