@sunerpy/kiro-provider 0.3.1 → 0.4.0

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 (3) hide show
  1. package/README.md +305 -23
  2. package/dist/cli.js +209 -94
  3. package/package.json +5 -3
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # kiro-provider
2
2
 
3
- > A standalone OpenAI-compatible HTTP gateway for AWS Kiro (CodeWhisperer) — point any OpenAI SDK or agent at your own Kiro accounts.
3
+ > A standalone OpenAI Responses and Anthropic Messages gateway for AWS Kiro (CodeWhisperer).
4
4
 
5
5
  [![CI](https://github.com/sunerpy/kiro-provider/actions/workflows/ci.yml/badge.svg)](https://github.com/sunerpy/kiro-provider/actions/workflows/ci.yml)
6
6
  [![codecov](https://codecov.io/gh/sunerpy/kiro-provider/branch/main/graph/badge.svg)](https://codecov.io/gh/sunerpy/kiro-provider)
@@ -14,20 +14,27 @@
14
14
  - [Features](#features)
15
15
  - [Install](#install)
16
16
  - [Quickstart](#quickstart)
17
+ - [Run as a background service](#run-as-a-background-service)
17
18
  - [Configuration](#configuration)
18
19
  - [Proxy](#proxy)
19
20
  - [Security](#security)
20
21
  - [Using with an LLM](#using-with-an-llm)
21
22
  - [Use with Codex CLI](#use-with-codex-cli)
23
+ - [Use with Claude Code](#use-with-claude-code)
22
24
  - [Development](#development)
23
25
  - [License](#license)
24
26
 
25
27
  ## Features
26
28
 
27
- - OpenAI-compatible `POST /v1/chat/completions` (streaming SSE and non-streaming JSON), `POST /v1/responses` (OpenAI Responses API, streaming typed SSE and non-streaming JSON), `GET /v1/models`, and `GET /health`.
29
+ - OpenAI Responses `POST /v1/responses` and Anthropic Messages `POST /v1/messages` (both streaming and non-streaming), plus `POST /v1/messages/count_tokens`, `GET /v1/models`, `GET /health`, and authenticated `GET /ready`.
30
+ - Legacy OpenAI Chat Completions is available at `POST /v1/chat/completions`, but is disabled by default and must be explicitly enabled with `enable_legacy_chat_completions`.
28
31
  - Bearer API-key gate that fails closed: the server refuses to start with no configured keys, and defaults to binding `127.0.0.1`.
29
- - Multi-account rotation with automatic token refresh and failover, backed by a local `bun:sqlite` account store with tombstone-based removal.
30
- - `accounts import` to reuse accounts already authenticated by [OpenCode's Kiro auth](https://opencode.ai/) instead of repeating device-code login.
32
+ - Live OpenCode authentication reuse by default: `auth_source: "opencode-shared"` reads the same `~/.config/opencode/kiro.db`, honors tombstones, updates shared health/usage, and uses a refresh lock compatible with `opencode-kiro-auth` v0.20.6.
33
+ - Standard-field session affinity: Codex/OpenAI, OpenCode, and Claude Code requests reuse a persisted account binding and Kiro conversation ID without private headers, cookies, or client patches.
34
+ - Account-scoped scheduling and keep-alive transport pools: unrelated accounts can run concurrently, while one account is protected from overlapping Kiro streams; access-token refresh updates the cached client instead of rebuilding its connection pool.
35
+ - Zero provider-owned prompt injection: request adapters preserve client text and structured protocol fields, and reject unsupported guarantees instead of emulating them with hidden instructions.
36
+ - Multi-account rotation with automatic token refresh and failover. Shared mode treats OpenCode's database as the authentication authority; the provider database stores session affinity only.
37
+ - An explicit `auth_source: "local"` compatibility mode retains `kiro-provider login` and `accounts import`; imported accounts are snapshots and must not be confused with live shared authentication.
31
38
  - A single global `proxy_url` that, when set, routes all upstream egress (model requests, token refresh, device-code login) through one HTTP(S) proxy.
32
39
  - Ships as a self-contained compiled binary via `bun build --compile` — no runtime install required on the target machine.
33
40
 
@@ -91,15 +98,20 @@ In the rest of this README, `./dist/kiro-provider` refers to any of the above; s
91
98
 
92
99
  ## Quickstart
93
100
 
94
- 1. **Get an account into the local store.** Either sign in interactively:
101
+ 1. **Authenticate Kiro through OpenCode.** The default shared-auth mode uses
102
+ OpenCode's live account database:
95
103
 
96
104
  ```bash
97
- ./dist/kiro-provider login
105
+ opencode auth login
98
106
  ```
99
107
 
100
- or import accounts already authenticated by OpenCode:
108
+ Select Kiro and complete the normal login flow. If you intentionally want
109
+ an independent compatibility store instead, set `"auth_source": "local"`
110
+ and then use:
101
111
 
102
112
  ```bash
113
+ ./dist/kiro-provider login
114
+ # or take a one-time snapshot:
103
115
  ./dist/kiro-provider accounts import
104
116
  ```
105
117
 
@@ -117,7 +129,7 @@ In the rest of this README, `./dist/kiro-provider` refers to any of the above; s
117
129
  ./dist/kiro-provider serve
118
130
  ```
119
131
 
120
- 4. **Call it with an OpenAI-compatible client.**
132
+ 4. **Call the default Responses endpoint.**
121
133
 
122
134
  ```bash
123
135
  curl -fsS http://127.0.0.1:8787/v1/models \
@@ -132,15 +144,18 @@ In the rest of this README, `./dist/kiro-provider` refers to any of the above; s
132
144
  apiKey: "sk-your-private-key",
133
145
  });
134
146
 
135
- const completion = await client.chat.completions.create({
147
+ const response = await client.responses.create({
136
148
  model: "auto",
137
- messages: [{ role: "user", content: "Explain this repository." }],
149
+ input: "Explain this repository.",
138
150
  });
139
151
 
140
- console.log(completion.choices[0]?.message.content);
152
+ console.log(response.output_text);
141
153
  ```
142
154
 
143
- Or with the [Vercel AI SDK](https://sdk.vercel.ai/) via `@ai-sdk/openai-compatible`:
155
+ OpenAI-compatible libraries that only implement Chat Completions require
156
+ `"enable_legacy_chat_completions": true` in the gateway config. For example,
157
+ with the [Vercel AI SDK](https://sdk.vercel.ai/) via
158
+ `@ai-sdk/openai-compatible`:
144
159
 
145
160
  ```ts
146
161
  import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
@@ -158,6 +173,225 @@ In the rest of this README, `./dist/kiro-provider` refers to any of the above; s
158
173
  });
159
174
  ```
160
175
 
176
+ ## Run as a background service
177
+
178
+ For an agent host, run **one long-lived provider per OS user** and point
179
+ Codex, OpenCode, Claude Code, Zuno, and other clients at that local endpoint.
180
+ Do not start a new provider for every agent or conversation. Keeping one
181
+ process alive lets those standard clients share the provider's persisted
182
+ session/account affinity and its process-local, account-scoped keep-alive
183
+ pools. This remains best-effort connection reuse, not a promise that every
184
+ request uses one physical TCP connection.
185
+
186
+ Use a pinned standalone binary for a service rather than fetching through
187
+ `bunx` on every start. The examples below assume the release installers'
188
+ defaults:
189
+
190
+ - binary: `~/.local/bin/kiro-provider` on Linux,
191
+ `%USERPROFILE%\.local\bin\kiro-provider.exe` on Windows;
192
+ - config: `~/.config/kiro-provider/config.json`;
193
+ - service/task name: `kiro-provider`.
194
+
195
+ Run the service as the **same OS user** that ran `opencode auth login`.
196
+ Default `auth_source: "opencode-shared"` resolves that user's OpenCode
197
+ database and home/XDG directories; running as `root`, `LocalSystem`, or
198
+ another user will normally select different credentials. Use absolute paths,
199
+ keep the API key in the protected config file rather than service arguments,
200
+ and set `opencode_auth_db_path` explicitly if the service has a different XDG
201
+ environment.
202
+
203
+ ### Linux: systemd user service
204
+
205
+ Verify the installed binary and config first:
206
+
207
+ ```bash
208
+ test -x "$HOME/.local/bin/kiro-provider"
209
+ test -r "$HOME/.config/kiro-provider/config.json"
210
+ chmod 600 "$HOME/.config/kiro-provider/config.json"
211
+ ```
212
+
213
+ Install a [systemd user service](https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html):
214
+
215
+ ```bash
216
+ SERVICE_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user"
217
+ install -d -m 700 "$SERVICE_DIR"
218
+ cat > "$SERVICE_DIR/kiro-provider.service" <<'EOF'
219
+ [Unit]
220
+ Description=kiro-provider local Kiro gateway
221
+
222
+ [Service]
223
+ Type=exec
224
+ ExecStart=%h/.local/bin/kiro-provider serve --config %h/.config/kiro-provider/config.json
225
+ Restart=on-failure
226
+ RestartSec=5s
227
+ TimeoutStopSec=30s
228
+ UMask=0077
229
+
230
+ [Install]
231
+ WantedBy=default.target
232
+ EOF
233
+ chmod 600 "$SERVICE_DIR/kiro-provider.service"
234
+
235
+ systemctl --user daemon-reload
236
+ systemctl --user enable --now kiro-provider.service
237
+ ```
238
+
239
+ If the binary or config is elsewhere, replace `ExecStart` with those absolute
240
+ paths. For a custom `XDG_CONFIG_HOME`, also add an explicit
241
+ `Environment=XDG_CONFIG_HOME=/absolute/path` line or configure
242
+ `opencode_auth_db_path`.
243
+
244
+ Operate and inspect the service:
245
+
246
+ ```bash
247
+ systemctl --user is-active kiro-provider.service
248
+ systemctl --user restart kiro-provider.service
249
+ journalctl --user -u kiro-provider.service -n 100 --no-pager
250
+ ```
251
+
252
+ User services normally start with that user's service manager. If the
253
+ provider must start at boot and remain after logout, an administrator may
254
+ enable lingering with `loginctl enable-linger <user>` after reviewing the
255
+ machine's security policy.
256
+
257
+ To remove the unit:
258
+
259
+ ```bash
260
+ systemctl --user disable --now kiro-provider.service
261
+ rm "${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user/kiro-provider.service"
262
+ systemctl --user daemon-reload
263
+ ```
264
+
265
+ ### Windows: per-user scheduled task
266
+
267
+ `kiro-provider.exe` is a normal foreground executable, not a native Windows
268
+ Service Control Manager executable. Do not register it directly with
269
+ `sc.exe`. The built-in, dependency-free option is a
270
+ [Scheduled Task](https://learn.microsoft.com/powershell/module/scheduledtasks/register-scheduledtask)
271
+ that starts at sign-in, runs as the current user, and restarts after failure.
272
+
273
+ Run the following in PowerShell as the same user that owns the OpenCode
274
+ credentials. It creates a small launcher so stdout/stderr are retained under
275
+ `%LOCALAPPDATA%\kiro-provider`:
276
+
277
+ ```powershell
278
+ $Binary = Join-Path $HOME ".local\bin\kiro-provider.exe"
279
+ $Config = Join-Path $HOME ".config\kiro-provider\config.json"
280
+ $ServiceDir = Join-Path $HOME ".config\kiro-provider"
281
+ $LogDir = Join-Path $env:LOCALAPPDATA "kiro-provider"
282
+ $Launcher = Join-Path $ServiceDir "service.ps1"
283
+
284
+ if (-not (Test-Path -LiteralPath $Binary -PathType Leaf)) {
285
+ throw "kiro-provider binary not found: $Binary"
286
+ }
287
+ if (-not (Test-Path -LiteralPath $Config -PathType Leaf)) {
288
+ throw "kiro-provider config not found: $Config"
289
+ }
290
+
291
+ New-Item -ItemType Directory -Force -Path $ServiceDir, $LogDir | Out-Null
292
+ @'
293
+ $ErrorActionPreference = "Stop"
294
+ $Binary = Join-Path $HOME ".local\bin\kiro-provider.exe"
295
+ $Config = Join-Path $HOME ".config\kiro-provider\config.json"
296
+ $LogDir = Join-Path $env:LOCALAPPDATA "kiro-provider"
297
+ $Log = Join-Path $LogDir "service.log"
298
+ $PreviousLog = Join-Path $LogDir "service.previous.log"
299
+
300
+ New-Item -ItemType Directory -Force -Path $LogDir | Out-Null
301
+ if ((Test-Path -LiteralPath $Log) -and ((Get-Item -LiteralPath $Log).Length -gt 10MB)) {
302
+ Move-Item -Force -LiteralPath $Log -Destination $PreviousLog
303
+ }
304
+
305
+ & $Binary serve --config $Config *>> $Log
306
+ exit $LASTEXITCODE
307
+ '@ | Set-Content -LiteralPath $Launcher -Encoding UTF8
308
+
309
+ $User = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
310
+ $PowerShell = (Get-Command powershell.exe).Source
311
+ $Action = New-ScheduledTaskAction `
312
+ -Execute $PowerShell `
313
+ -Argument ('-NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "{0}"' -f $Launcher)
314
+ $Trigger = New-ScheduledTaskTrigger -AtLogOn -User $User
315
+ $Principal = New-ScheduledTaskPrincipal `
316
+ -UserId $User `
317
+ -LogonType Interactive `
318
+ -RunLevel Limited
319
+ $Settings = New-ScheduledTaskSettingsSet `
320
+ -RestartCount 999 `
321
+ -RestartInterval (New-TimeSpan -Minutes 1) `
322
+ -ExecutionTimeLimit ([TimeSpan]::Zero) `
323
+ -MultipleInstances IgnoreNew `
324
+ -AllowStartIfOnBatteries `
325
+ -DontStopIfGoingOnBatteries `
326
+ -StartWhenAvailable
327
+
328
+ Stop-ScheduledTask -TaskName "kiro-provider" -ErrorAction SilentlyContinue
329
+ Register-ScheduledTask `
330
+ -TaskName "kiro-provider" `
331
+ -Action $Action `
332
+ -Trigger $Trigger `
333
+ -Principal $Principal `
334
+ -Settings $Settings `
335
+ -Description "Local AWS Kiro gateway for AI agents" `
336
+ -Force | Out-Null
337
+ Start-ScheduledTask -TaskName "kiro-provider"
338
+ ```
339
+
340
+ Inspect, restart, and follow logs:
341
+
342
+ ```powershell
343
+ Get-ScheduledTask -TaskName "kiro-provider" | Get-ScheduledTaskInfo
344
+ Stop-ScheduledTask -TaskName "kiro-provider"
345
+ Start-ScheduledTask -TaskName "kiro-provider"
346
+ Get-Content "$env:LOCALAPPDATA\kiro-provider\service.log" -Tail 100 -Wait
347
+ ```
348
+
349
+ To remove the task and launcher:
350
+
351
+ ```powershell
352
+ Stop-ScheduledTask -TaskName "kiro-provider" -ErrorAction SilentlyContinue
353
+ Unregister-ScheduledTask -TaskName "kiro-provider" -Confirm:$false
354
+ Remove-Item "$HOME\.config\kiro-provider\service.ps1"
355
+ ```
356
+
357
+ This task intentionally runs only in the current user's interactive session,
358
+ so it can use that user's network access and OpenCode credentials without
359
+ storing a Windows password. A true pre-login Windows service requires a
360
+ service wrapper and a deliberately configured user account; do not run it as
361
+ `LocalSystem` and expect the same OpenCode database.
362
+
363
+ ### Health checks and automation contract
364
+
365
+ After either installation, verify both process liveness and authenticated
366
+ readiness:
367
+
368
+ ```bash
369
+ curl -fsS http://127.0.0.1:8787/health
370
+ curl -fsS http://127.0.0.1:8787/ready \
371
+ -H 'Authorization: Bearer sk-your-private-key'
372
+ ```
373
+
374
+ PowerShell equivalent:
375
+
376
+ ```powershell
377
+ Invoke-RestMethod "http://127.0.0.1:8787/health"
378
+ $Headers = @{ Authorization = "Bearer sk-your-private-key" }
379
+ Invoke-RestMethod "http://127.0.0.1:8787/ready" -Headers $Headers
380
+ ```
381
+
382
+ For an AI agent or installer, treat setup as successful only when:
383
+
384
+ 1. the binary and explicit config path exist;
385
+ 2. the service/task runs as the credential-owning user;
386
+ 3. `/health` succeeds;
387
+ 4. authenticated `/ready` succeeds, proving a readable auth source and at
388
+ least one active account.
389
+
390
+ Use the fixed service/task name above so repeated setup is idempotent. Restart
391
+ it after changing the config or replacing the binary. Do not make the client
392
+ responsible for starting a private provider process; configure clients only
393
+ with the stable base URL and gateway API key.
394
+
161
395
  ## Configuration
162
396
 
163
397
  Config is loaded from `~/.config/kiro-provider/config.json` (or `$XDG_CONFIG_HOME/kiro-provider/config.json`), overridable by `KIRO_PROVIDER_*` environment variables and, for `serve`, by CLI flags. Precedence is **CLI flag > environment variable > config file > schema default**.
@@ -167,9 +401,14 @@ Config is loaded from `~/.config/kiro-provider/config.json` (or `$XDG_CONFIG_HOM
167
401
  | `host` | `127.0.0.1` | `KIRO_PROVIDER_HOST` |
168
402
  | `port` | `8787` | `KIRO_PROVIDER_PORT` |
169
403
  | `api_keys` | required, non-empty | `KIRO_PROVIDER_API_KEYS` |
404
+ | `enable_legacy_chat_completions` | `false` | `KIRO_PROVIDER_ENABLE_LEGACY_CHAT_COMPLETIONS` |
405
+ | `auth_source` | `opencode-shared` | `KIRO_PROVIDER_AUTH_SOURCE` |
406
+ | `opencode_auth_db_path` | `null` (uses the OpenCode default) | `KIRO_PROVIDER_OPENCODE_AUTH_DB_PATH` |
170
407
  | `proxy_url` | `null` | `KIRO_PROVIDER_PROXY_URL` |
171
408
  | `default_region` | `us-east-1` | `KIRO_PROVIDER_DEFAULT_REGION` |
172
409
  | `account_selection_strategy` | `lowest-usage` | `KIRO_PROVIDER_ACCOUNT_SELECTION_STRATEGY` |
410
+ | `session_affinity_ttl_ms` | `86400000` | `KIRO_PROVIDER_SESSION_AFFINITY_TTL_MS` |
411
+ | `session_affinity_max_entries` | `10000` | `KIRO_PROVIDER_SESSION_AFFINITY_MAX_ENTRIES` |
173
412
  | `log_level` | `info` | `KIRO_PROVIDER_LOG_LEVEL` |
174
413
 
175
414
  The full field reference, including retry/timeout tuning and the test-only `test_upstream_endpoint`, lives in [`docs/CONFIGURATION.md`](docs/CONFIGURATION.md).
@@ -180,36 +419,53 @@ Some networks reach one model family directly while another needs a proxy (for e
180
419
 
181
420
  ## Security
182
421
 
183
- - **Fail-closed authentication.** The server will not start without at least one non-empty `api_keys` entry, and every route requires `Authorization: Bearer <key>`.
422
+ - **Fail-closed authentication.** The server will not start without at least one non-empty `api_keys` entry. OpenAI routes require `Authorization: Bearer <key>`; Anthropic routes also accept `x-api-key: <key>`.
184
423
  - **Local bind by default.** `host` defaults to `127.0.0.1`; only bind `0.0.0.0` behind a firewall or authenticated reverse proxy.
185
- - **Locked-down account store.** `accounts.db` (and its WAL/SHM files) are created with mode `0600`.
424
+ - **Single authentication authority.** Shared mode reads and updates OpenCode's existing Kiro database and fails closed on an incompatible schema; it never runs provider-owned migrations against that database.
425
+ - **Locked-down provider state.** `accounts.db` (and its WAL/SHM files) are created with mode `0600`; in shared mode this database contains affinity/state, not the authoritative credentials.
186
426
  - **No secrets in logs.** Proxy URLs and account tokens are never printed; don't commit a real config file, account database, or gateway key.
187
427
 
188
428
  > **Responsible use.** kiro-provider reuses AWS Kiro accounts you already control and consumes your own account quota. Supply your own accounts — this project is not a way to share or resell someone else's Kiro access, and it should not be used to circumvent per-account usage limits.
189
429
 
190
430
  ## Using with an LLM
191
431
 
192
- Point any OpenAI-compatible client (`openai`, `@ai-sdk/openai-compatible`, LangChain, etc.) at `http://<host>:<port>/v1` with one of your configured `api_keys`.
432
+ Use `POST /v1/responses` for new OpenAI clients and Codex. Use
433
+ `POST /v1/messages` for Anthropic clients and Claude Code. Only point a
434
+ Chat-Completions-only client (`@ai-sdk/openai-compatible`, older LangChain
435
+ adapters, or an OpenCode custom provider using that package) at
436
+ `POST /v1/chat/completions` after explicitly enabling the legacy endpoint.
437
+
438
+ No client-specific session extension is required. The gateway derives
439
+ affinity from standard/native request fields when present and otherwise from
440
+ the initial user turn, stores only an irreversible key hash, and persists the
441
+ selected account plus Kiro conversation ID. Connection reuse is best-effort
442
+ through an account-scoped keep-alive pool; HTTP and upstream behavior can
443
+ still select a different physical socket. Stateful Responses fields
444
+ `previous_response_id` and `conversation` are rejected until the gateway has
445
+ a real response-state store, so clients must resend the complete input.
193
446
 
194
447
  <details>
195
448
  <summary>Agent command reference</summary>
196
449
 
197
450
  - `kiro-provider serve [--config <path>] [--host <host>] [--port <port>] [--proxy <url>]` — start the gateway.
198
- - `kiro-provider login [--config <path>] [--start-url <url>] [--region <region>]` — device-code login (AWS Builder ID, or IAM Identity Center with `--start-url`).
199
- - `kiro-provider accounts list` — list stored accounts and their health.
200
- - `kiro-provider accounts import [--from <path>] [--config <path>]` — import accounts from an OpenCode `kiro.db` (default source: `~/.config/opencode/kiro.db`).
201
- - `kiro-provider accounts remove <id|email>` — remove one account (writes a tombstone).
451
+ - `kiro-provider login [--config <path>] [--start-url <url>] [--region <region>]` — local compatibility mode only; shared mode directs you to `opencode auth login`.
452
+ - `kiro-provider accounts list` — list accounts in the local compatibility store.
453
+ - `kiro-provider accounts import [--from <path>] [--config <path>]` — take a one-time snapshot into the local compatibility store.
454
+ - `kiro-provider accounts remove <id|email>` — remove one account from the local compatibility store.
202
455
 
203
- Contract: human-readable status lines go to stdout, errors to stderr, non-zero exit on failure. `GET /v1/models` and `GET /health` return structured JSON.
456
+ Contract: human-readable status lines go to stdout, errors to stderr, non-zero exit on failure. `GET /v1/models`, `GET /health`, and authenticated `GET /ready` return structured JSON.
204
457
 
205
458
  </details>
206
459
 
207
460
  ## Use with Codex CLI
208
461
 
209
- kiro-provider's `POST /v1/responses` endpoint speaks the OpenAI Responses wire format, so [Codex CLI](https://github.com/openai/codex) (verified against 0.144.6) can use it as a custom `model_provider` with `wire_api = "responses"`. Test it with an isolated `CODEX_HOME` so your real `~/.codex` config is never touched:
462
+ kiro-provider's `POST /v1/responses` endpoint speaks the OpenAI Responses wire format, so [Codex CLI](https://github.com/openai/codex) (verified end-to-end against 0.149.0-alpha.4.1 on 2026-08-22) can use it as a custom `model_provider` with `wire_api = "responses"`. Test it with an isolated `CODEX_HOME` so your real `~/.codex` config is never touched:
210
463
 
211
464
  ```bash
212
- export CODEX_HOME="$(mktemp -d)" # isolated; your real ~/.codex is untouched
465
+ export CODEX_TEST_ROOT="$(mktemp -d)"
466
+ export CODEX_HOME="$CODEX_TEST_ROOT/home"
467
+ export CODEX_SQLITE_HOME="$CODEX_TEST_ROOT/sqlite"
468
+ mkdir -p "$CODEX_HOME" "$CODEX_SQLITE_HOME"
213
469
  export LOCALGW_KEY="sk-...your gateway api key..."
214
470
  cat > "$CODEX_HOME/config.toml" <<'EOF'
215
471
  model = "gpt-5.6-sol"
@@ -223,7 +479,33 @@ EOF
223
479
  codex exec --skip-git-repo-check "say hi"
224
480
  ```
225
481
 
226
- Requires the gateway running (`kiro-provider serve`) with an account already imported or logged in. Reasoning models work through Codex the same way they do for `/v1/chat/completions` (Claude via your configured proxy, GPT direct). Full details, plus a ready-made isolated smoke test (`scripts/codex-smoke.sh`), live in [`docs/CODEX.md`](docs/CODEX.md).
482
+ Requires the gateway running (`kiro-provider serve`) with at least one active
483
+ OpenCode Kiro account in the default shared mode, or an account in the
484
+ explicit local compatibility store. Full details, plus a ready-made isolated
485
+ smoke test (`scripts/codex-smoke.sh`), live in
486
+ [`docs/CODEX.md`](docs/CODEX.md).
487
+
488
+ ## Use with Claude Code
489
+
490
+ Claude Code uses the Anthropic Messages protocol rather than OpenAI Chat
491
+ Completions. Point it at the gateway root:
492
+
493
+ ```bash
494
+ export ANTHROPIC_BASE_URL="http://127.0.0.1:8787"
495
+ export ANTHROPIC_AUTH_TOKEN="sk-your-private-key"
496
+ claude
497
+ ```
498
+
499
+ The gateway accepts either `Authorization: Bearer <key>` or `x-api-key:
500
+ <key>` for Anthropic routes. Streaming text and tool calls are translated to
501
+ Anthropic SSE. Extended-thinking signatures are not fabricated or exposed,
502
+ and `/v1/messages/count_tokens` is an explicit estimate (the response carries
503
+ `x-kiro-token-count-mode: estimate`). See
504
+ [`docs/CLAUDE_CODE.md`](docs/CLAUDE_CODE.md).
505
+
506
+ The real-client validation record for OpenCode, Codex, Claude Code, shared
507
+ authentication, affinity reuse, and the legacy Chat gate is in
508
+ [`docs/E2E_VALIDATION_2026-08-22.md`](docs/E2E_VALIDATION_2026-08-22.md).
227
509
 
228
510
  ## Development
229
511