用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/ghost-him/ZeroLaunch-rs --skill add-rule命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | add-rule |
| description | 分析规则需求,设计 TTSR 规则的 frontmatter(condition、scope),生成 .omp/rules/ 下的规则文件 |
| argument-hint | 无直接参数 — 通过自然语言描述规则内容来触发 |
分析用户描述的约束或模式,设计合适的 condition 和 scope,生成带 frontmatter 的 .omp/rules/*.md 规则文件。
在对话中出现以下表述时触发:
遇到以下情况,不建议生成规则文件:
→ 以上情况建议用户改用 conversation 中的一次性提醒。
通读用户描述的规则内容,将零散的需求翻译成结构化的分析结果。按以下维度逐一确认:
1. 约束性质 — 这条规则是在约束什么?
2. 触发时机 — 用户希望规则在什么场景下"跳出来"?
unsafe 块、写测试、写某种 import)read 读某个配置文件)text / thinking / tool:<name> 哪个 scope token3. 约束对象的具体特征 — 选一个"最独特"的标识符:
extract_value、Bun.sleep、setTimeout)MyType、Result、Optional)unsafe、unwrap、todo!)@core/、crate::utils)4. 文件范围 — 规则约束应用在哪些文件上?
src/commands/**/*.rs)**/*.test.ts)src/main.rs)
→ 这个直接决定 tool:<name>(<glob>) 中的 glob在分析过程中如果用户描述的规则有歧义(例如"测试里不能用 unwrap",但没说是 Rust 还是 JS),先确认再继续。分析完成后,将以上结构化结果带入第二步映射到 frontmatter 字段。
根据规则内容,设计规则文件中的 frontmatter 字段。TTSR(Time-Traveling Stream Rules)通过这套元数据决定何时匹配(condition)和在哪匹配(scope)。
先理解 TTSR 是怎么工作的 —— 数据流向:
助手在"说话"(生成回复)
│
├─ 写自然语言(text)──→ text 缓冲区
├─ 思考过程(thinking)──→ thinking 缓冲区
└─ 调用工具(tool)──→ tool 缓冲区
│
▼
每个缓冲区的内容不断累积,
每来一段新内容就拿 condition 正则去匹配
│
匹配上了?
├─ 否 → 继续流
└─ 是 → scope 允许在这个场景触发吗?
├─ 否 → 继续流
└─ 是 → 中断助手 → 注入规则内容 → 重试
拆开解释几个术语:
text — 助手写的自然语言正文(就是你看到的对话回复)thinking — 模型的内心独白/思考过程(如果你开了思维链)tool — 助手调用工具时传的参数(例如 edit 工具传的补丁内容、write 工具传的文件内容)edit/write 这类工具时,参数可能是补丁格式(hashline),不是直接的可读代码。matcherDigest 是工具提供的一个"翻译器",能把补丁格式还原成最终要写入的源码。这样你写 condition 时就可以直接写源码里出现的函数名,而不用关心补丁格式长什么样。一句话总结:condition 正则匹配的是"助手正在说/写的内容"(不是文件名,不是文件内容快照),scope 控制的是"在哪种流场景下才允许触发"。
condition — 触发正则表达式condition 是一个正则表达式(或表达式数组),匹配流缓冲区内容(stream buffer):
tool:edit、tool:write、tool:read 等):匹配工具调用的参数原始 JSON,如果工具提供了 matcherDigest(如 edit/write 的源码快照还原器),则匹配还原后的标准化源码快照text):匹配助手生成的 prose 文本thinking):匹配模型的 thinking/chain-of-thought 文本当任意 condition 命中缓冲区时,规则触发中断当前流,注入规则内容后重试。
类型:string | string[](数组 = OR 语义,任一匹配即触发)
设计原则:
| 合并(注意转义)".*",匹配所有流内容(注意会增加 token 消耗)匹配内容随流来源变化,请根据规则的实际触发场景选择:
| 约束场景 | condition 匹配的内容 | 推荐 condition | 说明 |
|---|---|---|---|
| 约束 helper 函数调用 | edit/write 的源码快照 | "extract_value" | 函数名出现在写入的代码中 |
| 约束 import 模式 | edit/write 的源码快照 | "from '@core/parser'" | import 语句出现在写入的源码中 |
| 约束工具行为(如禁用某工具) | 工具参数 JSON | '"tool_name"' | 工具名称出现在参数 JSON 中 |
| 约束框架用法(如 unsafe 代码) | 写作的 prose/代码 | "unsafe" | 助手在生成代码时出现关键字 |
| 约束 serde 反序列化 | edit/write 的源码快照 | "serde_json::from_str|serde_json::from_value" | 反序列化调用写入代码时触发 |
| 约束全局架构 | 所有流 | ".*" | 始终触发(注意会增加 token 消耗) |
注意:
- condition 匹配的不是文件名,而是流内容。文件路径约束由
scope控制- 如果 condition 值看起来像文件 glob(如
*.rs、src/**/*.ts),系统会自动将其推导为tool:edit(<glob>), tool:write(<glob>)scope,并将 condition 设为".*"。这是一种简写形式,手动编写时建议明确写 condition + scope- 支持 PCRE 风格的头部内联 flag:
(?i)(忽略大小写)、(?m)(多行)、(?s)(单行/DOTALL),会自动翻译为原生 JS RegExp flags
scope — 触发的流范围
scope定义哪些流来源(text / thinking / tool)在哪些路径上会触发规则检查。
类型:string | string[],每个 token 为以下格式之一:
| Token | 含义 | 示例 |
|---|---|---|
text | 匹配助手自然语言输出(prose) | text |
thinking | 匹配思考过程文本 | thinking |
tool / toolcall | 匹配所有工具调用 | tool |
tool:<name> | 匹配指定工具的所有调用 | tool:edit、tool:write、tool:read |
tool:<name>(<glob>) | 匹配指定工具中路径匹配 glob 的调用 | tool:edit(src/**/*.rs) |
<bare_name> | 裸工具名(等同于 tool:<bare_name>) | edit、write |
设计原则:
tool:edit(<glob>) 和/或 tool:write(<glob>),不要用 tool:edit(**/*.rs) 覆盖整个项目,尽量缩小到规则真正约束的目录text tokentext 让写作时触发默认行为:scope 为空时,系统自动启用 text + tool(所有 prose 和工具调用,排除 thinking)
Scope 示例:
| 适用范围 | 推荐 scope |
|---|---|
| 单个模块的代码写操作 | "tool:edit(src/path/to/mod.rs), tool:write(src/path/to/mod.rs)" |
| 某个目录下所有代码操作 | "tool:edit(src/commands/**/), tool:write(src/commands/**)" |
| 分散文件 + prose 中提及 | "text, tool:edit(src/a.rs), tool:edit(src/b.rs)" |
| 所有 .rs 文件的编辑 | "tool:edit(**/*.rs)" |
| 全局(所有流) | "text, thinking, tool" |
---
name: my-rule
description: 禁止在 Rust 测试中使用 unwrap()
condition:
- "\.unwrap\(\)"
- "(?i)unwrap"
scope:
- tool:edit(**/*.rs)
- tool:write(**/*.rs)
---
提示:生成规则文件时,直接使用 frontmatter YAML 格式。
condition和scope支持 YAML 序列(数组形式)或逗号分隔的字符串。
在 .omp/rules/ 下创建 <short-name>.md,格式:
---
name: <规则文件名>
description: <一句话描述规则约束什么>
condition: <触发正则,支持数组或字符串>
scope: <流范围 token,支持数组或逗号分隔>
---
# <规则标题>
<规则正文,包含具体的行为约束、原因、示例>
文件命名规则:
kebab-case(短横线命名),例如 no-unwrap-in-tests.md.md 扩展名后即为规则的 name,会被 sanitizeRuleName() 清洗(只保留字母数字和连字符)YAML 中的正则转义注意事项:
\.、\(、\) 这类序列不是 YAML 的合法转义序列,所以会原样保留,传给正则引擎后含义正确(\. → 匹配点号,\( → 匹配左括号)。不需要额外转义。\\(YAML 双引号中代表一个反斜杠)需要留意——如果正则要匹配一个字面反斜杠,YAML 双引号里要写 \\\\(YAML → 两个反斜杠字符串 → 正则里匹配一个反斜杠)。condition:
- '\.unwrap\(\)'
- "(?i)unwrap"
这样写,\.unwrap\(\) 传到正则引擎就是 \.unwrap\(\),没有歧义。规则正文编写规范:
在生成后确认:
condition 正则在作用范围内足够独特(不会误触发)scope 覆盖规则约束的所有流场景和文件路径(不会漏触发).omp/AGENTS.md 或实际文件树)\.、\( 会原样传递到正则(不需要额外转义);如果用单引号+数组形式,完全不用操心转义glob 快速验证)condition 数组的每个条目都能编译通过(非空、非纯空白、有效的正则语法)