hooks
<tool_restrictions>
MANDATORY Tool Restrictions
REQUIRED TOOLS — use these, do not skip:
AskUserQuestion— REQUIRED for all user choices (Biome install options).
BANNED TOOLS — calling these is a skill violation:
EnterPlanMode— BANNED. Do NOT call this tool. This skill has its own structured process. Execute the steps below directly.ExitPlanMode— BANNED. You are never in plan mode. </tool_restrictions>
Step 0: Handle --remove flag
If the user passed --remove:
- Read
.claude/settings.json - Remove all Arc-installed hooks (identified by comments or known commands)
- Write back the cleaned settings
- Report what was removed
- Done — skip all other steps
Step 1: Detect Biome
grep -q '"@biomejs/biome"' package.json 2>/dev/null
If Biome is in package.json: Continue to Step 2.
If Biome is NOT found:
AskUserQuestion:
question: "Biome not found in package.json. Arc hooks require Biome for auto-formatting and linting. How would you like to proceed?"
header: "Biome Required"
options:
- label: "Install Biome and continue"
description: "Add @biomejs/biome as a dev dependency and set up all hooks"
- label: "Skip formatting hooks"
description: "Install context monitor and git guard only, skip Biome-dependent hooks"
- label: "Cancel"
description: "Exit without installing any hooks"
If user picks "Install Biome and continue":
# Detect package manager from lockfile
if [ -f pnpm-lock.yaml ]; then
pnpm add -D @biomejs/biome
elif [ -f yarn.lock ]; then
yarn add -D @biomejs/biome
else
npm install -D @biomejs/biome
fi
Then check for biome.json / biome.jsonc. If missing:
npx @biomejs/biome init
If user picks "Skip formatting hooks": Set SKIP_BIOME=true, continue to Step 3.
If user picks "Cancel": Stop. Do not install any hooks.
Step 2: Verify Biome works
./node_modules/.bin/biome --version
If this fails, the binary isn't available. Tell the user and offer to reinstall.
Also check for biome config:
ls biome.json biome.jsonc 2>/dev/null
If no config exists, note this — biome will use defaults, which is fine.
Step 3: Build the hooks config
Build the hooks object to merge into .claude/settings.json.
Biome format hook (PostToolUse, Edit|Write):
{
"matcher": "Edit|Write|NotebookEdit",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path // .tool_input.filePath // empty' | { read file_path; case \"$file_path\" in *.js|*.ts|*.jsx|*.tsx|*.json|*.jsonc|*.css|*.graphql) ./node_modules/.bin/biome format --write \"$file_path\" 2>/dev/null || true ;; esac; }"
}
]
}
Biome lint hook (Stop):
{
"hooks": [
{
"type": "command",
"command": "git diff --name-only --diff-filter=d HEAD 2>/dev/null | grep -E '\\.(js|ts|jsx|tsx|json|jsonc|css|graphql)$' | xargs -r ./node_modules/.bin/biome check --fix --unsafe 2>/dev/null || true"
}
]
}
TypeScript check hook (Stop):
Only include this if the project has TypeScript (tsconfig.json exists).
{
"hooks": [
{
"type": "command",
"command": "npx tsc --noEmit 2>&1 | tail -20 || true"
}
]
}
Git guard hook (PreToolUse, Bash):
This hook blocks destructive git operations before they execute. Always install — not dependent on Biome.
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.command' | grep -qE 'git\\s+(reset\\s+--hard|push\\s+(-f|--force)|clean\\s+-f|checkout\\s+\\.)' && echo '{\"decision\":\"block\",\"reason\":\"Destructive git operation blocked by Arc hooks. Ask the user first.\"}' || true"
}
]
}
Context monitor hook (PostToolUse, all tools):
Determine the absolute path to Arc's hooks/ directory by resolving the Arc install root from this skill's location. Use that resolved path as ${ARC_HOOKS_PATH}.
Read hooks/arc-context-monitor.js from the resolved Arc install root to confirm it exists.
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "node ${ARC_HOOKS_PATH}/arc-context-monitor.js"
}
]
}
Where ${ARC_HOOKS_PATH} is the resolved absolute path to the Arc plugin's hooks/ directory.
Statusline hook:
{
"type": "command",
"command": "node ${ARC_HOOKS_PATH}/arc-statusline.js"
}
If SKIP_BIOME is true: Only include the git guard, context monitor, and statusline hooks. The tsc hook is independent of Biome — include it if tsconfig.json exists.
Step 4: Read existing settings
cat .claude/settings.json 2>/dev/null
If file doesn't exist:
mkdir -p .claude
Start with an empty object {}.
If file exists: Parse the JSON. Preserve ALL existing fields (permissions, enabledMcpjsonServers, enableAllProjectMcpServers, enabledPlugins, etc.).
Step 5: Merge hooks into settings
This is the critical step. NEVER clobber existing hooks — merge with them.
Read the existing hooks object (may be undefined).
For PreToolUse:
- Get existing
hooks.PreToolUsearray (or empty array) - Check if an Arc git guard hook already exists (command contains
git.*reset.*--hard) - Add only if it doesn't exist
For PostToolUse:
- Get existing
hooks.PostToolUsearray (or empty array) - Check if an Arc biome format hook already exists (command contains
biome format) - Check if an Arc context monitor hook already exists (command contains
arc-context-monitor) - Add new entries only if they don't already exist
- Biome format hook and context monitor hook are separate entries (different matchers)
For Stop:
- Get existing
hooks.Stoparray (or empty array) - Check if an Arc biome lint hook already exists (command contains
biome check) - Check if an Arc tsc hook already exists (command contains
tsc --noEmit) - Add each only if it doesn't exist
- If no
tsconfig.jsonin the project, skip the tsc hook
For Statusline:
- Get existing
hooks.Statuslinearray (or empty array) - Check if Arc statusline already exists (command contains
arc-statusline) - Add only if it doesn't exist
Write the merged settings back: Use the Write tool to write the complete JSON (pretty-printed with 2-space indent).
CRITICAL: Preserve all non-hook fields exactly as they were. Do not add, remove, or modify anything outside the hooks key.
Step 6: Verify installation
Read back .claude/settings.json and confirm the hooks are present.
Count installed hooks:
- PreToolUse entries
- PostToolUse entries
- Stop entries
- Statusline entries
Step 7: Report
Arc hooks installed in .claude/settings.json
PreToolUse (Bash) → blocks destructive git ops (force push, reset --hard)
PostToolUse (Edit|Write) → biome format --write on edited file
PostToolUse (all tools) → context monitor (warns at 35%/25% remaining)
Stop → biome check --fix --unsafe on all changed files
Stop → tsc --noEmit (if tsconfig.json exists)
Statusline → context bar showing usage
Hooks run automatically — zero token cost, zero agent effort.
To remove: /arc:hooks --remove
If SKIP_BIOME was true:
Arc hooks installed in .claude/settings.json
PreToolUse (Bash) → blocks destructive git ops (force push, reset --hard)
PostToolUse (all tools) → context monitor (warns at 35%/25% remaining)
Statusline → context bar showing usage
Biome hooks skipped (not installed). Run /arc:hooks again after adding Biome.
To remove: /arc:hooks --remove