Skip to main content
hooksSource-backedReview first Safety Privacy

Dead Code Eliminator - Hooks

A Claude Code SessionEnd hook that scans a project for dead code and writes a report to .claude/reports. It runs available tools per language: ESLint and Knip for JS/TS, autoflake or pylint for Python, Knip for unused npm dependencies, ripgrep for unreferenced src files, and jq to flag zero-coverage files.

by JSONbored·added 2025-10-19·
HarnessClaude Code
Review first review before installing

Open the source and read safety notes before installing.

Citation facts

Source-backed facts for citing this resource, derived directly from the registry — also available as plain text for AI assistants.

Source URLs
https://code.claude.com/docs/en/hooks, https://github.com/JSONbored/awesome-claude/blob/main/content/hooks/dead-code-eliminator.mdx
Safety notes
Registered as a SessionEnd hook, so it runs automatically every time a Claude Code session ends., Invokes external tools via npx (ts-prune, Knip, eslint) and locally installed binaries (autoflake, pylint, vulture, jq, rg), which can trigger package downloads and execute project tooling., Defaults to DRY_RUN=true and only writes a report; setting DRY_RUN=false is intended to enable destructive cleanup, so review the report before changing it., Creates directories under .claude/backups and .claude/reports in the working tree.
Privacy notes
Writes a dead-code report containing file paths, export names, and dependency names from the project to .claude/reports/dead-code-report.txt and echoes it to stderr., Running tools via npx may fetch packages from the npm registry over the network.
Author
JSONbored
Claim status
unclaimed
Last verified
2025-10-19

Decision playbook

Review trust signals before you adopt

Signals are present but mixed. Use the checklist below to confirm the source and operational safety for your environment.

Compare context
Selected

0

Current score

78

Baseline

Delta

No baseline selected

No major trust-signal divergence detected in the current selection.

Source and provenance checks

Complete

Confirm ownership and provenance before trusting install instructions.

  • Source link availableRequired

    Open the canonical repository and verify ownership.

    Done
  • Source provenance statusRequired

    Marked as source-backed.

    Done
  • Metadata reviewed

    Registry metadata indicates a reviewed listing.

    Done

Safety and privacy checks

Complete

Validate risk disclosures before installation or API wiring.

  • Safety notes presentRequired

    Review the listed safety guidance before running commands.

    Done
  • Privacy notes presentRequired

    Review data handling notes before connecting accounts or secrets.

    Done
  • Trust level risk gateRequired

    Trust level does not block evaluation.

    Done

Package and install checks

Needs review

Check package metadata and artifact integrity signals.

  • Install payload available

    Install or copy payload is available for review.

    Done
  • Package verification flag

    No package verification flag provided.

    Pending
  • Checksum metadata

    No checksum provided for downloaded artifact.

    Pending

Compare-driven decision checks

Needs review

Use compare context to validate trade-offs before adoption.

  • Compare tray has multiple entries

    Add at least one more entry to compare trust differences.

    Pending
  • Baseline comparison available

    No baseline peer selected yet.

    Pending
  • Diverging trust signals identified

    No major trust-signal divergence found.

    Pending

Setup at a glance

CLI install

Copy-ready — paste the snippet to get started.

Install command

Provided

Config snippet

Provided

Copy snippet

Provided

Prerequisites

None

Platforms

1 listed

Difficulty

0/100

Adoption plan

Balanced adoption plan

Current risk score 16/100. Use staged verification before broader rollout.

Risk 16

Pre-adoption checks

Validate source and review signals before any execution.

  • Confirm source provenanceRequired

    Source URL/provenance metadata is present.

    Done
  • Confirm metadata review state

    Listing has review metadata.

    Done
  • Verify install payload

    Install/config payload exists and can be inspected.

    Done

Security checks

Confirm safety, privacy, and package integrity signals.

  • Review safety notesRequired

    Safety notes are present.

    Done
  • Review privacy notesRequired

    Privacy notes are present.

    Done
  • Verify package integrity metadata

    No package verification/checksum metadata.

    Pending

Rollout

Adopt in controlled steps based on the selected plan.

  • Run in isolated sandbox firstRequired

    Use a constrained sandbox and observe behavior across multiple tasks.

    Pending
  • Roll out graduallyRequired

    Roll out to a small cohort before wider usage.

    Pending
  • Set monitoring and fallback

    Define rollback path and monitor errors after adoption.

    Pending

Evidence readiness

Evidence readiness matrix · balanced

Required evidence gates are covered (5/6 signals complete).

Risk 15

Source provenance

Present

Source repository/provenance is listed.

Required in this preset

Metadata review

Present

Review metadata is present.

Required in this preset

Safety notes

Present

Safety notes are present.

Required in this preset

Privacy notes

Present

Privacy notes are present.

Optional in this preset

Package integrity

Missing

Package integrity metadata is missing.

Optional in this preset

Install payload

Present

Install payload is available.

Required in this preset

Required evidence gates are covered for this preset.

Decision timeline

Decision timeline · balanced

5/6 steps complete with no blocking gaps for this preset.

Risk 14

triage

Confirm source provenanceRequired

Source/provenance metadata is available.

Done

triage

Check metadata review statusRequired

Review metadata is available.

Done

verify

Review safety notesRequired

Safety notes are available.

Done

verify

Review privacy notes

Privacy notes are available.

Done

verify

Validate package integrity metadata

Package integrity metadata is missing.

Pending

rollout

Verify install payload and commandsRequired

Install payload is available.

Done

No required blockers for this timeline preset.

Safety & privacy surface

Safety & privacy surface

4 safety and 2 privacy notes across 5 risk areas. Review closely: credentials & tokens, network access.

5 areas
  • SafetyCredentials & tokensRegistered as a SessionEnd hook, so it runs automatically every time a Claude Code session ends.
  • SafetyNetwork accessInvokes external tools via npx (ts-prune, Knip, eslint) and locally installed binaries (autoflake, pylint, vulture, jq, rg), which can trigger package downloads and execute project tooling.
  • SafetyExecution & processesDefaults to DRY_RUN=true and only writes a report; setting DRY_RUN=false is intended to enable destructive cleanup, so review the report before changing it.
  • SafetyGeneralCreates directories under .claude/backups and .claude/reports in the working tree.
  • PrivacyLocal filesWrites a dead-code report containing file paths, export names, and dependency names from the project to .claude/reports/dead-code-report.txt and echoes it to stderr.
  • PrivacyNetwork accessRunning tools via npx may fetch packages from the npm registry over the network.

Safety notes

  • Registered as a SessionEnd hook, so it runs automatically every time a Claude Code session ends.
  • Invokes external tools via npx (ts-prune, Knip, eslint) and locally installed binaries (autoflake, pylint, vulture, jq, rg), which can trigger package downloads and execute project tooling.
  • Defaults to DRY_RUN=true and only writes a report; setting DRY_RUN=false is intended to enable destructive cleanup, so review the report before changing it.
  • Creates directories under .claude/backups and .claude/reports in the working tree.

Privacy notes

  • Writes a dead-code report containing file paths, export names, and dependency names from the project to .claude/reports/dead-code-report.txt and echoes it to stderr.
  • Running tools via npx may fetch packages from the npm registry over the network.

Schema details

Install type
cli
Reading time
1 min
Difficulty score
0
Troubleshooting
Yes
Breaking changes
No
Skill and platform metadata
Retrieval sources
https://code.claude.com/docs/en/hookshttps://github.com/PyCQA/autoflakehttps://github.com/jendrikseipp/vulturehttps://eslint.org/docs/latest/https://jqlang.github.io/jq/manual/https://knip.dev
Runtime and command metadata
Script language
bash
Script body
#!/usr/bin/env bash

echo "🧹 Dead Code Eliminator - Session Cleanup" >&2

# Configuration
BACKUP_DIR=".claude/backups/dead-code-$(date +%Y%m%d-%H%M%S)"
REPORT_FILE=".claude/reports/dead-code-report.txt"
DRY_RUN=${DRY_RUN:-true}

mkdir -p "$(dirname "$REPORT_FILE")"
mkdir -p "$BACKUP_DIR"

echo "📊 Analyzing codebase for dead code..." >&2
echo "Dead Code Analysis - $(date)" > "$REPORT_FILE"
echo "===========================================" >> "$REPORT_FILE"

# Function to find unused imports (JavaScript/TypeScript)
find_unused_imports_js() {
  echo "🔍 Checking for unused imports in JS/TS files..." >&2
  
  if command -v npx &> /dev/null; then
    # Check if eslint-plugin-unused-imports is available
    if [ -f "package.json" ] && grep -q "eslint" package.json; then
      echo "📦 Running ESLint unused imports check..." >&2
      npx eslint --ext .js,.jsx,.ts,.tsx --quiet --format compact . 2>/dev/null | \
        grep "unused" | head -20 >> "$REPORT_FILE" || true
    fi
    
    # Use ts-prune for TypeScript projects
    if [ -f "tsconfig.json" ] && command -v npx &> /dev/null; then
      echo "📦 Running ts-prune for unused exports..." >&2
      npx ts-prune 2>/dev/null | head -30 >> "$REPORT_FILE" || \
        echo "💡 Install ts-prune: npm i -D ts-prune" >&2
    fi
  fi
}

# Function to find unused Python imports
find_unused_imports_python() {
  echo "🔍 Checking for unused imports in Python files..." >&2
  
  if command -v autoflake &> /dev/null; then
    echo "📦 Running autoflake for unused imports..." >&2
    autoflake --check --recursive --remove-all-unused-imports . 2>/dev/null | \
      head -20 >> "$REPORT_FILE" || true
  elif command -v pylint &> /dev/null; then
    echo "📦 Running pylint for unused imports..." >&2
    find . -name "*.py" -type f | head -10 | while read -r file; do
      pylint --disable=all --enable=unused-import "$file" 2>/dev/null
    done >> "$REPORT_FILE" || true
  else
    echo "💡 Install autoflake or pylint for Python dead code detection" >&2
  fi
}

# Function to find unreferenced files
find_unreferenced_files() {
  echo "🔍 Finding potentially unreferenced files..." >&2
  
  # Find files that might be orphaned (not imported anywhere)
  if command -v rg &> /dev/null; then
    echo "" >> "$REPORT_FILE"
    echo "Potentially Unreferenced Files:" >> "$REPORT_FILE"
    echo "--------------------------------" >> "$REPORT_FILE"
    
    # Find .js/.ts files in src
    find src -type f \( -name "*.js" -o -name "*.ts" -o -name "*.tsx" -o -name "*.jsx" \) 2>/dev/null | \
      head -50 | while read -r file; do
        basename="$(basename "$file" | sed 's/\.[^.]*$//')"
        # Check if file is imported anywhere
        if ! rg -q "from.*['\"].*$basename" . 2>/dev/null && \
           ! rg -q "import.*['\"].*$basename" . 2>/dev/null; then
          echo "  - $file (no imports found)" >> "$REPORT_FILE"
        fi
      done
  fi
}

# Function to find unused dependencies
find_unused_dependencies() {
  echo "🔍 Checking for unused npm dependencies..." >&2
  
  if [ -f "package.json" ]; then
    if command -v npx &> /dev/null; then
      echo "" >> "$REPORT_FILE"
      echo "Unused Dependencies Check:" >> "$REPORT_FILE"
      echo "-------------------------" >> "$REPORT_FILE"
      
      # Use Knip if available
      if npx Knip --version &> /dev/null; then
        npx Knip --json 2>/dev/null | \
          jq -r '.dependencies[]' 2>/dev/null | \
          head -10 >> "$REPORT_FILE" || \
          echo "💡 Install Knip: npm i -D Knip" >&2
      fi
    fi
  fi
}

# Function to analyze dead code with coverage data
analyze_with_coverage() {
  echo "📊 Analyzing test coverage for dead code hints..." >&2
  
  if [ -f "coverage/coverage-summary.json" ]; then
    echo "" >> "$REPORT_FILE"
    echo "Zero-Coverage Files (Potential Dead Code):" >> "$REPORT_FILE"
    echo "------------------------------------------" >> "$REPORT_FILE"
    
    jq -r 'to_entries[] | select(.value.lines.pct == 0) | .key' \
      coverage/coverage-summary.json 2>/dev/null | \
      head -10 >> "$REPORT_FILE" || true
  fi
}

# Run all analysis functions
find_unused_imports_js
find_unused_imports_python
find_unreferenced_files
find_unused_dependencies
analyze_with_coverage

# Report summary
echo "" >> "$REPORT_FILE"
echo "Analysis Complete - $(date)" >> "$REPORT_FILE"

# Display report
if [ -s "$REPORT_FILE" ]; then
  echo "" >&2
  echo "📋 Dead Code Analysis Report:" >&2
  cat "$REPORT_FILE" >&2
  echo "" >&2
  echo "💾 Full report saved to: $REPORT_FILE" >&2
  
  if [ "$DRY_RUN" = "true" ]; then
    echo "" >&2
    echo "🔒 DRY RUN mode enabled - no files deleted" >&2
    echo "💡 Set DRY_RUN=false to enable automatic cleanup" >&2
  else
    echo "⚠️ Automatic cleanup enabled - review report carefully" >&2
  fi
else
  echo "✅ No dead code detected" >&2
fi

echo "" >&2
echo "🎯 Dead Code Elimination Best Practices:" >&2
echo "   • Run static analysis tools regularly" >&2
echo "   • Use tree-shaking for production builds" >&2
echo "   • Review unused exports before removal" >&2
echo "   • Maintain high test coverage to identify dead code" >&2
echo "   • Use automated tools: ts-prune, Knip, autoflake" >&2

exit 0
Full copyable content
{
  "hooks": {
    "sessionEnd": {
      "script": "./.claude/hooks/dead-code-eliminator.sh"
    }
  }
}

About this resource

Features

  • Unused import and export detection across multiple languages (JavaScript/TypeScript via ESLint and ts-prune, Python via autoflake or pylint), reported to a file
  • Static analysis of the codebase that aggregates each tool's findings into a single dead-code report
  • Unreferenced source-file detection using ripgrep to flag files in src/ with no matching import statements
  • Report-only output saved to .claude/reports/dead-code-report.txt and echoed to stderr for review
  • Creates a timestamped backup directory under .claude/backups and runs in DRY_RUN=true mode by default, so no files are deleted
  • Coverage-aware analysis that reads coverage/coverage-summary.json with jq to list zero-coverage files
  • Unused npm dependency detection via Knip when package.json is present
  • Multi-language support for JavaScript/TypeScript (ts-prune, ESLint), Python (autoflake, pylint), and dependency analysis (Knip); example snippets also show Knip and Vulture

Use Cases

  • Automated dead-code reporting on session completion, surfacing unused code and dependencies for review
  • Pre-cleanup discovery: identify removal candidates before manually deleting them
  • Refactoring support with safe unused code detection identifying code that can be safely removed during refactoring
  • CI/CD integration for continuous code quality ensuring codebases remain clean and maintainable
  • Technical debt reduction and maintenance automatically identifying and removing accumulated dead code
  • Development workflow optimization providing immediate feedback on unused code as development progresses

Installation

  1. Create hooks directory: mkdir -p .claude/hooks
  2. Create hook file: touch .claude/hooks/dead-code-eliminator.sh
  3. Make executable: chmod +x .claude/hooks/dead-code-eliminator.sh
  4. Add configuration from Hook Configuration section above to .claude/settings.json or ~/.claude/settings.json
  5. Alternative: Use the interactive /hooks command in Claude Code

Config paths

  • Local (not committed): .claude/settings.local.json
  • User settings (global): ~/.claude/settings.json
  • Project-wide (committed): .claude/settings.json

Requirements

  • Claude Code CLI installed
  • Project directory initialized
  • Bash shell available
  • jq command-line JSON processor
  • Dead code detection tools available on PATH or via npx: ts-prune, Knip, autoflake, pylint, ESLint (example snippets also reference Knip and Vulture)
  • Runtime environment: Node.js with npx (for ts-prune/Knip/ESLint) or Python with pip (for autoflake/pylint/Vulture), depending on project language

Hook Configuration

{
  "hooks": {
    "sessionEnd": {
      "script": "./.claude/hooks/dead-code-eliminator.sh"
    }
  }
}

Hook Script

#!/usr/bin/env bash

echo "🧹 Dead Code Eliminator - Session Cleanup" >&2

# Configuration
BACKUP_DIR=".claude/backups/dead-code-$(date +%Y%m%d-%H%M%S)"
REPORT_FILE=".claude/reports/dead-code-report.txt"
DRY_RUN=${DRY_RUN:-true}

mkdir -p "$(dirname "$REPORT_FILE")"
mkdir -p "$BACKUP_DIR"

echo "📊 Analyzing codebase for dead code..." >&2
echo "Dead Code Analysis - $(date)" > "$REPORT_FILE"
echo "===========================================" >> "$REPORT_FILE"

# Function to find unused imports (JavaScript/TypeScript)
find_unused_imports_js() {
  echo "🔍 Checking for unused imports in JS/TS files..." >&2

  if command -v npx &> /dev/null; then
    # Check if eslint-plugin-unused-imports is available
    if [ -f "package.json" ] && grep -q "eslint" package.json; then
      echo "📦 Running ESLint unused imports check..." >&2
      npx eslint --ext .js,.jsx,.ts,.tsx --quiet --format compact . 2>/dev/null | \
        grep "unused" | head -20 >> "$REPORT_FILE" || true
    fi

    # Use ts-prune for TypeScript projects
    if [ -f "tsconfig.json" ] && command -v npx &> /dev/null; then
      echo "📦 Running ts-prune for unused exports..." >&2
      npx ts-prune 2>/dev/null | head -30 >> "$REPORT_FILE" || \
        echo "💡 Install ts-prune: npm i -D ts-prune" >&2
    fi
  fi
}

# Function to find unused Python imports
find_unused_imports_python() {
  echo "🔍 Checking for unused imports in Python files..." >&2

  if command -v autoflake &> /dev/null; then
    echo "📦 Running autoflake for unused imports..." >&2
    autoflake --check --recursive --remove-all-unused-imports . 2>/dev/null | \
      head -20 >> "$REPORT_FILE" || true
  elif command -v pylint &> /dev/null; then
    echo "📦 Running pylint for unused imports..." >&2
    find . -name "*.py" -type f | head -10 | while read -r file; do
      pylint --disable=all --enable=unused-import "$file" 2>/dev/null
    done >> "$REPORT_FILE" || true
  else
    echo "💡 Install autoflake or pylint for Python dead code detection" >&2
  fi
}

# Function to find unreferenced files
find_unreferenced_files() {
  echo "🔍 Finding potentially unreferenced files..." >&2

  # Find files that might be orphaned (not imported anywhere)
  if command -v rg &> /dev/null; then
    echo "" >> "$REPORT_FILE"
    echo "Potentially Unreferenced Files:" >> "$REPORT_FILE"
    echo "--------------------------------" >> "$REPORT_FILE"

    # Find .js/.ts files in src
    find src -type f \( -name "*.js" -o -name "*.ts" -o -name "*.tsx" -o -name "*.jsx" \) 2>/dev/null | \
      head -50 | while read -r file; do
        basename="$(basename "$file" | sed 's/\.[^.]*$//')"
        # Check if file is imported anywhere
        if ! rg -q "from.*['\"].*$basename" . 2>/dev/null && \
           ! rg -q "import.*['\"].*$basename" . 2>/dev/null; then
          echo "  - $file (no imports found)" >> "$REPORT_FILE"
        fi
      done
  fi
}

# Function to find unused dependencies
find_unused_dependencies() {
  echo "🔍 Checking for unused npm dependencies..." >&2

  if [ -f "package.json" ]; then
    if command -v npx &> /dev/null; then
      echo "" >> "$REPORT_FILE"
      echo "Unused Dependencies Check:" >> "$REPORT_FILE"
      echo "-------------------------" >> "$REPORT_FILE"

      # Use Knip if available
      if npx Knip --version &> /dev/null; then
        npx Knip --json 2>/dev/null | \
          jq -r '.dependencies[]' 2>/dev/null | \
          head -10 >> "$REPORT_FILE" || \
          echo "💡 Install Knip: npm i -D Knip" >&2
      fi
    fi
  fi
}

# Function to analyze dead code with coverage data
analyze_with_coverage() {
  echo "📊 Analyzing test coverage for dead code hints..." >&2

  if [ -f "coverage/coverage-summary.json" ]; then
    echo "" >> "$REPORT_FILE"
    echo "Zero-Coverage Files (Potential Dead Code):" >> "$REPORT_FILE"
    echo "------------------------------------------" >> "$REPORT_FILE"

    jq -r 'to_entries[] | select(.value.lines.pct == 0) | .key' \
      coverage/coverage-summary.json 2>/dev/null | \
      head -10 >> "$REPORT_FILE" || true
  fi
}

# Run all analysis functions
find_unused_imports_js
find_unused_imports_python
find_unreferenced_files
find_unused_dependencies
analyze_with_coverage

# Report summary
echo "" >> "$REPORT_FILE"
echo "Analysis Complete - $(date)" >> "$REPORT_FILE"

# Display report
if [ -s "$REPORT_FILE" ]; then
  echo "" >&2
  echo "📋 Dead Code Analysis Report:" >&2
  cat "$REPORT_FILE" >&2
  echo "" >&2
  echo "💾 Full report saved to: $REPORT_FILE" >&2

  if [ "$DRY_RUN" = "true" ]; then
    echo "" >&2
    echo "🔒 DRY RUN mode enabled - no files deleted" >&2
    echo "💡 Set DRY_RUN=false to enable automatic cleanup" >&2
  else
    echo "⚠️ Automatic cleanup enabled - review report carefully" >&2
  fi
else
  echo "✅ No dead code detected" >&2
fi

echo "" >&2
echo "🎯 Dead Code Elimination Best Practices:" >&2
echo "   • Run static analysis tools regularly" >&2
echo "   • Use tree-shaking for production builds" >&2
echo "   • Review unused exports before removal" >&2
echo "   • Maintain high test coverage to identify dead code" >&2
echo "   • Use automated tools: ts-prune, Knip, autoflake" >&2

exit 0

Examples

Dead Code Eliminator Hook Script

Complete hook script that detects and reports dead code when session ends

#!/usr/bin/env bash
echo "Dead Code Eliminator - Session Cleanup" >&2
BACKUP_DIR=".claude/backups/dead-code-$(date +%Y%m%d-%H%M%S)"
REPORT_FILE=".claude/reports/dead-code-report.txt"
DRY_RUN=${DRY_RUN:-true}
mkdir -p "$(dirname "$REPORT_FILE")"
mkdir -p "$BACKUP_DIR"
echo "Analyzing codebase for dead code..." >&2
echo "Dead Code Analysis - $(date)" > "$REPORT_FILE"
if command -v npx &> /dev/null && [ -f "package.json" ]; then
  if npx knip --version &> /dev/null 2>&1; then
    echo "Running Knip for unused dependencies and exports..." >&2
    npx knip 2>/dev/null | head -30 >> "$REPORT_FILE" || true
  fi
fi
echo "Analysis Complete - $(date)" >> "$REPORT_FILE"
if [ "$DRY_RUN" = "true" ]; then
  echo "DRY RUN mode enabled - no files deleted" >&2
else
  echo "Automatic cleanup enabled - review report carefully" >&2
fi
exit 0

TypeScript Unused Exports Detection

Enhanced hook script for TypeScript unused exports detection using ts-prune

#!/usr/bin/env bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
if [ -f "tsconfig.json" ] && command -v npx &> /dev/null; then
  if npx ts-prune --version &> /dev/null 2>&1; then
    echo "Running ts-prune for unused TypeScript exports..." >&2
    npx ts-prune 2>/dev/null | head -20 || echo "Install ts-prune: npm i -D ts-prune" >&2
  fi
fi
exit 0

Python Dead Code Detection

Enhanced hook script for Python dead code detection using autoflake and Vulture

#!/usr/bin/env bash
if command -v autoflake &> /dev/null; then
  echo "Running autoflake for unused Python imports..." >&2
  autoflake --check --recursive --remove-all-unused-imports . 2>/dev/null | head -20 || true
elif command -v vulture &> /dev/null; then
  echo "Running Vulture for Python dead code detection..." >&2
  vulture . --min-confidence 100 2>/dev/null | head -20 || true
else
  echo "Install autoflake or vulture for Python dead code detection" >&2
fi
exit 0

Unused Dependencies Detection

Enhanced hook script for detecting unused npm dependencies using Knip

#!/usr/bin/env bash
if [ -f "package.json" ] && command -v npx &> /dev/null; then
  if npx Knip --version &> /dev/null 2>&1; then
    echo "Running Knip for unused npm dependencies..." >&2
    npx Knip --json 2>/dev/null | jq -r '.dependencies[]' 2>/dev/null | head -10 || echo "Install Knip: npm i -D Knip" >&2
  fi
fi
exit 0

Troubleshooting

SessionEnd hook runs but no dead code report generated

Check .claude/reports directory permissions and disk space. Verify jq command available for JSON parsing. Run manually to see stderr output: bash .claude/hooks/dead-code-eliminator.sh. Check if dead code detection tools are installed (Knip, ts-prune, Knip, autoflake, Vulture).

False positives for dynamic imports and runtime dependencies

Hook uses static analysis only. Exclude dynamic require() patterns from reports. Add ignore patterns to .dead-code-ignore file. Use /_ dead-code-safe _/ comments for runtime-loaded modules. Configure Knip with ignore patterns for dynamic imports.

ts-prune reports too many false positives on exports

Configure ts-prune with .ts-prunerc ignore patterns. Export unused items intentionally for public API. Use ts-prune --ignore to exclude specific paths or patterns from analysis. Consider using Knip 5.x for more accurate TypeScript analysis.

DRY_RUN=false mode deletes files without confirmation

Backup created in .claude/backups before deletion. Review report first in dry run mode. Implement confirmation prompt in script. Use git to recover deleted files if needed. Always test in dry-run mode first before enabling automatic deletion.

Coverage-based detection misses files outside test scope

Zero coverage indicates potential dead code but not definitive. Cross-reference with import analysis. Check if files are runtime-loaded or dynamically required. Verify files are not entry points or config files. Use Knip for more comprehensive analysis.

Knip reports unused dependencies that are actually used

Knip may miss dynamic imports or runtime-loaded dependencies. Add Knip configuration to ignore specific dependencies. Check if dependencies are used in configuration files or build scripts. Verify Knip 5.x version for improved accuracy.

autoflake removes imports that are used at runtime

autoflake uses static analysis and may miss runtime imports. Review autoflake output carefully before applying changes. Use --check flag first to preview changes. Add imports to whitelist if they are intentionally used at runtime.

Vulture reports false positives for framework entry points

Vulture may flag framework entry points as unused. Add entry point files to Vulture whitelist. Use --min-confidence flag to filter low-confidence results. Configure Vulture to ignore specific patterns or file paths.

Source citations

Add this badge to your README

Show that Dead Code Eliminator - Hooks is listed on HeyClaude. Paste this Markdown into your README — it renders the badge and links back to this page.

Listed on HeyClaude
[![Listed on HeyClaude](https://heyclau.de/badge/hooks/dead-code-eliminator.svg)](https://heyclau.de/entry/hooks/dead-code-eliminator)

How it compares

Dead Code Eliminator - Hooks side by side with 3 alternatives on trust, install, platform support, and disclosed safety notes — all from reviewed registry metadata.

Field

A Claude Code SessionEnd hook that scans a project for dead code and writes a report to .claude/reports. It runs available tools per language: ESLint and Knip for JS/TS, autoflake or pylint for Python, Knip for unused npm dependencies, ripgrep for unreferenced src files, and jq to flag zero-coverage files.

Open dossier

A Claude Code hook that flags files exceeding complexity thresholds after you edit them — estimating cyclomatic complexity, line and function counts, and nesting depth (via ESLint's complexity rule and Radon).

Open dossier

Detects unused CSS selectors when stylesheets are modified to keep CSS lean using PurgeCSS, PostCSS, and content analysis. This hook runs on CSS/SCSS file write/edit operations and analyzes stylesheets to identify unused selectors, generate optimized output, and report before/after size metrics.

Open dossier

A Stop hook that terminates lingering database connections when a Claude Code session ends — via PostgreSQL pg_terminate_backend, MySQL KILL, Redis CLIENT KILL, and MongoDB connection cleanup.

Open dossier
Next steps
Trust
Review statusReviewedMaintainer reviewedReviewedMaintainer reviewedReviewedMaintainer reviewedReviewedMaintainer reviewed
Package trustPackage not verifiedPackage not verifiedPackage not verifiedPackage not verified
Source provenanceSource-backedSource-backedSource-backedSource-backed
Submitter
Install riskReview firstReview firstReview firstReview first
Notes Safety Privacy Safety Privacy Safety Privacy Safety Privacy
Brand
Categoryhookshookshookshooks
Sourcesource-backedsource-backedsource-backedsource-backed
AuthorJSONboredJSONboredJSONboredJSONbored
Added2025-10-192025-09-192025-09-192025-09-19
Platforms
Claude Code
Claude Code
Claude Code
Claude Code
Source repo
Safety notesRegistered as a SessionEnd hook, so it runs automatically every time a Claude Code session ends. Invokes external tools via npx (ts-prune, Knip, eslint) and locally installed binaries (autoflake, pylint, vulture, jq, rg), which can trigger package downloads and execute project tooling. Defaults to DRY_RUN=true and only writes a report; setting DRY_RUN=false is intended to enable destructive cleanup, so review the report before changing it. Creates directories under .claude/backups and .claude/reports in the working tree.Runs after edits to JS/TS/Python files and prints advisory warnings only; the line/function/brace counts are heuristics, not a substitute for ESLint or Radon run on the full project.Runs automatically on its configured Claude Code hook event and executes shell logic that can read, modify, or delete files in your project (and may run builds, installs, or network calls); review the script and scope it to expected paths before enabling.Runs at session end and forcibly terminates database backends/clients (pg_terminate_backend, KILL, CLIENT KILL); pointed at a shared or production database it can drop other users' connections — scope it to local/dev databases and confirm the target before enabling.
Privacy notesWrites a dead-code report containing file paths, export names, and dependency names from the project to .claude/reports/dead-code-report.txt and echoes it to stderr. Running tools via npx may fetch packages from the npm registry over the network.Reads the contents of files you edit to compute complexity locally; it prints warnings to hook output and does not transmit code, but those messages can reveal file structure.Receives Claude Code hook input (session metadata, file paths, and tool output) and reads local project files; review what the script logs or forwards to external services and keep credentials out of its output.Uses locally configured database credentials and connection details to issue termination commands; keep those credentials in environment variables, not in the hook.
Prerequisites— none listed— none listed— none listed— none listed
Install
mkdir -p .claude/hooks && touch .claude/hooks/dead-code-eliminator.sh && chmod +x .claude/hooks/dead-code-eliminator.sh
mkdir -p .claude/hooks && touch .claude/hooks/code-complexity-alert-monitor.sh && chmod +x .claude/hooks/code-complexity-alert-monitor.sh
mkdir -p .claude/hooks && touch .claude/hooks/css-unused-selector-detector.sh && chmod +x .claude/hooks/css-unused-selector-detector.sh
mkdir -p .claude/hooks && touch .claude/hooks/database-connection-cleanup.sh && chmod +x .claude/hooks/database-connection-cleanup.sh
Config
{
  "hooks": {
    "sessionEnd": {
      "script": "./.claude/hooks/dead-code-eliminator.sh"
    }
  }
}
{
  "hooks": {
    "notification": {
      "script": "./.claude/hooks/code-complexity-alert-monitor.sh"
    }
  }
}
{
  "hooks": {
    "postToolUse": {
      "script": "./.claude/hooks/css-unused-selector-detector.sh",
      "matchers": [
        "write",
        "edit"
      ]
    }
  }
}
{
  "hooks": {
    "stop": {
      "script": "./.claude/hooks/database-connection-cleanup.sh"
    }
  }
}
Citations
ClaimUnclaimedUnclaimedUnclaimedUnclaimed
Open 4 picks in the interactive comparison tool

Related guides

Signals

Loading live community signals…

More like this, weekly

A short, calm digest of reviewed Claude resources. Unsubscribe any time.