I’m out of town for a wedding this week. Two nights ago I was in a hotel room, my laptop on the ironing board because there was no desk, and I kicked off four separate Freebo features before bed. When I woke up the next morning, four draft pull requests were sitting on GitHub, and all four of them had CI failures.
That’s not the failure story. That’s the success story. Let me explain.
/goal is the whole shape
Claude Code has a built-in called /goal. You give it a condition, and it runs turn-by-turn — planning, coding, running tests, reading errors, editing again — until the condition is met or you stop it. It’s the closest thing I have to writing a spec and walking away.
The quality of the run is bounded by the quality of the condition. A vague /goal "add partial refunds" gets you a vague result. A great condition names the hard gates: which files must be touched, which tests must pass, which shortcuts are forbidden, and what “done” actually looks like as strings a grep can find in the transcript.
I have a Freebo-specific skill called goalgeneratorfreebo whose entire job is to author that condition string for me. It reads a rough idea, spawns a schema-explorer and a codebase-explorer in parallel, asks me at most three questions, writes a PRD, writes a plan, and then emits a /goal invocation with sixteen non-negotiable gates baked in.
0
hard gates
0
PRs pushed overnight
0
line of safety guard
Here’s what a slice of those gates actually looks like when it hits the transcript. The /goal run has to prove each one is true before it can call itself done:

Notice the shape. Every gate is something a shell command can prove — a git diff --stat, a grep, an exit code from npx playwright test, a ls on a docs file that must exist. The agent can’t hand-wave “I think the endpoint is documented.” It has to grep "POST /v1/..." and put the match in the transcript.
The one-line safety guard
Here’s the thing that made me comfortable pushing four sprints at once from a hotel bed.
Commit current versions of each PR so we can always go back.
— the prompt I actually typed
That’s it. One clause bolted onto the /goal invocation. It tells the agent: at the start of every task, and again at every meaningful pause, snapshot the working state as a commit on the draft PR. Don’t wait until “done” to write history — write history while the work is in flight, so every intermediate state is a place I can rewind to.
Combined with the “draft PR, don’t merge” default, this turns the whole sprint into a checkpoint machine. If the last state is broken, I git reset --hard HEAD~1 and I’m back at a state that was working three turns ago. If four consecutive commits are broken, I still have a clean starting point twelve commits back.
Why the CI failures are the feature
So the next morning I open GitHub. Four draft PRs. Four red X marks on the checks tab.
The old me would have panicked. Overnight agents shipped garbage. Roll it all back.
The new me looks at which check failed, and on which commit. Because the commits are granular, the failure signal is granular too. A typecheck failure on commit 7 of 12 means commits 1–6 are probably fine. A Playwright timeout on the final commit means the plumbing is right and something in the last step regressed the flow. An integration test that hits a real Supabase failing on commit 3 tells me the migration is wrong and everything after it inherited the bug — but the migration file is the actual thing to fix, not the eleven commits that ran on top of it.
I don’t need the agent to have gotten it perfect. I need the agent to have gotten far enough that my morning coffee is spent reading a targeted diff, not writing feature code from scratch.
- 8:12pm CDTIroning-board deskLaptop propped up on a hotel ironing board. VPN on. Fed goalgeneratorfreebo four rough ideas back-to-back, approved four condition strings.
- 8:45pm CDTFour sprints runningKicked off four /goal runs in four terminals inside a tmux session on my Omarchy box back home, reachable over Tailscale.
- 10:30pm CDTSleepClosed the laptop with the sprints still running.
- 7:15am EDTFour draft PRsGitHub shows PRs #629, #630, #631, #632. All draft. All red. All granular enough to actually work with.
What the skill actually spits out
The goalgeneratorfreebo skill emits a condition string I paste as-is into /goal. The interesting bit isn’t the boilerplate — it’s the rule-shaped gates. For example, gate 13:
Every migration that creates a table also enables RLS in that same
migration. Demonstrate: `grep -A2 "CREATE TABLE" <migration>` showing a
matching `ENABLE ROW LEVEL SECURITY` for each.
That gate exists because RLS shipped disabled three separate times in earlier issues. So the rule now travels with every new /goal. The agent can’t ship a table-creating migration without proving in the transcript that RLS is on. Not “should be on.” Not “will be on.” Grep for it, put the match in the transcript, or you don’t get to call yourself done.
The whole skill file is worth a read if you’re into agent guardrails. But the pattern is generalizable:
- Automate the writing of your
/goalconditions. Prompt quality is the ceiling. - Bake your historical bugs into the gates. If it went wrong once, make the transcript prove it can’t go wrong the same way.
- Add the checkpoint clause. One line. Cheapest insurance you’ll ever buy.
- Send it to draft, not to main. Read the diff over coffee.
The bigger unlock
I used to think “unattended” meant “have to trust the outcome.” I don’t think that anymore. Unattended means “shift the review from writing to reading.” The overnight run doesn’t need to be right. It needs to be readable, with enough checkpoints that I can salvage the good and throw out the bad.
The wedding is Saturday. Between now and then, I’ll spend maybe two hours cleaning up those four PRs and merging what survives. Two hours of my time bought a night’s worth of forward motion on four different features.
That trade wasn’t available a year ago. It is now. And the whole thing hinges on a single clause — commit current versions so we can always go back — that took longer to type than to think.