关于 marginalia
marginalia 是用于为 TypeScript API 和复杂代码补充精简、高价值 JSDoc 的 Agent 技能。它面向希望改善 IDE 悬停说明、声明文件和生成式 API 参考文档的开发者,强调在恰当边界记录信息。
主要功能
- 01公共 API 文档编写指导
- 02精简 JSDoc 与 TSDoc 规范
- 03导出符号审查流程
- 04生成式 API 参考文档建议
- 05验证与完成检查
适用场景
- 01编写 TypeScript 包的公共 API 文档
- 02改善 IDE 悬停说明和声明文件
- 03审查复杂内部代码的注释
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ howells/ skills --skill marginalia安装后在 Claude Code 中输入/marginalia确认已加载。
附带文件agents/openai.yaml
详细介绍
Marginalia
使用此技能添加高信号量的 JSDoc,帮助读者、IDE、声明文件和生成的 API 文档。目标不是处处添加注释,而是在恰当的位置提供简洁文档。过长的 JSDoc 会让 IDE 悬停提示更难阅读,因此应优先用最短的注释解释缺失的上下文。
对于 TypeScript 包的 API,应将 JSDoc 视为 API 参考资料的唯一来源,而不是已编写文档的替代品。Props、导出类型、默认值、约束、回调契约和弃用信息应放在公共声明附近,以确保 IDE 悬停提示、.d.ts 输出和生成的文档保持一致。使用指南、示例、概念说明、迁移说明和操作方案通常应放在 README 或网站文档中。
开始
调用时:
- 说明你正在使用
marginalia技能。 - 确定文档目标:
- 公共包 API
- 包或模块中的所有导出项
- 仅复杂的内部代码
- React 组件、钩子、工具、类或类型
- 生成的文档或 IDE 悬停提示质量
- 如果用户未指定文件、符号、包或范围,请先提出一个简洁的澄清问题,再进行编辑。只有当请求明确提到包文档、发布文档、生成的 API 文档,或包的 IDE 悬停提示质量时,才推断为公共 API 文档检查。
- 编辑前阅读适当范围的内容:
- 定向检查:请求指定的文件或符号、附近的类型,以及一个相关用法或测试(若有)
- 公共 API 检查:
package.json导出项和类型、公共入口、barrel 文件、tsconfig*、文档工具、README/示例,以及有代表性的调用点 - 复杂内部代码检查:实现、测试,以及能揭示行为的调用方
不要仅凭名称推断行为。有实现时,应阅读实现代码和至少一种用法路径。
文档密度
选择足以满足请求的最低文档密度。
- 公共 API 检查: 考虑所有可从包入口访问的导出符号。仅在能说明行为、约束、用法或 API 意图时添加 JSDoc;对显而易见的导出项记录为
leave。 - 有意义的检查: 为导出符号以及复杂的内部函数、棘手类型、重载、状态机、生命周期行为、副作用和非显而易见的约束编写文档。
- 定向检查: 仅为指定的文件、组件或符号编写文档。
有意义的检查和定向检查应复用包 API 工作流的第 2 至 4 步(决定、编写、验证),而不必执行第 1 步的完整公共 API 清点。
避免为显而易见的局部变量、简单的单行包装函数,以及类型签名已足以说明一切的代码添加通用注释。
文档内容
优先记录:
- 具有非显而易见语义的导出函数、类、常量、React 组件、钩子和类型
- 重载、泛型、条件类型、映射类型、品牌类型和回调契约
- 当 IDE 自动补全应为使用者提供指引时,记录选项对象和配置字段
- 副作用、抛出的错误、异步行为、缓存、生命周期、清理、顺序和幂等性
- 单位、范围、默认值、稳定性保证、运行时环境,以及 SSR/客户端约束
- 弃用、实验性 API,以及仓库约定中仅供内部使用的导出项
对于已发布的包,应聚焦 exports 中包含的符号和生成的 .d.ts 文件。只有当内部辅助项足够复杂、维护者能从中受益时,才需要为其添加 JSDoc。
对于生成的 API 文档,如果默认值和行为约束无法仅从类型中看出,应在注释中明确说明。优先使用标准的、兼容 TSDoc 的标签,例如 @remarks、@defaultValue、@example、@deprecated、@see 和发布阶段标签(若仓库的工具链支持)。
注释规则
编写能够补充类型系统无法表达的信息的注释。注释应简短到适合在 IDE 悬停时阅读。
简洁规则:
- 简单的公共 API 优先使用一个句子。
- 描述行为或限制时,使用一个简短摘要,再加一个简短段落。
- 谨慎使用示例;仅在示例能避免常见误用时加入。
- 将冗长的概念性内容拆分到外部文档中,而不是放进 JSDoc。
- 如果悬停提示读起来像篇文章,就精简内容。
良好的 JSDoc:
/**
* Builds a stable cache key for a request.
*
* The key includes the normalized URL and sorted query params so equivalent
* requests dedupe even when callers pass params in different orders.
*/
export function createRequestKey(input: RequestInput): string {
// ...
}
避免:
/** Gets the user. */
export function getUser(id: string): User;
规则:
- 以简洁的摘要句开头。
- 只有在需要说明重要行为、限制或示例时,才添加第二段。
- 当 TypeScript 中的名称和类型已足够清楚时,优先使用普通说明文字,而不是冗余的
@param标签。 - 对公共 API,如果参数含义无法仅凭名称明确判断,或函数有多个位置参数、回调、选项、单位、默认值、副作用或重载语义,请使用
@param。 - 仅当返回语义无法从类型中明确判断时,才使用
@returns。 - 对导出的泛型,如果类型参数的作用、限制、推断行为、默认值或参数间的关系不明确,请使用
@typeParam。 - 当仓库的工具链或文档使用
@throws、@deprecated、@example、@remarks、@defaultValue、@see、@internal、@public、@alpha或@beta时,请使用这些标签。 - 在 TypeScript 源文件中,不要在
@param或@returns注释中重复声明的类型。在纯 JavaScript 中,JSDoc 类型注释会为 IDE 和checkJs提供类型信息;请保留这些注释,并在需要时补充。 - 不要添加仅仅复述函数名称的注释。
- 编写文档时不要改变运行时行为。
当项目中存在 TypeDoc、API Extractor 或 TSDoc 规范时,请遵循仓库已有的标签风格,保留发布标签,除非已配置,否则避免使用非标准标签;条件允许时,运行现有的文档或 API 报告检查。
生成的 API 参考文档
当文档目标是生成的 API 文档或单一来源的包文档时:
- 将公共源代码声明视为 API 参考文档的权威来源。
- 先检查现有文档工具,例如 TypeDoc、API Extractor、React docgen、声明文件汇总工具或自定义站点生成器。
- 优先使用结构化工具,而不是通过临时的字符串匹配来解析注释。
- 将生成的 API 表格和参考资料与编写的示例、指南及概念性文案分开。
- 在结束这项工作前,确认注释能保留在包的声明或文档生成流程中。
- 如果没有文档工具,请提出生成文档的计划;除非用户要求实现,否则不要添加新工具。
常见划分:
- JSDoc/TSDoc: API 表格、属性说明、导出类型文档、回调约定、默认值、限制、IDE 悬停文本。
- 编写的文档: 安装、快速入门、组合示例、设计原理、迁移指南、操作指南和屏幕截图。
包 API 工作流
1. 构建公共接口
列出通过以下方式公开的符号:
package.json中的exportstypes、typings或声明文件入口- 根 barrel 文件
- 有意设置的子路径导出
可用的搜索方式:
rg '^\s*export\b' -g '*.{ts,tsx,js,jsx,mts,cts,d.ts}'
rg '"(exports|types|typings|main|module|browser)"' -g 'package.json'
rg '^\s*(module\.exports|exports\.)' -g '*.{js,cjs,cts}'
rg '@public|@internal|@deprecated|@alpha|@beta|@remarks|@example' -g '*.{ts,tsx,js,jsx}'
对于每个公共符号,记录它是否已有实用的 JSDoc,以及声明文件输出是否会保留这些注释。
进行全包范围的修改前,先做一份轻量级清单:
| Symbol | Source file | Export path | Existing JSDoc | Decision | Reason |
| --- | --- | --- | --- | --- | --- |
2. 判断哪些内容需要 JSDoc
对每个候选项进行分类:
- add:缺少实用的公共 API 文档
- improve:现有注释已过时、含糊不清或重复描述类型
- leave:签名和命名已足够清楚
- skip:没有重要隐藏行为的私有或简单辅助函数
如果用户要求“全部”,应将其理解为涵盖所有有意义的导出/公共符号,除非用户明确要求详尽注释。
3. 编写注释
让注释紧邻消费者看到的导出声明。对于重载,将共享文档放在第一个重载或导出声明上;对于行为不同的重载,分别编写文档;不要依赖实现签名上的 JSDoc 为消费者提供文档。
对于 React 组件和钩子:
- 说明组件或钩子的用途和关键行为
- 如果存在导出的属性接口,说明重要属性
- 说明受控/非受控行为、无障碍方面的预期、SSR/客户端要求以及副作用
- 如果属性名称和类型已足以说明问题,避免为每个视觉属性都编写文档
对于类型和接口:
- 说明接口的用途
- 当用户需要在字段之间做选择、默认值很重要、字段会影响运行时行为,或字段定义了回调约定时,说明这些字段
- 不必说明一目了然的结构字段
- 复杂配置对象优先使用示例
此外,也要检查属于包 API 的导出 const 断言、令牌映射、架构、类似命名空间的对象、可辨识联合以及推断出的公开类型。
4. 验证
从 package.json 脚本、工作区包脚本或现有 CI/文档配置中选择命令。不要为了验证注释而臆造新工具。
运行范围最小且有意义的检查:
- 对涉及的包进行类型检查
- 如果注释会被 lint 检查,则运行 lint/格式检查
- 如果声明文件输出很重要,则构建相关包
- 如果代码库使用 TypeDoc、API Extractor 或类似工具,则生成 API 文档
- 如果目标是发布质量或 IDE 悬停提示质量,则检查生成的
.d.ts或文档输出
要确保声明文件保留注释,请检查相关编译器/文档设置,例如 removeComments、声明文件生成、生成的 .d.ts 入口、重新导出的符号、stripInternal、API Extractor 汇总,以及经过 barrel 或子路径导出生成后文档是否仍然附着于符号。
准确报告运行过的命令。如果无法运行检查或检查范围过大,请准确说明验证了什么、没有验证什么。
输出
规划时,请提供:
- 已检查的公开 API 范围
- 要新增、改进、保留和跳过的符号
- 验证计划
对于整个包或多个模块的检查,在编辑之前先列出候选公开 API 范围和计划的文档详略程度,前提是用户要求提供计划。用户要求添加或改进文档,即已授权进行相应范围内的编辑。
实施时,最后说明:
- 修改的文件
- 编写文档的 API 类型
- 已考虑的公开符号、已添加 JSDoc、已改进 JSDoc,以及因何未编写文档的符号
- 验证结果
守则
- 不要为了形式而写注释。注释必须能教会读者一些东西。
- 不要加入未经证实、可能过时的猜测。如果行为不明确,先阅读用法或测试再写文档。
- 不要写冗长的注释,让重点淹没其中。如果重要信息不能在一两句话内呈现,请改写。
- 除非私有辅助函数复杂到确有必要,否则不要为它们详尽编写文档。
- 不要用 JSDoc 掩盖糟糕的命名。只有在用户要求重构,或重命名既必要又安全时才重命名。
- 不要加入未经类型检查或至少与实际用法一致的示例。
- 除非用户要求或代码库已有此类工具,否则不要引入生成文档的工具。
- 添加 JSDoc 时不要更改公开 API,除非用户明确要求。保留发布和弃用标签;只有在用户要求更改 API 状态时,才添加或删除
@internal、@public、@alpha、@beta或@deprecated。这些标签可能影响生成的声明文件或消费者诊断。
完成检查
结束前,请确认:
- 已考虑用户要求的公开导出符号
- 注释说明了行为、约束、示例或有助于 IDE 提示的信息
- 注释足够简洁,能改善悬停提示的可读性
- 没有仅仅复述显而易见的名称或 TypeScript 类型的注释
- 在相关情况下,生成的声明文件/文档保留了注释
- 已运行验证,或已说明验证方面的不足