agent/claude/issues/016-hooks-format-auto.md
Snider 8fed5bc6ef docs: add hook improvement tasks for better feedback cycle
6 new issues for Claude Code hook improvements:

- 012: Test output filtering (reduce noise, show failures only)
- 013: Stop verification (verify work complete before stopping)
- 014: Auto-test on edit (async tests after code changes)
- 015: Session context injection (git/issues/CI on startup)
- 016: Silent auto-formatting (suppress formatter output)
- 017: Expose/hide policy (define what to show vs suppress)

Based on Claude Code hooks documentation:
- PostToolUse with suppressOutput for noise reduction
- Stop hooks with agent verification
- Async hooks for background testing
- SessionStart for context injection
- additionalContext for exposing important info

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 18:57:16 +00:00

1.8 KiB

feat(hooks): Auto-format code silently after edits

Summary

Add PostToolUse hooks that silently auto-format code after Write/Edit, without polluting context with formatter output.

Current State

Current hooks call formatters but output is visible:

  • php-format.sh - runs Pint
  • go-format.sh - runs gofmt

This creates noise in the conversation.

Solution

Use suppressOutput: true to hide formatter output entirely.

Hook Configuration

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "core ai format-file",
            "statusMessage": "Formatting..."
          }
        ]
      }
    ]
  }
}

Implementation

core ai format-file:

#!/bin/bash
INPUT=$(cat)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

[ -z "$FILE" ] || [ ! -f "$FILE" ] && exit 0

case "$FILE" in
  *.go)
    core go fmt "$FILE" 2>/dev/null
    ;;
  *.php)
    core php fmt "$FILE" 2>/dev/null
    ;;
  *.ts|*.tsx|*.js|*.jsx)
    npx prettier --write "$FILE" 2>/dev/null
    ;;
  *.json)
    jq '.' "$FILE" > "$FILE.tmp" && mv "$FILE.tmp" "$FILE" 2>/dev/null
    ;;
esac

# Suppress all output - formatting is silent
echo '{"suppressOutput": true}'

Benefits

  1. No context pollution - formatter output hidden
  2. Consistent formatting - every file formatted on save
  3. No manual step - Claude doesn't need to remember to format
  4. Fast - formatters are quick, doesn't block significantly

Error Handling

Only report if formatting fails badly:

if ! core go fmt "$FILE" 2>&1; then
  # Only surface actual errors, not warnings
  echo '{"systemMessage": "Format failed for '$FILE' - syntax error?"}'
  exit 0
fi

echo '{"suppressOutput": true}'