pi-balance
Pi extension that displays provider account balance in the status bar.
Package details
Install pi-balance from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-balance- Package
pi-balance- Version
1.0.2- Published
- May 25, 2026
- Downloads
- 1,414/mo · 16/wk
- Author
- rokiy
- License
- MIT
- Types
- extension
- Size
- 196.7 KB
- Dependencies
- 0 dependencies · 2 peers
Pi manifest JSON
{
"extensions": [
"./dist/index.js"
],
"image": "https://img.dog/file/1779542581467_mzRI9XShNB2pFCVDlx1f8.webp"
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
📋 Features
pi-balance is an extension for the pi coding agent that automatically fetches and displays your AI provider's API credit balance in the pi status bar.
- ✅ Auto-detects your currently active model provider
- ✅ Event-driven refresh — balance updates automatically after each conversation (with delta display ▲▼)
- ✅ Live updates on provider/model switch
- ✅ Multi-provider support — DeepSeek, Moonshot/Kimi, OpenRouter, Sub2Api, OpenAI Codex (and compatible APIs)
- ✅ Zero configuration for balance APIs — supported balance APIs work from existing model headers
- ✅ Graceful fallback — quietly hides when balance info is unavailable
- ✅ i18n support — English and Simplified Chinese, with
/balance lang <zh-CN|en>command
📦 Installation
Option 1: Install from npm (Recommended)
pi install npm:pi-balance
Option 2: Install from GitHub
pi install git:github.com/DragonYH/pi-balance
Option 3: Local Development
git clone https://github.com/DragonYH/pi-balance.git
cd pi-balance
npm install
npm run build
pi install ./
Verify Installation
Restart pi. You should see the balance indicator appear in the status bar once you connect to a supported provider.
🔌 Supported Providers
| Provider | Balance Endpoint | Display |
|---|---|---|
| DeepSeek | /user/balance |
¥ (CNY) balance |
| Moonshot / Kimi | /v1/users/me/balance |
¥ (CNY) available balance |
| Sub2Api | /usage |
$ (USD) remaining balance |
| Compatible APIs | /usage, /v1/usage |
$ (USD) remaining balance |
| OpenAI Codex | ChatGPT Codex usage API / codex app-server |
5-hour and weekly usage remaining |
| OpenRouter | /v1/credits |
$ (USD) remaining credits |
The extension automatically detects which provider you're using based on your current model configuration — no manual setup required.
🚀 Usage
Once installed, pi-balance works completely automatically:
- On session start — it fetches your balance immediately
- On model switch — it re-fetches for the new provider
- After each conversation (
agent_end) — automatically refreshes and shows balance delta (▲▼)
The balance is displayed in the status bar at the bottom of your pi terminal:
DeepSeek: ¥49.87
If the extension cannot determine your balance (e.g., unsupported provider or network issue), the status bar entry is gracefully hidden.
/balance Command
Run /balance to open an interactive configuration menu. You can:
- View support status for configured providers
- Expand/collapse providers to toggle display and extra options
- Enable/disable Sub2Api sub-providers inline (with auto-discovery)
- Toggle Codex CLI fallback on/off
- Refresh the current status immediately
You can also use command arguments directly:
/balance status
/balance refresh
/balance enable deepseek
/balance disable moonshot
/balance toggle codex
/balance toggle openrouter
/balance toggle sub2api
/balance sub2api # Open Sub2Api sub-provider menu
/balance sub2api rescan # Re-scan for new Sub2Api providers
/balance lang zh-CN # Switch to Simplified Chinese
/balance lang en # Switch to English
Configuration Notes
- Provider display toggles are saved by the
/balancemenu and apply on the next refresh. - Custom Sub2Api providers are discovered from your pi model configuration (
~/.pi/agent/models.json) and can be enabled/disabled individually from the main menu or/balance sub2api. Use/balance sub2api rescanafter changing model configuration. - OpenAI Codex usage is shown only while the active model provider is
openai-codex. The extension first reuses pi's Codex subscription auth headers and can fall back tocodex app-server --listen stdio://when available; the CLI fallback can be toggled in the/balancemenu. - The menu caches support states intelligently: expanding/collapsing providers is instant (no recomputation), while config changes trigger automatic refresh.
- Network requests time out quickly and failures are hidden from the status bar instead of interrupting your session.
🧠 How It Works
┌─────────────────────────────────────────────────────────────┐
│ pi Coding Agent │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ [Chat Interface] │ │
│ │ │ │
│ ├───────────────────────────────────────────────────────┤ │
│ │ Status Bar: DeepSeek: ¥49.87 ◉ Connected │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
│ ┌─ Extension: pi-balance ───────────────────────────────┐ │
│ │ session_start ──► fetchBalance() ──► setStatus() │ │
│ │ model_select ──► fetchBalance() ──► setStatus() │ │
│ │ agent_end ────► refreshBalance(showDelta) │ │
│ └────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Events Handled
session_start— initial balance fetch when a session beginsmodel_select— re-fetch when you switch models/providersagent_end— refresh balance after each conversation, showing delta (▲▼)session_shutdown— cleanup and clear status
🏗️ Project Structure
pi-balance/
├── src/
│ ├── index.ts # Entry point, commands, lifecycle
│ ├── types.ts # Type definitions and constants
│ ├── config.ts # Config load/persist/toggle
│ ├── utils.ts # Helpers (fetch, JSON, type guards)
│ ├── menu.ts # Dynamic menu builder with caching
│ └── providers/
│ ├── types.ts # BalanceProvider interface
│ ├── registry.ts # Singleton provider registry
│ ├── deepseek.ts # DeepSeek provider
│ ├── moonshot.ts # Moonshot/Kimi provider
│ ├── openrouter.ts # OpenRouter provider
│ ├── sub2api.ts # Sub2Api + auto-discovery
│ └── codex.ts # OpenAI Codex + CLI fallback
│ └── i18n/
│ ├── index.ts # t() function + language detection
│ ├── zh-CN.ts # Chinese translations
│ └── en.ts # English translations
├── tests/
│ └── index.test.ts
├── LICENSE # MIT license
├── README.md # English documentation
├── README.zh-CN.md # Chinese documentation
├── package.json # Node.js and pi package manifest
├── tsconfig.build.json # Build configuration
└── tsconfig.json # TypeScript configuration
🛠️ For Developers
Type-Checking
npm run typecheck
Build
npm run build
Test
npm test
Publish Checklist
This project publishes through GitHub Actions when a version tag is pushed.
Before publishing, verify the package contents:
npm pack --dry-run
Then create and push a tag that matches package.json:
git tag vX.Y.Z
git push origin vX.Y.Z
Before pushing the tag, configure npm Trusted Publishing for this package:
- Publisher: GitHub Actions
- Owner:
DragonYH - Repository:
pi-balance - Workflow:
release.yml - Environment: leave empty unless you add one to the workflow.
Adding a New Provider
The extension uses a pluggable provider architecture. To add support for a new provider, create a module in src/providers/ that implements the BalanceProvider interface, then import it in src/index.ts to trigger auto-registration:
// src/providers/yourprovider.ts
import type { BalanceProvider } from "./types.js";
import { registry } from "./registry.js";
import type {
BalanceResult,
BalanceConfig,
FetchContext,
ProviderSupport,
} from "../types.js";
import { getJson } from "../utils.js";
export const yourProvider: BalanceProvider = {
key: "yourprovider",
definition: {
key: "yourprovider",
label: "YourProvider",
color: "#FFD700",
},
shouldTry(model, baseUrl) {
return baseUrl.includes("yourprovider.com");
},
async fetchBalance(
ctx: FetchContext,
signal?: AbortSignal,
): Promise<BalanceResult | undefined> {
const data = await getJson(`${ctx.baseUrl}/your/endpoint`, ctx.headers, signal);
const amount = data?.credits_remaining;
return typeof amount === "number" ? { amount, unit: "$" } : undefined;
},
async getSupport(
ctx: ExtensionContext,
config: BalanceConfig,
): Promise<ProviderSupport> {
return {
provider: this.definition,
configured: true,
details: ["Configured"],
};
},
};
registry.register(yourProvider);
Then add one import in src/index.ts:
import "./providers/yourprovider.js";
That's it — the provider auto-registers, appears in the /balance menu, and participates in balance fetching. No other code changes needed.
