Repro (specweave 1.0.581)
echo '{"hook_event_name":"PreToolUse","tool_name":"Edit","tool_input":{"file_path":"/tmp/foo","old_string":"a","new_string":"b"}}' | specweave hook pre-tool-use
# Output: {"decision":"allow"}
Claude Code rejects this with:
PreToolUse:Edit hook error
Hook JSON output validation failed — (root): Invalid input
Why it's invalid
Claude Code's hook output schema accepts either:
- Legacy format:
{"decision": "approve" | "block", "reason": "..."} — the value "allow" is not in the enum.
- Current format:
{"hookSpecificOutput": {"hookEventName": "PreToolUse", "permissionDecision": "allow" | "deny" | "ask", "permissionDecisionReason": "..."}}
SpecWeave's CLI emits a bare {"decision":"allow"}, which matches neither. Returning {} (empty object), {"continue": true}, or migrating to the hookSpecificOutput shape would all fix this.
Why this is a regression of #1573
#1573 ("Eliminate PreToolUse Edit Hook Errors") was closed on 2026-03-15 with status:complete and 100% AC, but:
closedByPullRequestsReferences is empty — no PR was merged for the closure.
- The fix described (
set +e instead of set -e in pre-tool-use.sh) targeted a shell handler that has since been removed.
- Commit 0f81519 ("rework hooks: remove shell-based handlers, consolidate to CLI-first approach") replaced that shell handler with the Node CLI dispatcher, which reintroduces the same user-visible symptom — but now from a different code path (TypeScript schema bug instead of bash exit code).
Impact
The hook matcher is Write|Edit, so this error fires on every file edit during a Claude Code session. It's cosmetic (fail-open, the edit still happens), but produces:
- Persistent red error noise in the Claude Code UI.
- Wasted time per hook invocation (the dispatch + JSON serialize) for no useful effect when the schema is invalid.
- Erosion of trust in the plugin — users who hit this and don't actively use SpecWeave end up disabling the whole plugin.
Environment
- specweave:
1.0.581 (latest npm at time of report)
- Claude Code:
2.x (current line)
- macOS: Darwin 25.4.0 (arm64)
- Node: v25.9.0
Suggested fix
In the CLI's pre-tool-use handler, change the success response from:
to either:
{} // simplest — nothing returned means "proceed normally"
or, if explicit permission control is intended:
{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "allow",
permissionDecisionReason: "<your reason>"
}
}
Happy to test a candidate PR.
Repro (specweave 1.0.581)
Claude Code rejects this with:
Why it's invalid
Claude Code's hook output schema accepts either:
{"decision": "approve" | "block", "reason": "..."}— the value"allow"is not in the enum.{"hookSpecificOutput": {"hookEventName": "PreToolUse", "permissionDecision": "allow" | "deny" | "ask", "permissionDecisionReason": "..."}}SpecWeave's CLI emits a bare
{"decision":"allow"}, which matches neither. Returning{}(empty object),{"continue": true}, or migrating to thehookSpecificOutputshape would all fix this.Why this is a regression of #1573
#1573 ("Eliminate PreToolUse Edit Hook Errors") was closed on 2026-03-15 with
status:completeand 100% AC, but:closedByPullRequestsReferencesis empty — no PR was merged for the closure.set +einstead ofset -einpre-tool-use.sh) targeted a shell handler that has since been removed.Impact
The hook matcher is
Write|Edit, so this error fires on every file edit during a Claude Code session. It's cosmetic (fail-open, the edit still happens), but produces:Environment
1.0.581(latest npm at time of report)2.x(current line)Suggested fix
In the CLI's pre-tool-use handler, change the success response from:
to either:
or, if explicit permission control is intended:
Happy to test a candidate PR.