/blueprint:derive-rules
Extract project decisions from git commit history and codify them as Claude rules. Newer commits override older decisions when conflicts exist.
Use case: Derive implicit project patterns from git history to establish consistent AI-assisted development guidelines.
Usage: /blueprint:derive-rules [--since DATE] [--scope SCOPE]
When to Use This Skill
| Use this skill when... | Use alternative when... | |------------------------|-------------------------| | Want to extract implicit decisions from git history | Creating rules from requirements (use PRDs instead) | | Project has significant commit history | New project with little history | | Establishing project coding standards | Quick manual rule creation |
Context
- Git repository: !
git rev-parse --git-dir - Blueprint initialized: !
find . -path '*/docs/blueprint/*' -maxdepth 3 -name 'manifest.json' -type f - Total commits: !
git rev-list --count HEAD - Conventional commits %: !
git log --format="%s" - Existing rules in default location: !
find . -path '*/.claude/rules/*' -maxdepth 3 -name "*.md" -type f - Existing rules in blueprint subdir: !
find . -path '*/.claude/rules/blueprint/*' -maxdepth 4 -name "*.md" -type f
Parameters
Parse $ARGUMENTS:
--since DATE: Analyze commits from specific date (e.g.,--since 2024-01-01)--scope SCOPE: Focus on specific area (e.g.,--scope api,--scope testing)
Execution
Execute the complete git-to-rules derivation workflow:
Step 0: Resolve the output path
Read structure.generated_rules_path from docs/blueprint/manifest.json (default .claude/rules/):
RULES_DIR=$(jq -r '.structure.generated_rules_path // ".claude/rules/"' docs/blueprint/manifest.json)
mkdir -p "$RULES_DIR"
Use $RULES_DIR for all subsequent reads/writes and conflict checks. Hand-written files in the parent .claude/rules/ are intentionally invisible to this skill (issue #1043).
Step 1: Verify prerequisites
- If not a git repository → Error: "This directory is not a git repository"
- If Blueprint not initialized → Suggest
/blueprint:initfirst - If few commits (< 20) → Warn: "Limited commit history; derived rules may be incomplete"
Step 2: Analyze git history quality
- Calculate total commits in scope
- Calculate conventional commits percentage
- Report quality: Higher % = higher confidence in extracted rules
- Parse
--sinceand--scopeflags to determine analysis range
Step 3: Extract decision-bearing commits
Use parallel agents to analyze git history efficiently (see REFERENCE.md):
- Agent 1: Analyze
refactor:commits for code style patterns - Agent 2: Analyze
fix:commits for repeated issue types - Agent 3: Analyze
feat!:andBREAKING CHANGE:commits for architecture decisions - Agent 4: Analyze
chore:andbuild:commits for tooling decisions
Consolidate findings by domain (code-style, testing, api-design, etc.), chronologically (newest first), and by frequency (most common wins).
Step 4: Resolve conflicts
When multiple commits address the same topic:
- Detect conflicts using pattern matching:
git log --format="%H|%ai|%s" | grep "{topic}" - Apply resolution strategy:
- Newer overrides older: Latest decision wins
- Higher frequency wins: If 5 commits say X and 1 says Y, X wins
- Breaking changes override:
feat!:trumps regular commits
- Mark overridden decisions as "superseded" with reference to newer decision
- Confirm significant decisions with user via AskUserQuestion
Step 5: Generate rules in $RULES_DIR
For each decision, generate rule file using template from REFERENCE.md. Write each file to $RULES_DIR/<filename>.md (the configured structure.generated_rules_path):
-
Extract source commit, date, type
-
Determine confidence level (High/Medium/Low based on commit frequency and clarity)
-
Generate actionable rule statement
-
Include code examples from commit diffs
-
Reference any superseded earlier decisions
-
REQUIRED: scope every generated rule via
paths:frontmatter unless the rule genuinely applies everywhere. Rules withoutpaths:load on every session and pollute context for unrelated work. Pickpaths:from the source signal:| Signal | Source |
paths:value | |---|---|---| | Rule body cites a specific file via "patterns extracted from<path>" | Step 3 / 4 conflict resolution | Glob over that file's directory:<dir>/**/*.<ext>| | Rule was derived fromchore(deps)/build:commits | Tooling-decision agent | Lockfiles + manifests:package.json,pyproject.toml,Cargo.toml,go.mod,*.lock,biome.json, etc. | | Rule references a language (refactor:+ JS-only code blocks) | Code-style agent | Language Glob:**/*.{js,jsx,ts,tsx},**/*.py,**/*.rs| | Rule is about tests | Test-strategy agent |**/*.{test,spec}.*,tests/**/*,test/**/*| | Rule is about API endpoints | API-design agent |src/{api,routes}/**/*,**/*controller*,**/*handler*| | Rule is about documentation | Docs agent |docs/**,**/*.md| | Rule restates global project context (already in CLAUDE.md) | any | Do not emit — that's CLAUDE.md's job; abort the rule | | Rule genuinely applies to every file (e.g. universal error-handling philosophy, security mindset) | Rare | Omitpaths:deliberately and note "global rule" in the rule body |Default to scoping. The auto-derived starting point: take every code block in the rule body, collect the file extensions / directory roots they reference, and emit those as
paths:. Verify the resulting glob set actually matches files in the working tree before writing — an empty match list means the inferred scope is wrong; re-derive.
Generate separate rule files by category (see REFERENCE.md for canonical filenames and default paths: per category):
code-style.md,testing-standards.md,api-conventions.md,error-handling.md,dependencies.md,security-practices.md
Step 6: Handle conflicts with existing rules
Check for conflicts with existing rules only under $RULES_DIR (never the parent .claude/rules/, which may contain hand-authored content unrelated to blueprint):
- If conflicts found → Ask user: Git-derived overrides existing rule, or keep existing?
- Apply user choice: Update, merge, or keep separate
- Document conflict resolution in rule file
Step 7: Update task registry
Update the task registry entry in docs/blueprint/manifest.json:
jq --arg now "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--arg sha "$(git rev-parse HEAD 2>/dev/null)" \
--argjson processed "${COMMITS_ANALYZED:-0}" \
--argjson created "${RULES_DERIVED:-0}" \
'.task_registry["derive-rules"].last_completed_at = $now |
.task_registry["derive-rules"].last_result = "success" |
.task_registry["derive-rules"].context.commits_analyzed_up_to = $sha |
.task_registry["derive-rules"].stats.runs_total = ((.task_registry["derive-rules"].stats.runs_total // 0) + 1) |
.task_registry["derive-rules"].stats.items_processed = $processed |
.task_registry["derive-rules"].stats.items_created = $created' \
docs/blueprint/manifest.json > tmp.json && mv tmp.json docs/blueprint/manifest.json
Step 8: Update manifest and report
- Update
docs/blueprint/manifest.jsonwith derived rules metadata: timestamp, commits analyzed, rules generated, source commits - Generate completion report showing:
- Commits analyzed (count and date range)
- Conventional commits percentage
- Rules generated by category
- Confidence scores per rule
- Any conflicts resolved
- Prompt user for next action: Review rules, execute derived development workflow, or done
Agentic Optimizations
| Context | Command |
|---------|---------|
| Check git status | git rev-parse --git-dir 2>/dev/null && echo "YES" \|\| echo "NO" |
| Count total commits | git rev-list --count HEAD 2>/dev/null \|\| echo "0" |
| Conventional commits % | git log --format="%s" \| grep -c "^(feat\|fix\|refactor)" \|\| echo 0 |
| Extract decision commits | git log --format="%H\|%s\|%b" \| grep -E "(always\|never\|must\|prefer)" |
| Fast derivation | Use parallel agents (Explore) for multi-domain analysis |
For git analysis patterns, rule templates, conflict resolution, and detailed procedures, see REFERENCE.md.