npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lnilluv/pi-opencode-go-rotation

v1.5.1

Published

Rotate between multiple OpenCode Go API keys with reactive 429, rate-limit, and watchdog stall detection

Readme

pi-opencode-go-rotation

Rotate between multiple OpenCode Go API keys. The extension checks OpenCode Go usage when a 429 response arrives, rotates around quota-blocked and cooling-down keys, and recovers silent stalls detected by the watchdog.

Install

pi install npm:@lnilluv/pi-opencode-go-rotation

Setup

Add your API keys:

/opencode add personal sk-xxxx
/opencode add work sk-yyyy
/opencode add backup sk-zzzz

The first key added becomes active immediately.

How it works

The extension sets the active key as a runtime override, which takes priority over OPENCODE_API_KEY environment variables and auth.json credentials.

The extension has three recovery paths:

  1. Usage-verified Go quota exhaustion: when OpenCode Go returns HTTP 429, the extension sends the active key only to https://opencode.ai/zen/go/v1/usage. If a usage window is rate-limited, the failed key is blocked until the latest reported reset and the next non-quota-blocked key is activated. Rotation prefers keys outside transient cooldown, but can clear a cooldown rather than keep using an exhausted key. Repeated failures try each configured key once. When every key is quota-blocked, rotation stops and reports the earliest reset instead of cycling.
  2. Transient limit errors: when the usage endpoint is unavailable, does not report a rate-limited window, or does not finish within 10 seconds, the extension preserves the existing transient 429 behavior. It aborts a timed-out usage request, marks the current key as on cooldown, switches to the next key that is not quota-blocked, and applies it via setRuntimeApiKey.
  3. Silent stalls: when an opencode-go provider request has no response or stream activity for the watchdog window, the extension rotates to an eligible key, aborts the hung turn, and rewrites the abort as a retryable timeout error.

This is still reactive: it does not poll usage or check limits before normal requests.

Fixed-window Go plan quota errors reported at message end follow the same rotation path. A parseable reset timestamp is authoritative; otherwise the configured cooldown duration is used as the block duration. A response-hook rotation is deduplicated so the matching message-end error cannot rotate twice.

Pi's built-in auto-retry picks up the new key on the next request.

Cooldowns default to 60 minutes. Quota blocks expire at their persisted deadline. Manual /opencode use <n> and /opencode next clear both restrictions on the selected key.

Usage commands use https://opencode.ai/zen/go/v1/usage and stop waiting after 10 seconds. A timeout reports Usage request timed out after 10s..

Commands

| Command | Description | |---------|-------------| | /opencode or /opencode status | Show all keys, active key marker, cooldown and quota-blocked status | | /opencode usage or /opencode quota | Fetch OpenCode Go usage for the active key without showing key material | | /opencode use <n> | Switch to key number n (1-based) and clear its cooldown and quota block | | /opencode next | Advance to the next configured key and clear its cooldown and quota block before activating it | | /opencode add <name> <key> | Add a new key | | /opencode rm <n> | Remove key number n | | /opencode reset | Clear all cooldowns and quota blocks | | /opencode cooldown <min> | Set or view cooldown duration in minutes | | /opencode events | Show recent watchdog timeout history (last 10) | | /opencode watchdog [status\|on\|off\|<seconds>] | Configure silent-stall detection |

Configuration

Keys are stored in ~/.pi/agent/opencode-keys.json with file permissions 0600. Status output shows key names only; it does not display key material.

{
  "keys": [
    { "name": "personal", "key": "sk-xxx" },
    { "name": "work", "key": "sk-yyy" }
  ],
  "activeKeyIndex": 0,
  "cooldownMinutes": 60,
  "watchdogEnabled": true,
  "watchdogIdleMs": 90000,
  "cooldowns": {},
  "quotaBlockedUntil": {}
}

Retry settings

Pair with pi's auto-retry for best results. In ~/.pi/agent/settings.json:

{
  "retry": {
    "enabled": true,
    "maxRetries": 3
  }
}

Set maxRetries to at least the number of keys so all keys get a chance before pi gives up.

Limitations

  • The watchdog is scoped to the opencode-go provider only. Other providers are not aborted or rotated.
  • A legitimate long-running request with no stream activity can be treated as stalled; tune with /opencode watchdog <seconds> or disable with /opencode watchdog off.
  • When all non-quota-blocked keys are transiently cooling down, the extension may clear the next eligible key's cooldown. It never automatically clears or force-selects a quota-blocked key.
  • When all keys are quota-blocked, automatic rotation stops on the current runtime key until a block expires or a manual command clears one.
  • Go plan usage limits are tied to the subscription workspace; multiple keys from one workspace should not be assumed to provide independent quota. See the OpenCode Go documentation.
  • Keys added via /opencode add are stored in plaintext. The config file is created and maintained with 0600 permissions.

License

MIT