fix: align installer hook schema with current Claude Code format - #84
Conversation
The install-with-sondera.sh script generated settings.local.json using an outdated flat-object schema with kebab-case keys and deprecated properties (args, blocking, timeout). This updates it to the current array-based format with CamelCase event keys covering all 14 lifecycle events. - Update installer to generate correct hook schema (array-of-matcher format) - Add schema validation step to test-sondera-integration.sh - Update SONDERA_INTEGRATION.md to reflect full lifecycle coverage Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reviewer's GuideAligns the installer-generated Claude Code hook configuration with the current array-based, CamelCase lifecycle hook schema and adds a test-time schema guard plus matching documentation updates. Sequence diagram for lifecycle event hook execution with new array-based schemasequenceDiagram
actor Developer
participant ClaudeClient
participant HookDispatcher
participant SonderaClaudeHook
Developer->>ClaudeClient: Trigger action that causes UserPromptSubmit
ClaudeClient->>HookDispatcher: Emit UserPromptSubmit event
HookDispatcher->>HookDispatcher: Look up hooks[UserPromptSubmit]
HookDispatcher->>HookDispatcher: Match matcher "*" and select command hook
HookDispatcher->>SonderaClaudeHook: Execute "$HOOK_PATH --verbose user-prompt-submit"
SonderaClaudeHook-->>HookDispatcher: Return exit status and output
HookDispatcher-->>ClaudeClient: Apply policy decision / result
ClaudeClient-->>Developer: Continue workflow with validated action
Class diagram for updated Claude Code hook configuration schemaclassDiagram
class HooksConfig {
Map~LifecycleEvent,LifecycleEventHookList~ hooks
}
class LifecycleEventHookList {
List~LifecycleEventHook~ items
}
class LifecycleEventHook {
string matcher
List~HookEntry~ hooks
}
class HookEntry {
CommandHook commandHook
}
class CommandHook {
string type
string command
}
class LifecycleEvent {
PreToolUse
PermissionRequest
PostToolUse
PostToolUseFailure
UserPromptSubmit
Notification
Stop
SubagentStart
SubagentStop
TeammateIdle
TaskCompleted
PreCompact
SessionStart
SessionEnd
}
class OldFlatHookSchema {
string command
List~string~ args
bool blocking
int timeout
}
HooksConfig "1" --> "*" LifecycleEventHookList : contains
LifecycleEventHookList "1" --> "*" LifecycleEventHook : items
LifecycleEventHook "1" --> "*" HookEntry : hooks
HookEntry "1" --> "1" CommandHook : commandHook
HooksConfig "1" --> "*" LifecycleEvent : keys
OldFlatHookSchema <.. HooksConfig : replaced_by
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
📝 WalkthroughWalkthroughThe changes expand Sondera integration from a single Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- The new hook commands drop the
--socket "$SOCKET_PATH"argument that was present in the previous schema, so the Sondera hook may no longer know which socket to use; consider preserving the socket flag in each command invocation. - All hook entries repeat the same
matcher/hooksstructure with only the event-specific suffix changing; consider generating this JSON via a small loop or template to reduce duplication and the risk of inconsistent edits across events.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The new hook commands drop the `--socket "$SOCKET_PATH"` argument that was present in the previous schema, so the Sondera hook may no longer know which socket to use; consider preserving the socket flag in each command invocation.
- All hook entries repeat the same `matcher`/`hooks` structure with only the event-specific suffix changing; consider generating this JSON via a small loop or template to reduce duplication and the risk of inconsistent edits across events.
## Individual Comments
### Comment 1
<location path="install-with-sondera.sh" line_range="138" />
<code_context>
- "timeout": 5000
- }
+ "PreToolUse": [
+ { "matcher": "*", "hooks": [{ "type": "command", "command": "$HOOK_PATH --verbose pre-tool-use" }] }
+ ],
+ "PermissionRequest": [
</code_context>
<issue_to_address>
**issue (bug_risk):** The new hook commands no longer pass the socket path, which may break integration if the hook expects it.
Previously this hook was called with `--socket "$SOCKET_PATH"`, but the new config runs `$HOOK_PATH --verbose ...` without referencing `SOCKET_PATH`. If the hook still needs the socket flag to talk to Sondera, it will fail at runtime. Please either add the socket argument back (e.g. `"$HOOK_PATH --socket $SOCKET_PATH --verbose pre-tool-use"` or via an `args` array) or confirm that the hook implementation no longer requires it.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| "timeout": 5000 | ||
| } | ||
| "PreToolUse": [ | ||
| { "matcher": "*", "hooks": [{ "type": "command", "command": "$HOOK_PATH --verbose pre-tool-use" }] } |
There was a problem hiding this comment.
issue (bug_risk): The new hook commands no longer pass the socket path, which may break integration if the hook expects it.
Previously this hook was called with --socket "$SOCKET_PATH", but the new config runs $HOOK_PATH --verbose ... without referencing SOCKET_PATH. If the hook still needs the socket flag to talk to Sondera, it will fail at runtime. Please either add the socket argument back (e.g. "$HOOK_PATH --socket $SOCKET_PATH --verbose pre-tool-use" or via an args array) or confirm that the hook implementation no longer requires it.
PAL MCP Consensus Code Review (via AWS Bedrock)OverviewThis PR updates the Sondera integration installer to align with Claude Code's current hook schema format. The changes migrate from the deprecated flat kebab-case hook configuration (
Changed Files: 3 (0 Python files - all shell scripts and markdown) Critical IssuesNone identified. This is a schema migration fix with proper validation. High PriorityNone identified. The implementation is sound for this migration task. Medium Priority1. Hardcoded Socket Path ReferenceFile: Old format: "command": "$HOOK_PATH",
"args": ["--socket", "$SOCKET_PATH"]New format: "command": "$HOOK_PATH --verbose pre-tool-use"Impact: The Sondera hook binary might not know which socket to connect to. Verify that:
Recommendation: Verify with Sondera documentation or add 2. Missing Error Handling in Validation ScriptFile: Recommendation: Add a try-except block to catch JSON decode errors: try:
with open('.claude/settings.local.json') as f:
data = json.load(f)
except json.JSONDecodeError as e:
print(f'ERROR: Invalid JSON - {e}', file=sys.stderr)
sys.exit(1)3. Incomplete Hook CoverageFile:
Current: All hooks are blocking with default timeout (likely 5000ms based on old config) Positive ObservationsSchema Modernization ✓
Comprehensive Testing ✓
Documentation Alignment ✓
Clean Implementation ✓
Review Summary
Key Strengths
Recommended Actions Before Merge
Risk AssessmentLow Risk - This is a necessary schema migration. The validation script prevents broken deployments. Main risk is if socket path handling changed (medium severity but likely caught in testing). Code-Specific AnalysisShell Script Quality (install-with-sondera.sh)✓ Proper variable quoting ( Test Script Quality (test-sondera-integration.sh)✓ Clear test output with color-coded results Documentation Quality (SONDERA_INTEGRATION.md)✓ Accurate reflection of implementation This review was generated by manual comprehensive analysis using Claude Sonnet 4.5. |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
install-with-sondera.sh (1)
137-178: Consider generating the 14 hook entries from a single event list.This block is easy to drift over time (especially with the validator script). A loop/template-based emission would be safer to maintain.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@install-with-sondera.sh` around lines 137 - 178, Replace the repeated hard-coded JSON hook entries with a generator that iterates over a single EVENTS list and emits each event block; for example, define an array named EVENTS containing the 14 event names (e.g., "PreToolUse", "PermissionRequest", ..., "SessionEnd") and loop to print the JSON object using the existing HOOK_PATH variable so each entry uses "$HOOK_PATH --verbose <event-name>"—update the part of the script that currently outputs the literal blocks (the section referencing HOOK_PATH and the event keys) to use this loop/templating approach so the JSON remains consistent and avoids manual drift.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@install-with-sondera.sh`:
- Around line 137-178: The hook command strings currently embed an unescaped
$HOOK_PATH which will break for paths with spaces/special chars; update each
hook entry (e.g., "PreToolUse", "PermissionRequest", "PostToolUse",
"PostToolUseFailure", "UserPromptSubmit", "Notification", "Stop",
"SubagentStart", "SubagentStop", "TeammateIdle", "TaskCompleted", "PreCompact",
"SessionStart", "SessionEnd") to use an escaped/quoted variable (replace
$HOOK_PATH with a safely-escaped variant such as $HOOK_PATH_ESCAPED or wrap the
variable in quotes) so the command strings correctly handle spaces and
shell-significant characters.
In `@test-sondera-integration.sh`:
- Around line 30-53: The script only validates the 'PreToolUse' key; update the
python check in test-sondera-integration.sh to validate all required lifecycle
event keys by defining a list of the 14 expected CamelCase event names (instead
of just 'PreToolUse'), then iterate over that list and for each ensure it exists
in hooks and is a list; replace the single-key checks for 'PreToolUse' and
'user-prompt-submit' with this loop so any missing or non-array event (e.g.,
hooks[event] not isinstance(list)) causes an error and non-zero exit.
---
Nitpick comments:
In `@install-with-sondera.sh`:
- Around line 137-178: Replace the repeated hard-coded JSON hook entries with a
generator that iterates over a single EVENTS list and emits each event block;
for example, define an array named EVENTS containing the 14 event names (e.g.,
"PreToolUse", "PermissionRequest", ..., "SessionEnd") and loop to print the JSON
object using the existing HOOK_PATH variable so each entry uses "$HOOK_PATH
--verbose <event-name>"—update the part of the script that currently outputs the
literal blocks (the section referencing HOOK_PATH and the event keys) to use
this loop/templating approach so the JSON remains consistent and avoids manual
drift.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 22ff35ee-664f-437c-9950-9d76b4090644
📒 Files selected for processing (3)
SONDERA_INTEGRATION.mdinstall-with-sondera.shtest-sondera-integration.sh
| "PreToolUse": [ | ||
| { "matcher": "*", "hooks": [{ "type": "command", "command": "$HOOK_PATH --verbose pre-tool-use" }] } | ||
| ], | ||
| "PermissionRequest": [ | ||
| { "matcher": "*", "hooks": [{ "type": "command", "command": "$HOOK_PATH --verbose permission-request" }] } | ||
| ], | ||
| "PostToolUse": [ | ||
| { "matcher": "*", "hooks": [{ "type": "command", "command": "$HOOK_PATH --verbose post-tool-use" }] } | ||
| ], | ||
| "PostToolUseFailure": [ | ||
| { "matcher": "*", "hooks": [{ "type": "command", "command": "$HOOK_PATH --verbose post-tool-use-failure" }] } | ||
| ], | ||
| "UserPromptSubmit": [ | ||
| { "matcher": "*", "hooks": [{ "type": "command", "command": "$HOOK_PATH --verbose user-prompt-submit" }] } | ||
| ], | ||
| "Notification": [ | ||
| { "matcher": "*", "hooks": [{ "type": "command", "command": "$HOOK_PATH --verbose notification" }] } | ||
| ], | ||
| "Stop": [ | ||
| { "matcher": "*", "hooks": [{ "type": "command", "command": "$HOOK_PATH --verbose stop" }] } | ||
| ], | ||
| "SubagentStart": [ | ||
| { "matcher": "*", "hooks": [{ "type": "command", "command": "$HOOK_PATH --verbose subagent-start" }] } | ||
| ], | ||
| "SubagentStop": [ | ||
| { "matcher": "*", "hooks": [{ "type": "command", "command": "$HOOK_PATH --verbose subagent-stop" }] } | ||
| ], | ||
| "TeammateIdle": [ | ||
| { "matcher": "*", "hooks": [{ "type": "command", "command": "$HOOK_PATH --verbose teammate-idle" }] } | ||
| ], | ||
| "TaskCompleted": [ | ||
| { "matcher": "*", "hooks": [{ "type": "command", "command": "$HOOK_PATH --verbose task-completed" }] } | ||
| ], | ||
| "PreCompact": [ | ||
| { "matcher": "*", "hooks": [{ "type": "command", "command": "$HOOK_PATH --verbose pre-compact" }] } | ||
| ], | ||
| "SessionStart": [ | ||
| { "matcher": "*", "hooks": [{ "type": "command", "command": "$HOOK_PATH --verbose session-start" }] } | ||
| ], | ||
| "SessionEnd": [ | ||
| { "matcher": "*", "hooks": [{ "type": "command", "command": "$HOOK_PATH --verbose session-end" }] } | ||
| ] |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify whether unescaped HOOK_PATH is still used in generated command fields.
rg -n '"command": "\$HOOK_PATH --verbose' install-with-sondera.shRepository: Tony363/SuperClaude
Length of output: 1635
Escape $HOOK_PATH in all generated hook command strings to handle paths with spaces or special characters.
The unescaped $HOOK_PATH variable (lines 138, 141, 144, 147, 150, 153, 156, 159, 162, 165, 168, 171, 174, 177) will fail when the path contains spaces or shell-significant characters. This affects all 14 hook event handlers.
🔧 Proposed fix
HOOK_PATH="$SONDERA_DIR/apps/claude/target/release/sondera-claude-hook"
+HOOK_PATH_ESCAPED=$(printf '%q' "$HOOK_PATH")
cat > .claude/settings.local.json <<EOF
{
"hooks": {
"PreToolUse": [
- { "matcher": "*", "hooks": [{ "type": "command", "command": "$HOOK_PATH --verbose pre-tool-use" }] }
+ { "matcher": "*", "hooks": [{ "type": "command", "command": "$HOOK_PATH_ESCAPED --verbose pre-tool-use" }] }
],Replace $HOOK_PATH with $HOOK_PATH_ESCAPED for each of the 14 event command entries.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@install-with-sondera.sh` around lines 137 - 178, The hook command strings
currently embed an unescaped $HOOK_PATH which will break for paths with
spaces/special chars; update each hook entry (e.g., "PreToolUse",
"PermissionRequest", "PostToolUse", "PostToolUseFailure", "UserPromptSubmit",
"Notification", "Stop", "SubagentStart", "SubagentStop", "TeammateIdle",
"TaskCompleted", "PreCompact", "SessionStart", "SessionEnd") to use an
escaped/quoted variable (replace $HOOK_PATH with a safely-escaped variant such
as $HOOK_PATH_ESCAPED or wrap the variable in quotes) so the command strings
correctly handle spaces and shell-significant characters.
| # 1b. Validate hook schema format (array-based with CamelCase event keys) | ||
| echo -n "Validating hook schema format... " | ||
| if python3 -c " | ||
| import json, sys | ||
| with open('.claude/settings.local.json') as f: | ||
| data = json.load(f) | ||
| hooks = data.get('hooks', {}) | ||
| if 'user-prompt-submit' in hooks: | ||
| print('ERROR: Outdated flat schema detected (kebab-case key)', file=sys.stderr) | ||
| sys.exit(1) | ||
| if 'PreToolUse' not in hooks: | ||
| print('ERROR: Missing PreToolUse key - expected CamelCase event keys', file=sys.stderr) | ||
| sys.exit(1) | ||
| if not isinstance(hooks['PreToolUse'], list): | ||
| print('ERROR: PreToolUse should be an array, not flat object', file=sys.stderr) | ||
| sys.exit(1) | ||
| " 2>&1; then | ||
| echo -e "${GREEN}✓${NC}" | ||
| else | ||
| echo -e "${RED}✗ Invalid hook schema${NC}" | ||
| echo " Expected array-based format with CamelCase event keys (e.g., PreToolUse, PostToolUse)" | ||
| echo " Re-run install-with-sondera.sh to regenerate" | ||
| exit 1 | ||
| fi |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify generated hook schema has full 14-event coverage and array values.
python3 - <<'PY'
import json, sys
p = ".claude/settings.local.json"
with open(p) as f:
data = json.load(f)
hooks = data.get("hooks", {})
expected = {
"PreToolUse","PermissionRequest","PostToolUse","PostToolUseFailure",
"UserPromptSubmit","Notification","Stop","SubagentStart","SubagentStop",
"TeammateIdle","TaskCompleted","PreCompact","SessionStart","SessionEnd"
}
missing = sorted(expected - set(hooks))
wrong_type = sorted(k for k in expected if not isinstance(hooks.get(k), list))
legacy = "user-prompt-submit" in hooks
print("missing:", missing)
print("wrong_type:", wrong_type)
print("legacy_key_present:", legacy)
sys.exit(1 if missing or wrong_type or legacy else 0)
PYRepository: Tony363/SuperClaude
Length of output: 221
🏁 Script executed:
# First, find and examine the test-sondera-integration.sh file
find . -name "test-sondera-integration.sh" -o -name "*sondera*" | head -20Repository: Tony363/SuperClaude
Length of output: 118
🏁 Script executed:
# Look for documentation about lifecycle events/hooks
find . -type f \( -name "*.md" -o -name "*.json" -o -name "*.sh" \) | xargs grep -l "PreToolUse\|PostToolUse\|SessionStart" 2>/dev/null | head -20Repository: Tony363/SuperClaude
Length of output: 301
🏁 Script executed:
# Search for references to "14.*event" or similar hook documentation
rg "lifecycle|event.*hook|hook.*event" -t md -t json -t sh --max-count=30 2>/dev/null | head -50Repository: Tony363/SuperClaude
Length of output: 5923
🏁 Script executed:
# Read the test-sondera-integration.sh file, focusing on lines 30-53
cat -n test-sondera-integration.sh | sed -n '25,60p'Repository: Tony363/SuperClaude
Length of output: 1492
🏁 Script executed:
# Read SONDERA_INTEGRATION.md to find the 14 lifecycle events
cat SONDERA_INTEGRATION.md | head -100Repository: Tony363/SuperClaude
Length of output: 3065
🏁 Script executed:
# Check HOOKS_MODULE.md for the complete list of hook events
cat crates/superclaude-runtime/docs/HOOKS_MODULE.mdRepository: Tony363/SuperClaude
Length of output: 13373
🏁 Script executed:
# Search for references to all the proposed event names
rg "PermissionRequest|PostToolUseFailure|Notification|SubagentStart|TeammateIdle|TaskCompleted|PreCompact|SessionStart|SessionEnd" --max-count=50Repository: Tony363/SuperClaude
Length of output: 1877
🏁 Script executed:
# Check the install-with-sondera.sh script to see what it sets up
cat install-with-sondera.sh | head -200Repository: Tony363/SuperClaude
Length of output: 6603
🏁 Script executed:
# Search for documentation about the complete hook schema
rg "14.*event|event.*14|lifecycle.*event|event.*schema" -t md --max-count=20Repository: Tony363/SuperClaude
Length of output: 223
🏁 Script executed:
# Check what the current test actually validates by examining the full script
cat -n test-sondera-integration.sh | sed -n '1,100p'Repository: Tony363/SuperClaude
Length of output: 3619
🏁 Script executed:
# Search for any other validations of hook events in the codebase
rg "hooks.*get\|hooks\[" --max-count=20Repository: Tony363/SuperClaude
Length of output: 45
Validate all 14 lifecycle events, not just PreToolUse.
The current check passes if only PreToolUse exists with array value, leaving validation of 13 other required events unverified. This allows weak/partial hook coverage to pass undetected.
Proposed fix
if python3 -c "
import json, sys
with open('.claude/settings.local.json') as f:
data = json.load(f)
hooks = data.get('hooks', {})
if 'user-prompt-submit' in hooks:
print('ERROR: Outdated flat schema detected (kebab-case key)', file=sys.stderr)
sys.exit(1)
-if 'PreToolUse' not in hooks:
- print('ERROR: Missing PreToolUse key - expected CamelCase event keys', file=sys.stderr)
- sys.exit(1)
-if not isinstance(hooks['PreToolUse'], list):
- print('ERROR: PreToolUse should be an array, not flat object', file=sys.stderr)
- sys.exit(1)
+expected = {
+ 'PreToolUse', 'PermissionRequest', 'PostToolUse', 'PostToolUseFailure',
+ 'UserPromptSubmit', 'Notification', 'Stop', 'SubagentStart', 'SubagentStop',
+ 'TeammateIdle', 'TaskCompleted', 'PreCompact', 'SessionStart', 'SessionEnd'
+}
+missing = sorted(expected - set(hooks.keys()))
+if missing:
+ print(f'ERROR: Missing hook events: {", ".join(missing)}', file=sys.stderr)
+ sys.exit(1)
+bad = sorted(k for k in expected if not isinstance(hooks.get(k), list))
+if bad:
+ print(f'ERROR: Hook events must be arrays: {", ".join(bad)}', file=sys.stderr)
+ sys.exit(1)
" 2>&1; then📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| # 1b. Validate hook schema format (array-based with CamelCase event keys) | |
| echo -n "Validating hook schema format... " | |
| if python3 -c " | |
| import json, sys | |
| with open('.claude/settings.local.json') as f: | |
| data = json.load(f) | |
| hooks = data.get('hooks', {}) | |
| if 'user-prompt-submit' in hooks: | |
| print('ERROR: Outdated flat schema detected (kebab-case key)', file=sys.stderr) | |
| sys.exit(1) | |
| if 'PreToolUse' not in hooks: | |
| print('ERROR: Missing PreToolUse key - expected CamelCase event keys', file=sys.stderr) | |
| sys.exit(1) | |
| if not isinstance(hooks['PreToolUse'], list): | |
| print('ERROR: PreToolUse should be an array, not flat object', file=sys.stderr) | |
| sys.exit(1) | |
| " 2>&1; then | |
| echo -e "${GREEN}✓${NC}" | |
| else | |
| echo -e "${RED}✗ Invalid hook schema${NC}" | |
| echo " Expected array-based format with CamelCase event keys (e.g., PreToolUse, PostToolUse)" | |
| echo " Re-run install-with-sondera.sh to regenerate" | |
| exit 1 | |
| fi | |
| # 1b. Validate hook schema format (array-based with CamelCase event keys) | |
| echo -n "Validating hook schema format... " | |
| if python3 -c " | |
| import json, sys | |
| with open('.claude/settings.local.json') as f: | |
| data = json.load(f) | |
| hooks = data.get('hooks', {}) | |
| if 'user-prompt-submit' in hooks: | |
| print('ERROR: Outdated flat schema detected (kebab-case key)', file=sys.stderr) | |
| sys.exit(1) | |
| expected = { | |
| 'PreToolUse', 'PermissionRequest', 'PostToolUse', 'PostToolUseFailure', | |
| 'UserPromptSubmit', 'Notification', 'Stop', 'SubagentStart', 'SubagentStop', | |
| 'TeammateIdle', 'TaskCompleted', 'PreCompact', 'SessionStart', 'SessionEnd' | |
| } | |
| missing = sorted(expected - set(hooks.keys())) | |
| if missing: | |
| print(f'ERROR: Missing hook events: {", ".join(missing)}', file=sys.stderr) | |
| sys.exit(1) | |
| bad = sorted(k for k in expected if not isinstance(hooks.get(k), list)) | |
| if bad: | |
| print(f'ERROR: Hook events must be arrays: {", ".join(bad)}', file=sys.stderr) | |
| sys.exit(1) | |
| " 2>&1; then | |
| echo -e "${GREEN}✓${NC}" | |
| else | |
| echo -e "${RED}✗ Invalid hook schema${NC}" | |
| echo " Expected array-based format with CamelCase event keys (e.g., PreToolUse, PostToolUse)" | |
| echo " Re-run install-with-sondera.sh to regenerate" | |
| exit 1 | |
| fi |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@test-sondera-integration.sh` around lines 30 - 53, The script only validates
the 'PreToolUse' key; update the python check in test-sondera-integration.sh to
validate all required lifecycle event keys by defining a list of the 14 expected
CamelCase event names (instead of just 'PreToolUse'), then iterate over that
list and for each ensure it exists in hooks and is a list; replace the
single-key checks for 'PreToolUse' and 'user-prompt-submit' with this loop so
any missing or non-array event (e.g., hooks[event] not isinstance(list)) causes
an error and non-zero exit.
Summary
user-prompt-submitwithargs/blocking/timeout) with current array-based format covering all 14 lifecycle events (PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, etc.)Context
The installer was generating
settings.local.jsonwith a deprecated schema that didn't match the actual Claude Code hook format used in the project's own.claude/settings.local.json. This caused a mismatch between what the installer produces and what Claude Code expects.Test plan
bash -n install-with-sondera.sh— shell syntax validbash -n test-sondera-integration.sh— shell syntax validpython3 -m json.tool.claude/settings.local.jsonformat🤖 Generated with Claude Code
Summary by Sourcery
Align the Sondera installer-generated Claude hook configuration with the current Claude Code lifecycle hook schema and ensure it stays validated.
New Features:
Bug Fixes:
Enhancements:
Summary by CodeRabbit
Documentation
Configuration
Tests