claudekit / guides / goal-command
[ Guide · Practical · 6 min ]

Claude Code `/goal` — running auto-continuation safely

updated

`/goal` sets a completion condition; after every turn a small fast model checks whether it holds and Claude keeps starting new turns until it does. The real lever is how the condition is written — most `/goal` problems are condition problems, not command problems.

The real cost of multi-turn work

Multi-turn tasks have implicit dead time between turns — you press “continue” or hand-feed the next instruction every time. For work with a verifiable end state — migrating call sites until everything compiles, splitting a file under a size budget, working through a labeled issue queue — that dead time is pure overhead.

/goal removes it. One line stating the completion condition, and Claude keeps starting new turns until a small fast model says the condition is met.

The price of removing the human gate is that a bad condition costs you without you noticing. The interesting part of using /goal isn’t the command itself — it’s getting the condition right.

Three auto-continuation mechanisms — when to pick which

The decision rule is what triggers the next turn.

ApproachNext turn starts whenStops whenScope
/goalThe previous turn finishesA model judges the condition metCurrent session only
/loopA time interval elapsesYou stop it, or Claude decides the work is doneCurrent session only
Stop hookThe previous turn finishesYour own script or prompt decidesWhatever settings scope it lives in

/goal is the one-liner shortcut for “evaluate and continue after every turn, but only in this session.” Reach for a Stop hook when you need custom evaluation logic or want it across sessions. Reach for /loop when the trigger is time, not condition. Auto mode only auto-approves tool calls within a turn — pair it with /goal and both per-tool and per-turn prompts disappear, which is the unattended-run setup.

Usage

/goal all tests in test/auth pass and the lint step is clean

Setting a goal starts a turn immediately — no separate prompt needed. While the goal is active, a ◎ /goal active indicator shows elapsed time, and the evaluator’s most recent reason appears in the status view and transcript.

Reference commands:

CommandEffect
/goal (no arg)Show the current or most recently achieved goal: condition, elapsed time, evaluated turns, token spend, evaluator reason
/goal clearRemove the active goal before its condition holds (stop, off, reset, none, cancel are aliases)
/clearStart a new conversation — also removes any active goal

A goal that was active when a session ended is restored on --resume / --continue, but the turn counter, timer, and token-spend baseline reset.

Four condition pitfalls

Almost every “/goal went wrong” report traces back to one of these.

Pitfall 1 — the evaluator only sees what’s in the conversation

The evaluator does not call tools or read files. It only reads what Claude has already surfaced.

/goal all unit tests pass

A model trying to satisfy this condition can produce the sentence “I reviewed the tests and they all pass” without actually running them, and the evaluator can take that sentence as evidence.

/goal npm test exits 0 and its output is visible in the transcript

Bake the shape of the evidence into the condition. Require a command name, an exit code, or specific output text — something only a real execution can produce.

Pitfall 2 — the condition is abstract

/goal until the code quality is improved

“Improved” has no measurable end state. The evaluator can say “not yet” indefinitely and Claude burns turns on incremental refactors.

/goal until src/utils/format.ts is under 200 lines and every export referenced outside the file is preserved

Aim for one measurable end state plus invariants that must hold.

Pitfall 3 — no kill-switch

If the evaluator never reaches yes, the goal keeps running. Walk away from the keyboard and the bill accumulates.

Embed the kill-switch in the condition itself:

/goal all tests in test/auth pass and the lint step is clean,
or stop after 20 turns with a summary of what's left

Claude reports progress against that clause each turn, and the evaluator judges it from the conversation.

Pitfall 4 — no “do not touch” list

/goal until users has a created_at column and the migration passes

The condition can pass even if other migration files were modified along the way.

/goal until users has a created_at column added via a single new migration, with no existing migration files modified, and npm run migrate passes

For changes with blast radius, write what must not change alongside what must.

Headless usage

-p combined with a /goal invocation runs the whole loop in a single command — useful for background jobs or cron.

claude -p "/goal CHANGELOG.md has an entry for every PR merged this week" \
  --permission-mode auto

--permission-mode auto (or auto mode inside the session) removes per-tool prompts too, giving you fully unattended runs. Ctrl+C interrupts. The same combination plugs into claude agents dispatch if you want a dashboard view.

When /goal is not the right tool

  • Exploration and design decisions — work whose end state is “we agree on a direction” doesn’t fit /goal. Use plan mode with a human reviewer.
  • Workflows that need user checkpoints — auto-continuation is the wrong default when each step depends on a human decision.
  • Work without textual evidence — UI changes and other tasks where the evaluator can’t see the result need a strong turn cap, or the loop drifts indefinitely.

How evaluation actually runs

/goal is a wrapper around a session-scoped prompt-based Stop hook. After every turn, the condition and the conversation so far go to your configured small fast model (defaults to Haiku), which returns a yes/no decision and a short reason.

  • No — Claude is told to keep working, and the reason is passed in as guidance.
  • Yes — the goal clears and an “achieved” entry is recorded in the transcript.

The evaluator runs on the small fast model configured for your provider, so its token cost is typically negligible next to main-turn spend.

Requirements

  • Claude Code v2.1.139 or later
  • Workspace trust dialog accepted for the current directory
  • disableAllHooks not set at any settings level
  • allowManagedHooksOnly not set in managed settings
  • When /goal is unavailable, the command surfaces the reason — it never silently no-ops

References

§ 10

Frequently Asked Questions

frequently asked
§ 10.1
What is `/goal`?
It's a session-scoped command that takes a completion condition. After every turn a small fast model checks whether the condition holds, and Claude keeps starting new turns until it does. The goal clears automatically once met.
§ 10.2
Which version do I need?
Claude Code v2.1.139 or later, in a workspace where you have accepted the trust dialog.
§ 10.3
How is it different from `/loop`?
`/loop` re-runs the same prompt on a time interval. `/goal` evaluates the condition immediately after each turn and stops as soon as it's met — condition-based auto-continuation rather than time-based repetition.
§ 10.4
Can the evaluator be fooled by Claude's own claims of success?
Yes, that's the most common failure mode. The evaluator doesn't call tools — it only judges what's already in the conversation, so a claim like "tests pass" can be enough. Phrase the condition so the evidence has to appear in the transcript (e.g. `npm test exits 0 and its output is visible`).
§ 10.5
When can `/goal` not be used?
In workspaces where you have not accepted the trust dialog, when `disableAllHooks` is set at any settings level, or when `allowManagedHooksOnly` is set in managed settings. In each case `/goal` surfaces the reason rather than silently doing nothing.
§ 10.6
Does `/goal` work in non-interactive mode?
Yes. `claude -p "/goal <condition>"` runs the loop to completion in a single invocation, and Ctrl+C interrupts it. The same flow works in the desktop app and through Remote Control.