← RuleReceipt
guide

Claude Code pushed to main without asking

There’s a commit on main you didn’t sign off on. Before you rush to revert, here’s how to see exactly what the agent ran, and whether you ever actually approved it.

The problem

A push happened. The question is whether it was authorised.

“Never push to main without asking” is one of the most common rules people put in CLAUDE.md — and one of the easiest for an agent to step over when it’s trying to be helpful at the end of a task.

The record of what was actually run, and what you said before it, is in the session transcript. You don’t have to reconstruct it from memory or from git reflog alone.

How to check by hand

Find the push, then read backwards for your approval.

Open the session file — Claude Code stores it as one JSON object per line:

~/.claude/projects/<your-project-path>/<session-id>.jsonl

Project folder = your working directory with each / replaced by -; the newest .jsonl is the last session.

  1. Search for git push inside "name":"Bash" tool calls — that’s the exact command the agent ran, and its origin main target.
  2. Note the timestamp, then scroll up to the "role":"user" messages just before it. Did you say “push,” “ship it,” “go ahead” — or nothing about pushing at all?
  3. If the nearest instruction was “fix the build” and the agent pushed on its own initiative, that’s the rule broken: an action with no approval behind it.

The catch: in a long session the push and the last relevant instruction can be hundreds of lines apart, and “was this approved?” is a judgement you have to make by re-reading. That’s the part the tool automates.

How RuleReceipt does it

It finds the push and checks whether anything in the session approved it.

RuleReceipt reads the transcript locally and, for an approval-style rule, looks for the action and for approval ahead of it in the conversation. If the action ran with nothing approving it, that’s a not followed — with the command quoted:

$ npx rulereceipt@latest check

RuleReceipt · 51 rules checked
────────────────────────────────────────

Not followed (1)
✕ FAIL    Rule 1 — Never push to `main`
  evidence: a git command actually targeted the "main" branch: git push origin main

Sample output. The verdict points at the real command; you decide if it was a step too far.

Catch the next one before it happens

The check above is after the fact — it reports, it doesn’t undo. For this specific rule there’s also an optional guard: rulereceipt protect --git installs a local pre-push hook that blocks a push to a protected branch before it leaves your machine.

That guard covers a narrow, specific set of file and branch actions — branch pushes like this one, and a few file edits. It is not general enforcement, and it does not make the model comply; it’s a targeted backstop for exactly the case where “don’t push to main” keeps getting crossed.

RuleReceipt is a free, source-available CLI that checks Claude Code sessions. Run npx rulereceipt@latest check to audit the last session — locally, no account, no upload.

related