SuperAPI AI Directory

cursor-hook-authoring

Coding & development

View repository

Updated 10-15 23:42

About this skill

Cursor Hook Design

Trigger Timing

  1. Add or change Git hooks in the Cursor Cloud Agent environment
  2. Co-authored-by: Design the automatic addition and removal chain for
  3. Organize coexistence of existing hooks such as lefthook with Cursor-managed hooks
Git hook and Cursor Cloud commit-msg chain

Execution order

Cursor Cloud Agent は .git/hooks/<hook-name> を .dispatcher Replace via.commit-msg The execution order of is as follows:

  1. User hook — .cursor-original-hooks-path If a hook with the same name exists at the path pointed to by (usually .git/hooks) execute it first
  2. 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

  1. MUST: Place the removal logic in .cursor/hooks/strip-co-authored-by.sh place in
  2. MUST: commit-msg.cursor.co-author-strip Make it a thin wrapper that calls the relevant script
  3. MUST: The strip targets are Co-authored-by: / Co-Authored-By: lines (case-insensitive) and the immediately preceding blank line
  4. 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

  1. MUST: scripts/install-cursor-agent-hooks.sh Deploy the strip chain to the Cursor hook directory with
  2. 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 )
  3. MUST: commit-msg.cursor.co-author-strip Grant execution permission to
  4. IF: the install destination cannot be identified; THEN MUST: manually $CURSOR_AGENT_HOOKS_DIR specify and execute

lefthook defense in depth

  1. IF: the repository uses lefthook; THEN SHOULD: commit-msg Add the strip script to the job, and doubly with the Cursor hook chain Co-authored-by: remove
  2. IF: git-guard.sh etc. with git commit --no-verify deny; THEN MUST: in the strip chain, without --no-verify without Co-Authored-By satisfy the prohibition
  3. IF: restrict force push with git-guard; THEN MUST: if history modification is required, GIT_GUARD_ALLOW_FORCE_PUSH=1 temporarily set and restore after work

Test procedure

  1. MUST: scripts/install-cursor-agent-hooks.sh Execute
  2. MUST: Create a test commit and,git log -1 --format=%B で Co-authored-by: / Co-Authored-By: verify that is not included
  3. MUST: github skill's Co-Authored-By verify that it does not contradict the prohibition rule
  4. IF: use lefthook; THEN MUST: lefthook run commit-msg --commit-msg-file /tmp/test-msg unit-verify strip with

Related skills

  • github: commit author specification,Co-Authored-By prohibited, hook bypass prohibited
  • skill-escalation: upstream proposal for skill modification
  • refresh-skills: consistency check when adding skills