news 2026/10/9 1:31:26

Repowise 双主机插件单源化:以 plugins/shared 为单一事实源生成 Claude Code 与 Codex 技能及斜杠命令

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Repowise 双主机插件单源化:以 plugins/shared 为单一事实源生成 Claude Code 与 Codex 技能及斜杠命令

【免费下载链接】repowise

Codebase intelligence for AI and humans: code health scores, auto-generated docs, git analytics, dead code detection, and architectural decisions via MCP.

项目地址:https://gitcode.com/gh_mirrors/re/repowise
点击查看免费下载

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 Codeplugins/claude-code/skills/<dir>/SKILL.mdplugins/claude-code/commands/<id>.md
Codexplugins/codex/skills/<dir>/SKILL.mdpackages/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}全部保留
codexrepowise-{id}.md/prompts:repowise-{id}仅description、argument-hint

三个设计要点值得展开:

  1. Codex 命令文件名加repowise-前缀:因为~/.codex/prompts是与用户安装的其他工具共享的扁平全局目录,命名空间化避免冲突;Claude Code 的命令目录是专属的,无需前缀。
  2. 命令引用占位符{{cmd:risk}}:正文里写{{cmd:risk}},渲染时由command_reference格式化为/repowise:risk(Claude Code)或/prompts:repowise-risk(Codex),正则_TOKEN负责替换(scripts/gen_plugin_content.py#L132-L133)。
  3. 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 对磁盘上的生成文件(而非生成器返回值)做断言,因为"一个渲染器可以对自己从未写盘的内容完全正确"——那正是本测试要消灭的失败模式。六项核心断言:

  1. 逐文件黄金比对:参数化遍历rendered_files(),磁盘文件必须与期望逐字节一致(行尾规范化后),否则报错并提示"编辑共享源后运行生成器"(tests/unit/cli/test_plugin_content.py#L51-L63);
  2. 双宿主正文等价:同一技能分别对两个宿主渲染、剥掉 frontmatter、把命令引用标记归一化后必须相等——直接陈述"一个正文渲染两次"这一核心属性(tests/unit/cli/test_plugin_content.py#L66-L83);
  3. 每个技能必须渲染到两个宿主;
  4. Codex prompt 只携带 Codex 读得懂的 frontmatter 键;
  5. 树上不得存在没有共享源支撑的生成文件(孤儿检测);
  6. 清理不能误伤手维护文件——生成器写出的每个文件都以---开头,因此以 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/增改内容的完整流程为:

  1. 新增技能或命令:在plugins/shared/skills/或plugins/shared/commands/新建一个.md文件,必须从---frontmatter 块开始(load_item的硬性校验),正文中引用其他命令时写{{cmd:<id>}}占位符;
  2. 处理宿主差异:技能用claude-code:/codex:块声明各自的dir与frontmatter;命令依赖共享块 +select_keys白名单,无需手写差异;
  3. 重新生成:运行python scripts/gen_plugin_content.py写入四个目标;
  4. 验证:运行测试tests/unit/cli/test_plugin_content.py(或整仓测试),--check的幂等性也被测试断言;
  5. 下线条目:删除共享源文件后必须重新运行生成器(不带--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.

项目地址:https://gitcode.com/gh_mirrors/re/repowise
点击查看免费下载

相关推荐

上一篇:终极指南:用XiaoMusic让小爱音箱变身你的私人音乐管家
下一篇:MentraOS安全指南:数据加密与隐私保护最佳实践

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/9 1:31:06

Hyperframes:HTML帧级同步技术实践与CLI预处理方案

1. “hyperframes”不是新框架&#xff0c;而是对HTML媒体时间轴控制能力的一次概念性重提最近在多个前端技术社区和CLI工具讨论区里&#xff0c;“hyperframes”这个词突然高频出现——它既不像React、Vue那样有明确的GitHub仓库和文档站&#xff0c;也不像Tailwind CSS那样有…

作者头像 李华
网站建设 2026/10/9 1:27:11

Apache Beam 版本演进全览:基于 CHANGES.md 的 2.19~2.59 变更深度解读

批处理流处理大数据 【免费下载链接】beam Apache Beam is a unified programming model for Batch and Streaming data processing. 项目地址&#xff1a; https://gitcode.com/gh_mirrors/beam15/beam 点击查看 免费下载 Apache Beam 是一个统一的批流一体数据处理编程模型&…

作者头像 李华
网站建设 2026/10/9 1:26:57

Vibe Coding实战:智能体驱动全栈开发与工程化约束

1. 从“写代码”到“聊需求”&#xff1a;Vibe Coding 到底改变了什么第一次听到 Vibe Coding 这个词&#xff0c;是从一个做独立开发的朋友嘴里蹦出来的。他说自己最近三个月没写过一行完整的业务代码&#xff0c;全靠“跟智能体聊天”把一套带支付、带后台、带数据看板的全栈…

作者头像 李华
网站建设 2026/10/9 1:26:48

PocketTerm35:口袋级Linux工作站与边缘AI终端实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华