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-lite/skills/clean-codebase" ~/.claude/skills/pjt222-agent-almanac-clean-codebase && rm -rf "$T"
i18n/caveman-lite/skills/clean-codebase/SKILL.mdclean-codebase
When to Use
Use this skill when a codebase has accumulated hygiene debt:
- Lint warnings have piled up during rapid development
- Unused imports and variables clutter files
- Dead code paths exist but were never removed
- Formatting is inconsistent across files
- Static analysis tools report fixable issues
Do NOT use for architectural refactoring, bug fixes, or business logic changes. This skill focuses purely on hygiene and automated cleanup.
Inputs
| Parameter | 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) |
Procedure
Step 1: Pre-Cleanup Assessment
Measure the current state to quantify improvements 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
Got: Baseline metrics saved to
lint_before.json and cloc_before.json
If fail: If lint tool not found, skip automated fixes and focus on manual review
Step 2: Fix Automated Lint Warnings
Apply safe automated fixes (spacing, quotes, semicolons, trailing whitespace).
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
Got: All safe lint warnings resolved; files formatted consistently
If fail: If automated fixes introduce test failures, revert changes and escalate
Step 3: Identify Dead Code Paths
Use static analysis to find unreferenced functions, unused variables, and 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 for function definitions
- Grep for function calls
- Report functions defined but never called
Got:
dead_code.txt lists unused functions, variables, and files
If fail: If static analysis tool unavailable, manually review recent commit history for orphaned code
Step 4: Remove Unused Imports
Clean up import blocks by removing references to packages 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
Got: All unused import statements removed
If fail: If removing imports breaks build, they were used indirectly — restore and document
Step 5: Remove Dead Code (Mode-Dependent)
Safe Mode (default):
- Only remove code explicitly marked as deprecated
- Remove commented-out code blocks (if >10 lines and >6 months old)
- Remove TODO comments referencing completed issues
Aggressive Mode (opt-in):
- Remove all functions identified as unused in Step 3
- Remove private methods with zero references
- Remove feature flags for deprecated features
For each candidate deletion:
- Verify zero references in codebase
- Check git history for recent activity (skip if modified in last 30 days)
- Remove code and add entry to
CLEANUP_LOG.md
Got: Dead code removed;
CLEANUP_LOG.md documents all deletions
If fail: If uncertain whether code is truly dead, move to
archive/ directory instead
Step 6: Normalize Formatting
Ensure consistent formatting across all files (even if not caught by linters).
- Normalize line endings (LF vs CRLF)
- Ensure single newline at end of file
- Remove trailing whitespace
- Normalize indentation (spaces vs tabs, indent 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:]]*$//' {} +
Got: All files follow consistent formatting conventions
If fail: If sed breaks binary files, skip and document
Step 7: Run Tests
Validate that cleanup didn't break functionality.
# Language-specific test command npm test # JavaScript pytest # Python R CMD check # R cargo test # Rust
Got: All tests pass (or same failures as before cleanup)
If fail: Revert changes incrementally to identify breaking change, then escalate
Step 8: Generate Cleanup Report
Document 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
Got: Report saved to
CLEANUP_REPORT.md in project root
If fail: (N/A — generate report regardless of outcome)
Validation Checklist
After cleanup:
- All tests pass (or same failures as before)
- No new lint warnings introduced
- Backup created before any deletions
-
documents all removed codeCLEANUP_LOG.md - Cleanup report generated with metrics
- Git diff reviewed for unexpected changes
- CI pipeline passes
Pitfalls
-
Removing Code Still Used via Reflection: Static analysis misses dynamic calls (e.g.,
, metaprogramming). Always check git history.eval() -
Breaking Implicit Dependencies: Removing imports that were used by dependencies. Run tests after every import removal.
-
Deleting Feature Flags for Active Features: Even if unused in current branch, feature flags may be active in other environments. Check deployment configs.
-
Over-Aggressive Formatting: Tools like
orblack
may reformat code in ways that trigger unnecessary diffs. Configure tools to match project style.prettier -
Ignoring Test Coverage: Cannot safely clean codebases without tests. If coverage is low, escalate for test additions first.
-
Not Backing Up: Always create
directory before deleting anything, even if using git.backup_YYYYMMDD/ -
Wrong R binary on hybrid systems: On WSL or Docker,
may resolve to a cross-platform wrapper instead of native R. Check withRscript
. Prefer the native R binary (e.g.,which Rscript && Rscript --version
on Linux/WSL) for reliability. See Setting Up Your Environment for R path configuration./usr/local/bin/Rscript
Related Skills
- tidy-project-structure — Organize directory layout, update READMEs
- repair-broken-references — Fix dead links and imports
- escalate-issues — Route complex problems to specialists
- r-packages/run-r-cmd-check — Run full R package checks
- devops/dependency-audit — Check for outdated dependencies