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

tai-ai

v0.4.0

Published

Tai CLI — AI Gateway client for skills, LLM, AIGC, ASR, TTS

Readme

Tai 命令行工具

AI 网关的统一命令行客户端。一个 tai 命令覆盖技能管理、大模型对话、图片视频生成、语音识别与合成。

npm install -g tai-ai
tai config set --endpoint https://your-gateway.com --api-key YOUR_KEY
tai skill search "代码审查"

为什么用命令行,而不是开发包、接口、图形界面?

| 维度 | 开发包 (SDK) | 接口 (REST) | 命令行 (CLI) | |------|-------------|-------------|-------------| | 智能体兼容性 | 需要定制工具 | 需要写请求代码 | 天然适配——所有智能体都有 run(command) | | 上手难度 | 读文档 → 写代码 → 调试 | 拼请求头和请求体 | tai -h 三秒上手 | | 可组合性 | 函数调用 | 无 | 管道 + 重定向,Unix 50 年验证 | | 训练数据覆盖 | 低 | 中 | 极高——大模型见过海量终端命令 |

核心洞察:Unix 的一切皆文本流和大模型的一切皆文本片段在 50 年后收敛到同一个接口模型。命令行对大模型不是"也能用",是天然最优解

给智能体 10 个独立工具(搜索网页、读文件、生成图片……),它需要在不相关的接口间做模式切换。给它一个命令行命名空间(tai skill searchtai aigc imagetai llm chat),它只需做字符串组合——认知负荷降一个量级。


设计哲学

一、单工具假说 —— 一个 run(command) 够了

不要给大模型一堆独立工具,通过命令行子命令统一暴露:

tai skill search "代码审查"       # 搜索技能
tai llm chat "你好"              # 大模型对话
tai aigc image "日落"            # 生成图片
tai asr transcribe <音频地址>     # 语音识别
tai tts speak "你好" --voice xxx # 语音合成

智能体只需记住一个工具名 tai,剩下的靠 -h 自己发现。

二、渐进式帮助 —— 三层递进,按需加载

绝不把所有文档塞进系统提示词。 让智能体(或人类)按需逐层深入:

第 0 层:工具注册时的描述
  → "tai: AI 网关命令行,支持技能、大模型、图片视频、语音"

第 1 层:tai -h
  → 列出所有子命令 + 一行描述

第 2 层:tai aigc -h
  → 列出 image/video/status + 所有参数 + 示例

第 3 层:tai aigc image(缺参数时)
  → "[error] 缺少 <prompt>"
  → "用法:tai aigc image <提示词> [--model 模型] [--size 尺寸]"

每一层只暴露当前需要的信息量。智能体不需要提前知道语音合成有哪些音色,直到它要合成语音的那一刻。

实现规则:

  • 无参数 → 显示帮助(不报错)
  • -h / --help → 任何位置都能触发帮助
  • 缺少必需参数 → 报错 + 正确用法 + 示例

三、错误即导航 —— 每个错误指向正确方向

智能体不能搜索引擎。每个错误必须同时回答**"出了什么问题""该怎么做"**:

# 差的写法:
[error] skill not found

# 好的写法:
[error] "code-review" 在 SkillHub 和 ClawHub 均未找到。
  试试:tai skill search <关键词>

# 差的写法:
[error] unauthorized

# 好的写法:
[error] 缺少 API Key。
  运行:tai config set --api-key YOUR_KEY

实现规则:

  • 每条错误后面跟一个可直接执行的命令建议
  • \n 缩进建议命令,视觉上区分"问题"和"方案"
  • 多个可能的解决路径时,按可能性排列

四、输出尾注 —— 持续反馈

每次输出末尾追加元数据:

结果内容...
[exit:0 | 320ms]
  • 退出码:智能体通过 Unix 约定判断成败(0=成功,非0=失败)
  • 耗时:智能体感知操作成本
    • 12ms → 廉价操作,可以多调几次
    • 45000ms → 昂贵操作,下次要谨慎
    • 这个信息对智能体的决策至关重要

实现方式:

function out(text, code = 0, t = Date.now()) {
  console.log(text);
  console.log(`[exit:${code} | ${Date.now() - t}ms]`);
  process.exit(code);
}

五、溢出模式 —— 给地图,不给全部领土

输出过大时:截断 + 给探索路径。

#  标识符       名称       作者   下载  版本
-  ----------  --------   -----  --   -----
1  code-review  代码审查   admin  42   1.0.0
...
--- 显示前 20 条,共 128 条 ---

128 个结果。安装:tai skill install <标识符>
[exit:0 | 450ms]

给智能体一个"地图"(前 20 条 + 总数 + 翻页命令)比给它"全部领土"(128 条全量)有效得多。全量输出淹没上下文窗口,截断输出给出下一步行动路径。

六、双层架构 —— 执行层 与 呈现层

┌──────────────────────────────────────┐
│ 第二层:呈现层 (output.js)            │  ← 格式化、截断、尾注、错误导航
├──────────────────────────────────────┤
│ 第一层:执行层 (http.js + modules/)  │  ← 纯业务:接口调用、文件操作
└──────────────────────────────────────┘
  • 执行层只关心业务语义:发请求、拿数据、写文件
  • 呈现层只关心认知优化:截断大输出、格式化表格、追加退出码

为什么必须分层?

  • 如果在执行层截断 → 管道结果不完整
  • 如果在执行层加尾注 → 元数据流入下一个管道
  • 分层不是优化,是逻辑必然

三个手段的递进关系

帮助信息  → "我能做什么?"     → 主动发现
错误提示  → "做错了怎么办?"   → 被动纠偏
输出格式  → "做得怎么样?"     → 持续学习

这三个机制覆盖了智能体交互的完整生命周期。缺任何一个,智能体都会在某个阶段卡住。


项目架构

tai-cli/
├── src/                       # 源码(不发布到 npm)
│   ├── cli.js                 # 入口:参数解析 + 分发 + 版本号
│   ├── lib/                   # 基础设施层
│   │   ├── config.js          #   配置读写 (~/.tai/config.json)
│   │   ├── http.js            #   接口客户端(统一鉴权、错误处理)
│   │   ├── output.js          #   输出格式化(表格、尾注、参数解析)
│   │   └── update.js          #   自动更新检查 + 更新命令
│   └── modules/               # 业务模块层(模块间零依赖)
│       ├── skill.js           #   搜索 / 安装 / 发布 / 详情 / 列表
│       ├── aigc.js            #   生图 / 生视频 / 查状态
│       ├── llm.js             #   对话 / 模型列表
│       ├── asr.js             #   语音识别 / 查结果
│       ├── tts.js             #   语音合成 / 音色 / 下载
│       └── config.js          #   设置 / 查看 / 重置
├── dist/                      # 构建产物(发布到 npm 的唯一内容)
│   └── tai.min.js             #   打包 + 混淆后的单文件
├── scripts/
│   └── pre-publish-check.js   # 发布安全门禁(7 项检查)
├── build.js                   # 构建脚本
├── package.json
└── .npmignore

分层职责

| 层 | 目录 | 职责 | 依赖方向 | |----|------|------|---------| | 入口层 | cli.js | 解析参数,分发到对应模块 | 依赖所有模块 | | 基础设施层 | lib/ | 配置、网络、输出、更新 | 不依赖任何业务 | | 业务模块层 | modules/ | 各领域的命令实现 | 只依赖 lib/ |

模块之间零依赖——skill.js 不引用 aigc.js。新增一个模块只需要两步:

  1. modules/ 下新建文件
  2. cli.js 加一行分发

数据流

用户输入                      命令行内部                       网关
─────────                    ─────────                       ─────────
tai aigc image "猫"
        │
        ▼
    cli.js(分发)
        │
        ▼
    modules/aigc.js
        │  调用 lib/http.js
        ▼
    api('POST', '/aigc/images/generations', {body})
        │                                           ──→ 网关接口
        │                                           ←── 返回结果
        ▼
    lib/output.js
        │  格式化 + 尾注
        ▼
    标准输出: "任务:aigc_xxx\n[exit:0 | 3200ms]"

构建与发布

为什么要混淆?

命令行工具发布到 npm 是公开的。不混淆意味着:

  • 接口路径暴露(攻击者知道所有端点)
  • 鉴权逻辑暴露(攻击者知道请求头格式)
  • 内部域名暴露(攻击者知道目标服务器)

构建流程

npm run build
    │
    ▼
[第一步] esbuild:所有模块 → 单文件打包 (21KB)
    │  - 目标平台:Node.js 18
    │  - 模块格式:ESM
    │  - 不生成源码映射文件
    │  - 内置模块标记为外部依赖
    │
    ▼
[第二步] javascript-obfuscator:打包产物 → 混淆 (137KB)
    │  - 控制流平坦化:打乱代码执行顺序
    │  - 字符串加密:所有字符串编码为 base64 数组
    │  - 死代码注入:插入无用代码干扰逆向
    │  - 标识符替换:变量名改为十六进制
    │  - 字符串分割:长字符串拆成碎片
    │
    ▼
dist/tai.min.js  ← 这是唯一发布到 npm 的文件

发布安全门禁

npm publish 时自动触发构建前置钩子:

npm publish
  ↓
[第一步] build.js → 构建混淆产物
  ↓
[第二步] pre-publish-check.js → 7 项安全检查
  ├─ 源码目录不在包内?           (源码泄露检测)
  ├─ 源码映射文件不在包内?       (映射文件泄露检测)
  ├─ 混淆产物存在?               (构建产物检测)
  ├─ 只有白名单文件?             (意外文件检测)
  ├─ 接口路径已被混淆?           (混淆有效性检测)
  ├─ 函数名已被混淆?             (混淆有效性检测)
  └─ 配置文件不含源码目录?       (配置正确性检测)
  ↓
任何一项失败 → 退出码 1 → 发布中止
全部通过 → npm 上传

即使有人误改了配置把源码目录加进去,门禁也会拦住。这是最后一道自动化防线。

版本发布步骤

# 1. 修改代码
# 2. 更新版本号(两处同步改)
#    package.json  → version: "0.4.0"
#    src/cli.js    → const VERSION = '0.4.0'
# 3. 发布(自动构建 + 安全检查 + 上传)
npm publish --access public
# 4. 用户侧更新
tai update

自动更新机制

用户运行任意命令
       │
       ▼
  检查更新(非阻塞,不影响命令执行)
       │
       ├─ 读缓存文件 ~/.tai/.update-check
       │  └─ 距上次检查不到 24 小时?→ 跳过(只看缓存结果)
       │
       ├─ 请求 npm 仓库(3 秒超时)
       │  └─ 拿到最新版本号
       │
       ├─ 写缓存
       │
       └─ 最新版本 ≠ 当前版本?
           → 提示:"有新版本:v0.3.1 → v0.4.0,运行 tai update 更新"
  • 每天最多查一次(不浪费网络)
  • 3 秒超时(断网不阻塞正常使用)
  • 只提示不强制(用户决定何时更新)
  • tai update 一键更新到最新版

跨平台兼容

| 操作 | macOS / Linux | Windows | |------|---------------|---------| | 解压压缩包 | unzip -o | PowerShell Expand-Archive | | 删除目录 | Node.js rmSync() | Node.js rmSync() | | 技能安装路径 | ~/.codex/skills/<名称>/ | C:\Users\<用户>\.codex\skills\<名称>\ | | 配置文件路径 | ~/.tai/config.json | C:\Users\<用户>\.tai\config.json |

通过 os.platform() 检测操作系统,在解压等系统操作处做分支处理。路径拼接、用户目录等一律使用 Node.js 内置接口(path.joinhomedir()),不依赖特定操作系统的命令。


鉴权设计

用户只需一个项目密钥,覆盖所有操作:

tai config set --endpoint 地址 --api-key 密钥
                                    │
            ┌───────────────────────┼───────────────────────┐
            ▼                       ▼                       ▼
      技能搜索/安装          大模型/图片/语音           技能发布
      (公开读操作)          (业务调用)             (写操作)
            │                       │                       │
            ▼                       ▼                       ▼
      密钥 → 项目编号         密钥 → 项目编号         密钥 → 项目编号
                                                            │
                                                            ▼
                                                      项目 → 所有者
                                                    (自动解析作者身份)

没有令牌、没有授权流程、没有登录页面。一个密钥走天下。

发布技能时,后端通过"项目密钥 → 项目 → 项目所有者"自动关联作者,不需要额外的用户认证。


血泪教训

教训一:一张图片引发 20 轮崩溃

直接输出二进制文件内容 → 大模型收到乱码 → 反复盲试。

结论: 工具的输出就是智能体的眼睛,返回垃圾等于让智能体失明。

我们的做法: 压缩包下载不输出内容,引导到文件路径。

教训二:沉默的错误信息与 10 次盲猜

依赖不存在但错误被吞掉了,智能体盲猜了 10 种包管理器。

结论: 永远不要丢弃错误信息。

我们的做法: 所有异常捕获都通过 fail() 输出完整错误描述 + 解决建议。

教训三:5000 行日志淹没上下文

全文塞进上下文导致大模型注意力被淹没,关键信息被噪音掩盖。

结论: 截断 + 过滤探索,比全量输出高效 10 倍。

我们的做法: 搜索结果最多显示 20 条,超出部分提示总数和翻页方式。

教训四:源码直接发到公网

v0.2.0 把原始源代码发到 npm,接口路径和鉴权逻辑全部暴露,任何人都能分析出攻击路径。

结论: 公开发布 = 攻击面暴露,必须在发布前混淆。

我们的做法: 构建混淆 + 7 项安全门禁,源码永远不出代码仓库。

教训五:Windows 没有 unzip 命令

Linux 思维定势,用了 unzip 命令,Windows 用户直接报错"命令不存在"。

结论: 命令行的跨平台不只是路径分隔符,系统命令也不能想当然。

我们的做法: 检测操作系统,Windows 自动切换到 PowerShell 的 Expand-Archive


从零设计命令行的检查清单

如果你要设计一个新的命令行工具,对照以下清单逐项确认:

  • [ ] 每个命令有帮助:无参数时显示帮助信息,不报错
  • [ ] 每个错误带建议:告诉用户出了什么问题 + 该执行什么命令
  • [ ] 每个输出带尾注:退出码 + 耗时,让智能体感知操作结果和成本
  • [ ] 大结果集截断:显示前 N 条 + 总数 + 翻页或过滤提示
  • [ ] 统一鉴权:一个密钥覆盖所有操作,不要让用户管理多套凭证
  • [ ] 跨平台测试:至少覆盖 macOS 和 Windows,不依赖特定系统命令
  • [ ] 不发布源码:构建混淆 + 发布前自动检查,源码不出仓库
  • [ ] 自动更新:后台检查版本 + 一键更新命令,降低用户维护成本
  • [ ] 尽量零依赖:减少供应链攻击面,Node.js 内置能做的不引第三方包
  • [ ] 分层清晰:入口层(分发)/ 基础设施层(配置、网络、输出)/ 业务层(各模块)

许可证

MIT