← failproof.ai
guide·may 15, 2026·7 min read

how to prevent ai agent force push

block-force-push refuses git push --force and -f variants. block-push-master refuses pushes to main and master. block-work-on-main refuses commits, merges, and resets on protected branches. three PreToolUse hooks, one install command, works across claude code, codex, cursor, gemini cli, copilot, picode, and opencode.

“cursor force pushed to main”

The screenshot makes the rounds every few weeks. A cursor agent that force-pushed to main and rewrote two days of teammate commits. A claude code session that destroyed months of work with one “clean up the branch” rebase. A codex run that pushed +HEAD:mainto bypass a server-side check. The agent was not malicious - it hit a conflict, decided force was the cleanest exit, and the harness happily ran it. What stops this is not a longer prompt. it's a hook that reads the literal git command and refuses on --force, -f, --force-with-lease, and the +ref protocol-level form before the push leaves your machine.

Why ai agents force-push by accident

Force push is rarely the agent's plan - it's the agent's way out of a tangle. The model rebased, hit a conflict, decided the cleanest fix was git push --force. Or the remote moved and the model interpreted the rejection as a permissions problem. Either way the destination is a rewritten history that other engineers already pulled.

Server-side branch protection on github catches some of this, but not all of it: protection rules vary across repos, sometimes don't apply to admins, and only fire after the push has already left your laptop. Hooks catch it on the agent side, before the push leaves.

Install (60 seconds)

The git policies are on by default. Confirm with failproofai policies - you should see block-force-push, block-push-master, and block-work-on-main in the enabled list.

The three git-safety policies

block-force-push

Refuses every form of force push:

  • git push --force, git push -f
  • git push --force-with-lease, git push --force-if-includes
  • Push commands that include +ref:ref refspecs (which force the push at the protocol level)
  • Wrapped invocations: git push origin +HEAD:main, git -c receive.denyNonFastForwards=false push …

block-push-master

Refuses any push targeting a protected branch. Default protected set: main and master. Add release/*, deploy/*, or specific branch names from the dashboard.

block-work-on-main

Refuses commits, merges, resets, and rebases while the working tree is on a protected branch. Stops the destructive operation from accumulating in the first place - when the model tries to commit on main, failproof aborts the call and the agent learns to check out a feature branch first.

The git category also ships three warnings - they don't hard-block, they instruct. Useful when you want the agent to slow down rather than stop:

  • warn-git-amend - instructs caution before git commit --amend on a published commit
  • warn-git-stash-drop - requests confirmation before git stash drop
  • warn-all-files-staged - alerts when running git add -A or git add . (which sweeps in secrets and build artifacts more often than people realize)

Any warning can be promoted into a hard block from the dashboard without writing code.

What the agent sees when a push is blocked

block-force-push returns a structured deny:

refused: git push --force. force pushes rewrite history other people may have pulled. push the branch under a new name, or ask the user to confirm an interactive rebase.

The model receives this message back in the tool result. Most agents will then propose an alternative - a new branch, a merge instead of a rebase, asking the user - rather than looping on the same denied call. That is repair, not retry.

One policy, every agent

The same block-force-push behaves identically across every supported agent harness:

  • Claude Code (Anthropic CLI + SDK)
  • OpenAI Codex (CLI + agent runtime)
  • Cursor Agent
  • Gemini CLI
  • GitHub Copilot CLI
  • picode
  • opencode

Goose and deep agents are on the roadmap. You don't pick a different policy per harness - failproof ai subscribes to whatever hook surface the harness exposes, runs the same engine, and the git rules behave the same way.

Get started

book a demo →