はじめに
Claude Codeを日常的に使っていて、こんな経験はありませんか?
- 長いセッションで突然「コンテキストが圧縮されました」と表示される
- 5時間のローリングウィンドウ制限に気づかず作業が中断される
- セッション終了まで累積コストがわからない
これらの問題を解決するのが、Claude Codeのステータスライン(statusline)機能です。ターミナル下部に常時表示される1行のバーで、コンテキスト使用率・コスト・レート制限を一目で確認できます。
ただし、Windows環境では一筋縄ではいきません。筆者がWindows 11で設定を試みたところ、5つの問題に連続してハマりました。この記事では、その5つの罠と最終的な解決策(Node.jsによる実装)を体系的に解説します。
この記事でわかること:
- Claude Codeのstatusline機能の仕組みと設定方法
- Windows環境で遭遇する5つの問題とその原因
- Node.jsによる最終的な解決策(コピペで使えるコード付き)
- トラブルシューティングのフロー図
前提条件(2026-02時点):
| 項目 | 内容 |
|---|---|
| OS | Windows 11 |
| エディタ | VSCode 内蔵ターミナル |
| Claude Code | v2.1.42 |
| Node.js | インストール済み(Claude Codeの前提条件) |
ステータスラインはローカルで実行されるため、APIトークンを消費しません。安心して導入できます。
statusline機能とは?
ステータスラインは、Claude Codeのターミナル下部に表示されるカスタマイズ可能なバーです。設定ファイルでスクリプトを指定すると、Claude Codeがセッション情報をJSON形式でスクリプトに渡し、スクリプトの出力がバーに表示されます。
設定スキーマ
~/.claude/settings.json(ホームディレクトリ直下の.claudeフォルダ)に以下の形式で設定します。
{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline.sh",
"padding": 0
}
}
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
type |
string | Yes | 常に "command"
|
command |
string | Yes | 実行するコマンドまたはスクリプトパス |
padding |
number | No | 表示の余白(デフォルト: 0) |
この3つ以外のフィールドは公式スキーマに存在しません。 "enabled": true のような非公式フィールドを追加すると、設定全体が無言で無視される可能性があります(後述の問題2参照)。
動作原理
┌──────────────┐ stdin (JSON) ┌──────────────┐ stdout (text) ┌──────────────┐
│ Claude Code │ ────────────────→ │ スクリプト │ ────────────────→ │ ターミナル │
│ (本体) │ │ (.sh/.js等) │ │ (下部バー) │
└──────────────┘ └──────────────┘ └──────────────┘
- Claude CodeがJSON(セッション情報)をスクリプトのstdinにパイプする
- スクリプトがJSONをパースし、表示テキストをstdoutに出力する
- Claude Codeがその出力をターミナル下部に表示する
更新タイミング
| トリガー | 説明 |
|---|---|
| アシスタント応答後 | Claudeが応答するたびに更新 |
| パーミッション変更 | ユーザーが権限を許可/拒否した時 |
| Vimモード切り替え | Vimモードの有効/無効切り替え時 |
| デバウンス | 300ms の遅延(高速な変更をバッチ処理) |
stdinで送信されるJSONの主要フィールド
| フィールド | 説明 |
|---|---|
model.id / model.display_name
|
モデル識別子と表示名 |
cwd / workspace.current_dir
|
現在の作業ディレクトリ |
workspace.project_dir |
プロジェクトルート(起動ディレクトリ) |
cost.total_cost_usd |
セッション累積コスト(USD) |
cost.total_duration_ms |
セッション経過時間(ms) |
context_window.used_percentage |
コンテキストウィンドウ使用率(%、入力トークンベース) |
context_window.remaining_percentage |
残りコンテキスト(%) |
context_window.total_input_tokens |
累積入力トークン |
context_window.total_output_tokens |
累積出力トークン |
context_window.context_window_size |
コンテキストウィンドウ上限(通常200,000) |
session_id |
セッション識別子 |
transcript_path |
会話トランスクリプトのファイルパス |
version |
Claude Codeバージョン |
context_window.current_usage は最初のAPI呼び出し前は null になる場合があります。スクリプト内でnullチェックを実装してください。
最終的な完成形
先に結論をお見せします。Node.jsで実装したステータスラインの出力例です。
ブログ記事 | Opus 4.6 | [====== ] 31% 62k/200k | $1.9560 | 0h25m | 27791 tok | 5h: 0.6% | Week: 0.06%
表示項目:
- 作業ディレクトリ名
- 使用モデル
- コンテキストウィンドウ使用率(プログレスバー付き)
- セッション累積コスト(USD)
- セッション経過時間
- 累積トークン数
- 5時間レートリミット消費率(暫定ロジック)
- 週間レートリミット消費率(暫定ロジック)
設定はたった2ステップです。
1. スクリプトを配置
# ~/.claude/statusline.js に後述のコードを保存
2. settings.json に設定を追加
{
"statusLine": {
"type": "command",
"command": "node ~/.claude/statusline.js"
}
}
ここに至るまでに5つの問題を乗り越える必要がありました。順に解説します。
問題1: プロジェクト設定がグローバル設定を上書きする
症状
グローバル設定 ~/.claude/settings.json に statusline を設定したのに、何も表示されない。
原因
プロジェクトレベルの .claude/settings.json(プロジェクトルート直下)に、別の statusLine 設定が存在していました。
// プロジェクトの .claude/settings.json に残っていた設定
{
"statusLine": {
"type": "command",
"command": "input=$(cat); cwd=$(echo \"$input\" | jq -r '.workspace.current_dir // .cwd'); ..."
}
}
このコマンドには jq のパス未指定や Linux固有のオプション(stat -c %Y)が含まれており、Windows環境では動作しませんでした。
重要な発見
プロジェクトレベルの
.claude/settings.jsonは、グローバルの~/.claude/settings.jsonのstatusLineを「マージ」ではなく「完全に置換」する。
つまり、プロジェクト設定に statusLine が存在する限り、グローバル設定は完全に無視されます。
解決策
プロジェクトの .claude/settings.json から statusLine キーを削除し、グローバル設定に一本化しました。
{
- "statusLine": {
- "type": "command",
- "command": "input=$(cat); ..."
- },
"hooks": { ... }
}
問題2: 公式スキーマにないフィールドが設定を壊す
症状
問題1を修正後もステータスラインが表示されない。
原因
グローバル設定に、以前のデバッグ試行で追加された非公式フィールドが残っていました。
{
"statusLine": {
"type": "command",
"command": "bash ~/.claude/statusline.sh",
"enabled": true
}
}
"enabled": true は公式スキーマに存在しないフィールドです。公式スキーマが受け付けるのは type、command、padding の3つのみ。
不明なフィールドが存在すると、Claude Code が statusLine 設定全体を無言で拒否する可能性があります。エラーメッセージは一切表示されません。
解決策
enabled フィールドを削除しました。
{
"statusLine": {
"type": "command",
"command": "bash ~/.claude/statusline.sh"
}
}
問題3: Windowsでbashスクリプトが動かない
症状
設定スキーマの問題を解消してもステータスラインが表示されない。
二分探索的デバッグ
テスト1: インラインecho
"command": "echo 'STATUS LINE TEST'"
→ 表示された ![]()
テスト2: bashスクリプト呼び出し
"command": "bash ~/.claude/statusline.sh"
→ 表示されない ![]()
原因
Claude Codeは Windows上で statusLine コマンドを
bashではなく、cmd.exeまたは別のシェルで実行している。
echo は cmd.exe の内蔵コマンドとして動作しますが、bash はPATH上に存在しても外部プログラムであり、statusLineの実行環境からは解決できませんでした。
┌─────────────────────────────────────────────────────────────┐
│ Claude Code statusLine 実行環境 (Windows) │
│ │
│ ✅ echo, set, dir → cmd.exe 内蔵コマンド → 動作する │
│ ❌ bash, sh → 外部プログラム → 解決できない │
│ ✅ node, powershell → フルパスまたは特定条件で動作 │
└─────────────────────────────────────────────────────────────┘
公式ドキュメントにも以下のように記載されています(2026-02時点)。
These examples use Bash scripts, which work on macOS and Linux. On Windows, you can run Bash scripts through WSL (Windows Subsystem for Linux) or rewrite them in PowerShell.
— Claude Code 公式ドキュメント: Customize your status line
解決策
bashを放棄し、PowerShellに切り替えました。
問題4: PowerShell -File でstdinが空になる
症状
PowerShellに切り替えてテスト。
テスト3: PowerShellインラインコマンド
"command": "powershell -NoProfile -Command Write-Host 'PS TEST' -NoNewline"
→ 表示された ![]()
テスト4: PowerShellスクリプトファイル
"command": "powershell -NoProfile -ExecutionPolicy Bypass -File ~/.claude/statusline.ps1"
→ 表示されるが、全データが空/ゼロ ![]()
原因
PowerShell の -File フラグと -Command フラグでは、stdinの取り扱いが異なります。
| フラグ | stdinの挙動 |
|---|---|
-Command |
stdinをインタラクティブに読み取り可能 |
-File |
stdinのパイピング方式が異なり、[Console]::In.ReadToEnd() でデータを正しく受信できない |
デバッグ用にファイル出力を追加して確認したところ、受信データは空でした。
解決策
-File を -Command に切り替え、スクリプトをdot-sourceする方法に変更しました。しかし、ここで次の問題が発覚します。
問題5: CP932/UTF-8 エンコーディング問題(致命的)
症状
-Command モードに切り替えてstdinの読み取りは成功。しかし ConvertFrom-Json でエスケープシーケンスエラーが発生。
原因
日本語 Windows のデフォルトコンソールコードページは CP932(Shift-JIS) です。Claude CodeがUTF-8でJSONを送信すると、WindowsのコンソールサブシステムがこれをCP932として解釈します。
┌──────────────┐ UTF-8 JSON ┌──────────────┐ CP932 解釈 ┌──────────────┐
│ Claude Code │ ──────────────→ │ Windows │ ──────────────→ │ PowerShell │
│ (UTF-8出力) │ │ Console API │ │ (CP932入力) │
└──────────────┘ └──────────────┘ └──────────────┘
↓
ConvertFrom-Json
↓
❌ パースエラー
文字化けの実例:
デバッグ出力で確認した結果、以下のように日本語パスが破壊されていました。
元データ(UTF-8):
"cwd": "...\\デスクトップ\\Claude Code\\ブログ記事"
PowerShell 経由の受信データ(CP932 解釈):
"cwd": "...\\繝・せ繧ッ繝医ャ繝予\\Claude Code\\繝悶Ο繧ー險倅コ・"
問題は cwd の日本語だけではありません。JSON全体がバイト列として破壊されるため、model.display_name 等の日本語を含まないフィールドも取得不能になります。
試みた回避策(すべて失敗)
-
[Console]::OutputEncoding = [Text.Encoding]::UTF8→ 効果なし(出力側のみ) -
$OutputEncoding = [Text.Encoding]::UTF8→ 効果なし -
chcp 65001をスクリプト冒頭で実行 → statuslineのコンテキストでは効果なし
結論
日本語パスを含むWindows環境では、PowerShellによるstatusline実装は根本的に不可能。
PowerShellを完全に放棄し、Node.jsに移行しました。
Node.jsによる最終実装
Node.jsを選定した理由
| 理由 | 説明 |
|---|---|
| Claude Codeの前提条件 | Claude Code自体がNode.jsで動作するため、必ずインストール済み |
| UTF-8ネイティブ | 内部的にUTF-8を使用。CP932の影響を受けない |
| JSON組み込み |
JSON.parse() が標準搭載。jq のような外部依存なし |
| Buffer API |
Buffer.concat(chunks).toString('utf8') で確実にUTF-8デコード |
| クロスプラットフォーム | macOS/Linuxでもそのまま動作 |
設定(~/.claude/settings.json)
{
"statusLine": {
"type": "command",
"command": "node ~/.claude/statusline.js"
}
}
statusline.js 全文
以下のコードを ~/.claude/statusline.js に保存してください。
レートリミットの計算ロジック(定数値・計算式)は暫定的なものです。Anthropicは正確な制限値や内部の計算方法を公開していないため(2026-02時点)、実際の使用状況に合わせてご自身で調整してください。
// ============================================================
// Rate Limit Settings (Max 5x plan)
// ⚠️ 以下の定数値・計算ロジックは暫定値です
// Anthropicは正確な制限値を公開していないため、
// 実際の使用状況に合わせて調整してください
// ============================================================
const PLAN = 'Max 5x';
const LIMIT_5H_TOKENS = 5_000_000; // 5時間ローリングウィンドウ (暫定値)
const LIMIT_WEEKLY_TOKENS = 45_000_000; // 週間上限 (暫定値)
// ============================================================
// --- stdin 読み取り ---
// Claude Code が JSON をパイプで送信する
// Buffer で受け取り、最後に UTF-8 でデコードすることで
// Windows の CP932 エンコーディング問題を回避
const chunks = [];
process.stdin.on('data', c => chunks.push(c));
process.stdin.on('end', () => {
try {
// Buffer.concat → toString('utf8') で確実に UTF-8 デコード
const json = JSON.parse(Buffer.concat(chunks).toString('utf8'));
// --- モデル名 ---
const model = json.model?.display_name || 'N/A';
// --- コンテキストウィンドウ使用率 ---
const used = Math.round(json.context_window?.used_percentage || 0);
const totalIn = json.context_window?.total_input_tokens || 0;
const totalOut = json.context_window?.total_output_tokens || 0;
const tokens = totalIn + totalOut;
// --- コスト(API提供値を使用) ---
const cost = json.cost?.total_cost_usd
? json.cost.total_cost_usd.toFixed(4)
: '0.0000';
// --- コンテキストウィンドウのトークン数(k表記) ---
const ctxSize = json.context_window?.context_window_size || 200000;
const ctxUsed = Math.round(ctxSize * used / 100);
const fmtK = n => n >= 1000 ? Math.round(n / 1000) + 'k' : String(n);
// --- プログレスバー(20文字幅) ---
const filled = Math.floor(used * 20 / 100);
const bar = '[' + '='.repeat(filled) + ' '.repeat(20 - filled) + ']';
// --- レートリミット推定(5時間ローリングウィンドウ) ---
// 注意: セッション単位の累積値であり、5時間全体ではない
const rate5h = (tokens / LIMIT_5H_TOKENS * 100).toFixed(1);
// --- レートリミット推定(週間) ---
const rateWeek = (tokens / LIMIT_WEEKLY_TOKENS * 100).toFixed(2);
// --- ディレクトリ名(末尾のフォルダ名のみ) ---
const cwd = json.workspace?.current_dir || json.cwd || 'N/A';
const shortDir = cwd.split(/[/\\]/).pop();
// --- セッション経過時間 ---
let duration = 'N/A';
const durationMs = json.cost?.total_duration_ms;
if (durationMs) {
const sec = Math.floor(durationMs / 1000);
const h = Math.floor(sec / 3600);
const m = Math.floor((sec % 3600) / 60);
duration = `${h}h${m}m`;
}
// --- 出力 ---
process.stdout.write(
`${shortDir} | ${model} | ${bar} ${used}% ${fmtK(ctxUsed)}/${fmtK(ctxSize)} | $${cost} | ${duration} | ${tokens} tok | 5h: ${rate5h}% | Week: ${rateWeek}%`
);
} catch (e) {
process.stdout.write('statusline error: ' + e.message);
}
});
各セクションの解説
stdin読み取り部分
const chunks = [];
process.stdin.on('data', c => chunks.push(c));
process.stdin.on('end', () => {
const json = JSON.parse(Buffer.concat(chunks).toString('utf8'));
// ...
});
Node.jsの process.stdin はBufferオブジェクトとしてデータを受け取ります。Buffer.concat() で全チャンクを結合し、toString('utf8') で明示的にUTF-8デコードすることで、Windowsの CP932エンコーディング問題を完全に回避します。
プログレスバー
const filled = Math.floor(used * 20 / 100);
const bar = '[' + '='.repeat(filled) + ' '.repeat(20 - filled) + ']';
20文字幅のプログレスバーを生成します。使用率31%の場合、[====== ] のように表示されます。
セッション経過時間
const durationMs = json.cost?.total_duration_ms;
if (durationMs) {
const sec = Math.floor(durationMs / 1000);
const h = Math.floor(sec / 3600);
const m = Math.floor((sec % 3600) / 60);
duration = `${h}h${m}m`;
}
cost.total_duration_ms(セッション開始からの経過ミリ秒)を時間と分に変換します。
レートリミット推定
const rate5h = (tokens / LIMIT_5H_TOKENS * 100).toFixed(1);
const rateWeek = (tokens / LIMIT_WEEKLY_TOKENS * 100).toFixed(2);
レートリミットの計算ロジックは暫定的なものです。Anthropicはプランごとの正確な制限値や計算方法を公開していません(2026-02時点)。定数値(LIMIT_5H_TOKENS等)は推定であり、tokens(input + output)を等価扱いしている点も実際の課金比率(input:output = 1:5)とは異なります。ここでの値はセッション単位の累積値であり、5時間ローリングウィンドウ全体の使用量ではありません。実際の使用状況に合わせて調整してください。
トラブルシューティング
ステータスラインが正しく動作しない場合、以下のフローで原因を特定できます。
ステータスラインが表示されない
│
├─ settings.json を確認
│ ├─ statusLine キーが存在するか?
│ │ └─ No → 追加する
│ │
│ ├─ プロジェクトの .claude/settings.json に
│ │ statusLine が存在するか?
│ │ └─ Yes → グローバル設定が上書きされている → 削除
│ │
│ └─ type, command 以外のフィールドがあるか?
│ └─ Yes → 削除(enabled 等は公式スキーマにない)
│
├─ コマンドが実行されるか確認
│ ├─ "command": "echo 'TEST'" で表示される?
│ │ ├─ No → Claude Code 自体の問題の可能性
│ │ └─ Yes → スクリプト実行の問題 ↓
│ │
│ ├─ Windows で bash を使おうとしていないか?
│ │ └─ Yes → Node.js に切り替え
│ │
│ └─ PowerShell -File を使っていないか?
│ └─ Yes → Node.js に移行を推奨
│
├─ 表示されるが値がすべて 0 / 空
│ ├─ stdin のデータが届いていない
│ │ └─ デバッグファイル出力で確認
│ │
│ └─ 日本語パスによるエンコーディング問題
│ └─ Node.js に移行(Buffer.concat + toString('utf8'))
│
└─ Node.js 実装で解決
└─ "command": "node ~/.claude/statusline.js"
よくある質問
Q: /statusline コマンドで自動生成できないの?
A: Claude Codeには /statusline コマンドがあり、自然言語でstatuslineの生成を指示できます。ただし、Windows環境では生成されたbashスクリプトがそのまま動作しない場合があります。その場合は本記事のNode.js実装をお使いください。
Q: macOS/Linuxでもこのスクリプトは使える?
A: はい。Node.jsはクロスプラットフォームで動作するため、同じ statusline.js をmacOS/Linuxでもそのまま使用できます。
Q: disableAllHooks を設定するとstatuslineも消える?
A: はい。settings.json で "disableAllHooks": true を設定すると、ステータスラインも無効化されます(2026-02時点)。
まとめ
Windows環境でClaude Codeのステータスラインを設定する際に遭遇した5つの問題と、その解決策をまとめます。
| # | 問題 | 原因 | 解決策 |
|---|---|---|---|
| 1 | 表示されない | プロジェクト設定がグローバルを上書き | プロジェクトからstatusLineを削除 |
| 2 | 表示されない | 非公式フィールド(enabled等) | 公式スキーマの3フィールドのみ使用 |
| 3 | 表示されない | Windowsでbashが動作しない | Node.jsに切り替え |
| 4 | 値がすべて0 | PowerShell -File でstdinが空 | Node.jsに切り替え |
| 5 | 値がすべて0 | CP932/UTF-8エンコーディング不整合 | Node.jsのBuffer APIで解決 |
教訓
- WindowsでClaude Codeのカスタムスクリプトを書くならNode.jsが最適解 — Claude Codeの前提条件として必ず存在し、UTF-8をネイティブに扱える
- 設定のスコープを理解する — プロジェクトレベル設定はグローバル設定を「マージ」ではなく「置換」する
- 公式スキーマに忠実であること — 非公式フィールドはサイレントに設定を無効化するリスクがある
- 日本語Windows環境の特殊性 — CP932がデフォルトのコードページであり、外部プロセスとのstdin/stdoutパイピングでエンコーディング問題が発生しやすい
参考リンク
- Claude Code ステータスライン公式ドキュメント
- Claude Code 設定リファレンス
- ccstatusline(コミュニティ製statuslineツール)
- cc-statusline(コミュニティ製statuslineツール)
- GitHub Issue #14125: StatusLine not rendering in Windows Terminal
- GitHub Issue #6526: StatusLine not displaying output on Windows 11
検証日: 2026-02-14 / Claude Code v2.1.42 / Windows 11 Home