关于 sync-template
sync-template 用于在项目与 Rheinmir/setup 之间同步模板变更。它会自动处理下游更新并保留本地修改,也为上游发布、迁移和调试提供手动流程。
主要功能
- 01本地与远程文件三方哈希比较
- 02自动拉取新增及本地未改文件
- 03保留本地内容并报告冲突
- 04OKF 回填、指纹刷新与验证
- 05安装到三个 Claude Code 位置
- 06支持预演和 JSON 报告
适用场景
- 01将模板修复同步到项目
- 02向上游发布已批准的模板变更
- 03检查本地与远程编辑冲突
- 04迁移旧版 skills 目录结构
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ rheinmir/ setup --skill sync-template安装后在 Claude Code 中输入/sync-template确认已加载。
详细介绍
技能:sync-template
内容
目的和背景
- 目的: 在项目与
https://github.com/Rheinmir/setup.git之间同步结构/模板改进。 - 触发条件(何时使用):
- 上游: 本地改进了模板 → 保存到 Master。
- 下游: Master 有较新的修复 → 引入项目。
- 非目标: 不同步
.env、凭据和业务文档;不自行使用--strategy pull来缩短时间;不git clone模板;不自动触发(disable-model-invocation: true);Antigravity 无法运行此技能(沙盒会阻止工具)。
心智模型
下游默认流程:version.json + manifest remote → 对 3 个时间点的哈希进行分类(disk ↔ R0 remote_synced ↔ 当前 remote)→ NEW/UPDATE 自动 PULL · KEPT 保留 · CONFLICT 保留本地 + 保存 remote 版本 → OKF 回填 → fingerprint → 在 3 个位置安装技能 → 验证 3 个位置 → 记录日志。上游 / 迁移 / 调试则执行 MANUAL STEPS 0–8,并在 Step 5 停下询问用户。
输入和输出约定
| 字段 | 必填? | 含义 | |
|---|---|---|---|
| 输入 | 同步方向 | 是 | downstream(默认,FAST PATH)或 upstream(MANUAL) |
| 输入 | .template-manifest.json + harness/version.json | 是 | inclusion list、remote URL、branch、remote_synced |
| 输入 | --branch、--strategy pull、--dry-run、--json | 否 | 更改 branch、获取 CONFLICT 对应的 remote、预览、输出机器可读内容 |
| 输入 | 用户决定 | CONFLICT 或 Step 5 时需要 | 获取 remote 还是保留本地;拉取/推送哪些文件 |
| 输出 | 已同步的模板文件 + OKF 回填 | 是 | 将旧 wiki 文件中的粗体转换为 YAML |
| 输出 | 刷新的 harness/version.json | 是 | OKF 后的 fingerprint + template_version + remote_synced |
| 输出 | 安装在 .claude/commands/、~/.claude/skills/、~/.claude/commands/ 的技能 | downstream | 验证 3 个位置 |
| 输出 | 报告 + 退出代码 | 是 | 0 表示干净,1 表示下载/OKF/验证出错,3 表示存在需要决定的 CONFLICT |
| 输出 | wiki/log.md 中的日志行 + 报告草稿输出 | 是 | 脚本在使用 --full 时自动记录日志 |
规则和能力
- RULE-01(MUST):绝不同步
.env、凭据和业务文档。 - RULE-02(MUST):始终审核 remote 分支——非默认分支可能是最新的。
- RULE-03(MUST):始终为
[CONFLICT]显示差异 → 等待指示。 - RULE-04(MUST):绝不使用
cp -R——逐个文件处理。 - RULE-05(MUST):每次同步都执行 Step 3——检测旧版
skills/,并提出迁移。 - RULE-06(MUST):每次下游同步都执行 Step 7——安装所有 3 个 Claude Code 位置。
- RULE-07(MUST):
[NEW]:上游提交前添加到 manifest。 - RULE-08(MUST):
[MISSING]:下游复制后添加到 manifest。 - RULE-09(MUST):Frontmatter:技能需要
name:+description:;斜杠命令只需要description:。 - RULE-10(MUST):跳过
README.md、index.md、log.md以及没有 Purpose/Steps 的文件。 - 能力:读取远程模板(HTTP/GitHub API);在项目和用户级技能/命令目录中写入文件;上游同步时推送到远程模板(仅在获准后)。
失败边界
- CONFLICT(双方都做了更改)→ 保留本地,将 remote 版本保存到
/tmp/sync-template-conflicts/,退出代码为 3 → 与用户澄清。 - 下载/OKF/验证出错 → 退出代码为 1 → 失败,完成前修复
✗。 - 无法确定哪个 remote 分支最新 → 澄清,询问用户使用哪个分支。
- health-check 为
OK→ 无需同步,停止(成功,无操作)。 - 旧版
skills/布局 → 提议迁移,删除前须先确认。
操作
主工作流
| 步骤 | 类型 | 输入 | 操作 | 输出/退出 | 失败/后续 |
|---|---|---|---|---|---|
| W01 | 判断 | 要求 | 选择路径:常规下游 → FAST PATH --full;上游、迁移旧结构、调试 → MANUAL(B01) | 路径 | — |
| W02 | 效果 | manifest、远程服务 | 运行一次 python3 harness/scripts/sync-template.py --full(同步 + OKF + 指纹 + 安装到 3 个位置 + 验证 + 日志) | 报告 | exit 1 → 失败;exit 3 → W03 |
| W03 | 判断 | 报告 | 阅读报告;若 CONFLICT 且想采用远程版本 → 重新运行 --strategy pull;若是其他分支 → 使用 --branch | 决策 | 不确定 → 询问用户 |
| W04 | 确定性 | 报告 | 不要额外调用 okf-check、health-check、验证循环,也不要自行修改日志 | 向用户报告 | — |
| W05 | 效果 | 结果 | 输出 Report 草稿 | 草稿 + 索引 + 日志 | 0 个产物 → 跳过 |
各步骤详情(W01–W05 和 MANUAL 分支的事实来源):
FAST PATH — 下游通过一条命令 --full(< 30s,默认)
下游同步是一个非交互式、自包含的脚本。使用 --full 调用一次 → 所有同步后步骤(Step 6a/6b/8 + 写入日志)都在同一进程中运行。Agent 读取一份报告后进行汇报——不要重复运行单独的命令。此仓库的基准数据:稳定状态下 full 用时 0.27s · full pull+install+verify 用时 0.76s
(harness/metrics/sync-template-bench.json)。
python3 harness/scripts/sync-template.py --full # ⭐ MẶC ĐỊNH: sync + OKF backfill + fingerprint + verify ×3 + ghi log, 1 process
python3 harness/scripts/sync-template.py --full --json # như trên, output máy đọc (đọc okf_migrated / verify_bad)
python3 harness/scripts/sync-template.py --dry-run # xem trước, không ghi (kèm --full để xem OKF sẽ migrate gì)
python3 harness/scripts/sync-template.py --strategy pull # ghi đè cả CONFLICT bằng remote (backup .local-bak)
--full运行一次即可——不要接着调用okf-check、health-check --update、验证循环,也不要自行Editlog.md(脚本已经完成所有操作)。这是将技能控制在 30s 以内的方法:旧瓶颈是同步后步骤中的 Agent 往返次数,而不是 CPU。未使用--full标志 = 行为与旧版完全一致。
通过 3 个哈希进行分类——磁盘 ↔ R0(上次同步时的远程版本,保存在 version.json:remote_synced)↔ 当前远程版本:
NEW(本地缺失)+UPDATE(远程有更新,且本地未改动)→ 自动 PULL。KEPT(我方已自定义,远程没有更新)→ 保持不变,不询问。CONFLICT(双方都有改动)→ 默认保留本地版本 + 将远程版本保存到/tmp/sync-template-conflicts/以便比较;退出代码为 3。绝不会为缩短时间而自动使用--strategy pull。
脚本中的自动流程(--full):获取远程 version.json+manifest → 分类 → 并行下载 → 进程内 OKF 回填(将 bold 迁移为 YAML,幂等)→ 刷新 version.json(OKF 之后计算指纹 + template_version + remote_synced)→ 将技能安装到 3 个位置(.claude/commands/、~/.claude/skills/、~/.claude/commands/)→ 自行验证 3 个位置 → 追加写入 wiki/log.md。退出状态:0 表示无问题 · 1 表示下载/OKF/验证出错 · 3 表示需要处理 CONFLICT。
需要手动介入的情况(先运行脚本,再阅读报告):
- 报告中有
CONFLICT,且你想采用远程版本 → 重新运行--strategy pull(一个决策,而不是三个)。 - 远程分支与
version.json:branch不同 → 使用--branch <分支名>(查看 Step 2 以审查分支)。 - 需要迁移旧的
skills/结构(Step 3),或需要进行上游操作(推送)→ 使用下方的 MANUAL STEPS。
⚠ 已修复的 Bug:
health-check --update会将基准设为磁盘上的版本 → 同步无法区分“远程有更新”和“我方已自定义” → 差点覆盖自定义文件。此脚本使用独立的remote_synced基准(上次同步时的远程哈希),因此可以正确区分。不要再使用patterns(磁盘版本)作为分类基准。
MANUAL STEPS(回退流程——上游操作、迁移旧结构或调试)
Step 0:预检——health-check(同步前诊断)
运行 /health-check(python3 harness/scripts/health-check.py --root .)以了解应该朝哪个方向同步:
NEEDS-SYNC(落后/缺失)→ 下游(拉取)。DRIFT(本地已修改)→ 上游(推送)或还原。OK→ 无需同步,停止。
Step 1:加载 Manifest
读取 .template-manifest.json——文件包含清单 + 远程 URL。
Step 2:获取数据并审查分支
- CRITICAL:列出所有远程分支:
gh api repos/<owner>/<repo>/branches。 - 检查每个分支的提交日期——不要假设
master/main是最新的。 - 不确定 → 询问用户要使用哪个分支。
- 通过
gh api+curl获取——不要使用git clone。
步骤 3:检测旧结构迁移
检查是否存在需要迁移到 llmwiki/ 的旧 skills/ 布局:
# Signs of old structure:
[ -d "skills/" ] && [ ! -d "llmwiki/skills/" ] # old only
[ -d "skills/" ] && [ -d "llmwiki/skills/" ] # both exist → migration in progress
旧 skills/ 与新的 llmwiki/skills/ 并存:
- 列出
skills/(扁平的 .md 文件和子目录:dev-loop/、wiki-loop/等) - 映射旧文件 → 新文件:
skills/dev-loop/*.md→llmwiki/skills/dev-loop/*.mdskills/wiki-loop/*.md→llmwiki/skills/wiki-loop/*.mdskills/orchestrate/*.md→llmwiki/skills/orchestrate/*.mdskills/utils/*.md→llmwiki/skills/utils/*.mdskills/*.md(扁平文件) → 已由子目录覆盖,跳过重复项
- 内容相同 → 旧文件已过时,可以安全删除。
- 显示迁移表 → 删除前先确认。
步骤 4:比较清单文件
对 includes 中的每个文件执行本地与远程 diff:
BASE="https://raw.githubusercontent.com/<owner>/<repo>/<branch>"
for file in <includes>; do
http_code=$(curl -s -o /dev/null -w "%{http_code}" "$BASE/$file")
# SAME / DIFF / MISSING / NEW / ABSENT
done
状态:
SAME— 相同,跳过DIFF— 内容不同MISSING— 仅远程存在 → 下游候选项NEW— 仅本地存在 → 上游候选项ABSENT— 两者均不存在
步骤 5:同步计划
显示表格。停止 → 询问用户:全部拉取 / 全部推送 / 指定文件 / 为每个 DIFF 选择方向。
步骤 6:执行
- 下游:
mkdir -p→curl -sfL <url> -o <local_path>→ 更新wiki/log.md - 上游:通过
gh/git提交并推送 - 逐个处理文件 — 不使用
cp -R
步骤 6a/6b/8 已合并到
--full。 如果运行 FAST PATH--full,则跳过 6a/6b/8 — 脚本已在处理过程中完成 OKF-backfill + 刷新 fingerprint + 验证 + 记录日志。以下步骤仅 在 MANUAL 模式下使用(调试 / 上游 / 迁移旧结构),而不是在--full之后执行。
步骤 6a:OKF 回填 (MANUAL — --full 已完成)
新的模板/技能可能会升级 wiki 格式(例如 OKF v0.1 标准)。拉取后,将所有仍使用粗体伪 frontmatter(如 **Type:**)的旧内容文件转换为 YAML frontmatter,以免触发 R9:
python3 harness/scripts/okf-check.py --check # exit 3 = có file chưa đạt OKF
python3 harness/scripts/okf-check.py --migrate # convert bold → YAML (chỉ THÊM frontmatter, giữ body/## Origin)
- 幂等 — 已有
---frontmatter 的文件会被跳过。保留项(index/log/README/decisions/_template…)自动豁免。 - 迁移后:重新运行
--check,直至DAT CHUAN OKF v0.1,然后像处理其他 wiki 变更一样更新 index/log。
步骤 6b:刷新版本指纹 (MANUAL — --full 已完成)
模式内容刚刚发生变化 → 更新 harness/version.json,避免健康检查误报 DRIFT:
python3 harness/scripts/health-check.py --update # KHÔNG --bump ở project con
--bump major|minor|patch仅在模板仓库Rheinmir/setup中发布新模式版本时运行。- 在模板仓库执行上游同步:推送后,运行
--update --bump <part>,然后提交harness/version.json。
步骤 7:安装为原生技能 (每次下游同步都会运行)
收集已同步的技能文件(清单中的 llmwiki/skills/ 下)。跳过:README.md、index.md、log.md,以及不包含 ## Purpose/## Steps 的文件。
A. 项目级(.claude/commands/ — 此仓库):
mkdir -p .claude/commands/
# Add description: frontmatter if missing, then copy
printf -- "---\ndescription: %s\n---\n\n" "$desc" | cat - <src> > .claude/commands/<name>.md
B. 全局用户级(~/.claude/skills/<name>/SKILL.md — 所有项目):
mkdir -p ~/.claude/skills/<name>/
# Requires name: + description: frontmatter
printf -- "---\nname: %s\ndescription: %s\n---\n\n" "$name" "$desc" | cat - <src> > ~/.claude/skills/<name>/SKILL.md
C. 全局斜杠命令(~/.claude/commands/<name>.md):
printf -- "---\ndescription: %s\n---\n\n" "$desc" | cat - <src> > ~/.claude/commands/<name>.md
全部安装。报告:
| Skill | Project .claude/commands/ | ~/.claude/skills/ | ~/.claude/commands/ |
|----------------|---------------------------|-------------------|---------------------|
| propose | ✓ | ✓ | ✓ |
| ingest | ✓ | ✓ | ✓ |
| ... | ... | ... | ... |
步骤 8:验证并完成
for name in <skill-list>; do
[ -f ".claude/commands/$name.md" ] && echo "✓ proj $name" || echo "✗ proj $name"
[ -f "$HOME/.claude/skills/$name/SKILL.md" ] && echo "✓ global $name" || echo "✗ global $name"
done
完成前修复 ✗。无需重启。
分支
| ID | 类型 | 条件 | 行为 | 跳过 / 失败 | 汇合点 |
|---|---|---|---|---|---|
| B01 | conditional_required | 需要上游同步、迁移旧 skills/ 结构或调试 | 运行 MANUAL STEPS 0–8,在步骤 5 停止并询问用户 | 常规下游同步 → FAST PATH | W05 |
| B02 | recovery | exit 3 CONFLICT,且用户选择采用远程版本 | 重新运行 --strategy pull(覆盖,并备份到 .local-bak) | 用户保留本地版本 → 不执行任何操作 | W04 |
| B03 | conditional_required | 远程分支与 version.json:branch 不同 | 在审查分支(步骤 2)后使用 --branch <名称> | — | W02 |
| B04 | user_optional | 想要预览 | 使用 --dry-run(搭配 --full 可预览将迁移哪些内容至 OKF) | — | W02 |
| B05 | conditional_required | 检测到旧 skills/ 布局(步骤 3) | 显示迁移表,确认后再删除 | 用户拒绝 → 保留 | W05 |
验证与停止
所有必需条件:脚本退出码(0/1/3)、验证 3 个安装位置、okf-check.py --check 输出 DAT CHUAN OKF v0.1(MANUAL)、Step 8 中的 [ -f … ] 循环不再出现 ✗。--full 只运行一次,退出码为 0 时停止;退出码为 3 时停止并等待用户决定;MANUAL 在 Step 5 停止并等待审核。
示例
- **成功:**子项目中,Master 有新修复 →
python3 harness/scripts/sync-template.py --full→ 2 个 UPDATE 自动 PULL,1 个 KEPT 保持不变,OKF 迁移 3 个文件,验证 3 个位置 ✓,在 < 1 秒内退出码为 0 → 报告结果,不再运行任何命令。 - 边界情况/失败:
llmwiki/skills/dev-loop/ship.md在本地和远程都有修改 → CONFLICT,保留本地版本,将远程版本放在/tmp/sync-template-conflicts/,退出码为 3 → 显示差异,等待用户;不自动使用--strategy pull。
参考 — Agent 兼容性
| Agent | 运行? | 原因 |
|---|---|---|
| Claude Code | 是 | 完整的工具访问权限 |
| OpenCode | 是 | 完整的工具访问权限 |
| Antigravity | 否 | 沙盒会阻止文件/命令工具 |
交付 — 输出报告
所有主要技能任务完成后,将提案草稿写入 wiki。
步骤
1. 构建文件名:
- 格式:
DDMMYY-<ten>.md DDMMYY= 今天的日期(例如,2026 年 6 月 2 日为020626)<ten>= 2–4 个 kebab-case 单词,概括完成的工作(例如,landing-page-coteccons、brand-kit-fintech、ingest-auth-spec)
2. 写入 llmwiki/wiki/sources/draft/DDMMYY-<ten>.md:
---
type: draft
title: "DDMMYY-<ten>"
status: proposed
tags: [<skill-name>, output-report]
timestamp: YYYY-MM-DD
---
# DDMMYY-<ten>
**Type:** draft
**Status:** proposed
**Tags:** <skill-name>, output-report
**Proposed:** YYYY-MM-DD
## What
<One sentence — what this skill invocation produced or decided>
## Output
<Key artefacts, files created/modified, or decisions made>
## Files
| File | Action |
|------|--------|
| `path/to/file` | created / modified |
## Notes
- Invoked via: `/<skill-name>` skill
## Origin
- **Draft:** `wiki/sources/draft/DDMMYY-<ten>.md`
- **Commit:** _(filled by verify-before-commit)_
- **Date promoted:** _(filled by verify-before-commit)_
3. 更新 wiki 索引和日志:
llmwiki/wiki/index.md— 追加一行:| [DDMMYY-<ten>](sources/draft/DDMMYY-<ten>.md) | draft | YYYY-MM-DD |llmwiki/wiki/log.md— 追加:## YYYY-MM-DD — <skill-name> — <ten>
仅当该技能没有生成任何产物且没有任何决策时才跳过(例如,
/caveman-stats这类纯显示模式)。