神楽坂のシステムやさん通信

VS Code Remote SSH:外部ターミナルから VS Code をエディタとしてスマートに呼び出す

うぱるぱ tech
VS Code Remote SSH:外部ターミナルから VS Code をエディタとしてスマートに呼び出す

解決したい課題

VS Code Remote(SSH)は強力ですが、ターミナル操作だけは iTerm2 などのお気に入りの外部ターミナルで、行いたい場面があります。

しかし、外部ターミナルからだと、そのままでは VS Code をシームレスにエディタとして利用できません。

  • iTerm2, Alacritty, WezTerm などの外部ターミナルから code ファイル名 でファイルを開きたい
  • git commitcrontab -e のエディタとして VS Code を使いたい。ただし、VS Code が未起動なら別のエディタを自動で起動したい

これらを解決するラッパースクリプトを紹介します。

背景:なぜ VS Code 外のターミナルから code が動かないのか

VS Code 内の統合ターミナルでは、VS Code サーバーと通信するための環境変数(VSCODE_IPC_HOOK_CLI)や、専用の実行ファイルへのパスが自動で設定されています。

しかし、外部ターミナルにはこれらの情報が引き継がれません。そのため、単に code コマンドを実行しても「VS Code のウィンドウでファイルを開く」という動作にならないのです。

この問題自体はよく知られており、解決策を紹介する記事もあります。

よくある解決策は .zshrc.bashrc にソケット探索の処理を書くことですが、シェル起動時に一度だけ評価されるため、VS Code を後から起動・再起動した場合に追従できません。Zenn の記事のように独立したスクリプトにすれば毎回評価できますが、VS Code が起動していないときのフォールバックは考慮されていません。

本記事では、実行のたびに VS Code の通信用ソケットを探索し、適切なエディタを選択するスクリプトを作成します。

解決策:ラッパースクリプト editor

まず、スクリプトを配置するためのディレクトリ(例:~/bin)を作成し、そこに editor という名前で以下のスクリプトを保存します。

スクリプトの作成

#!/bin/bash
# 最新の通信用ソケットを探索
export VSCODE_IPC_HOOK_CLI=$(ls -t /run/user/$(id -u)/vscode-ipc-*.sock 2>/dev/null | head -1)
# VS Code の CLI 実行ファイルのパスを取得
vscode_code=$(ls -td ~/.vscode-server/cli/servers/*/server/bin/remote-cli/code 2>/dev/null | head -1)

# VS Code が利用可能な場合
if [ -S "$VSCODE_IPC_HOOK_CLI" ] && [ -n "$vscode_code" ]; then
  if [ $# -eq 0 ]; then
    # 引数なしの code コマンドはそのまま終了することが多いため、
    # エディタとして呼び出された場合はファイル指定を促すようにします
    echo "VS Code使用時は、ファイルを指定してください: editor <ファイル名>"
    exit 1
  fi
  # VS Code が背後に隠れている場合や、起動のラグを考慮してメッセージを表示
  echo "Opening in VS Code..."
  # --wait をつけることで、VS Code 上で閉じるまでコマンドを待機させます
  "$vscode_code" --wait "$@" >/dev/null 2>&1
  exit $?
else
  # VS Code が見つからない場合は、代替エディタ(nano, vim 等)を起動
  nano "$@"
fi

実行権限の付与

chmod +x ~/bin/editor

環境設定

作成したスクリプトをどこからでも呼び出せるようにし、システムの標準エディタとして登録します。.zshrc.bashrc に以下を追記してください。

# ~/bin にパスを通す(未設定の場合)
export PATH="$HOME/bin:$PATH"

# 標準エディタとして登録
export EDITOR="$HOME/bin/editor"
export VISUAL="$HOME/bin/editor"

ポイント解説

最新のソケットを自動探索

.zshrc などに直接ソケットパスを書く方法もありますが、それだと VS Code を再起動した際にパスが変わり、動かなくなることがあります。このスクリプトは実行のたびに /run/user/ 下のソケットを探しに行くため、接続状況の変化に柔軟に対応できます。

外部ターミナルからの利用

このスクリプトを通すことで、VS Code の「統合ターミナル」の中であるかどうかを意識せず、使い慣れた外部ターミナルから editor と打つだけで VS Code を呼び出せるようになります。

引数なし実行のハンドリング

code コマンドを引数なしで実行すると、単に終了してしまう挙動になります。editor スクリプト経由で呼ばれた際に何も起きないと混乱するため、ファイル指定がない場合はメッセージを表示するようにしています。

環境変数 EDITORVISUAL のどちらを参照するかはプログラムによって異なります。gitcrontab をはじめ、多くのツールは VISUAL を優先しますが、一部のツールや環境によっては EDITOR のみが参照されることもあります。どちらの変数から呼ばれても同じ挙動になるよう、両方に設定しておくのが最も確実です。

活用シーン

このスクリプトを環境変数 EDITOR/VISUAL に設定しておくと、以下のような場面で自動的に VS Code が使われます。

  • git commit — コミットメッセージの編集
  • git rebase -i — インタラクティブリベースの操作
  • crontab -e — crontab の編集
  • Ctrl+x, Ctrl+e — (Bash/Zsh の行編集)
  • Claude Code の Ctrl+X, Ctrl+E — プロンプト入力時の外部エディタ起動

もし VS Code を立ち上げていない状態でこれらのコマンドを打っても、自動的に nano(または設定したエディタ)が立ち上がるため、作業が止まる心配もありません。

動作まとめ

状態editor file.txteditor(引数なし)
VS Code 起動中VS Code で開くガイドメッセージを表示
VS Code 未起動nano で開くnano で開く

おわりに

VS Code 大好きなのですが、iTerm2のtmux統合(tmux -CC)が便利なので、VS Code内のターミナルを使わないことも多かったのです。そういう時でも、ファイル編集時はVS Codeを使いたかったので、とても便利になりました。 crontab編集時に、copilotが補完してくれるのも地味に便利です。

ちょっとした設定ですが、同じようにVS Codeを愛用している方の参考になれば嬉しいです。