🔭

Claude Codeでトークン使用量とGitブランチをリアルタイム表示する方法(解説あり)

に公開

3行まとめ

  • Claude Codeのステータスラインにトークン使用量・ブランチ名・セッションIDを常時表示
  • 設定は5分、コピペだけで完了
  • 圧縮タイミングを事前に把握して、セッションデータを計画的に管理が可能に

表示イメージ

設定後、こんな感じでステータスライン(ClaudeCodeの入力欄の下の表示)に情報が表示されます:

[Sonnet 4.5] 📁 task-management 🌿 master | 🪙 138.0K | 69% | 6cc163e0-91b9-471f-b8a6-a3cabe7514a1
  • モデル名: 使用中のモデル(Sonnet 4.5など)
  • ディレクトリ: 現在の作業ディレクトリ
  • ブランチ: Gitブランチ名
  • トークン数: 現在のセッションで使用中のトークン(K/M単位)
  • パーセント: 200Kコンテキストに対する使用率(色分け表示:緑→黄→赤)
  • セッションID: claude -r <session-id> で再開可能なID

これで何が嬉しいの?

Claude Codeの「自動圧縮」とは?

Claude Codeは**Context Usageが80%(160K)**に達すると、会話履歴を自動で圧縮して要約します。便利な機能ですが:

  • タイミングがコントロールできない → 作業の途中で突然圧縮される
  • コンテキストの精度が落ちる → 圧縮=要約なので、細かいニュアンスや議論の流れが失われる
  • 詳細な作業記録が失われる → 後から振り返れない

ステータスライン表示で解決できること

1. コンテキスト満杯前に対処できる

  • セッションを切り替えるタイミングを計画的に判断
  • 作業状況をmdファイルに吐き出して記録を残す
    • 記録をドキュメントで引き継げば、/clearや別セッションに切り替えて再開することも可能
    • 「セッションをクリアするので、引き継ぎ資料を作って」 というと、いい塩梅に作ってくれることが多いです。
    • /compactでそのまま続行してもOK

色分け表示で一目で分かる:

  • (<56%): 余裕あり、作業に集中
  • (56-71%): そろそろ注意、記録準備
  • (≥72%): 圧縮間近、セッション切り替えを検討

2. 区切りの良いタイミングで圧縮できる

  • 休憩前に /compact して整理できる
  • 自動圧縮だと変なタイミングで中断させるストレスから解放

3. 作業コンテキストが一目で分かる

  • 現在のディレクトリとブランチ名を常時表示
  • 複数プロジェクトを行き来するときに「今どこで作業してる?」が瞬時に分かる
  • ブランチ切り替え忘れを防げる

4. セッション管理が楽

  • フルセッションIDが表示されるので、claude -r <session-id> で簡単に再開
  • 複数セッションを使い分けるときに便利

セットアップ手順(5分で完了)

1. statusline.js の作成

~/.claude/statusline.js を作成して、以下のコードをコピペ:

#!/usr/bin/env node

const fs = require('fs');
const path = require('path');
const readline = require('readline');
const { execSync } = require('child_process');

// Constants
const COMPACTION_THRESHOLD = 200000

// Read JSON from stdin
let input = '';
process.stdin.on('data', chunk => input += chunk);
process.stdin.on('end', async () => {
  try {
    const data = JSON.parse(input);

    // Extract values
    const model = data.model?.display_name || 'Unknown';
    const currentDir = data.workspace?.current_dir || data.cwd || '.';
    const dirName = path.basename(currentDir);
    const sessionId = data.session_id;

    // Get Git branch
    let branch = '';
    if (currentDir && fs.existsSync(path.join(currentDir, '.git'))) {
      try {
        const branchName = execSync('git --no-optional-locks branch --show-current 2>/dev/null', {
          cwd: currentDir,
          encoding: 'utf-8'
        }).trim();
        if (branchName) {
          branch = ` 🌿 ${branchName}`;
        }
      } catch (e) {
        // Gitコマンドエラーは無視
      }
    }

    // Calculate token usage for current session
    let totalTokens = 0;

    if (sessionId) {
      // Find all transcript files
      const projectsDir = path.join(process.env.HOME, '.claude', 'projects');

      if (fs.existsSync(projectsDir)) {
        // Get all project directories
        const projectDirs = fs.readdirSync(projectsDir)
          .map(dir => path.join(projectsDir, dir))
          .filter(dir => fs.statSync(dir).isDirectory());

        // Search for the current session's transcript file
        for (const projectDir of projectDirs) {
          const transcriptFile = path.join(projectDir, `${sessionId}.jsonl`);

          if (fs.existsSync(transcriptFile)) {
            totalTokens = await calculateTokensFromTranscript(transcriptFile);
            break;
          }
        }
      }
    }

    // Calculate percentage
    const percentage = Math.min(100, Math.round((totalTokens / COMPACTION_THRESHOLD) * 100));

    // Format token display
    const tokenDisplay = formatTokenCount(totalTokens);

    // Color coding for percentage (same ratio as original article with 160K base)
    let percentageColor = '\x1b[32m'; // Green
    if (percentage >= 56) percentageColor = '\x1b[33m'; // Yellow (112K/200K)
    if (percentage >= 72) percentageColor = '\x1b[91m'; // Bright Red (144K/200K)

    // Build status line
    const statusLine = `[${model}] 📁 ${dirName}${branch} | 🪙 ${tokenDisplay} | ${percentageColor}${percentage}%\x1b[0m \x1b[90m| ${sessionId}\x1b[0m`;

    console.log(statusLine);
  } catch (error) {
    // Fallback status line on error
    console.log('[Claude Code]');
  }
});

async function calculateTokensFromTranscript(filePath) {
  return new Promise((resolve, reject) => {
    let lastUsage = null;

    const fileStream = fs.createReadStream(filePath);
    const rl = readline.createInterface({
      input: fileStream,
      crlfDelay: Infinity
    });

    rl.on('line', (line) => {
      try {
        const entry = JSON.parse(line);

        // Check if this is an assistant message with usage data
        if (entry.type === 'assistant' && entry.message?.usage) {
          lastUsage = entry.message.usage;
        }
      } catch (e) {
        // Skip invalid JSON lines
      }
    });

    rl.on('close', () => {
      if (lastUsage) {
        // The last usage entry contains cumulative tokens
        const totalTokens = (lastUsage.input_tokens || 0) +
          (lastUsage.output_tokens || 0) +
          (lastUsage.cache_creation_input_tokens || 0) +
          (lastUsage.cache_read_input_tokens || 0);
        resolve(totalTokens);
      } else {
        resolve(0);
      }
    });

    rl.on('error', (err) => {
      reject(err);
    });
  });
}

function formatTokenCount(tokens) {
  if (tokens >= 1000000) {
    return `${(tokens / 1000000).toFixed(1)}M`;
  } else if (tokens >= 1000) {
    return `${(tokens / 1000).toFixed(1)}K`;
  }
  return tokens.toString();
}

2. 実行権限の付与

chmod +x ~/.claude/statusline.js

3. settings.json の設定

~/.claude/settings.json に以下を追加:

{
  // (他の設定)
   "statusLine": {
      "type": "command",
       "command": "~/.claude/statusline.js"
    },
}

4. Claude Codeを再起動

claude

これで完了!ステータスラインにトークン使用量が表示されます 🎉

より高度な使い方:/compactでカスタム圧縮

カスタム指示で必要な情報を保持

/compactは、圧縮するものをカスタム指示で指定することが可能です。

# コード重視の圧縮
/compact コードサンプルとAPI使用例を重点的に残してください

# テスト結果重視
/compact テスト結果とエラーメッセージだけを残してください

# 設計情報重視
/compact 関数定義とインターフェースを保持してください

# 実践例:設計書を残す
/compact 設計書やタスクリストは残して、他のログはコンパクトしてください

よくある質問

Q. トークンが表示されない

プロジェクトディレクトリを確認

ls ~/.claude/projects/

現在のディレクトリに対応するプロジェクトディレクトリが存在するか確認してください。

スクリプトのエラーを確認

echo '{"session_id":"test","model":{"display_name":"Test"},"workspace":{"current_dir":"'$(pwd)'"}}' | node ~/.claude/statusline.js
Q. パーセンテージがおかしい

母数(COMPACTION_THRESHOLD)が正しいか確認してください。Sonnet 4.5の場合は 200000 です。

Q. セッションIDを非表示にしたい

145行目を以下のように変更:

const statusLine = `[${model}] 📁 ${dirName}${branch} | 🪙 ${tokenDisplay} | ${percentageColor}${percentage}%\x1b[0m`;
Q. 色の閾値を変更したい

140-142行目を変更:

// より早めに警告を出したい場合
if (percentage >= 50) percentageColor = '\x1b[33m'; // Yellow
if (percentage >= 65) percentageColor = '\x1b[91m'; // Bright Red
Q. /compactと/clearの違いは?
  • /compact:会話を要約・圧縮して重要な情報を保持

    • コンテキストは保持される(圧縮された形で)
    • 継続的な作業に適している
    • 実行に時間がかかる(分単位)
    • コンテキスト使用は0にはならない
  • /clear:会話履歴を完全にクリア

    • コンテキストがリセットされる
    • 全く新しいタスクを始めるときに使う

使い分け

  • 同じプロジェクト内で作業を続ける場合
    • そのまま続行 → /compact
    • いったんリセット → ドキュメントに作業内容を引き継いで /clear、新しいセッションでそのドキュメントを参照して再開
  • 別のプロジェクトに切り替える場合/clear
Q. compactを実行するとコストはかかる?

はい、compactの実行自体にトークンが消費されます。ただし:

  • 自動compact: 避けられないコスト(95%で自動実行)
  • 手動compact: 早めに実行する方がコスト効率が良い
    • 理由:コンテキストが小さいうちに圧縮した方が、処理するデータ量が少ない

コスト最適化のコツ

  • 黄色(56-71%)の段階でcompactするのがベスト
  • 赤(≥72%)まで待つと、圧縮コストが高くなる

技術的な補足(興味がある人向け)

トークン計算の仕組み
  • Claude Codeは会話履歴を ~/.claude/projects/{project_dir}/{session_id}.jsonl に保存
  • 最後のassistantメッセージのusageフィールドから累積トークン数を取得
  • input_tokens + output_tokens + cache_creation_input_tokens + cache_read_input_tokens を合算

注意: 全メッセージを合計すると重複カウントになります!

Context Usageとの違い

/context コマンドで表示される値とは異なります:

Context Usage (144k) = システムプロンプト + ツール + メモリ + メッセージ + Autocompact buffer
ステータスライン (99k) ≈ Context Usage - Autocompact buffer
  • Context Usage: 実際に割り当てられている全コンテキスト
  • ステータスライン: 実際のメッセージで使われているトークン(API課金に近い値)
色閾値の設計思想
  • 56%(112K): 黄色 → 自動圧縮(160K)の70%に相当(まだ余裕あり)
  • 72%(144K): 赤 → 自動圧縮(160K)の90%に相当(圧縮直前!)
  • 80%到達の8%前から警告が出るように設計

参考資料

まとめ

ステータスラインのカスタマイズで、Claude Codeがさらに使いやすくなります:

  • ✅ トークン使用量を常時把握、圧縮タイミングを事前察知
  • ✅ 作業記録を失わず、計画的にセッション管理
  • ✅ ブランチ名・セッションIDも一目で確認

ぜひ試してみてください!

Discussion