LM Warden

Claude Code,运行在你自己的 GPU 上。

保留你的 Claude 登录,让规则指定的模型在这里运行;或者完全在本地运行。

一个 ANTHROPIC_BASE_URL,回复可能来自两个地方。

Claude Code 发给 Anthropic 的每个请求都会计入你套餐的用量限制,或者在 API 密钥上按 token 计费,并且会把它的提示词(包括你的代码)带出你的机器。这些请求中有很多都很小。用你已经拥有的显卡来应答它们,花费的只是电费,它们不计入你的用量限制,提示词也留在你的主机上。

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 个 token,因此本地模型需要远超 40k token 的上下文。

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,或者以 529 返回,由 Claude Code 重试;连续失败 3 次后,该模型的熔断器断开:60 s 内不会再向它发送任何请求。

文字说明:Claude Code 把请求发给 warden,Authorization 中带着它自己的 Anthropic 登录,X-LMWarden-Key 中带着 warden 密钥。warden 按顺序尝试它的规则。针对某条规则指定的模型的请求会被转换,由调度器排队,再由副本路由器发送到某一个 vLLM 副本。其他任何请求(例如 Opus)都会转发到 api.anthropic.com,登录信息原样转发,warden 密钥被移除。如果本地这一段在第一个字节之前失败,请求会转到 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 自 13:38 起运行后的 Router 页面:“Routing normally”,自重启以来 96% 的请求在本地应答。一条规则把 claude-haiku* 发往本地模型,兜底规则把其余所有请求转发给 Anthropic;规则按尝试顺序编号。Traffic 面板统计本地 107 个、直通 2 个、回退 0 个、拒绝 2 个。左右滚动图片可查看整个页面。

第一轮通常最慢。在之前的一次会话中,Claude Code 的第一轮有 38,167 个 token,而本地模型加载时的上下文是 32,768 个 token,因此引擎拒绝了它(status_400),请求改发给了 Anthropic。把上下文提高到 65,536 个 token 并使用 fp8 KV 缓存(注意力缓存以 8 位保存,内存减半)后,16 GiB 显卡上的 4B 模型在 28 s 内于本地应答了同样的这一轮,整个 38k token 的提示词都需从头读取,缓存中还什么都没有。对话的后续轮次会发现大部分提示词已经在引擎的缓存中:图 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 个请求在本地应答,2 个直通到 Anthropic,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 个 token 的上下文:仅第一轮在读取任何文件之前就约有 38,000 个 token。
  • 实际会话建议 131,072 个 token 或更多;短会话用更少也可以。
  • Claude Code 可能会警告该模型名称不在它的目录中。这只是提示信息:它会假定窗口为 200k,并据此自动压缩。请把 CLAUDE_CODE_MAX_CONTEXT_TOKENS 设为模型的真实上下文窗口。

设置

在控制台中,Connect 会用你的 warden 地址、你的密钥和你选择的模型写入这些文件。下面以占位符展示这些文件。

Router:保留你的 Claude 登录

你的 Claude 登录继续发往 Anthropic;warden 密钥放在单独的标头中传输,你的规则指定的模型由这里应答。

Shell
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 发送任何内容。

Shell
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)。