Agent-almanac clean-codebase
git clone https://github.com/pjt222/agent-almanac
T=$(mktemp -d) && git clone --depth=1 https://github.com/pjt222/agent-almanac "$T" && mkdir -p ~/.claude/skills && cp -r "$T/i18n/caveman-ultra/skills/clean-codebase" ~/.claude/skills/pjt222-agent-almanac-clean-codebase-5b9b71 && rm -rf "$T"
i18n/caveman-ultra/skills/clean-codebase/SKILL.mdclean-codebase
Use When
Codebase has hygiene debt:
- Lint warns piled up during rapid dev
- Unused imports + vars clutter files
- Dead code paths never removed
- Formatting inconsistent across files
- Static analysis reports fixable issues
Do NOT use for architectural refactor, bug fixes, or business logic changes. This = hygiene + automated cleanup only.
In
| Param | Type | Required | Description |
|---|---|---|---|
| string | Yes | Absolute path to codebase root |
| string | Yes | Primary language (js, python, r, rust, etc.) |
| enum | No | (default) or |
| boolean | No | Run test suite after cleanup (default: true) |
| boolean | No | Create backup before deletion (default: true) |
Do
Step 1: Pre-Cleanup Assessment
Measure current state → quantify gains later.
# Count lint warnings by severity lint_tool --format json > lint_before.json # Count lines of code cloc . --json > cloc_before.json # List unused symbols (language-dependent) # JavaScript/TypeScript: ts-prune or depcheck # Python: vulture # R: lintr unused function checks
→ Baseline metrics saved to
lint_before.json + cloc_before.json
If err: Lint tool not found → skip automated fixes, manual review
Step 2: Fix Automated Lint Warnings
Apply safe auto fixes (spacing, quotes, semis, trailing ws).
JavaScript/TypeScript:
eslint --fix . prettier --write .
Python:
black . isort . ruff check --fix .
R:
Rscript -e "styler::style_dir('.')"
Rust:
cargo fmt cargo clippy --fix --allow-dirty
→ All safe lint warns resolved; files formatted consistent
If err: Auto fixes break tests → revert, escalate
Step 3: Identify Dead Code Paths
Static analysis → unreferenced fns, unused vars, orphaned files.
JavaScript/TypeScript:
ts-prune | tee dead_code.txt depcheck | tee unused_deps.txt
Python:
vulture . | tee dead_code.txt
R:
Rscript -e "lintr::lint_dir('.', linters = lintr::unused_function_linter())"
General approach:
- Grep fn defs
- Grep fn calls
- Report fns defined but never called
→
dead_code.txt lists unused fns, vars, files
If err: Static analysis tool unavail → manual review recent commit history for orphans
Step 4: Remove Unused Imports
Clean import blocks → drop refs to pkgs never used.
JavaScript:
eslint --fix --rule 'no-unused-vars: error'
Python:
autoflake --remove-all-unused-imports --in-place --recursive .
R:
# Manual review: grep for library() calls, check if package used grep -r "library(" . | cut -d: -f2 | sort | uniq
→ All unused imports removed
If err: Removing imports breaks build → used indirectly → restore + doc
Step 5: Remove Dead Code (Mode-Dependent)
Safe Mode (default):
- Remove code explicit marked deprecated
- Remove commented-out blocks (>10 lines + >6 months old)
- Remove TODO comments for completed issues
Aggressive Mode (opt-in):
- Remove all unused fns from Step 3
- Remove private methods w/ zero refs
- Remove feature flags for deprecated features
Each candidate deletion:
- Valid. zero refs in codebase
- Check git history → skip if modified last 30 days
- Remove + add entry to
CLEANUP_LOG.md
→ Dead code removed;
CLEANUP_LOG.md documents all deletions
If err: Uncertain code truly dead → move to
archive/ dir vs. delete
Step 6: Normalize Formatting
Consistent formatting all files (even if linters miss).
- Normalize line endings (LF vs CRLF)
- Single newline at EOF
- Remove trailing ws
- Normalize indentation (spaces vs tabs, width)
# Example: Fix line endings and trailing whitespace find . -type f -name "*.js" -exec sed -i 's/\r$//' {} + find . -type f -name "*.js" -exec sed -i 's/[[:space:]]*$//' {} +
→ All files follow consistent formatting conventions
If err: sed breaks binary files → skip + doc
Step 7: Run Tests
Valid. cleanup didn't break functionality.
# Language-specific test command npm test # JavaScript pytest # Python R CMD check # R cargo test # Rust
→ All tests pass (or same fails as pre-cleanup)
If err: Revert incrementally → identify breaking change → escalate
Step 8: Generate Cleanup Report
Doc all changes for review.
# Codebase Cleanup Report **Date**: YYYY-MM-DD **Mode**: safe | aggressive **Language**: <language> ## Metrics | Metric | Before | After | Change | |--------|--------|-------|--------| | Lint warnings | X | Y | -Z | | Lines of code | A | B | -C | | Unused imports | D | 0 | -D | | Dead functions | E | F | -G | ## Changes Applied 1. Fixed X lint warnings (automated) 2. Removed Y unused imports 3. Deleted Z lines of dead code (see CLEANUP_LOG.md) 4. Normalized formatting across W files ## Escalations - [Issue description requiring human review] - [Uncertain deletion moved to archive/] ## Validation - [x] All tests pass - [x] Backup created: backup_YYYYMMDD/ - [x] CLEANUP_LOG.md updated
→ Report saved to
CLEANUP_REPORT.md in project root
If err: (N/A — generate report regardless)
Check
Post-cleanup:
- All tests pass (or same fails as before)
- No new lint warns introduced
- Backup created pre-delete
-
documents all removed codeCLEANUP_LOG.md - Cleanup report generated w/ metrics
- Git diff reviewed for unexpected changes
- CI pipeline passes
Traps
-
Remove Code Still Used via Reflection: Static analysis misses dynamic calls (e.g.,
, metaprogramming). Always check git history.eval() -
Break Implicit Deps: Removing imports used by deps. Run tests after every import removal.
-
Delete Feature Flags for Active Features: Unused in current branch, but maybe active in other envs. Check deployment configs.
-
Over-Aggressive Formatting: Tools like
/black
reformat → unnecessary diffs. Configure tools → project style.prettier -
Ignore Test Coverage: Can't safely clean codebases w/o tests. Low coverage → escalate for test additions first.
-
No Backup: Always create
dir pre-delete, even w/ git.backup_YYYYMMDD/ -
Wrong R binary on hybrid systems: WSL / Docker,
maybe resolves to cross-platform wrapper vs. native R. Check w/Rscript
. Prefer native R binary (e.g.,which Rscript && Rscript --version
Linux/WSL) for reliability. See Setting Up Your Environment for R path config./usr/local/bin/Rscript
→
- tidy-project-structure — Organize dir layout, update READMEs
- repair-broken-references — Fix dead links + imports
- escalate-issues — Route complex problems to specialists
- r-packages/run-r-cmd-check — Full R pkg checks
- devops/dependency-audit — Check outdated deps