# pi-minimax-usage

[![License: MIT](https://img.shields.io/badge/license-MIT-blue)](https://opensource.org/licenses/MIT)
[![Node: >=18](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](package.json)
[![pi extension](https://img.shields.io/badge/pi-extension-purple)](https://pi.dev)

[Pi](https://pi.dev) extension that shows real Minimax M3 token usage, cost, prompt-cache savings, and 5-hour / weekly subscription quota in the status line.

## What you see in the TUI

Two compact widgets in the status line:

| Widget | Example |
|--------|---------|
| `minimax` | `↑45.2k R1.2M (96%) $0.0834 ↓$0.0271` |
| `minimax-quota` | `5h:13% R25m  wk:2% R3d14h` |

`minimax` rolls up your **session** tokens, cost, cache hit rate, and what the cache saved you.
`minimax-quota` shows your **subscription** 5-hour and weekly windows.

When a window is fully used, the cell flips to `x` and the widget gets a `‼` prefix so the cap is visible at a glance:

| State | Renders |
|-------|---------|
| 5h window fully used | `‼5h:x R25m  wk:2% R3d14h` |
| Weekly fully used | `‼5h:13% R25m  wk:x R3d14h` |
| Both maxed | `‼5h:x R25m  wk:x R3d14h` |

Run `/minimax-usage` for the full breakdown (input, output, cache read/write, cost, savings, both quota windows with reset times).

## Why this extension exists

The Minimax provider in `models.json` declares `cost` as zeros for `cacheRead`, `cacheWrite`, and `output` tokens. Pi's standard `calculateCost()` reads from that model definition, so without this hook the cost shown in the status line is always `$0.00` for cached/uncached output. This extension rewrites the `usage.cost` field on Minimax messages with the real M3 pricing from the official docs.

The 5h and weekly windows are fetched from `GET /v1/token_plan/remains` and rendered in a single compact status cell. The 1-minute poll is light — one tiny JSON request — and only runs while a session is active.

## Install

```bash
# Option A: npm (once published)
pi install npm:pi-minimax-usage

# Option B: local clone
git clone https://github.com/MarcBaumholz/pi-minimax-usage.git
cd pi-minimax-usage
pi install .
```

## Setup

The extension needs a Minimax subscription key. It reads it from the first match of:

1. **`MINIMAX_API_KEY` env var** (recommended for CI/containers)
   ```bash
   export MINIMAX_API_KEY="sk-cp-..."
   ```
2. **`~/.pi/agent/auth.json`** under `providers.minimax.access` (Pi's standard auth store — populated by `/login minimax` if you have a provider that supports it)
3. **`~/.pi/agent/models.json`** under `providers.minimax.apiKey` (the local convention)

## Optional environment variables

| Variable | Default | Purpose |
|----------|---------|---------|
| `MINIMAX_API_KEY` | _(none)_ | Subscription key. Overrides file-based lookups. |
| `MINIMAX_API_BASE` | `https://api.minimax.io` | Base URL. Set to `https://api.minimaxi.com` for China. |
| `MINIMAX_7DAY_CACHE=1` | off | If you have 7-day prompt retention enabled, halves the cache-read rate. |
| `MINIMAX_QUOTA_POLL_MS` | `60000` | Polling interval in ms for the quota endpoint. Lower = more responsive, more requests. |

## Pricing baked in

| Token type | ≤ 512k context | > 512k (long-context) |
|------------|----------------|-----------------------|
| Input | $0.60 / 1M | $1.20 / 1M |
| Output | $2.40 / 1M | $4.80 / 1M |
| Cache read | $0.12 / 1M  (or $0.06 with 7-day retention) | $0.24 / 1M |
| Cache write | $0.00  (passive caching — no write cost) | $0.00 |

Pricing is hardcoded from [platform.minimax.io/docs/guides/pricing-paygo](https://platform.minimax.io/docs/guides/pricing-paygo). If Minimax changes their pricing, open an issue.

## Slash commands

| Command | Effect |
|---------|--------|
| `/minimax-usage` | Full session + quota breakdown as a notification |

## Compatibility

- Pi ≥ 0.78 (uses the `message_end` and `setStatus` extension APIs)
- Minimax subscription plan (Plus / Max / Ultra) — required for the quota endpoint
- Models: any Minimax model on the Anthropic-compatible or OpenAI-compatible endpoint (the cost-rewrite hook only fires for messages with `provider === "minimax"`)

## License

MIT — see [LICENSE](./LICENSE).
