Windows で Claude code を使っていると「bash の出力が得られない」とか言われてとても不便していた。 Fable5 に調査を依頼して解決できたのでその顛末を以下に示す。
(Bash completed with no output) を返す問題に遭遇したgit-bash.exe(別窓のターミナルを開くランチャー)を誤選択していたこと。コマンドの出力はパイプではなく別窓の mintty に流れて消えていたCLAUDE_CODE_GIT_BASH_PATH に正しい bash.exe のパスを設定して解決した[System.Environment]::SetEnvironmentVariable(
"CLAUDE_CODE_GIT_BASH_PATH",
"C:\Users\<ユーザー名>\scoop\apps\git\current\bin\bash.exe",
"User")C:\Program Files\Git は存在しない)Backlog のリポジトリを clone しようとして「認証エラーだ」と Claude Code に相談したのが始まり。ところが調査を始めると、そもそも Bash ツールのすべてのコマンドが (Bash completed with no output) を返す状態だった。echo hello すら出力が返ってこない。
最初は的外れな仮説が続いた。
MSYSTEM=MINGW64 が確認でき、Git Bash 自体は起動していたこのあたりで「AI が推測で答えている」ことを指摘され、実証ベースの調査に切り替えた。
ファイルリダイレクトを使ったテストで大きな手がかりが得られた。
echo hello > /tmp/test.txt # → ファイルには正しく書き込まれる
echo hello # → 出力が返ってこないつまり bash は起動しており、コマンドも実行されている。stdout がツールに返る経路だけが壊れている。
さらに奇妙なことに、この bash 環境では ls も cat も which も見つからなかった。PATH が Windows 形式(セミコロン区切り)のまま MSYS 側で変換されておらず、/usr/bin が通っていなかった。
「bash が悪いのか、Claude Code が悪いのか」を切り分けるため、Node.js の spawnSync で同じ bash.exe を起動するテストを書いた。
const { spawnSync } = require('child_process');
const r = spawnSync(
'C:\\Users\\<ユーザー名>\\scoop\\apps\\git\\current\\usr\\bin\\bash.exe',
['-c', 'echo hello'],
{ encoding: 'utf8' });
// → status=0, stdout="hello\n" 正常に取得できるNode.js からは stdout が正常に取れた。 bash は無罪。問題は Claude Code 側のプロセス起動にある。
Claude Code は Bun でコンパイルされた単一バイナリだが、JavaScript ソースが文字列として埋め込まれているため、grep -a(バイナリ強制テキスト検索)と dd で内部実装を読める。
grep -aob "CLAUDE_CODE_GIT_BASH_PATH" ~/.local/share/claude/versions/2.1.218
dd if=<バイナリ> bs=1 skip=<オフセット> count=3000 | tr -c '[:print:]' '\n'抽出したコードから bash 検出ロジックが判明した。
// Windows での bash 探索順序
// 1. 環境変数 CLAUDE_CODE_GIT_BASH_PATH(最優先・存在しないパスなら起動拒否)
// 2. C:\Program Files\Git\bin\bash.exe
// 3. C:\Program Files (x86)\Git\bin\bash.exe
// 4. PATH 上の git から相対パスで解決ポイントは 2 つ。
CLAUDE_CODE_SHELL ではなく CLAUDE_CODE_GIT_BASH_PATH(CLAUDE_CODE_SHELL は設定しても無視される)PowerShell の Get-CimInstance Win32_Process で親子関係を調べたところ、決定的な証拠が出た。
claude.exe(15384) ← pwsh.exe ← WindowsTerminal.exe … 自分のターミナル
└─ git-bash.exe(4324) … Claude Code が起動した「シェル」
└─ mintty.exe(23228) … 別窓のターミナル GUI!Claude Code は bash として git-bash.exe を起動していた。git-bash.exe は「新しいターミナルウィンドウ (mintty) を開くためのランチャー」であり、標準入出力をパイプに返さない。
「実行されるのに出力だけが空」という症状が完全に説明できた。GitHub の Issue #38882(可視のコンソールウィンドウが出現する)とも整合する。
正しい bash(ランチャーではなく本体のラッパー)を明示指定する。
[System.Environment]::SetEnvironmentVariable(
"CLAUDE_CODE_GIT_BASH_PATH",
"C:\Users\<ユーザー名>\scoop\apps\git\current\bin\bash.exe",
"User")Claude Code を再起動すると:
echo hello-stdout-test && git --version && pwd
# hello-stdout-test
# git version 2.33.1.windows.1
# /c/dev/job/naritasan/srcstdout が返ってきた。 PATH 変換も正常化し、ls や stat などの GNU ツールも使えるようになった。
Bash 復旧後に本題の clone を実行したら、認証エラーは一切発生せずに成功した。Git Credential Manager に Backlog の認証情報が保存済みだったためだ。
当初の「認証エラー」の正体は、Bash が壊れていて git コマンドの結果がまともに見えていなかっただけの可能性が高い。最初の症状報告が別の問題の影だった、というデバッグあるあるだった。
grep -a + dd で内部実装をかなり読める。ドキュメントにない環境変数 CLAUDE_CODE_GIT_BASH_PATH はバイナリ解析でしか見つからなかったWin32_Process の親子関係が最終的な決定打だったCLAUDE_CODE_GIT_BASH_PATH を試してほしい