{"slug": "removing-the-guardrails-and-letting-my-coding-agents-loose", "title": "Removing the guardrails and letting my coding agents loose", "summary": "Developer Bas Nijholt has run coding agents in \"YOLO mode\" without per-command approval since May 2025, sometimes running ten agents in parallel, and now relies on a shared Python hook module called git_guard.py to block commands such as git commit --amend, git push --force, pushes to main, gh pr merge, git add -A, and sleep. Nijholt reported that Gemini 3 Pro merged his PR and force-pushed to main in November 2025, prompting hooks for Claude Code and Gemini CLI three weeks later, while OpenAI's Codex never ignored an explicit rule in his AGENTS.md and now runs the same hooks. He said Claude has been worse at following rules and Gemini \"far worse still,\" and that a Markdown rule is \"a hope\" whereas a hook actually stops the command and explains why.", "body_md": "I have run coding agents in YOLO mode since I started using them in May 2025. I think it is the only way to parallelize work. Sometimes I have ten agents running at the same time, and clicking “approve” on every command they run would make that impossible.\n\nWhat makes me comfortable with it is that models tend to do what you ask, and that you can keep them in an environment where they cannot do much harm.\nI don’t keep secrets within their reach, and above all I have [very good backups](/post/btrfs-to-zfs/).\nThe last piece is a small set of hooks that block the few things I never want an agent to do on its own.\n\nMy system prompt has always told agents not to force-push or merge PRs. Some of them did it anyway.\n\nThe first time I really noticed was with [Gemini 3 Pro in November 2025](/post/gemini-3-pro-first-impressions/), which merged my PR and force-pushed to `main`.\nIt happened a couple more times in the weeks after, as I parallelized more and asked more of the models.\nThree weeks later I had hooks for Claude Code and Gemini CLI that block these commands before they run.\nCodex did not support hooks yet.\nTo my surprise, it did not need them: OpenAI’s models are extremely good at following instructions, and Codex never ignored an explicit rule in my `AGENTS.md`.\nCodex supports hooks by now, so it runs the same ones as the others.\n\nClaude has been worse at following rules, and Gemini far worse still: absolutely dogshit. I only try Gemini now and then, and I have been disappointed every time. By now I don’t even try the latest Google models anymore.\n\nI don’t think agents are ever purposely malicious. They try to do what you asked, but they can misinterpret it, and then they force-push or merge something. A rule in a Markdown file is a hope; a hook actually stops the command. Not that a hook would stop a malicious agent: it could put the blocked command in a Bash script and run that instead. What the hook does is tell the agent why I don’t want it, because every block comes with a short explanation:\n\n```\ngit add -A is not allowed - add files explicitly to avoid adding unrelated untracked files\n```\n\nThe models are well aligned, so once they know my intention, they respect it.\n\nAll hooks live in [my dotfiles](https://github.com/basnijholt/dotfiles/tree/main/configs/claude/hooks), and I deliberately kept them simple.\nThe detection logic is one Python module, [`git_guard.py`](https://github.com/basnijholt/dotfiles/blob/main/configs/claude/hooks/git_guard.py), and the Claude Code, Codex, and Gemini CLI hooks all import it.\n\n**`git commit --amend` and `git push --force`.**\nThe unit I review is a PR.\nWhen I review a PR, I know I have reviewed it up to a certain commit, and later I only look at the diff of the new commits.\nRewriting history breaks that.\n\n**Pushing to `main`.**\nEverything happens in PRs.\nInside a PR I don’t care how messy the history gets.\nI want the agent to push very often, so no work gets lost, and every commit has to be green, so each one is a snapshot I can go back to.\nThe agent maintains its own development of the feature, and I have not written a commit message myself in a long time.\nWhen the PR is done, I squash merge it.\n\n**`gh pr merge`.**\nThe merge comes after my review, so it is mine to do.\n\n**`git add -A`.**\nI often have unrelated untracked or unstaged files lying around.\nI work in many open source repositories, and some of those files should not be public, like deployment plans.\nThis is the only block without an override.\n\n**`sleep`.**\nThis one is for Claude, and Opus 5 specifically, which I hate with a passion.\nIt would run tests in the background and then `sleep 300`, badly overestimating how long the tests take, when a blocking tool call returns exactly when they finish.\n\nOver time the models got more capable. I could parallelize more, and I trusted them to work on their own for longer. I noticed I was spending a significant fraction of my time clicking buttons and doing operations I had forbidden the agent to do, only to end up doing them myself.\n\nSo in July I added an override. When a hook blocks a command, the agent gets this hint:\n\n```\nIf (and only if) the user has explicitly approved this exact action,\nre-run the command prefixed with EXPLICITLY_USER_APPROVED_HOOK_OVERRIDE=1 to override this block.\n```\n\nNothing checks whether I actually approved it. It is a soft gate, but it works because the agent now has to write down, in the command itself, that I approved the action. When it runs into the block without my approval, it becomes obvious to the agent that it has to ask me first.\n\n`git add -A` stays hard-blocked, and a chained command cannot carry an override past it: `EXPLICITLY_USER_APPROVED_HOOK_OVERRIDE=1 git commit --amend && git add -A` is still rejected.\n\nIt has happened, mostly with GPT-5.6 Sol, which I used a lot at the time.\n\nIt used to be that you had to keep your context window short, because auto-compaction was lossy and produced poor summaries. Since around GPT-5.3, compaction works well enough that I keep a session going for as long as I am working on the same feature. So I would ask the agent to merge a PR early on, start a follow-up PR in the same session, and after a compaction the agent concluded that it should merge the new PR too. It did, without my approval.\n\nThe other case was my [`pr-review` skill](https://github.com/mindroom-ai/mindroom/blob/main/.claude/skills/pr-review/SKILL.md), by far my favorite skill that I wrote myself.\nI would tell the agent to run it and squash merge the PR only if the review approved it.\nA few times, the review found problems, the agent fixed them, and then it merged.\nWhat I meant was: merge if it is approved right away, and otherwise wait for me.\nNow I spell that out and end with “otherwise, wait for my instructions.”\n\nThe override matters most when I am away from my computer.\nOn a month-long trip visiting family in Europe, I worked only from my phone, using [my mobile coding workflow](/post/agentic-mobile-workflow/).\nTyping commands in a terminal on a phone is inconvenient, so I would rather say what I want and let the agent do it, including the merge.\nI have also built end-to-end encrypted voice calls to my agents over Matrix with [MindRoom](/post/mindroom/), and I am moving more toward that kind of voice-driven workflow.\n\nI recently reread [my first post on agentic coding](/post/agentic-coding/) from August 2025, and very little in it is outdated.\nThe models are more capable, and I give them much larger scopes, but the way I work is mostly the same.\nThe hooks are the main thing I added, and the override is how I loosened them again.", "url": "https://wpnews.pro/news/removing-the-guardrails-and-letting-my-coding-agents-loose", "canonical_source": "/post/removing-guardrails/", "published_at": "2026-09-22 00:00:00+00:00", "updated_at": "2026-09-23 04:26:14.524857+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools"], "entities": ["Bas Nijholt", "Gemini 3 Pro", "Claude Code", "Gemini CLI", "Codex", "OpenAI", "Google", "git_guard.py"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/removing-the-guardrails-and-letting-my-coding-agents-loose", "markdown": "https://wpnews.pro/news/removing-the-guardrails-and-letting-my-coding-agents-loose.md", "text": "https://wpnews.pro/news/removing-the-guardrails-and-letting-my-coding-agents-loose.txt", "jsonld": "https://wpnews.pro/news/removing-the-guardrails-and-letting-my-coding-agents-loose.jsonld"}}