下面我們來開發使用 claude code 的效率指標圖表功能

效率指標計算器

目標:計算每個 session 的效率分數,找出你的高效與低效 session

新增效率指標模組

新增 lib/efficiency.mjs

import { extractToolCalls } from './analytics.mjs';

/**
 * 計算 session 效率指標
 */
export function calcEfficiencyMetrics(messages) {
  const turns = messages.filter(m => m.type === 'assistant').length;
  const userMsgs = messages.filter(m => m.type === 'user').length;

  // 工具呼叫統計
  const allToolCalls = extractToolCalls(messages);
  const toolCalls = allToolCalls.length;

  // 工具錯誤數
  let toolErrors = 0;
  for (const msg of messages) {
    if (msg.type !== 'user') continue;
    for (const c of msg.message?.content ?? []) {
      if (c.type === 'tool_result' && c.is_error) toolErrors++;
    }
  }

  // 重複修改的檔案數
  const editCounts = {};
  for (const call of allToolCalls) {
    if (['Edit', 'Write', 'MultiEdit'].includes(call.name)) {
      const fp = call.input?.file_path ?? 'unknown';
      editCounts[fp] = (editCounts[fp] ?? 0) + 1;
    }
  }
  const repeatedEdits = Object.values(editCounts).filter(n => n >= 3).length;

  // Token 統計
  let totalTokens = 0;
  for (const msg of messages) {
    if (msg.type !== 'assistant') continue;
    const u = msg.message?.usage;
    if (u) totalTokens += (u.input_tokens ?? 0) + (u.output_tokens ?? 0);
  }

  const burnRate = turns > 0 ? totalTokens / turns : 0;
  const errorRate = toolCalls > 0 ? toolErrors / toolCalls : 0;

  // 效率分數
  let score = 100;
  score -= Math.max(0, (turns - 15) * 2);
  score -= Math.max(0, (burnRate - 5000) / 1000);
  score -= errorRate * 200;
  score -= repeatedEdits * 10;
  score = Math.max(0, Math.min(100, score));

  return {
    turns,
    user_msgs: userMsgs,
    tool_calls: toolCalls,
    tool_errors: toolErrors,
    error_rate: errorRate,
    repeated_edits: repeatedEdits,
    total_tokens: totalTokens,
    burn_rate: burnRate,
    efficiency_score: score,
  };
}

/**
 * 將效率分數轉為等級
 */
export function scoreGrade(score) {
  if (score >= 80) return { grade: 'A', label: '高效', emoji: '$' };
  if (score >= 60) return { grade: 'B', label: '正常', emoji: 'O' };
  if (score >= 40) return { grade: 'C', label: '偏低', emoji: '!' };
  return { grade: 'D', label: '高摩擦', emoji: 'X' };
}

新增效率報告腳本

新增 efficiency-report.mjs

import { scanProjects, scanProjectSessions } from './lib/scanner.mjs';
import { parseJsonl } from './lib/parser.mjs';
import { calcEfficiencyMetrics, scoreGrade } from './lib/efficiency.mjs';

const DAYS = parseInt(process.argv[2] ?? '30', 10);
const cutoff = new Date();
cutoff.setDate(cutoff.getDate() - DAYS);

const sessions = [];

for (const proj of scanProjects()) {
  for (const session of scanProjectSessions(proj)) {
    if (new Date(session.first_message_time) < cutoff) continue;
    const messages = parseJsonl(session.file_path);
    const metrics = calcEfficiencyMetrics(messages);
    sessions.push({ ...session, ...metrics });
  }
}

// 按效率分數排序
sessions.sort((a, b) => b.efficiency_score - a.efficiency_score);

console.log(`\n Session 效率分析(過去 ${DAYS} 天,共 ${sessions.length} 個)\n`);

// 分布統計
const grades = { A: 0, B: 0, C: 0, D: 0 };
for (const s of sessions) {
  grades[scoreGrade(s.efficiency_score).grade]++;
}
console.log('等級分布:');
console.log(`   A(高效):${grades.A} 個`);
console.log(`   B(正常):${grades.B} 個`);
console.log(`  ️ C(偏低):${grades.C} 個`);
console.log(`   D(高摩擦):${grades.D} 個`);

// TOP 5 高效
console.log('\n\n 效率最高的 Sessions:\n');
for (const s of sessions.slice(0, 5)) {
  const { emoji, label } = scoreGrade(s.efficiency_score);
  const date = new Date(s.first_message_time).toLocaleDateString();
  const summary = (s.summary ?? '(無摘要)').slice(0, 50);
  console.log(`  ${emoji} [${s.efficiency_score.toFixed(0)}分] [${date}] ${s.turns}輪 ${s.total_tokens.toLocaleString()}tokens`);
  console.log(`        ${summary}`);
}

// TOP 5 低效
console.log('\n\n 需要改善的 Sessions:\n');
for (const s of sessions.slice(-5).reverse()) {
  const { emoji, label } = scoreGrade(s.efficiency_score);
  const date = new Date(s.first_message_time).toLocaleDateString();
  const summary = (s.summary ?? '(無摘要)').slice(0, 50);
  console.log(`  ${emoji} [${s.efficiency_score.toFixed(0)}分] [${date}] ${s.turns}輪 ${s.tool_errors}錯誤 ${s.repeated_edits}重複修改`);
  console.log(`        ${summary}`);
}

// 平均指標
const avg = sessions.reduce((acc, s) => ({
  score: acc.score + s.efficiency_score,
  turns: acc.turns + s.turns,
  burnRate: acc.burnRate + s.burn_rate,
  errorRate: acc.errorRate + s.error_rate,
}), { score: 0, turns: 0, burnRate: 0, errorRate: 0 });

const n = sessions.length || 1;
console.log('\n\n 平均指標:');
console.log(`  效率分數:${(avg.score / n).toFixed(1)} 分`);
console.log(`  平均輪數:${(avg.turns / n).toFixed(1)} 輪`);
console.log(`  平均燃耗率:${(avg.burnRate / n).toFixed(0)} tokens/輪`);
console.log(`  平均工具錯誤率:${(avg.errorRate / n * 100).toFixed(1)}%`);

接著來執行

node efficiency-report.mjs        # 過去 30 天
node efficiency-report.mjs 7      # 過去 7 天
D:\Git\mathTalk\class\Claude-Code-Analytics\src>node monthly-report.mjs
生成 30 天報告中...

 月報已生成:ce-report-2026-06-12.md
   Sessions:130 個
   總費用:$12460.32 USD
   平均效率分:32.9

最後的報告如下:

一、整體概覽

指標 數值
總 Session 數 130
總 Token 用量 33,902,068
估算總費用 $12460.32 USD
平均每 Session 費用 $95.8486 USD
估算月費用 $12460.32 USD
平均效率分數 32.9 / 100

二、效率分布

等級 數量 比例
A(高效,80+) 31 24%
B(正常,60-79) 10 8%
️ C(偏低,40-59) 7 5%
D(高摩擦,<40) 82 63%

無標籤

新增評論