[AI] Remove agentic stop-hook from all platforms (#8684)

* [AI] Remove agentic stop-hook from all platforms

Drop the Stop hook wiring from Claude (.claude/settings.json) and Codex
(.codex/config.toml), and delete the now-unreferenced check-on-stop.sh.
Cursor never had a stop hook. common.sh stays — the remaining hook
scripts still use it.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01FoeRXh1A85w8RhAFdzJdZd

* [AI] Add release note

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01FoeRXh1A85w8RhAFdzJdZd

---------

Co-authored-by: Claude <[email protected]>
This commit is contained in:
Matiss Janis Aboltins
2026-08-09 06:53:07 +00:00
committed by GitHub
co-authored by Claude Fable 5
parent a9252f9cbc
commit a0d10a5b46
4 changed files with 8 additions and 123 deletions
-11
View File
@@ -52,17 +52,6 @@
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR/scripts/agent-hooks/check-on-stop.sh\"",
"timeout": 600
}
]
}
]
}
}
+2 -10
View File
@@ -12,8 +12,8 @@
# raw string in tool_input.command (no tool_input.file_path / .content), so the
# file-content hooks below (strict-ignore, format, one-component) only fire for
# the Write/Edit tools and no-op for apply_patch. They never false-block. The
# Bash/git guard and the Stop check work regardless. The file hooks are fully
# effective under Claude Code and Cursor.
# Bash/git guard works regardless. The file hooks are fully effective under
# Claude Code and Cursor.
#
# For hooks to run (any surface, including the ChatGPT desktop app):
# 1. Lifecycle hooks must be enabled — done by the [features] flag below.
@@ -78,11 +78,3 @@ matcher = "^mcp__github__create_pull_request$"
type = "command"
command = '"$(git rev-parse --show-toplevel)/scripts/agent-hooks/pr-template-blank.sh"'
statusMessage = "Checking PR template is left blank"
# When the turn ends, typecheck + test the workspaces this branch touched.
[[hooks.Stop]]
[[hooks.Stop.hooks]]
type = "command"
command = '"$(git rev-parse --show-toplevel)/scripts/agent-hooks/check-on-stop.sh"'
timeout = 600
statusMessage = "Typecheck + test touched workspaces"
-102
View File
@@ -1,102 +0,0 @@
#!/usr/bin/env bash
# Agent hook (Stop), shared across Claude and Codex.
#
# When the agent finishes its turn, run typecheck + test for each workspace this
# branch has touched (scoped — far cheaper than the whole-monorepo check).
# Failures are surfaced back to the agent via exit code 2 so it can fix them.
# Adapted from a suggestion by @StephenBrown2 on PR #8089.
set -uo pipefail
. "$(dirname "$0")/common.sh"
require_jq
# Read the hook payload (Claude provides stop_hook_active to prevent loops).
payload=$(cat 2>/dev/null || true)
if printf '%s' "$payload" | jq -e '.stop_hook_active == true' >/dev/null 2>&1; then
exit 0
fi
# Resolve the repo root regardless of which agent invoked us.
ROOT=$(resolve_repo_root)
cd "$ROOT" 2>/dev/null || exit 0
# Skip if dependencies aren't installed.
[ -f "$ROOT/node_modules/.yarn-state.yml" ] || exit 0
# Collect changed files, NUL-delimited so paths with spaces survive: this
# branch's commits vs master, plus tracked + untracked working-tree changes.
base=$(git merge-base HEAD origin/master 2>/dev/null || true)
files=()
while IFS= read -r -d '' f; do
[ -n "$f" ] && files+=("$f")
done < <(
{
[ -n "$base" ] && git diff -z --name-only "$base"...HEAD
git diff -z --name-only HEAD
git ls-files -z --others --exclude-standard
} 2>/dev/null
)
[ "${#files[@]}" -gt 0 ] || exit 0
# Map changed source files to the workspace dir that owns them (deduped).
# Stock macOS ships bash 3.2, which has no associative arrays (`declare -A`) and
# evaluates `arr[$d]` subscripts as arithmetic (slashes/hyphens in a path then
# blow up under `set -u`). So dedupe via a space-padded string match instead —
# `ws_dirs` stays a plain indexed array, which bash 3.2 handles fine.
seen=" "
ws_dirs=()
for f in "${files[@]}"; do
case "$f" in
*.js | *.mjs | *.jsx | *.ts | *.tsx) ;;
*) continue ;;
esac
d=$(dirname "$f")
while [ "$d" != "." ] && [ "$d" != "/" ]; do
if [ -f "$ROOT/$d/package.json" ]; then
case "$seen" in
*" $d "*) ;;
*)
seen="$seen$d "
ws_dirs+=("$d")
;;
esac
break
fi
d=$(dirname "$d")
done
done
[ "${#ws_dirs[@]}" -gt 0 ] || exit 0
fail=0
report=""
for d in "${ws_dirs[@]}"; do
# One jq read per package.json: name + which scripts exist. Every field is a
# non-empty token (the name falls back to "-", the flags to yes/no) so that
# `read` can't collapse an empty middle field — tab is IFS-whitespace, so a
# package with test-but-no-typecheck would otherwise shift the columns.
IFS=$'\t' read -r name tc te < <(
jq -r '[.name // "-",
(if .scripts.typecheck then "yes" else "no" end),
(if .scripts.test then "yes" else "no" end)] | @tsv' "$ROOT/$d/package.json"
)
[ "$name" != "-" ] || continue
if [ "$tc" = "yes" ]; then
if ! out=$(yarn workspace "$name" run typecheck 2>&1); then
report="$report"$'\n'"[typecheck failed: $name]"$'\n'"$(printf '%s' "$out" | tail -25)"
fail=1
fi
fi
if [ "$te" = "yes" ]; then
if ! out=$(yarn workspace "$name" run test 2>&1); then
report="$report"$'\n'"[tests failed: $name]"$'\n'"$(printf '%s' "$out" | tail -25)"
fail=1
fi
fi
done
if [ "$fail" -eq 1 ]; then
printf 'Stop check found failures in touched workspaces:%s\n' "$report" >&2
exit 2
fi
exit 0
@@ -0,0 +1,6 @@
---
category: Maintenance
authors: [MatissJanis]
---
Remove the agentic stop-hook (turn-end typecheck + test) from all agent platforms