Skip to main content

Hooks

Gate or notify on any arc event with plain executables in .arc/hooks/.


Overview

arc fires hooks before and after major operations. Hook files live in .arc/hooks/<event> — any executable: a shell script, a Python script, a compiled binary.

  • pre-* hooks are gates. A non-zero exit code aborts the operation with exit code 7. The underlying operation does not run.
  • post-* hooks are notifications. The exit code is ignored.

Run arc init to scaffold sample hook files.


Events

EventTriggerType
pre-submitBefore creating/updating PRsgate
post-submitAfter all PRs are created/updatednotification
pre-pushBefore force-pushing branchesgate
post-pushAfter branches are pushednotification
pre-syncBefore cascade rebase beginsgate
post-syncAfter cascade rebase completes cleanlynotification
pre-landBefore landing a PRgate
post-landAfter a PR is landed and branches restackednotification

Environment variables

Every hook receives these environment variables:

VariableValue
ARC_EVENTEvent name (e.g. pre-submit)
ARC_BRANCHCurrent branch name
ARC_BASEStack base branch name (e.g. main)
ARC_STACK_SIZENumber of branches in the stack
ARC_DRY_RUN1 if --dry-run was passed, 0 otherwise

Stdin JSON

Each hook also receives a JSON object on stdin with event-specific data:

{
"event": "pre-submit",
"branch": "feat/auth",
"base": "main",
"stack": ["feat/auth", "feat/api", "feat/ui"],
"dry_run": false
}

Read stdin in a hook with jq:

#!/bin/sh
data=$(cat)
branch=$(echo "$data" | jq -r '.branch')
echo "Submitting $branch"

Examples

Lint gate before submit

# .arc/hooks/pre-submit
#!/bin/sh
set -e
npm run lint
npm test
chmod +x .arc/hooks/pre-submit

arc runs this before touching GitHub. Any non-zero exit aborts all PR creates/updates.

Slack notification after push

# .arc/hooks/post-push
#!/bin/sh
data=$(cat)
branch=$(echo "$data" | jq -r '.branch')
curl -s -X POST "$SLACK_WEBHOOK" \
-H 'Content-type: application/json' \
-d "{\"text\": \"Pushed stack from $branch\"}"

Bypass a hook

arc submit --skip-hooks

Only pre-submit and post-submit hooks can be skipped. Other hooks always run.


Config-file hooks

For simple shell commands, you can also define hooks in .arc/config.json (committed, shared with your team):

{
"hooks": {
"pre-submit": ["npm run lint", "npm test"],
"post-push": ["scripts/notify.sh"]
}
}

When both a config-file hook and a file hook exist for the same event, the config-file hook runs first.

See Configuration for the full config schema.