Skip to content

Commit e0698d2

Browse files
lujun9972claude
andcommitted
blog: 读:ox-skills——用 Org-mode 管理 Claude Code 的 Skill 定义
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 4644a98 commit e0698d2

1 file changed

Lines changed: 191 additions & 0 deletions

File tree

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
#+TITLE: 读:ox-skills——用 Org-mode 管理 Claude Code 的 Skill 定义
2+
#+AUTHOR: lujun9972,Claude Code
3+
#+TAGS: Emacs, Org-mode, Claude Code, AI
4+
#+DATE: [2026-05-30 Fri]
5+
#+LANGUAGE: zh-CN
6+
#+OPTIONS: H:6 num:nil toc:t \n:nil ::t |:t ^:nil -:nil f:t *:t <:nil
7+
#+DESCRIPTION: ox-skills 是一个 Org exporter backend,把 Org 文件导出为带 YAML frontmatter 的 SKILL.md 文件。它让你用 Org-mode 编写 AI coding assistant 的 skill 定义,通过 org-export 一键生成目标格式,还支持动态上下文注入和批量管理。本文从实际操作出发,展示完整的编写→导出→使用流程。
8+
9+
[[https://github.com/gicrisf/ox-skills][ox-skills]] 是一个 Org exporter backend,做一件事,把 Org 文件导出为带 YAML frontmatter 的 SKILL.md 文件。
10+
11+
如果你用 Claude Code 或 OpenCode 这类 AI coding assistant,迟早会写自己的 skill(一种用 Markdown + YAML frontmatter 定义的提示词模板)。手写 YAML frontmatter 很繁琐,skill 的内容(指令、代码示例、检查清单)说到底就是结构化文本,用 Org-mode 管理顺手得多。ox-skills 把这个流程打通了,在 Org 里写 skill,一键导出成 AI 工具需要的格式。
12+
13+
* 一个 skill 从 Org 到 SKILL.md
14+
15+
假设我们要写一个审查当前未提交改动的 skill。用 ox-skills 的方式,Org 文件长这样,
16+
17+
#+begin_src org
18+
,#+SKILL_NAME: git-review
19+
,#+SKILL_DESCRIPTION: Review current uncommitted changes and suggest improvements
20+
,#+SKILL_ALLOWED_TOOLS: Bash Read
21+
,#+SKILL_USER_INVOCABLE: true
22+
,#+SKILL_BASE_DIR: ~/.claude/skills
23+
24+
Review the current uncommitted changes for:
25+
26+
1. *Bugs*: Logic errors, edge cases, missing error handling
27+
2. *Style*: Naming, function length, code organization
28+
3. *Security*: Input validation, injection risks
29+
30+
Be constructive. Prioritize findings by severity.
31+
32+
,* Current changes
33+
34+
,#+begin_src sh :inject yes
35+
git diff HEAD
36+
,#+end_src
37+
#+end_src
38+
39+
按 =C-c C-e s s= (或者 =M-x org-export-dispatch= 选 =s s= )导出后,ox-skills 在 =~/.claude/skills/git-review/SKILL.md= 生成这样的文件,
40+
41+
#+begin_src yaml
42+
---
43+
name: git-review
44+
description: Review current uncommitted changes and suggest improvements
45+
allowed-tools: [Bash, Read]
46+
user-invocable: true
47+
---
48+
49+
Review the current uncommitted changes for:
50+
51+
1. **Bugs**: Logic errors, edge cases, missing error handling
52+
2. **Style**: Naming, function length, code organization
53+
3. **Security**: Input validation, injection risks
54+
55+
Be constructive. Prioritize findings by severity.
56+
57+
## Current changes
58+
59+
```!
60+
git diff HEAD
61+
```
62+
#+end_src
63+
64+
对比源文件和产物,能看出 ox-skills 做了什么。 =#+SKILL_*= 关键字变成 YAML frontmatter 里的对应字段,Org 的正文变成 Markdown 正文, =*Current changes*= 标题变成 =## Current changes= ,加了 =:inject yes= 的 src block 变成了带叹号的代码围栏(区别于普通的代码围栏)。
65+
66+
带叹号的代码围栏是关键差异。普通代码块是静态内容,带叹号的围栏会被 Claude Code / OpenCode 在调用 skill 时实际执行,把运行结果注入到上下文里。你调用 =git-review= skill 的时候,AI 工具先跑 =git diff HEAD= ,拿到当前改动,再基于这个结果做审查。手写 SKILL.md 也可以直接写带叹号的围栏,但 ox-skills 让你用 Org 语法( =:inject yes= )来表达,跟其他 src block 的写法一致。
67+
68+
*关键词对照。 * ox-skills 支持的 =#+SKILL_*= 关键字和对应的 YAML 字段如下,
69+
70+
| Org 关键字 | YAML 字段 | 类型 |
71+
|-----------+----------+------|
72+
| =#+SKILL_NAME= | =name= | 字符串 |
73+
| =#+SKILL_DESCRIPTION= | =description= | 字符串 |
74+
| =#+SKILL_WHEN_TO_USE= | =when_to_use= | 字符串 |
75+
| =#+SKILL_ALLOWED_TOOLS= | =allowed-tools= | 列表(空格分隔) |
76+
| =#+SKILL_USER_INVOCABLE= | =user-invocable= | 布尔( =true=/=false= ) |
77+
| =#+SKILL_MODEL= | =model= | 字符串 |
78+
| =#+SKILL_EFFORT= | =effort= | 字符串 |
79+
80+
上表是常用字段,完整列表(含 =SKILL_ARGUMENTS= 、 =SKILL_CONTEXT= 、 =SKILL_AGENT= 等)见 [[https://github.com/gicrisf/ox-skills][项目 README]] 。另外示例里的 =#+SKILL_BASE_DIR= 控制输出文件写到哪个目录,它不会被导出到 YAML 里。
81+
82+
列表类型的值用空格分隔,多个词用引号括起来。布尔类型接受 =true=/=yes= 或 =false=/=no= 。
83+
84+
* 批量管理,一个文件管多个 skill
85+
86+
用着用着你会积累十几个甚至几十个 skill。ox-skills 支持把多个 skill 放在同一个 Org 文件里,给每个标题加属性抽屉(property drawer)设置元数据,一次性全部导出。
87+
88+
注意命名变化:文件级用 =#+SKILL_NAME= ,子树属性用 =EXPORT_SKILL_NAME= (多了 =EXPORT_= 前缀)。两种写法效果一样,只是位置不同,
89+
90+
#+begin_src org
91+
,#+SKILL_BASE_DIR: ~/.claude/skills
92+
93+
,* Review skill
94+
:PROPERTIES:
95+
:EXPORT_SKILL_NAME: git-review
96+
:EXPORT_SKILL_DESCRIPTION: Review current uncommitted changes
97+
:EXPORT_SKILL_ALLOWED_TOOLS: Bash Read
98+
:END:
99+
100+
Review instructions here...
101+
102+
,* Deploy skill
103+
:PROPERTIES:
104+
:EXPORT_SKILL_NAME: deploy
105+
:EXPORT_SKILL_DESCRIPTION: Deploy to production
106+
:EXPORT_SKILL_ALLOWED_TOOLS: Bash
107+
:END:
108+
109+
Deploy instructions here...
110+
#+end_src
111+
112+
按 =C-c C-e s w= (WIM 导出,"What I Mean",导出当前子树或文件),ox-skills 会遍历当前范围内的每个带 =EXPORT_SKILL_NAME= 属性的子树,各导出一个 SKILL.md 。上面的例子会在 =~/.claude/skills/git-review/SKILL.md= 和 =~/.claude/skills/deploy/SKILL.md= 各生成一个文件。
113+
114+
如果 skill 需要按目录组织(比如把工程类 skill 放在 =engineering/= 下),用 =EXPORT_SKILL_SUBDIR= 属性,
115+
116+
#+begin_src org
117+
,* Engineering
118+
:PROPERTIES:
119+
:EXPORT_SKILL_SUBDIR: engineering
120+
:END:
121+
122+
,** Code Review
123+
:PROPERTIES:
124+
:EXPORT_SKILL_NAME: code-review
125+
:EXPORT_SKILL_DESCRIPTION: Review code changes
126+
:END:
127+
...
128+
#+end_src
129+
130+
这样导出路径变成 =~/.claude/skills/engineering/code-review/SKILL.md= 。子目录层级可以嵌套,ox-skills 会沿着上层标题的 =EXPORT_SKILL_SUBDIR= 逐层拼接路径。没有 =EXPORT_SKILL_NAME= 的标题只贡献路径,本身不会被导出。
131+
132+
* 局限:只管 SKILL.md,不管 skill 目录里的其他文件
133+
134+
ox-skills 只导出 SKILL.md 这一个文件。如果你的 skill 依赖辅助脚本、参考文档(比如 =scripts/= 和 =references/= 目录下的文件),这些不会自动管理。你需要自己维护 skill 目录下的完整结构。
135+
136+
变通办法是用 org-babel 的 =:tangle= 。在 skills.org 里把脚本作为 src block 放在对应 skill 的子树下,用 =:tangle= 指定输出路径:
137+
138+
#+begin_src org
139+
,* url2blog
140+
:PROPERTIES:
141+
:EXPORT_SKILL_NAME: url2blog
142+
:EXPORT_SKILL_DESCRIPTION: 从 URL 读取内容生成 Org-mode 博文
143+
:END:
144+
145+
skill 正文...
146+
147+
,*** lint_org.el
148+
:PROPERTIES:
149+
:HEADER-ARGS: :tangle ~/.claude/skills/url2blog/scripts/lint_org.el
150+
:END:
151+
152+
,#+begin_src emacs-lisp
153+
;; lint 脚本内容
154+
,#+end_src
155+
#+end_src
156+
157+
这样工作流变成两步, =C-c C-e s w= 导出所有 SKILL.md , =C-c C-v t= ( =M-x org-babel-tangle= )提取脚本到 skill 目录。两个 Org 原生机制拼起来,勉强算完整。缺点是 skills.org 会变得很长,所有脚本内容都堆在一个文件里。
158+
159+
* 安装
160+
161+
四种方式选一个,
162+
163+
#+begin_src emacs-lisp
164+
;; Straight
165+
(use-package ox-skills
166+
:straight (:host github :repo "gicrisf/ox-skills"))
167+
168+
;; Emacs 29+ 内置 :vc
169+
(use-package ox-skills
170+
:vc (:url "https://github.com/gicrisf/ox-skills"
171+
:rev :newest
172+
:branch "main"))
173+
174+
;; Doom Emacs
175+
;; packages.el:
176+
(package! ox-skills :recipe (:host github :repo "gicrisf/ox-skills"))
177+
;; config.el:
178+
(use-package! ox-skills)
179+
180+
;; Spacemacs
181+
;; 在 dotspacemacs-configuration-layers 或 dotspacemacs-additional-packages 里加:
182+
(ox-skills :location (recipe :fetcher github :repo "gicrisf/ox-skills"))
183+
;; 然后在 dotspacemacs/user-config 里:
184+
(use-package ox-skills)
185+
#+end_src
186+
187+
安装后,Org 导出菜单里会多一个 =s= 键( =C-c C-e s= ),下级菜单分别是 =s= 导出当前文件到一个 SKILL.md , =S= 导出到临时缓冲区(预览用), =w= 导出当前子树或文件, =a= 导出所有子树或文件。
188+
189+
* 小结
190+
191+
ox-skills 解决的问题不大但很实在,让 skill 定义回到 Org 生态。你用 Org 管理笔记、知识库、任务,现在 skill 也在一起了,不用另外手写 YAML frontmatter,不用单独维护 Markdown 模板。 如果你同时是 Org-mode 重度用户和 Claude Code 使用者,值得一试。

0 commit comments

Comments
 (0)