Trigger Timing
- Add or change Git hooks in the Cursor Cloud Agent environment
Co-authored-by:Design the automatic addition and removal chain for- Organize coexistence of existing hooks such as lefthook with Cursor-managed hooks
Execution order
Cursor Cloud Agent は .git/hooks/<hook-name> を .dispatcher Replace via.commit-msg The execution order of is as follows:
- User hook —
.cursor-original-hooks-pathIf a hook with the same name exists at the path pointed to by (usually.git/hooks) execute it first - Cursor-managed hook —
$HOOKS_DIR/$HOOK_NAME.cursor*Execute sequentially in lexicographic order of file names
commit-msg Typical examples of:
| Order | File name | Role |
|---|---|---|
| 1 | commit-msg.cursor |
Secret scan (commit block) |
| 2 | commit-msg.cursor.co-author |
Co-authored-by: Automatically add |
| 3 | commit-msg.cursor.co-author-strip |
Co-authored-by: Remove lines (project strip hook) |
MUST: The base name of the strip hook is commit-msg.cursor.co-author-strip and name it so that it comes after in lexicographic order thancommit-msg.cursor.co-author . NEVER: Do not use names that are executed before co-author, such as commit-msg.cursor.strip-co-author .
strip hook implementation
- MUST: Place the removal logic in
.cursor/hooks/strip-co-authored-by.shplace in - MUST:
commit-msg.cursor.co-author-stripMake it a thin wrapper that calls the relevant script - MUST: The strip targets are
Co-authored-by:/Co-Authored-By:lines (case-insensitive) and the immediately preceding blank line - NEVER: Do not delete the commit message body (subject/description)
Reference implementation (.cursor/hooks/strip-co-authored-by.sh):
#!/usr/bin/env bash
set -euo pipefail
COMMIT_MSG_FILE="${1:?commit message file required}"
if [ ! -f "$COMMIT_MSG_FILE" ]; then
exit 0
fi
tmp="$(mktemp)"
trap 'rm -f "$tmp"' EXIT
awk '
BEGIN { skip_blank = 0 }
/^[Cc]o-[Aa]uthored-[Bb]y:/ { skip_blank = 1; next }
skip_blank && /^[[:space:]]*$/ { next }
{ skip_blank = 0; print }
' "$COMMIT_MSG_FILE" > "$tmp"
mv "$tmp" "$COMMIT_MSG_FILE"
trap - EXIT
install script
- MUST:
scripts/install-cursor-agent-hooks.shDeploy the strip chain to the Cursor hook directory with - MUST: The install destination is the actual directory where Cursor replaces
.git/hooks(the parent of the path resolved byreadlink -f .git/hooks, or used together with.git/hooks/.cursor-original-hooks-path) - MUST:
commit-msg.cursor.co-author-stripGrant execution permission to - IF: the install destination cannot be identified; THEN MUST: manually
$CURSOR_AGENT_HOOKS_DIRspecify and execute
lefthook defense in depth
- IF: the repository uses lefthook; THEN SHOULD:
commit-msgAdd the strip script to the job, and doubly with the Cursor hook chainCo-authored-by:remove - IF:
git-guard.shetc. withgit commit --no-verifydeny; THEN MUST: in the strip chain, without--no-verifywithoutCo-Authored-Bysatisfy the prohibition - IF: restrict force push with git-guard; THEN MUST: if history modification is required,
GIT_GUARD_ALLOW_FORCE_PUSH=1temporarily set and restore after work
Test procedure
- MUST:
scripts/install-cursor-agent-hooks.shExecute - MUST: Create a test commit and,
git log -1 --format=%BでCo-authored-by:/Co-Authored-By:verify that is not included - MUST:
githubskill'sCo-Authored-Byverify that it does not contradict the prohibition rule - IF: use lefthook; THEN MUST:
lefthook run commit-msg --commit-msg-file /tmp/test-msgunit-verify strip with
Related skills
github: commit author specification,Co-Authored-Byprohibited, hook bypass prohibitedskill-escalation: upstream proposal for skill modificationrefresh-skills: consistency check when adding skills