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 کم میآورد.
ساختار 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، نه عملیات مخرب روی جدول یا فایل.
به زبان ساده
Sandbox فقط Bash را پوشش میدهد. ابزار MCP (مثل Chrome) جداست. Hook قبل از ابزار اجرا میشود و میتواند با یک JSON بگوید Allow یا Deny — حتی دلیلش را به مدل بگوید.
مثال واقعی
مدل خواست برود laracasts.com؛ Hook رد کرد و گفت از laracasts.test استفاده کن. مدل حرف را فهمید و به دامنهٔ تست رفت. لاگ Hook هر دو درخواست را نشان داد: اول blocked، دوم allowed.