Claude Code / OpenHandsなどからVSCodeのGitHub Copilotを使える拡張機能「LM Proxy」を作った
VSCodeのLanguage Model APIを使って、GitHub CopilotをプロキシしてVSCodeの外部から使えるようにする「LM Proxy」という拡張機能を作りました。
Claude Code / OpenHands CLI / OpenAI Codex CLIなどで利用するモデルをGitHub Copilotのモデルにすることが可能です。OpenAI API / Anthropic API互換なので、その他のAPIエンドポイントを設定できるサービスで利用できるはずです。
使い方
拡張機能をインストールすると、VSCodeのステータスバーに「LM Proxy」という項目が追加されます。
項目をクリックするとQuick Picksが開きます。ここから、プロキシサーバの起動・停止やモデルの設定が可能です。
また、拡張機能の設定で、ポート番号の変更などがおこなえます(デフォルトは4000)。
その他詳しい使い方はドキュメントを参照してください。
例: Claude Codeでの使い方
例としてClaude CodeでLM Proxyを利用する方法を紹介します。
ANTHROPIC_BASE_URL の設定
export ANTHROPIC_BASE_URL="http://localhost:4000/anthropic/claude"
ANTHROPIC_BASE_URL
に http://localhost:4000/anthropic/claude
を設定します(Claude Code用エンドポイント)。
そして $ claude
でClaude Codeを起動。
API Base URL:
http://localhost:4000/anthropic/claude
という表示になっています。
LM Proxyの設定
LM Proxyの設定で、 Claude Code Background Model
と Claude Code Thinking Model
をそれぞれ設定します。例として、Background Modelに gpt-4o-mini
、Thinking Modelに claude-3.5-sonnet
を設定しています。
Quick Picksの Start Server
をクリックしてプロキシサーバを起動しておきます。
使ってみる
あとは普通に使うだけです。
実装について質問してみる。Readツールを使ってファイルの内容を読み取っている
リファクタリングの計画をTODOツールを使って立ててくれている
TODOを更新しつつファイルを編集していってくれている
実装について
最初はGitHub Copilot (Claude 3.5 Sonnet)を使って、Vibe Codingでコードを書かずに実装を進めていきました。途中から微妙な実装になってしまったので、人間が介入して完成させました。
一番人間が実装しないといけなかったのは、OpenAI API形式 / Anthropic API形式のリクエストをVSCode LM APIのリクエスト形式に変換するところと、VSCode LM APIのレスポンスをOpenAI API形式 / Anthropic API形式のレスポンスに再変換するところです。
Open AI APIとAnthropic APIのドキュメントはだいたいこの辺りですが、GitHub Copilotにドキュメントを渡しても微妙に違う実装をしたり、抜け漏れがあったりしたので、結局僕の方で1つずつオプションを見て、VSCode LM APIに変換できるものは変換する、そうでないものはどうするか考える、というような作業をやっていきました。
// --- messages変換 ---
const messages: vscode.LanguageModelChatMessage[] = []
// systemプロンプトがあればassistant roleで先頭に追加
if ('system' in anthropicRequest && anthropicRequest.system) {
if (typeof anthropicRequest.system === 'string') {
// stringの場合
messages.push(
new vscode.LanguageModelChatMessage(
vscode.LanguageModelChatMessageRole.Assistant,
`[SYSTEM] ${anthropicRequest.system}`,
'System',
),
)
} else if (Array.isArray(anthropicRequest.system)) {
// TextBlockParam[] の場合
for (const block of anthropicRequest.system) {
if (block.type === 'text' && typeof block.text === 'string') {
messages.push(
new vscode.LanguageModelChatMessage(
vscode.LanguageModelChatMessageRole.Assistant,
`[SYSTEM] ${block.text}`,
'System',
),
)
}
}
}
}
これはほんの一例ですが、VSCode LM APIではAnthropic APIのようにシステムプロンプトをセットすることが出来ません。なので、メッセージの配列にアシスタントメッセージとして [SYSTEM] ${anthropicRequest.system}
のような感じでシステムプロンプトを無理やりセットしています。
このような感じで、完全ではないにせよ、可能な限りOpenAI API / Anthropic API ←→ VSCode LM APIとの互換性を保つようにしています。
Tools変換
OpenAI API / Anthropic APIではRead, Edit, TODO, その他MCPサーバなどのToolsを利用することが出来ます。VSCode LM APIでもToolsを利用できるのですが、これも当然変換が必要です。
「Claude CodeでOpenAI API互換エンドポイントを使えるよ」みたいなライブラリなどが結構ありますが、このツール変換をしていないものが多いイメージです。ツール情報を渡さなければ、普通の会話は可能ですが、ファイルを読みったり編集したりといったことはおこなってくれません。
注意点と今後の課題
上記のように可能な限り変換処理を実装していますが、利用モデルが gpt-4.1
や gpt-4o
の場合、ツールを使ってくれず、ファイルの編集などがおこなわれず会話が終了してしまうことが多いです。一方 claude-3.5-sonnet
や claude-sonnet-4
のときはいい感じにツールを使ってくれるので、そもそものLLMの性能や性格によるのかも。
ただ、普通にGitHub CopilotでGPT-4.1を使うと普通に使えるのが謎…。GitHub Copilotのシステムプロンプトがめちゃくちゃよく考えられている可能性もあります。
今後改善出来そうなら改善したいポイントです。
まとめ
良ければインストールして使ってみて下さい!
IssueやPull Requestもお待ちしています。
Discussion