数据截至 (上游 commit 5284672feb57)
ctx7 CLI:查文档 + 一键接入 + OAuth 登录
30 秒导读:
ctx7是packages/cli里那支面向人的命令行工具。它做两件事: (1)让你在终端里直接查库文档(ctx7 library/ctx7 docs);(2)一条命令就把 Context7 接入你的 AI 编码工具——探测你装了哪些 agent、问你走 MCP 还是 CLI 模式、 把服务器条目写进各家配置文件、装上引导技能、帮你登录拿密钥。查询命令和 MCP 服务器的两个工具共用同一套后端契约,只是换了个外壳。
本章属于 Context7 系列。同系列其它章:
- index.md — Context7 是什么 · 全景与阅读地图
- 01-sdk-api-contract.md — SDK 与 API 契约(最底层:怎么跟后端对话)
- 02-mcp-server.md — MCP 服务器(旗舰:两个工具 · 传输 · 上下文 · 安全)
- 03-cli.md(本章)— ctx7 CLI:查文档 + 一键接入 + OAuth 登录
- 04-ai-sdk-tools-agent.md — AI-SDK 工具与 Agent · 跨端共享的提示词设计
- 05-delivery-skills-plugins.md — 分发即产品:Skills / Plugins / Rules 与两种交付模式
1. 这是什么(零基础也能懂)
一句话定义: ctx7 是 Context7 的命令行客户端——一个用 npx ctx7 就能跑起来的
小工具,既能当"查文档的搜索框",又能当"把 Context7 装进你编码工具的安装器"。
解决什么问题 / 给谁用。 假设你在用 Claude Code、Cursor、Codex 这类 AI 编码工具写代码。
你希望它回答"React 的 useEffect 怎么清理副作用"时,别用两年前训练数据里的旧知识,而是去
拉当前官方文档。要做到这点,得先把 Context7 "接进"你的工具——这活儿手动配置很烦
(每家工具配置文件格式还都不一样)。ctx7 setup 把这一步变成一条命令。
它能做什么(功能一览):
| 能力 | 命令 | 干什么 |
|---|---|---|
| 查库 ID | ctx7 library <名字> | 把"react"这种名字解析成 Context7 库 ID /facebook/react |
| 查文档 | ctx7 docs <库ID> "<问题>" | 按问题拉该库最相关的文档片段 |
| 一键接入 | ctx7 setup | 探测 agent → 选模式 → 写配置/装技能 → 登录 |
| 卸载 | ctx7 remove | 反向清掉配置、规则、技能 |
| 登录 | ctx7 login / whoami / logout | OAuth 设备码登录,拿更高配额 |
| 升级 | ctx7 upgrade | 检查新版本并按你的安装方式给升级命令 |
用起来什么样。 两条最典型的命令:
# 1) 先把名字解析成库 ID
$ npx ctx7 library react "how to use hooks"
1. Title: React
Context7-compatible library ID: /facebook/react
Source Reputation: High
...
Quick command:
ctx7 docs "/facebook/react" "<your question>"
# 2) 再用库 ID 拉文档
$ npx ctx7 docs /facebook/react "useEffect cleanup"
```
(此处会打印按问题排好序的代码片段和说明文本)
一句话直觉/类比。 把 ctx7 想成 Context7 的"双头插座":一头朝人(你在终端敲命令查文档),
一头朝机器(把 Context7 焊进你 AI 工具的配置)。两头电流同源——背后都是
01 章讲的那套 HTTP API。
2. 顶层全景(它大概怎么转)
ctx7 是一个 commander 程序:src/index.ts 注册所有
子命令、挂全局钩子、无参时打印 banner。每个子命令是 commands/ 下的一个文件。
怎么读这张图: 左边是用户敲的命令,中间是命令文件,右边是它们最终依赖的两类"出口" ——要么打后端 HTTP API(查询/登录),要么读写本地文件系统(接入/卸载)。
用户命令 commands/* 出口
───────── ────────── ────
ctx7 library ┐
ctx7 docs ┼───────► docs.ts ───────► HTTP: /api/v2/libs/search
│ HTTP: /api/v2/context
ctx7 login ┐
ctx7 whoami ┼───────► auth.ts ───────► HTTP: /api/oauth/device/*
ctx7 logout ┘ 本地: credentials.json
│
ctx7 setup ┼───────► setup.ts ──┐
ctx7 remove ┘ remove.ts ─┤
├─► setup/agents.ts (6家 agent 配置表)
├─► setup/mcp-writer (写 JSON/TOML 配置)
├─► setup/templates (取 rule / 定制技能)
└─► utils/installer (装技能文件/symlink)
部件一句话职责:
| 部件 | 干什么 | 文件 |
|---|---|---|
| 程序入口 | 注册子命令、--base-url 钩子、升级提示、banner | src/index.ts |
| 查询命令 | library/docs 两个查文档命令 | src/commands/docs.ts |
| 接入命令 | 端到端接入链(探测→选模式→写配置→登录) | src/commands/setup.ts |
| agent 配置表 | 6 家 agent 各自的规则/技能/MCP 路径 | src/setup/agents.ts |
| 配置写入器 | 把 Context7 条目合并进各家 JSON/TOML | src/setup/mcp-writer.ts |
| 模板/规则 | 拉 rule 正文、给 Codex/Cursor 定制 | src/setup/templates.ts |
| 技能安装器 | 写技能文件、防目录穿越、symlink | src/utils/installer.ts |
| 认证命令 | OAuth 设备流登录、whoami | src/commands/auth.ts |
| 认证工具 | 存取 token、判过期、设备流底层 | src/utils/auth.ts |
| HTTP 客户端 | 所有后端调用 + 认证头 | src/utils/api.ts |
主线走一遍(高层)。 以 ctx7 setup 为例:进程启动 → commander 解析出 setup 子命令 →
preAction 钩子可能改后端地址、提示升级 → 进入 setupCommand:先问"MCP 还是 CLI 模式" →
探测/选择要装的 agent → 登录换一把 API Key → 对每个 agent 写 配置 + 装技能 + 写规则 → 打印结果。
3. 核心机制(逐个讲)
3.1 入口:一个 commander 程序,两个全局钩子
它要解决的小问题: 所有子命令都需要两件公共事——能被 --base-url 重定向到测试后端、
能在合适时机提示"有新版本"。放进全局钩子,子命令就不必各自操心。
src/index.ts:20-37 把这些挂在根命令上:
program
.name("ctx7")
.version(VERSION, "-v, --version")
.option("--base-url <url>")
.hook("preAction", (thisCommand) => { // 钩子一:重定向后端
const opts = thisCommand.opts();
if (opts.baseUrl) { setBaseUrl(opts.baseUrl); setAuthBaseUrl(opts.baseUrl); }
})
.hook("preAction", async (_c, actionCommand) => { // 钩子二:升级提示
await maybeShowUpgradeNotice({ actionName: actionCommand.name(), argv: process.argv });
});
--base-url钩子调setBaseUrl(utils/api.ts:23)+setAuthBaseUrl(commands/auth.ts:21), 把默认的https://context7.com换掉——测试和自建后端靠它(src/index.ts:25-31)。- 第二个钩子
maybeShowUpgradeNotice(commands/upgrade.ts:71)只在交互式 TTY、且非upgrade命令本身时才提示,避免污染管道输出。
banner: 无子命令时,program.action 用 figlet 打印 ASCII 大字 "Context7" 和快速上手提示
(src/index.ts:67-81)。最后 await program.parseAsync() 启动整台机器(src/index.ts:83)。
所有子命令的注册集中在 src/index.ts:59-65:skill / auth / setup / remove / docs / upgrade 各一个
register* 函数 。
3.2 查询命令:library 找 ID,docs 拉文档
它要解决的小问题: Context7 的文档接口只认库 ID(/facebook/react),但人只记得住名字
("react")。所以查文档天然是两步:先把名字解析成 ID,再用 ID 拉文档。这正是
docs.ts 提供的两个命令(registerDocsCommands,commands/docs.ts:211)。
第一步 library。 resolveCommand(commands/docs.ts:46)调 resolveLibrary
(utils/api.ts:283)打 /api/v2/libs/search,把返回的候选逐个用 formatLibraryResult 排版
(commands/docs.ts:21-44)。
其中一个巧妙的小函数是声誉分级 getReputationLabel(commands/docs.ts:14-19):后端给的
trustScore 是个数字,直接暴露给人没意义,于是映射成三档标签——
| trustScore 范围 | 显示标签 |
|---|---|
>= 7 | High |
>= 4(且 < 7) | Medium |
>= 0(且 < 4) | Low |
undefined 或 < 0 | Unknown |
第二步 docs。 queryCommand(commands/docs.ts:111)先做两道校验/修复:
- 恢复被 Git Bash 改坏的库 ID。 Windows 上 Git Bash 会把
/facebook/react这种 前导斜杠参数误当成路径、改写成C:/Program Files/Git/facebook/react。recoverLibraryId(utils/library-id.ts:8)把它还原;还支持//owner/repo这种"双斜杠 逃逸写法"(commands/docs.ts:119)。 - 格式校验。 库 ID 必须形如
/owner/repo,否则报错并提示先跑ctx7 library(commands/docs.ts:121-132);在 win32 上额外提示用双斜杠绕过路径转换。
校验通过后调 getLibraryContext(utils/api.ts:316)。输出有两态: --json 走结构化
JSON;默认走 txt,后端直接返回排好版的纯文本,CLI 原样 console.log(commands/docs.ts:148-152)。
JSON 态才会遍历 codeSnippets / infoSnippets 自己排版(commands/docs.ts:188-208)。
重定向处理: 若库被搬走,后端返回 redirectUrl,CLI 不硬拉,而是提示新 ID + 现成命令
(commands/docs.ts:156-164)。
spinner 与 TTY。 两个命令都只在 process.stdout.isTTY 为真时才起 ora 转圈动画
(commands/docs.ts:12、59、142);非 TTY(被管道/重定向)时转而用 log.* 输出纯文本,
保证脚本里拿到干净结果。
和 MCP 是同一契约的两层皮。
library= MCP 的resolve-library-id工具,docs= MCP 的query-docs工具,底层都打utils/api.ts里同一批/api/v2/*端点(见 01 章)。 区别只在外壳:CLI 给人排版打印,MCP 给模型返回结构化结果。