oc-plugin-litellm-budget
v0.10.2
Published
Display LiteLLM budget usage in OpenCode TUI sidebar and footer
Maintainers
Readme
oc-plugin-litellm-budget
OpenCode TUI plugin that displays LiteLLM budget usage in the sidebar and home footer.
What it shows
Sidebar (during chat sessions, wide terminals):
Quota ░░░░░░░░░░ 97% libre Dia 4/7 | Reset 4d 20 rpm | 5M tpmFooter (home screen):
Quota: 97% libre [░░░░░░░░░░] Dia 4/7 | Reset 4d | 20 rpm | 5M tpm
Color: green (<60% used), yellow (60-80%), red (>80%).
What it measures
The percentage reflects your key's individual spend against your budget max. Limits are resolved with the same precedence that LiteLLM uses:
- Key-level limits win — if your key has explicit
rpm_limit,tpm_limit, ormax_budget, those are shown. - Global budget as fallback — if a field is not set on the key, the plugin looks up the global budget
(
budget_high/budget_low) that your key belongs to (viabudget_id) and uses its limits instead.
"Dia X/Y" shows which day of the budget cycle you're in, so you can gauge your burn rate.
Architecture
opencode TUI ---> LiteLLM /key/info ---> PostgreSQL
(bun) \--> LiteLLM /budget/list (LiteLLM_VerificationToken
(REST API) + LiteLLM_BudgetTable)The plugin:
- Reads the API key from env vars or
~/.config/opencode/opencode.json - Polls
GET /key/infoandGET /budget/listevery 60 seconds (in parallel) - Resolves limits: key-level wins; falls back to the global budget matched by
budget_id - Calculates used % from
info.spend / resolved_max_budget - Calculates day-in-period from
budget_reset_atandbudget_duration - Renders via solid-js into OpenCode's
sidebar_contentandhome_footerslots
API key resolution (fallback chain)
LITELLM_API_KEYenv varOPENAI_API_KEYenv varBINETZ_REMOTE_CONFIG_TOKENenv var~/.config/opencode/opencode.json->provider.binetz.options.apiKey~/.config/opencode/opencode.jsonc(same path, with JSONC comment stripping)
Base URL resolution
LITELLM_BASE_URLenv varOPENAI_BASE_URLenv var- Default:
https://litellm.binetz.com(if a key was found)
Files
| File | Purpose |
|------|---------|
| tui.tsx | Main plugin -- Sidebar and FooterQuota components, fetchQuota, readKeyFromConfig |
| server.ts | Server plugin no-op (required by OpenCode plugin structure) |
| package.json | Exports ./server and ./tui |
Installation
Via well-known (automatic for Binetz users)
The plugin is distributed via https://mcp.binetz.com/.well-known/opencode in the plugin array. New OpenCode installs pick it up automatically.
Manual (opencode.json)
Add to the plugin array in ~/.config/opencode/opencode.json:
{
"plugin": [
"[email protected]"
]
}Manual (tui.json -- required for TUI features)
The well-known only distributes server plugins. For the TUI sidebar/footer, add to ~/.config/opencode/tui.json:
{
"plugin": [
"[email protected]"
]
}Both files need the plugin for full functionality:
opencode.json-> server plugin loads (no-op currently, but required for well-known distribution)tui.json-> TUI plugin loads (sidebar + footer)
Updating
1. Edit tui.tsx
Make changes in /home/dev/mcp/opencode-plugins/oc-plugin-litellm-budget/tui.tsx.
2. Bump version
Edit package.json, increment version.
3. Publish to npm
cd /home/dev/mcp/opencode-plugins/oc-plugin-litellm-budget
echo "//registry.npmjs.org/:_authToken=<NPM_TOKEN>" > /tmp/.npmrc-budget
npm publish --access public --userconfig /tmp/.npmrc-budget
rm /tmp/.npmrc-budgetnpm user: diegolabonia. The granular token is in Passbolt.
4. Update well-known
Edit /home/dev/mcp/onboarding/well-known.json -- change version in the plugin array.
5. Deploy well-known to production
scp /home/dev/mcp/onboarding/well-known.json [email protected]:/storage/docker/mcp/onboarding/well-known.json
ssh [email protected] "docker cp /storage/docker/mcp/onboarding/well-known.json mcp-binetz:/app/onboarding/well-known.json && docker compose -f /storage/docker/mcp/docker-compose.yml restart mcp"6. Update local configs
Update version in:
~/.config/opencode/opencode.json(plugin array)~/.config/opencode/tui.json(plugin array)
7. Restart OpenCode
OpenCode downloads plugins on startup. Just restart to pick up the new version.
8. Roll out to team
Users get the new version automatically from well-known on their next OpenCode restart.
For tui.json, they need to update manually or via the onboarding script.
Maintenance
If LiteLLM budget structure changes
The plugin reads from info.litellm_budget_table which contains:
max_budget: number (USD)budget_duration: string (e.g. "7d")budget_reset_at: ISO8601 timestamp
If LiteLLM changes these field names or the /key/info response structure, update fetchQuota() in tui.tsx.
If budget period changes from weekly to monthly
Update the fallback in parseDurationDays() (currently defaults to 7).
Update the "Dia X/Y" display text if needed.
If the plugin doesn't show data
Check in order:
- API key is resolvable (env var or opencode.json)
- LiteLLM is reachable from the user's machine (
curl https://litellm.binetz.com/key/info -H 'Authorization: Bearer <key>') - The key has a budget assigned (
litellm_budget_tablein the response is not empty) - The plugin is in both
opencode.jsonANDtui.json
Known limitations
- Shows per-key spend, not total budget spend across all users
- Only polls every 60s; changes in spend won't appear instantly
- Sidebar only visible in terminals >= ~140 columns during active chat sessions
- Windows: may have issues with Bun.file() paths if opencode config is in a non-standard location
Version history
| Version | Changes | |---------|---------| | 0.10.0 | Limit resolution: key-level limits win, fallback to global budget (budget_high/budget_low) via budget_id | | 0.9.3 | Internal refactor | | 0.6.0 | Added "Dia X/7" period context, parse budget_duration | | 0.5.0 | Read API key from opencode.json, no dollar amounts shown | | 0.4.0 | Sidebar + footer, rate limits display | | 0.3.0 | Initial npm publish |
