Skip to content

Repository files navigation

opencode-key-rotator

npm version npm downloads CI code style: prettier License: MIT

OpenCode v2 plugin that automatically rotates provider API keys on rate limits and quota errors.

Automatically swaps to the next saved key when OpenCode encounters rate limits (429), quota exhaustion, or resource errors during sessions.

Features

  • Automatic rotation — detects rate-limit and quota errors and swaps to the next available key on retry
  • OpenCode v2 plugin — subscribes to public session events with one native v2 entrypoint
  • Persistent storage — keys and rotation logs stored in the XDG data directory
  • Configurable — customize rotation patterns via a sidecar config
  • Secure — transactional SQLite writes, restrictive permissions, and credential log sanitization

Installation

npx -y @dmmop/opencode-key-rotator init

Or install it globally:

npm install -g @dmmop/opencode-key-rotator
opencode-key-rotator init

Runtime compatibility

OpenCode runs the plugin with Bun and does not need additional flags. Node.js 22.5 or newer is also supported. In Node.js 22.5 through 22.12, node:sqlite is experimental: the installed opencode-key-rotator CLI enables --experimental-sqlite through its shebang, while direct package imports require:

NODE_OPTIONS=--experimental-sqlite node your-script.mjs

Node.js 22.13 and newer do not require this option.

Setup

Automatic (recommended)

Run the init command to register both OpenCode V2 entrypoints and create a default sidecar config:

npx -y @dmmop/opencode-key-rotator init

Manual

The server plugin and local TUI plugin use separate OpenCode V2 configuration files. Add both entries, then restart OpenCode:

opencode.json:

{
  "plugins": ["opencode-key-rotator"],
}

cli.json:

{
  "plugins": ["opencode-key-rotator/tui"],
}

init creates or updates ~/.config/opencode/opencode.json, ~/.config/opencode/cli.json, and ~/.config/opencode/opencode-key-rotator.json idempotently. Use --config-dir to target another OpenCode config directory. A direct path such as ./dist/tui.js is only needed when developing the plugin locally.

Uninstall

npx -y @dmmop/opencode-key-rotator uninstall

Saved keys and rotation logs are preserved on removal.

CLI

opencode-key-rotator init [--config-dir <dir>]
opencode-key-rotator uninstall [--config-dir <dir>]
opencode-key-rotator switch [--provider <id>] [--alias <alias>] [--data-dir <dir>]
opencode-key-rotator manage [--provider <id>] [--data-dir <dir>]
opencode-key-rotator status [--provider <id>] [--data-dir <dir>]

Key management

Use opencode-key-rotator switch for an interactive provider and alias selector. Pass --provider and --alias to use it non-interactively.

Use opencode-key-rotator manage for an interactive local workflow that saves the current credential, switches aliases, renames aliases, and deletes inactive aliases. It does not use the agent.

Use opencode-key-rotator status to list aliases, synchronization health, and the latest automatic rotation recorded in rotation.log.jsonl.

The server only translates OpenCode events. Rotation policy, cooldowns, switching, and automatic rotation logs live in rotation.ts, while SQLite CRUD lives in key-store.ts; the CLI and TUI adapter call the same core operations.

The ./tui adapter registers /key-save, /key-switch, and /key-status. It contains only TUI registration and rendering, and calls the same core operations.

Configuration

Create a sidecar config file at ~/.config/opencode/opencode-key-rotator.json:

{
  "rotation": {
    "enabled": true,
    "patterns": ["\\b429\\b", "rate\\s*limit", "quota", "resource exhausted", "usage limit", "insufficient quota"]
  }
}

The config file supports JSONC (comments and trailing commas). Resolution order:

  1. ${configDir}/opencode-key-rotator.json
  2. Built-in defaults

How rotation works

  1. The plugin handles session.retry.scheduled events and evaluates every retry whose status is 429 or whose message matches the configured patterns.
  2. session.error is a fallback and rotates on HTTP 429 or matching messages.
  3. The provider comes from the event payload or the session model.
  4. If at least two keys are saved for the provider, the plugin switches to the next alias in a round-robin cycle.
  5. If a rotated key fails on the next attempt, that alias enters a 2-minute cooldown and is skipped during subsequent rotations.
  6. Before switching, the current credentials are saved under the previous alias.
  7. Every decision is recorded in ~/.local/share/opencode/keys/rotation.log.jsonl.

Data layout

~/.local/share/opencode/
  opencode-next.db                 # OpenCode credentials plus plugin alias metadata
  keys/
    rotation.log.jsonl             # Rotation decisions (JSON Lines)

Troubleshooting

Symptom Cause Fix
Provider unknown The v2 event did not expose a provider ID Check the provider event data
No fallback key Only one key is saved for the provider Save another alias
All keys cooling down All saved aliases are in cooldown after failed attempts Wait 2 minutes or save additional aliases

Development

npm install
npm run typecheck
npm run build
npm test
npm run format

Releasing

A maintainer can trigger a fully automated release from GitHub Actions:

  1. Go to ActionsReleaseRun workflow
  2. Choose patch, minor, or major
  3. The workflow will:
    • Run the full test suite
    • Bump the version in package.json
    • Create and push a Git tag
    • Create a GitHub Release with auto-generated notes
    • Publish the package to npm

License

MIT

About

Reactive OpenCode plugin that automatically rotates provider API keys on rate limits and quota errors, with built-in TUI key management

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages