LM Warden

Claude Code を自分の GPU で。

Claude のログインはそのままに、ルールで指定したモデルをここで実行するか、完全にローカルで実行します。

ANTHROPIC_BASE_URL は一つ、応答の出どころは二つ。

Claude Code が Anthropic に送るリクエストはすべて、プランの使用量上限にカウントされるか、API キーでトークンごとに課金され、さらにコードを含むプロンプトがマシンの外に出ていきます。そうしたリクエストの多くは小さなものです。すでに持っているカードで応答すれば、かかるのは電気代だけで、上限にはカウントされず、プロンプトもホストに留まります。

Claude そのものがここで動くことはありません。このマシンが代わりに応答する Claude モデル (たとえば claude-haiku*) をルールで指定すると、読み込んだモデルが、Claude Code が要求した名前のまま代わりに応答します。Opus を含むそれ以外のリクエストは、ストリーミングも含め、自分のログインで Anthropic にバイト単位でそのまま渡されます。warden のキーは専用のヘッダーで送られるのでログインには一切触れず、「May relay to Anthropic」 フラグのないキーについては何も中継しません。

小さなモデルで十分でしょうか? 回答の品質は測定していないので、これはベンチマークではなく判断です。Claude Code は軽めのバックグラウンド作業に Haiku クラスのモデルを使っており、小さなローカル モデルはそこや、単純で明確に指定された編集の代わりとして妥当です。多数のファイルにまたがる変更、デバッグ、長い計画には、Sonnet と Opus を Anthropic のまま使ってください。ルールを追加しなければ、キャッチオール ルールによってそのように処理されます。より大きなカードでより大きなモデルを使えば、この境界は変わります。以下の Claude Code とレプリカの測定には 4B を使いました。

コンテキストはチャットではなく Claude Code に合わせて設定してください。自社のセッションでは最初のターンが 38,167 トークンだったので、ローカル モデルには 40k トークンを大きく超えるコンテキストが必要です。

Where a request from Claude Code goes Claude Code sends a request to LM Warden with two headers: Authorization, its own login, and X-LMWarden-Key, the warden key. LM Warden tries its rules in order and the first match wins. A request for claude-haiku or claude-sonnet matches a rule, is answered by your local model under the Claude name it asked for, and goes through translate, the scheduler and the replica router to one of four vLLM replicas, the conversation staying on its home replica. A request that matches no rule, such as Opus, or any other /v1 path, is passed to api.anthropic.com with the login forwarded and the warden key removed. If the local leg fails before the first byte, a dashed path sends the request to Anthropic, or the rule can refuse with a 529 that Claude Code retries. Claude Code ANTHROPIC_BASE_URL points at the warden Authorization your own login X-LMWarden-Key vw_…, the warden key POST /v1/messages LM Warden rules, first match wins claude-haiku* your local model claude-sonnet* your local model anything else pass through reads the warden key, never forwards it match Local leg translate to the engine scheduler, key priority replica router breaker: 3 failures, open 60 s session id picks the replica vLLM replica 0 vLLM replica 1 vLLM replica 2 vLLM replica 3 a conversation stays on its replica no match: Opus, or any other /v1 path passed on byte for byte, streaming included only for a key with “May relay to Anthropic” local leg failed before the first byte: the rule falls back to Anthropic, or refuses with a 529 that Claude Code retries api.anthropic.com your login forwarded, the warden key removed Off by default. The content of a passed-through request is never logged, stored or shown.
Where a request from Claude Code goes The same flow as the wide drawing, top to bottom. Claude Code sends a request to LM Warden with its own login in Authorization and the warden key in X-LMWarden-Key. LM Warden tries its rules in order; a request for claude-haiku or claude-sonnet is answered by your local model and goes down through the local leg (translate, scheduler, replica router) to one of four vLLM replicas, where the conversation stays. A request that matches no rule goes down the right-hand line to api.anthropic.com, with the login forwarded and the warden key removed. A dashed line from the local leg to Anthropic is the fallback when the local leg fails before the first byte; the rule can instead refuse with a 529 that Claude Code retries. Claude Code Authorization your own login X-LMWarden-Key the warden key ANTHROPIC_BASE_URL = the warden POST /v1/messages LM Warden rules, first match wins claude-haiku* your local model claude-sonnet* your local model anything else pass through reads the warden key, never forwards it match Local leg translate to the engine scheduler, key priority replica router breaker: 3 failures, open 60 s session id picks the replica vLLM replica 0 vLLM replica 1 vLLM replica 2 vLLM replica 3 a conversation stays on its replica no match: Opus, any other /v1 path dashed: the local leg failed before its first byte, so the rule falls back, or refuses with a 529 that Claude Code retries api.anthropic.com your login forwarded, the warden key removed Off by default. Only a key with “May relay to Anthropic” is passed through.
図 2リクエストの行き先。ルールは順に試され、最初に一致したものが適用されます。ローカルの応答も、ほかのリクエストと同じスケジューラーとレプリカ ルーターを通ります。レプリカはモデルの完全なコピー一つで、ここでは GPU ごとに一つです。最初のバイトより前にローカルで失敗すると、Anthropic に送られるか、Claude Code が再試行する 529 として返されます。3 回連続で失敗するとそのモデルのブレーカーが開き、60 s の間は何も送られません。

テキストによる説明:Claude Code は、Authorization に自分の Anthropic ログインを、X-LMWarden-Key に warden のキーを入れてリクエストを warden に送ります。warden はルールを順に試します。ルールが指定するモデル宛てのリクエストは変換され、スケジューラーでキューに入り、レプリカ ルーターによって vLLM レプリカの一つに送られます。Opus などそれ以外のリクエストは、ログインを転送し warden のキーを取り除いたうえで api.anthropic.com に渡されます。ローカル側が最初のバイトより前に失敗した場合、リクエストは Anthropic に送られるか、ルールが 529 を返して拒否し、Claude Code が再試行します。

export ANTHROPIC_BASE_URL=https://warden.example
export ANTHROPIC_CUSTOM_HEADERS="X-LMWarden-Key: vw_…"
claude

Claude Code 2.1.227 以降が必要です。通常の claude のログインはそのまま使います。キーは ANTHROPIC_API_KEY ではなく専用のヘッダーに入ります。

コンソールの Router ページ。緑のバナーに 「Routing normally」 と 「96% answered locally since 13:38」 とある。「Where each Claude model goes. First match wins」 の下で、ルール 1 は claude-haiku* を読み込み済みモデル qwen3-4b-dp4 に送り、「If it fails: Anthropic」 と 「Thinking off」 が付いている。最後の行はキャッチオールで、ほかのすべての Claude モデルと /v1 パスはユーザー自身のログインで Anthropic に送られ、「May relay to Anthropic」 の付いたキーが必要。Traffic パネルはローカル 107、Anthropic パススルー 2、Anthropic へのフォールバック 0、拒否またはエラー 2 を数え、理由として no_upstream_credential と relay_not_allowed を一件ずつ挙げている。 最初の一致が適用され、ほかのモデルはすべて Anthropic へ Anthropic にはユーザー自身のログインで接続
図 3warden の Router ページ (13:38 から稼働):「Routing normally」 で、再起動以降のリクエストの 96% にローカルで応答しています。一つのルールが claude-haiku* をローカル モデルに送り、キャッチオールがそれ以外をすべて Anthropic に渡します。ルールには試される順に番号が付いています。Traffic パネルはローカル 107、パススルー 2、フォールバック 0、拒否 2 を数えています。画像を横にスクロールするとページ全体が見られます。

最初のターンは遅いものと考えてください。以前のセッションでは Claude Code の最初のターンが 38,167 トークンで、ローカル モデルは 32,768 トークンのコンテキストで読み込まれていたため、エンジンがそれを拒否し (status_400)、リクエストは代わりに Anthropic に送られました。コンテキストを 65,536 トークンに上げ、fp8 の KV キャッシュ (アテンション キャッシュを 8 ビットで保持し、メモリは半分) を使うと、16 GiB のカード上の 4B モデルは同じターンに 28 s でローカルに応答しました。38k トークンのプロンプト全体をキャッシュなしで最初から読み込んだ結果です。会話の後のターンでは、プロンプトの大部分がすでにエンジンのキャッシュにあります。図 4 の claude-haiku* ルールの最初のバイトまでの時間の中央値は 290 ms です。

Router のアクティビティ ページ。四つのカウンター:ローカル 107、Anthropic パススルー 2、フォールバック 0、拒否 · エラー 2 · 0。「By rule」 表には、claude-haiku* を qwen3-4b-dp4 に送るルールのローカル、フォールバック、拒否の件数、p50 と p95 のレイテンシと最初のバイトまでの時間、ブレーカーの状態 closed が示され、パススルーの行には Anthropic に渡されたリクエストの同じ計時が示されている。ローカル モデルの表には qwen3-4b-dp4 がブレーカー closed で表示され、「Fallback reasons」 パネルには no_upstream_credential と relay_not_allowed が一件ずつ挙がっている。 このモデルのブレーカー:closed ルールによって Anthropic に送られた、または拒否されたリクエストの理由別内訳
図 4同じ期間の Router アクティビティ:ローカルで応答したリクエスト 107、Anthropic へのパススルー 2、フォールバック 0、拒否 2、エラー 0。その下に、ルールごとの p50 と p95 のレイテンシと最初のバイトまでの時間、ローカル モデルごとのブレーカー、ルールによってリクエストが Anthropic に送られた理由や拒否された理由。カウンターはプロセスごとで、再起動でゼロに戻ります。2026 年 10 月 4 日に記録。画像を横にスクロールするとページ全体が見られます。
プロトコル
Anthropic Messages
サポート
完全サポート

ルールで指定した Claude モデルはここで実行され、それ以外のモデルと /v1 パスはすべて自分のログインで Anthropic に送られます。ルーター モードでは、warden のキーを ANTHROPIC_API_KEY や ANTHROPIC_AUTH_TOKEN に入れないでください。ログインが置き換えられてしまいます。ローカル専用では、小さなバックグラウンド タスクも含めてすべてを一つの提供中のモデルで実行し、Anthropic には何も送りません。

要件

  • Claude Code 2.1.227 以降 (ANTHROPIC_CUSTOM_HEADERS)。
  • ルーティングがオンで、有効なルールが一つ以上必要です。
  • キーに Anthropic への中継が許可されている必要があります (May relay)。
  • 49,152 トークン以上のコンテキストが必要です。最初のターンだけで、ファイルを読む前から約 38,000 トークンあります。
  • 実際のセッションには 131,072 トークン以上。短いセッションならそれより少なくても動きます。
  • Claude Code が、モデル名がカタログにないと警告することがあります。これは情報提供にすぎません。200k のウィンドウを想定し、それに合わせて自動圧縮します。CLAUDE_CODE_MAX_CONTEXT_TOKENS にモデルの実際のコンテキスト ウィンドウを設定してください。

セットアップ

コンソールでは、Connect が warden のアドレス、キー、選んだモデルを入れてこれらのファイルを書き出します。ここではプレースホルダーを使って示しています。

Router:Claude のログインはそのまま

Claude のログインは引き続き Anthropic に送られます。warden のキーは専用のヘッダーで送られ、ルールで指定したモデルにはここで応答します。

シェル
export ANTHROPIC_BASE_URL=https://your-warden
export ANTHROPIC_CUSTOM_HEADERS="X-LMWarden-Key: vw_YOUR_KEY"
claude
settings.json (~/.claude/settings.json)
{
  "env": {
    "ANTHROPIC_BASE_URL": "https://your-warden",
    "ANTHROPIC_CUSTOM_HEADERS": "X-LMWarden-Key: vw_YOUR_KEY"
  }
}

ローカル専用 (Anthropic アカウント不要)

すべてのモデル スロットが選んだ提供中のモデルになり、warden のキーが認証トークンになります。Anthropic には何も送られません。

シェル
export ANTHROPIC_BASE_URL=https://your-warden
export ANTHROPIC_AUTH_TOKEN=vw_YOUR_KEY
export ANTHROPIC_MODEL=your-served-model-name
export ANTHROPIC_DEFAULT_OPUS_MODEL=your-served-model-name
export ANTHROPIC_DEFAULT_SONNET_MODEL=your-served-model-name
export ANTHROPIC_DEFAULT_HAIKU_MODEL=your-served-model-name
export CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1
export CLAUDE_CODE_MAX_CONTEXT_TOKENS=32768
# The model's context window is unknown: 32768 is a guess. Set it to the model's real window.
settings.json (~/.claude/settings.json)
{
  "env": {
    "ANTHROPIC_BASE_URL": "https://your-warden",
    "ANTHROPIC_AUTH_TOKEN": "vw_YOUR_KEY",
    "ANTHROPIC_MODEL": "your-served-model-name",
    "ANTHROPIC_DEFAULT_OPUS_MODEL": "your-served-model-name",
    "ANTHROPIC_DEFAULT_SONNET_MODEL": "your-served-model-name",
    "ANTHROPIC_DEFAULT_HAIKU_MODEL": "your-served-model-name",
    "CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS": "1",
    "CLAUDE_CODE_MAX_CONTEXT_TOKENS": "32768"
  }
}

公式ドキュメント:https://code.claude.com/docs/en/llm-gateway (2026-10-04 時点)。