Skip to main content
kRouter
All posts
How kRouter works

Kiro IDE with any model through a local MITM proxy

Kiro IDE has no custom endpoint setting. kRouter's MITM mode sends its chat turns to any model you map. How it works, the v0.5.137 fix, and setup.

Kodelyth · The team behind kRouter
· Updated
7 min read

Updated October 2026. The first version of this post got the history backwards: native passthrough for Kiro was added in v0.5.65 and removed in v0.5.74, so translation is still in the path and the prompt-cache claims it made do not hold. Its setup steps also used a sudo krouter --mitm command and a Settings menu that do not exist. Both are corrected below, and the Kiro IDE 1.0.228 fix is new.

The Kiro IDE desktop app is a capable coding environment with one hard limitation: you cannot configure a custom API endpoint. It talks to Kiro's own backend and nothing else. A request for bring-your-own-key and local model support is still open on Kiro's issue tracker.

If you want Kiro IDE's interface but with models from a subscription you already pay for, a local model, or a cheap API plan, the only route is a man-in-the-middle (MITM) proxy: something on your machine that answers for Kiro's hostnames, reads the chat request, and sends it somewhere else. kRouter's MITM mode does that. Here is how it works today, what broke along the way, and how to set it up.

How the interception works

  • DNS. When you start DNS for Kiro, kRouter points three hostnames at 127.0.0.1 in your hosts file: runtime.us-east-1.kiro.dev, q.us-east-1.amazonaws.com and codewhisperer.us-east-1.amazonaws.com.
  • TLS. A local server on port 443 answers for those names with certificates signed by a root CA that kRouter generates and you install.
  • Chat turns only. Only GenerateAssistantResponse calls are intercepted. Everything else on those hosts, such as the model list, passes through to AWS unchanged.
  • Per-model mapping. The Kiro card has a slot for each model Kiro asks for -- Auto, Claude Sonnet 4.5, Claude Sonnet 4, Claude Haiku 4.5, DeepSeek 3.2, MiniMax M2.1 and Qwen3 Coder Next -- and you map each one to any kRouter provider/model or combo. A request for a model with no mapping is passed through to Kiro as normal.
  • Translation. For a mapped model, kRouter converts Kiro's conversationState request into an OpenAI chat request, sends it to its own /v1/chat/completions, and turns the streamed answer back into the AWS EventStream frames Kiro expects. Because the request goes through the normal router, combos, Zenith account scoring and RTK all apply.

What broke, and when it was fixed

Native passthrough: added in v0.5.65, removed in v0.5.74

v0.5.65 tried to skip translation when Kiro IDE talked to the Kiro provider and forward the body byte for byte, which would have kept AWS's prompt-cache prefix intact. It did not work. Under MITM the body has already been converted to OpenAI format by the time the router sees it, so passthrough sent an OpenAI-shaped body to Kiro's API, which answered REQUEST_BODY_INVALID. v0.5.74 removed Kiro from native passthrough, and the translator has run on every mapped request since.

Tool IDs (v0.5.74)

Tool call IDs from other providers -- Gemini's dots and colons, OpenAI's slashes -- went into Kiro's toolUseId fields unchanged, and Kiro's Claude backends reject anything outside ^[a-zA-Z0-9_-]+$. v0.5.74 sanitizes the ID in all four places the Kiro translator sets one. That matters as soon as one conversation mixes models from different providers.

The anti-loop header (v0.5.74)

kRouter's own calls to Kiro's API use the same hostnames the MITM now answers for. They carry an x-request-source: local header, and the MITM server passes anything with that header straight through instead of intercepting it again. Some executors built their own headers and dropped it, so kRouter's outbound Kiro requests were caught by its own proxy and arrived with zero messages. v0.5.74 forces the header on every executor.

Persona prompts (v0.5.65)

Caveman and Ponytail fell through to the OpenAI request shape for Kiro and silently did nothing. v0.5.65 added a Kiro case that prepends the persona to the current user message, since Kiro's format has no separate system slot.

Streams that hung or ended quietly

The fork's first hardening pass made the MITM stream layer fail loudly instead:

  • An upstream HTTP error reaches Kiro as an EventStream exception frame carrying the real message, not an empty 200.
  • A connection that drops mid-stream ends with a terminal frame instead of leaving the IDE hanging.
  • The frame encoder bounds-checks its headers, which was the source of Truncated event message received.
  • Node's 5-minute request timeout is off, so long agentic streams are not cut mid-frame.

Later, v0.5.101 stopped the handler from dropping every <thinking> block after the first one in a chunk.

Kiro IDE 1.0.228 and later (v0.5.137)

This is the fix that matters if MITM "is on but nothing happens". Kiro IDE 1.0.228 moved chat from the /generateAssistantResponse path to POST / with an x-amz-target: KiroRuntimeService.GenerateAssistantResponse header. kRouter matched on the path only, so every chat turn was passed through to AWS: MITM showed as enabled, the mapping was set, and nothing was routed, with no error anywhere.

v0.5.137 matches the header as well, moves Kiro's MITM domain to runtime.us-east-1.kiro.dev, and sends the initial-response frame Kiro's stream decoder requires before the first token.

Leftover hosts entries (v0.5.134)

If the MITM server stopped while its hosts-file redirects stayed in place, every Kiro request died as a bare fetch failed, which looks like a network fault. Since v0.5.134, kRouter detects that state at startup, tries to remove the entries, and prints the exact command to run if it cannot.

What you get, and what you do not

  • Kiro's interface and agent, backed by whatever you map: your Claude subscription through the Claude Code provider (cc/claude-sonnet-4-6), a flat-rate plan such as OpenCode Go (ocg/kimi-k2.6), a free provider, or a combo.
  • RTK, which is on by default, compresses tool output in those requests, since they pass through the router.
  • Unmapped models and every non-chat call still go to Kiro, on your Kiro account.
  • Translation stays in the path. The byte-exact prompt-cache preservation an earlier version of this post promised does not happen; whether the provider you map to caches the translated prompt depends on that provider.
  • It needs admin rights on Windows, or your sudo password on macOS and Linux, for port 443, the hosts file and the trust store. It does not work inside Docker.
  • kRouter's MITM page carries its own warning: intercepting an IDE's traffic may break that tool's terms of service and get the account banned. Use it knowing that.

How to set it up

  1. Install and start kRouter normally. kRouter itself does not need sudo:

    npm install -g @sifxprime/krouter
    krouter -t
  2. Open http://localhost:20128/dashboard and choose MITM in the sidebar.

  3. In the MITM Server card, click Start Server. On macOS and Linux it asks for your sudo password, which it can cache encrypted; on Windows kRouter needs administrator rights.

  4. In the MITM Root Certificate card, click Install Certificate to add kRouter's root CA to your system trust store.

  5. Expand the Kiro card, click Start DNS, then map each Kiro model slot to a provider/model such as cc/claude-sonnet-4-6, or to a combo name.

  6. Restart Kiro IDE and send a prompt. Mapped requests show up on kRouter's Usage page.

To undo it, click Stop DNS on the Kiro card, Stop Server in the server card, and Uninstall in the certificate card. The MITM guide covers the same flow for Antigravity, Copilot and Claude Desktop.

Common questions

Why does MITM show as enabled while Kiro still uses its own models?

Most often it is a kRouter older than v0.5.137 with Kiro IDE 1.0.228 or later: the new chat call was not recognised and went straight to AWS. Update kRouter. Also check the slot for the model Kiro is using, because an unmapped model is passed through to Kiro on purpose.

Do I need to run kRouter with sudo?

No. kRouter runs as your user. The dashboard asks for your sudo password when it starts the MITM server on port 443, installs the root certificate and edits the hosts file. On Windows those steps need administrator rights.

Does Kiro IDE MITM work in Docker?

No. MITM has to edit the host's hosts file and trust store and listen on port 443, so kRouter detects a container and reports that MITM is unavailable. Run kRouter natively on the machine where Kiro IDE runs.

Is Kiro's prompt caching preserved?

Not byte for byte. Mapped requests are translated to OpenAI format and back, so caching depends on the provider you map to. Unmapped models go to Kiro untouched.

How do I remove the interception completely?

Stop DNS on the Kiro card, stop the MITM server, and click Uninstall on the MITM Root Certificate card. If Kiro shows fetch failed afterwards, a hosts-file entry was left behind; kRouter reports this at startup and prints the command that removes it.

Kodelyth · The team behind kRouter

Published by Kodelyth, the team that builds kRouter. Posts are drafted with AI assistance and reviewed by a person before they go out. kRouter is free and MIT licensed.

Install kRouter