Skip to content
 
 

Repository files navigation

👻 Kiro Gateway

Proxy gateway for Kiro API (Amazon Q Developer / AWS CodeWhisperer)

🇬🇧 English • 🇷🇺 Русский🇨🇳 中文🇪🇸 Español🇮🇩 Indonesia🇧🇷 Português🇯🇵 日本語🇰🇷 한국어

Made with ❤️ by @Jwadow

License: AGPL v3 Python 3.10+ FastAPI Sponsor

Use Claude models from Kiro with Claude Code, OpenCode, OpenClaw, Claw Code, Codex app, Cursor, Cline, Roo Code, Kilo Code, Obsidian, OpenAI SDK, LangChain, Continue and other OpenAI or Anthropic compatible tools

ModelsFeaturesEnterprise / IdC SetupConfiguration💖 Sponsor


🍴 About This Fork

This is a Polarity fork of Jwadow/kiro-gateway, maintained at polarity-dev/kiro-gateway.

It adds support for Kiro IDE Enterprise accounts (AWS IAM Identity Center), which the upstream project does not fully cover. See Enterprise / IdC Setup for the automated installer and Fork Changes for what differs from upstream.


🚀 Enterprise / IdC Setup

This repo is both the gateway and the setup kit for running Claude Code against it locally. Cloning it gets you everything you need to point Claude Code (and other AI coding tools) at your Kiro subscription.

🤖 Easiest path: guided setup

If you have Kiro IDE or another AI coding assistant open in this repo, ask:

"Set up kiro-gateway and Claude Code for me."

In Claude Code you can also run /setup-gateway. The setup uses the current repository directory automatically and keeps setup, gateway startup, and verification there. It uses another path only when you explicitly name one.

When safe event streaming is available, the agent runs one long-lived process:

./setup.sh -y --aws-profile company --agent-events

Its stdout contains only allowlisted KIRO_EVENT JSONL records, so the agent can relay the code and URL in chat while that same process continues polling. Raw setup/debug logs are never streamed. If safe monitoring is unavailable, enter ! ./setup.sh -y --aws-profile company directly at the Claude Code prompt. In a normal terminal, use the same command without !.

-y accepts local installer confirmations only; it does not bypass AWS approval. Keep the command running. It prints a Code: and URL: before opening the browser and before polling. Compare the browser code with the terminal code character-for-character, including case and hyphens, and choose Confirm and continue only when they match exactly and you initiated the request. If the code differs, is missing, or the request is unexpected, cancel it, press Ctrl+C, and rerun setup for a fresh code. Never reuse a code from an interrupted, denied, or expired attempt.

Add --no-browser to open the printed URL manually, --q-profile NAME_OR_ARN when multiple Q profiles are assigned, or --port PORT for a custom first-setup port. Wait for setup to exit successfully before starting the gateway:

python3 main.py

At startup, an expired access token is refreshed silently. If the direct IdC refresh token or client registration is no longer usable, a local foreground python3 main.py starts one device-authorization flow and then continues only after successful approval. It never loops or silently changes Q profiles. Docker, CI, direct uvicorn main:app, non-TTY services, SQLite/Kiro CLI, and multi-account mode never open a browser; renew credentials separately in those contexts. Use python3 main.py --no-interactive-reauth to disable startup device login explicitly. Agents may use --agent-events to stream only safe startup authentication events.

The full agent contract and troubleshooting flow live in .kiro/steering/setup.md, referenced from CLAUDE.md and AGENTS.md.

🛠️ Manual path

AWS IAM Identity Center users can bootstrap the gateway without Kiro IDE or Kiro CLI. Configure an AWS shared-config profile with sso_start_url and sso_region (directly or through sso_session), then use the normal-terminal command above. Keep it in the foreground and apply the same exact-code check.

What setup.sh does

With --aws-profile, setup registers a public AWS SSO OIDC client, completes device authorization, discovers the assigned Amazon Q Developer profile through bearer-authenticated ListAvailableProfiles, and writes refreshable owner-only (0600) credentials to ~/.aws/sso/cache/kiro-gateway-auth.json. It stores the SSO and Q API regions separately, generates .env, and atomically synchronizes Claude Code and the selected gateway port.

Running without --aws-profile preserves the legacy Kiro IDE credential/log path. Existing credential and .env files are never replaced without confirmation; .env is backed up first.

Requirements

  • Python 3.10+
  • an AWS shared-config IAM Identity Center profile
  • an assigned Amazon Q Developer subscription/profile
  • Claude Code

Troubleshooting

Code is not visible while the browser waits — cancel the request and stop the command; never reuse that code. Agents should rerun with --agent-events through safe event monitoring. Without it, use a visible foreground shell (! ./setup.sh ... inside Claude Code; no ! in a normal terminal).

Repeated 401 Invalid API key from the local gateway — setup and the running gateway may be using different checkouts, each with its own .env proxy key. This is a local Claude-to-gateway mismatch, not an expired IAM Identity Center token. Stop the gateway, return to the repository directory where setup was run, rerun setup/alignment there, restart from that same path, and open a new Claude Code session. Do not delete kiro-gateway-auth.json to fix a local 401.

Browser does not open — rerun with --no-browser, open the printed URL, and approve only if its code exactly matches the terminal Code:.

Code differs, was denied, or expired — cancel/stop the attempt and rerun setup for a fresh code.

No Q Developer profiles — ask the AWS administrator to assign the subscription/profile and retry after propagation.

Multiple Q Developer profiles — rerun with --q-profile NAME_OR_ARN.

runtime.<region>.kiro.dev does not resolve — configure VPN_PROXY_URL in .env.

Claude Code asks for a Claude account login — this is different from the expected AWS IAM Identity Center approval page. Rerun setup; it configures ANTHROPIC_AUTH_TOKEN, not ANTHROPIC_API_KEY.

Shell helper (optional)

setup.sh writes the Claude Code configuration to ~/.claude/settings.json, so claude works from any terminal without exporting anything. The only recurring task is starting the gateway.

Add this to ~/.zshrc to avoid typing the path each time:

# Kiro Gateway
kiro-gateway() {
  local gw_dir="$HOME/repo/kiro-gateway"   # adjust to your clone location
  (cd "$gw_dir" && python3 main.py)
}

Then kiro-gateway starts it in the foreground; stop it with Ctrl+C. Do not add --port or a SERVER_PORT=... assignment to the helper: main.py reads the persisted port from this checkout's .env, so the helper automatically follows future port changes.

Choosing or changing the gateway port

.env is the persisted source of truth for the gateway port. The installer uses the same value for the server runtime and Claude Code's ANTHROPIC_BASE_URL.

For a first setup on a custom port:

./setup.sh -y --aws-profile NAME --port 9000

To change the port after setup is already complete:

./setup.sh --port 9100

The existing-installation path changes only SERVER_PORT and the managed Claude Code connection values. It reuses the current proxy token, preserves unrelated Claude settings, and backs up .env to .env.bak.

Complete this checklist one step at a time:

  1. Run ./setup.sh --port <new-port> and resolve any reported zsh helper drift.
  2. Stop the running gateway with Ctrl+C.
  3. Start it again with python3 main.py or the port-neutral kiro-gateway helper.
  4. Open a new Claude Code session so it reloads ~/.claude/settings.json.
  5. Run ./setup.sh --check-port; it must report the runtime, Claude Code, and optional zsh helper as aligned.

Do not use python3 main.py --port N for a persistent change: that is a transient runtime override and cannot update Claude Code. Also remove any exported SERVER_PORT from the launching shell (unset SERVER_PORT), because shell environment variables override .env.

Why no export lines? Environment variables do not cross terminal sessions, so exporting them in the window running the gateway would not reach the window running claude. Putting them in ~/.claude/settings.json avoids the problem and also reaches Claude Code's background agents, which shell exports do not.

If you prefer environment variables over the settings file, export these instead — but note they apply only to the shell you set them in:

export ANTHROPIC_BASE_URL="http://localhost:$(python3 scripts/manage_gateway_port.py resolve)"
export ANTHROPIC_AUTH_TOKEN="<your PROXY_API_KEY from .env>"

Selecting a model

Model discovery is enabled by setup.sh, so /model inside Claude Code lists the models your subscription grants, labelled From gateway. To inspect them directly:

PORT=$(python3 scripts/manage_gateway_port.py resolve)
curl -s "localhost:$PORT/v1/models" -H "Authorization: Bearer $PROXY_API_KEY" \
  | python3 -c "import sys,json; print('\n'.join(m['id'] for m in json.load(sys.stdin)['data']))"

The synchronizer selects Kiro's auto router and maps Claude Code's virtual Default row to Kiro Auto. Haiku remains separately selectable through its explicit gateway row. Choose any other persistent model with /model or the top-level model setting. Do not set ANTHROPIC_MODEL: it has higher precedence and overrides the saved picker choice. When Kiro adds or removes models, refresh the static local allowlist with:

python3 scripts/sync_claude_models.py sync

Use --check to detect drift without writing. The user-level allowlist is local configuration, not an administrative policy boundary.


🔧 Fork Changes

Changes in this fork that are not yet in upstream:

setup.sh — Automated installer for Enterprise / IdC accounts, described above.

Transparent aliases for long tool names — Kiro limits tool names to 64 characters, while MCP clients can generate longer names such as mcp__<server>__<tool>. The gateway now assigns deterministic, request-scoped aliases only on the Kiro-facing side and restores the exact original names in OpenAI and Anthropic responses, in both streaming and non-streaming modes. Tool IDs, arguments, results, and short names are unchanged; MCP server names no longer need manual shortening.

Support for role: "system" in the Anthropic endpoint — Claude Code sends the system prompt as a message inside the messages array, while the Anthropic API specifies it as a separate top-level system field. Upstream rejects these requests with an HTTP 422 validation error. This fork accepts them:

  • kiro/models_anthropic.pyAnthropicMessage.role accepts "system" alongside "user" and "assistant"
  • kiro/converters_anthropic.pybuild_kiro_payload_anthropic() filters system messages out of the array and merges their text into the system prompt before building the Kiro payload

Note: this change currently covers the Anthropic endpoint only. Upstream's contribution guidelines require feature parity across both the OpenAI and Anthropic surfaces plus test coverage for streaming and non-streaming paths, so it is not yet suitable for a pull request.

Syncing with upstream

git fetch upstream
git merge upstream/main

Expect conflicts in kiro/models_anthropic.py and kiro/converters_anthropic.py, since both carry fork-specific changes.


🤖 Available Models

Model availability is discovered from Kiro for the authenticated subscription and region; this repository intentionally contains no authoritative static model list. Inspect the current gateway catalog with authenticated GET /v1/models, or run python3 scripts/sync_claude_models.py sync to refresh Claude Code's picker.

Non-Claude Kiro IDs are exposed through reversible claude-kiro-<length>-... rows, then decoded back to their raw Kiro modelId before inference.


✨ Features

Feature Description
🔌 OpenAI-compatible API Works with any OpenAI-compatible tool
🔌 Anthropic-compatible API Native /v1/messages endpoint
🔀 Multi-Account Support Intelligent failover between multiple accounts
🌐 VPN/Proxy Support HTTP/SOCKS5 proxy for restricted networks
🧠 Extended Thinking Reasoning is exclusive to our project
👁️ Vision Support Send images to model
🔍 Web Search Search the web for current information
🛠️ Tool Calling Supports function calling
💬 Full message history Passes complete conversation context
📡 Streaming Full SSE streaming support
🔄 Retry Logic Automatic retries on errors (403, 429, 5xx)
📋 Extended model list Including versioned models
🔐 Smart token management Automatic refresh before expiration

🚀 Legacy / Advanced Credential Setup

IAM Identity Center users: prefer the automated Enterprise / IdC Setup above. The methods below reuse credentials managed by Kiro IDE/Kiro CLI or configure credential sources manually; they are retained for compatibility.

Choose your deployment method:

  • 🐍 Native Python - Full control, easy debugging
  • 🐳 Docker - Isolated environment, easy deployment → jump to Docker

Prerequisites

  • Python 3.10+
  • One of the following:
    • Kiro IDE with logged in account, OR
    • Kiro CLI with AWS SSO (AWS IAM Identity Center, OIDC) - free Builder ID or corporate account

Installation

# Clone the repository (requires Git)
git clone https://github.com/Jwadow/kiro-gateway.git
cd kiro-gateway

# Or download ZIP: Code → Download ZIP → extract → open kiro-gateway folder

# Install dependencies
pip install -r requirements.txt

# Configure (see Configuration section)
cp .env.example .env
# Copy and edit .env with your credentials

# Start the server
python main.py

# Or with custom port (if 4567 is busy)
python main.py --port 9000

The server will be available at http://localhost:4567


⚙️ Configuration

💡 Advanced users: Looking for multi-account support? See Account System below.

Option 1: JSON Credentials File (Kiro IDE / Enterprise)

Specify the path to the credentials file:

Works with:

  • Kiro IDE (standard) - for personal accounts
  • Enterprise - for corporate accounts with SSO
KIRO_CREDS_FILE="~/.aws/sso/cache/kiro-auth-token.json"

# Password to protect YOUR proxy server (make up any secure string)
# You'll use this as api_key when connecting to your gateway
PROXY_API_KEY="my-super-secret-password-123"
📄 JSON file format
{
  "accessToken": "eyJ...",
  "refreshToken": "eyJ...",
  "expiresAt": "2025-01-12T23:00:00.000Z",
  "profileArn": "arn:aws:codewhisperer:us-east-1:...",
  "region": "us-east-1",
  "clientIdHash": "abc123..."  // Optional: for corporate SSO setups
}

Note: If you have two JSON files in ~/.aws/sso/cache/ (e.g., kiro-auth-token.json and a file with a hash name), use kiro-auth-token.json in KIRO_CREDS_FILE. The gateway will automatically load the other file.

Option 2: Environment Variables (.env file)

Create a .env file in the project root:

# Required
REFRESH_TOKEN="your_kiro_refresh_token"

# Password to protect YOUR proxy server (make up any secure string)
PROXY_API_KEY="my-super-secret-password-123"

# Optional
PROFILE_ARN="arn:aws:codewhisperer:us-east-1:..."
KIRO_REGION="us-east-1"

Option 3: AWS SSO Credentials (kiro-cli / Enterprise)

If you use kiro-cli or Kiro IDE with AWS SSO (AWS IAM Identity Center), the gateway will automatically detect and use the appropriate authentication.

Works with both free Builder ID accounts and corporate accounts.

KIRO_CREDS_FILE="~/.aws/sso/cache/your-sso-cache-file.json"

# Password to protect YOUR proxy server
PROXY_API_KEY="my-super-secret-password-123"

# Enterprise Amazon Q requests require a profile ARN.
# Direct bootstrap discovers it automatically. For legacy credential sources
# that omit it, set PROFILE_ARN manually. Builder ID may work without one.
📄 AWS SSO JSON file format

AWS SSO credentials files (from ~/.aws/sso/cache/) contain:

{
  "accessToken": "eyJ...",
  "refreshToken": "eyJ...",
  "expiresAt": "2025-01-12T23:00:00.000Z",
  "region": "us-east-1",
  "clientId": "...",
  "clientSecret": "..."
}

Note: Direct IAM Identity Center bootstrap discovers and stores profileArn automatically. Enterprise Amazon Q requests require it; legacy AWS SSO credential sources that omit it must provide PROFILE_ARN separately. Builder ID accounts may work without an Enterprise profile ARN.

🔍 How it works

The gateway automatically detects the authentication type based on the credentials file:

  • Kiro Desktop Auth (default): Used when clientId and clientSecret are NOT present

    • Endpoint: https://prod.{region}.auth.desktop.kiro.dev/refreshToken
  • AWS SSO (OIDC): Used when clientId and clientSecret ARE present

    • Endpoint: https://oidc.{region}.amazonaws.com/token

No additional configuration is needed — just point to your credentials file!

Option 4: kiro-cli SQLite Database

If you use kiro-cli and prefer to use its SQLite database directly:

KIRO_CLI_DB_FILE="~/.local/share/kiro-cli/data.sqlite3"

# Password to protect YOUR proxy server
PROXY_API_KEY="my-super-secret-password-123"

# Enterprise Amazon Q requests require a profile ARN.
# Direct bootstrap discovers it automatically. For legacy credential sources
# that omit it, set PROFILE_ARN manually. Builder ID may work without one.
📄 Database locations
CLI Tool Database Path
kiro-cli ~/.local/share/kiro-cli/data.sqlite3
amazon-q-developer-cli ~/.local/share/amazon-q/data.sqlite3

The gateway reads credentials from the auth_kv table which stores:

  • kirocli:odic:token or codewhisperer:odic:token — access token, refresh token, expiration
  • kirocli:odic:device-registration or codewhisperer:odic:device-registration — client ID and secret

Both key formats are supported for compatibility with different kiro-cli versions.

Getting Credentials

For Kiro IDE users:

  • Log in to Kiro IDE and use Option 1 above (JSON credentials file)
  • The credentials file is created automatically after login

For Kiro CLI users:

  • Log in with kiro-cli login and use Option 3 or Option 4 above
  • No manual token extraction needed!
🔧 Advanced: Manual token extraction

If you need to manually extract the refresh token (e.g., for debugging), you can intercept Kiro IDE traffic:

  • Look for requests to: prod.us-east-1.auth.desktop.kiro.dev/refreshToken

🔀 Account System (Advanced)

Account System is a way to manage multiple Kiro accounts with automatic failover. In the future, this system will replace .env file for credential configuration, but currently it's optional and intended for those who want to use multiple accounts.

Why You Need This

If you have multiple Kiro accounts, the gateway can automatically switch between them when account is temporarily unavailable.

The system works with a single account too — just without switching.

How to Enable

Add to your .env:

ACCOUNT_SYSTEM=true

What happens:

  • On first startup, your credentials from .env are automatically migrated to credentials.json (one-time)
  • After that, all account and region settings from .env are ignored
  • Account management only through credentials.json
📄 Configuration Examples

Single account:

[
  {
    "type": "json",
    "path": "~/.aws/sso/cache/kiro-auth-token.json"
  }
]

Multiple accounts:

[
  {
    "type": "json",
    "path": "~/.aws/sso/cache/kiro-auth-token.json"
  },
  {
    "type": "sqlite",
    "path": "~/.local/share/kiro-cli/data.sqlite3"
  },
  {
    "type": "refresh_token",
    "refresh_token": "eyJhbGc...",
    "profile_arn": "arn:aws:codewhisperer:us-east-1:..."
  }
]

Folder with files:

[
  {
    "type": "json",
    "path": "C:\\MyAccs\\kiro67"
  }
]

The gateway will scan all files in the folder and add them as separate accounts.

How Failover Works

When one account returns an error (429 rate limit, 402 quota exceeded), the gateway automatically tries the next account from the list. If an account fails several times in a row, the gateway temporarily stops using it and periodically checks if it has recovered.

For a single account, failover doesn't work — you get the original error from Kiro API.

For complete configuration examples (including per-account region settings), see credentials.json.example.


🐳 Docker Deployment

Docker-based deployment. Prefer native Python? See Enterprise / IdC Setup above.

Quick Start

# 1. Clone and configure
git clone https://github.com/Jwadow/kiro-gateway.git
cd kiro-gateway
cp .env.example .env
# Edit .env with your credentials

# 2. Run with docker-compose
docker-compose up -d

# 3. Check status
docker-compose logs -f
curl http://localhost:4567/health

Docker Run (Without Compose)

🔹 Using Environment Variables
docker run -d \
  -p 4567:4567 \
  -e PROXY_API_KEY="my-super-secret-password-123" \
  -e REFRESH_TOKEN="your_refresh_token" \
  --name kiro-gateway \
  ghcr.io/jwadow/kiro-gateway:latest
🔹 Using Credentials File

Linux/macOS:

docker run -d \
  -p 4567:4567 \
  -v ~/.aws/sso/cache:/home/kiro/.aws/sso/cache:ro \
  -e KIRO_CREDS_FILE=/home/kiro/.aws/sso/cache/kiro-auth-token.json \
  -e PROXY_API_KEY="my-super-secret-password-123" \
  --name kiro-gateway \
  ghcr.io/jwadow/kiro-gateway:latest

Windows (PowerShell):

docker run -d `
  -p 4567:4567 `
  -v ${HOME}/.aws/sso/cache:/home/kiro/.aws/sso/cache:ro `
  -e KIRO_CREDS_FILE=/home/kiro/.aws/sso/cache/kiro-auth-token.json `
  -e PROXY_API_KEY="my-super-secret-password-123" `
  --name kiro-gateway `
  ghcr.io/jwadow/kiro-gateway:latest
🔹 Using .env File
docker run -d -p 4567:4567 --env-file .env --name kiro-gateway ghcr.io/jwadow/kiro-gateway:latest

Docker Compose Configuration

Edit docker-compose.yml and uncomment volume mounts for your OS:

volumes:
  # Kiro IDE credentials (choose your OS)
  - ~/.aws/sso/cache:/home/kiro/.aws/sso/cache:ro              # Linux/macOS
  # - ${USERPROFILE}/.aws/sso/cache:/home/kiro/.aws/sso/cache:ro  # Windows
  
  # kiro-cli database (choose your OS)
  - ~/.local/share/kiro-cli:/home/kiro/.local/share/kiro-cli  # Linux/macOS
  # - ${USERPROFILE}/.local/share/kiro-cli:/home/kiro/.local/share/kiro-cli  # Windows
  
  # Debug logs (optional)
  - ./debug_logs:/app/debug_logs

Management Commands

docker-compose logs -f      # View logs
docker-compose restart      # Restart
docker-compose down         # Stop
docker-compose pull && docker-compose up -d  # Update
🔧 Building from Source
docker build -t kiro-gateway .
docker run -d -p 4567:4567 --env-file .env kiro-gateway

🌐 VPN/Proxy Support

For users in China, corporate networks, or regions with connectivity issues to AWS services.

The gateway supports routing all Kiro API requests through a VPN or proxy server. This is essential if you experience connection problems to AWS endpoints or need to use a corporate proxy.

Configuration

Add to your .env file:

# HTTP proxy
VPN_PROXY_URL=http://127.0.0.1:7890

# SOCKS5 proxy
VPN_PROXY_URL=socks5://127.0.0.1:1080

# With authentication (corporate proxies)
VPN_PROXY_URL=http://username:password@proxy.company.com:8080

# Without protocol (defaults to http://)
VPN_PROXY_URL=192.168.1.100:8080

Supported Protocols

  • HTTP — Standard proxy protocol
  • HTTPS — Secure proxy connections
  • SOCKS5 — Advanced proxy protocol (common in VPN software)
  • Authentication — Username/password embedded in URL

When You Need This

Situation Solution
Connection timeouts to AWS Use VPN/proxy to route traffic
Corporate network restrictions Configure your company's proxy
Regional connectivity issues Use a VPN service with proxy support
Privacy requirements Route through your own proxy server

Popular VPN Software with Proxy Support

Most VPN clients provide a local proxy server you can use:

  • Sing-box — Modern VPN client with HTTP/SOCKS5 proxy
  • Clash — Usually runs on http://127.0.0.1:7890
  • V2Ray — Configurable SOCKS5/HTTP proxy
  • Shadowsocks — SOCKS5 proxy support
  • Corporate VPN — Check your IT department for proxy settings

Leave VPN_PROXY_URL empty (default) if you don't need proxy support.


📡 API Reference

Endpoints

Endpoint Method Description
/ GET Health check
/health GET Detailed health check
/v1/models GET List available models
/v1/chat/completions POST OpenAI Chat Completions API
/v1/messages POST Anthropic Messages API

💡 Usage Examples

OpenAI API

🔹 Simple cURL Request
curl http://localhost:4567/v1/chat/completions \
  -H "Authorization: Bearer my-super-secret-password-123" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-5",
    "messages": [{"role": "user", "content": "Hello!"}],
    "stream": true
  }'

Note: Replace my-super-secret-password-123 with the PROXY_API_KEY you set in your .env file.

🔹 Streaming Request
curl http://localhost:4567/v1/chat/completions \
  -H "Authorization: Bearer my-super-secret-password-123" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-5",
    "messages": [
      {"role": "system", "content": "You are a helpful assistant."},
      {"role": "user", "content": "What is 2+2?"}
    ],
    "stream": true
  }'
🛠️ With Tool Calling
curl http://localhost:4567/v1/chat/completions \
  -H "Authorization: Bearer my-super-secret-password-123" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-5",
    "messages": [{"role": "user", "content": "What is the weather in London?"}],
    "tools": [{
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Get weather for a location",
        "parameters": {
          "type": "object",
          "properties": {
            "location": {"type": "string", "description": "City name"}
          },
          "required": ["location"]
        }
      }
    }]
  }'
🐍 Python OpenAI SDK
from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:4567/v1",
    api_key="my-super-secret-password-123"  # Your PROXY_API_KEY from .env
)

response = client.chat.completions.create(
    model="claude-sonnet-4-5",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Hello!"}
    ],
    stream=True
)

for chunk in response:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")
🦜 LangChain
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    base_url="http://localhost:4567/v1",
    api_key="my-super-secret-password-123",  # Your PROXY_API_KEY from .env
    model="claude-sonnet-4-5"
)

response = llm.invoke("Hello, how are you?")
print(response.content)

Anthropic API

🔹 Simple cURL Request
curl http://localhost:4567/v1/messages \
  -H "x-api-key: my-super-secret-password-123" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-5",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "Hello!"}]
  }'

Note: Anthropic API uses x-api-key header instead of Authorization: Bearer. Both are supported.

🔹 With System Prompt
curl http://localhost:4567/v1/messages \
  -H "x-api-key: my-super-secret-password-123" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-5",
    "max_tokens": 1024,
    "system": "You are a helpful assistant.",
    "messages": [{"role": "user", "content": "Hello!"}]
  }'

Note: In Anthropic API, system is a separate field, not a message.

📡 Streaming
curl http://localhost:4567/v1/messages \
  -H "x-api-key: my-super-secret-password-123" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-5",
    "max_tokens": 1024,
    "stream": true,
    "messages": [{"role": "user", "content": "Hello!"}]
  }'
🐍 Python Anthropic SDK
import anthropic

client = anthropic.Anthropic(
    api_key="my-super-secret-password-123",  # Your PROXY_API_KEY from .env
    base_url="http://localhost:4567"
)

# Non-streaming
response = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}]
)
print(response.content[0].text)

# Streaming
with client.messages.stream(
    model="claude-sonnet-4-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}]
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)

🔧 Debugging

Debug logging is disabled by default. To enable, add to your .env:

# Debug logging mode:
# - off: disabled (default)
# - errors: save logs only for failed requests (4xx, 5xx) - recommended for troubleshooting
# - all: save logs for every request (overwrites on each request)
DEBUG_MODE=errors

Debug Modes

Mode Description Use Case
off Disabled (default) Production
errors Save logs only for failed requests (4xx, 5xx) Recommended for troubleshooting
all Save logs for every request Development/debugging

Debug Files

When enabled, requests are logged to the debug_logs/ folder:

File Description
request_body.json Incoming request from client (OpenAI format)
kiro_request_body.json Request sent to Kiro API
response_stream_raw.txt Raw stream from Kiro
response_stream_modified.txt Transformed stream (OpenAI format)
app_logs.txt Application logs for the request
error_info.json Error details (only on errors)

🔧 Troubleshooting

Connection Issues

Error: "Name or service not known" or DNS resolution failed

The Q API endpoint may not be publicly resolvable in your region. Use a VPN or proxy:

VPN_PROXY_URL=http://127.0.0.1:7890

See VPN/Proxy Support for details.


Error: "503 Service Unavailable" through proxy

The Q API endpoint exists in specific regions only. Try a different region:

KIRO_API_REGION="eu-central-1"  # or us-east-1

Commonly reachable regions: us-east-1, eu-central-1


OIDC works but Q API fails

Your SSO region may differ from the Q API region. The gateway auto-detects this from credentials, but you can override:

KIRO_API_REGION="eu-central-1"

📜 License

This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).

This means:

  • ✅ You can use, modify, and distribute this software
  • ✅ You can use it for commercial purposes
  • ⚠️ You must disclose source code when you distribute the software
  • ⚠️ Network use is distribution — if you run a modified version on a server and let others interact with it, you must make the source code available to them
  • ⚠️ Modifications must be released under the same license

See the LICENSE file for the full license text.

Why AGPL-3.0?

AGPL-3.0 ensures that improvements to this software benefit the entire community. If you modify this gateway and deploy it as a service, you must share your improvements with your users.

Contributor License Agreement (CLA)

By submitting a contribution to this project, you agree to the terms of our Contributor License Agreement (CLA). This ensures that:

  • You have the right to submit the contribution
  • You grant the maintainer rights to use and relicense your contribution
  • The project remains legally protected

💖 Support the Project

Love

If this project saved you time or money, consider supporting it!

Every contribution helps keep this project alive and growing


🤑 Donate

☕ One-time Support


🪙 Or send crypto

Currency Network Address
USDT TRC20 TSVtgRc9pkC1UgcbVeijBHjFmpkYHDRu26
BTC Bitcoin 12GZqxqpcBsqJ4Vf1YreLqwoMGvzBPgJq6
ETH Ethereum 0xc86eab3bba3bbaf4eb5b5fff8586f1460f1fd395
SOL Solana 9amykF7KibZmdaw66a1oqYJyi75fRqgdsqnG66AK3jvh
TON TON UQBVh8T1H3GI7gd7b-_PPNnxHYYxptrcCVf3qQk5v41h3QTM

⚠️ Disclaimer

This project is not affiliated with, endorsed by, or sponsored by Amazon Web Services (AWS), Anthropic, or Kiro IDE. Use at your own risk and in compliance with the terms of service of the underlying APIs.


About

👻 Proxy API gateway for Kiro IDE & CLI (Amazon Q Developer / AWS CodeWhisperer). Use free Claude models with any client.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages