TROISINH
Nâng cao & Tự động hoáHooks — Tự động hoá sự kiện

PostToolUse Hook: 'Dọn dẹp' tự động sau mỗi lệnh AI

Cấu hình PostToolUse Hook trong Claude Code để tự động format code, ghi audit log và gửi notification sau mỗi hành động. Khắc phục triệt để tính 'quên trước nhớ sau' của LLM.

Định nghĩa

PostToolUse Hook đóng vai trò như "người dọn dẹp" trong Claude Code — tự động kích hoạt ngay sau khi AI hoàn thành bất kỳ thao tác nào (viết file, chạy lệnh bash, edit code) để thực thi các tác vụ deterministic như format code, kiểm tra bảo mật, hoặc gửi thông báo, bù đắp triệt để cho tính "quên trước nhớ sau" của LLM.

Giải thích chi tiết

Cơ chế "JSON trên stdin" — dữ liệu có cấu trúc thay vì log tự nhiên

Khác với việc parse log bằng regex, PostToolUse hook nhận thông tin về hành động vừa xảy ra qua stdin dưới dạng JSON có cấu trúc. Payload bao gồm:

  • tool_name: Loại thao tác (Write, Edit, Bash, v.v.)
  • tool_input: Chi tiết đầu vào (đường dẫn file, command string, nội dung)
  • tool_output: Kết quả trả về từ thao tác vừa rồi

Nhờ đó, script của bạn viết logic điều kiện chính xác: "if tool_name == 'Write' and file_path.endswith('.ts')", thay vì cố gắng đoán ý từ văn bản tự nhiên. JSON-RPC này biến hooks thành middleware có thể kiểm thử, không phải "script hacky" parse log.

Cleanup crew vs Gatekeeper — vai trò bổ sung cho PreToolUse

Nếu PreToolUse Hook đóng vai trò "bảo vệ" (gatekeeper) có quyền veto (exit code 2) để chặn lệnh nguy hiểm trước khi chạy, thì PostToolUse là "đội dọn vệ sinh" (cleanup crew). Nó không thể ngăn hành động xảy ra, chỉ có thể phản ứng sau đó bằng cách sửa chữa, ghi log, hoặc thông báo.

Sự phân chia này quan trọng về mặt kiến trúc: PreToolUse giải quyết vấn đề an toàn (safety), PostToolUse giải quyết vấn đề chất lượng và tuân thủ (quality & compliance).

Bài toán "Context Window Tax" — chi phí ẩn của auto-format

Khi dùng PostToolUse để format code (ví dụ chạy Prettier), Claude sẽ nhận thấy file thay đổi ngay sau khi hook chạy xong. Hệ thống đưa vào context window một system reminder ghi nhận thay đổi này, tiêu tốn khoảng 100-200 tokens cho mỗi lần edit.

Trong session dài 50 lần edit, đây là 5k-10k tokens "vô ích" nếu format ngay lập tức sau mỗi lần sửa. Chiến lược tối ưu là batched formatting: để AI code "bừa bãi" trong session, rồi dùng Stop Hook hoặc /simplify command để format toàn bộ một lần trước khi commit.

Async execution và race conditions

PostToolUse hỗ trợ chế độ async: true cho phép hook chạy non-blocking song song với luồng làm việc chính của AI. Phù hợp cho việc gửi Slack notification hoặc ghi audit log — những tác vụ không cần kết quả trả về ngay lập tức.

Tuy nhiên, do các hook chạy parallel, bạn không thể giả định thứ tự thực thi giữa chúng. Nếu hook A phụ thuộc vào side effect của hook B, sẽ gặp race condition. Giải pháp là gộp logic vào một script duy nhất hoặc dùng file lock/timestamp để đồng bộ.

Ví dụ thực tế

Auto-format Prettier cho dự án React/Node.js (Startup VN)

Tình huống: Team startup ở Hà Nội dùng Prettier với cấu hình single quote và 2 spaces, nhưng Claude thường quên và sinh code với double quote và 4 spaces do "quyền năng" từ training data.

Cấu hình hook (~/.claude/hooks/posttooluse/prettier-format.js):

#!/usr/bin/env node
const fs = require('fs');

// Đọc JSON từ stdin
const input = JSON.parse(fs.readFileSync(0, 'utf-8'));
const { tool_name, tool_input } = input;

// Chỉ xử lý Write và Edit với file JS/TS
if (['Write', 'Edit'].includes(tool_name) && 
    tool_input.file_path?.match(/\.(js|jsx|ts|tsx)$/)) {
    
    const { execSync } = require('child_process');
    const file = tool_input.file_path;
    
    try {
        // Chạy prettier trên file vừa edit
        execSync(`npx prettier --write "$[file]"`, { stdio: 'inherit' });
        console.error(`✓ Formatted $[file]`);
    } catch (e) {
        console.error(`✗ Format failed: ${e.message}`);
    }
}

// Exit 0 để báo thành công (không chặn gì cả)
process.exit(0);
chmod +x ~/.claude/hooks/posttooluse/prettier-format.js

Sau khi cấu hình, mỗi lần Claude sửa file components/UserProfile.tsx, hook tự động chạy Prettier ngay sau đó, đảm bảo codebase luôn consistent dù AI có "quên" coding standard.

Audit log cho ngân hàng/fintech (Compliance VietQR)

Tình huống: Một ngân hàng số triển khai tích hợp VietQR cần ghi lại mọi thao tác sửa code vào hệ thống SIEM để phục vụ audit trail theo quy định Ngân hàng Nhà nước (NHNN) về an toàn hệ thống thanh toán.

Hook script (~/.claude/hooks/posttooluse/audit-log.py):

#!/usr/bin/env python3
import json
import sys
import requests
from datetime import datetime

payload = json.load(sys.stdin)

# Chỉ log các thao tác ghi file hoặc bash nguy hiểm
if payload['tool_name'] in ['Write', 'Edit', 'Bash']:
    audit_entry = {
        'timestamp': datetime.now().isoformat(),
        'session_id': payload.get('session_id', 'unknown'),
        'tool': payload['tool_name'],
        'target': payload['tool_input'].get('file_path') or payload['tool_input'].get('command'),
        'user': payload.get('user', 'claude-session'),
        'environment': 'production' if 'prod' in sys.argv else 'development'
    }
    
    # Gửi async đến SIEM API (không block AI)
    try:
        requests.post(
            'https://siem.internal-bank.com/api/claude-audit',
            json=audit_entry,
            timeout=2
        )
    except:
        pass  # Silent fail để không làm chậm AI

sys.exit(0)

Lưu ý dùng async: true trong .claude/settings.json để API call không làm chậm luồng làm việc của Claude.

Zalo notification khi refactor module Shopee-style hoàn thành

Tình huống: Tech lead cần biết khi nào Claude Code vừa hoàn thành refactor module lớn (hơn 10 file) giống kiểu microservices của Shopee để kịp review trước giờ deploy.

Hook script kiểm tra số lượng file thay đổi:

#!/bin/bash
# ~/.claude/hooks/posttooluse/notify-refactor.sh

read JSON_INPUT

# Kiểm tra nếu là Edit và mention "refactor" trong output
if echo "$JSON_INPUT" | grep -q '"tool_name": "Edit"' && \
   echo "$JSON_INPUT" | grep -qi "refactor"; then
    
    # Đếm số file đã sửa trong session (từ transcript)
    FILE_COUNT=$(grep -c "Edit\\|Write" ~/.claude/transcript/*.json 2>/dev/null || echo "0")
    
    if [ "$FILE_COUNT" -gt 10 ]; then
        curl -X POST https://api.zalo.me/v2.0/oa/message \
            -H "access_token: $ZALO_OA_TOKEN" \
            -H "Content-Type: application/json" \
            -d "{
                \"recipient\": {\"user_id\": \"$LEAD_USER_ID\"},
                \"message\": {\"text\": \"Claude vừa refactor xong ~$FILE_COUNT files. Cần review trước khi lên production!\"}
            }"
    fi
fi

exit 0

Ứng dụng

Developer cá nhân (Freelancer/Indie Hacker): Tự động chạy eslint --fix hoặc black (Python) sau mỗi lần sửa file, giải phóng cognitive load khỏi việc nhớ coding standard. Kết hợp với Voice Mode để "nói" code xong rồi để hook tự dọn dẹp.

Team Lead/QA Engineer: Thiết lập audit trail tự động ghi lại "AI đã sửa gì, khi nào, ở đâu" vào hệ thống compliance. Đặc biệt quan trọng khi dùng Agent Teams với nhiều Claude instance chạy song song — cần biết agent nào đã touch file nào.

DevOps/SRE: Trigger auto-deployment hoặc smoke test sau khi AI push code. Ví dụ: hook nhận diện khi Claude chạy git push, tự động trigger GitHub Actions workflow hoặc gửi webhook đến CI/CD pipeline của doanh nghiệp.

Doanh nghiệp FinTech/Bảo hiểm: Đảm bảo mọi thao tác sửa code đều được log vào hệ thống enterprise setup, phục vụ kiểm toán nội bộ và compliance (SOC 2, ISO 27001, quy định NHNN).

So sánh

Đặc điểmPostToolUse HookPreToolUse HookSlash Commands
Thời điểm kích hoạtSau hành độngTrước hành độngKhi user gõ lệnh
Khả năng chặn (Veto)Không — chỉ cleanupCó — exit code 2Không liên quan
Mục đích chínhFormat, log, notifyChặn lệnh nguy hiểmTự động hóa workflow
Context window impactCao (nếu format liên tục)ThấpTrung bình
Độ phức tạp cấu hìnhTrung bìnhCao (cần pattern matching an toàn)Thấp

Kết luận: PostToolUse phù hợp cho "dọn dẹp và ghi chép", PreToolUse phù hợp cho "bảo vệ và chặn", còn Slash Commands phù hợp cho "lệnh chủ động". Trong thực tế, nên kết hợp cả ba: PreToolUse để ngăn AI xóa nhầm production database, PostToolUse để format code và ghi audit log, Slash Commands để trigger các workflow phức tạp.

Bài viết liên quan

Cùng cụm (Hooks & Automation)

Đọc tiếp (Nâng cao & Tự động hóa)

On this page