Paths Subjects Questions Quizzes Pricing Search
Advanced Open Free

Hardening an Overnight Fix Across a Monorepo

An engineer wants to leave a headless run going overnight in a large monorepo: claude -p "find and fix every call site still using the deprecated retry helper across packages/api and packages/web, commit each fix", run in auto mode, unattended. They plan to check the results in the morning.

  1. Identify three distinct gaps in this plan as described — one about what the run is allowed to touch, one about how it knows it's actually done, and one about the codebase's scale — and explain the concrete failure each gap could cause by morning.
  2. Propose a hardened version of the command and setup that closes all three gaps. Be specific about flags, settings, or scoping mechanisms, not just "add safety."
  3. The engineer says: "auto mode already reviews every action, so I don't need an allowlist too." Explain concretely why that reasoning is incomplete.
Solution

1. Three gaps and their failure modes:

  • What it's allowed to touch. Nothing in the command scopes the run's tools. Left as-is, a run that hits an unexpected situation (a call site inside a migration file, a test that needs regenerating) can reach for any tool it has access to, including ones far outside "fix call sites and commit" — by morning that could mean commits well beyond the intended scope, or a run that touched files nobody wanted touched.
  • How it knows it's done. "Fix every call site... commit each fix" is a one-off instruction with no verification target — Claude stops each fix when it looks fixed, with nobody there to notice a fix that compiles but changes behavior. By morning, some fraction of the "fixed" call sites could be subtly wrong with no evidence generated to catch it.
  • The codebase's scale. This is a monorepo, and the command gives Claude no scoping beyond the two package names in the prompt. Without directory-level scoping, the run's search and read behavior can wander into unrelated packages' files, generated/vendored code, or simply cost far more context (and tokens) per fix than necessary — by morning, cost and noise are both higher than the two-package scope of the actual task warranted.

2. A hardened version:

Scope the run's tools and budget, and give it a real verification gate:

claude -p "find and fix every call site still using the deprecated \
retry helper in packages/api and packages/web. For each fix, run \
that package's test suite and only commit if it passes. Report any \
call site you could not fix with a passing test, do not commit it." \
--allowedTools "Edit,Bash(npm test *),Bash(git commit *),Bash(git diff *)" \
--max-turns 60 \
--max-budget-usd 5 \
--output-format json

This closes the three gaps: --allowedTools bounds what the run can touch to editing and the specific test/commit commands it needs (not an open-ended Bash allowance); --max-turns and --max-budget-usd cap how far a run that goes wrong can go before something stops it; and requiring a passing test suite per fix before committing turns "looks fixed" into an actual pass/fail gate, with the report-only instruction for anything that doesn't pass giving the engineer morning-review evidence instead of an unverified commit. On the scale gap: the repository's permissions.deny should already block reads of generated/vendored paths (Read(./**/dist/**), etc.), and if this is a task the team runs repeatedly, worktree.sparsePaths scoped to packages/api and packages/web keeps any worktree the run creates from checking out the rest of the monorepo.

3. Why "auto mode is enough" is incomplete:

Auto mode's classifier blocks categories of risky action — scope escalation, unknown infrastructure, hostile-content-driven behavior — but it is a probabilistic reviewer making a judgment call on each action, not a guarantee, and the docs are explicit that it reduces prompts without guaranteeing safety. An allowlist (and explicit deny rules) is a deterministic, pre-committed boundary that doesn't depend on a classifier correctly recognizing a specific action as risky in the moment — it simply doesn't let a non-allowlisted command run unattended at all. The two are complementary layers, not substitutes: auto mode catches things you didn't think to write a rule for, and the allowlist holds even if auto mode's judgment call on a specific action turns out to be wrong.

Share this question

← Back to Claude Code Best Practices: Reliable, Cheap, High-Leverage Sessions practice

We use cookies for product analytics to improve OmniAtlas. See our Privacy Policy.