Loading...
Automatically checks for outdated dependencies and suggests updates with security analysis
{
"hookConfig": {
"hooks": {
"postToolUse": {
"script": "./.claude/hooks/dependency-update-checker.sh",
"matchers": [
"write",
"edit"
]
}
}
},
"scriptContent": "#!/usr/bin/env bash\n\n# Read the tool input from stdin\nINPUT=$(cat)\nTOOL_NAME=$(echo \"$INPUT\" | jq -r '.tool_name')\nFILE_PATH=$(echo \"$INPUT\" | jq -r '.tool_input.file_path // .tool_input.path // \"\"')\n\nif [ -z \"$FILE_PATH\" ]; then\n exit 0\nfi\n\n# Check if it's a dependency file\nif [[ \"$FILE_PATH\" == *package.json ]] || [[ \"$FILE_PATH\" == *requirements.txt ]] || [[ \"$FILE_PATH\" == *Gemfile ]] || [[ \"$FILE_PATH\" == *go.mod ]] || [[ \"$FILE_PATH\" == *Cargo.toml ]]; then\n echo \"📦 Dependency file detected: $FILE_PATH\" >&2\n \n # Node.js projects\n if [[ \"$FILE_PATH\" == *package.json ]]; then\n echo \"🟢 Node.js project detected - checking dependencies...\" >&2\n \n if command -v npm &> /dev/null; then\n echo \"🔍 Running npm outdated check...\" >&2\n OUTDATED_OUTPUT=$(npm outdated --depth=0 2>/dev/null || echo \"No outdated packages\")\n \n if [ \"$OUTDATED_OUTPUT\" = \"No outdated packages\" ]; then\n echo \"✅ All npm packages are up to date\" >&2\n else\n echo \"📊 Found outdated npm packages:\" >&2\n echo \"$OUTDATED_OUTPUT\" | head -10 >&2\n \n OUTDATED_COUNT=$(echo \"$OUTDATED_OUTPUT\" | wc -l)\n echo \"📈 Total outdated packages: $OUTDATED_COUNT\" >&2\n fi\n \n # Check for security vulnerabilities\n echo \"🔒 Checking for security vulnerabilities...\" >&2\n AUDIT_OUTPUT=$(npm audit --audit-level=moderate 2>&1)\n \n if echo \"$AUDIT_OUTPUT\" | grep -q \"found 0 vulnerabilities\"; then\n echo \"✅ No security vulnerabilities found\" >&2\n else\n VULN_COUNT=$(echo \"$AUDIT_OUTPUT\" | grep -o '[0-9]\\+ vulnerabilities' | head -1 || echo \"unknown vulnerabilities\")\n echo \"⚠️ Security audit found: $VULN_COUNT\" >&2\n echo \"💡 Run 'npm audit fix' to automatically fix vulnerabilities\" >&2\n fi\n \n # Check for npm-check-updates availability\n if command -v npx &> /dev/null && npx ncu --version &> /dev/null 2>&1; then\n echo \"🔧 Running npm-check-updates for detailed analysis...\" >&2\n NCU_OUTPUT=$(npx ncu 2>/dev/null | head -5)\n echo \"$NCU_OUTPUT\" >&2\n else\n echo \"💡 Install npm-check-updates for better dependency analysis: npm install -g npm-check-updates\" >&2\n fi\n else\n echo \"⚠️ npm command not available\" >&2\n fi\n \n # Python projects\n elif [[ \"$FILE_PATH\" == *requirements.txt ]] || [[ \"$FILE_PATH\" == *pyproject.toml ]]; then\n echo \"🐍 Python project detected - checking dependencies...\" >&2\n \n if command -v pip &> /dev/null; then\n echo \"🔍 Checking for outdated Python packages...\" >&2\n PIP_OUTDATED=$(pip list --outdated 2>/dev/null || echo \"Unable to check outdated packages\")\n \n if [ \"$PIP_OUTDATED\" = \"Unable to check outdated packages\" ]; then\n echo \"⚠️ Unable to check pip packages\" >&2\n else\n OUTDATED_COUNT=$(echo \"$PIP_OUTDATED\" | wc -l)\n if [ \"$OUTDATED_COUNT\" -gt 1 ]; then\n echo \"📊 Found $OUTDATED_COUNT outdated Python packages\" >&2\n echo \"$PIP_OUTDATED\" | head -5 >&2\n else\n echo \"✅ All Python packages are up to date\" >&2\n fi\n fi\n \n # Check for security issues with safety\n if command -v safety &> /dev/null; then\n echo \"🔒 Running Safety security check...\" >&2\n SAFETY_OUTPUT=$(safety check --json 2>/dev/null || safety check 2>/dev/null || echo \"Safety check completed\")\n \n if echo \"$SAFETY_OUTPUT\" | grep -q \"No known security vulnerabilities\"; then\n echo \"✅ No known security vulnerabilities in Python dependencies\" >&2\n else\n echo \"⚠️ Safety scan found potential security issues\" >&2\n fi\n else\n echo \"💡 Install Safety for Python security scanning: pip install safety\" >&2\n fi\n else\n echo \"⚠️ pip command not available\" >&2\n fi\n \n # Ruby projects\n elif [[ \"$FILE_PATH\" == *Gemfile ]]; then\n echo \"💎 Ruby project detected - checking dependencies...\" >&2\n \n if command -v bundle &> /dev/null; then\n echo \"🔍 Checking for outdated Ruby gems...\" >&2\n BUNDLE_OUTDATED=$(bundle outdated 2>/dev/null | head -10 || echo \"Unable to check outdated gems\")\n echo \"$BUNDLE_OUTDATED\" >&2\n \n # Check for security issues\n if bundle exec bundler-audit --version &> /dev/null; then\n echo \"🔒 Running bundler-audit security check...\" >&2\n BUNDLE_AUDIT=$(bundle exec bundler-audit check 2>&1 || echo \"Bundle audit completed\")\n \n if echo \"$BUNDLE_AUDIT\" | grep -q \"No vulnerabilities found\"; then\n echo \"✅ No vulnerabilities found in Ruby gems\" >&2\n else\n echo \"⚠️ Bundle audit found potential issues\" >&2\n fi\n else\n echo \"💡 Install bundler-audit: gem install bundler-audit\" >&2\n fi\n else\n echo \"⚠️ bundle command not available\" >&2\n fi\n \n # Go projects\n elif [[ \"$FILE_PATH\" == *go.mod ]]; then\n echo \"🐹 Go project detected - checking dependencies...\" >&2\n \n if command -v go &> /dev/null; then\n echo \"🔍 Checking Go module dependencies...\" >&2\n \n # List modules\n GO_LIST=$(go list -m -u all 2>/dev/null | head -10 || echo \"Unable to list Go modules\")\n echo \"$GO_LIST\" >&2\n \n # Check for available updates\n OUTDATED_MODULES=$(echo \"$GO_LIST\" | grep -c '\\[' 2>/dev/null || echo \"0\")\n if [ \"$OUTDATED_MODULES\" -gt 0 ]; then\n echo \"📊 Found $OUTDATED_MODULES Go modules with available updates\" >&2\n echo \"💡 Run 'go get -u ./...' to update dependencies\" >&2\n else\n echo \"✅ All Go modules are up to date\" >&2\n fi\n else\n echo \"⚠️ go command not available\" >&2\n fi\n \n # Rust projects\n elif [[ \"$FILE_PATH\" == *Cargo.toml ]]; then\n echo \"🦀 Rust project detected - checking dependencies...\" >&2\n \n if command -v cargo &> /dev/null; then\n # Check for outdated crates\n if cargo outdated --version &> /dev/null; then\n echo \"🔍 Checking for outdated Rust crates...\" >&2\n CARGO_OUTDATED=$(cargo outdated 2>/dev/null | head -10 || echo \"Unable to check outdated crates\")\n echo \"$CARGO_OUTDATED\" >&2\n else\n echo \"💡 Install cargo-outdated: cargo install cargo-outdated\" >&2\n fi\n \n # Security audit\n if cargo audit --version &> /dev/null; then\n echo \"🔒 Running Rust security audit...\" >&2\n CARGO_AUDIT=$(cargo audit 2>&1 || echo \"Audit completed\")\n \n if echo \"$CARGO_AUDIT\" | grep -q \"Success No vulnerable packages found\"; then\n echo \"✅ No vulnerable crates found\" >&2\n else\n echo \"⚠️ Cargo audit found potential issues\" >&2\n fi\n else\n echo \"💡 Install cargo-audit: cargo install cargo-audit\" >&2\n fi\n else\n echo \"⚠️ cargo command not available\" >&2\n fi\n fi\n \n # General recommendations\n echo \"\" >&2\n echo \"📋 Dependency Update Best Practices:\" >&2\n echo \" • Review changelogs before major version updates\" >&2\n echo \" • Test thoroughly after dependency updates\" >&2\n echo \" • Update security-critical packages immediately\" >&2\n echo \" • Use lockfiles for reproducible builds\" >&2\n \nelse\n echo \"File $FILE_PATH is not a recognized dependency file, skipping analysis\" >&2\nfi\n\nexit 0"
}.claude/hooks/~/.claude/hooks/{
"hooks": {
"postToolUse": {
"script": "./.claude/hooks/dependency-update-checker.sh",
"matchers": [
"write",
"edit"
]
}
}
}#!/usr/bin/env bash
# Read the tool input from stdin
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
if [ -z "$FILE_PATH" ]; then
exit 0
fi
# Check if it's a dependency file
if [[ "$FILE_PATH" == *package.json ]] || [[ "$FILE_PATH" == *requirements.txt ]] || [[ "$FILE_PATH" == *Gemfile ]] || [[ "$FILE_PATH" == *go.mod ]] || [[ "$FILE_PATH" == *Cargo.toml ]]; then
echo "📦 Dependency file detected: $FILE_PATH" >&2
# Node.js projects
if [[ "$FILE_PATH" == *package.json ]]; then
echo "🟢 Node.js project detected - checking dependencies..." >&2
if command -v npm &> /dev/null; then
echo "🔍 Running npm outdated check..." >&2
OUTDATED_OUTPUT=$(npm outdated --depth=0 2>/dev/null || echo "No outdated packages")
if [ "$OUTDATED_OUTPUT" = "No outdated packages" ]; then
echo "✅ All npm packages are up to date" >&2
else
echo "📊 Found outdated npm packages:" >&2
echo "$OUTDATED_OUTPUT" | head -10 >&2
OUTDATED_COUNT=$(echo "$OUTDATED_OUTPUT" | wc -l)
echo "📈 Total outdated packages: $OUTDATED_COUNT" >&2
fi
# Check for security vulnerabilities
echo "🔒 Checking for security vulnerabilities..." >&2
AUDIT_OUTPUT=$(npm audit --audit-level=moderate 2>&1)
if echo "$AUDIT_OUTPUT" | grep -q "found 0 vulnerabilities"; then
echo "✅ No security vulnerabilities found" >&2
else
VULN_COUNT=$(echo "$AUDIT_OUTPUT" | grep -o '[0-9]\+ vulnerabilities' | head -1 || echo "unknown vulnerabilities")
echo "⚠️ Security audit found: $VULN_COUNT" >&2
echo "💡 Run 'npm audit fix' to automatically fix vulnerabilities" >&2
fi
# Check for npm-check-updates availability
if command -v npx &> /dev/null && npx ncu --version &> /dev/null 2>&1; then
echo "🔧 Running npm-check-updates for detailed analysis..." >&2
NCU_OUTPUT=$(npx ncu 2>/dev/null | head -5)
echo "$NCU_OUTPUT" >&2
else
echo "💡 Install npm-check-updates for better dependency analysis: npm install -g npm-check-updates" >&2
fi
else
echo "⚠️ npm command not available" >&2
fi
# Python projects
elif [[ "$FILE_PATH" == *requirements.txt ]] || [[ "$FILE_PATH" == *pyproject.toml ]]; then
echo "🐍 Python project detected - checking dependencies..." >&2
if command -v pip &> /dev/null; then
echo "🔍 Checking for outdated Python packages..." >&2
PIP_OUTDATED=$(pip list --outdated 2>/dev/null || echo "Unable to check outdated packages")
if [ "$PIP_OUTDATED" = "Unable to check outdated packages" ]; then
echo "⚠️ Unable to check pip packages" >&2
else
OUTDATED_COUNT=$(echo "$PIP_OUTDATED" | wc -l)
if [ "$OUTDATED_COUNT" -gt 1 ]; then
echo "📊 Found $OUTDATED_COUNT outdated Python packages" >&2
echo "$PIP_OUTDATED" | head -5 >&2
else
echo "✅ All Python packages are up to date" >&2
fi
fi
# Check for security issues with safety
if command -v safety &> /dev/null; then
echo "🔒 Running Safety security check..." >&2
SAFETY_OUTPUT=$(safety check --json 2>/dev/null || safety check 2>/dev/null || echo "Safety check completed")
if echo "$SAFETY_OUTPUT" | grep -q "No known security vulnerabilities"; then
echo "✅ No known security vulnerabilities in Python dependencies" >&2
else
echo "⚠️ Safety scan found potential security issues" >&2
fi
else
echo "💡 Install Safety for Python security scanning: pip install safety" >&2
fi
else
echo "⚠️ pip command not available" >&2
fi
# Ruby projects
elif [[ "$FILE_PATH" == *Gemfile ]]; then
echo "💎 Ruby project detected - checking dependencies..." >&2
if command -v bundle &> /dev/null; then
echo "🔍 Checking for outdated Ruby gems..." >&2
BUNDLE_OUTDATED=$(bundle outdated 2>/dev/null | head -10 || echo "Unable to check outdated gems")
echo "$BUNDLE_OUTDATED" >&2
# Check for security issues
if bundle exec bundler-audit --version &> /dev/null; then
echo "🔒 Running bundler-audit security check..." >&2
BUNDLE_AUDIT=$(bundle exec bundler-audit check 2>&1 || echo "Bundle audit completed")
if echo "$BUNDLE_AUDIT" | grep -q "No vulnerabilities found"; then
echo "✅ No vulnerabilities found in Ruby gems" >&2
else
echo "⚠️ Bundle audit found potential issues" >&2
fi
else
echo "💡 Install bundler-audit: gem install bundler-audit" >&2
fi
else
echo "⚠️ bundle command not available" >&2
fi
# Go projects
elif [[ "$FILE_PATH" == *go.mod ]]; then
echo "🐹 Go project detected - checking dependencies..." >&2
if command -v go &> /dev/null; then
echo "🔍 Checking Go module dependencies..." >&2
# List modules
GO_LIST=$(go list -m -u all 2>/dev/null | head -10 || echo "Unable to list Go modules")
echo "$GO_LIST" >&2
# Check for available updates
OUTDATED_MODULES=$(echo "$GO_LIST" | grep -c '\[' 2>/dev/null || echo "0")
if [ "$OUTDATED_MODULES" -gt 0 ]; then
echo "📊 Found $OUTDATED_MODULES Go modules with available updates" >&2
echo "💡 Run 'go get -u ./...' to update dependencies" >&2
else
echo "✅ All Go modules are up to date" >&2
fi
else
echo "⚠️ go command not available" >&2
fi
# Rust projects
elif [[ "$FILE_PATH" == *Cargo.toml ]]; then
echo "🦀 Rust project detected - checking dependencies..." >&2
if command -v cargo &> /dev/null; then
# Check for outdated crates
if cargo outdated --version &> /dev/null; then
echo "🔍 Checking for outdated Rust crates..." >&2
CARGO_OUTDATED=$(cargo outdated 2>/dev/null | head -10 || echo "Unable to check outdated crates")
echo "$CARGO_OUTDATED" >&2
else
echo "💡 Install cargo-outdated: cargo install cargo-outdated" >&2
fi
# Security audit
if cargo audit --version &> /dev/null; then
echo "🔒 Running Rust security audit..." >&2
CARGO_AUDIT=$(cargo audit 2>&1 || echo "Audit completed")
if echo "$CARGO_AUDIT" | grep -q "Success No vulnerable packages found"; then
echo "✅ No vulnerable crates found" >&2
else
echo "⚠️ Cargo audit found potential issues" >&2
fi
else
echo "💡 Install cargo-audit: cargo install cargo-audit" >&2
fi
else
echo "⚠️ cargo command not available" >&2
fi
fi
# General recommendations
echo "" >&2
echo "📋 Dependency Update Best Practices:" >&2
echo " • Review changelogs before major version updates" >&2
echo " • Test thoroughly after dependency updates" >&2
echo " • Update security-critical packages immediately" >&2
echo " • Use lockfiles for reproducible builds" >&2
else
echo "File $FILE_PATH is not a recognized dependency file, skipping analysis" >&2
fi
exit 0Hook triggers on every file write but only dependency files should activate it
Verify matchers array includes only 'write' and 'edit' tools. Add file path validation in script header to exit early when FILE_PATH doesn't match dependency file patterns.
npm outdated command returns empty output despite outdated packages existing
Run 'npm update --dry-run' instead of 'npm outdated' to see available updates. Check npm cache with 'npm cache verify' and clear if corrupted using 'npm cache clean --force'.
Hook execution floods stderr with security warnings during rapid file edits
Add debouncing by storing last check timestamp in temp file. Skip audit if less than 5 minutes elapsed since previous check to reduce noise during active development sessions.
jq command not found error prevents hook from parsing tool input JSON
Install jq JSON processor using package manager: 'brew install jq' on macOS, 'apt-get install jq' on Ubuntu. Verify installation with 'jq --version' before testing hook again.
Python safety check fails in virtual environments with permission errors
Activate correct virtual environment before running hook or detect venv using VIRTUAL_ENV variable. Install safety in project venv rather than globally: 'pip install safety' within activated environment.
Loading reviews...
Join our community of Claude power users. No spam, unsubscribe anytime.
Automated accessibility testing and compliance checking for web applications following WCAG guidelines
Automatically generates or updates API documentation when endpoint files are modified
Automatically formats code files after Claude writes or edits them using Prettier, Black, or other formatters