mcpField
B
book-to-skill

book-to-skill

github.com/virgiliojr94Agent 工作流36.4k8.7k 次安装今天更新
代码仓库

关于 book-to-skill

book-to-skill 将书籍和其他文档中的结构化知识转化为可复用的 Agent 技能,适用于构建或维护技能的用户。它提取框架、原则、方法和反模式,而非生成内容摘要,并支持分析、完整转换及更新现有技能。

主要功能

  1. 01从文档提取结构化知识
  2. 02提取框架、原则与技巧
  3. 03支持分析后再生成
  4. 04更新并合并现有技能
  5. 05适配多种 Agent 技能目录

适用场景

  1. 01将技术书籍转化为可执行技能
  2. 02先审阅知识提取结果再生成
  3. 03把新资料并入已有技能
  4. 04为不同 Agent 环境创建技能

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/virgiliojr94/book-to-skill --skill book-to-skill

安装后在 Claude Code 中输入/book-to-skill确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

.gitignore
AGENTS.md
CHANGELOG.md
BACKERS.md
CLAUDE.md
CONTRIBUTING.md
README.md
LICENSE.md
README.ru.md
SECURITY.md
SECURITY-NOTICE.md
README.zh-CN.md
.github/
FUNDING.yml
dependabot.yml
PULL_REQUEST_TEMPLATE.md
.github/ISSUE_TEMPLATE/
bug_report.md
feature_request.md
.github/workflows/
codeql.yml
deploy-docs.yml
ci.yml
book_to_skill/
__main__.py
config.py
__init__.py
cli.py
exceptions.py
dependencies.py
book_to_skill/parsers/
__init__.py
calibre.py
docx.py
epub.py

详细介绍

书籍转技能转换器

通过提取结构,将书面知识转化为可操作的 Agent 技能——而不是生成摘要。

理念

书籍中凝聚着结晶化的专业知识:历经多年发展而成的框架、原则和技术。本技能将这些知识提取为一种格式,使 GitHub Copilot CLI、Amp、Claude Code、Hermes Agent、OpenCode、OpenClaw 或其他兼容 Agent 能够反复利用。 提取结构,而非摘要。 技能不是读书报告。它是一套工具包,包含:

  • 命名框架(具有明确应用场景的思维模型)
  • 可操作原则(指导决策的规则)
  • 技术(分步方法)
  • 反模式(应避免什么以及为什么)
  • 语气校准(作者如何思考与表达)

保留作者的精确性。 框架之所以有特定名称,往往有其原因。「5 Why」不能与「多次问为什么」互换。要捕捉确切的表述。

恰当地分层深度。 简单的书 → 简单的技能。包含 10+ 个框架的复杂书籍 → 带有参考文件和按需章节的技能。


操作模式

提供四条路径。根据用户的请求进行路由:

1. 完整转换(默认)

触发: 用户在无特殊说明的情况下提供一个或多个文档/目录/glob 路径 操作: 运行以下所有步骤(步骤 0–9) 输出: 完整技能,包含 SKILL.md、chapters/、术语表、模式、速查表

2. 仅分析

触发: 用户说「分析」、「只提取」或「我想在生成前先审阅」 操作: 运行步骤 0–3,然后生成结构化提取报告(发现的框架、原则、技术)。停止——不要生成技能文件。 输出: 供用户审阅的分析报告

3. 基于先前分析生成

触发: 用户已有分析笔记,或之前运行过仅分析模式 操作: 跳过步骤 0–3,将提供的分析作为输入,运行步骤 4–9 输出: 基于所提供分析的技能文件

4. 更新 / 合并(现有技能)

触发: 用户提供一个或多个新源路径,并表示希望更新现有技能(通过指向现有技能文件夹、提供已存在于 SKILLS_HOME 中的技能 slug,或明确请求更新)。 操作: 运行步骤 0(范围外检查)、步骤 1(验证输入)、步骤 1.5(识别书籍类型)和步骤 2(提取新文件)。然后跳到步骤 5(识别/检测现有技能路径),并运行更新 / 合并工作流,将新内容合并到现有技能文件中。 输出: 更新后的现有技能,包含新增/修订的章节摘要以及合并后的索引/术语表。


技能位置

此转换器可以从多个技能系统运行。在查找此转换器的辅助脚本或写入生成的 book 技能时,请按顺序优先使用以下位置:

  1. GitHub Copilot CLI 个人技能:~/.copilot/skills/
  2. 跨 Agent 个人技能(Copilot、Amp、Codex;OpenClaw 及其默认状态):~/.agents/skills/
  3. Claude Code 个人技能:~/.claude/skills/
  4. 项目本地 Copilot 技能:.github/skills/
  5. 项目本地 Claude 技能:.claude/skills/
  6. 项目本地 Amp / Copilot / OpenClaw 技能:.agents/skills/
  7. Amp 全局技能:~/.config/agents/skills/
  8. Amp 旧版全局技能:~/.config/amp/skills/
  9. Hermes Agent 个人技能:$HERMES_HOME/skills/(默认为 ~/.hermes/skills/)
  10. Hermes Agent 项目技能:.hermes/skills/ 或 .agents/skills/
  11. OpenClaw 个人技能:${OPENCLAW_STATE_DIR:-~/.openclaw}/skills/(活动状态;~/.agents/skills/ 仅与默认状态共享)
  12. OpenClaw 项目技能:.agents/skills/ 或 skills/
  13. OpenCode 个人技能:~/.config/opencode/skills/ 或 ~/.agents/skills/
  14. OpenCode 项目技能:.opencode/skills/ 或 .agents/skills/

对于生成的 book 技能,优先使用用户级跨 Agent 根目录 ~/.agents/skills/ —— 一份物理副本即可服务于跨 Agent 主机以及使用默认状态的 OpenClaw。Copilot CLI 和 Amp 可原生发现它;Claude Code 需要从 ~/.claude/skills/<skill_name> 创建符号链接(在第 10 步中创建,规则见第 5 步)。仅当用户明确要求时,才选择主机私有或项目本地根目录。BOOK_TO_SKILL_SCOPE=project 或 personal 可以为自动化明确该选择;不要仅仅因为两种范围都可用就询问必答的范围问题。


Step 0 — 范围外检查

如果未提供任何参数,则停止并回复:

“book-to-skill 需要一个支持的文档路径、文件夹或 glob 模式。用法:book-to-skill <path-to-document-folder-or-glob>... [skill-name-slug]”

在整个工作流中:

  • 首先解析目标根目录。 在任何现有技能查找之前,先确定本次运行将写入哪里:根据 Step 5 表格和选择规则,确定用户主机的个人根目录或项目本地根目录——项目本地请求使用其项目本地根目录,绝不使用个人根目录。下文中,“解析出的根目录”即指该目标位置。
  • 识别输入路径以及可选的技能 slug。
  • 如果最后一个参数不是存在的文件、文件夹,或不存在或不匹配任何文件的 glob,并且它看起来像技能 slug(例如小写连字符、字母数字),则将其视为 SKILL_NAME。
  • 将所有其他参数视为 INPUT_PATHS 列表。
  • 如果任何输入路径是现有技能目录(包含 SKILL.md 和 chapters/ 子文件夹),或者如果 SKILL_NAME 与解析出的根目录中现有技能 slug 匹配,则将本次运行标记为 Update/Fold-in 操作(Mode 4)。
  • 重跑防护。 在开始 Full Conversion 的提取之前,根据 Step 5 的命名选项推导出预期技能 slug——作者概念形式、按标题形式,以及任何给定的 SKILL_NAME——并在解析出的根目录中检查是否存在匹配项。若匹配,STOP 并询问用户:“<skill-name> 已存在。请选择:(1) Update/Fold-in(Mode 4),(2) 验证现有技能完整并停止,或 (3) 强制完全重新生成。” 在用户选择之前,不要重新提取。在一次中断运行(网络中断、重放或继续的对话)后的上下文恢复中,重用该次运行报告的提取工作目录(其输出中的 Workdir ->,或你在 BOOK_SKILL_WORKDIR 中设置的路径),前提是它仍然完整且仍然匹配当前输入和选项——该目录存在,其 metadata.json 可读,它列出的 sources 与当前正在转换的文件在文件名和内容指纹上一一匹配(提取器在 metadata.json 中记录每个源的 sha256;根据每个文件当前存在状态重新计算指纹,并要求完全匹配——book_to_skill/utils.py 中的 reuse_is_safe() 是此检查的可执行形式),并且其记录的 extraction_mode 是本次运行正在使用的模式(Step 2 的“确认提取内容就是你要求的文档”规则)。如果它缺失(临时清理)、其 metadata.json 已不存在、源不再匹配(文件名不同,或内容指纹已更改)、记录的元数据中某个源没有 sha256(在指纹功能存在之前记录,因此无法确定新鲜度),或模式不同,则说明情况并开始全新提取,而不是恢复。如有疑问,在丢弃或恢复之前询问用户。

Step 1 — 验证输入

验证 INPUT_PATHS 中至少有一个受支持的文件、目录或 glob 模式。 对于目录和 glob,展开它们以查找匹配的受支持文件(.pdf、.epub、.docx、.txt、.md、.markdown、.rst、.adoc、.html、.htm、.rtf、.mobi、.azw、.azw3)。

如果未找到受支持文件,则以清晰的错误消息停止。


步骤 1.5 — 识别内容类型

在提取之前,询问用户:

“这些来源包含什么样的内容?这有助于我选择最佳的提取方法。

  1. 技术类 — 包含代码块、表格、公式、图表(例如编程书籍、学术论文、架构指南)
  2. 文本为主 — 主要是散文,几乎没有表格/代码(例如管理、生产力、叙事类非虚构作品)
  3. 不确定 — 我会使用快速方法,如果质量似乎有限会提醒你”

将答案保存为 BOOK_TYPE:

  • 选项 1 → BOOK_TYPE=technical
  • 选项 2 → BOOK_TYPE=text
  • 选项 3 → BOOK_TYPE=text

如果 BOOK_TYPE=technical,在继续之前告知用户:

“📐 已选择技术模式 — 使用 Docling 进行结构感知提取(表格、代码块、公式以 markdown 形式保留)。每页约需 1.5 秒,因此较长的来源预计需要几分钟。现在开始……”

如果 BOOK_TYPE=text,告知:

“📄 已选择文本模式 — 为每种文件类型使用最合适的快速提取器。纯文本/Markdown/HTML 通常几秒即可完成;PDF 在可用时使用 pdftotext。”


步骤 2 — 从源文档中提取文本

运行提取脚本,传入输入路径:

SCRIPT_PATH=""
HERMES_HOME_RESOLVED="${HERMES_HOME:-$HOME/.hermes}"
OPENCLAW_STATE_DIR_RESOLVED="${OPENCLAW_STATE_DIR:-$HOME/.openclaw}"
PROJECT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || true)"
HERMES_PROJECT_TRUSTED=false
if [ -n "$PROJECT_ROOT" ] && [ "${HERMES_AGENT:-}" = true ] && \
  command -v hermes >/dev/null 2>&1 && \
  command -v python3 >/dev/null 2>&1 && \
  hermes config get skills.trusted_project_dirs --json 2>/dev/null | PROJECT_ROOT="$PROJECT_ROOT" python3 -c 'import json, os, pathlib, sys; root=pathlib.Path(os.environ["PROJECT_ROOT"]).resolve(); sys.exit(not any(pathlib.Path(p).expanduser().resolve() == root for p in json.load(sys.stdin)))' 2>/dev/null
then
  HERMES_PROJECT_TRUSTED=true
fi

CANDIDATES=(
  "$HOME/.copilot/skills/book-to-skill/scripts/extract.py"
  "$HOME/.agents/skills/book-to-skill/scripts/extract.py"
  "$HOME/.claude/skills/book-to-skill/scripts/extract.py"
  "${OPENCLAW_STATE_DIR_RESOLVED}/skills/book-to-skill/scripts/extract.py"
  "${OPENCLAW_STATE_DIR_RESOLVED}/skills"/*/book-to-skill/scripts/extract.py
  "${OPENCLAW_STATE_DIR_RESOLVED}/skills"/*/*/book-to-skill/scripts/extract.py
  "${OPENCLAW_STATE_DIR_RESOLVED}/skills"/*/*/*/book-to-skill/scripts/extract.py
  "${OPENCLAW_STATE_DIR_RESOLVED}/skills"/*/*/*/*/book-to-skill/scripts/extract.py
  "${OPENCLAW_STATE_DIR_RESOLVED}/skills"/*/*/*/*/*/book-to-skill/scripts/extract.py
  "${OPENCLAW_STATE_DIR_RESOLVED}/skills"/*/*/*/*/*/*/book-to-skill/scripts/extract.py
  "$HOME/.config/opencode/skills/book-to-skill/scripts/extract.py"
  "$HERMES_HOME_RESOLVED/skills/book-to-skill/scripts/extract.py"
  "$HERMES_HOME_RESOLVED"/skills/*/book-to-skill/scripts/extract.py
)
if [ "${HERMES_AGENT:-}" != true ]; then
  # Project-local roots are resolved against the git worktree, not the current
  # directory: an agent can be invoked from anywhere inside the project (e.g.
  # `src/nested`) and these roots still have to be found — that is how OpenCode
  # and the other hosts discover project skills. The CWD-relative forms are kept
  # so the probe also works outside a git repository.
  if [ -n "$PROJECT_ROOT" ]; then
    CANDIDATES+=(
      "$PROJECT_ROOT/.github/skills/book-to-skill/scripts/extract.py"
      "$PROJECT_ROOT/.claude/skills/book-to-skill/scripts/extract.py"
      "$PROJECT_ROOT/.agents/skills/book-to-skill/scripts/extract.py"
      "$PROJECT_ROOT/.opencode/skills/book-to-skill/scripts/extract.py"
    )
  fi
  CANDIDATES+=(
    ".github/skills/book-to-skill/scripts/extract.py"
    ".claude/skills/book-to-skill/scripts/extract.py"
    ".agents/skills/book-to-skill/scripts/extract.py"
    "skills/book-to-skill/scripts/extract.py"
    "skills"/*/book-to-skill/scripts/extract.py
    "skills"/*/*/book-to-skill/scripts/extract.py
    "skills"/*/*/*/book-to-skill/scripts/extract.py
    "skills"/*/*/*/*/book-to-skill/scripts/extract.py
    "skills"/*/*/*/*/*/book-to-skill/scripts/extract.py
    "skills"/*/*/*/*/*/*/book-to-skill/scripts/extract.py
    ".opencode/skills/book-to-skill/scripts/extract.py"
  )
  if [ -n "$PROJECT_ROOT" ]; then
    CANDIDATES+=(
      "$PROJECT_ROOT/skills/book-to-skill/scripts/extract.py"
      "$PROJECT_ROOT/skills"/*/book-to-skill/scripts/extract.py
      "$PROJECT_ROOT/skills"/*/*/book-to-skill/scripts/extract.py
      "$PROJECT_ROOT/skills"/*/*/*/book-to-skill/scripts/extract.py
      "$PROJECT_ROOT/skills"/*/*/*/*/book-to-skill/scripts/extract.py
      "$PROJECT_ROOT/skills"/*/*/*/*/*/book-to-skill/scripts/extract.py
      "$PROJECT_ROOT/skills"/*/*/*/*/*/*/book-to-skill/scripts/extract.py
    )
  fi
fi
CANDIDATES+=(
  "$HOME/.config/agents/skills/book-to-skill/scripts/extract.py"
  "$HOME/.config/amp/skills/book-to-skill/scripts/extract.py"
)
if [ "$HERMES_PROJECT_TRUSTED" = true ]; then
  CANDIDATES=(
    "$PROJECT_ROOT/.hermes/skills/book-to-skill/scripts/extract.py"
    "$PROJECT_ROOT/.hermes/skills"/*/book-to-skill/scripts/extract.py
    "$PROJECT_ROOT/.agents/skills/book-to-skill/scripts/extract.py"
    "$PROJECT_ROOT/.agents/skills"/*/book-to-skill/scripts/extract.py
    "${CANDIDATES[@]}"
  )
fi
for candidate in "${CANDIDATES[@]}"
do
  if [ -f "$candidate" ]; then
    SCRIPT_PATH="$candidate"
    break
  fi
done

if [ -z "$SCRIPT_PATH" ]; then
  echo "Could not find scripts/extract.py for book-to-skill" >&2
  exit 1
fi

PYTHON_BIN="${PYTHON_BIN:-python3}"
if ! command -v "$PYTHON_BIN" >/dev/null 2>&1; then
  PYTHON_BIN="python"
fi

"$PYTHON_BIN" "$SCRIPT_PATH" $INPUT_PATHS --mode <BOOK_TYPE> --install-missing ask

在提取之前,脚本会检查检测到的格式所需的可选 Python 包。如果缺少更好的提取器,它会向用户提示可用的回退方案。除非安装模式明确为 yes,否则非交互式会话默认使用回退方案。

提示 — 预检环境: 运行 "$PYTHON_BIN" "$SCRIPT_PATH" --check,即可打印一份按格式划分的报告,说明已安装哪些提取器,以及安装缺失项的确切命令,而无需处理任何文件。当用户报告设置或质量问题时很有用。

这会创建一个每次运行独立的工作目录 — 默认是 <tempdir>/book_skill_work-<pid>/,或者你在 BOOK_SKILL_WORKDIR 中设置的确切路径 — 其中包含:

  • full_text.txt — 所有来源合并后的提取文本,带有清晰直观的分隔边界。
  • metadata.json — 整体合并后的大小、词数、页数、token 计数、丢弃的 EPUB 图片数量、解析后的 workdir,以及各个已处理 sources 的详细列表。

运行完成后会打印全部三个路径(Workdir ->、Text ->、Meta ->)。请从该输出中(或从 metadata.json 自带的 workdir 字段中)获取这些路径,而不要假设固定位置 — 目录名每次运行都不同,这样同一台机器上的并发提取就不会互相覆盖结果。

读取该次运行的 metadata.json 以检查结果。

在生成任何内容之前,务必确认提取出的正是你所要的文档:检查 metadata.json 中的 filename / source_file,或 full_text.txt 第一行的 SOURCE: 头。如果你在等待某个后台运行,请等待它的特定 workdir — 轮询共享路径可能会显示另一次运行的输出。


步骤 2.5 — 预检成本估算

读取本次运行的 metadata.json(提取输出中的 Meta -> 路径),并在进行任何生成之前向用户展示估算:

📖 Sources detected: <total_sources> source(s)
<list each source filename and format from the sources metadata list>
<if images_dropped > 5: warn that N source images were not read>
📄 Combined Pages/Sections: ~<N> | Words: ~<N> | Total tokens: ~<N>K

💰 Estimated token cost (Full Conversion / Update):
   Input  (reading + prompts): ~<N>K tokens
   Output (skill files generated/updated):  ~<N>K tokens
   Total:                           ~<N>K tokens

   Cost: multiply the token counts above by your model's current
   input/output per-1M-token rates (prices and model names change often —
   do not hardcode them; quote today's rate and label it as an estimate).

   ⏱  Estimated time: ~<N> minutes

📁 Files to be generated/updated:
   SKILL.md + chapter files + glossary + patterns + cheatsheet

➡  Proceed with Full Conversion / Update? (or type "analyze only" to preview first)

如何估算:

  • 输入 token ≈ metadata 中的 estimated_tokens × 1.3(每章处理的提示词开销)
  • 输出 token ≈ 章节数 × 每章预算 + 4,000(SKILL.md)+ 4,500(术语表 + 模式 + 速查表)
    • 按 BOOK_TYPE 的每章预算中值(DEPTH 在步骤 4 中稍后决定,且可提高该值):text ≈ 1,000,technical ≈ 1,800。如果用户已表明是仅作参考还是深入学习,则使用步骤 7 矩阵中对应的那一行。
  • 成本:报告 token 数量,并乘以用户当前的每百万 token 输入/输出费率。不要硬编码美元金额 — 模型名称和价格会变化;如果你展示一个,请标注为估算值并注明日期。

等待用户确认后再继续。如果他们表示“仅分析”,则切换到模式 2。


第 2.6 步 — 面向大型书籍(> 50k tokens)的 REPL 式访问

受递归语言模型(RLM)范式的启发:将 full_text.txt 视为可查询的语料库,而非一次性的读取对象。将整个文件加载进上下文会消耗你后续生成时所需的预算。

对于超过约 50k tokens 的书籍,优先使用程序化探测,而不是不带边界地 Read(full_text.txt):

# Size check before any Read
wc -w "$FULL_TEXT_PATH"

# Find chapter offsets without loading the whole file
grep -n -E "^\s*(Chapter|CHAPTER)\s+[0-9]+" "$FULL_TEXT_PATH" | head -40

# Pull only the chapter you need (lines start..end inclusive)
sed -n '<start>,<end>p' "$FULL_TEXT_PATH"

# Verify a framework is actually mentioned before claiming it in SKILL.md
grep -c -i "westrum\|dora" "$FULL_TEXT_PATH"

# Targeted Read with offset/limit avoids dumping the full file
# Read(file_path=full_text.txt, offset=<line>, limit=<lines>)

在第 3 步(结构分析)、第 7 步(逐章摘要)和第 8 步(术语表 / 模式提取)中采用此方法。对于 50k tokens 以下的书籍,单次 Read 即可。

为什么这很重要:一本 200 页的书约 75k tokens。每章重读一次(28 遍)会消耗约 2M 输入 tokens;使用 grep + sed 只提取相关片段,能让生成成本与输出成正比,而非与源文本成正比。


第 3 步 — 分析书籍结构

读取提取出的 full_text.txt 的前 8,000 个字符,以识别:

  • 书籍 标题 和 作者
  • 章节结构(寻找 "Chapter N"、"PART I"、编号标题、目录)
  • 核心主题 和学科领域
  • 大致章节数量

然后读取目录部分(如果存在),以映射所有章节。

如果模式为 "Analyze Only": 立即生成提取报告并停止。结构:

## Extraction Report — <Title>

### Author's Core Frameworks
- **<Framework Name>**: <what it is and when to apply>

### Key Principles
- <Principle>: <actionable rule>

### Techniques & Methods
- <Technique>: <step-by-step or how-to>

### Anti-patterns
- <What to avoid>: <why>

### Suggested Skill Name
`{author-lastname}-{core-concept}` — e.g. `cialdini-influence`

### Chapters Detected
| # | Title | Main Frameworks |

第 4 步 — 询问用途(仅限完整转换)

在生成之前,询问用户:

"这个 skill 应该帮助你做什么?(可多选)

  1. 在工作中应用作者的框架
  2. 用作者的心智模型进行思考
  3. 参考具体章节和概念
  4. 以上全部"

使用答案来决定 SKILL.md 核心部分中突出显示的内容。

根据答案推导 DEPTH(无需额外提示):

  • 答案 仅 为选项 3(参考)→ DEPTH=reference — 精简、快速查阅的章节。
  • 答案包含选项 1、2 或 4 → DEPTH=study — 更深入的章节,包含更多实操细节、示例和推理。

DEPTH 和 BOOK_TYPE 共同决定第 7 步中每章的 token 预算。不要 单独询问 "study vs reference" 问题 — 在此处推断。(在模式 2/3 中,跳过第 4 步时,默认 DEPTH=study。)


第 5 步 — 确定 skill 名称

如果提供了 SKILL_NAME,则将其用作 skill slug。 否则,提出两个选项并让用户选择:

  • 按作者-概念:{author-lastname}-{core-concept}(例如 cialdini-influence、meadows-systems)
  • 按标题:书籍标题的小写连字符形式(例如 designing-data-intensive-apps)

如果书籍具有强烈的方法论特征,默认使用作者-概念格式。

选择目标 skill 根目录(SKILLS_HOME)。首先根据明确的用户请求或 BOOK_TO_SKILL_SCOPE 解析 范围,然后探测 宿主。请求项目本地/项目输出会选择项目本地行;请求个人/全局输出会选择个人行。如果两个范围都未被请求,则保留既定的个人默认值(非 Hermes 宿主为 ~/.agents/skills)。不要仅因为存在项目本地根目录就强制询问范围问题。选定的根目录在写入前仍可能需要宿主批准。

宿主 Agent个人 skill 根目录项目本地根目录
GitHub Copilot CLI~/.agents/skills(原生发现).github/skills → .claude/skills → .agents/skills
Amp~/.agents/skills(原生发现).agents/skills
OpenAI Codex~/.agents/skills(原生发现;跟随符号链接).agents/skills
Hermes Agent$HERMES_HOME/skills/<category>(默认为 ~/.hermes/skills/<category>).hermes/skills/<category> → .agents/skills
Claude Code~/.agents/skills + 来自 ~/.claude/skills/<skill_name> 的符号链接.claude/skills
OpenClaw${OPENCLAW_STATE_DIR:-~/.openclaw}/skills(活动状态;仅默认状态下为 ~/.agents/skills).agents/skills → skills/
Hermes Agent 是唯一保留自身个人根目录的宿主:它按类别划分个人技能,并且不会扫描跨 Agent 根目录。使用当前活跃 profile 的 HERMES_HOME,并选择一个与所生成技能主题匹配的类别。不要手动构造 profile 路径。如果用户选择了项目本地的 Hermes 根目录,请在生成后运行 hermes skills trust <project-root>,并用 hermes skills list 验证能否被发现;在项目被信任之前,项目技能一直不可用。

对于 OpenClaw,使用当前活跃状态目录的 skills/ 根目录:${OPENCLAW_STATE_DIR:-~/.openclaw}/skills/。共享的 ~/.agents/skills 兼容根目录只有在 OPENCLAW_STATE_DIR 未设置或为默认值 ~/.openclaw 时才可被发现;如果状态目录非默认,不要声称 OpenClaw 能看到共享根目录的安装。生成后用 openclaw skills list 验证能否被发现。 | OpenCode | ~/.agents/skills(可原生发现;~/.config/opencode/skills 和 ~/.claude/skills 也会被读取) | .opencode/skills → .agents/skills → .claude/skills |

Hermes Agent 是唯一保留自身个人根目录的宿主:它按类别划分个人技能,并且不会扫描跨 Agent 根目录。使用当前活跃 profile 的 HERMES_HOME,并选择一个与所生成技能主题匹配的类别。不要手动构造 profile 路径。如果用户选择了项目本地的 Hermes 根目录,请在生成后运行 hermes skills trust <project-root>,并用 hermes skills list 验证能否被发现;在项目被信任之前,项目技能一直不可用。

OpenCode 可原生扫描跨 Agent 的 ~/.agents/skills 根目录,因此上文中的生成技能默认位置已能满足它——无需符号链接,也无需信任步骤。它还会读取自己管理的 ~/.config/opencode/skills 根目录以及 Claude 兼容根目录 ~/.claude/skills;只有在用户要求时才使用 OpenCode 管理的根目录。项目技能是通过从工作目录向上查找到 git 工作树来发现的,因此如果生成后技能没有出现,请启动一个新会话。(~/.cache/opencode/skills 是来自 skills.urls 的远程技能下载缓存,不是创作根目录——绝不要把生成的技能写入那里。)

选择规则:

  1. 个人安装:将 SKILLS_HOME 设为 ~/.agents/skills(如果目录不存在则创建)。有一个例外,以免默认行为在别人的地盘上凭空发明约定:如果 ~/.agents/skills 不存在 且 宿主的私有根目录中已包含技能,则改用该私有根目录,并在报告中说明原因。
  2. Claude Code 不会扫描 ~/.agents/skills——生成完成后,第 10 步会用 ln -sfn "$HOME/.agents/skills/<skill_name>" "$HOME/.claude/skills/<skill_name>" 将技能链接进去。
  3. Hermes Agent 个人安装使用上方的 Hermes 行,而不是跨 Agent 根目录,并且不创建符号链接。
  4. 如果用户明确要求使用宿主私有根目录(~/.copilot/skills、~/.claude/skills、~/.config/agents/skills、~/.config/amp/skills),请遵照执行并跳过符号链接。
  5. 如果用户明确要求项目本地输出,请使用其宿主对应的项目本地行。
  6. 如果该选择需要知道宿主身份(项目本地输出、Hermes 个人根目录、OpenClaw 状态根目录或 Claude Code 符号链接),而你无法确定,请询问:“你运行的是哪个 Agent——OpenCode、OpenClaw、Hermes Agent、GitHub Copilot CLI、Amp、Codex 还是 Claude Code?”
  7. 对于 OpenClaw 个人输出,使用 ${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/skills。共享的 ~/.agents/skills 根目录只有在 OPENCLAW_STATE_DIR 未设置或等于默认值 $HOME/.openclaw 时才是有效的 OpenClaw 目标;否则请使用当前活跃状态根目录或项目/额外目录。
  8. 如果用户明确要求使用 OpenClaw 管理的个人根目录,请使用当前活跃状态根目录,并用 openclaw skills list 验证能否被发现。 将 SKILLS_HOME 设置为选定的根目录,并检查 $SKILLS_HOME/<skill_name>/ 是否已存在。在 Claude Code 上,还要检查 ~/.claude/skills/<skill_name> 是否作为真实目录(而非符号链接)存在——之前的安装可能就位于那里;如果是这样,在继续之前主动提出迁移它(将该目录移动到 ~/.agents/skills/,并用符号链接替换原路径)。 如果该技能已存在,提示用户选择:
  9. 更新 / 折叠合并(模式 4)——将新文件/内容整合到现有技能组件中。
  10. 覆盖——删除并从头重新生成该技能。
  11. 重命名——追加 -2 或使用不同的自定义 slug。

如果用户选择更新 / 折叠合并,则在步骤 2.5 之后立即进入更新 / 折叠合并工作流部分(跳过步骤 3、4、6、7、8、9)。


步骤 6 — 创建技能目录结构

mkdir -p "$SKILLS_HOME/<skill_name>/chapters"

步骤 7 — 生成章节摘要

Token 预算规则 — 关键(自适应):

每章预算随 BOOK_TYPE 和 DEPTH 而缩放。技术类章节需要为代码和表格留出空间;学习深度需要为逐步推理留出空间。从以下矩阵中选择预算:

DEPTH=referenceDEPTH=study
BOOK_TYPE=text800–1,200 tokens1,000–1,800 tokens
BOOK_TYPE=technical1,200–1,800 tokens2,000–3,000 tokens
  • 这些是每个文件的目标值,而非硬性上限——内容密集的章节可能超出,内容单薄的章节可能低于。密度仍然胜过长度(质量规则 #3):绝不要为了凑数而填充。
  • 文件是按需加载的,因此更大的章节只有在实际被读取时才会消耗 token。
  • 在两个单元格之间难以抉择时(例如混合内容的书),使用较低的预算,让深度来自精确而非体量。

DEPTH=study 是靠内容赢得的,而不是靠更大的数字。 标准章节模板(核心思想 → 关联到)自然会让内容密集的散文章节落在 700–900 tokens 左右。要诚实地——而非通过填充——达到学习预算,学习深度的章节必须添加具体材料:

  • 复现一个来自该章节的完整示例或产物(例如示例新闻稿、一段对话样本、一份填好的模板、作者逐步推演的一个决策),放在 ## Worked Example 部分下。这是最大的杠杆,也是学习者回访的主要原因。
  • 将每个框架的“如何做”扩展为明确的步骤或标准,而非一句话。
  • 为排名前 1–2 的框架添加简短的“为何有效 / 失败模式”注释。

如果某个章节确实没有完整示例且难以扩展,就让它落在学习下限之下,而不是填充——并在其核心思想中注明该章节内容单薄。相比之下,reference 深度的章节会刻意省略完整示例,只保留可直接用于决策的要点。

对于在步骤 3 中识别出的每一个章节/主要部分:

阅读提取出的 full_text.txt 中对应的部分(使用字符偏移量或 grep 查找章节标题)。

使用以下结构创建 $SKILLS_HOME/<skill_name>/chapters/ch<NN>-<slug>.md。

根据 BOOK_TYPE 调整侧重:

  • technical → 优先处理“代码示例”、“参考表”和“命令与 API”部分;保留精确语法
  • text → 优先处理“引入的框架”、“心智模型”和“关键要点”;跳过空的技术性部分
# Chapter N: <Full Title>

## Core Idea
<1–2 sentences: the single most important thing this chapter teaches>

## Frameworks Introduced
- **<Framework Name>**: <exact formulation — preserve the author's naming>
  - When to use: <specific situation>
  - How: <steps or criteria>

## Key Concepts
- **<Term>**: <precise definition in 1 sentence>
(5–10 most important terms from this chapter)

## Mental Models
<2–4 frameworks or thinking tools. Write as "Use X when Y" or "Think of X as Y">

## Anti-patterns
- **<What to avoid>**: <why it fails>

## Code Examples *(technical books only — omit if BOOK_TYPE=text)*

```<language>
<key code example from this chapter>
  • 它演示了什么:<一行说明>

Reference Tables (仅技术类书籍——若 BOOK_TYPE=text 则省略)

Worked Example (仅 DEPTH=study——DEPTH=reference 则省略)

Key Takeaways

  1. <可操作的见解>
  2. <可操作的见解>
  3. <可操作的见解> (3–7 条实践者必须记住的要点)

Connects To

  • 第 N 章:<为什么本章与之相关>
  • <概念>:<它所连接的外部概念或标准>

---

## Step 8 — Generate supporting files

### glossary.md
Create `$SKILLS_HOME/<skill_name>/glossary.md`:
- Every significant term from the book, alphabetically sorted
- Format: `**Term** — definition (Ch N)`
- Max 1,500 tokens

### patterns.md
Create `$SKILLS_HOME/<skill_name>/patterns.md`:
- All concrete techniques, design patterns, algorithms from the book
- Format: `## Pattern Name\n**When to use**: ...\n**How**: ...\n**Trade-offs**: ...`
- Max 2,000 tokens

### cheatsheet.md
Create `$SKILLS_HOME/<skill_name>/cheatsheet.md`:

**This is the most differentiated layer of the skill — treat it as a reasoning aid, not a keyword list.** Anyone can grep the glossary for a term. The cheatsheet captures the author's *judgment*: the decisions they'd make and why. It's the file that turns "I know the words" into "I'd act the way the author would".

Prioritize, in order:
1. **Decision rules** — "When X, do Y, because Z." The if/then logic the author applies, stated so the reader can apply it without re-reading the book.
2. **Decision trees / flowcharts** (as nested bullets or a small table) — for choices with more than two branches.
3. **Trade-off matrices** — competing options scored on the dimensions the author cares about, so the reader can pick under their own constraints.
4. **Thresholds & defaults** — the specific numbers, ratios, or rules of thumb the author commits to (e.g. "keep functions under ~20 lines", "alert when error budget < 10%").
5. **Tells & smells** — fast heuristics for recognizing a situation ("if you see X, you're probably in trouble Y").

Avoid: bare term→definition rows (that's the glossary), and prose paragraphs (that's the chapters). Every line should help the reader *decide* something.

- Format mostly as compact tables and decision rules; the content you'd want on a single printed page kept beside you while working.
- Max 1,200 tokens.

---

## Step 9 — Generate the master SKILL.md

**CRITICAL TOKEN BUDGET: Keep SKILL.md body under 4,000 tokens.**
Compaction truncates from the END — put the most important content FIRST.

Create `$SKILLS_HOME/<skill_name>/SKILL.md`:

```markdown
---
name: <skill_name>
description: "Knowledge base from \"<Full Title>\" by <Author(s)>. Use when applying <author>'s frameworks for <key topics, 3–6 terms>, studying the book, or referencing its concepts."
---



# <Full Title>
**Author**: <Author(s)> | **Pages**: ~<N> | **Chapters**: <N> | **Generated**: <YYYY-MM-DD>

## How to Use This Skill

- **Without arguments** — load core frameworks for reference
- **With a topic** — ask about `replication`, `pricing`, or another indexed topic; I find and read the relevant chapter
- **With chapter** — ask for `ch05`; I load that specific chapter
- **Browse** — ask "what chapters do you have?" to see the full index

When you ask about a topic not covered in Core Frameworks below, I will read
the relevant chapter file before answering.

---

## Core Frameworks & Mental Models


<generate 2,000 tokens of the most critical frameworks and insights here>

---

## Chapter Index

| # | Title | Key Frameworks |
|---|-------|----------------|
| [ch01](chapters/ch01-<slug>.md) | <Title> | <framework1>, <framework2> |
| [ch02](chapters/ch02-<slug>.md) | <Title> | <framework1>, <framework2> |
...

## Topic Index


- **<Term>** → ch<N>[, ch<N>]
- **<Term>** → ch<N>

## Supporting Files

- [glossary.md](glossary.md) — all key terms with definitions
- [patterns.md](patterns.md) — all techniques and design patterns
- [cheatsheet.md](cheatsheet.md) — quick reference tables and decision guides

---

## Scope & Limits

This skill covers the book content only. For hands-on implementation in your codebase,
combine with project-specific tools. For topics beyond this book, check related skills
or ask the agent directly.
<if images_dropped > 5: state that N source images were not read>

第 9.5 步 — 扫描生成的 skill

在报告成功、在另一个会话中加载该 skill 或发布它之前,运行建议性安全扫描:

SKILL_CONVERTER_ROOT="$(cd "$(dirname "$SCRIPT_PATH")/.." && pwd)"
"$PYTHON_BIN" "$SKILL_CONVERTER_ROOT/tools/scan_generated_skill.py" "$SKILLS_HOME/<skill_name>"

如果扫描器以非零状态退出,请停止并让人类审查其文件/行号发现项。不要默默重写生成的文件,也不要在发现项得到解决或明确接受之前加载或发布该 skill。


第 10 步 — 清理并报告

如果宿主是 Claude Code,且 SKILLS_HOME 为 ~/.agents/skills(默认的个人安装位置),请用符号链接将该 skill 暴露给 Claude Code——Claude Code 只扫描 ~/.claude/skills:

mkdir -p "$HOME/.claude/skills"
LINK="$HOME/.claude/skills/<skill_name>"
TARGET="$HOME/.agents/skills/<skill_name>"
if [ -d "$LINK" ] && [ ! -L "$LINK" ]; then
  CLAUDE_STATUS="skipped-realdir"                 # Step 5 migration declined; leave the old dir
else
  ln -sfn "$TARGET" "$LINK" 2>/dev/null || true
  # Read the link back — do NOT trust that `ln` did what was asked. On Windows/MSYS
  # `ln -s` may COPY instead of link (or need Developer Mode / an elevated shell), and
  # PowerShell/cmd have no `ln` at all. The report must reflect what is on disk, not the
  # fact that the command ran.
  if [ -L "$LINK" ] && [ "$(readlink "$LINK")" = "$TARGET" ]; then
    CLAUDE_STATUS="linked"
  elif [ -e "$LINK" ]; then
    CLAUDE_STATUS="copy"                           # a real file/dir landed instead of a link
  else
    CLAUDE_STATUS="absent"                         # ln unavailable or refused
  fi
fi

真实目录防护是必需的:ln -sfn 指向一个已存在的真实目录时,会把链接嵌套到该目录内部(~/.claude/skills/<skill_name>/<skill_name>),使 Claude Code 继续加载过期副本。如果用户在 Step 5 迁移中选择了拒绝,请跳过符号链接并在报告中说明——在完成迁移之前,Claude Code 会继续使用旧目录。

在报告任何关于该链接的内容之前,先读回该链接。 符号链接是一种声明,而非事实:"Discoverable by" 一行应依据 CLAUDE_STATUS(磁盘上实际存在的内容)填写,绝不能依据"命令已发出"。当链接缺失或是副本时,不要硬性失败——该 skill 存在于 hub,其他所有宿主仍能找到它;诚实的报告应是"已写入 ~/.agents/skills/<skill_name>;在创建链接之前,Claude Code 不会看到它",而不是中止。(Windows 线索,未经证实:目录联接——在提权的 cmd 中执行 mklink /J,或在 PowerShell 中执行 New-Item -ItemType Junction——既不需要开发者模式,也不需要符号链接特权;如果你尝试它,这不会改变先读回再报告的规则。)

当用户选择了宿主私有或项目本地的根目录时(Step 5,规则 3-4),跳过此步骤。

然后清理提取工作目录:

PYTHON_BIN="${PYTHON_BIN:-python3}"
if ! command -v "$PYTHON_BIN" >/dev/null 2>&1; then
  PYTHON_BIN="python"
fi

Remove **the work directory this run actually used** — the `Workdir ->` path from the
extraction output, which is also stored as `workdir` in `metadata.json`. Never delete a
directory you did not create: another extraction may be running beside yours.

```bash
# WORKDIR is the path this run reported; quote it in case of spaces.
rm -rf "$WORKDIR"

等价地,如果你仍有元数据文件:

"$PYTHON_BIN" - "$WORKDIR_METADATA_JSON" <<'PY'
import json
import shutil
import sys
from pathlib import Path

meta_path = Path(sys.argv[1])
workdir = json.loads(meta_path.read_text(encoding="utf-8")).get("workdir")
if workdir:
    shutil.rmtree(workdir, ignore_errors=True)
PY

此文件的旧版本会删除单个固定的 book_skill_work 目录。该路径已不再使用,因此这样的清理现在是无害的空操作,而不再可能删除某个并发运行的输出。

然后向用户报告:

✅ Skill created: $SKILLS_HOME/<skill_name>/

📚 Book: <Full Title> — <Author>
📄 Pages: ~<N> | Chapters: <N>

Files generated:
  SKILL.md         — core frameworks + index   (~X tokens)
  chapters/        — <N> chapter summaries     (~X tokens each, ~X total)
  glossary.md      — key terms                 (~X tokens)
  patterns.md      — techniques & patterns     (~X tokens)
  cheatsheet.md    — quick reference           (~X tokens)
  ─────────────────────────────────────────────────────
  Total skill size: ~X tokens (loaded on-demand, not all at once)

💡 Tip: check your agent's session cost/usage command to see actual token usage.

Usage:
  Ask for <skill_name>                  → load core frameworks
  Ask <skill_name> about <topic>        → find and explain a topic
  Ask <skill_name> for ch<N>            → dive into a specific chapter

Discoverable by: <only what is true for the chosen destination — see below>

Somewhere else?  mv ~/.agents/skills/<skill_name> <dest_root>/<skill_name> \
                   && ln -sfn <dest_root>/<skill_name> ~/.claude/skills/<skill_name>

Prompted for permission on every file? That is your host gating writes outside the
working directory. Say "save it in this project" and re-run to write inside it.

Reload (if your agent doesn't auto-detect new skills):
  GitHub Copilot CLI:  /skills reload
  Claude Code:         restart the session
  Amp:                 restart the session
  Hermes Agent:         start a new session
  OpenClaw:             openclaw skills list (new session if watcher disabled)
  OpenCode:             start a new session

Share this skill (optional):
  GitHub repo, installable on any host (Step 11):  say "publish"
  Copilot ecosystem:  gh skill publish $SKILLS_HOME/<skill_name>

"Discoverable by" 一行应依据 CLAUDE_STATUS(读回结果)填写,绝不能依据 ln 已运行这一事实——对于 ~/.agents/skills 安装:

  • linked → "Copilot CLI、Amp、Codex(原生);Claude Code 通过符号链接 ~/.claude/skills/<skill_name>"
  • skipped-realdir → "Copilot CLI、Amp、Codex(原生);不包括 Claude Code——请先迁移 ~/.claude/skills/<skill_name> 处的真实目录"
  • copy 或 absent → "Copilot CLI、Amp、Codex(原生);不包括 Claude Code——宿主无法创建符号链接(普通副本会在下次 Update/Fold-in 时发生偏移)。请启用开发者模式 / 手动创建链接,或从 ~/.agents/skills 运行该 skill"
  • Hermes Agent 个人根目录 → "Hermes Agent(来自 $HERMES_HOME/skills/<category>)";不声明符号链接,也不声明跨 Agent,因为其他宿主不扫描 Hermes 根目录
  • 其他宿主私有或项目本地根目录 → 只列出扫描该根目录的宿主;不声明符号链接 "Somewhere else?" 重定位行必须与实际采用的路径相符,这样它才不会破坏该次运行刚刚创建的符号链接。mv 始终以最终的 skill 目录 <dest_root>/<skill_name> 为目标,而绝不能是 <dest_root> 本身。 mv ~/.agents/skills/mybook ~/.copilot/skills && ln -sfn ~/.copilot/skills ~/.claude/skills/mybook 读起来像是有效的,其实并不是:skill 会落到 ~/.copilot/skills/mybook,而链接却指向上一级的根目录,于是 Claude Code 解析到一个没有 SKILL.md 的目录,而这正是这一行所要避免的破坏。替换为用户实际指定的目标位置,这样打印出的命令就带有真实路径,没有任何需要解读的地方:
  • ~/.agents/skills + 符号链接 → mv ~/.agents/skills/<skill_name> <dest_root>/<skill_name> && ln -sfn <dest_root>/<skill_name> ~/.claude/skills/<skill_name>
  • 主机私有根目录,包括 Hermes Agent → mv <src_root>/<skill_name> <dest_root>/<skill_name>
  • 项目本地根目录 → mv <project_root>/<skill_name> <dest_root>/<skill_name>

"Prompted for permission on every file?" 这一行是针对会拦截工作目录之外写入的主机(任何个人范围根目录都属于 cwd 之外)给出的答案:目标位置已在上文说明,而一行修复方法——重新运行并请求使用项目本地根目录——就在其旁边。仅在个人范围安装时保留它;当用户已经选择项目本地时,将其删除。


第 11 步 — 将生成的 skill 发布到 GitHub(可选)

在第 10 步报告之后,只提供一次——并且仅当第 9.5 步扫描通过时:

"Want me to publish this skill to GitHub so any Agent Skills host can install it with npx skills add? (yes / skip)"

如果用户拒绝,就到此为止。要求:gh 命令行,且已通过身份验证(检查 gh auth status)。如果缺少 gh 或未通过身份验证,可提出帮忙设置(brew install gh 或 https://cli.github.com ,然后 gh auth login)——或者使用无需 gh 的路径:用户在 GitHub 网页界面中创建一个所选可见性的空仓库,然后你运行下面的 git init/add/commit 命令,接着运行 git remote add origin <repo-url> && git push -u origin main。下面的可见性规则同样适用于通过网页创建的仓库。

可见性是一个单独的封闭式问题——绝不推断,绝不从先前的回答中读取。 一旦用户接受,就单独询问它,并要求用一个词回答:

"Private or public repository? Reply with one word: private or public."

回答必须就是 public,而不仅仅是包含它——这是一条硬性规则,不是建议。 除一种情况外,在所有情况下都以 --private 运行 gh repo create:对可见性问题的回答是那个光秃秃的词 public。禁止子字符串匹配,因为一句关于来源许可的话并不是可见性回答——"it's public domain"、"the book is public domain"、"it's publicly available" 都是在描述材料,而不是仓库,并且都解析为 --private。改述、一句话、模棱两可的回答、沉默,或你自己的推断都不是同意:重新询问一次,如果回答仍然不是那个光秃秃的词,就使用 --private 并在报告中说明。私有仓库之后可以转为公开;对源自书籍的内容进行公开推送则无法取消发布。

版权关卡——在创建仓库之前始终应用: 章节文件是合成的摘要,不是原始文本,但它们仍然源自源材料。根据 README 的版权与合理使用政策,由第三方受版权保护的书籍生成的 skill 必须保持私有;只有在来源是用户自己的作品、开放许可的内容,或用户明确确认其有权公开再分发的材料时,才提供公开——并说明适用的是哪种情况。能够访问公司内部材料并不等于获准披露它:源自内部文档的 skill 保持私有,除非用户声明其拥有发布权。

如果接受:

  1. 在 $SKILLS_HOME/<skill_name>/ 内添加一个仓库 README.md(绝不要覆盖已有文件)——包含技能标题、一段描述(“由 使用 book-to-skill 从 生成的 Agent skill”)、下文第 3 步中的安装命令、文件清单,以及一条说明:内容是综合整理的摘要,而非原书文本。
  2. 将该 skill 文件夹初始化为 git 仓库并创建远程仓库(默认仓库名为 <skill_name>;允许用户覆盖——有些人偏好 <skill_name>-skill 后缀)。嵌套仓库防护: 首先检查该 skill 文件夹是否已位于某个 git 仓库内(git -C "$SKILLS_HOME/<skill_name>" rev-parse --show-toplevel —— 对于 .claude/skills/ 这类项目本地根目录,情况总是如此)。如果是,切勿就地执行 git init:外层仓库会将该文件夹记录为嵌入式仓库(gitlink,mode 160000)且不含 .gitmodules,而外层项目的新克隆会静默遗漏该 skill。取而代之,应将 skill 文件夹复制到临时目录,从副本中运行以下命令,并告知用户:已发布的仓库——而非项目本地文件夹——才是远程仓库的工作副本。
cd "$SKILLS_HOME/<skill_name>"
git init -b main
git add -A
git commit -m "Add <skill_name> skill"
gh repo create <repo_name> --private --source . --push
# --private is the default; substitute --public ONLY under the visibility rule above
# (the visibility answer WAS the bare word "public" AND the copyright gate allows it)
  1. 报告仓库 URL 和跨主机安装命令:
✅ Published: https://github.com/<owner>/<repo_name> (<private|public>)

Install on any Agent Skills host:
  npx skills add https://github.com/<owner>/<repo_name> --skill <skill_name>

当嵌套仓库防护被触发、且仓库是从临时副本发布时,添加一行——该本地文件夹永远不会获得远程仓库,因此其永远不会出现 Update/Fold-in 推送提示:

⚠️  Published from a copy: <skill folder> sits inside another git repository, so it has
    no remote of its own. To publish a later update, re-run Step 11, or clone
    https://github.com/<owner>/<repo_name> and fold new material into the clone.

根级 SKILL.md 布局正是 skills CLI 所检测的布局,因此该仓库可直接安装——无需重新组织。除嵌套仓库情况外,本地文件夹仍是本机的实时安装位置,也是远程仓库的工作副本,因此后续 Update/Fold-in 运行可以将更改提交并推送到同一远程仓库。


Update / Fold-in 工作流

对 $SKILLS_HOME/<skill_name>/ 处的现有 skill 执行 Update/Fold-in 操作时:

1. 读取现有 Skill 结构

读取并解析现有 skill 的文件:

  • 读取 $SKILLS_HOME/<skill_name>/SKILL.md,解析现有的 Chapter Index、Topic Index、元数据(作者、总章节数)和 Core Frameworks。
  • 列出 $SKILLS_HOME/<skill_name>/chapters/ 中的所有文件,找出最高章节编号(例如 ch12)。
  • 读取 $SKILLS_HOME/<skill_name>/glossary.md、$SKILLS_HOME/<skill_name>/patterns.md 和 $SKILLS_HOME/<skill_name>/cheatsheet.md,查看已索引的术语和框架。
2. 匹配内容并区分修订与新增

分析本次运行 full_text.txt(提取输出中的 Text -> 路径)中新提取的文本,判断新内容属于以下哪种情况:

  • 对现有章节的更新/修订:如果新内容的某一部分直接更新或扩展了现有章节的主题,则读取现有章节文件,将新细节合并进去,并重写该文件。
  • 新增内容:如果内容引入了新章节、论文或独立小节,则在 chapters/ 下创建新的章节摘要文件。从现有最高章节编号之后开始编号(例如,如果现有章节止于 ch12,则创建 ch13-*.md、ch14-*.md 等)。
3. 生成或更新章节摘要文件

对于每个新增或修订的章节:

  • 读取提取出的新文本中对应的部分。
  • 遵循 Step 7 中的格式指南来构建摘要。
  • 在 $SKILLS_HOME/<skill_name>/chapters/ 中写入/更新该文件。
4. 合并支撑文件
  • 合并 glossary.md:
    • 读取现有的 $SKILLS_HOME/<skill_name>/glossary.md。
    • 从新内容中提取所有新术语和定义(Step 8 术语表指南)。
    • 合并现有术语和新术语列表,并按字母顺序排列。
    • 如果某个术语已存在,则向其追加新的章节/来源引用(例如 **Term** — definition (Ch 4, Ch 13))。
    • 用完全合并、按字母顺序排列的列表重写 $SKILLS_HOME/<skill_name>/glossary.md。
  • 合并 patterns.md:
    • 读取现有的 $SKILLS_HOME/<skill_name>/patterns.md。
    • 从新内容中提取任何新技术、算法或模式。
    • 追加新模式,确保格式一致,并保持总长度简洁(少于 2,500 tokens)。
  • 合并 cheatsheet.md:
    • 读取现有的 $SKILLS_HOME/<skill_name>/cheatsheet.md。
    • 提取新的比较规则、决策表或参数指南。
    • 将它们整洁地整合到 cheatsheet 结构中。
5. 重新生成主 SKILL.md

更新主 skill 文件 $SKILLS_HOME/<skill_name>/SKILL.md:

  • 元数据:递增章节数,更新预估页数,并在合适时添加新的来源名称。将 Generated 日期更新为当前日期。
  • 核心框架:融入新内容中影响最大的心智模型或原则(确保整个文件保持在 4,000 tokens 以下)。
  • 章节索引:将新章节追加到索引表中,并链接到新创建的文件。
  • 主题索引:按字母顺序合并新主题。如果某个现有主题也在新章节中有所涵盖,则在其行后追加新的章节链接(例如 - **Topic** → ch05, ch13)。
6. 扫描、清理并报告

文件成功写入并合并后,运行 Step 9.5,然后继续执行 Step 10,执行清理并打印自定义更新报告,汇总新增章节、合并的术语表条目以及更新后的索引。如果 skill 文件夹是一个带有远程仓库的 git 仓库(通过 Step 11 发布),则提议提交更新并推送。


质量规则

  1. 提取结构,而非摘要 — 捕获具名框架、精确表述、反模式;而不是章节回顾
  2. 保留作者的精确性 — “The 5 Whys” ≠ “多次询问为什么”;保留精确命名
  3. 密度优先于完整性 — 1,000 tokens 的摘要胜过 10,000 tokens 的摘录
  4. 实践者语气 — 写“在 Y 时使用 X”,而不是“书中解释了 X”
  5. 将 SKILL.md 前置 — 压缩会保留前 5,000 tokens;最重要的内容放在最前面
  6. 章节文件按需加载 — 在加载之前,它们不计入 skill 预算
  7. 绝不复制原始书本文本 — 始终综合、概括、提取信号
  8. 主题索引至关重要 — 这是 Agent 导航到正确章节文件的方式

评论

支持 Markdown