{"id":50865300,"url":"https://github.com/joaogsleite/opencode-provider-rotator","last_synced_at":"2026-06-15T00:32:06.266Z","repository":{"id":360730257,"uuid":"1251394229","full_name":"joaogsleite/opencode-provider-rotator","owner":"joaogsleite","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-27T16:00:40.000Z","size":4,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-27T17:25:26.462Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/joaogsleite.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-27T14:32:49.000Z","updated_at":"2026-05-27T16:00:52.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/joaogsleite/opencode-provider-rotator","commit_stats":null,"previous_names":["joaogsleite/opencode-provider-rotator"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/joaogsleite/opencode-provider-rotator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joaogsleite%2Fopencode-provider-rotator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joaogsleite%2Fopencode-provider-rotator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joaogsleite%2Fopencode-provider-rotator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joaogsleite%2Fopencode-provider-rotator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joaogsleite","download_url":"https://codeload.github.com/joaogsleite/opencode-provider-rotator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joaogsleite%2Fopencode-provider-rotator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34343312,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-14T02:00:07.365Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-15T00:32:05.318Z","updated_at":"2026-06-15T00:32:06.251Z","avatar_url":"https://github.com/joaogsleite.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Opencode Provider Rotator\n\nGlobal opencode plugin that rotates across multiple OpenRouter and Google Gemini API keys. When a provider returns a retryable limit or outage response, the plugin temporarily blocks that key and retries the same request with the next configured key.\n\n## Global Setup\n\nInstall the plugin in your global opencode config directory:\n\n```sh\nmkdir -p ~/.config/opencode/plugins\ncp provider-rotator.ts ~/.config/opencode/plugins/provider-rotator.ts\n```\n\nThen add your provider configuration to `~/.config/opencode/opencode.jsonc`.\n\nFor OpenRouter:\n\n```jsonc\n{\n  \"$schema\": \"https://opencode.ai/config.json\",\n  \"provider\": {\n    \"openrouter\": {\n      \"options\": {\n        \"rotatorKeys\": [\n          \"your-first-openrouter-key\",\n          \"your-second-openrouter-key\",\n        ],\n        \"apiKey\": \"opencode-provider-rotator\",\n      },\n    },\n  },\n}\n```\n\nYou can also keep keys out of the config file and read them from an environment variable:\n\n```jsonc\n{\n  \"$schema\": \"https://opencode.ai/config.json\",\n  \"provider\": {\n    \"openrouter\": {\n      \"options\": {\n        \"rotatorKeysEnv\": \"OPENROUTER_API_KEYS\",\n        \"apiKey\": \"opencode-provider-rotator\",\n      },\n    },\n  },\n}\n```\n\nThen start opencode with:\n\n```sh\nexport OPENROUTER_API_KEYS=\"your-first-openrouter-key,your-second-openrouter-key\"\nopencode\n```\n\nUse OpenRouter models normally, for example `openrouter/anthropic/claude-sonnet-4.5`.\n\nFor Google Gemini:\n\n```jsonc\n{\n  \"$schema\": \"https://opencode.ai/config.json\",\n  \"provider\": {\n    \"google\": {\n      \"options\": {\n        \"rotatorKeys\": [\n          \"your-first-gemini-key\",\n          \"your-second-gemini-key\",\n        ],\n        \"apiKey\": \"opencode-provider-rotator\",\n      },\n    },\n  },\n}\n```\n\nYou can also keep Gemini keys out of the config file and read them from an environment variable:\n\n```jsonc\n{\n  \"$schema\": \"https://opencode.ai/config.json\",\n  \"provider\": {\n    \"google\": {\n      \"options\": {\n        \"rotatorKeysEnv\": \"GEMINI_API_KEYS\",\n        \"apiKey\": \"opencode-provider-rotator\",\n      },\n    },\n  },\n}\n```\n\nThen start opencode with:\n\n```sh\nexport GEMINI_API_KEYS=\"your-first-gemini-key,your-second-gemini-key\"\nopencode\n```\n\nUse Google Gemini models normally, for example `google/gemini-2.5-pro`.\n\n## Configuration\n\nopencode auto-loads `~/.config/opencode/plugins/provider-rotator.ts` at startup. The global `opencode.jsonc` enables the provider with a placeholder key; the plugin replaces the request auth header with one of your real keys.\n\nPlugin options:\n\n- `rotatorKeys`: array of provider API keys, or a comma/newline-separated string.\n- `rotatorKeysEnv`: optional environment variable containing additional keys. Defaults to `OPENROUTER_API_KEYS` for OpenRouter and `GEMINI_API_KEYS` for Google Gemini.\n- `rotatorBlockedForMs`: how long to skip a key after a retryable failure. Defaults to one hour.\n- `rotatorRetryStatuses`: HTTP statuses that trigger rotation. OpenRouter defaults to `402`, `408`, `409`, `425`, `429`, `500`, `502`, `503`, and `504`. Google Gemini defaults to `408`, `409`, `425`, `429`, `500`, `502`, `503`, and `504`.\n- `rotatorRetryErrorCodes`: provider error codes that trigger rotation when present. OpenRouter defaults to `insufficient_credits`, `rate_limit_exceeded`, `quota_exceeded`, and `context_length_exceeded`. Google Gemini defaults to `ABORTED`, `DEADLINE_EXCEEDED`, `INTERNAL`, `RESOURCE_EXHAUSTED`, and `UNAVAILABLE`.\n\nThis plugin supports the Google Generative AI provider used by `google/*` models. It does not rotate Google Vertex AI credentials for `google-vertex/*` models.\n\nRestart opencode after changing the plugin or config; opencode loads plugins only at startup.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoaogsleite%2Fopencode-provider-rotator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoaogsleite%2Fopencode-provider-rotator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoaogsleite%2Fopencode-provider-rotator/lists"}