7.7 KiB
opencode-kimi-full
An opencode plugin that adds a Kimi For Coding OAuth provider.
This plugin:
- uses the official Kimi device flow against
https://auth.kimi.comwithscope: kimi-code - talks to
https://api.kimi.com/coding/v1through@ai-sdk/openai-compatible - sends the same
User-Agent/X-Msh-*fingerprint headers askimi-cli - reuses
~/.kimi/device_idforX-Msh-Device-Id - adds
prompt_cache_key,thinking, andreasoning_effortforkimi-for-codingrequests
This is the K2.6 / kimi-for-coding OAuth path: Moonshot routes static sk-kimi-... API keys to K2.5, and OAuth tokens with scope: kimi-code to K2.6.
Contributor and agent documentation lives in AGENTS.md.
Requirements
opencode≥ 1.4.6- A Kimi account with an active Kimi For Coding subscription (the same plan that works with kimi-cli)
Install
opencode plugin opencode-kimi-full --global
That installs the plugin through opencode and adds it to your global config.
Or add the package name to the plugin list in ~/.config/opencode/opencode.json or a project-local .opencode/opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-kimi-full"]
}
From a local checkout
Point the plugin entry at the repo root instead of the npm package name:
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["/absolute/path/to/opencode-kimi-full"]
}
Configure
After the plugin is installed, add a provider entry in ~/.config/opencode/opencode.json or .opencode/opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-kimi-full"],
"provider": {
"kimi-for-coding-oauth": {
"name": "Kimi For Coding (OAuth)",
"npm": "@ai-sdk/openai-compatible",
"options": {
"baseURL": "https://api.kimi.com/coding/v1"
},
"models": {
"kimi-for-coding": {
"name": "Kimi For Coding",
"reasoning": true,
"options": {},
"variants": {
"off": { "reasoning_effort": "off" },
"auto": { "reasoning_effort": "auto" },
"low": { "reasoning_effort": "low" },
"medium": { "reasoning_effort": "medium" },
"high": { "reasoning_effort": "high" }
}
}
}
}
}
}
Two identifiers are load-bearing:
- provider id
kimi-for-coding-oauth— the plugin'sauthandchat.paramshooks match on it. - model id
kimi-for-coding— a stable opencode-side alias. At login and on every token refresh the plugin queries/coding/v1/modelsand rewrites the wiremodelfield if the server reports a different slug for your account.
Note. The provider id is intentionally not
kimi-for-coding. That id is already published by models.dev and points at a static-API-key flow using a different SDK and auth shape. Using a distinct id keeps the two paths from colliding under a singleopencode auth loginentry.
Log in
opencode auth login -p kimi-for-coding-oauth
The plugin returns a verification URL and user code. After browser approval it polls the device-auth endpoint, queries /coding/v1/models to discover the current model id and context length for your account, prints a config snippet with that context length filled in, and stores the token plus discovered model metadata in opencode's auth store. Model discovery runs again on every token refresh. Access tokens refresh automatically, and the loader retries once after a 401.
Use
Select kimi-for-coding-oauth/kimi-for-coding in opencode.
The default variant-cycle keybind is Ctrl+T. The variants map as follows:
off→ sendsthinking: { "type": "disabled" }auto→ omits boththinkingandreasoning_effortlow/medium/high→ sendthinking: { "type": "enabled" }plus the matchingreasoning_effort
Why this plugin exists
This plugin exists to bring the OAuth/device-flow kimi-cli path into opencode without sharing kimi-cli's credential files.
What it changes.
- OAuth device flow with
scope: kimi-code. @ai-sdk/openai-compatiblepointed athttps://api.kimi.com/coding/v1.prompt_cache_keyset to opencode's session id, for session-scoped cache reuse.- Paired
thinking+reasoning_effortfields. - The seven
X-Msh-*headers and a kimi-cli-shapedUser-Agent. ~/.kimi/device_idshared with a locally-installed kimi-cli.- Tokens stored in opencode's auth store under a dedicated provider id, so the plugin and kimi-cli keep independent refresh-token chains and do not invalidate each other.
- Streaming,
reasoning_contentdeltas, and tool-call schemas are handled upstream by@ai-sdk/openai-compatible— not reimplemented here.
Request fields in detail
| Field | Wire shape | Purpose |
|---|---|---|
prompt_cache_key |
top-level body, snake_case, set to opencode's sessionID |
Opt-in, session-scoped cache key, mirroring kimi-cli. |
thinking + reasoning_effort |
thinking: { type: "enabled" | "disabled" } with sibling reasoning_effort: "low" | "medium" | "high" |
Sent together, matching kimi-cli. |
Seven X-Msh-* headers + UA |
User-Agent, X-Msh-Platform, X-Msh-Version, X-Msh-Device-Name, X-Msh-Device-Model, X-Msh-Device-Id, X-Msh-Os-Version |
Matches kimi-cli's _kimi_default_headers() at the pinned KIMI_CLI_VERSION. |
~/.kimi/device_id |
UUID persisted on disk, embedded in X-Msh-Device-Id |
Sends the same X-Msh-Device-Id as a locally-installed kimi-cli. |
Effort-to-field mapping, taken verbatim from kimi-cli:
| user effort | reasoning_effort |
thinking |
|---|---|---|
auto |
(omitted) | (omitted) — server picks dynamically |
off |
(omitted) | { type: "disabled" } |
low / medium / high |
same string | { type: "enabled" } |
Files the plugin touches
| Path | Purpose |
|---|---|
~/.kimi/device_id |
Stable UUID used in X-Msh-Device-Id. Shared with kimi-cli. |
opencode auth store (auth.json in opencode's XDG data dir; on Linux typically ~/.local/share/opencode/auth.json) |
Token storage, managed by opencode through client.auth.*. |
No other state is persisted. Credentials are never written to ~/.kimi/credentials/; that path belongs to kimi-cli, and sharing it would cause refresh-token races between the two clients.
Architecture at a glance
┌────────────── opencode core ─────────────┐
│ │
│ auth.login ─▶ plugin.auth.authorize() │ device-code flow, poll
│ └─▶ oauth.ts │
│ │
│ chat ──────▶ plugin.loader() │ custom fetch that:
│ ├─▶ ensureFresh() │ • proactive refresh
│ └─▶ kimiHeaders() │ • 7 X-Msh-* headers
│ │ • 401 → force-refresh + retry
│ chat.params ─▶ plugin "chat.params" │ thinking / reasoning_effort /
│ │ prompt_cache_key
└──────────────────────────────────────────┘
A full description of the invariants that keep this working is in AGENTS.md, under "Architecture" and "Contracts to keep intact".
License
MIT.