AGENT SKILL

guard-git

Block dangerous git commands (push, force push, reset --hard, clean, branch -D, checkout/restore .) and enforce Conventional Commits & Branch Protection before an AI agent runs them. Installs hook scripts for Claude Code, Cursor, Cursor CLI, and Gemini CLI; documents Google Antigravity Terminal deny lists. Use when the user wants git safety hooks, to block git push or destructive git in agents, or to mirror the same policy across AI coding tools.

适用职业开发工程师
License 许可
MIT
最近更新
2026-11-10
Stars
★ 290
Forks
24

01 前言 Front Matter

name
guard-git
model
haiku
description
Block dangerous git commands (push, force push, reset --hard, clean, branch -D, checkout/restore .) and enforce Conventional Commits & Branch Protection before an AI agent runs them. Installs hook scripts for Claude Code, Cursor, Cursor CLI, and Gemini CLI; documents Google Antigravity Terminal deny lists. Use when the user wants git safety hooks, to block git push or destructive git in agents, or to mirror the same policy across AI coding tools.

03 SKILL.md 正文

Guard Git

HARD GATE — HARD GATE — Before committing, verify: branch is not main/master, author is correct, git user is configured. Bad commits are hard to fix.

Installs a shared hook that blocks destructive git operations and enforces workflow discipline. Requires jq on the agent's PATH when the hook runs.

What gets blocked/enforced

  • Safety: force push (-f, --force, +refspec), reset with --hard, clean with any -f*, branch -D / --delete --force, checkout/restore that discard work (-f, . pathspec).
  • Argv, not substrings: the hook tokenizes each command, strips git's global options (-C <path>, -c k=v, --no-pager, --git-dir=…) and judges the (subcommand, arguments) pair — so git -C repo reset -q --hard is blocked, while git push --force-with-lease is allowed. Rules live in scripts/lib/git-argv.py, mirrored in extensions/omp-hooks.ts; scripts/test-guard-git-normalize.sh fails if the two disagree.
  • Discipline: Blocks direct commits or pushes to protected branches (main, master) unless GIT_BIGPOWERS_LAND=1 (set only by scripts/land-branch.sh).
  • Allows: git push origin <feature-branch> for backup/CI; solo land push to main only inside land-branch.sh.
  • Standardization: Enforces Conventional Commits for all git commit commands.
  • Secrets: Blocks commits containing common secret patterns (sk-, ghp_, AKIA, xoxb-, -----BEGIN private keys) — see REFERENCE.md.

Quick start

  1. Scope: ask project-only vs global (paths differ per product).
  2. Write the hook bundle from REFERENCE.md into the client's hooks directory.
  3. Run chmod +x on pre-tool-use.sh.
  4. Merge the hook snippet from REFERENCE.md into the right settings file — do not wipe unrelated keys.
  5. Verify with the tests in REFERENCE.md.
Client Mechanism Config
Claude Code PreToolUse (Bash) .claude/settings.json or ~/.claude/settings.json
Cursor / Cursor CLI beforeShellExecution .cursor/hooks.json or ~/.cursor/hooks.json
Gemini CLI BeforeTool + run_shell_command .gemini/settings.json or ~/.gemini/settings.json
Google Antigravity Built-in Terminal Deny list Settings UI (no shell hook)

Modes (env on the hook command): GIT_GUARDRAILS_MODE is claude (default) or cursor → stderr + exit 2 on block. Set gemini for Gemini CLI → JSON decision on stdout.

Customization

The rule table lives in scripts/lib/git-argv.py (shell hooks) and is mirrored in extensions/omp-hooks.ts. Add a rule to both and a row to specs/verifications/fixtures/guard-git-normalize.yaml.

The TS side is judged through evaluateBashCall() — the single pure function the tool_call handler calls — so the fixture covers every rule (destructive argv, protected-branch push, Conventional Commits), not just the argv table. The gate (bash scripts/test-guard-git-normalize.sh) runs both implementations with GIT_BIGPOWERS_LAND unset and fails if they disagree, so a verdict can never depend on the developer's shell.

Protected-branch rules answer differently on main than on a feature branch, so a row that touches commit/push semantics states its branch: and both sides are run in it (the shell hook in a throwaway repo checked out on that branch). A row without branch: is judged on a feature branch. Do not pin the branch inside either implementation — that is what made the gate pass on PRs and fail on main.

Advanced

Full JSON examples, merge rules, Antigravity deny-list entries, and test commands: REFERENCE.md.

<!-- story: e01s03 -->


Git guardrails — reference

Navigation

Lines Section
1 Title
3–16 Navigation
17–28 Secret patterns (audit + pre-commit)
29–46 Copy layout
47–72 Claude Code
73–94 Cursor and Cursor CLI
95–122 Gemini CLI
123–137 Google Antigravity
138–180 Verify (local tests)

Secret patterns (audit + pre-commit)

Agents must not commit files containing:

  • sk- (OpenAI API keys)
  • ghp_ / gho_ (GitHub tokens)
  • AKIA (AWS access key id)
  • xoxb- (Slack bot tokens)
  • -----BEGIN private keys

Use audit-code supply-chain checklist before commit. Consider git-secrets or custom pre-commit hook in target projects.

Copy layout

The main script is pre-tool-use.sh.

<hooks-dir>/pre-tool-use.sh

Example project locations:

  • Claude: .claude/hooks/
  • Cursor: .cursor/hooks/
  • Gemini: .gemini/hooks/

Use the same layout for user-level hooks (~/.claude/hooks, ~/.cursor/hooks, ~/.gemini/hooks).


Claude Code

Hook command does not need GIT_GUARDRAILS_MODE (defaults to claude).

Project (.claude/settings.json):

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/pre-tool-use.sh"
          }
        ]
      }
    ]
  }
}

Cursor and Cursor CLI

Use beforeShellExecution. Set GIT_GUARDRAILS_MODE=cursor.

Project (.cursor/hooks.json):

{
  "version": 1,
  "hooks": {
    "beforeShellExecution": [
      {
        "command": "GIT_GUARDRAILS_MODE=cursor .cursor/hooks/pre-tool-use.sh",
        "matcher": "git"
      }
    ]
  }
}

Gemini CLI

Use BeforeTool with matcher run_shell_command. Set GIT_GUARDRAILS_MODE=gemini.

Project (.gemini/settings.json):

{
  "hooks": {
    "BeforeTool": [
      {
        "matcher": "run_shell_command",
        "hooks": [
          {
            "name": "git-guardrails",
            "type": "command",
            "command": "GIT_GUARDRAILS_MODE=gemini \"$GEMINI_PROJECT_DIR\"/.gemini/hooks/pre-tool-use.sh",
            "timeout": 5000
          }
        ]
      }
    ]
  }
}

Google Antigravity

Add Deny list entries in Antigravity → Settings → Terminal:

  • git push --force
  • git push origin main
  • git push origin master
  • git reset --hard
  • git clean
  • git branch -D
  • git checkout .
  • git restore .

Verify (local tests)

1. Block push to main without land mode (Claude mode):

echo '{"tool_input":{"command":"git push origin main"}}' | ./pre-tool-use.sh
# Expected: exit 2, protected branch message

2. Allow push to main with GIT_BIGPOWERS_LAND=1:

GIT_BIGPOWERS_LAND=1 echo '{"tool_input":{"command":"git push origin main"}}' | ./pre-tool-use.sh
# Expected: exit 0 (when on main)

3. Allow push to feature branch:

echo '{"tool_input":{"command":"git push -u origin feat/my-task"}}' | ./pre-tool-use.sh
# Expected: exit 0

4. Conventional Commits (Gemini mode):

echo '{"tool_input":{"command":"git commit -m \"bad message\""}}' | GIT_GUARDRAILS_MODE=gemini ./pre-tool-use.sh
# Expected: exit 0, {"decision":"deny", "reason":"..."}

5. Protected Branch commit (Cursor mode):

# Run on 'main' branch
echo '{"command":"git commit -m \"feat: valid message\""}' | GIT_GUARDRAILS_MODE=cursor ./pre-tool-use.sh
# Expected: exit 2, "Direct commits to protected branch 'main' are forbidden"

6. Land script exists:

test -x scripts/land-branch.sh && echo OK

7. Allow (Gemini mode):

echo '{"tool_input":{"command":"git status"}}' | GIT_GUARDRAILS_MODE=gemini ./pre-tool-use.sh
# Expected: exit 0, {"decision":"allow"}

04 同仓库更多 Skills