← All guides
testing

15 /goal Examples You Can Copy-Paste (With Exit Conditions)

15 /goal Examples You Can Copy-Paste (With Exit Conditions)

A goal loop is the simplest useful agent loop: state an outcome, give the agent a mechanical way to check it, cap the iterations, and let it run. The whole art is in the exit condition — if the check isn't a command with an exit code, the agent will argue it's done instead of being done.

Every example below follows the same template. Swap in your own commands and paste into your harness, or feed any of them to the [builder](/builder) to get a runnable script.

/goal <outcome>
exit: <command that returns 0 when true>
budget: <max iterations>, <max wall-clock>
scope: <paths the agent may touch>

Browse the full goal-loop collection at [/type/goal](/type/goal).

Testing & CI

### 1. Tests pass and lint is clean

The canonical first loop. Directory: [fix-tests-and-lint](/loops/fix-tests-and-lint).

/goal all tests pass and lint is clean
exit: npm test && npm run lint
budget: 15 iterations, 60m
scope: src/, tests/ — never delete or skip a test to make it pass

### 2. Kill the flaky tests

Note the exit condition: consecutive passes, not one lucky run. Directory: [kill-flaky-tests](/loops/kill-flaky-tests).

/goal the test suite passes 10 consecutive runs with zero flakes
exit: for i in $(seq 10); do npm test || exit 1; done
budget: 25 iterations, 3h
scope: tests/, src/ — fix root causes; quarantining a test requires a TODO comment with the reason

### 3. Get the build green

/goal CI is green on this branch
exit: gh run watch --exit-status
budget: 10 iterations, 90m
scope: anything except .github/workflows/ — fixing the code is allowed, gaming the pipeline is not

Directory: [get-the-build-green](/loops/get-the-build-green).

### 4. Reach a coverage target

/goal line coverage is at or above 80%
exit: npm test -- --coverage && node scripts/check-coverage.mjs 80
budget: 20 iterations, 2h
scope: tests/ only — write tests for existing behavior, do not modify src/ to be "more testable"

Directory: [reach-coverage-target](/loops/reach-coverage-target).

### 5. Ship the PR until it's green

A goal loop wrapped around CI feedback. Directory: [ship-pr-until-green](/loops/ship-pr-until-green).

/goal PR #482 passes all required checks
exit: gh pr checks 482 --required
budget: 12 iterations, 2h
scope: the PR branch only — respond to CI failures with fixes, push, re-check

Types, lint, and formatting

### 6. TypeScript strict mode, zero errors

/goal the repo compiles under "strict": true
exit: npx tsc --noEmit
budget: 30 iterations, 4h
scope: src/ — no `any`, no `@ts-ignore` without a comment justifying it

### 7. Format until clean

/goal formatter and import sort produce zero diffs
exit: npx prettier --check . && npx eslint --max-warnings 0 .
budget: 5 iterations, 20m
scope: whole repo except generated files listed in .prettierignore

Directory: [format-until-clean](/loops/format-until-clean).

Refactoring & cleanup

### 8. Delete all dead code

/goal knip reports zero unused exports, files, or dependencies
exit: npx knip
budget: 15 iterations, 90m
scope: src/, package.json — every deletion must keep `npm test` passing

Directory: [dead-code-elimination](/loops/dead-code-elimination).

### 9. Burn down the TODOs

/goal zero TODO/FIXME comments older than 90 days remain
exit: node scripts/stale-todos.mjs --max-age 90 --fail-on-found
budget: 20 iterations, 2h
scope: src/ — each TODO is either fixed or converted to a tracked issue with a link

Directory: [todo-burn-down](/loops/todo-burn-down).

### 10. Migrate an API, callsite by callsite

/goal no callers of the deprecated v1 client remain
exit: ! grep -rn "from '@lib/api-v1'" src/ && npm test
budget: 25 iterations, 3h
scope: src/ — migrate one module per iteration, tests pass after each

Directory: [migrate-an-api](/loops/migrate-an-api).

Security & dependencies

### 11. Secrets scan comes back clean

/goal gitleaks finds zero secrets in the working tree
exit: gitleaks detect --no-git --exit-code 1 && echo clean
budget: 8 iterations, 45m
scope: whole repo — move secrets to env vars, add patterns to .gitleaksignore only for confirmed false positives

Directory: [secrets-scan-clean](/loops/secrets-scan-clean).

### 12. Upgrade dependencies, one at a time

/goal zero outdated minor/patch dependencies, tests green after each bump
exit: npm outdated --json | node scripts/only-majors-left.mjs
budget: 30 iterations, 4h
scope: package.json, lockfile — ONE package per iteration, commit per package, revert on test failure

Directory: [dependency-upgrade-one-at-a-time](/loops/dependency-upgrade-one-at-a-time).

Performance & database

### 13. Hunt the N+1 queries

/goal the request-path query count in the perf suite is under budget
exit: npm run perf:queries -- --budget 12
budget: 15 iterations, 2h
scope: src/db/, src/api/ — add eager loading or batching; schema changes need human review

Directory: [n-plus-one-query-hunt](/loops/n-plus-one-query-hunt).

### 14. Hold the bundle-size line

/goal the client bundle is under 250 kB gzipped
exit: npm run build && node scripts/check-bundle-size.mjs 250
budget: 12 iterations, 90m
scope: src/, next.config.mjs — code-split and prune; removing user-facing features is out of bounds

Directory: [bundle-size-budget](/loops/bundle-size-budget).

### 15. Apply migrations until the schema matches

/goal migrations apply cleanly to a fresh database and schema matches models
exit: dropdb --if-exists loop_test && createdb loop_test && node scripts/migrate.mjs && node scripts/schema-check.mjs
budget: 10 iterations, 60m
scope: db/migrations/ — additive migrations only; destructive changes stop the loop for human review

Directory: [apply-db-migrations](/loops/apply-db-migrations).

The pattern behind all 15

Three rules, no exceptions:

1. The exit condition is a command. If you can't && it in a shell, it's not an exit condition. 2. The scope names what's forbidden, not just what's allowed. The failure mode of every goal loop is achieving the letter of the goal by violating its spirit — deleting tests, skipping checks, gutting features. 3. The budget is enforced by the harness. The model doesn't count its own iterations; your script does.

Long-running loops also deserve a notification path — a loop that finishes at 3am and tells no one might as well not have run. One ConnectMyEmail hook at the end of the harness fixes that.

Got a goal that isn't on this list? Feed it to the [loop builder](/builder) — it'll pressure-test your exit condition, attach a budget, and hand back a harness you can run today.

Ready to run one? Browse the loop directory →