跳到主要内容

ctx7 CLI:查文档 + 一键接入 + OAuth 登录

30 秒导读: ctx7packages/cli 里那支面向的命令行工具。它做两件事: (1)让你在终端里直接查库文档(ctx7 library / ctx7 docs);(2)一条命令就把 Context7 接入你的 AI 编码工具——探测你装了哪些 agent、问你走 MCP 还是 CLI 模式、 把服务器条目写进各家配置文件、装上引导技能、帮你登录拿密钥。查询命令和 MCP 服务器的两个工具共用同一套后端契约,只是换了个外壳。

本章属于 Context7 系列。同系列其它章:


1. 这是什么(零基础也能懂)

一句话定义: ctx7 是 Context7 的命令行客户端——一个用 npx ctx7 就能跑起来的 小工具,既能当"查文档的搜索框",又能当"把 Context7 装进你编码工具的安装器"。

解决什么问题 / 给谁用。 假设你在用 Claude Code、Cursor、Codex 这类 AI 编码工具写代码。 你希望它回答"React 的 useEffect 怎么清理副作用"时,别用两年前训练数据里的旧知识,而是去 拉当前官方文档。要做到这点,得先把 Context7 "接进"你的工具——这活儿手动配置很烦 (每家工具配置文件格式还都不一样)。ctx7 setup 把这一步变成一条命令。

它能做什么(功能一览):

能力命令干什么
查库 IDctx7 library <名字>把"react"这种名字解析成 Context7 库 ID /facebook/react
查文档ctx7 docs <库ID> "<问题>"按问题拉该库最相关的文档片段
一键接入ctx7 setup探测 agent → 选模式 → 写配置/装技能 → 登录
卸载ctx7 remove反向清掉配置、规则、技能
登录ctx7 login / whoami / logoutOAuth 设备码登录,拿更高配额
升级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 钩子、升级提示、bannersrc/index.ts
查询命令library/docs 两个查文档命令src/commands/docs.ts
接入命令端到端接入链(探测→选模式→写配置→登录)src/commands/setup.ts
agent 配置表6 家 agent 各自的规则/技能/MCP 路径src/setup/agents.ts
配置写入器把 Context7 条目合并进各家 JSON/TOMLsrc/setup/mcp-writer.ts
模板/规则拉 rule 正文、给 Codex/Cursor 定制src/setup/templates.ts
技能安装器写技能文件、防目录穿越、symlinksrc/utils/installer.ts
认证命令OAuth 设备流登录、whoamisrc/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.actionfiglet 打印 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:218)。

第一步 library resolveCommand(commands/docs.ts:52)调 resolveLibrary (utils/api.ts:283)打 /api/v2/libs/search,把返回的候选逐个用 formatLibraryResult 排版 (commands/docs.ts:27)。

其中一个巧妙的小函数是声誉分级 getReputationLabel(commands/docs.ts:14-19):后端给的 trustScore 是个数字,直接暴露给人没意义,于是映射成三档标签——

trustScore 范围显示标签
>= 7High
>= 4(且 < 7)Medium
>= 0(且 < 4)Low
undefined< 0Unknown

第二步 docs queryCommand(commands/docs.ts:117)先做两道校验/修复:

  1. 恢复被 Git Bash 改坏的库 ID。 Windows 上 Git Bash 会把 /facebook/react 这种 前导斜杠参数误当成路径、改写成 C:/Program Files/Git/facebook/reactrecoverLibraryId(utils/library-id.ts:8)把它还原;还支持 //owner/repo 这种"双斜杠 逃逸写法"(commands/docs.ts:125)。
  2. 格式校验。 库 ID 必须形如 /owner/repo,否则报错并提示先跑 ctx7 library (commands/docs.ts:127-138);在 win32 上额外提示用双斜杠绕过路径转换。

校验通过后调 getLibraryContext(utils/api.ts:316)。输出有两态: --json 走结构化 JSON;默认走 txt,后端直接返回排好版的纯文本,CLI 原样 console.log(commands/docs.ts:155-159)。 JSON 态才会遍历 codeSnippets / infoSnippets 自己排版(commands/docs.ts:195-215)。

重定向处理: 若库被搬走,后端返回 redirectUrl,CLI 不硬拉,而是提示新 ID + 现成命令 (commands/docs.ts:163-171)。

spinner 与 TTY。 两个命令都只在 process.stdout.isTTY 为真时才起 ora 转圈动画 (commands/docs.ts:1259142);非 TTY(被管道/重定向)时转而用 log.* 输出纯文本, 保证脚本里拿到干净结果。

和 MCP 是同一契约的两层皮。 library = MCP 的 resolve-library-id 工具,docs = MCP 的 query-docs 工具,底层都打 utils/api.ts 里同一批 /api/v2/* 端点(见 01 章)。 区别只在外壳:CLI 给人排版打印,MCP 给模型返回结构化结果。


3.3 接入链:setup 如何"探测→选模式→写配置/装技能→登录"

这是整个 CLI 工程含量最高的一支。setupCommand(commands/setup.ts:533)是总调度, 下面拆成四步依次讲。

第 0 步:选模式(MCP vs CLI)。 resolveMode(commands/setup.ts:145)决定走哪条路:

  • 显式 --cli → CLI 模式;
  • --mcp / -y / --oauth / --stdio 任一 → MCP 模式;
  • 都没给 → 交互式二选一菜单。

两种模式的差别:

MCP 模式CLI + Skills 模式
agent 怎么用通过 MCP 协议调 Context7 工具被技能引导去跑 ctx7 CLI 命令
写什么MCP 服务器条目 + 规则 + context7-mcp 技能find-docs 技能 + 规则(不写 MCP 服务器)
入口函数setupMcp(setup.ts:403)setupCli(setup.ts:482)

第 1 步:探测/选 agent。 resolveAgents(commands/setup.ts:211)三级决策:

显式传了 --claude/--cursor/... ? ── 是 ──► 直接用这些
│否
detectAgents(scope) 探测到已装的 ── 且 -y ──► 直接用探测到的
│否/无 -y
弹多选框让用户勾 ────────► 用户选的

探测靠 detectAgents(setup/agents.ts:288):遍历每家 agent 的 detect.projectPaths / detect.globalPaths,只要有一个路径存在(如 ~/.cursor 目录在),就认为装了这家。

第 2 步(MCP):登录换 API Key。 resolveAuth(commands/setup.ts:136)决定认证方式: --api-key 直接用;--oauth 走 OAuth 端点;否则 authenticateAndGenerateKey (commands/setup.ts:102)——先拿有效 access token(没有就 performLogin 登录),再 POST /api/dashboard/api-keys 现场生成一把新 API Key(名字带随机后缀 ctx7-cli-<hex>, setup.ts:116)。这样写进配置文件的是长期 API Key,而非会过期的 OAuth token。

第 3 步:逐个 agent 落地。 setupAgent(commands/setup.ts:293)对每家 agent 做三件事—— 写 MCP 配置、写规则、装技能(下节 3.4 讲配置写入细节):

  • MCP 配置:mcp.projectPaths/globalPaths 选出目标文件路径 resolveMcpPath; .tomlappendTomlServer,其余走 readJsonConfig + mergeServerEntry + writeJsonConfig
  • 规则: installRule(commands/setup.ts:229)——rule 有两种 kind:"file" 写一个独立 规则文件(如 Claude 的 .claude/rules/context7.md);"append" 往共享的 AGENTS.md/GEMINI.md 里插一段带 <!-- context7 --> 标记的区块,已存在就正则替换、不存在就追加(setup.ts:259-270)。
  • 技能: downloadSkill("/upstash/context7", agent.skill.name)(utils/api.ts:63)拉技能文件, 再 installSkillFiles 写盘(commands/setup.ts:366-370)。

CLI 模式的对应流程。 setupCli(setup.ts:482)先 resolveCliAuth(有 API Key 就存成 token, 否则登录),再下载一次 find-docs 技能、对每个 agent 调 setupCliAgent(setup.ts:447): 用 customizeSkillFilesForAgent 给 Codex 打补丁后安装,并写 "cli" 模式的规则。


3.4 配置写入器:把一个条目安全塞进六种格式

它要解决的小问题: 六家 agent 的 MCP 配置格式各不相同——大多是 JSON,Codex 是 TOML, 键名有的叫 mcpServers、有的叫 mcp / mcp_servers,条目结构有的要 type:"http"、有的要 serverUrl / httpUrlsetup/mcp-writer.ts 把"合并一个条目进去、别弄坏用户已有配置"这件事 封装干净。

JSON 路径。 readJsonConfig(mcp-writer.ts:30)读文件,先 stripJsonComments 去掉 ///* */ 注释(为了兼容 OpenCode 的 .jsonc,mcp-writer.ts:5-28); mergeServerEntry(mcp-writer.ts:44)在指定 configKey 下加/覆盖 context7 键,并回报 alreadyExists(用来区分文案 "configured" vs "reconfigured");writeJsonConfig(mcp-writer.ts:102) 以两空格缩进写回。

TOML 路径(Codex)。 appendTomlServer(mcp-writer.ts:250)手写 TOML——因为要精确替换 [mcp_servers.context7] 这一块而保留文件其余部分和它的子表([...context7.http_headers])。 buildTomlServerBlock(mcp-writer.ts:230)把 headers 单独渲染成 http_headers 子表。

每家 agent 的条目形状agents.ts 里各自的 buildEntry 决定。以 HTTP 传输为例:

agentconfigKeyHTTP 条目形状
claudemcpServers{ type:"http", url }
cursormcpServers{ url }
opencodemcp{ type:"remote", url, enabled:true }
codexmcp_servers{ type:"http", url }(TOML)
antigravitymcpServers{ serverUrl }
geminimcpServers{ httpUrl }

URL 由 mcpUrl 决定:OAuth 模式用 .../mcp/oauth,否则 .../mcp(agents.ts:82-84); API Key 模式则由 withHeaders(agents.ts:86-91)在条目上挂 headers.CONTEXT7_API_KEY

stdio 传输的巧处:保留用户手改。 --stdio 让 MCP 跑成本地 npx @upstash/context7-mcp 进程。 问题是用户可能自己 pin 了版本(@upstash/context7-mcp@latest)。所以 resolveEntryToWrite (commands/setup.ts:280)先探测已有条目:若已是 stdio 形态(isStdioContext7Entry, mcp-writer.ts:168),就只调 patchStdioApiKey(mcp-writer.ts:216)换掉 --api-key 那一对参数、 其余原样保留;否则才用 agent 的标准形状重建。


3.5 SetupAgent 表:六家 agent 的差异全在一张表里

它要解决的小问题: 上面每一步(探测、写配置、写规则、装技能)对六家 agent 都得走一遍, 且路径、键名、文件名各不相同。与其在流程里散落 if agent === "cursor",不如把差异收进一张 声明式的数据表——setup/agents.tsagents 记录(agents.ts:93),每家一个 AgentConfig (接口在 agents.ts:62)。

SetupAgent 联合类型枚举了六家(agents.ts:5):claude / cursor / opencode / codex / antigravity / gemini。每个 AgentConfig 声明四组信息:

字段装什么例(cursor)
mcpMCP 配置路径 + 键名 + 条目构造器项目 .cursor/mcp.json,键 mcpServers
rule规则文件名/类型(file 还是 append)file 类型,context7.mdc
skill技能名 + 安装目录context7-mcp,.cursor/skills
detect探测"这家装没装"用的路径~/.cursor 存在即算装了

getAgent(agents.ts:273)按名取表,ALL_AGENT_NAMES(agents.ts:277)供菜单遍历。

一个值得记的边界:Antigravity 没有项目级 MCP。 它的 mcp.projectPaths 是空数组 (agents.ts:224),因为它只从全局 ~/.gemini/config/mcp_config.json 读 MCP。于是 setupAgent 里遇到空 projectPaths回退到全局路径(commands/setup.ts:309-312),卸载时同理直接跳过 项目级(commands/remove.ts:196328)。


3.6 规则模板:同一份提示词,给不同 agent 微调

它要解决的小问题: 装进各 agent 的"规则"(告诉模型何时该用 Context7)正文其实是同一段 提示词,但个别 agent 需要微调:Cursor 要 frontmatter,Codex 要加沙箱提示。setup/templates.ts 负责取正文并做这些定制。

getRuleContent(templates.ts:53)按模式选文件名和兜底文案,fetchRule(templates.ts:41) 从 GitHub raw 拉 context7-mcp.md / context7-cli.md;两个 URL(master/main)都失败时用内置的 FALLBACK_MCP(templates.ts:6)/ FALLBACK_CLI(templates.ts:18)兜底——离线也能装

两处定制(templates.ts:58-62):

  • Cursor 前面拼 CURSOR_FRONTMATTER(---\nalwaysApply: true\n---),让规则始终生效。
  • Codex + CLI 模式 追加 CODEX_CLI_SANDBOX_GUIDANCE(templates.ts:37):提示 Codex 在沙箱外 跑 Context7 命令,免得 DNS/网络被沙箱挡住。

技能文件也有对应定制:customizeSkillFilesForAgent(templates.ts:65)只对 codex + find-docsSKILL.md 生效,把沙箱提示插到 ## Step 1 前(templates.ts:79-87)。


3.7 技能安装器:防目录穿越的写盘

它要解决的小问题: 技能文件来自远端(GitHub / 后端),文件里的 path 字段不可全信—— 恶意 ../../etc/xxx 能写到目标目录外。utils/installer.ts 在写盘前做两道防护。

installSkillFiles(installer.ts:7):

  1. assertSkillNameInRoot(utils/skill-name.ts:14)先校验技能名安全(白名单正则、不含 ../\0、 resolve 后必须仍在 root 下),得到 skillDir
  2. 对每个文件,resolve(skillDir, file.path) 后检查结果路径必须仍以 skillDir/ 开头,否则抛 "resolves outside the target directory"(installer.ts:18-24)。

symlinkSkill(installer.ts:33)用于多目标安装:主目录真装一份,其余目录 symlink 过去,省空间。


3.8 OAuth 设备流登录:终端里没浏览器怎么办

它要解决的小问题: CLI 跑在终端,没有浏览器回调地址,标准 OAuth 授权码流玩不转。解法是 RFC 8628 设备授权流:CLI 拿一个短用户码,让你去 浏览器输码授权,CLI 这边轮询等结果。

performLogin(commands/auth.ts:111)是整条流水线,三段:

① startDeviceAuthorization ─► 拿 user_code + verification_uri (+ device_code)
② 渲染代码框 + 打开浏览器 ─► renderDeviceCodeBox / open(target)
③ 循环 pollDeviceToken ─► approved 就 saveTokens,否则按状态调节奏
  • ① 取码: startDeviceAuthorization(utils/auth.ts:153)POST /api/oauth/device/code, 还捎上 hostname 让授权页显示"你正在授权哪台机器"(RFC 8628 §5.4 反钓鱼,utils/auth.ts:158-166)。
  • ② 展示: renderDeviceCodeBox(commands/auth.ts:49)用 boxen 画框;即使有 verification_uri_complete(带码直链)也仍显示裸 verification_uri,照顾读屏/纸笔用户 (commands/auth.ts:56-60)。waitForEnter 等你按回车再开浏览器(commands/auth.ts:72)。
  • ③ 轮询: pollDeviceToken(utils/auth.ts:188)POST /api/oauth/device/token,把服务器返回 归一成六种状态。CLI 据此调节:
poll 状态来源performLogin 的反应
approved200 + tokenssaveTokens 并成功返回(auth.ts:155-160)
pendingauthorization_pending保持原节奏继续轮询
slow_downslow_down间隔 +5s(auth.ts:161-164)
transient网络错 / 5xx间隔 +5s 继续(RFC §3.5,auth.ts:173-179)
deniedaccess_denied失败退出
expiredexpired_token失败退出

服务器不给 interval 时默认 5 秒(DEFAULT_DEVICE_POLL_INTERVAL_SECONDS,utils/auth.ts:151)。

登录成功后: announceIdentity(commands/auth.ts:97)调 fetchWhoami(commands/auth.ts:254, 打 /api/dashboard/whoami)显示"Logged in as <邮箱> (<团队>)"。whoami 命令(commands/auth.ts:219) 和 logout(commands/auth.ts:210)是这套的配套。


3.9 Token 存取与"密钥 or OAuth"双轨

它要解决的小问题: 老版本(0.5 前)登录存的是会过期、带 refresh_token 的 OAuth token; 新版本存的是长期 API Key。同一套 utils/auth.ts 要兼容两者。

  • saveTokens(utils/auth.ts:34)写 credentials.json,强制 0o600 权限——凭据绝不能被 同组/其他用户读到(utils/auth.ts:3243-45);目录也 0o700(utils/auth.ts:26)。 文件位置由 storage-paths.ts 给(XDG 目录,并从旧的 ~/.context7/ 迁移)。
  • isTokenExpired(utils/auth.ts:80):没 expires_at 视为永不过期(API Key 的情形); 有则留 60 秒余量提前判过期。
  • getValidAccessToken(utils/auth.ts:112):未过期直接返回;过期且有 refresh_token 才走 /api/oauth/token 刷新(utils/auth.ts:87);过期又无 refresh(API Key 情形)返回 null。

查询命令用的是更轻的 getAccessToken(commands/docs.ts:21):loadTokens + isTokenExpired, 过期就当匿名(降级到低配额),而非阻塞去刷新——查文档不该被登录卡住。

认证头的优先级。 getAuthHeaders(utils/api.ts:267)统一给所有查询请求加头: 环境变量 CONTEXT7_API_KEY 优先于登录 token(utils/api.ts:274-279),另带一组 X-Context7-* 标识来源为 CLI。


4. 其它命令(择要)

  • remove(commands/remove.ts:70)。setup 的镜像:探测已配置的 agent (detectConfiguredAgents,remove.ts:286,查是否有 MCP 条目/规则/技能),按模式反向清理—— removeServerEntry(mcp-writer.ts:65,删空 configKey 时把键也删掉)、uninstallRule 删掉 <!-- context7 --> 区块、uninstallSkills 删技能目录。别名 uninstall(remove.ts:73)。
  • upgrade(commands/upgrade.ts:22)。detectInstallMethod(utils/update-check.ts:108) 从 execPath/npm_config_user_agent 认出你是 npm-global / pnpm-global / bun-global / npx 哪种装法, getUpgradePlan(update-check.ts:127)给出对应升级命令;npx 这类临时运行器 canRun:false、 只提示用 @latest,能装的才真正 spawn 跑升级(upgrade.ts:177)。
  • skills ...(已废弃)(commands/skill.ts:101,命令隐藏)。旧的 Skill Hub 命令树 (install/search/list/remove/suggest/generate),每次调用先打废弃警告 warnSkillHubDeprecated (skill.ts:66)。安装逻辑(下载→装主目录→symlink 其余)和 setup 复用同一批 installer 工具。 代码里多处 TODO(deprecate-skills-phase-2) 标记待删(如 skill.ts:63)。
  • generate(commands/generate.ts:41,挂在 skills 下)。AI 生成技能:登录 → 查配额 (getSkillQuota)→ 问"想让 agent 精通什么" → 选来源库 → 流式生成 → 预览/编辑/反馈重生成 → 装。

5. 巧妙之处(可借鉴的技术)

  • 一份契约,两层外壳。 library/docs 命令和 MCP 的两个工具打的是同一批 /api/v2/* 端点 (utils/api.ts:283316);CLI 只负责给人排版。想加个查询前端?套壳即可,不碰后端。
  • 差异收进声明式表。 六家 agent 的路径/键名/文件名全在 agents.tsagents 记录里 (agents.ts:93);流程代码只认 AgentConfig 字段,加第七家 agent 只需加一条数据,不改流程。
  • 精确改配置,不覆盖用户的手改。 stdio 场景只换 --api-key 那对参数(patchStdioApiKey, mcp-writer.ts:216);TOML 只替换 [mcp_servers.context7] 这一块并保子表(appendTomlServer, mcp-writer.ts:250)——把"合并进已有文件"当一等公民对待。
  • 离线可装。 规则正文拉不到就用内置 FALLBACK_* 文案(templates.ts:41-51),网络抖动不致命。
  • 凭据最小权限 + 兜底 chmod。 0o600 写、且对已存在文件显式再 chmodSync(utils/auth.ts:43-45), 因为 writeFileSyncmode 对已存在文件无效——一个真实踩过的坑。
  • TTY 感知输出。 有 TTY 才转圈(ora),无 TTY 走纯文本 log.*(commands/docs.ts:1259), 脚本管道拿到的结果干净可解析。
  • 写盘防目录穿越。 远端文件的相对路径 resolve 后必须仍在目标目录内(installer.ts:18-24)。

6. 边界与局限

  • 改配置默认全局。 不加 -p/--project 就写全局配置(setup.ts:485539);Antigravity 干脆 没有项目级 MCP(agents.ts:224)。
  • stdio 与 oauth 互斥。 --stdio + --oauth 直接报错拒绝(setup.ts:405-408),因为 OAuth 只走 托管 HTTP 端点。
  • 配置写入是尽力而为,单点失败不阻塞整体。 某个 agent 的 MCP/规则/技能任一步失败,记成 failed: ... 继续下一步/下一家,最后统一打印(如 setup.ts:343-345372-373),不整体回滚。
  • JSONC 是自写的极简去注释器(stripJsonComments,mcp-writer.ts:5),不是完整 JSON5 解析器; TOML 的读写也是面向 Context7 条目的手写逻辑(readTomlServerEntry,mcp-writer.ts:126), 不解析任意 TOML。
  • skills 命令树已废弃,下个大版本会停(skill.ts:60-68)。
  • Git Bash 恢复靠启发式。 只认 Git/PortableGit/git-bash 安装目录模式(library-id.ts:20), 非常规安装路径可能恢复不了,故还留了 //owner/repo 手动逃逸。

7. 横向对比

同系列里,本章讲的是 Context7 面向人的外壳;02 章面向模型的 MCP 外壳。两者共享 01 章的 API 契约。04 章讲把同一契约 包成 AI-SDK 工具、以及跨端共享的提示词设计——setup 装的那些规则/技能正文,与 04 章的提示词同源。 05 章讲 Skills/Plugins/Rules 作为分发产物,以及 MCP 与 CLI 两种交付 模式的取舍——setupresolveMode 正是这两种模式在 CLI 里的落地入口。


8. 代码地图(导航索引)

主题文件路径符号名
程序入口 / 全局钩子 / bannerpackages/cli/src/index.tsprogramsetBaseUrlmaybeShowUpgradeNotice
查询命令注册packages/cli/src/commands/docs.tsregisterDocsCommands
名字→ID / 文档查询packages/cli/src/commands/docs.tsresolveCommandqueryCommand
声誉分级 / 结果排版packages/cli/src/commands/docs.tsgetReputationLabelformatLibraryResult
Git Bash 库 ID 恢复packages/cli/src/utils/library-id.tsrecoverLibraryId
HTTP 客户端 / 认证头packages/cli/src/utils/api.tsresolveLibrarygetLibraryContextgetAuthHeadersdownloadSkill
接入总调度packages/cli/src/commands/setup.tssetupCommandresolveModeresolveAgents
MCP / CLI 两模式落地packages/cli/src/commands/setup.tssetupMcpsetupAgentsetupClisetupCliAgent
认证换 Key / 规则安装packages/cli/src/commands/setup.tsauthenticateAndGenerateKeyresolveAuthinstallRule
stdio 条目补丁选择packages/cli/src/commands/setup.tsresolveEntryToWrite
六家 agent 配置表packages/cli/src/setup/agents.tsagentsAgentConfiggetAgentdetectAgentsmcpUrlwithHeaders
配置写入 (JSON)packages/cli/src/setup/mcp-writer.tsreadJsonConfigmergeServerEntrywriteJsonConfigremoveServerEntry
配置写入 (TOML)packages/cli/src/setup/mcp-writer.tsappendTomlServerbuildTomlServerBlockreadTomlServerEntryremoveTomlServer
stdio 条目探测/补丁packages/cli/src/setup/mcp-writer.tsisStdioContext7EntrypatchStdioApiKeygetJsonServerEntry
规则正文 / agent 定制packages/cli/src/setup/templates.tsgetRuleContentfetchRulecustomizeSkillFilesForAgentFALLBACK_MCPFALLBACK_CLI
技能写盘 / symlinkpackages/cli/src/utils/installer.tsinstallSkillFilessymlinkSkill
技能名安全校验packages/cli/src/utils/skill-name.tsassertSkillNameInRootisSafeSkillName
OAuth 登录命令packages/cli/src/commands/auth.tsperformLoginrenderDeviceCodeBoxannounceIdentityfetchWhoamiwhoamiCommand
Token 存取 / 设备流底层packages/cli/src/utils/auth.tssaveTokensloadTokensisTokenExpiredgetValidAccessTokenstartDeviceAuthorizationpollDeviceToken
卸载packages/cli/src/commands/remove.tsremoveCommanddetectConfiguredAgentsuninstallAgent
升级packages/cli/src/commands/upgrade.tsupgradeCommandmaybeShowUpgradeNotice
安装方式探测 / 升级计划packages/cli/src/utils/update-check.tsdetectInstallMethodgetUpgradePlan
废弃 Skill Hub 命令树packages/cli/src/commands/skill.tsregisterSkillCommandsinstallCommandwarnSkillHubDeprecated
AI 生成技能packages/cli/src/commands/generate.tsregisterGenerateCommandgenerateCommand
CLI 客户端 IDpackages/cli/src/constants.tsCLI_CLIENT_ID