hiroro-work/claude-plugins

merge-rules

Merge extract-rules output from multiple projects into a unified portable rule set. Promotes .local.md patterns shared across projects to Principles format.

First seen Apr 4, 2026

Installation

$ npx skills add hiroro-work/claude-plugins --skill merge-rules

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from hiroro-work/claude-plugins · top by installs.

npx skills add hiroro-work/claude-plugins

Browse all from hiroro-work/claude-plugins

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 47
Default branch main
Open issues 0
Status Active

Skill metadata

Parsed from SKILL.md frontmatter.

Allowed toolsRead, Glob, Grep, Write, Bash(ls *), Bash(mkdir *), Bash(wc *)
Declared agents claude-code

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 13,387 B
  • docs SUMMARY.md 175 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 10 installs

SKILL.md

Merge Rules

Usage

/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

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).

---
# Source projects (each must have extract-rules output)
projects:
  - ~/projects/frontend-app
  - ~/projects/backend-api
  - ~/projects/shared-lib

# Output directory (default: .claude/rules)
# Examples go to the sibling <output_dir>-extras (.claude/rules-extras)
output_dir: .claude/rules

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

# Threshold for promoting .local.md patterns (default: 0.5 = majority)
# Examples: 3 projects → 2/3 needed, 4 projects → 3/4, 5 projects → 3/5
promote_threshold: 0.5

# Report language (default: ja)
language: ja
---

Examples directories (no configuration key). Examples live in a sibling of the rules directory: that path with any trailing / removed and -extras appended — {path}/{rulesdir}-extras for each source project, <outputdir>-extras for the output. Strip the trailing / before appending, or a configured .claude/rules/ yields .claude/rules/-extras. Collection takes each rule file's examples from the derived directory first and from the rule directory itself only when that misses, so a pre-split layout — examples still beside the rule files — is still collected; writing always targets the derived directory. merge-rules does not read extract-rules' examplesoutputdir. Source of truth for the derived name is extract-rules' examplesoutputdir default; keep in sync when that default changes.

Processing Flow

Step 1: Load Configuration

  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."

  1. Parse YAML frontmatter, apply defaults for omitted fields

- language resolution order: Skill config → Claude Code settings (~/.claude/settings.json → language field) → default ja

  1. Validate:

- projects must have at least 2 entries - Each project path must exist and contain rules_dir - Error with clear message if validation fails

Step 2: Collect Rule Files

For each project:

  1. Recursively list {path}/{rulesdir}/ and {path}/{rulesdir}-extras (derived per § Configuration's "Examples directories (no configuration key)" paragraph) — two listings per project, never a third. A missing -extras directory is the normal pre-split case: treat it as an empty listing rather than an error. Rule files are the .md and .local.md entries of the first listing; examples are the union of the *.examples.md entries of both, with -extras winning when the same relative sub-path appears in each. A project part-way through migration therefore contributes both its moved and its still-co-located examples
  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)

  1. Parse each file: extract YAML frontmatter (paths:) and body sections (## Principles, ## Project-specific patterns, ## Principles Examples, ## Project-specific Examples)

Step 3: Normalize Similar File Names

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 at the same relative sub-path (e.g., rails-controller.md vs rails-controllers.md, rails-model.md vs rails-models.md). The rule tree and the examples tree mirror each other, so frameworks/ in either tree is the same position

- 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)

  1. 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>)

  1. Treat grouped files as the same file for subsequent merge steps (Step 4 and Step 5)
  2. Report normalized groups in the summary (e.g., "rails-controller.md + rails-controllers.md → rails-controllers.md")

Step 4: Merge Portable Rules (.md)

Once a pattern is promoted to a Principle (via Step 5), subsequent merge-rules runs 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 - Preserve unique principles from any project

  1. Merge paths: frontmatter: union of all path patterns, deduplicate
  2. If file exists in only 1 project, include as-is

Step 5: Promote .local.md Patterns to 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).
  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)

  1. Count occurrences per pattern across projects
  2. Calculate threshold: pattern must appear in more than len(projects) * promote_threshold projects (i.e., strict majority when threshold = 0.5)
  3. 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) - cleanbracketparams(:keyword) - WAF付加のブラケット除去 → WAF付加のブラケット除去 (cleanbracketparams) - 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)

  1. Patterns below threshold → discard (listed in report for reference)

Step 5.5: Merge Examples (.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

  1. 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)

  1. Output .examples.md file structure:
# <Category> Rules - Examples

## Principles Examples

### <Principle name>
**Good:**
```<lang>
<example>

Bad: ```<lang> <example>

  • ### titles must match the corresponding rule name in the merged output .md file. Do not rephrase
  • No paths: frontmatter
  • If no examples exist for any merged rule, skip generating the .examples.md file

Step 6: Write Output

  1. Check the output directories outputdir and <outputdir>-extras (derived per § Configuration's "Examples directories (no configuration key)" paragraph):

- If --dry-run: skip writing, show planned file list with contents summary, then go to Step 7 - If either exists and has files: warn and ask for confirmation before overwriting - For either that does not exist: create with mkdir -p

  1. Write merged files preserving directory structure:

- <outputdir>/languages/<lang>.md - <outputdir>-extras/languages/<lang>.examples.md (if examples exist) - <outputdir>/frameworks/<framework>.md - <outputdir>-extras/frameworks/<framework>.examples.md (if examples exist) - <outputdir>/integrations/<framework>-<integration>.md - <outputdir>-extras/integrations/<framework>-<integration>.examples.md (if examples exist) - Only .md and .examples.md files (no .local.md in output)

  1. Output file format:
---
paths:
  - "**/*.ts"
  - "**/*.tsx"
---
# TypeScript Rules

## 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: <relative-path-to-examples-file> ` The path is that examples file — <outputdir>-extras/<same relative sub-path>/<name>.examples.md — expressed relative to the rule file's own directory. With the default outputdir, languages/typescript.md gets ../../rules-extras/languages/typescript.examples.md`.

Step 7: Report Summary

Display report using the project's directory name (last path component) as label. Report headers are always in English.

# Merge Rules Report

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

## File Name Normalization
- `rails-controller.md` + `rails-controllers.md` → `rails-controllers.md`
- `rails-model.md` + `rails-models.md` → `rails-models.md`

## Merge Results
| File | Sources | Principles | Promoted to Principles | Examples |
|------|---------|------------|------------------------|----------|
| languages/typescript.md | 3/3 | 5 | 2 | 7 |
| frameworks/react.md | 2/3 | 3 | 1 | 4 |
| integrations/rails-inertia.md | 2/3 | 2 | 0 | 2 |

**Principles** = total including promoted. **Examples** = total `###` entries in the output `.examples.md`.

## Promoted to Principles
- `useAuth()` → Auth hook interface (useAuth) - 3/3 projects
- `pathFor() + url()` → Path helpers (pathFor, url) - 2/3 projects

## Below Threshold (reference)
- `useCustomHook()` (typescript) - 1/3 (frontend-app only)
- `ApiClient.create()` (typescript) - 1/3 (backend-api only)

## Skipped
- project.md x3 (project-specific, skipped)

Conflict Handling

  • Contradicting principles: Keep both, report as conflict for human review