Skip to content
Back to skills

Hook Feedback Merge

ASecurity

Hook feedback to tool result merge pattern. Documents how pre/post hook feedback (warnings, blocks, suggestions) gets merged into tool results so the model sees quality signals inline with tool output. Auto-activates when: writing hooks that produce feedback, reviewing hook output flow. Triggers: hook feedback, tool result, merge, pre-write, post-edit, quality gate

  • 3 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 2, 2026
ai-agentsgobashnodebackenddevops

Works with

  • claude code

Security analysis

A100/100

Scanned September 29, 2026

npx -y skills add Yoodaddy0311/artibot --skill hook-feedback-merge --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Hook Feedback Merge?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Hook Feedback Merge
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/yoodaddy0311-hook-feedback-merge/badge)](https://www.skillsdirectory.com/skills/yoodaddy0311-hook-feedback-merge)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
context: fork
user-invocable: false
name: hook-feedback-merge
description: |
  Hook feedback to tool result merge pattern. Documents how pre/post hook
  feedback (warnings, blocks, suggestions) gets merged into tool results
  so the model sees quality signals inline with tool output.
  Auto-activates when: writing hooks that produce feedback, reviewing hook output flow.
  Triggers: hook feedback, tool result, merge, pre-write, post-edit, quality gate
lang: [en]
platforms: [claude-code]
level: 2
triggers:
  - "hook"
  - "feedback"
  - "tool result"
  - "merge"
  - "quality gate"
allowed-tools: [Read, Grep, Glob]
tokens: "~1.5K"
category: "infrastructure"
agents: [devops-engineer, backend-developer]
version: "1.0.0"
source_hash: ba191989
whenNotToUse: "Business logic, UI components, or any code that does not interact with the Claude Code hook system; this skill is exclusively for hook pipeline and tool result flow."
---
# Hook Feedback Merge Pattern

## Overview

Claude Code merges hook stdout JSON directly into tool results. When a hook
emits structured feedback (warnings, blocks, reasons), the model receives it
as part of the tool call response -- not as a separate system message. This
means hook feedback is contextually attached to the exact tool invocation
that triggered it.

## How It Works

```
Tool Call (e.g., Edit)
  -> PreToolUse hooks run
     -> Hook writes JSON to stdout: { "decision": "block", "reason": "..." }
  -> Claude Code merges hook output into tool result
  -> Model sees: tool result + hook feedback in one response
```

## Hook Output Contract

Hooks communicate by writing a single JSON object to stdout:

### Allow (passthrough -- no interference)
Print nothing and exit 0. Do not print `{"decision":"approve"}` to allow: the host
reads the legacy `approve` as `permissionDecision: "allow"` and skips the permission
prompt (PreToolUse on the Bash tool, measured on host 2.1.284 with `claude -p`;
evidence: `.artibot/guides/v5-design/evidence/ca04-host-ask-probe.md`, section 3.1).
Other tools and events are unmeasured, so print nothing there as well.

### Block (prevent tool execution)
```json
{
  "decision": "block",
  "reason": "Human-readable explanation of why blocked"
}
```

### Warn (allow but annotate)
```json
{
  "message": "Warning text that appears in tool result"
}
```

### Structured Feedback (rich metadata)
```json
{
  "decision": "block",
  "reason": "Review gate found 2 issue(s):\n  - Bracket mismatch\n  - Missing tests",
  "issues": ["...", "..."],
  "changedFiles": ["src/foo.js"],
  "codexCrossCheck": true
}
```

All fields beyond `decision` and `reason`/`message` are passed through and
available to the model as additional context.

## Existing Hooks Using This Pattern

| Hook | Phase | Key Fields |
|------|-------|------------|
| `pre-write-guard.js` | PreToolUse | `decision`, `reason` (block on unread files) |
| `pre-bash.js` | PreToolUse | `decision`, `reason` (block dangerous commands) |
| `quality-gate.js` | PostToolUse | `decision`, `reason` (block); `hookSpecificOutput.additionalContext` (warnings) |
| `stop-review-gate.js` | Stop | `decision`, `reason`, `issues[]`, `changedFiles[]` |
| `pre-compact.js` | PreCompact | `message`, `summary`, `tokenEstimate` |

## Implementation Guidelines

### For Hook Authors

1. **Always use `writeStdout()`** (or `writeJSON()`) from `scripts/utils/index.js`
2. **Use `decision` only to block**: `"block"` plus `reason`. The legacy field takes
   just `"approve"` and `"block"`; anything else (`"allow"`, `"warn"`, `"BLOCK"`) is a
   schema violation (`CHANGELOG.md` 2.1.1 fixed hooks that emitted `"ALLOW"`/`"BLOCK"`).
   Never emit `"approve"` (on PreToolUse it skips the permission prompt); to allow on
   any event, print nothing
3. **Include `reason`** with human-readable text -- the model reads this
4. **Add structured data** alongside reason for programmatic consumers
5. **Keep output small** -- hook output adds to the tool result token cost

### For Pre-Phase Hooks (PreToolUse)

```js
// Block pattern
writeStdout({ decision: 'block', reason: 'File not read before write' });

// Allow pattern: write nothing and exit 0. Do NOT writeStdout({ decision: 'approve' })
// -- the host turns it into permissionDecision "allow" and skips the permission prompt.
```

### For Post-Phase Hooks (PostToolUse)

```js
// Warning pattern (non-blocking)
writeStdout({ message: 'console.log detected in written file' });

// Block pattern (rare in post -- use for critical issues)
writeStdout({ decision: 'block', reason: 'Hardcoded secret detected' });
```

### For Stop Hooks

```js
// Review result: block only when there are issues, otherwise write nothing
if (issues.length > 0) {
  writeStdout({
    decision: 'block',
    reason: 'Review gate summary...',
    issues,
    changedFiles,
  });
}
```

## Best Practices

- **Keep `reason` under 500 chars** -- it appears inline in tool results
- **Use `message` for informational output**, `decision`+`reason` for actionable output
- **Never log secrets** in hook output -- it becomes part of the conversation
- **Test hook output** by running the hook manually with `echo '{}' | node hook.js`
- **Use stderr for debug logs** (`process.stderr.write(...)`) -- only stdout is merged

## Anti-Patterns

- Writing free-form text to stdout (must be valid JSON)
- Emitting large payloads (file contents, full diffs) in hook output
- Using `console.log()` in hooks (goes to stdout, corrupts JSON)
- Relying on hook output order (hooks may run in parallel within a phase)

## Rationalizations
> 이 절은 참고 자료다 — 아래 변명·반박은 모델이 작업 중 스스로 지름길을 점검하는 데 쓰고, 사용자에게 묻는 질문 목록이나 별도 게이트로 쓰지 않는다. 반박에 비추어 스스로 바로잡을 수 없으면 이 스킬의 Step·Checkpoint 규칙을 따른다.

The following table captures common excuses agents make to skip the discipline of this skill, paired with factual rebuttals.

| Excuse | Rebuttal |
|--------|----------|
| "hook warnings are advisory, I'll ignore them" | advisory warnings encode lessons from prior failures; ignoring them re-runs the experiment with the known result |
| "merging hook feedback clutters tool results" | unmerged feedback gets lost in stderr noise — merging is how the model actually sees it |
| "the model can't act on hook feedback mid-tool" | the model reads the merged result on the next turn and adjusts; that's exactly the feedback loop you want |
| "pre-hook blocks are too aggressive" | pre-hook blocks catch errors before they cost a tool round-trip; aggressive is the correct default |
| "post-hook suggestions arrive too late" | late suggestions steer the NEXT call; steering is always cheaper than correction |

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.