我把 Claude Code 的工作狀態變成了武俠修煉場
起心動念
某天在 GitHub 上看到 pixel-agents 這個專案 — 用像素風小人來呈現 AI agent 的工作狀態,覺得很有意思,不過看著看著就想:如果是中文世界的開發者,用武俠風格?
於是「武俠修煉場」就誕生了。
原始碼:github.com/pcc402-art/wuxia-monitor

概念:把 Coding 變成修煉
Claude Code 在幫你工作的時候,其實一直在切換不同的動作:讀檔案、寫程式碼、跑指令、思考下一步... 這些動作對應到武俠世界,就變成了:
| 寫程式的你看到的 | 武林弟子看到的 |
|---|---|
| 讀檔案(Read / Grep) | 📜 翻閱秘笈 |
| 寫檔案(Write / Edit) | ⚔ 出劍攻伐 |
| 跑指令(Bash) | 💨 施展輕功 |
| 思考中 | 🌀 運功催動 |
| 閒置 | 🧘 打坐修煉 |
| 完成任務 | ✨ 大功告成 |
角色名字也都從金庸小說裡取的 — 令狐沖、張無忌、蕭峰、小龍女... 每個 agent 進場就隨機分配一個武俠名字和一種顏色的袍子。
技術架構
整個專案只有兩個主要檔案:
Python 後端(wuxia-monitor.py)
Claude Code 在工作時會把所有操作寫成 JSONL 格式的 transcript 檔案,存在 ~/.claude/projects/ 底下。後端做的事情很單純:
- 掃描 — 每 0.5 秒掃一次所有
.jsonl檔案(只看最近 5 分鐘修改過的) - 解析 — 讀取新增的行,判斷 agent 正在做什麼
- 分類 — 根據
tool_use的工具名稱,分成 reading / writing / running / thinking / done - 提供 API — 一個簡單的
/api/stateJSON endpoint
判斷邏輯其實就是看 tool 名稱裡有沒有關鍵字:
if any(w in tool_lower for w in ["read", "glob", "grep", "search"]):
return "reading", tool
if any(w in tool_lower for w in ["write", "edit", "patch"]):
return "writing", tool
if any(w in tool_lower for w in ["bash", "exec", "run", "shell"]):
return "running", tool
有個小細節花了不少時間 debug:Claude Code 的 tool_result 回傳(type=user 且 content 包含 tool_result)不應該覆蓋狀態,否則角色會在「翻閱秘笈」和「運功催動」之間不停閃爍,因為每次工具回傳都會被誤判為「使用者輸入 → thinking」。
Canvas 前端(index.html)
一個單檔 HTML,內嵌 CSS 和 JS,不依賴任何框架。
前端每 500ms 輪詢一次 /api/state,根據回傳的 agent 列表更新畫面。角色用 Canvas 2D 繪製在 760×400 的設計座標系上,再透過 devicePixelRatio 縮放到實際螢幕大小,支援 HiDPI。
角色圖是用 Google Gemini 生成的 PNG,6 種顏色 × 7 種狀態 = 42 張角色圖 + 1 張背景圖,原始圖片 41MB,用 Pillow 壓縮到 1.2MB(縮小到 256×256 + 256 色量化),畫質幾乎看不出差異。
開發過程中解決的問題
問題一:角色重疊
最初的設計是每個狀態對應一個固定區域,區域裡有幾個預設的站位。問題是:如果所有 agent 都在思考,六個人就擠成一團。
最後的解法是「軸心擴散」— 每個區域有一個中心點,多人時以中心為圓心等角排列,人越多圈越大:
function getExpandedPosition(zone, agentIdx, totalInZone) {
if (totalInZone <= 1) return { x: zone.cx, y: zone.cy };
const radius = 50 + totalInZone * 10;
const angle = (agentIdx / totalInZone) * Math.PI * 2 - Math.PI / 2;
return {
x: zone.cx + Math.cos(angle) * radius,
y: zone.cy + Math.sin(angle) * radius * 0.45, // Y 壓縮做透視
};
}
6 個區域排成 3×2 網格,上排放靜態狀態(打坐、運功、讀經),下排放動態狀態(完成、出劍、輕功),蠻符合武俠的意境。
問題二:偵測不到 subagent
Claude Code 的 transcript 結構是這樣的:
- 主 session:
~/.claude/projects/{project}/{uuid}.jsonl - subagent:
~/.claude/projects/{project}/{uuid}/subagents/agent-{id}.jsonl
一開始所有 subagent 都被當成同一個人,因為 JSONL 裡的 sessionId 都指向父 session,後來改成用檔名作為 agent ID 才解決。
問題三:狀態閃爍
Claude Code 每次呼叫工具後,transcript 會寫入一筆 tool_result(type=user)。如果不特別處理,這筆紀錄會讓狀態從「翻閱秘笈」跳回「運功催動」再跳回「翻閱秘笈」,造成角色在兩個區域之間反覆跑。
修法是讓 tool_result 回傳 None,保持前一個狀態不變。
最後
整個專案大概花了一個下午完成(用 Claude Code 開發 Claude Code 的監控工具,有點遞迴的味道)。
如果你也在用 Claude Code,歡迎試玩看看:
git clone https://github.com/pcc402-art/wuxia-monitor.git
cd wuxia-monitor
python3 wuxia-monitor.py
# 開瀏覽器到 http://localhost:3000
然後在另一個終端機開 Claude Code 做事,就能看到你的武林弟子在修煉場裡翻閱秘笈、出劍攻伐了。
原始碼:github.com/pcc402-art/wuxia-monitor
Member discussion