/goal is for defining an end condition, so Claude Code can be instructed to run until it's met without prompting after every step. Behind the scenes, it works like this:
after every turn a separate small model reads the conversation and gives a verdict: met, not yet, or impossible.
not yet means another turn; met or impossible ends the goal and hands control back to you.
The main difference between this and a regular instruction is that in case of /goal we define not a one-shot action but a process that should run until some condition becomes true. It requires Claude Code v2.1.139 or newer to work.
We'll show you how it behaves in real life and how to write a condition that will survive even if you set it up for 20 turns.
What does /goal actually do?
The main thing this feature does is wrap your prompt in a loop. By default, whenever you ask Claude to do something, it takes the prompt, acts on it and then waits for further instructions from you. With /goal in place, instead of waiting for the next prompt, it does another turn. In order to make use of it, you need to set up the goal once with /goal followed by a condition and it will become its directive. What's more, setting it up launches the first turn immediately so you don't need to run another prompt after this. You can only have one goal active per session and if you want to set up a new one it replaces the previous one. While the goal is running, a /goal active indicator shows how much time has already passed since you defined it.
How does Claude know the goal is met?
The most important thing though is what actually decides whether the goal has been achieved. After every turn, together with the conversation, the condition goes to a separate, small and fast model (Haiku by default) which returns one of three verdicts and a short reason: not yet met, met, or impossible. Not yet met means another turn, with the reason passed to Claude as a hint; met marks the goal as achieved; impossible ends it too, with the reason logged so you can see why. A goal also clears itself, with a notice, when a turn dies on an error only you can fix, like revoked auth, an empty credit balance or a context overflow compaction can't clear.
Behind the scenes, /goal is just a prompt-based Stop hook registered for the current session. A Stop hook runs every time Claude finishes a turn, and a prompt-based one hands a prompt to a small model instead of running a script, so that after-every-turn check is the hook doing its normal job. What's also important is that the model that examines the condition doesn't use any of your tools — it can't run tests, open files or check git status, so its only source of knowledge is the conversation itself. That means whatever you want to achieve with this feature, Claude needs to surface the proof in the transcript.
How do you write a condition that holds?
To sum up — what you need to do is to tell Claude what needs to happen so it can be proved by its own output: a measurable end state (like exit code from npm test), a check (like: npm test exits 0) and some constraints (like: don't change any other files from the test folder).
For example, this condition works: all tests in test/auth pass and lint is clean. When Claude runs npm test and the linter, their outputs land in the transcript as tool results, and that's what the checking model reads to decide the condition is met.
But this one doesn't work well: make the auth module better. It's not measurable, not checkable and you can't bound anything around it. The checking model has no chance to be sure when it's done so it either quits too early or never.
This is much better: every test in test/auth passes with npm test exiting 0, tsc no errors and no files changed outside src/auth.
You have 4k characters to define the condition so you can even include a specification of sorts in it. And if you don't want it to run indefinitely, you can tell Claude when to stop by including it in the condition itself, for example: or stop after 20 turns. After every turn, it keeps Claude updated about its progress against this bound and the checking model analyses it from the conversation perspective.
How is /goal different from /loop, a Stop hook, and auto mode?
There are other ways to run Claude Code without per-step prompting that you might already be familiar with but are based on different signals to trigger and stop the next turn:
| Approach | The next turn happens when… | It stops when… |
|---|---|---|
| /goal | the previous one is finished | a model says the condition is met or can't be met, or you clear it |
| /loop | X minutes pass | you intervene, or Claude decides it's done |
| Stop hook | the previous one is finished | your script or prompt says so |
With this in mind, choose what you'd like to base the next turn on. Generally though, /goal is best friends with auto mode, because a goal doesn't change your permission mode. Sessions on Pro, Max and Team plans start in auto mode since v2.1.228, but with an Enterprise plan, an API key, a third-party provider or -p they start in Manual mode, where Claude asks before every tool call your settings don't already allow. A goal that relies on your test command then pauses at that prompt every turn until you answer, unless you pick "Yes, and don't ask again" or already have an allow rule for it. In a -p run there's nobody to ask, so the call is denied and Claude carries on without the evidence it needs. Auto mode approves tool calls within a turn and /goal starts the turns themselves, so together they take away the routine prompts. That doesn't cover every prompt: explicit ask rules still ask, the classifier denies anything it judges risky rather than asking, and if it keeps blocking, auto mode pauses and you're back to answering prompts. In other scenarios, you might want to go with /loop if you want a regular time-based re-run rather than a goal, or a Stop hook if you want the same after-every-turn check to live in your settings, so it's active in every session those settings cover and not only this one.
Can you run /goal non-interactively?
It's worth mentioning that /goal also works non-interactively and runs the entire loop with -p in one go, for example:
claude -p "/goal CHANGELOG.md has an entry for every PR merged this week"But, because of the default behaviour of Claude Code, nothing is being printed until the goal is completed so if you set it up for 20 turns for instance, it looks like it hangs. If you want to observe it in action, you can use stream-json and verbose flags to see every message being sent:
claude -p "/goal CHANGELOG.md has an entry for every PR merged this week" --output-format stream-json --verboseAnd then you can stop it with Ctrl+C. It works the same when using Remote Control or the desktop app.
The gotchas you only learn by using it
There are a few things to be aware of in terms of this feature:
the model that examines the condition sees only the conversation, so if the proof of what you wanted to achieve isn't there, it doesn't count. So for example if you set up a goal like "make sure the deployed site returns 200", it's not going to work because even if Claude deploys the site and it does indeed return 200, Claude will never know unless it's being logged somehow, so make sure you include a check that leaves a trace in the transcript
it won't work if you don't have any hooks set up or you set up your workspace with
disableAllHooksorallowManagedHooksOnly. It's based on hooks so it needs a trusted workspace and tells you why it can't be run if it's not available — if you think it's not working, check these settingsif you resume a session with a goal in place, the turn counter and the timer get reset so even though the condition is being carried over, the turn count, the timer and the token baseline are being set to 0. You resume it with --resume or --continue
the checking model is the cheap part: it runs on a small, fast model and its tokens are a rounding error next to the main turns it keeps launching. Left unbounded, a goal ends on its own only if the checking model decides the condition is impossible, or if Claude goes several turns without calling a tool and Claude Code stops the loop. As long as Claude stays busy, it keeps running, so put the ceiling in the condition and glance at /goal now and then for the turn count and token spend
So is /goal worth using?
Delegating to a model works best if you check what it shipped instead of taking its word for it. /goal is worth the five minutes it takes to learn because it bakes a bit of that discipline into the tool itself: it moves one decision off your plate — not "did Claude do the thing yet", but "do we have the desired state yet", asked by a model that didn't do the work and can't fool itself into a yes. Set a finish line it can prove, give it a ceiling, and let it run.



