merge-rules

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Merge Rules

规则合并

Merges
.claude/rules/
from multiple projects into a unified portable rule set (.md + .examples.md). Promotes
.local.md
patterns that appear across a threshold of projects by converting them to Principles format. Merges
.examples.md
files alongside rule files.
将多个项目的
.claude/rules/
目录内容合并为统一的可移植规则集(.md + .examples.md)。将出现在超过阈值数量项目中的
.local.md
模式转换为Principles格式,同时合并规则文件对应的
.examples.md
文件。

Usage

使用方法

text
/merge-rules                    # Merge using config file
/merge-rules --config <path>    # Merge using specified config file
/merge-rules --dry-run          # Show what would be merged without writing
text
/merge-rules                    # 基于配置文件执行合并
/merge-rules --config <path>    # 使用指定的配置文件执行合并
/merge-rules --dry-run          # 预览合并结果,不写入文件

Configuration

配置

Config file search order:
  1. --config <path>
    argument
  2. .claude/merge-rules.local.md
    (project-level)
  3. ~/.claude/merge-rules.local.md
    (user-level)
File format: YAML frontmatter only (no markdown body), same convention as
extract-rules.local.md
.
yaml
---
配置文件搜索优先级:
  1. --config <path>
    参数指定的文件
  2. .claude/merge-rules.local.md
    (项目级别)
  3. ~/.claude/merge-rules.local.md
    (用户级别)
文件格式: 仅包含YAML frontmatter(无markdown正文),与
extract-rules.local.md
的约定一致。
yaml
---

Source projects (each must have extract-rules output)

源项目列表(每个项目都需要有extract-rules的输出)

projects:
  • ~/projects/frontend-app
  • ~/projects/backend-api
  • ~/projects/shared-lib
projects:
  • ~/projects/frontend-app
  • ~/projects/backend-api
  • ~/projects/shared-lib

Output directory (default: .claude/rules/)

输出目录(默认:.claude/rules/)

output_dir: .claude/rules/
output_dir: .claude/rules/

Rules directory within each project (default: .claude/rules/)

每个项目内的规则目录(默认:.claude/rules/)

Corresponds to extract-rules' output_dir setting

对应extract-rules的output_dir配置

rules_dir: .claude/rules/
rules_dir: .claude/rules/

Threshold for promoting .local.md patterns (default: 0.5 = majority)

.local.md模式的升级阈值(默认:0.5 = 过半数)

Examples: 3 projects → 2/3 needed, 4 projects → 3/4, 5 projects → 3/5

示例:3个项目 → 需要出现在2个项目中,4个项目 → 需要出现在3个项目中,5个项目 → 需要出现在3个项目中

promote_threshold: 0.5
promote_threshold: 0.5

Report language (default: ja)

报告语言(默认:ja)

language: ja

undefined

language: ja

undefined

Processing Flow

处理流程

Step 1: Load Configuration

第1步:加载配置

  1. Search for config file (see search order above)
    • If not found: Error "No config file found. Create
      .claude/merge-rules.local.md
      or specify with
      --config
      ."
  2. Parse YAML frontmatter, apply defaults for omitted fields
    • language
      resolution order:
      Skill config → Claude Code settings (
      ~/.claude/settings.json
      language
      field) → default
      ja
  3. Validate:
    • projects
      must have at least 2 entries
    • Each project path must exist and contain
      rules_dir
    • Error with clear message if validation fails
  1. 按照上述优先级搜索配置文件
    • 未找到则报错:"No config file found. Create
      .claude/merge-rules.local.md
      or specify with
      --config
      ."
  2. 解析YAML frontmatter,对未指定的字段应用默认值
    • language
      解析优先级:
      Skill配置 → Claude Code设置(
      ~/.claude/settings.json
      language
      字段)→ 默认值
      ja
  3. 校验:
    • projects
      配置至少需要2个条目
    • 每个项目路径必须存在且包含
      rules_dir
      指定的目录
    • 校验失败则返回清晰的错误提示

Step 2: Collect Rule Files

第2步:收集规则文件

For each project:
  1. Find all
    .md
    ,
    .local.md
    , and
    .examples.md
    files under
    {path}/{rules_dir}/
    (recursive)
  2. Categorize:
    • languages/*.md
      → portable principles (always merge). If the file also contains
      ## Project-specific patterns
      (hybrid format from
      split_output: false
      ), treat patterns as promotion candidates (same as
      .local.md
      )
    • frameworks/*.md
      → same as above
    • integrations/*.md
      → same as above
    • languages/*.local.md
      → promotion candidate
    • frameworks/*.local.md
      → promotion candidate
    • integrations/*.local.md
      → promotion candidate
    • languages/*.examples.md
      → example file (merge with rules)
    • frameworks/*.examples.md
      → example file (merge with rules)
    • integrations/*.examples.md
      → example file (merge with rules)
    • project.md
      → skip (inherently project-specific)
    • project.examples.md
      → skip (inherently project-specific)
  3. Parse each file: extract YAML frontmatter (
    paths:
    ) and body sections (
    ## Principles
    ,
    ## Project-specific patterns
    ,
    ## Principles Examples
    ,
    ## Project-specific Examples
    )
对每个项目执行以下操作:
  1. 递归查找
    {路径}/{rules_dir}/
    下所有
    .md
    .local.md
    .examples.md
    文件
  2. 分类处理:
    • languages/*.md
      → 可移植原则(始终合并)。如果文件同时包含
      ## Project-specific patterns
      split_output: false
      生成的混合格式),则将其中的模式视为待升级候选(与
      .local.md
      处理逻辑一致)
    • frameworks/*.md
      → 同上
    • integrations/*.md
      → 同上
    • languages/*.local.md
      → 待升级候选
    • frameworks/*.local.md
      → 待升级候选
    • integrations/*.local.md
      → 待升级候选
    • languages/*.examples.md
      → 示例文件(随规则合并)
    • frameworks/*.examples.md
      → 示例文件(随规则合并)
    • integrations/*.examples.md
      → 示例文件(随规则合并)
    • project.md
      → 跳过(本身属于项目专属内容)
    • project.examples.md
      → 跳过(本身属于项目专属内容)
  3. 解析每个文件:提取YAML frontmatter(
    paths:
    字段)和正文部分(
    ## Principles
    ## Project-specific patterns
    ## Principles Examples
    ## Project-specific Examples

Step 3: Normalize Similar File Names

第3步:相似文件名归一化

Before merging, group files that refer to the same concept but have different names. This applies to
.md
,
.local.md
, and
.examples.md
files — a
.md
and its corresponding
.local.md
and
.examples.md
share the same normalization (e.g.,
rails-controller.md
,
rails-controller.local.md
, and
rails-controller.examples.md
are normalized together with their
rails-controllers.*
variants).
  1. Detect similar file names within the same directory (e.g.,
    rails-controller.md
    vs
    rails-controllers.md
    ,
    rails-model.md
    vs
    rails-models.md
    )
    • Singular/plural variants (e.g.,
      controller
      /
      controllers
      )
    • Minor naming differences for the same concept (use AI judgment based on file content and
      paths:
      frontmatter overlap)
  2. For each group of similar files, select a canonical name:
    • Prefer the name used by the majority of projects
    • If tied, prefer the name matching extract-rules' layered framework convention (e.g.,
      <framework>-<layer>
      )
  3. Treat grouped files as the same file for subsequent merge steps (Step 4 and Step 5)
  4. Report normalized groups in the summary (e.g., "
    rails-controller.md
    +
    rails-controllers.md
    rails-controllers.md
    ")
合并前,将指向同一概念但名称不同的文件归为一组,该规则适用于
.md
.local.md
.examples.md
文件——
.md
文件与其对应的
.local.md
.examples.md
文件共享相同的归一化逻辑(例如
rails-controller.md
rails-controller.local.md
rails-controller.examples.md
会与其
rails-controllers.*
变体一起归一化处理)。
  1. 识别同一目录下的相似文件名(例如
    rails-controller.md
    rails-controllers.md
    rails-model.md
    rails-models.md
    • 单复数变体(例如
      controller
      /
      controllers
    • 同一概念的微小命名差异(基于文件内容和
      paths:
      frontmatter的重叠度,通过AI判断)
  2. 为每组相似文件选择一个规范名称:
    • 优先选择多数项目使用的名称
    • 平票时优先选择符合extract-rules分层框架约定的名称(例如
      <framework>-<layer>
      格式)
  3. 在后续合并步骤(第4步和第5步)中,同组文件将被视为同一个文件处理
  4. 在汇总报告中展示归一化的分组(例如:"
    rails-controller.md
    +
    rails-controllers.md
    rails-controllers.md
    ")

Step 4: Merge Portable Rules (.md)

第4步:合并可移植规则(.md)

Design note: Once a pattern is promoted to a Principle (via Step 5), it becomes a permanent org-level rule. Subsequent merge-rules runs will preserve it through Step 4's principle deduplication, regardless of whether the original
.local.md
pattern still meets the promotion threshold. To demote or remove a promoted Principle, manually edit the org rules output.
For each unique (normalized) file name across projects (e.g.,
languages/typescript.md
,
integrations/rails-inertia.md
):
  1. Collect all versions from projects that have this file (including normalized variants)
  2. Merge
    ## Principles
    sections:
    • Deduplicate by principle name (text before parenthetical hints)
    • Union hints from all projects for the same principle
    • If same principle name but clearly different meaning → keep both, flag in report (see Conflict Handling)
    • Preserve unique principles from any project
  3. Merge
    paths:
    frontmatter: union of all path patterns, deduplicate
  4. If file exists in only 1 project, include as-is
设计说明: 模式通过第5步升级为Principle后,将成为永久的组织级规则。后续执行merge-rules时,会通过第4步的原则去重逻辑保留该规则,无论原
.local.md
模式是否仍满足升级阈值。如需降级或删除已升级的Principle,请手动编辑组织规则输出文件。
对所有项目中每个唯一(归一化后)的文件名(例如
languages/typescript.md
integrations/rails-inertia.md
):
  1. 收集所有包含该文件(包括归一化变体)的项目对应的版本
  2. 合并
    ## Principles
    部分:
    • 按原则名称(括号内提示前的文本)去重
    • 合并同一原则下所有项目的提示信息并去重
    • 如果原则名称相同但含义明显不同 → 同时保留,在报告中标记(见冲突处理)
    • 保留所有项目的独有原则
  3. 合并
    paths:
    frontmatter:合并所有路径模式并去重
  4. 如果仅1个项目包含该文件,直接保留原内容

Step 5: Promote .local.md Patterns to Principles

第5步:将.local.md模式升级为Principles

For each normalized category (e.g.,
languages/typescript
,
frameworks/rails-controllers
,
integrations/rails-inertia
):
  1. Collect
    ## Project-specific patterns
    from all projects — from
    .local.md
    files and from hybrid
    .md
    files that contain this section (see Step 2)
  2. Deduplicate against existing Principles: Exclude patterns whose description (text after
    -
    ) semantically matches an existing principle name in the corresponding
    .md
    output (from Step 4). Use AI judgment for semantic equivalence (case-insensitive, synonyms). This prevents self-amplification when
    .local.md
    contains patterns previously promoted by older versions
  3. Match remaining patterns by inline code signature (backtick portion before
    -
    )
    • Use AI judgment to determine semantic equivalence (e.g.,
      useAuth()
      and
      useAuth() → { user, login, logout }
      refer to the same pattern)
  4. Count occurrences per pattern across projects
  5. Calculate threshold: pattern must appear in more than
    len(projects) * promote_threshold
    projects (i.e., strict majority when threshold = 0.5)
  6. Convert to Principles format and append to
    ## Principles
    in the corresponding normalized
    .md
    output:
    • Signature format:
      `signature` - description
      → Principles format:
      Description (simplified signature)
    • The description becomes the principle name, the function/type name from the signature becomes the hint
    • Examples:
      • `useAuth() → { user, login, logout }` - auth hook interface
        Auth hook interface (useAuth)
      • `clean_bracket_params(:keyword)` - WAF付加のブラケット除去
        WAF付加のブラケット除去 (clean_bracket_params)
      • `RefOrNull<T extends { id: string }> = T | { id: null }` - nullable refs
        Nullable refs (RefOrNull<T>)
    • Apply Step 4's principle deduplication to the converted principles (skip if same principle name already exists)
  7. Patterns below threshold → discard (listed in report for reference)
对每个归一化后的分类(例如
languages/typescript
frameworks/rails-controllers
integrations/rails-inertia
):
  1. 收集所有项目的
    ## Project-specific patterns
    ——来自
    .local.md
    文件和包含该部分的混合格式
    .md
    文件(见第2步)
  2. 与现有Principles去重: 排除描述(
    -
    后的文本)与对应
    .md
    输出文件(第4步生成)中现有原则名语义匹配的模式。使用AI判断语义等价性(不区分大小写、同义词),避免
    .local.md
    包含旧版本已升级的模式时出现自我重复。
  3. 按行内代码标识(
    -
    前的反引号部分)匹配剩余模式
    • 使用AI判断语义等价性(例如
      useAuth()
      useAuth() → { user, login, logout }
      指向同一模式)
  4. 统计每个模式在所有项目中出现的次数
  5. 计算阈值:模式必须出现在超过
    项目数量 * promote_threshold
    的项目中(即阈值为0.5时需要严格过半数)
  6. 转换为Principles格式并追加到对应归一化
    .md
    输出文件的
    ## Principles
    部分:
    • 原标识格式:
      `signature` - description
      → Principles格式:
      Description (simplified signature)
    • 描述作为原则名称,标识中的函数/类型名作为提示
    • 示例:
      • `useAuth() → { user, login, logout }` - auth hook interface
        Auth hook interface (useAuth)
      • `clean_bracket_params(:keyword)` - WAF付加のブラケット除去
        WAF付加のブラケット除去 (clean_bracket_params)
      • `RefOrNull<T extends { id: string }> = T | { id: null }` - nullable refs
        Nullable refs (RefOrNull<T>)
    • 对转换后的原则应用第4步的原则去重逻辑(如果已存在同名原则则跳过)
  7. 未达到阈值的模式 → 丢弃(在报告中列出供参考)

Step 5.5: Merge Examples (.examples.md)

第5.5步:合并示例(.examples.md)

For each normalized
.examples.md
file group:
  1. Collect all versions from projects that have this file (including normalized variants)
  2. Principles Examples: Merge by section heading (e.g.,
    ### FP only
    )
    • Same principle heading across projects → adopt the most detailed example, or merge Good/Bad from different projects
    • If Good/Bad contrast exists in one project but not another → adopt from the project that has it
    • Deduplicate identical examples
  3. Promoted pattern examples: For patterns promoted in Step 5, include their examples under
    ## Principles Examples
    • Use the same semantic equivalence judgment as Step 5 (matching by inline code signature with AI judgment) to link
      ###
      example headings to promoted patterns — do not rely solely on exact heading match
    • ###
      title uses the converted Principle name (from Step 5), not the original signature
    • Include the full original signature as a Good example showing usage
    • Discard examples for patterns below threshold (same as the pattern itself)
  4. Output
    .examples.md
    file structure:
markdown
undefined
对每个归一化后的
.examples.md
文件组:
  1. 收集所有包含该文件(包括归一化变体)的项目对应的版本
  2. Principles Examples:按章节标题合并(例如
    ### FP only
    • 不同项目中同一原则的标题 → 采纳最详细的示例,或合并不同项目的正/反例
    • 如果一个项目中有正/反例对比而另一个没有 → 采纳包含对比的项目的内容
    • 完全相同的示例去重
  3. 已升级模式的示例:对于第5步中升级的模式,将其示例归入
    ## Principles Examples
    • 使用与第5步相同的语义等价判断(通过AI按行内代码标识匹配)将
      ###
      示例标题与已升级模式关联,不要仅依赖精确标题匹配
    • ###
      标题使用第5步转换后的Principle名称,而非原始标识
    • 保留完整的原始标识作为正例展示用法
    • 丢弃未达到阈值的模式的示例(与模式本身处理逻辑一致)
  4. 输出
    .examples.md
    文件结构:
markdown
undefined

<Category> Rules - Examples

<Category> Rules - Examples

Principles Examples

Principles Examples

<Principle name>

<Principle name>

Good:
<example>
Bad:
<example>

- `###` titles must match the corresponding rule name in the merged output `.md` file. Do not rephrase
- No `paths:` frontmatter (prevents auto-loading)
- If no examples exist for any merged rule, skip generating the `.examples.md` file
Good:
<example>
Bad:
<example>

- `###`标题必须与合并输出的`.md`文件中对应的规则名称完全一致,不得改写
- 不包含`paths:` frontmatter(避免自动加载)
- 如果所有合并后的规则都没有示例,跳过生成`.examples.md`文件

Step 6: Write Output

第6步:写入输出文件

  1. Check output directory:
    • If
      --dry-run
      : skip writing, show planned file list with contents summary, then go to Step 7
    • If exists and has files: warn and ask for confirmation before overwriting
    • If not exists: create with
      mkdir -p
  2. Write merged files preserving directory structure:
    • languages/<lang>.md
    • languages/<lang>.examples.md
      (if examples exist)
    • frameworks/<framework>.md
    • frameworks/<framework>.examples.md
      (if examples exist)
    • integrations/<framework>-<integration>.md
    • integrations/<framework>-<integration>.examples.md
      (if examples exist)
    • Only
      .md
      and
      .examples.md
      files (no
      .local.md
      in output)
  3. Output file format:
markdown
---
paths:
  - "**/*.ts"
  - "**/*.tsx"
---
  1. 检查输出目录:
    • 如果指定了
      --dry-run
      :跳过写入,展示计划生成的文件列表和内容摘要,然后进入第7步
    • 如果目录已存在且包含文件:覆盖前发出警告并请求确认
    • 如果目录不存在:执行
      mkdir -p
      创建目录
  2. 保留目录结构写入合并后的文件:
    • languages/<lang>.md
    • languages/<lang>.examples.md
      (存在示例时生成)
    • frameworks/<framework>.md
    • frameworks/<framework>.examples.md
      (存在示例时生成)
    • integrations/<framework>-<integration>.md
    • integrations/<framework>-<integration>.examples.md
      (存在示例时生成)
    • 仅输出
      .md
      .examples.md
      文件(输出中不包含
      .local.md
  3. 输出文件格式:
markdown
---
paths:
  - "**/*.ts"
  - "**/*.tsx"
---

TypeScript Rules

TypeScript Rules

Principles

Principles

  • Immutability (spread, map/filter/reduce, const)
  • Type safety (strict mode, explicit annotations, no any)
  • Auth hook interface (useAuth)

- Output `.md` contains only `## Principles` (promoted patterns are converted and included here)
- Omit `## Principles` section if no principles exist for this category
- If a corresponding `.examples.md` was generated, append a reference section at the end:
  ```markdown
  ## Examples
  When in doubt: ./<name>.examples.md
  • Immutability (spread, map/filter/reduce, const)
  • Type safety (strict mode, explicit annotations, no any)
  • Auth hook interface (useAuth)

- 输出的`.md`文件仅包含`## Principles`部分(已升级的模式会转换后归入此处)
- 如果该分类没有任何原则,省略`## Principles`章节
- 如果生成了对应的`.examples.md`文件,在末尾追加参考章节:
  ```markdown
  ## Examples
  When in doubt: ./<name>.examples.md

Step 7: Report Summary

第7步:输出汇总报告

Display report using the project's directory name (last path component) as label. Report headers are always in English.
undefined
使用项目的目录名(路径的最后一段)作为标签展示报告,报告标题始终使用英文。
undefined

Merge Rules Report

Merge Rules Report

Sources

Sources

  • frontend-app (3 files)
  • backend-api (2 files)
  • shared-lib (4 files)
  • frontend-app (3 files)
  • backend-api (2 files)
  • shared-lib (4 files)

File Name Normalization

File Name Normalization

  • rails-controller.md
    +
    rails-controllers.md
    rails-controllers.md
  • rails-model.md
    +
    rails-models.md
    rails-models.md
  • rails-controller.md
    +
    rails-controllers.md
    rails-controllers.md
  • rails-model.md
    +
    rails-models.md
    rails-models.md

Merge Results

Merge Results

FileSourcesPrinciplesPromoted to PrinciplesExamples
languages/typescript.md3/3527
frameworks/react.md2/3314
integrations/rails-inertia.md2/3202
Principles = total including promoted. Examples = total
###
entries in the output
.examples.md
.
FileSourcesPrinciplesPromoted to PrinciplesExamples
languages/typescript.md3/3527
frameworks/react.md2/3314
integrations/rails-inertia.md2/3202
Principles = 包含已升级模式的总原则数。Examples = 输出的
.examples.md
文件中
###
条目的总数。

Promoted to Principles

Promoted to Principles

  • useAuth()
    → Auth hook interface (useAuth) - 3/3 projects
  • pathFor() + url()
    → Path helpers (pathFor, url) - 2/3 projects
  • useAuth()
    → Auth hook interface (useAuth) - 3/3 projects
  • pathFor() + url()
    → Path helpers (pathFor, url) - 2/3 projects

Below Threshold (reference)

Below Threshold (reference)

  • useCustomHook()
    (typescript) - 1/3 (frontend-app only)
  • ApiClient.create()
    (typescript) - 1/3 (backend-api only)
  • useCustomHook()
    (typescript) - 1/3 (frontend-app only)
  • ApiClient.create()
    (typescript) - 1/3 (backend-api only)

Skipped

Skipped

  • project.md x3 (project-specific, skipped)
undefined
  • project.md x3 (project-specific, skipped)
undefined

Conflict Handling

冲突处理

  • Same principle, different hints: Union all hints, deduplicate
  • Same principle name, different meaning: Keep both, flag in report for human review
  • Same category, different paths: Union all path patterns
  • Contradicting principles: Keep both, report as conflict for human review
  • 同一原则,不同提示:合并所有提示并去重
  • 同一原则名称,不同含义:同时保留,在报告中标记供人工审核
  • 同一分类,不同路径:合并所有路径模式
  • 相互矛盾的原则:同时保留,在报告中标记为冲突供人工审核