このページは原文を AI が翻訳したものです。

先日、イライラするエッジケースに遭遇しました。Claudeデスクトップアプリ内のClaude Codeパネルが、Gitをインストールするよう求めるモーダルを繰り返し表示したのです。

Claude Codeの「Gitをインストール」ダイアログ
ローカルセッションを実行するにはGitが必要です。 ターミナルでxcode-select --installを実行してCommand Line Toolsをインストールするか、Gitを直接ダウンロードするか、リモート環境に切り替えてください。

問題は、Gitはすでにインストールされていたことです。

ターミナルでgit --versionを実行すると、すぐに有効なバージョンが返ってきました。Claude Codeはコマンドラインからはシームレスに動作していました。Gitの存在を認めなかったのは、デスクトップGUIアプリだけだったのです。

macOS 27ベータを実行していたので、最初は「ベータのバグ」だと思いました。その思い込みだけで、1時間も迷路に迷い込んでしまいました。ここに、間違った道も含めた完全なポストモーテムを記します。

最初の推測:Command Line Toolsの破損

macOSでは、/usr/bin/gitは実際にはGitバイナリではなく、xcode-selectが現在指している開発者ディレクトリにコマンドを転送するシムランチャーです。主要なmacOSアップグレードでは、このポインタが壊れたり未設定になったりすることが頻繁にあり、OSアップデート後にGitが突然「消える」場合、古いCommand Line Toolsのインストールが教科書的な原因となります。

ベータOSリリース向けの直接パッケージアップデートがSoftware Updateで常に即座に提供されるわけではないため、.dmgApple Developer Downloadsページから直接ダウンロードしてインストールし、開発者ディレクトリを手動でリセットしました:

sudo xcode-select -s /Library/Developer/CommandLineTools
git --version   # git version 2.54.0 (Apple Git-157)
clang --version # Apple clang version 21.0.0

CLIではすべて問題ありませんでした:gitclangも動作しました。

しかし、デスクトップアプリを再度開いても、ダイアログは頑固に表示されたままでした。

シェルでGitが機能しているのにGUIに見えない場合、問題はGit自体ではなく、アプリが環境バイナリを解決する方法にありました。

2番目の推測:GUIのPATH環境

これはmacOSの典型的な落とし穴です。Finder、Dock、またはSpotlightから起動されたアプリは、シェルの起動スクリプト(.zshrc.bash_profile)で設定した環境変数や独自のPATH定義を引き継ぎません。GUIアプリケーションは最小限のlaunchdコンテキスト内で起動されます。シェルでは簡単に解決できるバイナリでも、GUIアプリからは完全に見えないことがあります。

さらに、Claudeのデスクトップアプリは起動時に環境をキャッシュします。アプリがアクティブな間にパスの問題を修正しても、アプリのシステム認識はハード再起動(Dockアイコンを右クリック→終了。単にウィンドウを閉じるのではなく)まで古いままです。

システムのデフォルトのlaunchd設定を確認しました:

launchctl getenv PATH
# (empty)

空で返ってきました。そこで、launchd用のベースラインとなるPATHを明示的に設定しました:

sudo launchctl config user path "/Library/Developer/CommandLineTools/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"

システムを完全に再起動した後、launchctl getenv PATHで更新された環境を確認しました。Claude Desktopを再起動し、勝利を確信しました。

まったく同じダイアログが表示されました。

この時点で、私は2つの正当なシステム問題——壊れたCLIツールのポインタと乏しいGUI環境——を診断し修正していました。どちらも修正する価値はありましたが、根本原因には対処できていませんでした。

根本原因:2022年からの壊れたシンボリックリンク

推測をやめて、実際のプロセスログを調べました。この正確な動作に関するGitHub issue(#54754)を確認すると、根本的な失敗モードが明らかになりました:

Failed to spawn /Users/xxx/bin/git: spawn /Users/xxx/bin/git EACCES

アプリはGitを*見つけられなかった*のではなく、システムの実行順序で壊れたGitエントリを最初に見つけ、それを実行しようとしてEACCES(許可拒否)エラーで失敗していたのです。

デスクトップアプリがサブプロセスを生成するとき、解決パスで最初に見つけた一致を実行しようとします。その候補が失敗したり実行権限がなかったりすると、インタラクティブシェルのように後続の一致にフォールバックするのではなく、プロセスは即座に中止されます。

登録されているすべてのgitバイナリパスを確認するため、解決チェックを実行しました:

which -a git
# /usr/local/bin/git
# /usr/bin/git

ありました:/usr/local/bin/gitが標準のシステムパス/usr/bin/gitより前に来ていました。

そのファイルを調べると、その起源が明らかになりました:

ls -la /usr/local/bin/git
# lrwxr-xr-x  1 epona  admin  28 Feb  8  2022 /usr/local/bin/git -> ../Cellar/git/2.35.1/bin/git

2022年2月に作成された残存シンボリックリンクでした。それは../Cellar/git/2.35.1/を指しており、数年前に消去された古いIntelベースのHomebrewインストールの遺物でした。(/usr/localはレガシーなx86 Homebrewパスです。Apple Silicon Homebrewは/opt/homebrewの下で動作します)。

ターゲットパスが存在しなくなったため、この壊れた参照を直接実行しようとするとエラーが発生しました。

解決には単一のクリーンアップコマンドが必要でした:

sudo rm /usr/local/bin/git

アクティブなパスを再度確認しました:

which -a git
# /usr/bin/git

git --version
# git version 2.54.0 (Apple Git-157)

デスクトップアプリケーションを強制終了して、再度起動しました。プロンプトは完全に消えていました。

重要なポイント

  1. シェルは壊れたパスを隠すが、GUIアプリは隠さない。 対話型シェルはエイリアス設定や環境変数の扱いによって孤立したバイナリを隠すことがありますが、スパウン方式のアプリケーション呼び出しは、最初の不正なエントリに遭遇すると即座に失敗します。
  2. `which -a` を使うこと。`which` だけでは不十分。 基本的な which git はアクティブなパスのみを表示しますが、which -a は環境全体の すべての インスタンスを優先順位順にリスト表示するため、影に隠れたり無効化されたバイナリがすぐにわかります。
  3. アプリケーションのエラーログを早めに確認する。 中間的な環境問題(Command Line Tools や launchctl 変数など)を修正するのは生産的に感じられましたが、実際のサブプロセススパウンログを直接読むことで、数秒で正確なパス障害を特定できました。

GUI開発ツールが、ターミナルでは正常に動作しているCLIバイナリが見つからないと報告する場合、which -a <tool> を実行してみてください。古いシンボリックリンクが先頭に立っている可能性が高いです。

Epona
執筆Epona

There's nothing wrong with having a little fun

x.com/simura_epona

コメントを読み込み中…