5 min read

我把 Claude Code 的工作狀態變成了武俠修煉場

我把 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/ 底下。後端做的事情很單純:

  1. 掃描 — 每 0.5 秒掃一次所有 .jsonl 檔案(只看最近 5 分鐘修改過的)
  2. 解析 — 讀取新增的行,判斷 agent 正在做什麼
  3. 分類 — 根據 tool_use 的工具名稱,分成 reading / writing / running / thinking / done
  4. 提供 API — 一個簡單的 /api/state JSON 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