@pikoloo/codex-proxy 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +199 -0
  3. package/bin/cli.js +118 -0
  4. package/docs/ACCOUNTS.md +202 -0
  5. package/docs/API.md +289 -0
  6. package/docs/ARCHITECTURE.md +129 -0
  7. package/docs/CLAUDE_INTEGRATION.md +163 -0
  8. package/docs/OAUTH.md +85 -0
  9. package/docs/OPENCLAW.md +34 -0
  10. package/docs/legal.md +11 -0
  11. package/images/dashboard-screenshot.png +0 -0
  12. package/images/demo-screenshot.png +0 -0
  13. package/images/f757093f-507b-4453-994e-f8275f8b07a9.png +0 -0
  14. package/package.json +61 -0
  15. package/public/css/style.css +1502 -0
  16. package/public/index.html +827 -0
  17. package/public/js/app.js +601 -0
  18. package/src/account-manager.js +528 -0
  19. package/src/account-rotation/index.js +93 -0
  20. package/src/account-rotation/rate-limits.js +293 -0
  21. package/src/account-rotation/strategies/base-strategy.js +48 -0
  22. package/src/account-rotation/strategies/index.js +31 -0
  23. package/src/account-rotation/strategies/round-robin-strategy.js +42 -0
  24. package/src/account-rotation/strategies/sticky-strategy.js +97 -0
  25. package/src/claude-config.js +153 -0
  26. package/src/cli/accounts.js +557 -0
  27. package/src/direct-api.js +164 -0
  28. package/src/format-converter.js +420 -0
  29. package/src/index.js +46 -0
  30. package/src/kilo-api.js +68 -0
  31. package/src/kilo-format-converter.js +285 -0
  32. package/src/kilo-models.js +103 -0
  33. package/src/kilo-streamer.js +243 -0
  34. package/src/middleware/credentials.js +116 -0
  35. package/src/middleware/sse.js +96 -0
  36. package/src/model-api.js +189 -0
  37. package/src/model-mapper.js +157 -0
  38. package/src/oauth.js +666 -0
  39. package/src/response-streamer.js +409 -0
  40. package/src/routes/accounts-route.js +332 -0
  41. package/src/routes/api-routes.js +98 -0
  42. package/src/routes/chat-route.js +229 -0
  43. package/src/routes/claude-config-route.js +121 -0
  44. package/src/routes/logs-route.js +43 -0
  45. package/src/routes/messages-route.js +203 -0
  46. package/src/routes/models-route.js +119 -0
  47. package/src/routes/settings-route.js +143 -0
  48. package/src/security.js +142 -0
  49. package/src/server-settings.js +56 -0
  50. package/src/server.js +58 -0
  51. package/src/signature-cache.js +106 -0
  52. package/src/thinking-utils.js +312 -0
  53. package/src/utils/logger.js +156 -0
package/docs/API.md ADDED
@@ -0,0 +1,289 @@
1
+ # API Reference
2
+
3
+ ## Main Endpoints
4
+
5
+ ### Kilo Routing Settings
6
+
7
+ The explicit `kilo` model route can be configured to use an alternate provider target such as **MiniMax M2.5** or **Kimi K2.5** when `CODEX_CLAUDE_PROXY_ENABLE_KILO=true` is set. Claude Haiku aliases use OpenAI by default.
8
+
9
+ ```bash
10
+ GET /settings/haiku-model
11
+
12
+ # Response
13
+ {
14
+ "success": true,
15
+ "haikuKiloModel": "minimax/minimax-m2.5:free",
16
+ "kiloEnabled": false
17
+ }
18
+ ```
19
+
20
+ ```bash
21
+ POST /settings/haiku-model
22
+ Content-Type: application/json
23
+
24
+ {
25
+ "haikuKiloModel": "minimax-2.5"
26
+ }
27
+
28
+ # Response
29
+ {
30
+ "success": true,
31
+ "haikuKiloModel": "minimax-2.5",
32
+ "kiloEnabled": true
33
+ }
34
+ ```
35
+
36
+ ### Chat Completions (OpenAI-compatible)
37
+
38
+ ```bash
39
+ POST /v1/chat/completions
40
+ Content-Type: application/json
41
+
42
+ {
43
+ "model": "gpt-5.5",
44
+ "messages": [{"role": "user", "content": "Hello"}],
45
+ "tools": [...],
46
+ "stream": true
47
+ }
48
+ ```
49
+
50
+ ### Messages (Anthropic-compatible)
51
+
52
+ ```bash
53
+ POST /v1/messages
54
+ Content-Type: application/json
55
+
56
+ {
57
+ "model": "claude-sonnet-4-5",
58
+ "max_tokens": 1024,
59
+ "system": "You are helpful.",
60
+ "messages": [{"role": "user", "content": "Hello"}],
61
+ "tools": [...],
62
+ "stream": true
63
+ }
64
+ ```
65
+
66
+ ### Models
67
+
68
+ ```bash
69
+ GET /v1/models
70
+ ```
71
+
72
+ ### Token Counting
73
+
74
+ ```bash
75
+ POST /v1/messages/count_tokens
76
+ Content-Type: application/json
77
+
78
+ {
79
+ "messages": [...],
80
+ "tools": [...]
81
+ }
82
+ ```
83
+
84
+ ## Account Management
85
+
86
+ Common endpoints:
87
+
88
+ | Endpoint | Method | Description |
89
+ |----------|--------|-------------|
90
+ | `/accounts` | GET | List all accounts |
91
+ | `/accounts/status` | GET | Get account status summary |
92
+ | `/accounts/add` | POST | Start OAuth flow (returns URL) |
93
+ | `/accounts/switch` | POST | Switch active account |
94
+ | `/accounts/models` | GET | Get models for account |
95
+ | `/accounts/quota` | GET | Get quota info |
96
+ | `/accounts/quota/all` | GET | Refresh all quotas |
97
+ | `/accounts/usage` | GET | Get usage stats |
98
+
99
+ (Additional maintenance endpoints exist for token refresh/import/removal; see the source if you need them.)
100
+
101
+ ### Add Account
102
+
103
+ ```bash
104
+ POST /accounts/add
105
+ Content-Type: application/json
106
+
107
+ # Optional: specify callback port
108
+ {"port": 1455}
109
+
110
+ # Response
111
+ {
112
+ "status": "oauth_url",
113
+ "oauth_url": "https://auth.openai.com/oauth/authorize?...",
114
+ "callback_port": 1455
115
+ }
116
+ ```
117
+
118
+ ### Account Selection Strategy
119
+
120
+ Requests use the active account only by default. Account rotation settings are inert unless `CODEX_CLAUDE_PROXY_ENABLE_MULTI_ACCOUNT_ROTATION=true` is set.
121
+
122
+ ```bash
123
+ GET /settings/account-strategy
124
+
125
+ # Response
126
+ {
127
+ "success": true,
128
+ "accountStrategy": "sticky",
129
+ "rotationEnabled": false
130
+ }
131
+ ```
132
+
133
+ ### Switch Account
134
+
135
+ ```bash
136
+ POST /accounts/switch
137
+ Content-Type: application/json
138
+
139
+ {"email": "user@gmail.com"}
140
+
141
+ # Response
142
+ {"success": true, "message": "Switched to account: user@gmail.com"}
143
+ ```
144
+
145
+ ### OAuth Callback
146
+
147
+ ```bash
148
+ GET /auth/callback?code=...&state=...
149
+ ```
150
+
151
+ ## Claude CLI Configuration
152
+
153
+ | Endpoint | Method | Description |
154
+ |----------|--------|-------------|
155
+ | `/claude/config` | GET | View current config |
156
+ | `/claude/config/proxy` | POST | Configure for proxy |
157
+ | `/claude/config/direct` | POST | Configure for direct API |
158
+
159
+ ### Configure Proxy Mode
160
+
161
+ ```bash
162
+ POST /claude/config/proxy
163
+
164
+ # Response
165
+ {
166
+ "success": true,
167
+ "message": "Claude CLI configured to use proxy at http://localhost:8081",
168
+ "config": {...}
169
+ }
170
+ ```
171
+
172
+ ## Health
173
+
174
+ ```bash
175
+ GET /health
176
+
177
+ # Response
178
+ {
179
+ "status": "ok",
180
+ "total": 2,
181
+ "active": "active@example.com",
182
+ "accounts": [...]
183
+ }
184
+ ```
185
+
186
+ ## Error Responses
187
+
188
+ ### Authentication Error
189
+
190
+ ```json
191
+ {
192
+ "type": "error",
193
+ "error": {
194
+ "type": "authentication_error",
195
+ "message": "No active account with valid credentials"
196
+ }
197
+ }
198
+ ```
199
+
200
+ ### Rate Limit Error
201
+
202
+ ```json
203
+ {
204
+ "type": "error",
205
+ "error": {
206
+ "type": "rate_limit_error",
207
+ "message": "Rate limited: ..."
208
+ }
209
+ }
210
+ ```
211
+
212
+ ## Streaming Events
213
+
214
+ Anthropic SSE format:
215
+
216
+ ```
217
+ event: message_start
218
+ data: {"type":"message_start","message":{...}}
219
+
220
+ event: content_block_start
221
+ data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}
222
+
223
+ event: content_block_delta
224
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Hello"}}
225
+
226
+ event: content_block_stop
227
+ data: {"type":"content_block_stop","index":0}
228
+
229
+ event: message_delta
230
+ data: {"type":"message_delta","delta":{"stop_reason":"end_turn"},"usage":{...}}
231
+
232
+ event: message_stop
233
+ data: {"type":"message_stop"}
234
+
235
+ data: [DONE]
236
+ ```
237
+
238
+ ## Tool Calling
239
+
240
+ ### Request with Tools
241
+
242
+ ```json
243
+ {
244
+ "model": "claude-sonnet-4-5",
245
+ "messages": [
246
+ {"role": "user", "content": "What's the weather in Tokyo?"}
247
+ ],
248
+ "tools": [{
249
+ "name": "get_weather",
250
+ "description": "Get weather for a location",
251
+ "input_schema": {
252
+ "type": "object",
253
+ "properties": {
254
+ "location": {"type": "string"}
255
+ },
256
+ "required": ["location"]
257
+ }
258
+ }]
259
+ }
260
+ ```
261
+
262
+ ### Response with Tool Use
263
+
264
+ ```json
265
+ {
266
+ "id": "msg_...",
267
+ "type": "message",
268
+ "role": "assistant",
269
+ "content": [{
270
+ "type": "tool_use",
271
+ "id": "toolu_...",
272
+ "name": "get_weather",
273
+ "input": {"location": "Tokyo"}
274
+ }],
275
+ "stop_reason": "tool_use"
276
+ }
277
+ ```
278
+
279
+ ### Tool Result
280
+
281
+ ```json
282
+ {
283
+ "messages": [
284
+ {"role": "user", "content": "What's the weather?"},
285
+ {"role": "assistant", "content": [{"type": "tool_use", "id": "toolu_123", "name": "get_weather", "input": {"location": "Tokyo"}}]},
286
+ {"role": "user", "content": [{"type": "tool_result", "tool_use_id": "toolu_123", "content": "Sunny, 22°C"}]}
287
+ ]
288
+ }
289
+ ```
@@ -0,0 +1,129 @@
1
+ # Architecture
2
+
3
+ ## Overview
4
+
5
+ ```
6
+ ┌──────────────────┐ ┌─────────────────────┐ ┌────────────────────────────┐
7
+ │ Claude Code │────▶│ This Proxy Server │────▶│ ChatGPT Codex backend │
8
+ │ (Anthropic │ │ (Anthropic format) │ │ (internal API) │
9
+ │ API format) │ │ │ │ │
10
+ └──────────────────┘ └─────────────────────┘ └────────────────────────────┘
11
+
12
+
13
+ ┌─────────────────────┐
14
+ │ Account Manager │
15
+ │ (local storage) │
16
+ │ │
17
+ └─────────────────────┘
18
+ ```
19
+
20
+ ## Key Discovery
21
+
22
+ This proxy forwards requests from Anthropic-compatible clients (like Claude Code) to the ChatGPT Codex backend, handling authentication, format conversion, and streaming.
23
+
24
+ ## Project Structure
25
+
26
+ ```
27
+ codex-proxy/
28
+ ├── package.json
29
+ ├── README.md
30
+ ├── docs/
31
+ │ ├── ARCHITECTURE.md
32
+ │ ├── API.md
33
+ │ ├── OAUTH.md
34
+ │ ├── ACCOUNTS.md
35
+ │ └── CLAUDE_INTEGRATION.md
36
+ ├── public/
37
+ │ ├── index.html
38
+ │ ├── css/style.css
39
+ │ └── js/app.js # Web UI logic
40
+ └── src/
41
+ ├── index.js # App entrypoint
42
+ ├── server.js # Express server setup
43
+ ├── routes/api-routes.js # API route registrations
44
+ └── ... # OAuth, accounts, converters, upstream clients
45
+ ```
46
+
47
+ (See the `src/` directory for the full implementation; this doc focuses on the high-level shape.)
48
+
49
+ ## Module Responsibilities
50
+
51
+ | File | Purpose |
52
+ |------|---------|
53
+ | `index.js` | Entry point (starts server) |
54
+ | `server.js` | Express server, routes, request handling (CORS restricted) |
55
+ | `routes/api-routes.js` | API route registrations (mounted by server) |
56
+ | `oauth.js` | OAuth 2.0 PKCE flow, token exchange |
57
+ | `account-manager.js` | Account persistence, switching, token refresh |
58
+ | `format-converter.js` | Convert between Anthropic and OpenAI Responses API formats |
59
+ | `response-streamer.js` | Parse SSE events, convert to Anthropic streaming format |
60
+ | `direct-api.js` | HTTP client for ChatGPT backend |
61
+ | `kilo-api.js` | Alternate upstream client |
62
+ | `kilo-format-converter.js` | Anthropic ↔ OpenAI Chat conversion |
63
+ | `kilo-streamer.js` | Streaming adapter |
64
+ | `server-settings.js` | Server-wide settings persistence |
65
+ | `model-api.js` | Fetch models, usage, quota |
66
+ | `claude-config.js` | Read/write Claude Code settings |
67
+
68
+ ## Data Flow
69
+
70
+ ### Request Flow
71
+
72
+ 1. Claude Code sends Anthropic-format request to `/v1/messages`
73
+ 2. The proxy maps the requested model to an upstream target
74
+ 3. If the mapped path requires ChatGPT auth, the account manager loads/refreshes credentials
75
+ 4. Request is converted and sent upstream
76
+ 5. Response is streamed back as Anthropic SSE events
77
+
78
+ ### Web UI Account/Quota Flow
79
+
80
+ 1. Web UI loads account list from `/accounts`
81
+ 2. Web UI fetches quota snapshots from `/accounts/quota/all`
82
+ 3. Quota values are merged into account rows for table + modal views
83
+ 4. Remaining quota is rendered from normalized usage percentages
84
+ 5. On mobile/tablet, sidebar navigation auto-closes after tab change and account table uses horizontal scrolling
85
+
86
+ ### Format Conversion
87
+
88
+ **Anthropic → OpenAI Responses API:**
89
+ - `messages` → `input` array with `type: 'message'`
90
+ - `system` → `instructions`
91
+ - `tools` → OpenAI function format
92
+ - `tool_use` → `function_call` input item
93
+ - `tool_result` → `function_call_output` input item
94
+
95
+ **OpenAI → Anthropic:**
96
+ - `output_text` → `{ type: 'text', text: ... }`
97
+ - `function_call` → `{ type: 'tool_use', id, name, input }`
98
+ - SSE events converted to Anthropic streaming format
99
+
100
+ ## Available Models
101
+
102
+ | Model | Description |
103
+ |-------|-------------|
104
+ | `gpt-5.5` | Current OpenAI flagship model |
105
+ | `gpt-5.4` | Current lower-cost frontier model |
106
+ | `gpt-5.4-mini` | Current small OpenAI model |
107
+ | `gpt-5.3-codex` | Latest Codex-optimized model |
108
+ | `gpt-5.2` | Older general-purpose frontier model |
109
+
110
+ ## Model Mapping
111
+
112
+ Claude model names are automatically mapped:
113
+
114
+ | Claude Model | Codex Model |
115
+ |--------------|-------------|
116
+ | `claude-opus-4-5` | `gpt-5.5` |
117
+ | `claude-sonnet-4-5` | `gpt-5.5` |
118
+ | `claude-haiku-4` | `gpt-5.4-mini` |
119
+ | `kilo` | selected Kilo target, disabled by default |
120
+
121
+ Kilo routing is explicit and disabled unless `CODEX_CLAUDE_PROXY_ENABLE_KILO=true` is set. The `/settings/haiku-model` endpoints choose the Kilo target used when the requested model is `kilo`.
122
+
123
+ ## Account Selection
124
+
125
+ The default execution mode is personal local use: `/v1/messages` uses the active account only and does not rotate across configured accounts. Multi-account rotation is disabled unless `CODEX_CLAUDE_PROXY_ENABLE_MULTI_ACCOUNT_ROTATION=true` is set.
126
+
127
+ ## Data Storage
128
+
129
+ Account and configuration files are stored under your home directory (platform-specific). See `docs/ACCOUNTS.md` and `docs/CLAUDE_INTEGRATION.md` for details.
@@ -0,0 +1,163 @@
1
+ # Claude Code Integration
2
+
3
+ ## Setup
4
+
5
+ ### Automatic Configuration
6
+
7
+ ```bash
8
+ curl -X POST http://localhost:8081/claude/config/proxy
9
+ ```
10
+
11
+ Updates `~/.claude/settings.json`:
12
+
13
+ ```json
14
+ {
15
+ "env": {
16
+ "ANTHROPIC_BASE_URL": "http://localhost:8081",
17
+ "ANTHROPIC_API_KEY": "any-key",
18
+ "ANTHROPIC_MODEL": "claude-sonnet-4-5",
19
+ "ANTHROPIC_DEFAULT_OPUS_MODEL": "claude-opus-4-5",
20
+ "ANTHROPIC_DEFAULT_SONNET_MODEL": "claude-sonnet-4-5",
21
+ "ANTHROPIC_DEFAULT_HAIKU_MODEL": "claude-haiku-4"
22
+ }
23
+ }
24
+ ```
25
+
26
+ ### Manual Configuration
27
+
28
+ ```bash
29
+ export ANTHROPIC_BASE_URL=http://localhost:8081
30
+ export ANTHROPIC_API_KEY=any-key
31
+ claude
32
+ ```
33
+
34
+ ## Using Claude Code
35
+
36
+ When prompted about API key:
37
+
38
+ ```
39
+ Detected a custom API key in your environment
40
+ ANTHROPIC_API_KEY: any-key
41
+ Do you want to use this API key?
42
+ ❯ 1. Yes <-- Choose this
43
+ 2. No (recommended)
44
+ ```
45
+
46
+ ## How It Works
47
+
48
+ ### Request Flow
49
+
50
+ ```
51
+ Claude Code (Anthropic format)
52
+
53
+ Proxy Server
54
+
55
+ Format Conversion
56
+
57
+ ChatGPT Backend API
58
+
59
+ Response Stream
60
+
61
+ Format Conversion
62
+
63
+ Claude Code (Anthropic format)
64
+ ```
65
+
66
+ ### Format Conversion
67
+
68
+ **Anthropic → OpenAI Responses API:**
69
+
70
+ ```javascript
71
+ // Anthropic request
72
+ {
73
+ "model": "claude-sonnet-4-5",
74
+ "system": "You are helpful.",
75
+ "messages": [
76
+ {"role": "user", "content": "Hello"},
77
+ {"role": "assistant", "content": [{"type": "tool_use", "id": "t1", "name": "fn", "input": {}}]},
78
+ {"role": "user", "content": [{"type": "tool_result", "tool_use_id": "t1", "content": "result"}]}
79
+ ],
80
+ "tools": [...]
81
+ }
82
+
83
+ // Converted to OpenAI Responses API
84
+ {
85
+ "model": "gpt-5.5",
86
+ "instructions": "You are helpful.",
87
+ "input": [
88
+ {"type": "message", "role": "user", "content": "Hello"},
89
+ {"type": "function_call", "id": "fc_t1", "call_id": "fc_t1", "name": "fn", "arguments": "{}"},
90
+ {"type": "function_call_output", "call_id": "fc_t1", "output": "result"}
91
+ ],
92
+ "tools": [...],
93
+ "store": false,
94
+ "stream": true
95
+ }
96
+ ```
97
+
98
+ **Key Conversions:**
99
+ - `system` → `instructions`
100
+ - `messages` → `input` array
101
+ - `tool_use` → `function_call` + `function_call_output` items
102
+ - Tool IDs prefixed with `fc_` for API compatibility
103
+
104
+ ### Streaming Events
105
+
106
+ OpenAI Responses API → Anthropic SSE:
107
+
108
+ | OpenAI Event | Anthropic Event |
109
+ |--------------|-----------------|
110
+ | `response.output_item.added` | `message_start`, `content_block_start` |
111
+ | `response.output_text.delta` | `content_block_delta` (text_delta) |
112
+ | `response.function_call_arguments.delta` | `content_block_delta` (input_json_delta) |
113
+ | `response.completed` | `message_delta`, `message_stop` |
114
+
115
+ ## Tool Calling
116
+
117
+ Works natively via OpenAI Responses API:
118
+
119
+ 1. Claude Code sends tools in Anthropic format
120
+ 2. Proxy converts to OpenAI function format
121
+ 3. ChatGPT executes and returns function calls
122
+ 4. Proxy converts back to Anthropic `tool_use` blocks
123
+ 5. Claude Code processes and returns tool results
124
+
125
+ ## View Configuration
126
+
127
+ ```bash
128
+ curl http://localhost:8081/claude/config
129
+ ```
130
+
131
+ ## Revert to Direct API
132
+
133
+ ```bash
134
+ curl -X POST http://localhost:8081/claude/config/direct \
135
+ -H "Content-Type: application/json" \
136
+ -d '{"apiKey":"sk-ant-..."}'
137
+ ```
138
+
139
+ ## Troubleshooting
140
+
141
+ ### Claude Code hangs
142
+
143
+ 1. Check proxy health: `curl http://localhost:8081/health`
144
+ 2. Verify config: `cat ~/.claude/settings.json`
145
+ 3. Re-configure: `curl -X POST http://localhost:8081/claude/config/proxy`
146
+
147
+ ### "No active account" error
148
+
149
+ Add an account first:
150
+
151
+ ```bash
152
+ curl -X POST http://localhost:8081/accounts/import
153
+ # or use WebUI
154
+ ```
155
+
156
+ ### Tool calls not working
157
+
158
+ Ensure you're using the direct API mode (not CLI subprocess). Check:
159
+
160
+ ```bash
161
+ curl http://localhost:8081/health
162
+ # Should show accounts with valid tokens
163
+ ```
package/docs/OAUTH.md ADDED
@@ -0,0 +1,85 @@
1
+ # OAuth Implementation
2
+
3
+ This proxy uses **OAuth 2.0 with PKCE** for secure authentication with ChatGPT.
4
+
5
+ ## Quick Start
6
+
7
+ ### Desktop (Browser)
8
+ ```bash
9
+ codex-proxy accounts add
10
+ ```
11
+
12
+ ### Headless/VM (No Browser)
13
+ ```bash
14
+ codex-proxy accounts add --no-browser
15
+ ```
16
+
17
+ The legacy `codex-claude-proxy` command remains supported as an alias.
18
+
19
+ ## Headless/VM Workflow
20
+
21
+ When running on a server without a browser (VM, Docker, SSH):
22
+
23
+ 1. Run the command with `--no-browser`:
24
+ ```bash
25
+ codex-proxy accounts add --no-browser
26
+ ```
27
+
28
+ 2. It prints a URL like:
29
+ ```
30
+ https://auth.openai.com/oauth/authorize?response_type=code&...
31
+ ```
32
+
33
+ 3. Copy the URL and open it in a browser on **any other device** (your laptop, phone, etc.)
34
+
35
+ 4. Complete the ChatGPT login
36
+
37
+ 5. After successful login, you'll be redirected to a localhost URL that looks like:
38
+ ```
39
+ http://localhost:1455/auth/callback?code=ABC123...
40
+ ```
41
+
42
+ 6. Copy that entire URL (or just the `code` parameter) and paste it back in the terminal
43
+
44
+ 7. The proxy exchanges the code for tokens and saves your account
45
+
46
+ ## OAuth Config
47
+
48
+ - **Client ID**: `app_EMoamEEZ73f0CkXaXp7hrann`
49
+ - **Auth URL**: `https://auth.openai.com/oauth/authorize`
50
+ - **Token URL**: `https://auth.openai.com/oauth/token`
51
+ - **Callback Port**: `1455`
52
+
53
+ ## Features
54
+
55
+ - **PKCE**: Secure code exchange with SHA256 challenge
56
+ - **Auto-Refresh**: Tokens refresh automatically before expiry
57
+ - **Account Selection**: Uses `prompt=login` so you can choose the account to add
58
+ - **Headless Support**: Works on servers without browsers
59
+
60
+ ## Managing Accounts
61
+
62
+ ```bash
63
+ # List accounts
64
+ codex-proxy accounts list
65
+
66
+ # Add account (browser)
67
+ codex-proxy accounts add
68
+
69
+ # Add account (headless)
70
+ codex-proxy accounts add --no-browser
71
+
72
+ # Clear all accounts
73
+ codex-proxy accounts clear
74
+ ```
75
+
76
+ ## Troubleshooting
77
+
78
+ ### "Port already in use"
79
+ The `--no-browser` mode works independently of the server - you can add accounts even while the proxy is running.
80
+
81
+ ### "Invalid state" error
82
+ This happens if you use a code from an old session. Generate a fresh URL and try again.
83
+
84
+ ### Same account keeps getting selected
85
+ Clear cookies at `auth.openai.com` or use a private/incognito window.
@@ -0,0 +1,34 @@
1
+ # Using with OpenClaw
2
+
3
+ [OpenClaw](https://docs.openclaw.ai/) is an AI agent gateway. This proxy provides the Anthropic-compatible API it needs.
4
+
5
+ ## Quick Integration
6
+
7
+ 1. **Add Provider** to `~/.openclaw/openclaw.json`:
8
+ ```json
9
+ {
10
+ "codex-proxy": {
11
+ "baseUrl": "http://127.0.0.1:8081",
12
+ "apiKey": "test",
13
+ "api": "anthropic-messages",
14
+ "models": [
15
+ { "id": "claude-sonnet-4-5", "name": "GPT-5.5" },
16
+ { "id": "claude-opus-4-5", "name": "GPT-5.5" },
17
+ { "id": "gpt-5.3-codex", "name": "GPT-5.3 Codex" }
18
+ ]
19
+ }
20
+ }
21
+ ```
22
+ 2. **Set Primary Model**:
23
+ ```bash
24
+ openclaw models set codex-proxy/claude-sonnet-4-5
25
+ ```
26
+
27
+ ## Key Benefits
28
+ - **Personal Account Mode**: Proxy uses the active local ChatGPT account by default.
29
+ - **SSE Streaming**: Full real-time response support.
30
+ - **Tool Calling**: Native support for agentic workflows.
31
+
32
+ ## Troubleshooting
33
+ - Use `127.0.0.1` instead of `localhost`.
34
+ - Verify proxy health: `curl http://127.0.0.1:8081/health`.
package/docs/legal.md ADDED
@@ -0,0 +1,11 @@
1
+ # Legal
2
+
3
+ - **Not affiliated with OpenAI or Anthropic.** This is an independent open-source project and is not endorsed by, sponsored by, or affiliated with OpenAI or Anthropic.
4
+
5
+ - "ChatGPT", "OpenAI", and "Codex" are trademarks of OpenAI.
6
+
7
+ - "Claude" and "Anthropic" are trademarks of Anthropic PBC.
8
+
9
+ - "Kilo" and "Kilo Search" are trademarks of their respective owners.
10
+
11
+ - Software is provided "as is", without warranty. You are responsible for complying with all applicable Terms of Service and Acceptable Use Policies.