Skip to content

The automated safety net

This page covers the automatic guards the base runs for you without your having to memorize any command. If somewhere in the workflow you see “something showed up on screen that I never asked for” or “the AI suddenly stopped a commit,” it is almost always one of the things listed here.

Learn once what happens automatically, and the next time you see the same behavior you move to the next step instead of getting thrown.

The .claude/hooks/ folder holds three shell scripts. Whether each is active is decided in .claude/settings.json. The base ships them all wired up, and they work from the start without your touching anything.

FileWhen it runsIn one line
session-start.shWhen you open a new Claude Code sessionHands the AI “where you left off” automatically
stop-reminder.shWhen the AI’s response endsNudges you to “jot one line for next session”
pre-commit-check.shRight before the AI issues a git commitRuns typecheck and lint first to block broken code

The first — the AI does not ask where you stopped yesterday

Section titled “The first — the AI does not ask where you stopped yesterday”

That is what session-start.sh does. Open a fresh Claude Code window and this script runs first, automatically showing the AI these files.

  • active.md: the “next task” the previous session left
  • progress.md: recent progress history
  • feature_list.json: the list of test cases and whether they pass
  • docs/design/e2e-spec.md: app overview and critical flows
  • MEMORY.md: the project decision cache index

Healthy shape: open a new session and the contents of those files are all there in the first message. You can say “continue” and the AI starts the next step from that seat.

Silent the first time: right after you get the base, the first session has none of those files yet. So the script prints nothing and quietly bows out. At that point the /start router creates the empty templates for you.

The second — it reminds you to jot one line

Section titled “The second — it reminds you to jot one line”

That is what stop-reminder.sh does. When the AI’s response ends, if active.md is empty, it shows you a short nudge. Something like “jot one line for next session and picking up will be easier.”

This is the seat non-developers leave blank most often. The habit of noting what to do next is not in place yet, so they just close the window. Then the next session’s auto-restore seat starts blank, and the AI drops back into asking where you left off. Jot one line when the nudge appears, and it lands verbatim in the next session’s first restore message.

If active.md already has enough written in it, the nudge does not appear. It is not forced.

The third — it blocks broken code from being committed

Section titled “The third — it blocks broken code from being committed”

That is what pre-commit-check.sh does. When the AI goes to issue a git commit, it runs typecheck and lint ahead of it. Both have to pass for the commit to proceed; if either fails, the commit is blocked.

This is the seat most helpful to non-developers. The AI sometimes mis-types a value while writing test code and then issues a commit on top of it. Run that command as is and the broken state gets stamped into git history. This hook blocks that seat.

When a block appears, copy the printed error verbatim into Claude Code and say “fix this.” After the fix, issue the commit again and it passes the second time.

Six-dimension validation — why /review-e2e stops

Section titled “Six-dimension validation — why /review-e2e stops”

After the tests are written, the base scores them across six criteria to judge whether they were written well. This is /review-e2e. Without a person inspecting by hand, the gate blocks if test quality drops below a threshold.

The six criteria are these.

  • Coverage: did every promised critical flow get turned into a test
  • Flakiness: does the result stay steady across runs, with no arbitrary waits (hard sleeps)
  • Selector quality: are screen elements found in a stable way
  • Test isolation: do the tests avoid depending on each other’s state
  • Run performance: is it not excessively slow
  • Maintainability: is it easy to read and fix later

Each criterion scores 5, 3, or 1, and all six have to be 3 or higher to pass. If any falls short, the AI fixes that part and re-scores. But this fix-and-re-score loop runs at most twice. Fail to pass after two fixes and it stops at blocked. Why it stops at two, and how to get out when it does, is covered in When the AI gets stuck.

The value this gate gives you is simple. Even when the AI says “I wrote all the tests,” it does not let them pass if they wobble on every run or break the moment one screen changes.

The strongest boundary — the production block

Section titled “The strongest boundary — the production block”

The seat reinforced in several places gets nailed down once more here. This base never attaches to a live production service or a real database.

This is not a recommendation, it is enforced. If you try to enter a production URL by mistake, /3-analyze-target warns you and steers you toward staging or a dedicated environment. And if you try to run tests anyway with a production address pinned in, /run-suite refuses to run at all.

The tests sign up, click checkout, create and delete data. If the target is the production server, real data gets corrupted and real charges fire. This block prevents that accident. Always attach the tests to local, staging, or a dedicated test environment.

If a particular hook gets in the way of your workflow, drop just that entry in .claude/settings.json. They are all independent, so dropping one does not affect the other two. To turn it back on, copy that entry from the base’s original settings.json.

The recommendation is to leave them as they are. All three guard the seats non-developers fall into most often, so turning one off hands that seat back to you. The production block, above all, do not turn off.

With the automated safety net in hand, see how to get out when the AI workflow loops in the same spot, in When the AI gets stuck.