Skip to content

Instantly share code, notes, and snippets.

@Pradeek
Created October 14, 2025 13:09
Show Gist options
  • Save Pradeek/4ac4295af3c4fce547ee18c603db0b44 to your computer and use it in GitHub Desktop.
Save Pradeek/4ac4295af3c4fce547ee18c603db0b44 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
"""
PreToolUse hook that denies bare 'python' commands in uv projects.
Enforces using 'uv run python' for proper virtual environment isolation.
Only applies when project has uv indicators (pyproject.toml with uv.lock or .venv managed by uv).
Put this under ~/.claude/hooks/
"""
import json
import sys
import os
import re
from datetime import datetime
from pathlib import Path
# Read input
input_data = json.load(sys.stdin)
# Extract tool information
tool_name = input_data.get('tool_name', '')
tool_input = input_data.get('tool_input', {})
# Check if it's a Bash tool
if tool_name == 'Bash':
command = tool_input.get('command', '').strip()
cwd = input_data.get('cwd', '')
# Check if command starts with 'python' (but not 'python3' or specific paths)
python_pattern = r'^python(?:\s|$)'
uses_bare_python = bool(re.match(python_pattern, command))
if uses_bare_python:
# Check if this is a uv project by looking for indicators
def is_uv_project(directory):
path = Path(directory)
# Walk up the directory tree looking for project root
for current_path in [path] + list(path.parents):
# Check for pyproject.toml + uv.lock
pyproject_path = current_path / "pyproject.toml"
uv_lock_path = current_path / "uv.lock"
if pyproject_path.exists() and uv_lock_path.exists():
return True
# Check for .venv with pyvenv.cfg mentioning uv
venv_path = current_path / ".venv" / "pyvenv.cfg"
if venv_path.exists():
try:
with open(venv_path) as f:
content = f.read()
if 'uv' in content.lower():
return True
except:
pass
# Stop at git root or filesystem root
if (current_path / ".git").exists() or current_path == current_path.parent:
break
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment