feat(plugin): ship as Claude Code plugin with 150-line cap and sync command

Turns ClaudeForge into an installable Claude Code plugin and adds the
missing pieces for a clean lifecycle: hard line-cap enforcement, modular
chaining via @path imports, a sync/cleanup command, and Explore-agent
delegation for project discovery.

- .claude-plugin/plugin.json: plugin manifest registering both skills,
  both commands, and the guardian agent (installable via /plugin marketplace
  add alirezarezvani/ClaudeForge && /plugin install claudeforge)
- skill/validator.py: MAX_RECOMMENDED_LINES 300 -> 150 (warning at 120)
- skill/template_selector.py: target_lines capped at 150 across all
  team sizes (solo 75 / small 100 / medium 125 / large 150) so any
  single CLAUDE.md fits within the cap; bigger projects spread content
  across modular sub-files
- skill/analyzer.py: length thresholds, quality scoring, and recommendations
  rebased on the 150 cap (was 300/400)
- skill/generator.py: modular root now emits @path imports next to the
  human-readable links; every sub-CLAUDE.md gets a back-link header
  pointing to ../CLAUDE.md (markdown + @import) for bidirectional chaining
- command/sync-claude-md.md: new /sync-claude-md command that inventories
  every CLAUDE.md, prunes stale references, enforces the 150 cap by
  splitting into sub-files, and repairs the root <-> sub chain
- command/enhance-claude-md.md: discovery phase now delegates the deep
  codebase scan to the Explore subagent to keep context lean
- install.sh / install.ps1: each command in command/ installs as its own
  ~/.claude/commands/<name>.md (legacy bundle backed up on upgrade)
- skill/SKILL.md, CLAUDE.md, README.md, CHANGELOG.md: docs updated for
  the plugin install path, sync command, and new line cap

Verified via smoke test: validator constants, template targets, generator
output line counts across 5 presets (all <= 150), context files with
backlinks, @-import chain in modular root, idempotent merge_with_existing,
validator status transitions at the new cap, analyzer quality differential,
and plugin manifest JSON shape with all referenced paths existing on disk.
This commit is contained in:
Claude
2026-05-19 00:04:22 +00:00
parent ffff0fc4c3
commit a45e6f5dbd
13 changed files with 318 additions and 64 deletions
+6 -5
View File
@@ -294,7 +294,7 @@ Analyzes existing CLAUDE.md files to identify structure, sections, and quality i
Validates CLAUDE.md files against best practices and Anthropic guidelines.
**Key Functions**:
- `validate_length()` - Check file length (warn if >300 lines)
- `validate_length()` - Check file length (hard cap: 150 lines; warn from 120)
- `validate_structure()` - Verify required sections present
- `validate_formatting()` - Check markdown formatting quality
- `validate_completeness()` - Ensure critical information included
@@ -367,10 +367,11 @@ Before finalizing any CLAUDE.md generation:
## Template Categories
### By Size
- **Minimal** (50 lines) - Solo developers, prototypes, hackathons
- **Core** (100-150 lines) - Small teams, MVPs, standard projects
- **Detailed** (200-300 lines) - Large teams, production systems, enterprise
### By Size (single CLAUDE.md cap: 150 lines)
- **Minimal** (≤ 75 lines) - Solo developers, prototypes, hackathons
- **Core** (100 lines) - Small teams, MVPs, standard projects
- **Detailed** (≤ 125 lines) - Medium teams, production systems
- **Comprehensive** (≤ 150 lines + modular sub-files) - Large teams, enterprise; spread detail across chained sub-CLAUDE.md files instead of growing the root
### By Project Type
- **Web App** - Frontend-focused (React, Vue, Angular)
+17 -10
View File
@@ -165,17 +165,23 @@ class CLAUDEMDAnalyzer:
issues = []
# Check file length
if self.line_count > 400:
if self.line_count > 250:
issues.append({
"type": "length_critical",
"severity": "high",
"message": f"File is too long ({self.line_count} lines). Recommended: split into modular files."
"message": f"File is too long ({self.line_count} lines). Hard cap is 150; split into modular files."
})
elif self.line_count > 300:
elif self.line_count > 150:
issues.append({
"type": "length_warning",
"severity": "high",
"message": f"File exceeds the 150-line cap ({self.line_count} lines). Split now."
})
elif self.line_count > 120:
issues.append({
"type": "length_warning",
"severity": "medium",
"message": f"File exceeds recommended 300 lines ({self.line_count} lines). Consider splitting."
"message": f"File is approaching the 150-line cap ({self.line_count} lines)."
})
# Check if file is too short
@@ -238,12 +244,13 @@ class CLAUDEMDAnalyzer:
"""
score = 0
# Length appropriateness (25 points)
if 50 <= self.line_count <= 300:
# Length appropriateness (25 points). Hard cap is 150 lines; anything
# above that loses points sharply because it indicates context bloat.
if 50 <= self.line_count <= 150:
score += 25
elif 30 <= self.line_count < 50 or 300 < self.line_count <= 400:
elif 30 <= self.line_count < 50 or 150 < self.line_count <= 200:
score += 15
elif self.line_count > 400:
elif self.line_count > 200:
score += 5
else:
score += 10
@@ -329,9 +336,9 @@ class CLAUDEMDAnalyzer:
recommendations.append(f"CRITICAL: {issue['message']}")
# Length recommendations
if self.line_count > 300:
if self.line_count > 150:
recommendations.append(
"Reduce root CLAUDE.md to <150 lines - move detailed guides to context-specific files"
"Reduce this CLAUDE.md to <=150 lines (hard cap) - move detail to context-specific files and chain them via @path imports"
)
elif self.line_count < 30:
recommendations.append(
+36 -11
View File
@@ -99,7 +99,8 @@ class ContentGenerator:
context: Context name ('backend', 'frontend', 'database', etc.)
Returns:
Context-specific CLAUDE.md content
Context-specific CLAUDE.md content with a back-link to the root
CLAUDE.md so Claude can navigate back up the chain.
"""
generators = {
'backend': self._generate_backend_file,
@@ -110,7 +111,17 @@ class ContentGenerator:
}
generator = generators.get(context, self._generate_generic_context_file)
return generator()
body = generator()
# Depth-aware back-link: most context dirs are one level deep, but
# ``.github`` may sit at the repo root next to the root CLAUDE.md.
rel_root = "../CLAUDE.md"
backlink = (
"> Parent context: see the root [CLAUDE.md]"
f"({rel_root}) for project-wide guidelines and behavioural rules.\n"
f"> Chained import: `@{rel_root}`\n\n"
)
return backlink + body
def _generate_backend_file(self) -> str:
"""Generate backend-specific CLAUDE.md."""
@@ -412,22 +423,36 @@ class ContentGenerator:
return sections
def _generate_navigation_section(self, template: Dict[str, Any]) -> List[str]:
"""Generate navigation section for modular architecture."""
"""Generate navigation section for modular architecture.
Emits both human-readable markdown links and Claude Code ``@`` imports
so the chained CLAUDE.md files are loaded automatically when the root
file is read.
"""
project_type = self.project_context.get('type')
links = []
targets: List[tuple] = [] # (label, relative_path)
if project_type == 'fullstack':
links.append("- [Backend Guidelines](backend/CLAUDE.md)")
links.append("- [Frontend Guidelines](frontend/CLAUDE.md)")
links.append("- [Database Operations](database/CLAUDE.md)")
targets.append(("Backend Guidelines", "backend/CLAUDE.md"))
targets.append(("Frontend Guidelines", "frontend/CLAUDE.md"))
targets.append(("Database Operations", "database/CLAUDE.md"))
if 'cicd' in self.project_context.get('workflows', []):
links.append("- [CI/CD Workflows](.github/CLAUDE.md)")
targets.append(("CI/CD Workflows", ".github/CLAUDE.md"))
if not links:
links.append("- [Add links to context-specific CLAUDE.md files]")
if not targets:
return ["- [Add links to context-specific CLAUDE.md files]"]
return links
lines: List[str] = []
for label, path in targets:
lines.append(f"- [{label}]({path})")
lines.append("")
lines.append("Chained context (Claude Code auto-imports these):")
lines.append("")
for _, path in targets:
lines.append(f"@{path}")
return lines
def _generate_core_principles(self, template: Dict[str, Any], max_count: int = 7) -> List[str]:
"""Generate core principles list."""
+8 -4
View File
@@ -78,7 +78,11 @@ class TemplateSelector:
}
}
# Team size templates
# Team size templates. All targets stay <= MAX_LINES_PER_FILE (150) so any
# single CLAUDE.md remains within the hard cap; larger projects spread
# content across modular sub-files instead of growing the root file.
MAX_LINES_PER_FILE = 150
TEAM_SIZE_TEMPLATES = {
"solo": {
"target_lines": 75,
@@ -87,19 +91,19 @@ class TemplateSelector:
"detail_level": "concise"
},
"small": {
"target_lines": 125,
"target_lines": 100,
"complexity": "core",
"focus": "Core guidelines, collaboration basics",
"detail_level": "moderate"
},
"medium": {
"target_lines": 200,
"target_lines": 125,
"complexity": "detailed",
"focus": "Team coordination, process standardization",
"detail_level": "comprehensive"
},
"large": {
"target_lines": 275,
"target_lines": 150,
"complexity": "comprehensive",
"focus": "Enterprise standards, governance",
"detail_level": "extensive"
+4 -3
View File
@@ -12,9 +12,10 @@ import re
class BestPracticesValidator:
"""Validates CLAUDE.md files against best practices and guidelines."""
# Maximum recommended line count
MAX_RECOMMENDED_LINES = 300
WARNING_THRESHOLD_LINES = 200
# Hard cap: every CLAUDE.md (root or modular) must stay under this.
# Modular split is required when content would exceed this cap.
MAX_RECOMMENDED_LINES = 150
WARNING_THRESHOLD_LINES = 120
# Minimum content requirements
MIN_LINES = 20