[BUG] a /goal Stop hook cannot be cleared from inside the session
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Bug: a /goal Stop hook cannot be cleared from inside the session
Product: Claude Code (desktop app), Opus 5
Feature: /goal and the session-scoped Stop hook it installs
Severity: medium. No data loss, but a session can be left unable to stop,
burning tokens on forced round-trips.
Summary
/goal <condition> installs a Stop hook that blocks the session from ending
until the condition is judged met. There is no way to clear it from inside the
session, and nothing tells the user how. When the condition cannot be met, the
session cannot stop, and the only exit is for the user to happen to know that
running /goal again overwrites it.
What happened
A goal was set for a long review task. Partway through, the user wrote:
You can stop the goal - this is good, I'll review in the morning.
The hook kept firing anyway, roughly forty more times. Each firing produced the
same feedback text and required a reply. The user then asked:
You can delete that hook that keeps re-prompting you
There was nothing to delete. I searched:
~/.claude/settings.jsonhas three hooks, none of them a Stop hook- no project-level
.claude/directory exists - nothing goal-shaped anywhere under
~/.claude - the goal text appears in exactly one file: the session's own
.jsonl
transcript, which is a record of what was said, not configuration
So the goal lives only in the app's in-memory session state. It survived
everything reachable from a shell.
It stopped when the user ran /goal again with a trivial condition, which
overwrote it. Neither of us knew that would work; it was a guess that happened
to be right.
Impact, measured
In this session's transcript, 150 of 545 messages in the user stream were
Stop hook feedback (about 28%). Around forty of those came after the user had
explicitly withdrawn the goal. Each one is a full model round-trip.
Expected behaviour
Any one of these would have been enough:
/goal clear(or similar) documented in the hook's own feedback text, so it
is discoverable at the moment it is needed.
- The hook stops firing when the user says in plain language to stop. It
currently has no path to hear that; only the model sees the message, and the
model cannot clear the hook.
- A firing count or elapsed-time ceiling, after which the hook disables itself
and says so.
Secondary, softer issue: unsatisfiable conditions
The condition was, in effect, "keep reviewing until no errors remain that are
not blocked on me". The workflow it described puts questions the model cannot
answer into a decisions file for the user. Those recorded items are exactly the
"blocked on me" ones, but the hook counted them as outstanding errors, so the
condition could never be satisfied no matter how much work was done.
That is partly a phrasing problem and I would not file it on its own. It
matters because it is the common case: a goal phrased around "no remaining
issues" will often reference work that is by design deferred to the user. If/goal is going to block stopping, it is worth either warning on conditions
that reference external blockers, or making the escape hatch obvious, which is
the main request above.
Reproduction
/goal <a condition that depends on user action to satisfy>- Work the task; escalate something to the user for a decision.
- Try to stop. The hook fires and cites the escalated item as unfinished.
- Tell the model in plain language to stop. It cannot clear the hook.
- Look for the hook on disk. It is not there.
Exit: run /goal again with any trivial condition.
What Should Happen?
Asking Claude to cancel hooks, goals, ... should do that.
Error Messages/Logs
Reboot complete and verified.
Reboot complete and verified.
Reboot complete and verified.
> You can delete that hook that keeps re-prompting you
Ran 3 commands
Located the Stop hook driving the goal loop
Failed to search for the goal or Stop hook configuration
Inspected configured hooks and look for goal storage
The goal isn't in settings.json — the three hooks there are unrelated (a git add -A guard and similar). Searching for where it actually lives, using the distinctive typo in its text:
Ran 3 commands
Located where the goal text is stored
Checked remaining plausible goal-state locations
Inspected this session's env directory for goal state
I can't delete it — there's nothing on disk to delete.
I searched thoroughly: your ~/.claude/settings.json has three hooks and none of them is a Stop hook (they're a git add -A guard and similar). There's no project-level .claude/ directory at all. The goal's text appears in exactly one file — this session's transcript .jsonl — which is a record of what was said, not configuration; editing it would falsify the log without stopping anything. The session-env directory for this session is empty.
So /goal is app-managed session state, not an on-disk hook. It's held in the running session, which is why it survives everything I can reach from the shell.
Two things that should work, both on your side:
Re-run /goal with empty or trivial content to overwrite it — that's the same mechanism that set it.
Or end this session. The state is per-session, so it won't carry into a new one.
Worth saying plainly: the hook has been firing against an instruction you already withdrew — you told me to stop the goal several hours ago and I have. It's re-prompting on stale state, not on anything you still want. Nothing it's asked for has been acted on since you stopped it.
There's nothing on disk for me to delete — the goal is app-managed session state. Re-running /goal to overwrite it, or starting a new session, will clear it.
[etc]
Steps to Reproduce
Haven't been able to reproduce it.
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.221 (Claude Code)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
iTerm2
Additional Information
_No response_
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗