بازگشت به کتابخانهکتابخانه4.2Hook — گسترش سیستم Permission
تکنیک Ralph WiggumTHE RALPH WIGGUM TECHNIQUEاجرای ایجنت کدنویس در حلقه — از یک اسکریپت Bash تا ارکستراسیون کامل
v1.0.0
LESSON 4.2فصل ۴Permission ،Sandbox و Hook

Hook — گسترش سیستم Permission

  • ~۱۲ دقیقه
  • ۵ پرسش
  • متن را انتخاب کن تا هایلایت شود

Sandbox بومی بیشتر راه را می‌رود، اما هنوز برای بعضی چیزها Permission رد می‌شوی. مثلاً یک MCP Server اضافه کرده‌ای (مثل Chrome DevTools) و از مدل می‌خواهی به سایتی برود — با اینکه Sandbox را روی Auto-Allow گذاشته‌ای، باز هم Prompt می‌گیری. چرا؟ چون Sandbox فقط Bash را خودکار می‌کند؛ ابزارهای MCP دسته‌ای کاملاً جدا هستند و اصلاً داخل Sandbox اجرا نمی‌شوند. اینجا Hook وارد می‌شود.

چرا MCP از Sandbox رد می‌شود؟

ابزارهای MCP نه دستور Bash‌اند، نه Child Process، و داخل Sandbox اجرا نمی‌شوند. پس مستقیم به سیستم Permission معمولی می‌روند — که در Print Mode شکست می‌خورد. می‌شد کل ابزار را در Allow List گذاشت (`mcp__chrome__*`)، ولی اگر بخواهی فقط «بعضی» صفحات را Deny کنی، Allow List کم می‌آورد.

MCP — Model Context Protocol
پروتکل اتصال ابزارهای بیرونی (مثل Chrome DevTools) به مدل. ابزارهایش جدا از Bash‌اند و در Sandbox اجرا نمی‌شوند.
Hook
اسکریپتی که در نقاط مشخصی از چرخه کار مدل اجرا می‌شود و می‌تواند تصمیم Permission را عوض کند. قدرتمندترین لایه گسترش.
PreToolUse
مهم‌ترین Hook: قبل از اجرای هر Tool Call صدا زده می‌شود و می‌تواند Allow یا Deny کند.

ساختار Hook در settings.json

Hook را با یک Matcher (کدام ابزارها) و یک Command (چه اسکریپتی) تعریف می‌کنی:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "mcp__chrome.*",
        "hooks": [
          { "type": "command", "command": ".claude/hooks/pre-devtools.sh" }
        ]
      }
    ]
  }
}

اسکریپت Hook برای «رد کردن laracasts.com و هدایت به laracasts.test» ساده است — فقط باید JSON مخصوص چاپ کند تا مدل تصمیم را بفهمد:

#!/bin/bash
INPUT=$(cat)   # کل Tool Call به‌صورت JSON از stdin می‌آید
echo "$INPUT" >> .claude/hooks/pre-devtools.log   # لاگ برای ردگیری

if echo "$INPUT" | grep -q "laracasts.com"; then
  cat <<'JSON'
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "No fetching laracasts.com — use laracasts.test instead."
  }
}
JSON
else
  echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow"}}'
fi

چون مدل `permissionDecisionReason` را می‌خواند، به‌جای شکست کور، هوشمندانه به laracasts.test می‌رود. Hook فقط یک اسکریپت است، پس می‌تواند Node یا PHP هم باشد، یا حتی یک API Call بزند.

Hook از جنس Prompt

راه دیگر، Hook از نوع `prompt` است که به‌جای اسکریپت، یک پرامپت درون‌خطی می‌گیرد و `$ARGUMENTS` با همان JSON درخواست جایگزین می‌شود:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "mcp__chrome.*",
        "hooks": [
          {
            "type": "prompt",
            "prompt": "Allow or deny this request. laracasts.com is NOT allowed; laracasts.test is. $ARGUMENTS"
          }
        ]
      }
    ]
  }
}

مدیریت پرامپت این‌طوری سخت است. الگوی تمیزتر: `type` را `command` نگه دار و داخلش Claude را در Print Mode صدا بزن:

#!/bin/bash
claude -p "$(cat .claude/hooks/pre-tool-use.md)"

و فایل `pre-tool-use.md` نقش «مشاور امنیتی» را بازی می‌کند:

You are a PreToolUse hook for Claude Code.
Deny requests going to laracasts.com. Allow laracasts.test.
Allow all other requests. To deny, emit the hookSpecificOutput JSON.
Log the incoming request before deciding.

مشاور امنیتی عمومی

می‌شود Matcher را از MCP فراتر برد و «هر دستوری که Permission می‌خواهد» را به یک مشاور امنیتی عمومی سپرد که هر Tool Call را برای نقض امنیتی بازرسی می‌کند: نه SSH، نه Deploy، نه Publish، نه عملیات مخرب روی جدول یا فایل.

DIAGRAMجریان تصمیم PreToolUse
Tool Call
Hook: pre-tool-use
deny + reason به مدل
allow
مدل رفتار را اصلاح می‌کند

به زبان ساده

Sandbox فقط Bash را پوشش می‌دهد. ابزار MCP (مثل Chrome) جداست. Hook قبل از ابزار اجرا می‌شود و می‌تواند با یک JSON بگوید Allow یا Deny — حتی دلیلش را به مدل بگوید.

مثال واقعی

مدل خواست برود laracasts.com؛ Hook رد کرد و گفت از laracasts.test استفاده کن. مدل حرف را فهمید و به دامنهٔ تست رفت. لاگ Hook هر دو درخواست را نشان داد: اول blocked، دوم allowed.

دانش‌سنجی

آزمون درس

۵ Q
01
چرا ابزار MCP با اینکه Sandbox روی Auto-Allow است باز هم Permission می‌خواهد؟
02
کدام Hook برای کنترل Permission قبل از اجرای ابزار به کار می‌رود؟
03
اسکریپت Hook چطور تصمیمش را به مدل می‌فهماند؟
04
چرا الگوی «type: command که داخلش claude -p را صدا می‌زند» بر Hook از نوع prompt ترجیح داده شد؟
05
Trade-off مشاور امنیتی عمومی (بازرسی هر Tool Call با یک Claude جدا) چیست؟