Skip to content

Commit 79f1f63

Browse files
authored
Merge pull request #45 from alex-feel/alex-feel-dev
Fix hooks
2 parents 0e436fb + 8d1a746 commit 79f1f63

File tree

1 file changed

+54
-40
lines changed

1 file changed

+54
-40
lines changed

scripts/setup-environment.py

Lines changed: 54 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -464,28 +464,33 @@ def configure_all_mcp_servers(servers: list[dict[str, Any]]) -> bool:
464464
return True
465465

466466

467-
def update_hooks_settings(hooks: list[dict[str, Any]], claude_user_dir: Path) -> bool:
468-
"""Update hooks in settings.json."""
469-
if not hooks:
470-
return True
467+
def create_additional_settings(hooks: list[dict[str, Any]], claude_user_dir: Path) -> bool:
468+
"""Create additional-settings.json with environment-specific hooks.
471469
472-
info('Configuring hooks...')
470+
This file is always overwritten to avoid duplicate hooks when re-running the installer.
471+
It's loaded via --settings flag when launching Claude.
473472
474-
settings_path = claude_user_dir / 'settings.json'
475-
476-
# Load existing settings or create new
477-
if settings_path.exists():
473+
Returns:
474+
bool: True if successful, False otherwise.
475+
"""
476+
if not hooks:
477+
# Still create an empty additional-settings.json for consistency
478+
additional_settings_path = claude_user_dir / 'additional-settings.json'
478479
try:
479-
with open(settings_path) as f:
480-
settings = json.load(f)
481-
except (OSError, json.JSONDecodeError):
482-
settings = {}
483-
else:
484-
settings = {}
480+
with open(additional_settings_path, 'w') as f:
481+
json.dump({}, f, indent=2)
482+
info('Created empty additional-settings.json (no hooks configured)')
483+
return True
484+
except Exception as e:
485+
error(f'Failed to create additional-settings.json: {e}')
486+
return False
485487

486-
# Ensure hooks key exists
487-
if 'hooks' not in settings:
488-
settings['hooks'] = {}
488+
info('Configuring hooks in additional-settings.json...')
489+
490+
# Create fresh settings structure for this environment
491+
settings = {
492+
'hooks': {},
493+
}
489494

490495
# Process each hook
491496
for hook in hooks:
@@ -542,7 +547,9 @@ def update_hooks_settings(hooks: list[dict[str, Any]], claude_user_dir: Path) ->
542547
# Windows needs explicit Python interpreter
543548
# Use 'py' which is more reliable on Windows, fallback to 'python'
544549
python_cmd = 'py' if shutil.which('py') else 'python'
545-
full_command = f'{python_cmd} "{str(hook_path)}"'
550+
# Use forward slashes for the path (works on Windows and avoids JSON escaping issues)
551+
hook_path_str = hook_path.as_posix()
552+
full_command = f'{python_cmd} {hook_path_str}'
546553
else:
547554
# Unix-like systems can use shebang directly
548555
# Make script executable
@@ -553,23 +560,22 @@ def update_hooks_settings(hooks: list[dict[str, Any]], claude_user_dir: Path) ->
553560
# Not a Python script, use command as-is
554561
full_command = command
555562

556-
# Add hook if not already present
563+
# Add hook configuration
557564
hook_config = {
558565
'type': hook_type,
559566
'command': full_command,
560567
}
568+
matcher_group['hooks'].append(hook_config)
561569

562-
if hook_config not in matcher_group['hooks']:
563-
matcher_group['hooks'].append(hook_config)
564-
565-
# Save settings
570+
# Save additional settings (always overwrite)
571+
additional_settings_path = claude_user_dir / 'additional-settings.json'
566572
try:
567-
with open(settings_path, 'w') as f:
573+
with open(additional_settings_path, 'w') as f:
568574
json.dump(settings, f, indent=2)
569-
success('Hooks configured successfully')
575+
success('Created additional-settings.json with environment hooks')
570576
return True
571577
except Exception as e:
572-
error(f'Failed to save settings.json: {e}')
578+
error(f'Failed to save additional-settings.json: {e}')
573579
return False
574580

575581

@@ -624,13 +630,16 @@ def create_launcher_script(claude_user_dir: Path, command_name: str, system_prom
624630
$argsString = $escapedArgs -join ' '
625631
# Use a here-string to avoid complex quote escaping
626632
$bashCommand = @"
627-
p=`$(tr -d '\\\\r' < ~/.claude/prompts/{system_prompt_file}); exec claude --append-system-prompt=\\"`$p\\" $argsString
633+
p=`$(tr -d '\\\\r' < ~/.claude/prompts/{system_prompt_file}); s=~/.claude/additional-settings.json; \\
634+
exec claude --append-system-prompt=\\"`$p\\" --settings=\\"`$s\\" $argsString
628635
"@
629636
& $bashPath -lc $bashCommand
630637
}} else {{
631638
# Use --% to stop PowerShell parsing, with literal command string
632-
& $bashPath `
633-
--% -lc "p=$(tr -d '\\r' < ~/.claude/prompts/{system_prompt_file}); exec claude --append-system-prompt=\\"$p\\""
639+
$bashCommand = "p=`$(tr -d '\\r' < ~/.claude/prompts/{system_prompt_file}); " + `
640+
"s=~/.claude/additional-settings.json; " + `
641+
"exec claude --append-system-prompt=\\`"`$p\\`" --settings=\\`"`$s\\`""
642+
& $bashPath --% -lc $bashCommand
634643
}}
635644
'''
636645
launcher_path.write_text(launcher_content)
@@ -654,11 +663,12 @@ def create_launcher_script(claude_user_dir: Path, command_name: str, system_prom
654663
REM Build the command with all arguments
655664
set BASH_EXE="C:\\Program Files\\Git\\bin\\bash.exe"
656665
set CMD_PREFIX=p=$(tr -d '\\r' ^< ~/.claude/prompts/{system_prompt_file})
666+
set SETTINGS_PATH=~/.claude/additional-settings.json
657667
if "%~1"=="" (
658-
%BASH_EXE% -lc "%CMD_PREFIX%; exec claude --append-system-prompt=\\"$p\\""
668+
%BASH_EXE% -lc "%CMD_PREFIX%; exec claude --append-system-prompt=\\"$p\\" --settings=\\"%SETTINGS_PATH%\\""
659669
) else (
660670
echo Passing additional arguments: %*
661-
%BASH_EXE% -lc "%CMD_PREFIX%; exec claude --append-system-prompt=\\"$p\\" %*"
671+
%BASH_EXE% -lc "%CMD_PREFIX%; exec claude --append-system-prompt=\\"$p\\" --settings=\\"%SETTINGS_PATH%\\" %*"
662672
)
663673
'''
664674
batch_path.write_text(batch_content)
@@ -683,13 +693,14 @@ def create_launcher_script(claude_user_dir: Path, command_name: str, system_prom
683693
684694
# Read the prompt content
685695
PROMPT_CONTENT=$(cat "$PROMPT_PATH")
696+
SETTINGS_PATH="$CLAUDE_USER_DIR/additional-settings.json"
686697
687698
# Pass any additional arguments to Claude
688699
if [ $# -gt 0 ]; then
689700
echo -e "\\033[0;36mPassing additional arguments: $@\\033[0m"
690-
claude --append-system-prompt "$PROMPT_CONTENT" "$@"
701+
claude --append-system-prompt "$PROMPT_CONTENT" --settings "$SETTINGS_PATH" "$@"
691702
else
692-
claude --append-system-prompt "$PROMPT_CONTENT"
703+
claude --append-system-prompt "$PROMPT_CONTENT" --settings "$SETTINGS_PATH"
693704
fi
694705
'''
695706
launcher_path.write_text(launcher_content)
@@ -722,10 +733,11 @@ def register_global_command(launcher_path: Path, command_name: str, system_promp
722733
REM Global {command_name} command for CMD
723734
set BASH_EXE="C:\\Program Files\\Git\\bin\\bash.exe"
724735
set CMD_PREFIX=p=$(tr -d '\\r' ^< ~/.claude/prompts/{system_prompt_file})
736+
set SETTINGS_PATH=~/.claude/additional-settings.json
725737
if "%~1"=="" (
726-
%BASH_EXE% -lc "%CMD_PREFIX%; exec claude --append-system-prompt=\\"$p\\""
738+
%BASH_EXE% -lc "%CMD_PREFIX%; exec claude --append-system-prompt=\\"$p\\" --settings=\\"%SETTINGS_PATH%\\""
727739
) else (
728-
%BASH_EXE% -lc "%CMD_PREFIX%; exec claude --append-system-prompt=\\"$p\\" %*"
740+
%BASH_EXE% -lc "%CMD_PREFIX%; exec claude --append-system-prompt=\\"$p\\" --settings=\\"%SETTINGS_PATH%\\" %*"
729741
)
730742
'''
731743
batch_path.write_text(batch_content)
@@ -755,13 +767,14 @@ def register_global_command(launcher_path: Path, command_name: str, system_promp
755767
756768
# Read the prompt content and pass it directly to claude
757769
PROMPT_CONTENT=$(cat "$PROMPT_PATH")
770+
SETTINGS_PATH="$HOME/.claude/additional-settings.json"
758771
759772
# Pass all arguments to claude with the system prompt
760773
if [ $# -gt 0 ]; then
761774
echo "Passing additional arguments: $@"
762-
claude --append-system-prompt "$PROMPT_CONTENT" "$@"
775+
claude --append-system-prompt "$PROMPT_CONTENT" --settings "$SETTINGS_PATH" "$@"
763776
else
764-
claude --append-system-prompt "$PROMPT_CONTENT"
777+
claude --append-system-prompt "$PROMPT_CONTENT" --settings "$SETTINGS_PATH"
765778
fi
766779
'''
767780
bash_wrapper_path.write_text(bash_content, newline='\n') # Use Unix line endings
@@ -920,7 +933,7 @@ def main() -> None:
920933
print(f'{Colors.CYAN}Step 9: Configuring hooks...{Colors.NC}')
921934
hooks = config.get('hooks', [])
922935
if hooks:
923-
update_hooks_settings(hooks, claude_user_dir)
936+
create_additional_settings(hooks, claude_user_dir)
924937
else:
925938
info('No hooks configured')
926939

@@ -965,7 +978,8 @@ def main() -> None:
965978
else:
966979
print(f' * Full path: {launcher_path}')
967980
if prompt_path:
968-
print(f" * Manual: claude --append-system-prompt '@{prompt_path}'")
981+
settings_path = claude_user_dir / 'additional-settings.json'
982+
print(f" * Manual: claude --append-system-prompt '@{prompt_path}' --settings '{settings_path}'")
969983

970984
print()
971985
print(f'{Colors.YELLOW}Available Commands (after starting Claude):{Colors.NC}')

0 commit comments

Comments
 (0)