はじめに
Windows + 日本語環境で Claude Code のステータスラインを設定したのに、何も表示されない——という問題にハマりました。調べてみると、原因は 1 つではなく 2 つの要因が重なっていました。同じ環境で困っている人向けに、原因の切り分けと直し方をまとめます。
まず前提として、私のマシンには 2 つの PowerShell が共存していました。
| 名前 | 実体 | バージョン |
|---|---|---|
pwsh |
C:\Program Files\WindowsApps\...\pwsh.exe |
7.6.3 |
powershell |
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe |
5.1.26100.8655 |
- 既定/対話シェルは 7(pwsh)。
- しかし
settings.jsonのコマンドは文字列がpowershellで始まっていた。これは 5.1 の実行体を指す別名。 - そのため、既定が 7 でも ステータスラインのスクリプトは実際には 5.1 の下で動いていた。
powershell と pwsh は別物。powershell は Windows PowerShell 5.1、pwsh は PowerShell 7。既定シェルが 7 でも、コマンドに powershell と書けば 5.1 が起動する。
問題
症状は次の 2 つでした。
- ステータスラインに何も表示されない
- スクリプト単体で叩くと、モデル名だけ欠けて
| Context: 42% usedのように崩れる
原因を切り分けると、要因は 2 つありました。
要因1:パスが見つからず、そもそも実行されない(→ 何も表示されない)
settings.json のパスが %USERPROFILE%\.claude\... のままでした。
-
%USERPROFILE%は cmd.exe 用の変数の書き方。cmd.exe を通さず実行されると実際のフォルダに置き換わらず、7 文字がそのまま文字として PowerShell に渡ります(PowerShell 側の書き方は$env:USERPROFILE)。 - PowerShell は
%USERPROFILE%\.claude\statusline-command.ps1という名前のファイルを探し、存在しないのでエラー終了 → 出力が空 → 何も表示されない。
根拠:パスを絶対パスに変えた直後にステータスラインが表示されました。
要因2:文字化けでモデル名が消える(→ 表示が崩れる)
スクリプトが 5.1 の下で動くと、5.1 は BOM なしの .ps1 を Shift-JIS と誤読します。日本語コメントのバイト列が直後のコード行を侵食し、モデル名の代入が消えていました。
BOM(Byte Order Mark)=ファイル先頭に付く「これは UTF-8 です」という数バイトの目印。PowerShell 7 は BOM 無しでも UTF-8 と解釈するが、5.1 は無いと Shift-JIS と勘違いする。
解決方法
どちらのパターンも共通で、パスは 絶対パスにします(%USERPROFILE% を使わない)。これで要因1が解決します。あとは起動する PowerShell に応じて要因2の対策が変わります。
パターンA:pwsh(7)で動かす — 推奨
{
"statusLine": {
"type": "command",
"command": "pwsh -NoProfile -ExecutionPolicy Bypass -File \"C:\\Users\\007476\\.claude\\statusline-command.ps1\""
}
}
-
pwsh(7.6.3)は BOM なしでも UTF-8 として正しく読む → 文字化けの要因そのものが消える。 - スクリプトの保存文字コードを気にしなくてよいので堅牢。
パターンB:powershell(5.1)のまま動かす
{
"statusLine": {
"type": "command",
"command": "powershell -NoProfile -ExecutionPolicy Bypass -File \"C:\\Users\\007476\\.claude\\statusline-command.ps1\""
}
}
- 5.1 は BOM なしの
.ps1を Shift-JIS と誤読するので、スクリプトを必ず UTF-8(BOM 付き) で保存する。
スクリプト本体
# 標準入力の JSON を受け取り、モデル名とコンテキスト使用率を出力する
$raw = [Console]::In.ReadToEnd()
$data = $raw | ConvertFrom-Json
$model = $data.model.display_name
# context_window が来ない起動タイミングもあるためガードする
$used = $null
if ($data.PSObject.Properties.Name -contains 'context_window' -and $data.context_window) {
$used = $data.context_window.used_percentage
}
[Console]::Out.Write("$model | Context: $used% used")
- フィールド名(
model.display_name/context_window.used_percentage)は Claude Code が渡す実際の JSON に合わせる。 - パターンB を選ぶ場合はこのファイルを UTF-8(BOM 付き) で保存する。
おわりに
学びは 3 つでした。
- 「何も出ない」ときは、まず実行・パスを疑う。出力ストリーム(
Write-Hostなど)の議論はその後。 - Windows で自動生成された設定は
%USERPROFILE%を含みがち。絶対パスにする。 -
powershellとpwshの取り違えに注意。日本語コメント入りのスクリプトはpwsh(7)で動かすのが安全。
同じ環境でステータスラインが出ない人の助けになれば幸いです。
参考
- Claude Code 公式ドキュメント:ステータスライン(statusLine)設定
- PowerShell の文字エンコーディング(Windows PowerShell 5.1 と PowerShell 7 の既定の違い)
-
about_Character_Encoding/about_Automatic_Variables(PowerShell 公式ヘルプ)
JISOUのメンバー募集中!
プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか?
興味のある方は、ぜひホームページをのぞいてみてください!
▼▼▼
https://projisou.jp