Loading…

Shift-Left Guardrails for AI Coding Agents: Run Your Rules on Every Edit | DATASPHERES AI - Dataspheres AI

Feed your repo's rules to your AI coding agent after every edit, then roll it out across every developer, laptop, sandbox and cloud agent - Claude Code, Codex, Cursor, Copilot, Windsurf, Aider and Cline.

Your repo already knows its rules. The trick is telling your AI coding agent the moment it breaks one, not fifteen minutes later at commit time. The problem: the agent finds out too late Most mature codebases have rules beyond "it compiles": a linter, accessibility checks, "no fixed sleeps in end-to-end tests", "every button needs an accessible name", "database access goes through one module". Those rules usually run in one place, the pre-commit hook , because that is where humans meet them. An AI coding agent works differently. It writes dozens of files in a few minutes, runs the type checker and the tests it knows about, and declares victory. Then the commit gate runs, a full suite that can take ten or fifteen minutes, and fails on a rule the agent never saw while it was writing. It fixes that one, commits again, waits again, and fails on the next one. We watched exactly this happen: three commit attempts in a row, about fifteen minutes each, blocked by: a clickable image with no keyboard handler (an accessibility lint rule); new clickable elements missing the tag that lets an in-app assistant find and press them; three new tests that waited a fixed 600 ms instead of waiting for something to happen. None of these was hard to fix. Each took seconds once seen. The cost was entirely in when the agent saw them. The idea: same rules, three moments Don't invent new rules for the agent. Run the rules you already have at three moments: After every edit : the fast, per-file checks, on the file just changed, with failures fed straight back to the agent as part of the tool result. Before the agent says "done" : the same checks over every file changed in the session. Optional, but it catches anything that slipped through. At commit : the full gate, unchanged, as the backstop for humans, other tools and anything the first two missed. The commit gate keeps the slow things (the full test suite, migrations, repo-wide ratchets). The edit-time check carries only what is fast enough to run in a second or two per file. Design one checker, call it from everywhere Write a single script, say scripts/check-changed , and make every agent's hook call it. The rules live in one place. The hooks are just thin adapters. Five properties make the difference between a guardrail people keep and one they rip out within a week: Judge only what the agent added. Compare the file with the last commit ( git show HEAD:path ) and report only findings on new or changed lines. Otherwise touching one line of a legacy file drowns the agent in old debt, and it learns to ignore the hook. Be fast. Lint one file, not the project. Run your custom rules on one file. Keep repo-wide checks for those that are genuinely cheap. Aim for under three seconds. Speak to the agent, not to a CI log. Print file:line [rule] what is wrong , one line each, then one sentence on how to fix it or how to mark a deliberate exception. Fail open on your own bugs. If the checker crashes, exit cleanly. A broken guardrail must never stop all editing. Use the "block" exit code for real findings. In most agent tools that is exit 2 with the message on stderr. That is the signal that puts the text in front of the model. A minimal shape, in any language: read the hook payload (JSON on stdin) files = the edited file, or every source file a shell command changed for each file: added = line numbers that differ from HEAD findings += lint(file) filtered to added lines findings += custom_rules(file) filtered to added lines if findings: print findings to stderr exit 2 exit 0 Two gaps that will bite you 1. Edits made through the shell. Agents don't only edit through their edit tool. They also run sed , small Python scripts and code generators. An edit hook never sees those. Cover the shell too: record the time when a shell command starts (a pre-tool hook), and afterwards check the source files modified since then ( git ls-files -m -o --exclude-standard , filtered by modification time). If other processes write in the same folder, skip long-running commands. A fifteen-minute test run will otherwise sweep in other people's files. 2. Where the agent was started. Project hook files are usually read from the folder the agent was launched in. Start the agent in a parent folder that contains several repos and the repo's own hooks may silently never load. That is exactly what had happened to us: the repo already had a write-time rule check, and it never ran. Either always launch the agent in the repo root, or add a user-level or parent-level hook that calls the repo's checker by absolute path. Have the checker find the repo from the edited file's path, not from the current directory. Wiring it up, tool by tool Hook systems have converged quickly, but they change fast. Treat the snippets below as the shape, and check your version's documentation for exact field names. Claude Code Hooks live in .claude/settings.json (shared with the team, committed), .claude/settings.local.json (personal) or ~/.claude/se