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

@yinxe/opencode-tui-usage

v1.0.5

Published

OpenCode TUI 额度显示插件 - 在侧边栏显示用量和额度信息

Readme

OpenCode TUI Usage Plugin

OpenCode TUI 插件,在侧边栏显示用量和额度信息,支持多额度 provider。

preview

🤖 Agent 快速安装

把下面这段提示词发给你的 AI 编码代理(OpenCode 等),即可自动完成安装和配置:

给用户安装 opencode-tui-usage 插件(@yinxe/opencode-tui-usage)。

步骤:

  1. ~/.config/opencode/tui.json"plugin" 数组中添加 "@yinxe/opencode-tui-usage@latest"
  2. 如果文件不存在,创建它:
    {
      "$schema": "https://opencode.ai/tui.json",
      "plugin": ["@yinxe/opencode-tui-usage@latest"]
    }
  3. 根据用户使用的 AI provider 设置对应的环境变量(任选其一或多个):
    • DeepSeekexport DEEPSEEK_API_KEY="sk-xxxxx"
    • MiniMaxexport MINIMAX_API_KEY="your-key"
    • OpenCode Goexport OPENCODE_GO_AUTH_COOKIE="cookie"export OPENCODE_GO_WORKSPACE_ID="wrk_xxx"
  4. 重启 OpenCode
  5. 打开一个会话,在侧边栏查看用量信息

提示:本插件已内置环境变量保底支持。即使不创建 usage.provider.json 配置文件,只要设置了上述约定的环境变量就能工作。

功能特性

  • 📊 支持 plan 型与按量计费型两种 provider
  • 💰 余额展示(按量计费 provider,如 DeepSeek)
  • 📈 额度展示(plan 型 provider,进度条 + rolling/weekly/monthly)
  • 🎨 树线风格展示 Session / Token 用量信息
  • 🔄 自动根据当前会话的 provider 切换数据源
  • 🛠️ 支持扩展新的 provider 适配器

安装

~/.config/opencode/tui.json 中添加插件路径:

{
  "$schema": "https://opencode.ai/tui.json",
  "plugin": ["@yinxe/opencode-tui-usage@latest"]
}

重启 OpenCode 使插件生效。

首次配置或修改插件版本后,下次重启 OpenCode 会花费一些时间从 npm 自动下载安装插件。

配置额度 Provider

插件支持多个额度 provider,会根据当前会话的 providerID 自动选择对应的适配器。

环境变量引用

配置值支持两种环境变量引用格式,从 process.env 读取实际值:

| 格式 | 示例 | 说明 | |------|------|------| | ${VAR} | "apiKey": "${MY_KEY}" | 旧写法(兼容) | | {env:VAR} | "apiKey": "{env:MY_KEY}" | 新写法 |

保底支持:每个 provider 都有约定的环境变量名称。即使 usage.provider.json 中未配置,只要设置了约定环境变量就能工作。

| Provider | 保底环境变量 | |----------|-------------| | DeepSeek | DEEPSEEK_API_KEY | | MiniMax | MINIMAX_API_KEY | | OpenCode-Go | OPENCODE_GO_AUTH_COOKIE + OPENCODE_GO_WORKSPACE_ID |

MiniMax-CN

适用于 providerIDminimax-cn-coding-plan 的会话。

创建 ~/.config/opencode/usage.provider.json

{
  "providers": {
    "minimax-cn-coding-plan": {
      "apiKey": "${MINIMAX_API_KEY}"
    }
  }
}

设置环境变量:

export MINIMAX_API_KEY="your-api-key-here"

OpenCode-Go

适用于 providerIDopencode-go 的会话。

~/.config/opencode/usage.provider.json 中添加:

{
  "providers": {
    "opencode-go": {
      "cookie": "${OPENCODE_GO_AUTH_COOKIE}",
      "workspaceId": "${OPENCODE_GO_WORKSPACE_ID}"
    }
  }
}

设置环境变量:

export OPENCODE_GO_AUTH_COOKIE="your-cookie"
export OPENCODE_GO_WORKSPACE_ID="wrk_xxxxxxxxxxxx"

DeepSeek

适用于 providerIDdeepseek 的按量计费会话。

~/.config/opencode/usage.provider.json 中添加:

{
  "providers": {
    "deepseek": {
      "apiKey": "{env:DEEPSEEK_API_KEY}"
    }
  }
}

设置环境变量:

export DEEPSEEK_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

获取 OpenCode-Go 配置

  1. 登录 https://opencode.ai
  2. 打开浏览器开发者工具 → Network
  3. 访问 /workspace/{workspaceId}/usage 页面
  4. 找到 _server 请求,从 Request Headers 复制完整的 cookie
  5. workspaceId 从 URL 中获取(格式:wrk_ 开头)

开发

# 安装依赖
npm install

# 类型检查
npm run lint

# 构建输出到 dist/
npm run build

# 监听模式(开发时使用)
npm run dev

目录结构

src/
├── tui.tsx              # 插件入口,注册 sidebar_content slot
├── formatters.ts        # 格式化工具
├── components.tsx       # 可复用组件 (TreeItem, Collapsible, ProgressBar)
├── balance-view.tsx     # 余额展示组件(按量计费)
├── usage.tsx            # 额度展示组件(plan 型)
├── session-info.tsx     # Session 组件(含 Context 合并)
├── tokens-usage.tsx     # Token 统计组件(树线展示)
├── index.ts             # 重新导出
└── quota/               # 额度/余额服务
    ├── types.ts         # QuotaData, BalanceData 类型定义
    ├── provider.ts      # QuotaProvider + BalanceProvider 接口
    ├── service.ts       # QuotaService 多 provider 管理
    ├── config.ts        # 读取 usage.provider.json
    └── providers/       # provider 适配器
        ├── minimax.ts
        ├── opencode-go.ts
        └── deepseek.ts  # 按量计费(Balance + Quota 双接口)

添加新的 Provider 适配器

支持两种类型的 provider:

| 类型 | 接口 | 适用场景 | 展示组件 | |------|------|----------|----------| | Quota (额度) | QuotaProvider | plan 型(coding plan / token plan) | UsageView(进度条 + rolling/weekly/monthly) | | Balance (余额) | BalanceProvider | 按量计费(pay-as-you-go) | BalanceView(余额数值) |

一个 provider 可以同时实现两个接口(如 DeepSeek 无 plan quota 但提供余额查询)。

1. 抓包获取 API

在浏览器中打开目标网站的额度页面(如 https://example.com/workspace/xxx/usage),打开开发者工具 → Network,找到获取额度数据的请求:

  • Chrome/Edge: 右键请求 → Copy → Copy as cURL
  • Firefox: 右键请求 → Copy Value → Copy as cURL

2. 调试 curl,精简参数

拿到 curl 后,在终端中反复调试,逐步移除不必要的 headers 和参数,直到找到最小可复现的请求。常用技巧:

# 逐步删除 headers,看哪些是必需的(通常是 Authorization/Cookie)
# 移除浏览器特有的 headers:sec-fetch-*, user-agent, referer, accept-language 等
# 保留核心:认证信息 + Content-Type

# 调试过程中可以用 | jq 格式化响应,方便分析
curl -s 'https://example.com/api/quota' \
  -H 'Authorization: Bearer xxx' \
  | jq .

目标:得到一个稳定可复现参数最少的 curl 命令。

3. 分析响应结构

运行精简后的 curl,将响应字段映射到对应数据结构:

QuotaData(plan 型):

| 响应字段 | QuotaData 字段 | 说明 | |----------|---------------|------| | xxx.total / xxx.used | rolling.usage | 计算百分比 | | xxx.reset_time | rolling.reset | 用 formatDurationCompact() 格式化 |

BalanceData(按量计费型):

| 响应字段 | BalanceData 字段 | 说明 | |----------|-----------------|------| | xxx.total_balance | totalBalance | 总余额 | | xxx.currency | currency | 币种 |

4. 编写适配器

src/quota/providers/ 创建 {name}.ts

Plan 型(实现 QuotaProvider): 参考 minimax.tsopencode-go.ts

import type { QuotaData, ProviderConfig } from "../types.js";
import { QuotaProvider, resolveEnvVar } from "../provider.js";

export class MyQuotaProvider implements QuotaProvider {
  readonly name = "my-provider";
  private apiKey: string | undefined;

  init(config: ProviderConfig, _credentials: Record<string, unknown>): void {
    this.apiKey = resolveEnvVar(config.apiKey as string | undefined);
  }

  async fetchQuota(): Promise<QuotaData | null> {
    // 调用 API 并映射为 QuotaData(rolling/weekly/monthly)
  }
}

按量计费型(实现 BalanceProvider): 参考 deepseek.ts

import type { BalanceData, QuotaData, ProviderConfig } from "../types.js";
import { QuotaProvider, BalanceProvider, resolveEnvVar } from "../provider.js";

export class MyBalanceProvider implements QuotaProvider, BalanceProvider {
  readonly name = "my-provider";

  init(config: ProviderConfig, _credentials: Record<string, unknown>): void {
    this.apiKey = resolveEnvVar(config.apiKey as string | undefined);
  }

  // QuotaProvider:无 plan quota 时返回 null
  async fetchQuota(): Promise<QuotaData | null> { return null; }

  // BalanceProvider:返回余额数据
  async fetchBalance(): Promise<BalanceData | null> {
    // 调用 API 并映射为 BalanceData
  }
}

5. 注册到 QuotaService

src/quota/service.ts 构造函数中注册:

import { MyQuotaProvider } from "./providers/my-provider.js";
this.registerProvider(new MyQuotaProvider());

6. 添加配置

~/.config/opencode/usage.provider.json 中添加 provider 配置:

{
  "providers": {
    "my-provider": {
      "apiKey": "${MY_API_KEY}"
    }
  }
}

7. 测试

构建并重启 OpenCode,切换到对应 provider 的会话,检查侧边栏是否正常显示额度数据。

调试

查看插件日志:

cat ~/.local/share/opencode/log/$(ls -t ~/.local/share/opencode/log/ | head -1) | grep -i "tui.plugin\|error\|QuotaService\|DeepSeek"

常见问题:

| 问题 | 原因 | 解决方案 | |------|------|----------| | 侧边栏无显示 | 缺少 "oc-plugin": ["tui"] | 检查 package.json | | JSX 报错 | 缺少 pragma | 每个 .tsx 顶部加 /** @jsxImportSource @opentui/solid */ | | 显示 "No data" | provider 未注册或配置缺失 | 检查 usage.provider.json 和环境变量 | | opencode-go 500 错误 | cookie 过期或 headers 不对 | 重新抓包获取最新 cookie |

技术栈

  • Solid.js - 响应式 UI 框架
  • @opentui/solid - TUI 组件库(<box>, <text> 等)
  • TypeScript - 类型安全

CI/CD 自动化发版

本项目使用 GitHub Actions 实现自动化发版。推送 v* 格式的 tag 后,同时发布到 npm 和 GitHub Packages

发布流程

使用 npm version 管理版本号(会自动创建 tag):

# 更新版本并创建 tag
npm version patch  # 0.0.1 → 0.0.2
npm version minor  # 0.0.1 → 0.1.0
npm version major  # 0.0.1 → 1.0.0

# 推送 tag 触发 CI/CD
git push origin v0.0.3

自动触发的工作流

推送 tag 后,以下 job 会自动执行:

build → publish-npm + publish-github

| Job | 目标 | 依赖 | |-----|------|------| | build | 安装依赖、构建项目、运行测试 | - | | publish-npm | 发布到 npm registry | build | | publish-github | 发布到 GitHub Packages | build |

首次发版配置

  1. GitHub Packages 认证

    • 无需额外配置,使用内置 GITHUB_TOKEN
  2. npm 认证(如需发布到 npm)

    • npm.npmjs.com 创建 Access Token
    • 在 GitHub 仓库 Settings → Secrets and variables → Actions 添加 secret:
      • Name: npm_token
      • Secret: 你的 npm access token
  3. scoped 包配置

    • 包名 @yinxe/opencode-tui-usage 已在 package.json 中配置
    • publishConfig.registry 指定发布到哪个 registry

发布地址

| 平台 | 包名 | 地址 | |------|------|------| | npm | @yinxe/opencode-tui-usage | https://www.npmjs.com/package/@yinxe/opencode-tui-usage | | GitHub Packages | @yinxe/opencode-tui-usage | https://github.com/Yinxe/opencode-tui-usage/packages |

License

MIT