Skip to content

About

A TUI plugin for opencode providing budget and token information for the current user

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

228 Commits

Folders and files

Repository files navigation

GitHub Actions CI Status codecov Coveralls Known Vulnerabilities Socket Badge renovate npm downloads npm version npm license semver Conventional Commits code style: prettier github stars

opencode-requesty-plugin

An opencode TUI plugin that shows your Requesty.ai budget, current monthly spend, and per-model cost distribution right in the session prompt, in the session sidebar, plus a detail dialog via the /requesty slash command.

Requirements

Features

The plugin surfaces your Requesty.ai budget and usage in three places, each optimized for the space it occupies: a compact sidebar, a full detail dialog, and a minimal prompt-area readout.

Sidebar widget

Sidebar widget

The sidebar gives a quick, at-a-glance view of your current month's Requesty usage:

  • Monthly spend and monthly limit, pulled from GET /v1/manage/apikey/self
  • A color-coded progress bar that turns yellow/red at configurable thresholds
  • Projected month-end spend (~$X EOM), extrapolated with a weekday-aware run rate (see Month-end projection), with a pace marker: ↑ over pace, → on pace, ↓ under pace
  • Daily spend trend: today · daily average · 7-day average · 30-day average
  • Optional input/output token breakdown for each spend metric (sidebar.showTokens)
  • API key name in the header, linking to the Requesty analytics dashboard filtered by that key
  • Top models for the current month (up to sidebar.maxModels), each with spend, total tokens, and input (↑) / output (↓) breakdown; click the header to collapse or expand the list
  • Session cost for the current session: today's spend and spend since the session started (from the session's creation timestamp, falling back to a rolling 90-day window when unavailable), each with request count and token breakdown; click the header to collapse or expand (sidebar.showSessionInfo). Figures cover the root session including all its sub-agents, so viewing a sub-agent session shows its root's aggregate. Shows a "loading…" placeholder until the active session's data has been fetched, so it never displays an incorrect zero while loading. Revisiting a session whose figures were already loaded shows them immediately from a per-session cache.

You can disable the sidebar entirely with "sidebar": { "enabled": false }.

Prompt indicator

Prompt indicator

A compact readout on the right side of the session prompt shows:

  • Today's spend
  • Spend vs. limit with percentage and API key name, colored by the same thresholds as the sidebar
  • Optional total session spend (S $X, including sub-agents) to the left of today's spend when prompt.showSessionInfo is enabled
  • Optional month-end projection (~$X EOM ↑) when prompt.monthlyProjection is enabled

Disable the readout with "prompt": { "budgetIndicator": false }.

Detail dialog

Detail dialog

Open the dialog with /requesty from the command palette for the full breakdown:

  • KPI row: spent, limit, remaining, End of Month projection (labelled with the projection method actually used) with a colored pace arrow, and last month's spend with a colored trend chevron
  • Budget Overview card: wide progress bar, budget-health badge, days-to-exhaustion estimate based on your 7-day average, and today/daily avg/7d/30d averages
  • Model Breakdown (Current Month) card: per-model table with spend, share of total spend, tokens, request count, and output/input ratio

The dialog keeps its footer visible while the content scrolls, and lays out the headline budget and trend metrics separately to keep them readable in narrower terminals.

Data comes from the Requesty Management API (apikey/self + apikey/self/usage grouped by model_used, current calendar month).

Installation

Choose the instructions for your OpenCode major version. The same npm package supports both, but OpenCode 1.x and 2.x use different plugin installers and configuration files.

OpenCode 1.x

Install globally:

opencode plugin -g @christiangalsterer/opencode-requesty-plugin

Or install into the current project:

opencode plugin @christiangalsterer/opencode-requesty-plugin

OpenCode 1.x stores TUI plugin configuration in tui.json. The install command adds the package there. Plugin options can be set in the project .opencode/tui.json or global ~/.config/opencode/tui.json.

OpenCode 2.x

Install the package globally with the v2 plugin command:

opencode plugin add @christiangalsterer/opencode-requesty-plugin

For a project-specific installation, add the package to that project's opencode.json plugins array. V2 does not use the v1 opencode plugin <package> command to edit project configuration.

{
  "$schema": "https://opencode.ai/config.json",
  "plugins": [
    {
      "package": "@christiangalsterer/opencode-requesty-plugin",
      "options": {
        "refreshIntervalMs": 300000
      }
    }
  ]
}

Updating

For OpenCode 1.x, force the plugin installer to fetch the package again:

opencode plugin -f @christiangalsterer/opencode-requesty-plugin

For OpenCode 2.x, update global plugins with:

opencode plugin update @christiangalsterer/opencode-requesty-plugin

Project-configured v2 plugins use the version resolved from the plugins entry in opencode.json; update a pinned version there when needed.

OpenCode does not currently support plugin updates reliably. See OpenCode PRs #35777, #32822, and #37300. To force OpenCode to download the configured plugin versions, clear its plugin cache:

rm -rf ~/.cache/opencode/packages/@christiangalsterer/opencode-requesty-plugin*

Configuration

The plugin options are the same in both versions, but the files and JSON shapes differ:

  • OpenCode 1.x: plugin registration/options go in tui.json; the Requesty provider goes in opencode.json.
  • OpenCode 2.x: plugin registration/options and the Requesty provider both go in opencode.json.

Use the matching example below. Do not combine the v1 plugin/tuple shape with the v2 plugins/object shape.

OpenCode 1.x

For OpenCode 1.x, find the project configuration at .opencode/tui.json or the global configuration at ~/.config/opencode/tui.json.

{
  "$schema": "https://opencode.ai/tui.json",
  "plugin": [
    [
      "@christiangalsterer/opencode-requesty-plugin",
      {
        "refreshIntervalMs": 300000,
        "warningThreshold": 0.6,
        "errorThreshold": 0.85,
        "sidebar": {
          "enabled": true,
          "maxModels": 5,
          "showTokens": true,
          "order": 50
        }
      }
    ]
  ]
}

The Requesty provider is configured separately in the project or global opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "requesty": {
      "options": {
        "apiKey": "{env:REQUESTY_API_KEY}"
      }
    }
  }
}

OpenCode 2.x

OpenCode 2 uses plugins with an object containing package and options. Provider configuration uses the plural providers key and provider settings:

{
  "$schema": "https://opencode.ai/config.json",
  "plugins": [
    {
      "package": "@christiangalsterer/opencode-requesty-plugin",
      "options": {
        "refreshIntervalMs": 300000,
        "warningThreshold": 0.7,
        "errorThreshold": 0.9,
        "sidebar": {
          "enabled": true,
          "maxModels": 5,
          "showTokens": true,
          "showKeyName": true,
          "order": 50
        },
        "prompt": {
          "enabled": true,
          "budgetIndicator": true,
          "todaySpend": true,
          "dailyAvg": false,
          "7dAvg": false,
          "30dAvg": false,
          "showTokens": true,
          "showKeyName": true,
          "showSessionInfo": true,
          "monthlyProjection": true,
          "order": 50
        },
        "dialog": {
          "showKeyName": true
        }
      }
    }
  ],
  "providers": {
    "requesty": {
      "settings": {
        "apiKey": "{env:REQUESTY_API_KEY}",
        "baseURL": "https://api-v2.requesty.ai/v1"
      }
    }
  }
}

Restart OpenCode after changing configuration.

Configuration options

Option Type Default Description
refreshIntervalMs number 300000 (5 min) Periodic refresh interval (safety net)
warningThreshold number 0.7 (70%) Budget usage ratio at which the bar turns yellow (accepts 0–1 or 0–100)
errorThreshold number 0.9 (90%) Budget usage ratio at which the bar turns red (accepts 0–1 or 0–100)
projection.method string "weekday" How month-end spend is extrapolated: "weekday" (per-weekday profile from your usage history), "workdays" (Mon–Fri only), or "calendar" (every day weighs the same)
projection.historyDays number 28 Completed days of usage history sampled for the "weekday" method (7–84, whole days)
sidebar.enabled boolean true Show the sidebar widget
sidebar.maxModels number 5 Number of models shown in the compact sidebar list
sidebar.showTokens boolean true Show input/output token breakdown alongside spend in the sidebar averages block
sidebar.showKeyName boolean false Show the API key nickname in the sidebar header
sidebar.showSessionInfo boolean true Show the per-session cost collapsible section (today + since session start)
sidebar.order number 50 Slot order for the sidebar widget; lower numbers appear first
prompt.enabled boolean true Show the prompt widget
prompt.budgetIndicator boolean true Show spend/limit readout on the right side of the session prompt
prompt.todaySpend boolean true Show today's spend (T $X) in the session prompt averages block
prompt.dailyAvg boolean false Show the current month's daily average (D $X) in the prompt averages block
prompt."7dAvg" boolean false Show the 7-day average (7d $X) in the prompt averages block
prompt."30dAvg" boolean false Show the 30-day average (30d $X) in the prompt averages block
prompt.showTokens boolean true Show today's input/output token breakdown (↑X↓Y) next to today's spend in the session prompt
prompt.showKeyName boolean false Show the API key nickname in the session prompt readout
prompt.showSessionInfo boolean true Show total session spend (S $X, incl. sub-agents) left of today's spend in the prompt averages block
prompt.monthlyProjection boolean true Show a month-end projection (~$X EOM ↑) in the session prompt, red when the estimated spend exceeds the budget
prompt.order number 50 Slot order for the prompt indicator; lower numbers appear first
dialog.showKeyName boolean false Show the API key nickname in the detail dialog title

warningThreshold must be lower than errorThreshold; if the ordering is invalid, both fall back to the defaults (70%/90%). Values above 1 are treated as percents, e.g. 80 means 80%.

Using Requesty with multiple API keys

If you utilize different API keys for various projects, it is highly recommended to enable showKeyName in your configuration. This allows you to easily identify which Requesty API key is currently active in the sidebar, session prompt, and detail dialog.

Example for enabling key identification:

{
  "sidebar": { "showKeyName": true },
  "prompt": { "showKeyName": true },
  "dialog": { "showKeyName": true }
}

Complete OpenCode 1.x plugin options example

{
  "$schema": "https://opencode.ai/tui.json",
  "plugin": [
    [
      "@christiangalsterer/opencode-requesty-plugin",
      {
        "refreshIntervalMs": 300000,
        "warningThreshold": 0.7,
        "errorThreshold": 0.9,
        "sidebar": {
          "enabled": true,
          "maxModels": 5,
          "showTokens": true,
          "showKeyName": true,
          "order": 50
        },
        "prompt": {
          "enabled": true,
          "budgetIndicator": true,
          "todaySpend": true,
          "dailyAvg": false,
          "7dAvg": false,
          "30dAvg": false,
          "showTokens": true,
          "showKeyName": true,
          "showSessionInfo": true,
          "monthlyProjection": true,
          "order": 50
        },
        "dialog": {
          "showKeyName": true
        }
      }
    ]
  ]
}

Complete OpenCode 2.x configuration example

Place this in the project opencode.json (or opencode.jsonc). For global use, add the plugin to your global OpenCode configuration instead.

{
  "$schema": "https://opencode.ai/config.json",
  "plugins": [
    {
      "package": "@christiangalsterer/opencode-requesty-plugin",
      "options": {
        "refreshIntervalMs": 300000,
        "warningThreshold": 0.7,
        "errorThreshold": 0.9,
        "sidebar": {
          "enabled": true,
          "maxModels": 5,
          "showTokens": true,
          "showKeyName": true,
          "showSessionInfo": true
        },
        "prompt": {
          "enabled": true,
          "budgetIndicator": true,
          "todaySpend": true,
          "dailyAvg": false,
          "7dAvg": false,
          "30dAvg": false,
          "showTokens": true,
          "showKeyName": true,
          "showSessionInfo": true,
          "monthlyProjection": true
        },
        "dialog": {
          "showKeyName": true
        }
      }
    }
  ],
  "providers": {
    "requesty": {
      "settings": {
        "apiKey": "{env:REQUESTY_API_KEY}",
        "baseURL": "https://api-v2.requesty.ai/v1"
      }
    }
  }
}

Data is refreshed on startup, on a configurable periodic interval, when a new session is created, and when messages are updated.

Metrics

All amounts are in USD and dates are evaluated in UTC. The detail dialog's Updated: footer is shown in your local timezone.

  • Today — spend and tokens for the current calendar day.
  • Daily avg — current month's total spend and tokens divided by the number of days elapsed so far this month.
  • 7d avg — average spend and tokens over the previous 7 completed calendar days (excluding today). Days without usage count as $0 / 0 tokens. Uses a rolling window to ensure accuracy across month boundaries.
  • 30d avg — average spend and tokens over the previous 30 completed calendar days (excluding today). Days without usage count as $0 / 0 tokens. Uses a rolling window to ensure accuracy across month boundaries.
  • End of Month projection — current spend extrapolated to the end of the month, weighting the remaining days by how much you typically spend on each weekday. See Month-end projection.
  • Session cost — spend, request count, and tokens for the currently active opencode session: Today and Since . Figures cover the root session including all its sub-agents (viewing a sub-agent shows its root's aggregate). The window starts at the session's creation timestamp; if that is unavailable it falls back to the last 90 days. Attribution uses Requesty's extra.X-Session-Affinity metadata, so values are exact per session (not estimates). While a session's data is still loading the section shows a "…" placeholder rather than a misleading zero; a previously-loaded session is served from a per-session cache so its figures appear immediately on revisit.

Month-end projection

Coding usage is rarely spread evenly across the week, so a plain "spend so far ÷ days so far × days in month" run rate over-projects when the month started on a busy stretch and under-projects when it started on a quiet weekend. The projection therefore assigns every day of the month a weight and extrapolates over weights instead of days:

projection = spend so far ÷ (weight of days 1…today) × (weight of all days in the month)

Three methods are available via projection.method:

Method Weights Use when
"weekday" (default) Measured from your own usage: each weekday's average spend over the last projection.historyDays completed days You want the projection to learn your actual rhythm
"workdays" Mon–Fri count, Sat/Sun count as zero You only work weekdays and have no usable history yet
"calendar" Every day counts the same (the classic run rate) You want the simple, unweighted estimate

Details:

  • Weights are normalized to an average of 1, so a weight of 1 means "an average day" and the "calendar" method reduces exactly to the plain run rate.
  • The "weekday" method needs at least 7 sampled days carrying some spend; with a shorter or empty history it silently falls back to "calendar". The detail dialog's KPI label shows which method was actually used (End of Month (weekday profile), (workdays) or (calendar)).
  • Days with no usage count as $0, which is what makes a consistently quiet weekend measurable. Today is excluded from the history sample because its spend is still incomplete.
  • The pace marker (↑/→/↓) and the Budget Overview days-to-exhaustion estimate use the same weights, so a weekend no longer looks like "under pace" and an exhaustion date no longer counts days you never spend on.
  • Choosing projection.method: "weekday" with a historyDays above 30 widens the usage request window accordingly; it stays within a single API request.

API key detection

The plugin resolves credentials in this order: an explicit API key in a Requesty provider configuration, an environment variable declared by a matching Requesty provider, then REQUESTY_API_KEY from the plugin process environment. {env:VAR} values are interpolated. OpenCode 1.x uses provider.requesty.options.apiKey; OpenCode 2.x uses providers.requesty.settings.apiKey. Custom provider entries are supported when their baseURL points to a Requesty host.

{
  "provider": {
    "requesty": {
      "options": { "apiKey": "sk-..." }
    }
  }
}

OpenCode 2.x configuration uses providers and settings:

{
  "providers": {
    "requesty": {
      "settings": {
        "apiKey": "{env:REQUESTY_API_KEY}",
        "baseURL": "https://api-v2.requesty.ai/v1"
      }
    }
  }
}

Or via an environment variable:

{
  "provider": {
    "requesty": {
      "options": { "apiKey": "{env:REQUESTY_API_KEY}" }
    }
  }
}

If no key is found, the widget shows a short setup hint instead of failing.

Development

Local development install

Point at a local checkout instead:

{
  "$schema": "https://opencode.ai/tui.json",
  "plugin": [
    [
      "file:///absolute/path/to/opencode-requesty-plugin/dist/tui.js",
      {
        "sidebar": { "showKeyName": true },
        "prompt": { "showKeyName": true },
        "dialog": { "showKeyName": true }
      }
    ]
  ]
}
bun install
bun run format:fix
bun run typecheck
bun run test
bun run build

Test the local plugin in Docker

Build the version-specific image, then start its interactive Bash shell with the checked-out plugin mounted into the container. Each run script builds dist/tui.js first; no tarball or registry installation is needed.

OpenCode 1.x

bun run docker:build:v1
REQUESTY_API_KEY=your-requesty-api-key bun run docker:run:v1

OpenCode 2.x

bun run docker:build:v2
REQUESTY_API_KEY=your-requesty-api-key bun run docker:run:v2

Both containers start in Bash at /home/harness/workspace. For V1, the mounted .opencode/tui.json loads /home/harness/plugin/dist/tui.js; for V2, OpenCode discovers .opencode/plugins/requesty/tui.ts, whose adapter loads the same local build. Both containers mount ~/.config/opencode/opencode.json for provider settings.

The project is fully typed TypeScript (strict mode). Sources live in src/ (.ts/.tsx), tests in test/. The build pre-compiles the shared src/tui.tsx entrypoint and both lazy host adapters with OpenTUI's Solid Babel plugin (@opentui/solid/bun-plugin), then emits declarations via tsconfig.build.json. The entrypoint dynamically imports only the adapter selected by the host (tui for v1, setup for v2), so the unused host API is not loaded.

License

MIT

About

A TUI plugin for opencode providing budget and token information for the current user

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages