81 lines
2.4 KiB
Python
Executable File
81 lines
2.4 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Type-checking hook for Claude Code
|
|
Runs mypy/ruff on modified Python files
|
|
"""
|
|
|
|
import sys
|
|
import json
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
def main():
|
|
try:
|
|
# Read input from Claude Code
|
|
input_data = json.loads(sys.stdin.read())
|
|
|
|
# Check if this is a file modification
|
|
tool = input_data.get('tool', '')
|
|
if tool not in ['edit', 'multi_edit', 'write']:
|
|
return 0
|
|
|
|
# Get the file path
|
|
result = input_data.get('result', {})
|
|
file_path = result.get('file_path', '')
|
|
|
|
if not file_path:
|
|
return 0
|
|
|
|
# Check if it's a Python file
|
|
if not file_path.endswith('.py'):
|
|
return 0
|
|
|
|
# Convert to Path object
|
|
file_path = Path(file_path)
|
|
if not file_path.exists():
|
|
return 0
|
|
|
|
# Run type checking with mypy
|
|
mypy_result = subprocess.run(
|
|
['uv', 'run', 'mypy', str(file_path)],
|
|
capture_output=True,
|
|
text=True,
|
|
cwd='/Users/enias/projects/my-ai-projects/apps/trax'
|
|
)
|
|
|
|
# Run linting with ruff
|
|
ruff_result = subprocess.run(
|
|
['uv', 'run', 'ruff', 'check', str(file_path)],
|
|
capture_output=True,
|
|
text=True,
|
|
cwd='/Users/enias/projects/my-ai-projects/apps/trax'
|
|
)
|
|
|
|
# Collect errors
|
|
errors = []
|
|
|
|
if mypy_result.returncode != 0:
|
|
errors.append(f"Type errors in {file_path}:\n{mypy_result.stdout}")
|
|
|
|
if ruff_result.returncode != 0:
|
|
errors.append(f"Linting errors in {file_path}:\n{ruff_result.stdout}")
|
|
|
|
# Report errors if any
|
|
if errors:
|
|
error_msg = "\n\n".join(errors)
|
|
print(f"❌ Quality Check Failed:\n\n{error_msg}", file=sys.stderr)
|
|
# Exit code 2 = blocking error (Claude Code must fix)
|
|
# Exit code 1 = warning (Claude Code is informed but continues)
|
|
return 2
|
|
|
|
# Success message
|
|
print(f"✅ Quality checks passed for {file_path}")
|
|
return 0
|
|
|
|
except Exception as e:
|
|
# Don't break Claude Code if hook fails
|
|
print(f"Hook error (non-blocking): {e}", file=sys.stderr)
|
|
return 0
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main()) |