「Failed to spawn /usr/bin/ssh」の原因と対処 — Claude Desktop
Claude DesktopのSSHセッションがWindowsでFailed to spawn /usr/bin/sshエラーになる原因と、symlink回避策の先で出る別のエラーを、ログの見分け方つきで解説します。
Windows版Claude Desktopで、CodeタブからSSHセッションを使ってリモートマシンに接続しようとすると、Failed to spawn /usr/bin/ssh: spawn /usr/bin/ssh ENOENTというエラーで接続自体が始まらないことがあります。SSHバイナリを起動するパスがUnix系の/usr/bin/sshに固定されており、Windowsにはそのパスが存在しないために起きる不具合です。GitHub issue #25659で2026年2月14日に報告されています。
回避策のシンボリックリンクでこのエラーは消えますが、その先で別のエラーに突き当たる報告もあります。どちらの段階で止まっているかはログの文言で見分けられます。Windowsでは、ウィンドウが最前面に固定される別の不具合も報告されています。
このTipsでできること
自分のエラーがどの不具合に当たるのかを、ログの1行から切り分けられるようになります。シンボリックリンクの回避策と、その回避策の先で出る非標準ポートの問題、~が展開されない問題も扱います。
ログの文言でどの段階かを見分ける
Desktopは接続の記録をssh.logに残します。issueに貼られたログから、1段階目から2段階目へは順に現れ、3段階目はそれらとは別の問題です。
エラー文言で見る3つの症状
- 1
ENOENTで止まる
[RemoteServerController] Connection failed: Failed to spawn /usr/bin/ssh: spawn /usr/bin/ssh ENOENTが出ます。SSHバイナリを起動する前の失敗で、鍵やポートの設定は無関係です。 - 2
Host denied (verification failed)で止まる
[SSH2Connection]で始まる行が並び、Host <host>:<port> is not in known_hostsのあとにHost denied (verification failed)が出ます。/usr/bin/sshのリンクを作ったあとに現れた段階です。 - 3
key: falseと出る(別の問題)
接続の行に
key: falseが出るときは、sshIdentityFileの指定先を鍵として読めていません。~で始まるパスを指定していると、この形になる報告があります。
1段階目の対処は「シンボリックリンクの回避策」の節に、2段階目の仕組みは「非標準ポートでホスト鍵検証が壊れる仕組み」の節にあります。3段階目は「sshIdentityFileの~がWindowsで展開されない」の節が対応します。
実際に出るエラーメッセージと発生条件
報告者の環境はWindows 11 Pro、Claude Code Desktop(最新版)、OpenSSH 10.2p1導入済みでした。ターミナルからはsshコマンドが正常に動くのに、Desktop側のSSHセッション機能だけがこのエラーで止まります。
再現手順は次の4ステップです。
- Windows 11でClaude Desktopを開く
- SSHの機能・設定画面に移動する
- 任意のマシンへのリモートSSH接続を設定する
- SSHリモート機能で接続を試みる
期待される結果は接続の確立、実際の結果はFailed to spawn /usr/bin/ssh: spawn /usr/bin/ssh ENOENTでの失敗です。報告フォームの「リグレッションか」の欄は「No, this never worked」で、過去バージョンからの後退ではなく最初から存在した不具合だとされています。
原因は/usr/bin/sshのハードコードとみられる
報告によると、SSHセッション機能はSSHバイナリのパスとしてUnix系の/usr/bin/sshを固定で参照しています。WindowsでSSHクライアントが置かれる場所は通常C:\Windows\System32\OpenSSH\ssh.exe(標準搭載のOpenSSH)かC:\Program Files\Git\usr\bin\ssh.exe(Git for Windows付属)のいずれかです。/usr/bin/sshというパス自体がWindowsには存在しません。
報告者が求めた期待動作は、プラットフォームを検出して適切なパスに切り替えるか、システムのPATHを参照する実装への変更でした。
この不具合が影響するのはClaude DesktopのSSHセッション機能です。ターミナルで直接claudeコマンドを実行する運用は対象外です(詳しくは「影響範囲」の節)。DesktopのSSHセッションとターミナル単体での認証手順は、Claude Code SSH接続ガイドにまとまっています。
シンボリックリンクの回避策と、そこで見つかった別の不具合
報告の翌日、ユーザーのSSS135氏がシンボリックリンクを使った回避策を共有しました。
mkdir C:\usr\bin
mklink C:\usr\bin\ssh.exe "C:\Windows\System32\OpenSSH\ssh.exe"/usr/bin/sshが探しに来るパスへ、標準搭載のOpenSSHへのシンボリックリンクを事前に作っておく方法です。ENOENTは消えますが、SSS135氏は直後にHost denied (verification failed)という別のエラーに突き当たったと報告しています。
pockerhead氏が同じ回避策で詳しく検証したところ、ログの表記が[SSH2Connection]に変わりました。システムのsshを起動する代わりに、アプリ内蔵のssh2ライブラリで接続しているというのが同氏の見立てです。この内蔵ライブラリ側で、非標準ポートのホスト鍵検証が壊れていました。
非標準ポートでホスト鍵検証が壊れる仕組み
pockerhead氏の検証環境はWindows 11 Pro(ビルド10.0.26100、x64)、Claude Desktop 1.1.3189、同梱のClaude Code 2.1.41でした。接続先はポート40010(非標準)のクラウドGPUインスタンスです。symlink適用後のログは次の順で失敗します。
[SSH2Connection] Resolved root@<host> -> root@<host>:40010
[SSH2Connection] Host <host>:40010 is not in known_hosts
[SSH2Connection] Connecting to root@<host>:40010 (agent: false, key: true, proxy: false, keyboard: true)
[SSH2Connection] Connection error: Host denied (verification failed)該当するホスト鍵は~/.ssh/known_hostsに存在し、ターミナルからssh -p 40010 root@<host>を実行すれば即座に接続できました。同氏はssh-keygen -F "[<host>]:40010"で、ed25519・rsa・ecdsaの3種の鍵がすべて登録されていることも確かめています。それでもDesktopアプリだけが鍵を見つけられません。次の対応はどれも効果がなく、試行のたびにDesktopを完全に再起動しても同じエラーでした。
| 試した対応 | 結果 |
|---|---|
known_hostsに[<host>]:40010形式(OpenSSH標準)で登録 | 結果認識されない |
ポートなし・ブラケットなしの<host>形式で登録 | 結果認識されない |
ログ表記に合わせた<host>:40010形式で登録 | 結果認識されない |
ssh_configs.jsonのtrustedHostsに各形式を登録 | 結果効果なし |
~/.ssh/configにStrictHostKeyChecking no | 結果無視される |
~/.ssh/configにUserKnownHostsFile /dev/null | 結果無視される |
同氏が挙げた根本原因は次の4点です。
- OpenSSHは非標準ポートのエントリを
[host]:portのようにブラケット付きでknown_hostsに保存するが、内蔵のssh2ライブラリはブラケットなしのhost:portで検索するため一致しない - 未知のホスト鍵を許可するUIが無く、鍵が見つからないと即座に接続を拒否する。「信頼して続行」のようなプロンプトが無く、選べるのは同じエラーを繰り返す「Try again」だけ
ssh_configs.jsonのtrustedHostsがホスト鍵検証に効かない~/.ssh/configのHost・Port・HostNameは正しく読み込む一方、StrictHostKeyCheckingやUserKnownHostsFileといったセキュリティ関連の設定は無視する
1点目のブラケット形式は、OpenSSHの標準的な保存形式です。一時ディレクトリに作ったknown_hostsで、保存形式と検索形式の食い違いを再現できます(出力例はmacOSのOpenSSH 10.2p1のものです)。
# 非標準ポートの鍵は [host]:port の形で保存される
$ cat known_hosts
[gpu.example.invalid]:40010 ssh-ed25519 AAAA...
$ ssh-keygen -F "[gpu.example.invalid]:40010" -f known_hosts
# Host [gpu.example.invalid]:40010 found: line 1
[gpu.example.invalid]:40010 ssh-ed25519 AAAA...
# ブラケットなしの host:port では見つからない(終了コード 1)
$ ssh-keygen -F "gpu.example.invalid:40010" -f known_hosts
$ echo $?
1ブラケットなしの検索では何も返らず、ログのis not in known_hostsと同じ状況になります。ssh -Gで設定の解決結果を出すと、StrictHostKeyCheckingとUserKnownHostsFileは~/.ssh/configの記述どおりに反映されます。
$ ssh -G -F cfg gpu | grep -E "^(hostname|port|stricthostkeychecking|userknownhostsfile) "
hostname gpu.example.invalid
port 40010
stricthostkeychecking false
userknownhostsfile /dev/nullOpenSSH本体が解釈する設定を、Desktopのssh2経路が読み飛ばしている、というのが報告の指摘です。
issueには5つの修正案も書き添えられています。ブラケット形式への対応、未知ホストを承認するUI、trustedHostsを実際に効かせること、StrictHostKeyCheckingに従うこと、Windowsでの~展開です。同氏は「Claude Desktopで非標準ポートに接続するWindowsユーザーの回避策は無い」と書いています。
sshIdentityFileの~がWindowsで展開されない
同じ報告で、ssh_configs.jsonのsshIdentityFileに~を使ったパスを指定すると、Windows上では展開されないとも指摘されています。ログのkeyフィールドが違いを示します。
sshIdentityFileの書き方でkeyが変わる
~で始まるパス
"sshIdentityFile": "~/.ssh/id_ed25519"と書くと、ログのkeyがfalseになり、鍵が見つかりません。
フルパス
"sshIdentityFile": "C:\\Users\\<user>\\.ssh\\id_ed25519"と書くと、keyがtrueになり、鍵を認識します。JSONなのでバックスラッシュを二重に書きます。
この報告の環境はDesktop 1.1.3189です。公式ドキュメントの入力例は~/.ssh/id_rsaや~/.ssh/id_ed25519を使っています。Windowsでユーザーディレクトリを含むフルパスにしておくと、この食い違いの影響を避けられます。
影響範囲とDesktopのSSH接続の前提
SSH接続の追加ダイアログには、Name・SSH Host・SSH Port・Identity Fileの4項目があります。SSH Hostにはuser@hostnameか~/.ssh/configで定義したホスト名を入れ、SSH Portを空にすると22番か設定ファイルのポートが使われます。接続先のリモートマシンはLinuxかmacOSである必要があります。初回の接続時には、DesktopがリモートマシンへClaude Codeを自動でインストールします。Windows同士で試している場合は、この前提に当たらないか先に見てください。
Windowsには、SSHとは別にWSL 2のディストリビューションを実行環境に選ぶ方法があります。同じPC上のLinux環境で動かしたいだけなら、SSHで自分自身につなぐ必要はありません。
設定の保存先は資料によって違います。issueのログと報告ではssh_configs.jsonが登場します。公式ドキュメントでは、ダイアログで追加した接続は~/.claude/settings.jsonのsshConfigsに保存されると書かれています。報告時点の1.1.3189と現在のドキュメントとで、保存先が変わっている可能性があります。
管理者向けにはsshHostAllowlistがあり、~/.ssh/configの解決後のホスト名(ssh -Gの結果)で判定します。ただしこれはDesktopアプリだけが読む設定で、Bashツール経由のsshコマンドは制限しません。管理設定で配る場合、sshConfigsはSSHセッションでもリモートではなくローカルマシンの管理設定から読まれます。sshHostAllowlistは管理設定でのみ有効で、ユーザー設定に書いても無視されます。
WindowsとClaude Codeの組み合わせでは、今回とは別の不具合も報告されています。Git Bashで発生するnulという名前のファイルが生成される不具合や、shebang付きスクリプト実行時にstdoutが空になる不具合があります。ARM64版でclaude.exeが0xC0000005でクラッシュする不具合も別の問題です。エラーメッセージやログの文言で切り分けると、症状を混同せずに済みます。
issueの経過と開発側の返信
issueに動きがあったのは2月14日・15日・16日・24日の4日です。
issue #25659の経過
- 2026-02-14報告と重複候補の通知
報告の数分後に自動botが重複候補として#25187と#7528を挙げました。どちらもWindowsでパスや実行ファイルが固定されている不具合です。3日以内にコメントが無ければ自動クローズする、という通知も付きました。
- 2026-02-15回避策と第2の不具合
同じ症状を訴えるコメントが重なり、SSS135氏がsymlinkの回避策を共有しました。pockerhead氏が非標準ポートの検証結果と
~の問題を報告しました。 - 2026-02-16開発側の返信とクローズ
リポジトリの貢献者であるamorriscode氏が「Sorry about this folks, this will be fixed in the next release.」と返信しました。issueはその約30秒後に、重複としてクローズされています。
- 2026-02-24自動ロック
7日間動きが無かったとして、botがissueを自動でロックしました。
ユーザー側の改善案として、evaneaston氏は、Windows標準のOpenSSHをそのまま起動する実装を挙げました。Git BashやWSLが使える環境では、そちら経由の接続も選べるようにする案です。ただしこれは利用者個人の要望で、Anthropicが採用を約束した設計ではありません。
返信は「next release」と述べるだけで、版番号も、修正の対象がENOENT・ホスト鍵検証・~展開のどこまでかも書いていません。ロック時のbotのコメントは、同様の問題が続く場合は新しいissueを立てて元のissueを参照するよう案内しています。ENOENTが直った版でも非標準ポートや~の症状が残るときは、ログの文言を添えた新しい報告が受け皿になります。
まとめ
非標準ポートのホストでHost deniedになる場合、known_hostsや~/.ssh/configの書き換えでは解消しなかったという報告です。同じPC上のLinux環境で動かしたいだけなら、WSL 2を実行環境に選ぶ道があります。ターミナルのOpenSSHやClaude Code CLIで接続できているなら、問題はDesktopのSSHセッション側にあります。