icebear0828 Claude Opus 4.6 commited on
Commit
2f3712c
·
1 Parent(s): 92c5df7

feat: Claude Code quick setup — dashboard card, model aliases & README

Browse files

Add one-click env var configuration for Claude Code in the web dashboard
with model selector (opus/sonnet/haiku) and copy-all button. Map Claude
model names to Codex models in aliases config.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

README.md CHANGED
@@ -154,6 +154,28 @@ curl http://localhost:8080/v1/chat/completions \
154
 
155
  ## 🔗 客户端接入 (Client Setup)
156
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  ### Cursor
158
 
159
  Settings → Models → OpenAI API Base:
 
154
 
155
  ## 🔗 客户端接入 (Client Setup)
156
 
157
+ ### Claude Code
158
+
159
+ 在终端设置环境变量,即可让 Claude Code 通过 codex-proxy 使用 Codex 模型:
160
+
161
+ ```bash
162
+ export ANTHROPIC_BASE_URL=http://localhost:8080
163
+ export ANTHROPIC_API_KEY=your-api-key
164
+ export ANTHROPIC_MODEL=claude-opus-4-6 # Opus → gpt-5.3-codex(默认)
165
+ # export ANTHROPIC_MODEL=claude-sonnet-4-6 # Sonnet → gpt-5.2-codex
166
+ # export ANTHROPIC_MODEL=claude-haiku-4-5-20251001 # Haiku → gpt-5.1-codex-mini
167
+
168
+ claude # 启动 Claude Code
169
+ ```
170
+
171
+ | Claude Code 模型 | 映射到 Codex 模型 |
172
+ |------------------|------------------|
173
+ | Opus (`claude-opus-4-6`) | `gpt-5.3-codex` |
174
+ | Sonnet (`claude-sonnet-4-6`) | `gpt-5.2-codex` |
175
+ | Haiku (`claude-haiku-4-5-20251001`) | `gpt-5.1-codex-mini` |
176
+
177
+ > 也可以在控制面板 (`http://localhost:8080`) 的 **Claude Code Quick Setup** 卡片中一键复制环境变量。
178
+
179
  ### Cursor
180
 
181
  Settings → Models → OpenAI API Base:
config/models.yaml CHANGED
@@ -74,3 +74,10 @@ aliases:
74
  codex: "gpt-5.3-codex"
75
  codex-max: "gpt-5.1-codex-max"
76
  codex-mini: "gpt-5.1-codex-mini"
 
 
 
 
 
 
 
 
74
  codex: "gpt-5.3-codex"
75
  codex-max: "gpt-5.1-codex-max"
76
  codex-mini: "gpt-5.1-codex-mini"
77
+ # Claude Code model aliases
78
+ claude-opus-4-6: "gpt-5.3-codex"
79
+ claude-sonnet-4-6: "gpt-5.2-codex"
80
+ claude-haiku-4-5-20251001: "gpt-5.1-codex-mini"
81
+ opus: "gpt-5.3-codex"
82
+ sonnet: "gpt-5.2-codex"
83
+ haiku: "gpt-5.1-codex-mini"
web/src/App.tsx CHANGED
@@ -4,6 +4,7 @@ import { Header } from "./components/Header";
4
  import { AccountList } from "./components/AccountList";
5
  import { AddAccount } from "./components/AddAccount";
6
  import { ApiConfig } from "./components/ApiConfig";
 
7
  import { CodeExamples } from "./components/CodeExamples";
8
  import { Footer } from "./components/Footer";
9
  import { useAccounts } from "./hooks/use-accounts";
@@ -36,6 +37,9 @@ function Dashboard() {
36
  selectedModel={status.selectedModel}
37
  onModelChange={status.setSelectedModel}
38
  />
 
 
 
39
  <CodeExamples
40
  baseUrl={status.baseUrl}
41
  apiKey={status.apiKey}
 
4
  import { AccountList } from "./components/AccountList";
5
  import { AddAccount } from "./components/AddAccount";
6
  import { ApiConfig } from "./components/ApiConfig";
7
+ import { ClaudeCodeSetup } from "./components/ClaudeCodeSetup";
8
  import { CodeExamples } from "./components/CodeExamples";
9
  import { Footer } from "./components/Footer";
10
  import { useAccounts } from "./hooks/use-accounts";
 
37
  selectedModel={status.selectedModel}
38
  onModelChange={status.setSelectedModel}
39
  />
40
+ <ClaudeCodeSetup
41
+ apiKey={status.apiKey}
42
+ />
43
  <CodeExamples
44
  baseUrl={status.baseUrl}
45
  apiKey={status.apiKey}
web/src/components/ClaudeCodeSetup.tsx ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useState, useCallback, useMemo } from "preact/hooks";
2
+ import { useT } from "../i18n/context";
3
+ import { CopyButton } from "./CopyButton";
4
+
5
+ type ClaudeModel = "opus" | "sonnet" | "haiku";
6
+
7
+ const CLAUDE_MODELS: { id: ClaudeModel; label: string; desc: string }[] = [
8
+ { id: "opus", label: "Opus", desc: "gpt-5.3-codex" },
9
+ { id: "sonnet", label: "Sonnet", desc: "gpt-5.2-codex" },
10
+ { id: "haiku", label: "Haiku", desc: "gpt-5.1-codex-mini" },
11
+ ];
12
+
13
+ interface ClaudeCodeSetupProps {
14
+ apiKey: string;
15
+ }
16
+
17
+ export function ClaudeCodeSetup({ apiKey }: ClaudeCodeSetupProps) {
18
+ const t = useT();
19
+ const [model, setModel] = useState<ClaudeModel>("opus");
20
+
21
+ const origin = typeof window !== "undefined" ? window.location.origin : "http://localhost:8080";
22
+
23
+ const envLines = useMemo(() => ({
24
+ ANTHROPIC_BASE_URL: origin,
25
+ ANTHROPIC_API_KEY: apiKey,
26
+ ANTHROPIC_MODEL: `claude-${model}-4-${model === "haiku" ? "5-20251001" : "6"}`,
27
+ }), [origin, apiKey, model]);
28
+
29
+ const allEnvText = useMemo(
30
+ () => Object.entries(envLines).map(([k, v]) => `${k}=${v}`).join("\n"),
31
+ [envLines],
32
+ );
33
+
34
+ const getAllEnv = useCallback(() => allEnvText, [allEnvText]);
35
+ const getBaseUrl = useCallback(() => envLines.ANTHROPIC_BASE_URL, [envLines]);
36
+ const getApiKey = useCallback(() => envLines.ANTHROPIC_API_KEY, [envLines]);
37
+ const getModel = useCallback(() => envLines.ANTHROPIC_MODEL, [envLines]);
38
+
39
+ const activeBtn = "px-3 py-1.5 text-xs font-semibold rounded bg-white dark:bg-[#21262d] text-slate-800 dark:text-text-main shadow-sm border border-transparent dark:border-border-dark transition-all";
40
+ const inactiveBtn = "px-3 py-1.5 text-xs font-medium rounded text-slate-500 dark:text-text-dim hover:text-slate-700 dark:hover:text-text-main hover:bg-white/50 dark:hover:bg-[#21262d] border border-transparent transition-all";
41
+
42
+ return (
43
+ <section class="bg-white dark:bg-card-dark border border-gray-200 dark:border-border-dark rounded-xl p-5 shadow-sm transition-colors">
44
+ <div class="flex items-center justify-between mb-6 border-b border-slate-100 dark:border-border-dark pb-4">
45
+ <div class="flex items-center gap-2">
46
+ <svg class="size-5 text-primary" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
47
+ <path stroke-linecap="round" stroke-linejoin="round" d="M6.75 7.5l3 2.25-3 2.25m4.5 0h3m-9 8.25h13.5A2.25 2.25 0 0021 18V6a2.25 2.25 0 00-2.25-2.25H5.25A2.25 2.25 0 003 6v12a2.25 2.25 0 002.25 2.25z" />
48
+ </svg>
49
+ <h2 class="text-[0.95rem] font-bold">{t("claudeCodeSetup")}</h2>
50
+ </div>
51
+ <div class="flex gap-2 p-1 bg-slate-100 dark:bg-bg-dark dark:border dark:border-border-dark rounded-lg">
52
+ {CLAUDE_MODELS.map((m) => (
53
+ <button
54
+ key={m.id}
55
+ onClick={() => setModel(m.id)}
56
+ class={model === m.id ? activeBtn : inactiveBtn}
57
+ >
58
+ {m.label}
59
+ <span class="ml-1 text-[0.65rem] opacity-60">({m.desc})</span>
60
+ </button>
61
+ ))}
62
+ </div>
63
+ </div>
64
+
65
+ {/* Env vars */}
66
+ <div class="space-y-3">
67
+ {(["ANTHROPIC_BASE_URL", "ANTHROPIC_API_KEY", "ANTHROPIC_MODEL"] as const).map((key) => {
68
+ const getter = key === "ANTHROPIC_BASE_URL" ? getBaseUrl : key === "ANTHROPIC_API_KEY" ? getApiKey : getModel;
69
+ return (
70
+ <div key={key} class="flex items-center gap-3">
71
+ <label class="text-xs font-mono font-semibold text-slate-600 dark:text-text-dim w-44 shrink-0">{key}</label>
72
+ <div class="relative flex items-center flex-1">
73
+ <input
74
+ class="w-full pl-3 pr-10 py-2 bg-slate-100 dark:bg-bg-dark border border-gray-200 dark:border-border-dark rounded-lg text-[0.78rem] font-mono text-slate-500 dark:text-text-dim outline-none cursor-default select-all"
75
+ type="text"
76
+ value={envLines[key]}
77
+ readOnly
78
+ />
79
+ <CopyButton getText={getter} class="absolute right-2" />
80
+ </div>
81
+ </div>
82
+ );
83
+ })}
84
+ </div>
85
+
86
+ {/* Copy all button */}
87
+ <div class="mt-5 flex items-center gap-3">
88
+ <CopyButton getText={getAllEnv} variant="label" />
89
+ <span class="text-xs text-slate-400 dark:text-text-dim">{t("claudeCodeCopyAllHint")}</span>
90
+ </div>
91
+ </section>
92
+ );
93
+ }
web/src/i18n/translations.ts CHANGED
@@ -32,6 +32,8 @@ export const translations = {
32
  "Use this key to authenticate requests to the proxy. Do not share it.",
33
  copyUrl: "Copy URL",
34
  copyApiKey: "Copy API Key",
 
 
35
  integrationExamples: "Integration Examples",
36
  copy: "Copy",
37
  addStep1:
@@ -87,6 +89,8 @@ export const translations = {
87
  "\u4f7f\u7528\u6b64\u5bc6\u94a5\u5411\u4ee3\u7406\u53d1\u9001\u8ba4\u8bc1\u8bf7\u6c42\uff0c\u8bf7\u52ff\u6cc4\u9732\u3002",
88
  copyUrl: "\u590d\u5236 URL",
89
  copyApiKey: "\u590d\u5236 API \u5bc6\u94a5",
 
 
90
  integrationExamples: "\u96c6\u6210\u793a\u4f8b",
91
  copy: "\u590d\u5236",
92
  addStep1:
 
32
  "Use this key to authenticate requests to the proxy. Do not share it.",
33
  copyUrl: "Copy URL",
34
  copyApiKey: "Copy API Key",
35
+ claudeCodeSetup: "Claude Code Quick Setup",
36
+ claudeCodeCopyAllHint: "Copy all env vars — paste into terminal or .env file",
37
  integrationExamples: "Integration Examples",
38
  copy: "Copy",
39
  addStep1:
 
89
  "\u4f7f\u7528\u6b64\u5bc6\u94a5\u5411\u4ee3\u7406\u53d1\u9001\u8ba4\u8bc1\u8bf7\u6c42\uff0c\u8bf7\u52ff\u6cc4\u9732\u3002",
90
  copyUrl: "\u590d\u5236 URL",
91
  copyApiKey: "\u590d\u5236 API \u5bc6\u94a5",
92
+ claudeCodeSetup: "Claude Code \u5feb\u901f\u914d\u7f6e",
93
+ claudeCodeCopyAllHint: "\u590d\u5236\u6240\u6709\u73af\u5883\u53d8\u91cf \u2014 \u7c98\u8d34\u5230\u7ec8\u7aef\u6216 .env \u6587\u4ef6",
94
  integrationExamples: "\u96c6\u6210\u793a\u4f8b",
95
  copy: "\u590d\u5236",
96
  addStep1: