npx claudepluginhub braininahat/brains-in-a-hat --plugin brains-in-a-hatDefined in hooks/hooks.json
{
"PreToolUse": [
{
"hooks": [
{
"type": "command",
"command": "INPUT=$(cat); FILE=$(echo \"$INPUT\" | jq -r '.tool_input.file_path // empty'); PLUGIN_ROOT=\"${CLAUDE_PLUGIN_ROOT:-__unset__}\"; if [ \"$PLUGIN_ROOT\" != \"__unset__\" ] && echo \"$FILE\" | grep -qF \"$PLUGIN_ROOT\"; then echo '{\"decision\":\"block\",\"reason\":\"Cannot modify plugin files from within an agent.\"}'; fi"
},
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/block-team-lead-edits\""
}
],
"matcher": "Write"
},
{
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/pretool-agent-check\""
}
],
"matcher": "Agent"
},
{
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/block-team-lead-edits\""
}
],
"matcher": "Edit"
},
{
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/block-team-lead-edits\""
}
],
"matcher": "NotebookEdit"
},
{
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/block-team-lead-edits\""
}
],
"matcher": "Bash"
}
],
"SessionEnd": [
{
"hooks": [
{
"type": "command",
"command": "ls .brains_in_a_hat/state/active.* &>/dev/null && printf '{\"hookSpecificOutput\":{\"hookEventName\":\"SessionEnd\",\"additionalContext\":\"Session ending. Spawn session-manager (background, model=sonnet) to persist state: decisions made, WIP items, and vault updates. Use subagent_type=brains-in-a-hat:session-manager.\"}}'"
}
],
"matcher": ""
}
],
"PostToolUse": [
{
"hooks": [
{
"type": "command",
"command": "if ls .brains_in_a_hat/state/active.* &>/dev/null; then mkdir -p .brains_in_a_hat/state; INPUT=$(cat); AGENT=$(echo \"$INPUT\" | jq -r '.tool_input.name // .tool_input.subagent_type // \"agent\"'); DESC=$(echo \"$INPUT\" | jq -r '.tool_input.description // \"\"'); SESSION=$(ls -t .brains_in_a_hat/state/active.* 2>/dev/null | head -1); SESSION=\"${SESSION##*/active.}\"; jq -nc --arg ts \"$(date -Iseconds)\" --arg agent \"$AGENT\" --arg detail \"$DESC\" --arg session \"$SESSION\" '{ts:$ts,agent:$agent,session:$session,event:\"spawn\",detail:$detail}' >> .brains_in_a_hat/state/activity.jsonl; fi"
},
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/update-session-state\""
}
],
"matcher": "Agent"
}
],
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd\" session-start"
}
],
"matcher": ""
}
],
"SubagentStop": [
{
"hooks": [
{
"type": "command",
"command": "if ls .brains_in_a_hat/state/active.* &>/dev/null; then INPUT=$(cat); AGENT=$(echo \"$INPUT\" | jq -r '.agent_type // \"agent\"'); SESSION=$(ls -t .brains_in_a_hat/state/active.* 2>/dev/null | head -1); SESSION=\"${SESSION##*/active.}\"; jq -nc --arg ts \"$(date -Iseconds)\" --arg agent \"$AGENT\" --arg session \"$SESSION\" '{ts:$ts,agent:$agent,session:$session,event:\"done\",detail:\"completed\"}' >> .brains_in_a_hat/state/activity.jsonl 2>/dev/null; fi"
},
{
"type": "command",
"command": "if [ -n \"${ZELLIJ:-}\" ] && ls .brains_in_a_hat/state/active.* &>/dev/null; then INPUT=$(cat); AGENT_NAME=$(echo \"$INPUT\" | jq -r '.name // .agent_type // \"agent\"' 2>/dev/null); SESSION=$(ls -t .brains_in_a_hat/state/active.* 2>/dev/null | head -1); SESSION=\"${SESSION##*/active.}\"; PANE_FILE=\".brains_in_a_hat/state/zellij-pane-${SESSION}-${AGENT_NAME}.id\"; PANE_ID=$(cat \"$PANE_FILE\" 2>/dev/null); if [ -n \"$PANE_ID\" ]; then zellij action rename-pane --pane-id \"$PANE_ID\" \"${AGENT_NAME} [done]\" 2>/dev/null; rm -f \"$PANE_FILE\"; fi; fi"
}
],
"matcher": ""
}
],
"SubagentStart": [
{
"hooks": [
{
"type": "command",
"command": "if ls .brains_in_a_hat/state/active.* &>/dev/null; then INPUT=$(cat); AGENT=$(echo \"$INPUT\" | jq -r '.agent_type // \"agent\"'); SESSION=$(ls -t .brains_in_a_hat/state/active.* 2>/dev/null | head -1); SESSION=\"${SESSION##*/active.}\"; jq -nc --arg ts \"$(date -Iseconds)\" --arg agent \"$AGENT\" --arg session \"$SESSION\" '{ts:$ts,agent:$agent,session:$session,event:\"start\",detail:\"spawned\"}' >> .brains_in_a_hat/state/activity.jsonl 2>/dev/null; fi"
},
{
"type": "command",
"command": "if [ -n \"${ZELLIJ:-}\" ] && ls .brains_in_a_hat/state/active.* &>/dev/null; then INPUT=$(cat); AGENT_NAME=$(echo \"$INPUT\" | jq -r '.name // .agent_type // \"agent\"' 2>/dev/null); SESSION=$(ls -t .brains_in_a_hat/state/active.* 2>/dev/null | head -1); SESSION=\"${SESSION##*/active.}\"; ACTIVITY='.brains_in_a_hat/state/activity.jsonl'; PANE_ID=$(zellij action new-pane --floating --name \"$AGENT_NAME\" --close-on-exit -- bash -c \"tail -f '$ACTIVITY' | jq --unbuffered -r 'select(.agent==\\\"$AGENT_NAME\\\") | \\\"\\(.ts) \\(.event): \\(.detail)\\\"'\" 2>/dev/null); [ -n \"$PANE_ID\" ] && echo \"$PANE_ID\" > \".brains_in_a_hat/state/zellij-pane-${SESSION}-${AGENT_NAME}.id\"; fi"
},
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/inject-subagent-context\""
}
],
"matcher": ""
}
],
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/first-prompt-greeting\""
}
],
"matcher": ""
}
]
}"Blocks PreToolUse Write/Edit/Bash/Agent/NotebookEdit calls to protect plugin files and enforce team-lead rules; logs brains-in-a-hat agent activity to JSONL files and persists session state via bash. Writes files."