我把博客复盘工作流拆成了 3 个 Skill

从内容复盘、仓库发布到总入口编排,一次把博客自动化工作流讲清楚

Posted by Hux on March 29, 2026

这篇文章记录的不是“又写了一篇博客”,而是我把“把一次刚刚完成的问题解决过程整理成博客,并在需要时发布到博客仓库”这套动作,正式固化成了 3 个可复用 Skill。

前面我刚让 AI 帮我完成了一件很具体的事:先解决一个真实问题,然后把这个问题从开始到成功的全过程写成博客,再提交并推送到我的博客仓库里。

做完之后,我很快意识到,这其实不应该只停留在“一次对话里的临时发挥”。因为以后我还会反复说类似的话:

  • “写篇博客记录一下”
  • “把刚刚这个问题解决过程写成博客”
  • “整理成一篇技术博客,并推送到我的博客仓库”

如果每次都重新解释、重新猜路径、重新决定是只写文章还是还要顺手推送,那整件事的稳定性和复用性都会很差。

所以这次我干脆把这套流程抽出来,拆成了 3 个 Skill:

  1. solution-retrospective-blog:负责把问题解决过程写成复盘博客
  2. blog-repo-publish:负责检查博客仓库格式、写入文章、提交并推送
  3. blog-retrospective-publish:作为总入口 skill,负责根据用户意图编排前两者

这篇文章会把这 3 个 Skill 的设计思路、职责边界、默认路径配置,以及它们的完整内容全部展示出来。


一、为什么要拆成 3 个 Skill,而不是只保留一个

一开始最直觉的做法,其实是写一个“大而全”的 skill:

  • 用户一说“写篇博客记录一下”
  • 它就去回看问题
  • 整理文章
  • 找博客仓库
  • 写进 _posts
  • 校验
  • 提交
  • 推送

这种做法看起来省事,但问题很明显:

1. 写作和发布是两种不同职责

“把问题复盘成一篇好文章”和“把文章安全写入博客仓库并推送”其实是两类能力。

前者关注:

  • 故事是不是基于真实过程
  • 时间线是不是清楚
  • 知识点有没有讲透
  • 是否把案例事实和普遍规律区分开了

后者关注:

  • _posts 路径是不是对的
  • front matter 格式对不对
  • 仓库当前分支和 upstream 是什么
  • 有没有做当前环境允许的验证
  • commit message 风格是否匹配仓库现状

如果把这两类事情塞进一个 skill 里,最后一定会变得职责不清。

2. 用户并不是每次都要发布

有时候我只是想先看文章内容,不想当场 push。

所以更合理的拆法是:

  • 复盘写作单独成为一个 skill
  • 仓库发布单独成为一个 skill
  • 再做一个总入口,根据用户说的话自动路由

3. 总入口 skill 更适合接自然语言

用户最常说的不是“请调用写作 skill 再调用发布 skill”,而是:

“写篇博客记录一下。”

所以还需要一个总入口 skill,把自然语言映射成内部流程:

  • 如果只是写文章 → 调 solution-retrospective-blog
  • 如果写文章并发布 → 先调 solution-retrospective-blog,再调 blog-repo-publish
  • 如果文章已经有了,只要求发仓库 → 直接调 blog-repo-publish

这就是我最后选择 3 个 skill 的原因。


二、这 3 个 Skill 各自负责什么

1)solution-retrospective-blog

这个 skill 只关注一件事:

把一个刚刚完成的问题解决过程,整理成一篇真实、清楚、可复用的技术复盘博客。

它要求文章必须建立在真实证据上,而不是编一个“看起来更顺”的故事。

它重点负责:

  • 重建时间线
  • 识别表面问题和隐藏问题
  • 记录阻塞、失败尝试和修复动作
  • 解释相关知识点
  • 最后给出可复用经验

不负责 commit / push 本身。

2)blog-repo-publish

这个 skill 只关注博客仓库侧的事情:

  • 仓库根目录是不是正确
  • _posts 在哪里
  • front matter 怎么写
  • 当前环境能做哪些验证
  • git 状态、分支、upstream、commit 风格是否合理
  • 最终如何提交并推送

它的职责很明确:

把文章安全、诚实地写进正确的博客仓库,并在用户明确要求时完成发布动作。

3)blog-retrospective-publish

这个 skill 现在被我改成了总入口 / 编排 skill

它不再重复实现所有细节,而是专门负责:

  • 理解用户的自然语言意图
  • 决定是只写文章,还是还要发布
  • 然后把工作路由给前两个 skill

所以,这 3 个 skill 的关系可以概括成一句话:

solution-retrospective-blog 把内容写对,blog-repo-publish 把仓库动作做对,blog-retrospective-publish 负责把两者编排起来。


三、我还专门给它们加了“博客目标路径配置”

做这种事情最怕什么?

最怕每次都重新猜:

  • 博客仓库到底是哪一个
  • _posts 到底在哪个目录
  • 这次是不是又要让我自己指定一遍路径

所以我把“默认博客目标路径”也写进了 skill 里。

统一采用这种配置形式:

1
2
博客仓库根目录:<BLOG_REPO_ROOT>
博文目录:<BLOG_POSTS_DIR>

并且给了默认示例:

1
2
博客仓库根目录:D:\Github\langkemaoxin.github.io
博文目录:D:\Github\langkemaoxin.github.io\_posts

这样以后执行时会按这个优先级处理:

  1. 用户本次指令显式给出的路径
  2. skill 中预设的博客路径
  3. 如果都没有,再去检查仓库结构推断

这一步非常重要,因为它把“博客写到哪里”从一种临时判断,变成了一个稳定配置。


四、三个 Skill 的完整内容

下面我把这 3 个 Skill 的完整内容都贴出来,方便以后直接查阅、修改和维护。


Skill 1:solution-retrospective-blog

路径:C:\Users\CGY\.config\opencode\skill\solution-retrospective-blog\SKILL.md

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
---
name: solution-retrospective-blog
description: "当用户希望把一个刚刚完成的问题解决过程整理成技术博客时使用。重点是把原始问题、真实步骤、阻塞点、解决方式、相关知识点和可复用经验讲清楚。示例:\"写篇博客记录一下\"\"把这次问题解决过程写成博客\"\"复盘一下刚刚这个任务\""
---

# 解决过程复盘博客

这个 skill 专门用于把一个**已经完成的问题解决过程**整理成一篇高质量技术博客。

它关注的不是“泛泛写一篇文章”,而是:

- 用户原始问题是什么
- 从第一条指令到最后成功,真实经历了哪些步骤
- 过程中遇到了什么错误、阻塞和失败尝试
- 最后是如何解决的
- 为什么某些工具、命令或方案是必要的
- 相关知识点是什么
- 对未来类似任务的可复用经验是什么

> 如果用户还要求“保存到博客仓库、提交并推送”,请联动使用 `blog-repo-publish` skill。

## 何时使用

- “写篇博客记录一下”
- “把刚刚这个问题解决过程写成博客”
- “复盘一下这个任务是怎么完成的”
- “解释一下你是如何一步步解决这个问题的”
- “整理成一篇技术博客,讲清楚中间经历了什么”

## 工作流

```text
1. 重建真实执行时间线
2. 识别用户表面问题与隐藏问题
3. 提炼真实执行步骤、阻塞点、失败尝试和修复动作
4. 解释与本次任务相关的工具、协议、架构边界
5. 组织成一篇可读的技术复盘文章
6. 如果用户要求发布,再交给 blog-repo-publish skill 继续处理

博客目标路径配置

如果用户有固定博客仓库,应在执行时优先读取并使用这个目标路径约定:

1
2
3
博客仓库根目录:<BLOG_REPO_ROOT>
博文目录:<BLOG_POSTS_DIR>
默认文件落点:<BLOG_POSTS_DIR>/YYYY-MM-DD-slug.md 或 .markdown

例如:

1
2
博客仓库根目录:D:\Github\langkemaoxin.github.io
博文目录:D:\Github\langkemaoxin.github.io\_posts

规则:

  • 如果 skill 或上下文里已经明确给出路径,就优先使用该路径
  • 如果用户另外临时指定路径,以用户本次指令为准
  • 如果没有固定路径,就先检查目标博客仓库结构再决定 _posts 位置

不可妥协的规则

1. 只写真实发生过的事情

必须基于真实证据写作:

  • 真实工具输出
  • 真实仓库状态
  • 真实错误信息
  • 真实执行步骤
  • 真实解决方案

不要为了让文章更顺畅而虚构一个不存在的“理想过程”。

2. 区分案例事实与普遍规律

文章中必须区分:

  • 这次具体发生了什么
  • 类似任务通常会怎么做
  • 相关概念本身是什么意思

不要把一次案例路径写成唯一标准答案。

3. 解释边界,而不仅是记流水账

重点解释让任务复杂起来的边界,例如:

  • 本地 git 与远程 GitHub 的边界
  • shell 工具与 MCP 工具的边界
  • 认证问题与仓库状态问题的边界
  • 文件级成功与构建级成功的边界

检查清单

1
2
3
4
5
6
7
- [ ] 重建原始任务和真实目标
- [ ] 列出从开始到成功的关键步骤
- [ ] 记录所有重要阻塞和失败尝试
- [ ] 解释最后真正起作用的解决方式
- [ ] 提炼相关知识点并讲清楚
- [ ] 给出一个可复用的经验模型
- [ ] 如果用户要求发布,则调用 blog-repo-publish skill

推荐文章结构

1. 开头:先说清楚问题表面是什么

例如:

  • “表面上是 push 一个文件夹,实际上中间卡在 GitHub 认证和远程仓库创建。”
  • “表面上是写一篇博客,实际上背后是一次工具链边界的复盘。”

2. 中段:按时间顺序讲真实过程

需要覆盖:

  • 先检查了什么
  • 缺了什么
  • 安装了什么
  • 哪一步失败了
  • 后来如何调整
  • 最后如何成功

3. 技术解释:为什么这样做

不要只说“做了什么”,要解释:

  • 为什么需要这一步
  • 为什么前面的直接方法不够
  • 为什么最后这个方案有效

4. 概念解释:把相关工具讲明白

根据具体案例选择解释:

  • git
  • gh
  • GitHub MCP Server
  • MCP host
  • OpenCode
  • PAT / SSH / CLI 认证
  • 构建工具 / 运行时依赖

5. 收尾:给出可复用结论

文章最后必须给出一个“以后遇到类似问题该怎么想”的总结。

输出要求

最终文章至少应覆盖:

1
2
3
4
5
6
7
1. 原始用户问题
2. 隐藏真实问题
3. 执行时间线
4. 阻塞与解决方式
5. 相关技术知识点
6. 最终结果
7. 可复用经验

示例

1
2
3
4
5
6
7
8
9
用户:写篇博客记录一下刚刚这个问题。

你应该:
1. 重建这次任务真实发生了什么
2. 说明表面问题和隐藏问题
3. 把阻塞点、错误和修复动作写清楚
4. 顺带解释相关工具和知识点
5. 给出一篇结构完整的复盘型技术博客
6. 如果用户还要求发布,则交给 blog-repo-publish skill

一个好的最终交付应包含

  • 文章标题与主题聚焦明确
  • 时间线真实可信
  • 阻塞与解决过程讲清楚
  • 知识点不是硬塞,而是从案例自然展开
  • 结尾能给读者留下“以后遇到类似问题如何处理”的方法论 ```

Skill 2:blog-repo-publish

路径:C:\Users\CGY\.config\opencode\skill\blog-repo-publish\SKILL.md

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
---
name: blog-repo-publish
description: "当用户已经有博客文章内容,或者已经要求把复盘文章保存到博客仓库、检查格式、提交并推送时使用。示例:\"发到我的博客仓库里\"\"保存到 _posts 并推送\"\"检查博客格式后提交\""
---

# 博客仓库检查与发布

这个 skill 专门负责**博客仓库侧的工作**
- 检查博客仓库结构
- 确认 `_posts` 格式
- 写入文章文件
- 做可用范围内的验证
- 提交并推送博客仓库

它可以单独使用,也可以作为 `solution-retrospective-blog` 的发布后半段。

## 何时使用

- “发到我的博客仓库里”
- “保存到 _posts 并推送”
- “按我博客格式写进去,然后提交”
- “检查一下博客仓库格式,写完顺手 push”
- 用户明确要求 **commit + push**

## 工作流

```text
1. 检查博客仓库结构和文章格式约定
2. 确认 _posts 目录、文件扩展名、front matter 和写作风格
3. 把文章内容写入正确文件
4. 读回文章文件,校验 front matter 与正文
5. 执行当前环境下最接近的验证(build / lint / file readback)
6. 检查 git 状态、diff、分支、upstream、commit 风格
7. 创建聚焦提交
8. 推送到当前跟踪分支
9. 返回文章路径、commit hash、push 结果与验证边界

博客目标路径配置

这个 skill 应优先从固定配置中读取博客写入目标:

1
2
博客仓库根目录:<BLOG_REPO_ROOT>
博文目录:<BLOG_POSTS_DIR>

例如:

1
2
博客仓库根目录:D:\Github\langkemaoxin.github.io
博文目录:D:\Github\langkemaoxin.github.io\_posts

执行规则:

  • 如果这里已经有明确路径,默认直接按这个路径执行
  • 如果用户本次明确给了另一个博客仓库路径,以用户本次指令为准
  • 如果仓库根目录存在但 _posts 不存在,要先检查该博客系统是否使用其他文章目录
  • 不要在路径不明确时擅自写到错误仓库

检查清单

1
2
3
4
5
6
7
8
9
10
11
- [ ] 检查博客仓库根目录是否正确
- [ ] 检查博客目标路径配置是否与本次任务一致
- [ ] 检查 _posts 的文件命名与 front matter 风格
- [ ] 按正确格式写入文章
- [ ] 读回文件确认内容落盘
- [ ] 运行环境允许的验证
- [ ] 明确说明哪些验证做不了,以及为什么做不了
- [ ] 检查 git status / diff / branch / upstream
- [ ] 提交信息匹配仓库现有风格
- [ ] 仅在用户要求时 commit 和 push
- [ ] 返回最终仓库状态

验证规则

1. 先做文件级验证

始终至少完成:

  • 文件路径确认
  • front matter 读回确认
  • 正文读回确认
  • git status 确认

2. 环境级验证只在工具存在时做

例如:

  • Jekyll → bundle exec jekyll build
  • Hugo → hugo
  • Next/React 博客 → npm run build

如果运行时不存在,就必须明确说明:

  • 缺了什么(例如 Ruby / Bundler)
  • 因此没法做哪一步
  • 已经完成了哪些替代验证

3. 不要假装验证通过

如果没有 Ruby / Bundler,就不能说 Jekyll build 已通过。 如果没有 Node 依赖,也不能说前端构建已通过。

Git 规则

发布前必须检查:

  • 当前分支
  • upstream
  • 工作区变更范围
  • 最近提交风格

提交时应遵循:

  • 只提交这篇文章和必要的直接相关修正
  • 尽量匹配仓库现有 commit message 风格
  • 推送到当前跟踪的远程分支

如果 push 被阻塞:

  • 明确指出是认证问题、远程问题还是网络问题
  • 不要声称发布成功
  • 让仓库保持在干净、可继续操作的状态

输出格式

最终答复至少应包含:

1
2
3
4
5
6
7
1. 文章写入路径
2. 是否已 commit
3. 是否已 push
4. commit hash
5. 当前分支与远程状态
6. 已完成的验证
7. 未完成的验证及原因

示例

1
2
3
4
5
6
7
8
9
10
用户:把这篇博客发到我的博客仓库里,并提交推送。

你应该:
1. 检查博客仓库 _posts 格式
2. 写入正确文件名和 front matter
3. 读回文件确认
4. 做可用的 build / file 级验证
5. 检查 git 分支和 commit 风格
6. 提交并 push
7. 返回路径、commit hash 和验证边界

建议配合方式

如果任务是“先写复盘博客,再发布”:

  1. 先使用 solution-retrospective-blog
  2. 再使用 blog-repo-publish

前者负责把内容写对,后者负责把仓库发布动作做对

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
---

## Skill 3:`blog-retrospective-publish`

路径:`C:\Users\CGY\.config\opencode\skill\blog-retrospective-publish\SKILL.md`

```md
---
name: blog-retrospective-publish
description: "总入口 skill:当用户希望把一个刚刚完成的问题解决过程整理成博客,并在需要时发布到博客仓库、提交并推送时使用。它本身负责整体编排:先调用 solution-retrospective-blog 生成复盘内容,再在需要发布时调用 blog-repo-publish 完成仓库写入与推送。示例:\"写篇博客记录一下\"、\"把这次问题解决过程整理成博客并推送\"、\"复盘刚刚这个任务,发到我的博客里\""
---

# 任务复盘博客总入口

这个 skill 是**博客复盘与发布体系的总入口**。

它不是自己重复实现所有细节,而是负责把两类能力串起来:

1. **`solution-retrospective-blog`**
   - 负责把“刚刚完成的问题解决过程”整理成一篇结构完整、基于真实证据的技术复盘博客

2. **`blog-repo-publish`**
   - 负责检查博客仓库格式、把文章写入正确位置、做可用验证、提交并推送

所以,这个 skill 的定位是:

> **统一接住“写篇博客记录一下”这类自然语言请求,然后根据用户是否要求发布,自动把写作与发布两段工作串起来。**

## 何时使用

- “写篇博客记录一下”
- “把刚刚这个问题解决过程写成博客”
- “复盘一下从开始到成功中间经历了什么”
- “整理成一篇技术博客,并推送到我的博客仓库”
- “把这次解决过程发到我的博客里”

## 路由规则

### 情况 1:用户只要求写博客

如果用户只是要求写文章,没有要求 commit / push:

```text
直接调用 solution-retrospective-blog

情况 2:用户要求写博客并发布

如果用户同时要求:

  • 保存到博客仓库
  • 写入 _posts
  • 提交
  • 推送

那么流程应是:

1
2
1. 先调用 solution-retrospective-blog
2. 再调用 blog-repo-publish

情况 3:用户只要求“发到博客仓库”

如果文章内容已经有了,用户只是要求发布:

1
直接调用 blog-repo-publish

工作流

1
2
3
4
1. 判断用户到底是要“只写文章”,还是“写完还要发布”
2. 如果需要复盘写作,先走 solution-retrospective-blog
3. 如果需要发布,再走 blog-repo-publish
4. 最终回答里明确:文章路径、是否已提交、是否已推送、commit hash、验证边界

博客目标路径配置

这个总入口 skill 应维护一份统一的博客目标路径约定,供两个子 skill 共用:

1
2
博客仓库根目录:<BLOG_REPO_ROOT>
博文目录:<BLOG_POSTS_DIR>

例如:

1
2
博客仓库根目录:D:\Github\langkemaoxin.github.io
博文目录:D:\Github\langkemaoxin.github.io\_posts

路由时的使用规则:

  • 写作阶段:把这个路径传递给 solution-retrospective-blog
  • 发布阶段:把这个路径传递给 blog-repo-publish
  • 如果用户本次任务另行指定了博客仓库路径,则覆盖这里的默认值

不可妥协的规则

1. 不要在总入口里重复造轮子

这个 skill 的职责是编排,不是复制两个子 skill 的所有细节。

因此:

  • 内容写作规范 → 交给 solution-retrospective-blog
  • 博客仓库检查与发布规范 → 交给 blog-repo-publish

2. 必须保留“真实复盘”的原则

即使这是总入口,也不能放松最核心的要求:

  • 必须基于真实过程写
  • 不要虚构没有发生过的步骤
  • 要区分这次案例与普遍规律

3. 只有用户明确要求时才做发布动作

默认不要擅自 commit / push。

如果用户只说“写篇博客记录一下”,那就停在文章内容层。 如果用户明确说“发到我的博客仓库里”,再进入发布阶段。

推荐调用方式

写作阶段

优先使用:

1
solution-retrospective-blog

发布阶段

优先使用:

1
blog-repo-publish

一体化场景

当用户一句话同时包含“复盘 + 博客 + 发布”时:

1
2
3
blog-retrospective-publish
→ solution-retrospective-blog
→ blog-repo-publish

检查清单

1
2
3
4
- [ ] 判断用户要的是“写作”还是“写作 + 发布”
- [ ] 如果需要写作,调用 solution-retrospective-blog
- [ ] 如果需要发布,调用 blog-repo-publish
- [ ] 保证最终回复说明文章路径、提交状态、推送状态和验证边界

示例

1
2
3
4
5
6
7
用户:把刚刚这个问题复盘成博客,并推到我的博客仓库。

你应该:
1. 识别这是“写作 + 发布”的组合任务
2. 先调用 solution-retrospective-blog 生成复盘内容
3. 再调用 blog-repo-publish 完成博客仓库写入与推送
4. 最终返回文章路径、commit hash、push 结果、以及验证范围

一个好的最终交付应包含

  • 文章写到了哪里
  • 是否已经写完
  • 是否已经 commit
  • 是否已经 push
  • commit hash 是什么
  • 哪些验证已完成
  • 哪些验证因为环境限制无法完成

这样,这个总入口 skill 才真正起到了“统一编排,而不是混杂职责”的作用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
---

## 五、这套设计真正解决了什么问题

把这 3 个 skill 拆出来以后,我觉得最核心的变化不是“以后少写几句提示词”,而是整个流程终于稳定下来了。

它解决了 4 个长期会反复出现的问题:

### 1. 文章写作不再脱离真实过程

以前很容易写成一种“看起来很合理”的总结,但其实细节靠脑补。

现在 `solution-retrospective-blog` 明确要求:

- 必须基于真实工具输出
- 必须基于真实阻塞和修复过程
- 必须区分案例路径和普遍规律

这让文章的可信度明显高很多。

### 2. 发布动作不再和写作混在一起

以前“写完博客顺手发出去”听起来像一句话,实际上里面有一整套仓库层动作。

拆出 `blog-repo-publish` 之后,仓库检查、路径确认、验证边界、commit、push 都有了自己的规范。

### 3. 默认博客路径被显式配置了

以后不需要每次都重新猜文章应该写到哪里。

默认就是:

- 博客仓库:`D:\Github\langkemaoxin.github.io`
- 文章目录:`D:\Github\langkemaoxin.github.io\_posts`

### 4. 用户自然语言终于有了稳定入口

最重要的是:

我以后不需要再靠“临场猜测”去判断一句“写篇博客记录一下”到底意味着什么。

因为现在有了 `blog-retrospective-publish` 这个总入口 skill,它就是专门来接这种自然语言请求的。

---

## 六、我以后会怎么用这 3 个 Skill

以后如果任务是:

### 只写文章

例如:

> “写篇博客记录一下刚刚这个问题。”

那就优先走:

```text
solution-retrospective-blog

写文章并发布

例如:

“把刚刚这个问题复盘成博客,并发到我的博客仓库里。”

那就走:

1
2
3
blog-retrospective-publish
→ solution-retrospective-blog
→ blog-repo-publish

已经有文章,只做发布

例如:

“这篇文章已经有了,帮我写进博客仓库并推上去。”

那就直接走:

1
blog-repo-publish

这让整个博客工作流从“每次重新组织一次”变成了“以后持续复用一套固定能力”。


七、最后的结论

我现在越来越相信一件事:

真正值得固化成 Skill 的,不是某条命令,而是一整套会反复出现的决策结构。

“把刚刚解决的问题写成博客,并在需要时发布到博客仓库”这件事,看起来像写作任务,实际上中间同时牵涉到了:

  • 真实执行过程复盘
  • 技术边界解释
  • 博客仓库格式适配
  • 文件落盘与验证
  • Git 提交与推送

如果这些能力全混在一起,维护起来一定越来越乱。

而现在把它拆成:

  • solution-retrospective-blog
  • blog-repo-publish
  • blog-retrospective-publish

之后,整个系统就清楚很多了:

  • 谁负责写内容
  • 谁负责做发布
  • 谁负责接用户自然语言并编排流程

这就是这 3 个 Skill 真正的价值。