Skip to content

Commit 2c9b3cc

Browse files
authored
Merge pull request #240 from alex-feel/alex-feel-dev
Add prompt hooks support to environment configuration
2 parents 71e43b7 + 48769e4 commit 2c9b3cc

File tree

1 file changed

+82
-56
lines changed

1 file changed

+82
-56
lines changed

scripts/setup_environment.py

Lines changed: 82 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -3848,8 +3848,16 @@ def create_additional_settings(
38483848
command = hook.get('command')
38493849
config = hook.get('config') # Optional config file reference
38503850

3851-
if not event or not command:
3852-
warning('Invalid hook configuration, skipping')
3851+
if not event:
3852+
warning('Invalid hook configuration: missing event, skipping')
3853+
continue
3854+
3855+
# For command hooks, command is required; for prompt hooks, prompt is required
3856+
if hook_type == 'command' and not command:
3857+
warning('Invalid command hook: missing command, skipping')
3858+
continue
3859+
if hook_type == 'prompt' and not hook.get('prompt'):
3860+
warning('Invalid prompt hook: missing prompt, skipping')
38533861
continue
38543862

38553863
# Add to settings
@@ -3876,63 +3884,81 @@ def create_additional_settings(
38763884
hooks_event_list: list[dict[str, Any]] = cast(list[dict[str, Any]], hooks_event_list_raw)
38773885
hooks_event_list.append(matcher_group)
38783886

3879-
# Build the proper command based on file type
3880-
# Strip query parameters from command if present
3881-
clean_command = command.split('?')[0] if '?' in command else command
3882-
3883-
# Check if this looks like a file reference or a direct command
3884-
# File references typically don't contain spaces (just the filename)
3885-
# Direct commands like 'echo "test"' contain spaces
3886-
is_file_reference = ' ' not in clean_command
3887-
3888-
if is_file_reference:
3889-
# Determine if this is a Python script (case-insensitive check)
3890-
# Supports both .py and .pyw extensions
3891-
is_python_script = clean_command.lower().endswith(('.py', '.pyw'))
3892-
3893-
if is_python_script:
3894-
# Python script - use uv run for cross-platform execution
3895-
# Build absolute path to the hook file in .claude/hooks/
3896-
hook_path = claude_user_dir / 'hooks' / Path(clean_command).name
3897-
# Use POSIX-style path (forward slashes) for cross-platform compatibility
3898-
# This works on Windows, macOS, and Linux, and avoids JSON escaping issues
3899-
hook_path_str = hook_path.as_posix()
3900-
# Use uv run with Python 3.12 - works cross-platform without PATH dependency
3901-
# uv automatically downloads Python 3.12 if not installed
3902-
# For .pyw files on Windows, uv automatically uses pythonw
3903-
# Use --no-project flag to prevent uv from detecting and applying project Python requirements
3904-
full_command = f'uv run --no-project --python 3.12 {hook_path_str}'
3905-
3906-
# Append config file path if specified
3907-
if config:
3908-
# Strip query parameters from config filename
3909-
clean_config = config.split('?')[0] if '?' in config else config
3910-
config_path = claude_user_dir / 'hooks' / Path(clean_config).name
3911-
config_path_str = config_path.as_posix()
3912-
full_command = f'{full_command} {config_path_str}'
3887+
# Build hook configuration based on hook type
3888+
hook_config: dict[str, Any]
3889+
3890+
if hook_type == 'command':
3891+
# Command hooks require file path processing
3892+
# command is guaranteed to be non-None here due to validation above
3893+
assert command is not None
3894+
3895+
# Build the proper command based on file type
3896+
# Strip query parameters from command if present
3897+
clean_command = command.split('?')[0] if '?' in command else command
3898+
3899+
# Check if this looks like a file reference or a direct command
3900+
# File references typically don't contain spaces (just the filename)
3901+
# Direct commands like 'echo "test"' contain spaces
3902+
is_file_reference = ' ' not in clean_command
3903+
3904+
if is_file_reference:
3905+
# Determine if this is a Python script (case-insensitive check)
3906+
# Supports both .py and .pyw extensions
3907+
is_python_script = clean_command.lower().endswith(('.py', '.pyw'))
3908+
3909+
if is_python_script:
3910+
# Python script - use uv run for cross-platform execution
3911+
# Build absolute path to the hook file in .claude/hooks/
3912+
hook_path = claude_user_dir / 'hooks' / Path(clean_command).name
3913+
# Use POSIX-style path (forward slashes) for cross-platform compatibility
3914+
# This works on Windows, macOS, and Linux, and avoids JSON escaping issues
3915+
hook_path_str = hook_path.as_posix()
3916+
# Use uv run with Python 3.12 - works cross-platform without PATH dependency
3917+
# uv automatically downloads Python 3.12 if not installed
3918+
# For .pyw files on Windows, uv automatically uses pythonw
3919+
# Use --no-project flag to prevent uv from detecting and applying project Python requirements
3920+
full_command = f'uv run --no-project --python 3.12 {hook_path_str}'
3921+
3922+
# Append config file path if specified
3923+
if config:
3924+
# Strip query parameters from config filename
3925+
clean_config = config.split('?')[0] if '?' in config else config
3926+
config_path = claude_user_dir / 'hooks' / Path(clean_config).name
3927+
config_path_str = config_path.as_posix()
3928+
full_command = f'{full_command} {config_path_str}'
3929+
else:
3930+
# Other file - build absolute path and use as-is
3931+
# System will handle execution based on file extension (.sh, .bat, .cmd, .ps1, etc.)
3932+
hook_path = claude_user_dir / 'hooks' / Path(clean_command).name
3933+
hook_path_str = hook_path.as_posix()
3934+
full_command = hook_path_str
3935+
3936+
# Append config file path if specified
3937+
if config:
3938+
# Strip query parameters from config filename
3939+
clean_config = config.split('?')[0] if '?' in config else config
3940+
config_path = claude_user_dir / 'hooks' / Path(clean_config).name
3941+
config_path_str = config_path.as_posix()
3942+
full_command = f'{full_command} {config_path_str}'
39133943
else:
3914-
# Other file - build absolute path and use as-is
3915-
# System will handle execution based on file extension (.sh, .bat, .cmd, .ps1, etc.)
3916-
hook_path = claude_user_dir / 'hooks' / Path(clean_command).name
3917-
hook_path_str = hook_path.as_posix()
3918-
full_command = hook_path_str
3944+
# Direct command with spaces - use as-is
3945+
full_command = command
39193946

3920-
# Append config file path if specified
3921-
if config:
3922-
# Strip query parameters from config filename
3923-
clean_config = config.split('?')[0] if '?' in config else config
3924-
config_path = claude_user_dir / 'hooks' / Path(clean_config).name
3925-
config_path_str = config_path.as_posix()
3926-
full_command = f'{full_command} {config_path_str}'
3947+
# Add hook configuration for command hook
3948+
hook_config = {
3949+
'type': hook_type,
3950+
'command': full_command,
3951+
}
39273952
else:
3928-
# Direct command with spaces - use as-is
3929-
full_command = command
3930-
3931-
# Add hook configuration
3932-
hook_config: dict[str, str] = {
3933-
'type': hook_type,
3934-
'command': full_command,
3935-
}
3953+
# Prompt hook - no file processing needed, use inline prompt
3954+
hook_config = {
3955+
'type': hook_type,
3956+
'prompt': hook.get('prompt', ''),
3957+
}
3958+
# Include timeout if specified
3959+
if hook.get('timeout'):
3960+
hook_config['timeout'] = hook.get('timeout')
3961+
39363962
if matcher_group and 'hooks' in matcher_group:
39373963
matcher_hooks_raw = matcher_group['hooks']
39383964
if isinstance(matcher_hooks_raw, list):

0 commit comments

Comments
 (0)