VSCode Copilot Chat と Claude Code、bash の扱いが違う

午前中、Copilot Chat のエージェントモードでコマンド実行したら止まるという事象が頻発した。.bashrc に仕掛け作って凌いだ。定時過ぎに Claude Code の仕組みを調べたらなんか知らんけど上手く動いてた、という一日の話。

午前:Copilot Chat のエージェントモードでコマンド実行すると以後進まない

VSCode の Copilot Chat をエージェントモードで使っていたら、コマンドを実行させるとそこで「Preparing」が点滅し続けてそこから進まなくなった。

なんだよこれと思って調べてみると、oh-my-posh が原因。oh-my-posh v28.1.1 以降で VSCode Shell Integration と競合するようになったらしく、エージェントが叩いた bash がそのまま固まる。

解決策として .bashrc に VSCode 向けの早期リターンを仕込んだ。$TERM_PROGRAM は VSCode が統合ターミナルを開くときにセットする変数で、WSL・ネイティブ Ubuntu どちらでも vscode になる。

# mise shims(全環境で必要)
eval "$(mise activate bash --shims)"

# VSCode 統合ターミナルはここで早期リターン
if [[ "$TERM_PROGRAM" == "vscode" ]]; then
  return
fi

# 以降はインタラクティブ専用(Tabby / GNOME Terminal など)
eval "$(oh-my-posh init bash ...)"
# ghq, fzf など...

これで Copilot Chat のエージェントモードは直った。さくさく進むようになった。でも午前の業務は溶けた。う○こですよ。

定時過ぎ:じゃあうちの Claude Code はどうなってんの??

定時過ぎてからふと「んじゃ、うちの Claude Code はどうやってコマンド実行してるんだろう」と気になったので調べた(Claude さんに調べてもらった)。

結果、Claude Code は内部で Node.js プロセスから bash -c "xxx" を叩く設計になってるらしい。非インタラクティブシェルなので .bashrc は読まれない。

いやちょっと待って、再度疑問。

え、なんで Claude Code で npm や python が動いてんの?

mise activate bash は、.bashrc でやってるので非インタラクティブシェルから見えないんじゃね?

過去の自分がやってくれてた

自分の環境を確認したら .profile の末尾にこれが書いてあった。

eval "$(mise activate bash --shims)"

--shims モードは mise のフル起動ではなく、shims ディレクトリを PATH に追加するだけの軽量な設定。非インタラクティブシェル向けに書いておいたやつだ。
いつ追加したか覚えてませんw

整理する

環境mise の解決方法経路
Claude Code(bash -c)--shims モード.profile
VSCode Copilot Chat--shims モード.bashrc early return 前
Tabby / GNOME Terminalmise activate bash フル.bashrc フル読み込み

各ツールの bash の起動方法をまとめると:

VSCode Copilot ChatClaude Code
実行方法VSCode 統合ターミナル(インタラクティブシェル)bash -c "xxx"(非インタラクティブ)
.bashrc読まれる読まれない
.profile読まれない(通常)ログイン時に読まれた環境を継承
$TERM_PROGRAMvscode がセットされるセットされない

まとめ

  • Copilot Chat のエージェントモードは VSCode 統合ターミナルを使うので .bashrc が読まれる。oh-my-posh との競合に注意
  • $TERM_PROGRAM=vscode を使った early return で VSCode だけ別扱いにできる
  • Claude Code は bash -c の非インタラクティブ実行なので .bashrc を読まない
  • .profilemise activate bash --shims を書いておくと Claude Code からも mise 管理のランタイムが使える