Loading...
Automatically runs cargo check and clippy when Rust files are modified
{
"hookConfig": {
"hooks": {
"postToolUse": {
"script": "./.claude/hooks/rust-cargo-check.sh",
"matchers": [
"write",
"edit"
]
}
}
},
"scriptContent": "#!/bin/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 this is a Rust file or Cargo configuration\nif [[ \"$FILE_PATH\" == *.rs ]] || [[ \"$FILE_PATH\" == *Cargo.toml ]] || [[ \"$FILE_PATH\" == *Cargo.lock ]]; then\n echo \"đĻ Rust Cargo Check - Analyzing Rust code...\"\n echo \"đ File: $FILE_PATH\"\n \n # Check if cargo is available\n if ! command -v cargo >/dev/null 2>&1; then\n echo \"â ī¸ Cargo not found - please install Rust toolchain\"\n echo \"đĄ Install from: https://rustup.rs/\"\n exit 1\n fi\n \n # Check if we're in a Rust project\n if [ ! -f \"Cargo.toml\" ]; then\n echo \"â ī¸ No Cargo.toml found - not a Rust project\"\n exit 0\n fi\n \n echo \"đ Running Rust toolchain checks...\"\n \n # Step 1: Run cargo check for fast compilation validation\n echo \"⥠Running cargo check (fast compilation check)...\"\n if cargo check --message-format=short; then\n echo \"â
Cargo check passed - code compiles successfully\"\n else\n echo \"â Cargo check failed - compilation errors found\"\n echo \"đĄ Fix compilation errors before proceeding\"\n exit 1\n fi\n \n # Step 2: Run clippy for linting (if available)\n echo \"\"\n echo \"đ Running clippy (Rust linter)...\"\n if command -v cargo-clippy >/dev/null 2>&1 || cargo clippy --version >/dev/null 2>&1; then\n if cargo clippy --message-format=short -- -W clippy::pedantic -W clippy::nursery; then\n echo \"â
Clippy analysis passed - no linting issues\"\n else\n echo \"â ī¸ Clippy found linting issues (non-blocking)\"\n fi\n else\n echo \"âšī¸ Clippy not available - install with: rustup component add clippy\"\n fi\n \n # Step 3: Check formatting (if rustfmt is available)\n echo \"\"\n echo \"đ¨ Checking code formatting...\"\n if command -v rustfmt >/dev/null 2>&1; then\n if cargo fmt -- --check; then\n echo \"â
Code formatting is correct\"\n else\n echo \"â ī¸ Code formatting issues found\"\n echo \"đĄ Run 'cargo fmt' to fix formatting\"\n fi\n else\n echo \"âšī¸ rustfmt not available - install with: rustup component add rustfmt\"\n fi\n \n # Step 4: Security audit (if cargo-audit is available)\n echo \"\"\n echo \"đ Running security audit...\"\n if command -v cargo-audit >/dev/null 2>&1; then\n if cargo audit; then\n echo \"â
No known security vulnerabilities found\"\n else\n echo \"â ī¸ Security vulnerabilities detected - review dependencies\"\n fi\n else\n echo \"âšī¸ cargo-audit not available - install with: cargo install cargo-audit\"\n fi\n \n # Step 5: Project analysis\n echo \"\"\n echo \"đ Project Analysis:\"\n \n # Count Rust files\n RUST_FILES=$(find . -name \"*.rs\" -not -path \"./target/*\" | wc -l)\n echo \" âĸ Rust files: $RUST_FILES\"\n \n # Check for tests\n TEST_FILES=$(find . -name \"*.rs\" -not -path \"./target/*\" -exec grep -l \"#\\[test\\]\\|#\\[cfg(test)\\]\" {} \\; | wc -l)\n echo \" âĸ Files with tests: $TEST_FILES\"\n \n # Check dependencies\n DEPENDENCIES=$(grep -c '^[a-zA-Z].*=' Cargo.toml 2>/dev/null || echo 0)\n echo \" âĸ Dependencies: $DEPENDENCIES\"\n \n # Check for unsafe blocks\n if find . -name \"*.rs\" -not -path \"./target/*\" -exec grep -l \"unsafe\" {} \\; | head -1 >/dev/null 2>&1; then\n UNSAFE_COUNT=$(find . -name \"*.rs\" -not -path \"./target/*\" -exec grep -c \"unsafe\" {} \\; | awk '{sum+=$1} END {print sum}')\n echo \" âĸ â ī¸ Unsafe blocks found: $UNSAFE_COUNT\"\n fi\n \n echo \"\"\n echo \"đĄ Rust Development Tips:\"\n echo \" âĸ Use 'cargo test' to run all tests\"\n echo \" âĸ Use 'cargo build --release' for optimized builds\"\n echo \" âĸ Use 'cargo doc --open' to generate and view documentation\"\n echo \" âĸ Use 'cargo bench' for benchmarking (if available)\"\n echo \" âĸ Consider using 'cargo watch' for continuous testing\"\n \n echo \"\"\n echo \"đ¯ Rust code analysis complete!\"\n \nelse\n echo \"âšī¸ File is not a Rust file: $FILE_PATH\"\nfi\n\nexit 0"
}.claude/hooks/~/.claude/hooks/{
"hooks": {
"postToolUse": {
"script": "./.claude/hooks/rust-cargo-check.sh",
"matchers": [
"write",
"edit"
]
}
}
}#!/bin/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 this is a Rust file or Cargo configuration
if [[ "$FILE_PATH" == *.rs ]] || [[ "$FILE_PATH" == *Cargo.toml ]] || [[ "$FILE_PATH" == *Cargo.lock ]]; then
echo "đĻ Rust Cargo Check - Analyzing Rust code..."
echo "đ File: $FILE_PATH"
# Check if cargo is available
if ! command -v cargo >/dev/null 2>&1; then
echo "â ī¸ Cargo not found - please install Rust toolchain"
echo "đĄ Install from: https://rustup.rs/"
exit 1
fi
# Check if we're in a Rust project
if [ ! -f "Cargo.toml" ]; then
echo "â ī¸ No Cargo.toml found - not a Rust project"
exit 0
fi
echo "đ Running Rust toolchain checks..."
# Step 1: Run cargo check for fast compilation validation
echo "⥠Running cargo check (fast compilation check)..."
if cargo check --message-format=short; then
echo "â
Cargo check passed - code compiles successfully"
else
echo "â Cargo check failed - compilation errors found"
echo "đĄ Fix compilation errors before proceeding"
exit 1
fi
# Step 2: Run clippy for linting (if available)
echo ""
echo "đ Running clippy (Rust linter)..."
if command -v cargo-clippy >/dev/null 2>&1 || cargo clippy --version >/dev/null 2>&1; then
if cargo clippy --message-format=short -- -W clippy::pedantic -W clippy::nursery; then
echo "â
Clippy analysis passed - no linting issues"
else
echo "â ī¸ Clippy found linting issues (non-blocking)"
fi
else
echo "âšī¸ Clippy not available - install with: rustup component add clippy"
fi
# Step 3: Check formatting (if rustfmt is available)
echo ""
echo "đ¨ Checking code formatting..."
if command -v rustfmt >/dev/null 2>&1; then
if cargo fmt -- --check; then
echo "â
Code formatting is correct"
else
echo "â ī¸ Code formatting issues found"
echo "đĄ Run 'cargo fmt' to fix formatting"
fi
else
echo "âšī¸ rustfmt not available - install with: rustup component add rustfmt"
fi
# Step 4: Security audit (if cargo-audit is available)
echo ""
echo "đ Running security audit..."
if command -v cargo-audit >/dev/null 2>&1; then
if cargo audit; then
echo "â
No known security vulnerabilities found"
else
echo "â ī¸ Security vulnerabilities detected - review dependencies"
fi
else
echo "âšī¸ cargo-audit not available - install with: cargo install cargo-audit"
fi
# Step 5: Project analysis
echo ""
echo "đ Project Analysis:"
# Count Rust files
RUST_FILES=$(find . -name "*.rs" -not -path "./target/*" | wc -l)
echo " âĸ Rust files: $RUST_FILES"
# Check for tests
TEST_FILES=$(find . -name "*.rs" -not -path "./target/*" -exec grep -l "#\[test\]\|#\[cfg(test)\]" {} \; | wc -l)
echo " âĸ Files with tests: $TEST_FILES"
# Check dependencies
DEPENDENCIES=$(grep -c '^[a-zA-Z].*=' Cargo.toml 2>/dev/null || echo 0)
echo " âĸ Dependencies: $DEPENDENCIES"
# Check for unsafe blocks
if find . -name "*.rs" -not -path "./target/*" -exec grep -l "unsafe" {} \; | head -1 >/dev/null 2>&1; then
UNSAFE_COUNT=$(find . -name "*.rs" -not -path "./target/*" -exec grep -c "unsafe" {} \; | awk '{sum+=$1} END {print sum}')
echo " âĸ â ī¸ Unsafe blocks found: $UNSAFE_COUNT"
fi
echo ""
echo "đĄ Rust Development Tips:"
echo " âĸ Use 'cargo test' to run all tests"
echo " âĸ Use 'cargo build --release' for optimized builds"
echo " âĸ Use 'cargo doc --open' to generate and view documentation"
echo " âĸ Use 'cargo bench' for benchmarking (if available)"
echo " âĸ Consider using 'cargo watch' for continuous testing"
echo ""
echo "đ¯ Rust code analysis complete!"
else
echo "âšī¸ File is not a Rust file: $FILE_PATH"
fi
exit 0Cargo check fails with 'No Cargo.toml found' in monorepos
Hook searches from file directory upward but may fail in nested workspaces. Add cd logic to find workspace root: while [ ! -f Cargo.toml ] && [ $(pwd) != / ]; do cd ..; done before running cargo commands.
Target directory compilation artifacts cause slow check times
Cargo check reuses incremental compilation from target/. Ensure .gitignore excludes target/ but preserve it locally. Use cargo clean selectively or CARGO_TARGET_DIR to separate hook builds from development builds.
Cargo audit fails when offline or network restricted environments
Script treats cargo-audit as optional but doesn't handle network errors. Add CARGO_NET_OFFLINE=true check or wrap in: timeout 5s cargo audit || echo 'Audit skipped (offline)' to prevent hanging on network unavailable.
Multiple Rust files changed simultaneously trigger concurrent checks
PostToolUse fires per operation causing parallel cargo check processes. Add flock-based locking: { flock -n 200 || exit 0; cargo check; } 200>/tmp/cargo-check.lock to serialize executions and prevent resource contention.
Hook executes before file write completes showing stale errors
PostToolUse hooks fire after tool completion but file system may buffer writes. Add small delay: sleep 0.1 before cargo check, or verify file timestamp: [ "$FILE_PATH" -nt /tmp/last-check ] to ensure fresh content is analyzed.
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