npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

pi-usage-hub

v1.0.9

Published

Usage hub for pi — provider quota/balance registry with cache, /usage-hub panel, and pull API

Readme

pi-usage-hub

Track provider quotas and balances in pi — /usage-hub panel, session stats, and a pull API for footer integration.

npm version License: MIT

Why

Checking separate dashboards for DeepSeek, NewAPI relays, xAI, Kiro, OpenCode Go, and ARK breaks flow. pi-usage-hub brings their quotas and balances into one TUI panel while keeping footer integration optional and pull-based.

Install

pi install npm:pi-usage-hub

Commands

| Command | Description | |---------|-------------| | /usage-hub | Show quotas and balances for detected providers | | /usage-hub session | Show local session token and cost stats | | /usage-hub login <name> | Open browser login for a cookie-based provider |

Inside the panel, Tab switches between Quota and Session. In the Quota view, ↑↓ scrolls when content overflows.

pi-usage-hub quota panel

pi-usage-hub session panel

Configuration

Create ~/.pi/agent/pi-usage-hub.json. Provider order is preserved in the panel.

{
  "providers": [
    {
      "type": "deepseek",
      "apiKey": "sk-..."
    },
    {
      "name": "xh",
      "type": "newapi",
      "matchProviders": ["xh-cc", "xh-glm"],
      "host": "https://example.com",
      "token": "...",
      "userId": "1"
    },
    {
      "name": "ocg",
      "type": "opencode-go",
      "workspaceId": "wrk_...",
      "matchProviders": ["opencode-go"]
    },
    { "type": "ark" },
    {
      "type": "xai",
      "matchProviders": ["xai-auth", "xai", "grok-cli"]
    },
    { "type": "kiro" }
  ]
}

Common fields

| Field | Required | Description | |-------|----------|-------------| | type | yes | Built-in provider factory | | name | no | Instance key; defaults to type, then type-2, type-3, and so on | | matchProviders | no | Additional model.provider values mapped to this entry | | shortLabel / label | no | Override the footer label or panel title | | hidden | no | Exclude from panel and footer; /usage-hub login still works |

Provider types

| Type | Credentials | Notes | Website | |------|-------------|-------|---------| | deepseek | apiKey | Account balance | deepseek | | newapi | host, token, userId | Balance and today's spend; supports multiple instances | newapi | | opencode-go | workspaceId; optional auth | Uses the configured auth cookie or macOS Chrome | opencode | | ark | optional cookie, csrfToken | Uses the configured Cookie header or macOS Chrome | 火山引擎 | | xai | — | Reads auth.json or ~/.grok/auth.json | x.ai/grok | | kiro | — | Reads the Kiro OAuth entry from auth.json | kiro.dev |

For NewAPI, token is the system access token (not a chat sk- token), and userId is sent as New-Api-User. See Authentication and Generate access token.

For ARK and OpenCode Go, configured cookie / auth values take priority over Chrome. Manual credentials disable /usage-hub login for that entry; replace them when they expire. Automatic Chrome cookie reading is macOS only.

Related auth packages

These are companion packages, not npm peer dependencies:

| Type | Companion | Purpose | |------|-----------|---------| | xai | pi-xai-oauth | /login xai-auth writes the OAuth entry to auth.json | | kiro | pi-provider-kiro-dev | Provides /login kiro, models, and the auth.json entry |

pi-usage-hub only reads those credentials; it does not run their OAuth flows.

Built-in providers cover the integrations used and smoke-tested by the author. To support another provider, register a custom provider from an extension, or fork the package and submit a PR.

Add a custom provider

See examples/custom-provider.ts for a self-contained extension that implements and registers a provider. Copy it into ~/.pi/agent/extensions/, then adapt the endpoint, credentials, response shape, and labels.

pi.events.on("pi-usage-hub:ready", (hub) => hub.register(myProvider));
pi.events.emit("pi-usage-hub:register", myProvider);
pi.events.emit("pi-usage-hub:unregister", { key: "my-relay" });

Pull API

The hub caches results for 60 seconds and deduplicates concurrent requests. It never pushes footer text: consumers start refreshes without blocking lifecycle events, read the cached summary, and re-render when notified.

| API | Role | |-----|------| | pi-usage-hub:ready | Provides the hub; also emitted on session_start | | hub.refresh({ model?, force? }) | Refreshes the matching provider and returns its summary | | hub.getSummary(model?) | Synchronously reads the cached one-line summary | | pi-usage-hub:updated | Signals { key, summary } after a cache update |

Footer example

footer integration

type UsageHub = {
  getSummary(model?: { provider?: string }): string | null;
  refresh(opts?: {
    model?: { provider?: string };
    force?: boolean;
  }): Promise<string | null>;
};

let usageHub: UsageHub | null = null;
let requestRender: (() => void) | null = null;

const offReady = pi.events.on("pi-usage-hub:ready", (hub: UsageHub) => {
  usageHub = hub;
  requestRender?.();
});

const offUpdated = pi.events.on("pi-usage-hub:updated", () => {
  requestRender?.();
});

// Pi awaits lifecycle handlers; refresh in the background and re-render on pi-usage-hub:updated.
pi.on("session_start", (_event, ctx) => {
  void usageHub?.refresh({ model: ctx.model, force: true });
});
pi.on("model_select", (event) => {
  void usageHub?.refresh({ model: event.model, force: true });
});
pi.on("agent_end", (_event, ctx) => {
  void usageHub?.refresh({ model: ctx.model, force: true });
});

// Inside footer render():
// const usageText = usageHub?.getSummary(ctx.model);
// "XAI 87% · ↻ 3d 16h"

pi.on("session_shutdown", async () => {
  offReady();
  offUpdated();
  usageHub = null;
});

License

MIT