【免费下载链接】repowise
Codebase intelligence for AI and humans: code health scores, auto-generated docs, git analytics, dead code detection, and architectural decisions via MCP.
Repowise 通过 MCP 与 CLI 为 AI 编程助手提供代码库智能,而这份智能落地的载体,是同时面向 Claude Code 与 Codex 两套 Agent 宿主分发的技能(Skills)与斜杠命令(Slash Commands)。plugins/shared/正是这两套插件内容的唯一事实源(single source of truth):所有技能正文、命令正文都在这里以「一个条目一个文件」的格式编写,再由一个渲染器按宿主差异生成到各自的安装目录。本文以 plugins/shared/README.md 为核心骨架,结合仓库中的生成器源码与黄金测试,讲解这套单源渲染机制的格式约定、宿主差异处理、漂移防护与维护工作流,读完你可以安全地新增、修改或下线任意一条技能或命令。
为什么需要单源:一次已经真实发生过的漂移
plugins/shared/的存在源于一次具体事故。在引入共享源之前,plugins/codex/skills/是plugins/claude-code/skills/的手抄副本,而两侧已经悄悄分叉:
- 描述被逐条改写(description 是面向各自宿主调度器的触发文本);
- 标题被重新命名(例如 "Dead Code CleanupWithRepowise" 与 "…withRepowise" 的大小写差异);
- 一个目录被改名。
最致命的是没有任何机制检测到这些差异——正如 README 所说:"两个用不同措辞表达大致相同内容的文件,单独从任何一侧看都无可挑剔"(Two files that say roughly the same thing in different words look fine from either side alone.)。这一洞察直接决定了当前架构:把正文(body)收敛为一份共享副本,让漂移从"第二次手改"变成"重新生成(regenerate)"。生成器 scripts/gen_plugin_content.py 的模块 docstring 完整记录了这段历史。
目录结构:共享源与四个生成目标
共享源只包含两类条目:
plugins/shared/ ├── README.md # 本文所依托的机制说明 ├── commands/ # 18 个斜杠命令源文件 │ ├── ask.md context.md coverage.md dead-code.md decision.md │ ├── doctor.md export.md health.md impacted-tests.md init.md │ ├── reindex.md risk.md search.md security.md status.md │ ├── symbol.md update.md why.md └── skills/ # 6 个技能源文件 ├── architectural-decisions.md ├── change-review.md ├── code-health.md ├── codebase-exploration.md ├── dead-code-cleanup.md └── pre-modification.md每个源文件渲染为四个目标,且全部是生成产物,直接编辑会触发下一轮测试失败:
| 宿主 | 技能产物 | 命令产物 |
|---|---|---|
| Claude Code | plugins/claude-code/skills/<dir>/SKILL.md | plugins/claude-code/commands/<id>.md |
| Codex | plugins/codex/skills/<dir>/SKILL.md | packages/cli/src/repowise/cli/agent_targets/_data/codex_prompts/repowise-<id>.md |
可以对照实际生成的目录验证:plugins/claude-code/skills/与plugins/codex/skills/下各有 6 个SKILL.md,其中pre-modification.md因两个宿主目录命名不一致(pre-modification对pre-modification-check),正是每宿主dir覆盖的典型实例。
渲染器的宿主模型:一处源码看懂全部差异
生成器用Host数据类(scripts/gen_plugin_content.py#L68-L104)集中描述"每个宿主把文件放哪、如何拼写自身特有语法",所有差异都收敛在这两个常量表里:
| 宿主 | 命令文件名 | 命令引用语法 | 命令 frontmatter 键 |
|---|---|---|---|
claude-code | {id}.md | /repowise:{id} | 全部保留 |
codex | repowise-{id}.md | /prompts:repowise-{id} | 仅description、argument-hint |
三个设计要点值得展开:
- Codex 命令文件名加
repowise-前缀:因为~/.codex/prompts是与用户安装的其他工具共享的扁平全局目录,命名空间化避免冲突;Claude Code 的命令目录是专属的,无需前缀。 - 命令引用占位符
{{cmd:risk}}:正文里写{{cmd:risk}},渲染时由command_reference格式化为/repowise:risk(Claude Code)或/prompts:repowise-risk(Codex),正则_TOKEN负责替换(scripts/gen_plugin_content.py#L132-L133)。 command_frontmatter_keys键白名单:Codex 的 prompt frontmatter 只定义description与argument-hint,其余键(如 Claude Code 的allowed-tools)会被剔除而不是原样输出——"向宿主输出它读不懂的键,正是让两种格式重新变成分叉的那类事情"(测试 tests/unit/cli/test_plugin_content.py#L95-L107 的 docstring 原话)。
共享源文件格式:一个条目一个文件
以 plugins/shared/skills/code-health.md 为例,共享源格式如下:
--- frontmatter: | # 供没有自有覆盖的宿主使用 description: ... claude-code: # 可选:每宿主覆盖块 dir: code-health # 输出目录,用于宿主命名不一致时 frontmatter: | # 整体替换共享 frontmatter 块 name: code-health description: > ... user-invocable: false codex: dir: code-health frontmatter: | name: code-health description: ... --- # Code Health with Repowise (正文,所有宿主共享,且是黄金测试固定比对的对象)关键约定:
- frontmatter 以原文(verbatim)存储,而非解析成键值对。这样渲染器按字节还原,不会经由 YAML dumper 重新折叠 folded scalar,避免"每次渲染都产生一个 diff"从而击碎黄金测试。这也是
select_keys采用行级过滤(按顶层键名逐行保留,附带其缩进续行)而非 parse-and-redump 的原因(scripts/gen_plugin_content.py#L162-L181)。 - 技能按宿主携带各自的 frontmatter:因为 description 是写给特定宿主调度器的触发文本,Claude Code 侧还带
user-invocable: false等专属字段。 - 命令共享同一个 frontmatter 块,再由
select_keys按宿主键白名单裁剪(见上文)。 - 正文被
_FRONTMATTER正则从---\n…\n---\n之后切出,是宿主无关的共享部分。
渲染与写入:可复现性纪律
渲染器(scripts/gen_plugin_content.py#L184-L204)输出固定槽位顺序:frontmatter、空行、body,并强制三项纪律:
- 固定槽位顺序(frontmatter、空行、body),是黄金测试可行的前提;
- 统一 LF 换行,与检出时的行尾风格无关——仓库在 Windows 上用
core.autocrlf检出,未改动的生成文件读回是 CRLF,write_if_changed会先规范化再比较(scripts/gen_plugin_content.py#L250-L263); - 绝不输出时间戳、版本号或生成器横幅——"没有变化却发生变化的文件不配当黄金"(a file that changes when nothing changed cannot be a golden)。
条目按id排序加载(load_items用sorted(...glob("*.md"))),因为目录列举在不同文件系统上顺序不稳定,排序保证了渲染的可复现性。
两个入口命令:写入与漂移检查
python scripts/gen_plugin_content.py # 写入所有生成产物 python scripts/gen_plugin_content.py --check # 报告漂移,不写任何文件--check模式逐文件与期望文本比对,并额外检查孤儿文件,有任一不一致即向 stderr 打印汇总并返回退出码 1(scripts/gen_plugin_content.py#L266-L317)。这使它可以作为 CI 门禁:tests/unit/cli/test_plugin_content.py::test_rendering_is_idempotent断言GEN.main(["--check"]) == 0,即"干净树上的 --check 必须零漂移"。
黄金测试:防分叉的最终防线
测试文件 tests/unit/cli/test_plugin_content.py 对磁盘上的生成文件(而非生成器返回值)做断言,因为"一个渲染器可以对自己从未写盘的内容完全正确"——那正是本测试要消灭的失败模式。六项核心断言:
- 逐文件黄金比对:参数化遍历
rendered_files(),磁盘文件必须与期望逐字节一致(行尾规范化后),否则报错并提示"编辑共享源后运行生成器"(tests/unit/cli/test_plugin_content.py#L51-L63); - 双宿主正文等价:同一技能分别对两个宿主渲染、剥掉 frontmatter、把命令引用标记归一化后必须相等——直接陈述"一个正文渲染两次"这一核心属性(tests/unit/cli/test_plugin_content.py#L66-L83);
- 每个技能必须渲染到两个宿主;
- Codex prompt 只携带 Codex 读得懂的 frontmatter 键;
- 树上不得存在没有共享源支撑的生成文件(孤儿检测);
- 清理不能误伤手维护文件——生成器写出的每个文件都以
---开头,因此以 frontmatter fence 作为所有权测试,README 之类无 frontmatter 的手维护文件会被豁免(tests/unit/cli/test_plugin_content.py#L128-L149)。
孤儿文件检测:让下线的条目真正下线
orphaned_files()(scripts/gen_plugin_content.py#L207-L242)解决的是"只删共享源、不删产物"的问题:rendered_files()只说明应当存在什么,没有人对比实际存在什么,于是删除一个共享源会在磁盘上留下两份渲染副本,而--check依然宣称干净。后果并非纯装饰性:退役的命令会继续随 wheel 打包、每次安装仍被写入~/.codex/prompts;技能目录被改名后旧SKILL.md会作为同名第二个技能被宿主加载。
清理逻辑按内容而非位置划定范围,并遵循两条安全规则:
- 只删除以
---\n开头的文件(生成物标志),README 或手维护文件绝不自动删除; - 只有技能(
SKILL.md)拥有其目录,删除命令产物不递归删除目录——否则最后一个命令退役时会连命令根目录一起删掉,包括 Codex 的包数据目录,进而让install中的bundled_prompts直接FileNotFoundError(tests/unit/cli/test_plugin_content.py#L152-L170 记录了这个真实回归)。
Codex 命令为何不进 plugins/codex/
这是 README 中「Where the Codex commands go」一节回答的问题,也是理解整套布局的关键:Codex 插件清单没有命令槽位。一个 Codex 插件可以捆绑skills/、hooks/、assets/、.mcp.json、.app.json,仅此而已;能产生 Codex 斜杠命令的唯一表面是~/.codex/prompts/,而它是仅本机有效、由 CLI 写入的目录(生成器 docstring 原文:local-only and written by the CLI)。
因此 Codex 命令以包数据形式随 CLI 分发包内置(即packages/cli/src/repowise/cli/agent_targets/_data/codex_prompts/,常量CODEX_PROMPT_DATA,见 scripts/gen_plugin_content.py#L63-L65),由repowise agents add --target=codex在安装时写入用户本机~/.codex/prompts。测试test_retiring_every_command_does_not_delete_the_directory_itself还验证了该包数据目录下的bundled_prompts()恰好返回 18 个命令。
共享源里装的是什么:六项技能速览
共享源承载的技能正文(即黄金测试固定的部分)覆盖 Agent 在编码全流程中的六类介入时机:
- pre-modification.md:改动前风险评估。调用
get_risk(targets=[...])读取hotspot_score、defect_profile(含bug_magnet标志与近 6 个月fix_count)、impact_surface、co_change_partners、bus_factor、test_gap等;批改多个文件时把所有 target 合并为一次调用;改前先get_context防违反架构决策,重度重构再叠加get_health拿改造前后分数。 - change-review.md:合并前变更评审。先用
get_change_risk(revspec=...)对整段变更(commit 或base..head)打分并读directive与health_delta,再用get_risk(targets=..., changed_files=...)的 PR 模式逐文件读may_break、missing_cochanges、missing_tests、tests_to_run(注意区分measured与inferred两种依据),可加include=["blast"]取完整pr_blast_radius档案。 - code-health.md:代码健康。
get_health()无参为仪表盘(fix_first+ 仓库级 KPI),带targets为逐文件打分;include可加biomarkers/refactoring/coverage/trend,only反向裁剪;按weighted_deficit而非score排序,并核对unresolved/not_indexed语义。 - codebase-exploration.md:代码库探索。给出了"问题 → 工具"对照表:首次上手用
get_overview(),具体问题用get_answer(question=...),符号/路径/概念用search_codebase(mode自动路由,search_method区分embedding/bm25),精确定位用get_context后接get_symbol取字节。 - architectural-decisions.md:架构决策。
get_why四种模式:关键词+语义搜索、按文件查询其治理决策与对齐度、target 锚定搜索、无参决策健康仪表盘;决策来自 ADR、PR/squash 提交体、WHY:/DECISION:/TRADEOFF:/ADR:内联标记等五类来源,逐条溯源到原文 span。 - dead-code-cleanup.md:死代码清理。
get_dead_code()按置信分层返回,kind区分unreachable_file/unused_export/zombie_package,safe_only=true、tier、min_confidence、group_by控制筛选;只对safe_to_delete: true建议删除,删除前用get_risk复查依赖,并按"不可达文件 → 未用内部符号 → 未用导出"的安全顺序执行。
共享命令内容示例:risk 与 init
命令同样在plugins/shared/commands/编写。以 risk.md 为例,它演示了{{cmd:init}}占位符与allowed-tools键的实际用法:repowise risk对变更(而非文件)打分,权威字段是仓库相对百分位risk_percentile与classification,支持无参(未提交工作)、<sha>、<base>..<head>三种 revspec,提供--ext、-x/--exclude(并尊重.riskignore)、--format json、--baseline、-t/--target、--path等旗标。
init.md 则是流程型命令的范例,其 7 步序列(检查安装 → 检查.repowise/→ 提供模式但绝不阻塞于密钥 → 判定仓库是否值得注册 → 选择 provider → 确认排除项 → 运行并收尾)内嵌了完整的repowise init旗标参考,涵盖--prose/--no-prose、--mode fast、--embedder、--concurrency、-x/--exclude、--commit-limit、--editor-setup/--no-editor-setup、--hook、--save-key/--no-save-key、--resume/--force、--dry-run等全部选项。
维护工作流:新增、修改与下线
基于以上机制,向plugins/shared/增改内容的完整流程为:
- 新增技能或命令:在
plugins/shared/skills/或plugins/shared/commands/新建一个.md文件,必须从---frontmatter 块开始(load_item的硬性校验),正文中引用其他命令时写{{cmd:<id>}}占位符; - 处理宿主差异:技能用
claude-code:/codex:块声明各自的dir与frontmatter;命令依赖共享块 +select_keys白名单,无需手写差异; - 重新生成:运行
python scripts/gen_plugin_content.py写入四个目标; - 验证:运行测试
tests/unit/cli/test_plugin_content.py(或整仓测试),--check的幂等性也被测试断言; - 下线条目:删除共享源文件后必须重新运行生成器(不带
--check),由orphaned_files清理两个宿主的遗留产物;CI 会在下次运行时拦截任何漏删。
不要直接编辑plugins/claude-code/、plugins/codex/skills/或codex_prompts中的生成文件——下一轮黄金测试必然失败;所有修改一律落到plugins/shared/并重新生成。这正是这套架构的全部意义:把"双宿主内容一致性"从需要人工自律的纪律,变成一次渲染、一次测试即可机械保证的工程事实。
【免费下载链接】repowise
Codebase intelligence for AI and humans: code health scores, auto-generated docs, git analytics, dead code detection, and architectural decisions via MCP.
相关推荐
Claude Code 插件命令实战指南:十种插件斜杠命令模式与 CLAUDE_PLUGIN_ROOT 工程实践
Claude Code 插件命令实战指南:十种插件斜杠命令模式与 CLAUDE_PLUGIN_ROOT 工程实践 本篇技术指南以 claude plugins
AI 插件开发工具插件系统Claude Code 斜杠命令开发实战:基于 claude-plugins-official 的 10 个基础命令示例与模式解析
Claude Code 斜杠命令开发实战:基于 claude plugins official 的 10 个基础命令示例与模式解析 本文是 Claude Cod
AI 插件开发工具插件系统idea-claude-code-gui 集成 Codex Custom Prompts 实战指南:用 `/prompts:` 斜杠命令固化你的可复用指令
idea claude code gui 集成 Codex Custom Prompts 实战指南:用 /prompts: 斜杠命令固化你的可复用指令 本指南以
开发工具AI 应用代码智能体
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考