opencode-kimi-rotator
v1.2.4
Published
Kimi API Key Rotator for OpenCode - Automatically rotate between multiple Kimi API keys to handle rate limits
Downloads
348
Maintainers
Readme
Kimi API Key Rotator for OpenCode
Automatically rotate between multiple Kimi API keys to handle rate limits and distribute load across accounts.
What You Get
- Multiple API Key Support — Store and manage unlimited Kimi API keys
- Auto-Rotation — Automatically switch keys when rate limited
- Billing Limit Cooldown — 24-hour automatic cooldown when billing cycle limits are reached
- Health-Based Selection — Smart rotation using health scores and LRU
- Three Rotation Strategies:
round-robin— Cycle through keys sequentiallyhealth-based— Use health scores + freshness (default)sticky— Stay on one key until rate limited
- CLI Management — Easy commands to add, list, and manage keys
- Plugin compatible — Works alongside other OpenCode plugins (oh-my-opencode, antigravity-auth, etc.)
Installation
Option A: NPM (One-line installation)
npm install -g opencode-kimi-rotatorThat's it! The plugin is automatically built and installed. Now add your API keys:
opencode-kimi add-key sk-kimi-your-key-here "My Account"Option B: Automatic Install Script
curl -fsSL https://raw.githubusercontent.com/deyndev/opencode-kimi-rotator/main/scripts/install.sh | bashOr for Windows (PowerShell):
irm https://raw.githubusercontent.com/deyndev/opencode-kimi-rotator/main/scripts/install.ps1 | iexOption C: Manual setup
Clone and build the plugin:
git clone https://github.com/deyndev/opencode-kimi-rotator.git cd opencode-kimi-rotator npm install npm run build npm run install:pluginAdd the model to your
~/.config/opencode/opencode.json:{ "provider": { "anthropic": { "name": "Anthropic", "models": { "kimi-for-coding": { "name": "Kimi K2.5 (via Kimi API)", "attachment": true, "limit": { "context": 262144, "output": 32768 }, "modalities": { "input": ["text", "image", "video", "pdf"], "output": ["text"] } } } } } }Add your API keys:
opencode-kimi add-key sk-kimi-your-key-here "My Account 1" opencode-kimi add-key sk-kimi-another-key "My Account 2"Use it:
opencode run "Hello" --model=anthropic/kimi-for-coding
Complete Installation Steps
1. Clone and build the plugin:
git clone https://github.com/deyndev/opencode-kimi-rotator.git
cd opencode-kimi-rotator
npm install
npm run install:plugin2. Add the plugin and model to ~/.config/opencode/opencode.json:
Add the plugin to your existing config. The plugin path must use the full absolute path:
{
"plugin": ["file:///Users/YOUR_USERNAME/.config/opencode/plugins/kimi-rotator.js"],
"provider": {
"anthropic": {
"name": "Anthropic",
"models": {
"kimi-for-coding": {
"name": "Kimi K2.5 (via Kimi API)",
"attachment": true,
"limit": {
"context": 262144,
"output": 32768
},
"modalities": {
"input": ["text", "image", "video", "pdf"],
"output": ["text"]
}
}
}
}
}
}Important: Replace
YOUR_USERNAMEwith your actual username. Example paths:
- macOS:
file:///Users/john/.config/opencode/plugins/kimi-rotator.js- Linux:
file:///home/john/.config/opencode/plugins/kimi-rotator.js
3. Configure oh-my-opencode agents in ~/.config/opencode/oh-my-opencode.json:
You must configure ALL agents you want to use with Kimi:
{
"google_auth": false,
"ralph_loop": {
"enabled": true,
"default_max_iterations": 100
},
"agents": {
"sisyphus": { "model": "anthropic/kimi-for-coding" },
"prometheus": { "model": "anthropic/kimi-for-coding" },
"oracle": { "model": "anthropic/kimi-for-coding" },
"librarian": { "model": "anthropic/kimi-for-coding" },
"explore": { "model": "anthropic/kimi-for-coding" },
"frontend-ui-ux-engineer": { "model": "anthropic/kimi-for-coding" },
"document-writer": { "model": "anthropic/kimi-for-coding" },
"multimodal-looker": { "model": "anthropic/kimi-for-coding" },
"atlas": { "model": "anthropic/kimi-for-coding" }
}
}Note: If you get "model is not valid" errors, make sure the agent is configured in oh-my-opencode.json.
4. Add your Kimi API keys:
opencode-kimi add-key sk-kimi-your-key-here "My Account"5. Verify installation:
opencode-kimi list-keysWhat the plugin does automatically:
- Sets
ANTHROPIC_BASE_URLto Kimi's API endpoint - Intercepts fetch requests to
api.kimi.com - Rotates API keys based on health scores
- Shows toast notifications for key rotation
Models
Available Model
The Kimi Coding API provides a single flagship model:
| Model ID | Name | Context | Output |
| ----------------- | --------- | ------- | ------ |
| kimi-for-coding | Kimi K2.5 | 262,144 | 32,768 |
Use it as: anthropic/kimi-for-coding
Add this to your ~/.config/opencode/opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["file:///Users/YOUR_USERNAME/.config/opencode/plugins/kimi-rotator.js"],
"provider": {
"anthropic": {
"name": "Anthropic",
"models": {
"kimi-for-coding": {
"name": "Kimi K2.5 (via Kimi API)",
"attachment": true,
"limit": {
"context": 262144,
"output": 32768
},
"modalities": {
"input": ["text", "image", "video", "pdf"],
"output": ["text"]
}
}
}
}
}
}Usage
Add API Keys
# Add a key with optional name
opencode-kimi add-key sk-kimi-your-key-here "My Account 1"
opencode-kimi add-key sk-kimi-another-key "My Account 2"List All Keys
opencode-kimi list-keysOutput:
Kimi API Keys (2 total, strategy: health-based):
● [0] My Account 1
Key: sk-kim...yDigS
Health: ██████████ 100%
Requests: 45/50 successful
Status: ✓ Active
○ [1] My Account 2
Key: sk-kim...xxxxx
Health: ████████░░ 80%
Requests: 20/25 successful
Status: ✓ ActiveRemove a Key
opencode-kimi remove-key 1Manually Rotate
opencode-kimi rotateChange Rotation Strategy
# Round-robin: cycle through keys sequentially
opencode-kimi set-strategy round-robin
# Health-based: smart selection based on health scores (default)
opencode-kimi set-strategy health-based
# Sticky: stay on one key until rate limited
opencode-kimi set-strategy stickyView Usage Statistics
opencode-kimi statsOutput:
📊 Usage Statistics
[0] My Account 1
Total Requests: 1425
Successful: 1227
Failed: 198
Success Rate: 86.1%
Avg Response Time: 245ms
Requests Today: 12
Requests Last 7 Days: 89
[1] My Account 2
Total Requests: 811
Successful: 793
Failed: 18
Success Rate: 97.8%
Avg Response Time: 198ms
Requests Today: 5
Requests Last 7 Days: 42
──────────────────────────────────────────────────
📈 Aggregate Statistics
Total Requests (All Keys): 2236
Total Successful: 2020
Overall Success Rate: 90.3%
Overall Avg Response Time: 221msHealth Auto-Refresh
Automatically restore health scores for rate-limited keys after a cooldown period.
# Check current auto-refresh settings
opencode-kimi list-keys
# Enable/disable auto-refresh (default: enabled)
opencode-kimi set-auto-refresh true
opencode-kimi set-auto-refresh false
# Set cooldown period in minutes (default: 30, range: 1-1440)
opencode-kimi set-cooldown 30
opencode-kimi set-cooldown 60 # 1 hour
opencode-kimi set-cooldown 180 # 3 hours
# Manually trigger health refresh
opencode-kimi refresh-healthHow It Works
Health Score System
Each API key has a health score (0-100):
- Initial: 100
- Success: +2 points
- Rate Limited (HTTP 429): -15 points
- Billing Limit Reached: -30 points + 24-hour cooldown
- Failure: -20 points
Keys with health score < 30 are temporarily skipped.
Rate Limit Handling
When a key is rate limited (HTTP 429):
- Health score decreases by 15 points
- Key is marked as rate limited with reset time from
retry-afterheader - Next request automatically uses next available key
- Once reset time passes, key becomes available again
Billing Cycle Limit Handling
When a key hits the billing cycle usage limit ("You've reached your usage limit for this billing cycle"):
- Health score decreases by 30 points
- Key is put on a 24-hour cooldown (until midnight of the next day)
- Next request automatically uses next available key
- A toast notification shows how many hours until the key is available
- The key won't be retried until the cooldown expires
Data Storage
Keys are stored in ~/.config/opencode/kimi-accounts.json:
{
"version": 1,
"accounts": [
{
"key": "sk-kimi-xxx",
"name": "My Account",
"addedAt": 1234567890,
"lastUsed": 1234567890,
"rateLimitResetTime": 0,
"billingLimitResetTime": 0,
"healthScore": 100,
"consecutiveFailures": 0,
"totalRequests": 50,
"successfulRequests": 45,
"responseTimes": [245, 198, 210],
"dailyRequests": {
"2026-01-31": 12,
"2026-02-01": 5
}
}
],
"activeIndex": 0,
"rotationStrategy": "health-based",
"autoRefreshHealth": true,
"healthRefreshCooldownMinutes": 30
}Account Tracking
Each account tracks additional metrics for health-based rotation:
- responseTimes — Array of the last 100 response times (in milliseconds)
- dailyRequests — Record of request counts by date (YYYY-MM-DD format)
Health Auto-Refresh Settings
- autoRefreshHealth — Whether to automatically refresh health scores after cooldown (default:
true) - healthRefreshCooldownMinutes — Minutes to wait before health can be refreshed (default:
30, range: 1-1440)
When enabled, keys that were rate-limited will have their health score gradually restored (+10 points) after the cooldown period passes, making them available for rotation again.
Export/Import Keys
Backup and migrate your API keys between machines using encrypted files.
# Export all keys to an encrypted file
opencode-kimi export-keys
opencode-kimi export-keys my-backup.json.enc
# Import keys from an encrypted file
opencode-kimi import-keys my-backup.json.encFeatures:
- AES-256-GCM encryption with password protection
- Exports all keys, settings, and statistics
- Duplicate keys are skipped during import
- Rotation strategy and auto-refresh settings are preserved
Configuration
Configuration Path (All Platforms)
OpenCode uses ~/.config/opencode/ on all platforms including Windows.
| File | Path |
| ----------- | --------------------------------------- |
| Main config | ~/.config/opencode/opencode.json |
| Accounts | ~/.config/opencode/kimi-accounts.json |
Windows users:
~resolves to your user home directory (e.g.,C:\Users\YourName). Do NOT use%APPDATA%.
In Oh My OpenCode
To use Kimi models with Oh My OpenCode agents, update ~/.config/opencode/oh-my-opencode.json:
{
"google_auth": false,
"ralph_loop": {
"enabled": true,
"default_max_iterations": 100
},
"agents": {
"sisyphus": { "model": "anthropic/kimi-for-coding" },
"prometheus": { "model": "anthropic/kimi-for-coding" },
"oracle": { "model": "anthropic/kimi-for-coding" },
"librarian": { "model": "anthropic/kimi-for-coding" },
"explore": { "model": "anthropic/kimi-for-coding" },
"frontend-ui-ux-engineer": { "model": "anthropic/kimi-for-coding" },
"document-writer": { "model": "anthropic/kimi-for-coding" },
"multimodal-looker": { "model": "anthropic/kimi-for-coding" },
"atlas": { "model": "anthropic/kimi-for-coding" }
}
}Troubleshooting
"No Kimi API keys configured"
Run:
opencode-kimi add-key your-api-keyAll keys rate limited
The plugin will wait for the soonest available key. You can:
- Wait for rate limits to reset
- Add more API keys
- Check status with
opencode-kimi list-keys
Plugin not loading
- Ensure plugin is installed: Check
~/.config/opencode/opencode.jsonhas"plugin": ["opencode-kimi-rotator@latest"] - Verify the plugin package is installed:
npm list -g opencode-kimi-rotator - Check OpenCode logs for errors
Reset Everything
If you need to start fresh:
rm ~/.config/opencode/kimi-accounts.json
opencode-kimi add-key your-new-api-keyPlugin Compatibility
opencode-antigravity-auth
Both plugins can work together. List them in your preferred order:
{
"plugin": ["opencode-kimi-rotator@latest", "opencode-antigravity-auth@latest"]
}oh-my-opencode
Configure agent models in oh-my-opencode.json:
{
"google_auth": false,
"agents": {
"sisyphus": { "model": "anthropic/kimi-for-coding" },
"oracle": { "model": "anthropic/kimi-for-coding" },
"librarian": { "model": "anthropic/kimi-for-coding" },
"atlas": { "model": "anthropic/kimi-for-coding" }
}
}Automatic Installation Script
For automated setup, you can use this one-liner:
curl -fsSL https://raw.githubusercontent.com/deyndev/opencode-kimi-rotator/main/scripts/install.sh | bashOr for Windows (PowerShell):
irm https://raw.githubusercontent.com/deyndev/opencode-kimi-rotator/main/scripts/install.ps1 | iexDevelopment
Local Development Setup
- Clone the repository:
git clone https://github.com/deyndev/opencode-kimi-rotator.git
cd opencode-kimi-rotator- Install dependencies and build:
npm install
npm run build- Link for local testing:
npm link- Add to your OpenCode config:
{
"plugin": ["opencode-kimi-rotator"]
}Public API
KimiAccountManager
Main class for managing Kimi API key rotation.
Methods
markAccountSuccess(index, responseTime?, date?)
Marks an account as successfully used and updates health metrics.
async markAccountSuccess(
index: number,
responseTime?: number,
date?: string
): Promise<void>- index — Account index in the accounts array
- responseTime — Optional response time in milliseconds (tracked in rolling window of 100)
- date — Optional date string (YYYY-MM-DD) for daily request tracking
setAutoRefreshHealth(enabled)
Enables or disables automatic health score refresh.
async setAutoRefreshHealth(enabled: boolean): Promise<void>setHealthRefreshCooldown(minutes)
Sets the cooldown period for health refresh.
async setHealthRefreshCooldown(minutes: number): Promise<void>- minutes — Cooldown duration (1-1440, default: 30)
- Throws — Error if minutes is outside valid range
refreshHealthScores()
Manually triggers health score refresh for eligible accounts.
async refreshHealthScores(): Promise<{
refreshed: number;
details: string[];
}>Returns the number of accounts refreshed and detailed change log.
KimiStorage
Handles persistent storage of account configuration with file locking.
Constructor
constructor();Creates a new storage instance. The config directory is automatically set to ~/.config/opencode/.
Methods
init()
Initializes the storage directory and files.
async init(): Promise<void>Creates the config directory if it doesn't exist and initializes an empty accounts file.
loadConfig()
Loads and validates the accounts configuration.
async loadConfig(): Promise<KimiAccountsConfig>- Returns — Parsed and validated configuration
- Throws — Error if file cannot be read or parsed
saveConfig(config)
Saves the configuration to disk with file locking.
async saveConfig(config: KimiAccountsConfig): Promise<void>- config — Configuration object to save
- Throws — Error if validation fails or file cannot be written
addAccount(key, name?)
Adds a new API key account.
async addAccount(key: string, name?: string): Promise<KimiAccount>- key — The API key to store
- name — Optional display name for the account
- Returns — The created account object
- Throws — Error if the key already exists
removeAccount(index)
Removes an account by index.
async removeAccount(index: number): Promise<void>- index — Account index to remove
- Throws — Error if index is invalid
listAccounts()
Returns all stored accounts.
async listAccounts(): Promise<KimiAccount[]>getActiveAccount()
Returns the currently active account.
async getActiveAccount(): Promise<KimiAccount | null>- Returns — The active account or
nullif no accounts exist
setActiveIndex(index)
Sets the active account index.
async setActiveIndex(index: number): Promise<void>- index — Account index to set as active
- Throws — Error if index is invalid
getActiveIndex()
Returns the current active account index.
async getActiveIndex(): Promise<number>- Returns — The current active index from the configuration
getAndIncrementActiveIndex(availableIndices)
Atomically gets the current active index and sets the next one for round-robin rotation. This ensures proper serialization of rotation operations.
async getAndIncrementActiveIndex(availableIndices: number[]): Promise<number>- availableIndices — Array of available account indices to rotate through
- Returns — The selected next index (guaranteed to be unique per call)
- Throws — Error if no available indices are provided
atomicSetActiveIndex(preferredIndex)
Atomically sets the active index to a specific value. Use this for sticky and health-based rotation to claim an account.
async atomicSetActiveIndex(preferredIndex: number): Promise<number>- preferredIndex — The desired index to set
- Returns — The actual index that was set (may differ if validation fails)
updateAccount(index, updates)
Updates specific fields of an account.
async updateAccount(index: number, updates: Partial<KimiAccount>): Promise<void>- index — Account index to update
- updates — Partial account object with fields to update
- Throws — Error if index is invalid
Schemas
KimiAccountSchema
Zod schema for validating Kimi account objects:
{
key: string, // API key (required)
name: string, // Optional account name
addedAt: number, // Timestamp when added
lastUsed: number, // Timestamp of last use
rateLimitResetTime: number, // Default: 0
healthScore: number, // 0-100, default: 100
consecutiveFailures: number, // Default: 0
totalRequests: number, // Default: 0
successfulRequests: number, // Default: 0
responseTimes: number[], // Array of response times (ms)
dailyRequests: Record<string, number> // Requests per day
}KimiAccountsConfigSchema
Zod schema for the accounts configuration:
{
version: number, // Default: 1
accounts: KimiAccount[], // Array of accounts
activeIndex: number, // Default: 0
rotationStrategy: 'round-robin' | 'health-based' | 'sticky',
autoRefreshHealth: boolean, // Default: true
healthRefreshCooldownMinutes: number // Default: 30, range: 1-1440
}Types
KimiAccount— Inferred type fromKimiAccountSchemaKimiAccountsConfig— Inferred type fromKimiAccountsConfigSchema
Constants
DEFAULT_ACCOUNT
Default values for new accounts (excludes key, addedAt, lastUsed):
{
rateLimitResetTime: 0,
healthScore: 100,
consecutiveFailures: 0,
totalRequests: 0,
successfulRequests: 0,
responseTimes: [],
dailyRequests: {}
}DEFAULT_CONFIG
Default configuration values (excludes accounts):
{
version: 1,
activeIndex: 0,
rotationStrategy: 'health-based',
autoRefreshHealth: true,
healthRefreshCooldownMinutes: 30
}License
MIT License. See LICENSE for details.
Intended Use
- Personal / internal development only
- Respect internal quotas and data handling policies
- Not for production services or bypassing intended limits
Warning
By using this plugin, you acknowledge:
- Terms of Service risk — This approach may violate ToS of AI model providers
- Account risk — Providers may suspend or ban accounts
- No guarantees — APIs may change without notice
- Assumption of risk — You assume all legal, financial, and technical risks
Disclaimer
- Not affiliated with Moonshot AI. This is an independent open-source project.
- "Kimi", "Moonshot", and "Moonshot AI" are trademarks of Moonshot AI.
Contributors
Thanks to all the people who already contributed!
