
Continuous Claudemd Updates
- 1 installs
- Updated February 15, 2026
- vijaykpatel/favorite_skills_and_plugins
Keep CLAUDE.md in sync with codebase changes after commits, moving verbose content to docs/ and removing outdated references to stay concise.
About
Analyzes each commit and audits CLAUDE.md for needed updates, keeping entries concise while relocating detailed content to the docs/ folder. A developer uses it to maintain accurate project documentation as the codebase evolves.
- analyze_changes.py categorizes commit impact to decide whether CLAUDE.md needs updates
- Keeps entries 1-4 sentences and moves verbose content to docs/ with links
Continuous Claudemd Updates by the numbers
- 1 all-time installs (skills.sh)
- Ranked #1,356 of 1,879 Documentation skills by installs in the Skillselion catalog
- Data as of Jul 8, 2026 (Skillselion catalog sync)
npx skills add https://github.com/vijaykpatel/favorite_skills_and_plugins --skill continuous-claudemd-updatesAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1 |
|---|---|
| Last updated | February 15, 2026 |
| Repository | vijaykpatel/favorite_skills_and_plugins ↗ |
What it does
Keep CLAUDE.md in sync with codebase changes after commits, moving verbose content to docs/ and removing outdated references to stay concise.
Files
Continuous CLAUDE.md Updates
Overview
Keeps CLAUDE.md synchronized with codebase changes through automatic analysis after commits and periodic audits. Maintains conciseness by moving detailed content to docs/ folder, removes outdated information, and ensures documentation accuracy.
Announce at start: "I'm using the continuous-claudemd-updates skill to sync CLAUDE.md with recent changes."
Workflow
After Each Commit (Automatic Mode)
Follow this sequence when a commit has been made:
1. Analyze Changes
Run the analysis script to understand the impact:
python scripts/analyze_changes.py --commit HEADThis outputs JSON with:
- Changed files categorized by type (config, source, tests, docs, assets)
- Change magnitude (insertions, deletions, total changes)
- Impact level (minor, moderate, major)
- Commit message for context
2. Review CLAUDE.md Relevance
Based on analysis, determine if CLAUDE.md needs updates:
Update if:
- Config files changed (package.json, tsconfig.json, etc.)
- New patterns/conventions introduced in source files
- Architecture or structure modified
- Files referenced in CLAUDE.md were changed/deleted
- Major features added (impact: "major" or "moderate")
Skip if:
- Only test files changed
- Documentation-only changes
- Minor bug fixes with no pattern changes
- Impact level: "minor" with no config changes
3. Read Current CLAUDE.md
cat CLAUDE.mdUnderstand current structure and content before modifying.
4. Compare Against Changes
For each changed file category:
Config changes: Check if CLAUDE.md mentions these configs
- Update version numbers, dependency changes, new scripts
- Add new configuration requirements
- Remove references to deleted configs
Source changes: Identify pattern changes
- New component structures
- Changed API conventions
- Modified file organization
- Updated workflows
Deletions: Remove obsolete references
- Check for file paths that no longer exist
- Remove outdated pattern descriptions
- Delete deprecated workflow instructions
5. Apply Updates
When updating CLAUDE.md:
Keep entries concise (1-4 sentences):
## API Client
All API calls use `src/lib/api.ts`. Handles auth, retries, errors.
See [docs/api-patterns.md](docs/api-patterns.md) for advanced patterns.Move verbose content to docs/:
If adding >3 paragraphs or >20 lines of code examples:
1. Create a docs/ note using the template from assets/note-template.md 2. Place detailed content there 3. Add concise summary to CLAUDE.md with link
Example:
# Create detailed note
cp assets/note-template.md docs/authentication-flow.md
# Edit docs/authentication-flow.md with detailsThen in CLAUDE.md:
## Authentication
Using NextAuth.js with session-based auth. Config in `pages/api/auth/[...nextauth].ts`.
Full setup guide: [docs/authentication-flow.md](docs/authentication-flow.md)Remove outdated information:
- Delete references to renamed/deleted files
- Remove deprecated patterns
- Eliminate historical context ("previously we used...")
- Update file paths that changed
6. Verify Links
Check that all docs/ links are valid:
# Manual verification or use audit script
python scripts/audit_claudemd.py --claudemd CLAUDE.mdFix any broken links before committing.
7. Commit Updates
Create a commit for CLAUDE.md changes:
git add CLAUDE.md docs/
git commit -m "$(cat <<'EOF'
Update CLAUDE.md: [brief description of changes]
- [Specific change 1]
- [Specific change 2]
Synced with commit: [original commit hash]
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
EOF
)"Manual Audit Mode
When explicitly requested or for periodic maintenance:
1. Run Full Audit
python scripts/audit_claudemd.py --claudemd CLAUDE.md --reportThis checks for:
- Broken file references
- Outdated configuration mentions
- Overly verbose sections
- Broken docs/ links
2. Review Audit Results
The audit categorizes issues:
missing_file: File referenced in CLAUDE.md no longer exists
- Remove the reference or update to correct path
config_check: Configuration file mentioned may be outdated
- Verify the reference matches actual config state
- Update or remove if inaccurate
verbosity: Section is too long
- Move content to docs/ with link
- Condense to essential points
broken_link: docs/ link is invalid
- Fix the link or create the missing doc
3. Systematic Cleanup
Work through audit issues systematically:
1. Fix file references: Update all missing file paths 2. Verify configs: Check each config reference against actual files 3. Reduce verbosity: Move long sections to docs/ 4. Repair links: Create missing docs or fix paths
4. Overall Coherence Check
After fixing audit issues, review CLAUDE.md as a whole:
Structure check:
- Is organization logical?
- Are sections clearly labeled?
- Is there a natural flow?
Content check:
- Does each section add value?
- Are examples current and accurate?
- Is information duplicated anywhere?
Completeness check:
- Are critical conventions documented?
- Are new patterns from recent commits included?
- Is anything essential missing?
5. Commit Audit Changes
git add CLAUDE.md docs/
git commit -m "$(cat <<'EOF'
Audit and update CLAUDE.md
- Fix [N] broken file references
- Move verbose sections to docs/
- Update configuration references
- Remove outdated information
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
EOF
)"Content Guidelines
See references/guidelines.md for comprehensive content standards.
Quick reference:
- Be concise: Bullet points over paragraphs
- Be current: Remove outdated info immediately
- Be specific: Link to actual file paths
- Split when verbose: >3 paragraphs → docs/ folder
- Link generously: Point to details rather than include everything
Examples
See references/examples.md for good vs bad examples covering:
- Configuration changes
- Component patterns
- API conventions
- Testing requirements
- Major refactoring scenarios
- When to create docs/ notes
Common Patterns
Pattern 1: New Feature Added
1. Analyze: Major source changes detected
2. Review: New component pattern introduced
3. Update: Add concise entry to CLAUDE.md
4. If complex: Create docs/component-patterns.md
5. Commit: "Update CLAUDE.md: Document new component pattern"Pattern 2: Configuration Changed
1. Analyze: Config file modified (e.g., package.json)
2. Review: New scripts or dependencies
3. Update: Modify relevant CLAUDE.md section
4. Verify: Ensure all config references accurate
5. Commit: "Update CLAUDE.md: Sync with package.json changes"Pattern 3: Files Renamed/Deleted
1. Analyze: File deletions detected
2. Review: CLAUDE.md for references to deleted files
3. Update: Remove or fix file path references
4. Verify: Run audit to catch any missed references
5. Commit: "Update CLAUDE.md: Fix stale file references"Pattern 4: Audit Finds Verbosity
1. Audit: Section flagged as too long
2. Create: New docs/ note using template
3. Move: Detailed content to docs/ file
4. Update: Replace with concise summary + link
5. Commit: "Refactor CLAUDE.md: Move [topic] details to docs/"Decision Tree
Commit made or update requested?
├─ Automatic after commit
│ ├─ Run analyze_changes.py
│ ├─ Impact level "minor" + no config changes?
│ │ └─ Skip update (notify user)
│ └─ Impact "moderate"/"major" or config changed?
│ ├─ Read CLAUDE.md
│ ├─ Compare against changes
│ ├─ Apply updates (concise, split if verbose)
│ └─ Commit changes
│
└─ Manual audit requested
├─ Run audit_claudemd.py --report
├─ Review audit issues
├─ Fix systematically (files → configs → verbosity → links)
├─ Overall coherence check
└─ Commit audit changesResources
scripts/analyze_changes.py
Analyzes git changes and determines impact on CLAUDE.md.
Usage:
python scripts/analyze_changes.py [--commit <hash>]Output: JSON with change analysis (magnitude, categories, impact level)
scripts/audit_claudemd.py
Audits CLAUDE.md against actual codebase state.
Usage:
python scripts/audit_claudemd.py [--claudemd <path>] [--report] [--json]Checks:
- Missing file references
- Outdated config mentions
- Overly verbose sections
- Broken docs/ links
references/guidelines.md
Comprehensive content guidelines for CLAUDE.md including:
- When to include vs move to docs/
- Content quality standards
- Section organization
- Maintenance workflow
- Red flags to watch for
Load when you need detailed guidance on content decisions.
references/examples.md
Good vs bad examples covering:
- Configuration changes
- Component patterns
- API conventions
- Major refactoring scenarios
- When to create docs/ notes
Load when you need specific examples for comparison.
assets/note-template.md
Template for creating detailed docs/ notes with standard structure:
- Purpose statement
- Overview
- Sections with examples
- Common patterns
- Troubleshooting
- Last updated date
Copy this template when creating new docs/ notes.
Red Flags
Never:
- Leave outdated file references in CLAUDE.md
- Add verbose content (>4 paragraphs) directly to CLAUDE.md
- Include historical context ("we used to...")
- Skip verification after updates
- Commit without descriptive message
Always:
- Run analysis before updates (automatic mode)
- Check for verbosity (split to docs/ if needed)
- Remove outdated information immediately
- Verify links before committing
- Create commit with specific change description
Integration
This skill runs:
Automatically (if configured):
- After git commit via post-commit hook
- Triggered by commit workflow skills
Manually:
- User requests CLAUDE.md update
- User requests CLAUDE.md audit
- After major refactoring
- Periodic maintenance (weekly/monthly)
Pairs with:
- Commit workflow skills
- Documentation maintenance tasks
- Code review processes
[Topic Title]
Purpose: [One sentence describing what this document covers and when to reference it]
>
Linked from: CLAUDE.md - [Section Name]
Overview
[Brief 2-3 sentence overview of the topic]
[Section 1]
[Detailed content goes here]
Examples
```[language] // Code examples with clear comments
## [Section 2]
[More detailed content]
## Common Patterns
[Reusable patterns or recipes]
## Troubleshooting
[Common issues and solutions]
---
*Last updated: [YYYY-MM-DD]*
*Related docs: [Link to related documentation if applicable]*
CLAUDE.md Examples: Good vs Bad
Example 1: Configuration Changes
❌ Bad (Too Verbose)
## Build Configuration
Our build process has evolved over time. We started with webpack but migrated to Vite for better performance and developer experience. The configuration is complex because we need to support multiple entry points and optimize for production.
Here's our complete vite.config.ts:
import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' // ... 40 more lines of config
When you need to modify the build:
1. First, understand what you're trying to change
2. Read the Vite documentation
3. Make your changes carefully
4. Test in development first
5. Then test in production build✅ Good (Concise + Link)
## Build Configuration
Using Vite with React. Key settings in `vite.config.ts`:
- Multi-entry for main app + admin panel
- Custom alias: `@/` maps to `src/`
For configuration details: [docs/build-setup.md](docs/build-setup.md)---
Example 2: Component Patterns
❌ Bad (Over-explained)
## Component Structure
We use a specific component structure that follows React best practices and our team conventions. Each component should be in its own directory with the following files:
- ComponentName.tsx - The main component file
- ComponentName.module.css - Styles for the component
- ComponentName.test.tsx - Unit tests
- index.ts - Re-exports the component for cleaner imports
This structure helps us maintain consistency across the codebase and makes it easier to find related files. When creating a new component, always follow this pattern. For example, if you're creating a Button component, you would create:
components/ Button/ Button.tsx Button.module.css Button.test.tsx index.ts
The Button.tsx file should export a default function...
[continues with more explanation]✅ Good (Example-driven)
## Component Structure
Components follow this structure:components/ ComponentName/ ComponentName.tsx # Main component ComponentName.module.css # Styles ComponentName.test.tsx # Tests index.ts # Re-export
See existing components in `src/components/` for patterns.---
Example 3: API Conventions
❌ Bad (Duplicate Information)
## API Integration
All API calls go through our centralized API client located in `src/lib/api.ts`. This client handles authentication, error handling, retry logic, and response transformation. We use this pattern to ensure consistency across the application.
The API client exports these methods:
- get(url, options)
- post(url, data, options)
- put(url, data, options)
- delete(url, options)
Each method returns a Promise that resolves with the response data or rejects with an error object.
Authentication is handled automatically by the client. It reads the token from localStorage and includes it in the Authorization header. If the token is expired, the client will attempt to refresh it before making the request.
Error handling is centralized. All errors are transformed into a consistent format with:
- status: HTTP status code
- message: User-friendly error message
- code: Application-specific error code
[continues with more details about error types, retry logic, etc.]✅ Good (Reference Implementation)
## API Integration
All API calls use `src/lib/api.ts` client:
import { api } from '@/lib/api'
const users = await api.get('/users') const created = await api.post('/users', { name: 'John' })
Client handles auth, errors, and retries. See [docs/api-client.md](docs/api-client.md) for error handling patterns.---
Example 4: Testing Requirements
❌ Bad (Unnecessary Context)
## Testing Philosophy
We believe strongly in testing. Tests help us catch bugs early, document expected behavior, and enable confident refactoring. Our testing approach has evolved as the team has grown and the codebase has matured.
We use Jest as our test runner because it provides a great developer experience with features like snapshot testing, mocking, and code coverage. We also use React Testing Library for component tests because it encourages testing from the user's perspective rather than implementation details.
When writing tests, you should:
- Test behavior, not implementation
- Use meaningful test descriptions
- Keep tests focused and isolated
- Mock external dependencies
- Aim for high coverage but don't obsess over 100%
Here's an example of a good test:
describe('LoginForm', () => { it('should submit credentials when form is valid', async () => { // ... 30 lines of test code }) })
✅ Good (Requirements Only)
## Testing
Requirements:
- Tests required for all new features
- Run `npm test` before committing
- Min 80% coverage for new code
Use Jest + React Testing Library. See [docs/testing-patterns.md](docs/testing-patterns.md) for examples.---
Example 5: Handling Major Changes
Scenario: Authentication system was refactored from custom JWT to NextAuth.js
❌ Bad (Historical Context)
## Authentication
Previously, we used a custom JWT authentication system with tokens stored in localStorage. However, we migrated to NextAuth.js for better security and OAuth support. The old system can still be found in git history if you need to reference it.
Current authentication uses NextAuth.js...✅ Good (Current State Only)
## Authentication
Using NextAuth.js with session-based auth:
- Config: `pages/api/auth/[...nextauth].ts`
- Session access: `useSession()` hook
- Providers: Google, GitHub, Email
See [docs/auth-setup.md](docs/auth-setup.md) for provider configuration.---
Example 6: When to Create docs/ Notes
Trigger: Adding database schema information (50+ lines)
❌ Bad (Everything in CLAUDE.md)
## Database Schema
We use PostgreSQL with Prisma ORM. Here's the complete schema:
// ... 100 lines of schema
And here are the relationships between tables:
[Detailed explanations of each table, relationships, indexes, etc.]✅ Good (Summary + Link)
## Database
PostgreSQL with Prisma ORM. Schema in `prisma/schema.prisma`.
Key tables: users, posts, comments. See [docs/database-schema.md](docs/database-schema.md) for relationships and indexes.
Migrations: `npm run db:migrate`docs/database-schema.md
# Database Schema Reference
## Overview
Complete schema documentation with relationships, indexes, and query patterns.
## Tables
### users
[Detailed table documentation]
### posts
[Detailed table documentation]
...---
Key Takeaways
1. CLAUDE.md = Quick Reference: Essential info only 2. docs/ = Deep Dives: Detailed documentation 3. Remove Historical Context: Only current state matters 4. Show, Don't Tell: Examples over explanations 5. Link Generously: Point to details rather than including everything 6. Update Ruthlessly: Delete outdated info immediately
CLAUDE.md Content Guidelines
Core Principle
CLAUDE.md serves as a concise orientation guide for AI agents working on the codebase. It should contain only essential procedural knowledge that helps agents understand how to work effectively in this specific codebase.
When to Include in CLAUDE.md
Include information that:
- Explains non-obvious conventions or patterns
- Describes essential workflows (deployment, testing, development)
- Documents critical constraints or requirements
- Clarifies the project's structure and organization
- Provides context that would prevent common mistakes
When to Move to docs/
Move content to docs/ when:
- Information exceeds 3-4 paragraphs
- Content includes extensive code examples (>20 lines)
- Details are reference material rather than procedural
- Information is domain-specific deep-dive
- Content will rarely be needed but should be available
Content Quality Standards
Be Concise
- Use bullet points over paragraphs
- Prefer examples over explanations
- Remove redundant information
- Assume AI agents are competent
Be Current
- Remove outdated information immediately after changes
- Update references when files are renamed/moved
- Verify configuration references match actual state
- Delete obsolete workflows or patterns
Be Specific
- Link to actual file paths when referencing code
- Use concrete examples rather than abstract descriptions
- Include exact command syntax for important operations
- Reference specific line numbers for critical patterns
Linking to docs/
When creating docs/ notes, follow this pattern:
## Component Architecture
Components follow a compound pattern with composition. For detailed examples and advanced patterns, see [docs/component-patterns.md](docs/component-patterns.md).
Key principles:
- Single responsibility per component
- Composition over prop drilling
- TypeScript strict mode requiredThe CLAUDE.md entry should: 1. Provide the essential principle (1-2 sentences) 2. Link to detailed docs/ 3. Include minimal example if helpful
Section Organization
Organize CLAUDE.md with clear headers:
# Project Name
Brief 1-2 sentence description
## Development Workflow
## Architecture
## Testing
## Deployment
## Key Conventions
## Common PitfallsAvoid:
- Long introductions
- Historical context
- Personal notes
- Duplicate information
Examples
✅ Good CLAUDE.md Entry
## CSS Conventions
- **No inline CSS** - Use Tailwind classes or CSS modules
- **CSS variables for tokens** - Check globals.css before creating new variables
- See [docs/css-architecture.md](docs/css-architecture.md) for variable namingConcise, actionable, links to details.
❌ Bad CLAUDE.md Entry
## CSS Conventions
This project uses CSS in a specific way that we've found works really well for our team. We've adopted a pattern where we avoid using inline styles because it makes the code harder to maintain and violates our separation of concerns. Instead, we use Tailwind CSS classes which provide utility-first styling...
[continues for several paragraphs]
Here's an example of how to use CSS variables:
[50 lines of code examples]Too verbose, should be split with details in docs/.
Maintenance Workflow
After each commit: 1. Review what changed in the codebase 2. Identify if CLAUDE.md needs updates 3. Check for outdated references 4. If adding >3 paragraphs, create docs/ note instead 5. Remove information that is no longer true 6. Commit CLAUDE.md updates with descriptive message
Red Flags
Watch for these issues:
- CLAUDE.md over 200 lines (likely too verbose)
- Sections with >5 paragraphs (split to docs/)
- Code blocks over 30 lines (move to docs/)
- Historical information ("previously we...", "we used to...")
- Information duplicated from README or other docs
- References to deleted/renamed files
- Outdated configuration mentions
#!/usr/bin/env python3
"""
Analyzes git changes and determines their impact on CLAUDE.md.
Usage:
python analyze_changes.py [--commit <hash>]
--commit: Analyze specific commit (default: HEAD)
"""
import subprocess
import sys
import json
import argparse
from pathlib import Path
from typing import Dict, List, Tuple
def get_git_diff(commit: str = "HEAD") -> str:
"""Get git diff numstat for the specified commit."""
try:
if commit == "HEAD":
# Compare working directory with last commit
result = subprocess.run(
["git", "diff", "HEAD~1..HEAD", "--numstat"],
capture_output=True,
text=True,
check=True
)
else:
result = subprocess.run(
["git", "diff", f"{commit}~1..{commit}", "--numstat"],
capture_output=True,
text=True,
check=True
)
return result.stdout
except subprocess.CalledProcessError as e:
print(f"Error getting git diff: {e}", file=sys.stderr)
return ""
def get_changed_files(commit: str = "HEAD") -> List[str]:
"""Get list of changed files."""
try:
if commit == "HEAD":
result = subprocess.run(
["git", "diff", "HEAD~1..HEAD", "--name-only"],
capture_output=True,
text=True,
check=True
)
else:
result = subprocess.run(
["git", "diff", f"{commit}~1..{commit}", "--name-only"],
capture_output=True,
text=True,
check=True
)
return [f.strip() for f in result.stdout.split('\n') if f.strip()]
except subprocess.CalledProcessError as e:
print(f"Error getting changed files: {e}", file=sys.stderr)
return []
def get_commit_message(commit: str = "HEAD") -> str:
"""Get commit message."""
try:
result = subprocess.run(
["git", "log", "-1", "--pretty=%B", commit],
capture_output=True,
text=True,
check=True
)
return result.stdout.strip()
except subprocess.CalledProcessError as e:
print(f"Error getting commit message: {e}", file=sys.stderr)
return ""
def analyze_change_magnitude(diff_stats: str) -> Dict[str, int]:
"""Analyze the magnitude of changes from git diff --numstat output.
Format: <insertions>\t<deletions>\t<filename>
Example: 413\t0\tfile.txt
"""
lines = diff_stats.split('\n')
total_files = 0
total_insertions = 0
total_deletions = 0
for line in lines:
if not line.strip():
continue
parts = line.split('\t')
if len(parts) >= 3:
total_files += 1
try:
# Handle binary files (marked as '-')
insertions = 0 if parts[0] == '-' else int(parts[0])
deletions = 0 if parts[1] == '-' else int(parts[1])
total_insertions += insertions
total_deletions += deletions
except ValueError:
# Skip lines that can't be parsed
continue
return {
"files_changed": total_files,
"insertions": total_insertions,
"deletions": total_deletions,
"total_changes": total_insertions + total_deletions
}
def categorize_files(files: List[str]) -> Dict[str, List[str]]:
"""Categorize changed files by type."""
categories = {
"config": [],
"source": [],
"tests": [],
"docs": [],
"assets": [],
"other": []
}
config_patterns = ['.json', '.yaml', '.yml', '.toml', '.env', 'config']
test_patterns = ['test', 'spec', '__tests__']
doc_patterns = ['.md', 'README', 'docs/']
asset_patterns = ['.png', '.jpg', '.svg', '.css', '.scss']
for file in files:
file_lower = file.lower()
if any(pattern in file_lower for pattern in config_patterns):
categories["config"].append(file)
elif any(pattern in file_lower for pattern in test_patterns):
categories["tests"].append(file)
elif any(pattern in file_lower for pattern in doc_patterns):
categories["docs"].append(file)
elif any(pattern in file_lower for pattern in asset_patterns):
categories["assets"].append(file)
elif file.endswith(('.js', '.ts', '.tsx', '.jsx', '.py', '.go', '.rs', '.java')):
categories["source"].append(file)
else:
categories["other"].append(file)
return {k: v for k, v in categories.items() if v}
def assess_impact(magnitude: Dict[str, int], categories: Dict[str, List[str]]) -> str:
"""Assess the impact level of changes."""
total_changes = magnitude["total_changes"]
files_changed = magnitude["files_changed"]
# Major change indicators
if total_changes > 100 or files_changed > 10:
return "major"
elif "config" in categories and len(categories.get("config", [])) > 2:
return "major"
elif total_changes > 30 or files_changed > 3:
return "moderate"
else:
return "minor"
def main():
parser = argparse.ArgumentParser(description="Analyze git changes for CLAUDE.md updates")
parser.add_argument("--commit", default="HEAD", help="Commit hash to analyze")
args = parser.parse_args()
# Gather change data
diff_stats = get_git_diff(args.commit)
changed_files = get_changed_files(args.commit)
commit_msg = get_commit_message(args.commit)
# Analyze changes
magnitude = analyze_change_magnitude(diff_stats)
categories = categorize_files(changed_files)
impact = assess_impact(magnitude, categories)
# Output analysis
analysis = {
"commit": args.commit,
"commit_message": commit_msg,
"magnitude": magnitude,
"categories": categories,
"impact": impact,
"changed_files": changed_files
}
print(json.dumps(analysis, indent=2))
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
Audits CLAUDE.md against the actual codebase state.
Checks for:
- References to deleted files
- Outdated configuration references
- Inconsistent patterns or conventions
- Missing critical information
Usage:
python audit_claudemd.py [--claudemd <path>] [--report]
"""
import os
import sys
import subprocess
import json
import re
import argparse
from pathlib import Path
from typing import List, Dict, Tuple
def read_claudemd(path: str = "CLAUDE.md") -> str:
"""Read CLAUDE.md file."""
try:
with open(path, 'r', encoding='utf-8') as f:
return f.read()
except FileNotFoundError:
print(f"Error: {path} not found", file=sys.stderr)
sys.exit(1)
def extract_file_references(content: str) -> List[str]:
"""Extract file path references from CLAUDE.md."""
# Match common patterns: `src/file.ts`, /path/to/file, etc.
patterns = [
r'`([a-zA-Z0-9_\-./]+\.[a-zA-Z0-9]+)`', # `file.ext`
r'(?:^|\s)([a-zA-Z0-9_\-./]+/[a-zA-Z0-9_\-./]+\.[a-zA-Z0-9]+)(?:\s|$)', # path/to/file.ext
]
refs = set()
for pattern in patterns:
matches = re.findall(pattern, content)
refs.update(matches)
return list(refs)
def check_file_exists(filepath: str) -> bool:
"""Check if a file exists in the repository."""
return os.path.exists(filepath)
def get_all_files() -> List[str]:
"""Get all tracked files in the repository."""
try:
result = subprocess.run(
["git", "ls-files"],
capture_output=True,
text=True,
check=True
)
return [f.strip() for f in result.stdout.split('\n') if f.strip()]
except subprocess.CalledProcessError:
return []
def check_outdated_references(content: str, tracked_files: List[str]) -> List[Dict[str, str]]:
"""Find references to files that no longer exist or aren't git-tracked."""
issues = []
file_refs = extract_file_references(content)
for ref in file_refs:
# Check if file exists and is git-tracked
if not check_file_exists(ref):
issues.append({
"type": "missing_file",
"file": ref,
"message": f"Referenced file does not exist: {ref}"
})
elif ref not in tracked_files:
issues.append({
"type": "untracked_file",
"file": ref,
"message": f"Referenced file exists but is not git-tracked: {ref}"
})
return issues
def check_config_consistency(content: str) -> List[Dict[str, str]]:
"""Check for outdated configuration references."""
issues = []
# Check for common config files and their actual state
config_files = {
"package.json": ["dependencies", "scripts"],
"tsconfig.json": ["compilerOptions"],
"next.config.js": ["next.config"],
".env": ["environment variables"]
}
for config_file, keywords in config_files.items():
if os.path.exists(config_file):
# Check if CLAUDE.md mentions this config (any keyword match)
if any(keyword.lower() in content.lower() for keyword in keywords):
issues.append({
"type": "config_check",
"file": config_file,
"message": f"Review {config_file} references for accuracy"
})
return issues
def check_verbosity(content: str) -> List[Dict[str, str]]:
"""Check for overly verbose sections."""
issues = []
sections = content.split('\n##')
for i, section in enumerate(sections):
lines = section.split('\n')
# Check for very long paragraphs
for line in lines:
if len(line) > 500: # Very long line
issues.append({
"type": "verbosity",
"section": f"Section {i}",
"message": f"Consider breaking up long paragraph ({len(line)} chars) or moving to docs/"
})
# Check for code blocks over 30 lines
code_blocks = re.findall(r'```[\s\S]*?```', section)
for block in code_blocks:
lines_in_block = len(block.split('\n'))
if lines_in_block > 30:
issues.append({
"type": "verbosity",
"section": f"Section {i}",
"message": f"Large code block ({lines_in_block} lines) - consider moving to docs/ with link"
})
return issues
def check_docs_links(content: str) -> List[Dict[str, str]]:
"""Check that docs/ links are valid."""
issues = []
# Extract markdown links
links = re.findall(r'\[([^\]]+)\]\(([^)]+)\)', content)
for link_text, link_url in links:
if link_url.startswith('docs/'):
if not check_file_exists(link_url):
issues.append({
"type": "broken_link",
"link": link_url,
"message": f"Broken docs/ link: {link_url}"
})
return issues
def generate_report(issues: List[Dict[str, str]]) -> str:
"""Generate audit report."""
if not issues:
return "✅ CLAUDE.md audit passed - no issues found"
report = ["CLAUDE.md Audit Report", "=" * 50, ""]
# Group by type
by_type = {}
for issue in issues:
issue_type = issue["type"]
if issue_type not in by_type:
by_type[issue_type] = []
by_type[issue_type].append(issue)
for issue_type, items in by_type.items():
report.append(f"\n{issue_type.upper().replace('_', ' ')} ({len(items)} issues):")
report.append("-" * 50)
for item in items:
report.append(f" • {item['message']}")
report.append("\n" + "=" * 50)
report.append(f"Total issues found: {len(issues)}")
return '\n'.join(report)
def main():
parser = argparse.ArgumentParser(description="Audit CLAUDE.md against codebase")
parser.add_argument("--claudemd", default="CLAUDE.md", help="Path to CLAUDE.md file")
parser.add_argument("--report", action="store_true", help="Generate detailed report")
parser.add_argument("--json", action="store_true", help="Output as JSON")
args = parser.parse_args()
content = read_claudemd(args.claudemd)
tracked_files = get_all_files()
# Run all checks
all_issues = []
all_issues.extend(check_outdated_references(content, tracked_files))
all_issues.extend(check_config_consistency(content))
all_issues.extend(check_verbosity(content))
all_issues.extend(check_docs_links(content))
if args.json:
print(json.dumps({"issues": all_issues}, indent=2))
else:
print(generate_report(all_issues))
# Exit with error code if issues found (1 for any issues, 0 for success)
sys.exit(1 if all_issues else 0)
if __name__ == "__main__":
main()