Sentinels: The Quiet Power of a Touched File A developer uses sentinel files—empty files on disk—to gate risky actions by coding agents, such as exiting plan mode or opening pull requests. The sentinel acts as a durable state outside the agent's volatile context window, checked by hooks that block or allow actions based on the file's presence. This pattern prevents agents from making irreversible moves without explicit precondition verification. Sentinels: The Quiet Power of a Touched File How I use sentinel files to gate the risky moves my coding agents make—exiting plan mode, opening a pull request, addressing review feedback, backing off a rate-limited model. The whole mechanism is a file on disk and a hook that checks for it. You know what’s really annoying? When you write some instructions in AGENTS.md or CLAUDE.md and then the agent ignores them. Absolutely rage-inducing. I spend a lot of time thinking about the architecture and design of a given project, defining the tasks, adding acceptance criteria and all of that fun stuff. In a perfect world, if I do all of that planning up front, I should be able to let agents do a lot of unsupervised work. They plan, they write code, they open pull requests, they grind through review feedback until CI goes green. Most of that is fine to run on autopilot. But, a handful of moves are the kind you don’t get to take back cleanly. Exiting plan mode and committing to an approach. Running gh pr create and putting a half-baked PR in front of a human who trusts me. Hammering a model’s API right after it told me to slow down. Those are the moments where I want a gate—something that says “you may not do this yet, and here’s exactly what has to be true first.” Ask me how many times I’ve watched an agent cheerfully open a PR the second I looked away. The thing I keep reaching for to build those gates is almost embarrassingly simple or, at least it took me way too long to arrive at this station . It’s a file. An empty one, usually. The presence of the file means “the precondition was met”; its absence means “not yet, go do the work.” We call these sentinels , and once you start seeing them as a coordination primitive instead of a hack, they show up everywhere in my setup. A confession about scope This is how I wired up my own Claude Code https://code.claude.com/docs/ skills and hooks. It’s not a framework or a thing you install. It’s a pattern, and the pattern is what I want you to walk away with—not my exact file paths. Also, I am constantly tweaking all of this stuff and whatever I include here will be woefully out of date in a matter of weeks—or days, possibly. If y’all hassle me enough, maybe I’ll add a gist https://gist.github.com or something. What a sentinel actually is Here’s the thing the fancy word is hiding: a sentinel is just a piece of state that lives outside the conversation. The agent’s context window is volatile—it gets summarized, compacted, thrown away between iterations. Disk doesn’t. So when I need one step to leave a durable signal that a later step can check, I write a file. The check is a hook https://code.claude.com/docs/en/hooks : a small script the harness runs at specific moments in the agent’s lifecycle—before a tool call, when the agent exits plan mode, when it tries to stop—and which can look at the filesystem and decide whether to let that moment proceed. Crucially, a hook runs in the harness, not in the agent, so it’s a check the agent can’t simply reason its way past. That’s the whole shape of it. One side produces the file, the other side blocks until it exists. If you’ve ever used a .lock file, a PID file, or a CI job that won’t deploy until a build-succeeded artifact shows up, you basically already have the gist. The novelty here isn’t the mechanism—it’s pointing it at a non-deterministic agent. Here’s why that matters. I can’t trust the agent to remember that it ran a review three messages ago, because three messages ago might not exist anymore. But I can absolutely trust that a file is on disk. The sentinel moves the proof out of the model’s head and into a place the model can’t accidentally forget. Don’t leave plan mode until Codex signs off The first place this earned its keep is my plan-review gate. When an agent is in plan mode, it’s drafting an approach but hasn’t been allowed to touch anything yet. Exiting plan mode is the commitment—the moment it stops planning and starts doing. I don’t want that to happen until a second model— Codex https://developers.openai.com/codex/ , a different model family I call out to from my own skills—has adversarially picked the plan apart and grudgingly approved it. So there’s a hook on the ExitPlanMode tool. Before the agent is allowed to exit, the hook hashes the plan text and looks for a file named for that hash: tmp/plan-review/plan-