cd /news/artificial-intelligence/stop-prompting-and-start-looping-a-c… · home topics artificial-intelligence article
[ARTICLE · art-52612] src=pub.towardsai.net ↗ pub= topic=artificial-intelligence verified=true sentiment=· neutral

Stop Prompting And Start Looping. A Claude Code Engineer’s Guide to /goal and /loop

Boris Cherny, creator of Claude Code at Anthropic, introduced /goal and /loop commands that enable autonomous AI agents to work without human intervention, shifting the paradigm from prompting to loop engineering. The /goal command sets a finish line verified by a separate evaluator model, while /loop runs prompts on a timer, allowing developers to write loops that prompt Claude rather than prompting it directly.

read17 min views1 publishedJul 9, 2026

TL;DR:/goal gives Claude Code a finish line and a second model to check if it’s been crossed - Claude keeps working autonomously until the condition is provably met. /loop runs a prompt on a timer, polling on a schedule without you present. Together they are the foundation of loop engineering. The paradigm shift Boris Cherny, creator of Claude Code, described in Jun 2026 as :This article covers both commands from first principles, and also practical demonstration by building loops on simple application end to end.“I don’t prompt Claude anymore. I have loops running that prompt Claude and figure out what to do. My job is to write loops.”

For most of Claude Code’s user, the interaction model looked like this :

Here if you observe carefully, you were the loop. Every iteration required your attention. You read the output, decided if it was good enough, and either approved or corrected. Claude was fast, but you were still the bottleneck.

In June’2026, Boris Cherny the creator and head of Claude Code at Anthropic described how his own workflow had changed he said that “I don’t prompt Claude anymore. I have loops running that prompt Claude and figuring out what to do. My job is to write loops.”

Google’s Addy Osmani put a name to it : Loop Engineering

The shift is conceptual before it’s technical. The question stops being *“how do I write a good prompt?” *and becomes “how do I write a finish line precise enough that a machine can tell when it’s been crossed?”

That finish line is /goal . The clock that keeps the look ticking is /loop .

Before diving into the commands, it’s worth understanding what Claude Code is doing under the hood, because both commands are built on top of it.

The official docs describe it simply :

“When you start an agent, the SDK runs the same execution loop that powers Claude Code : Claude evaluates your prompt, calls tools to take action, receives the results, and repeats until the task is complete.”

In each full cycle, claude produces output, tools execute, results feedback is one turn. A simple question might take 1–2 turns. A complex refactor can chain dozens.

The loop runs until claude produces a text-only responses with no tool calls. That’s the natural stopping point. But ** “Claude decides it’s done” **is a problem in this process : without an external checks, Claude is grading its own homework.

And /goal solves this at the architecture level.

The official definition from the Claude code docs :

"/goal works by wrapping a session-scoped prompt-based Stop hook. Each time Claude finishes a turn, the condition and the conversation so far are sent to a small fast model which defaults to Haiku which returns a yes-or-no decision and a short reason. A 'no' tells Claude to keep working and includes the reason as guidance for the next turn. A 'yes' clears the goal and records an achieved entry in the transcript.”

Let that sink in. There are now two models running:

The evaluator model does not call tools. It can only judge what claude has already surfaced in the conversation. This is the key architectural insight : the checker is intentionally blind to the codebase and it can only verify what Claude has demonstrated, which forces claude to surface proof of completion, not just claim it.

The /goal Command Interface

/goal <condition>          # Set or replace the active goal (starts immediately)/goal                      # Show status: condition, turns, tokens, last evaluator reason/goal clear                # Clear the goal (aliases: stop, off, reset, none, cancel)

Requirements:

One goal per session. A new /goal replaces the current one. The condition can be up to 4,000 characters.

This is the skill. The official docs are direct about it:

Bad : ‘improve the dashboard.’

Good : ‘one measurable end state, a stated check (how Claude proves it), constraints that must hold, and optionally a turn or time limit.’

The evaluator model can only read the conversation. So your condition must be written as something Claude can demonstrate in conversation, not just claim.

The four components of a good condition examples:

Bad Conditions (vague, unmeasurable):

❌ "Fix the bugs in the code"❌ "Improve code quality"❌ "Make the tests better"❌ "Clean up the auth module"

Good conditions (verifiable by a second model reading the transcript):

✓ "pytest src/ exits with code 0. Claude must run pytest and    show the full output. No files in tests/ are modified.    Stop after 25 turns."✓ "CHANGELOG.md has an entry for every PR merged this week.    Claude must run git log --oneline and show which PRs were    found, then show the CHANGELOG diff. Stop after 10 turns."✓ "All TODO comments in src/ are resolved. Claude must run    grep -r TODO src/ and show it returns no results.    Stop after 15 turns."

Notice the pattern : you’re not just describing the end state, you are specifying the ** evidence **the evaluator will look for in the conversation.

Our counterintuitive insight from practitioners : running /goal with a weaker main model often demonstrates the loop’s power more clearly than using Opus also it help us to manage token expenditure.

When Opus runs /goal , it often solves problems in one or two turns. The loop barely shows. When Haiku or Sonnet runs the same goal on a hard problem, you see the loop in action: tying an approach, getting the evaluator’s “no+reason”, trying again differently, spawning subagents, brute-forcing search strategies. The same goal, the same commands, but the loop’s autonomous persistence becomes visible.

For production, use the best model for the task but of course using best model as evaluator come with a some cost attached to it. For learning the system, deliberately run a medium-difficulty problem with a mid-tier model.

/loog and /goal are often mentioned together, but they solve different problems:

The official docs describe /loop precisely:

“/loop runs on a specified interval; without an interval,it self-paces based on output.”

The command interface:

/loop 30m                  # Run the current prompt every 30 minutes/loop 1h                   # Run every hour/loop                      # Self-paced: re-runs as soon as previous run completes/loop stop                 # Stop the active loop

/loop is designed for recurring work that arrives on a schedule; the kind of task where there is no single “done” state, just on ongoing stream:

Now, you might have question that then why not to run corn job rather spending money on LLM models. But there is huge difference from a corn job, a corn job runs a fixed script. /loop runs a model that reads the current state and decides what to do next. The action adapts to the situation.

The real architecture emerges when you combine them:

/loop provides the cadence. /goal handles completion logic for each unit or work. Together they form a continuous, self-driven engineering agent.

The Claude code team’s own documentation describes this combination directly for handling incoming feedback:

“Use /schedule to run a routine that checks for new reports, /goal to define what done looks like, and auto mode so the routine runs without stopping to ask for permissions.”

What it is: A cycle where AI acts on user inputs, continuing until the conversation ends. This is every standard Claude Code session you’ve already run.

How it starts: A standard user prompt. How it ends: You close the chat, go idle, or switch to a new topic. Best for: General queries, exploratory dialogue, basic assistance anything where you want to stay in the driver’s seat.

This is where most engineers live today. It’s useful, but you are the loop. Every iteration costs your attention.

What it is: A continuous cycle focused on achieving a specific, user-defined objective. Claude doesn’t stop until the goal is provably met verified by a separate evaluator model.

How it starts: Give a clear, verifiable objective “all tests pass,” “no linter errors,” “CHANGELOG updated.” How it ends: The evaluator model confirms the condition is met, or you explicitly cancel. Best for: Project management, fixing bugs, creating complex reports, iterative design any task with a checkable finish line.

This is /goal. The evaluator is the key innovation: it separates "doing the work" from "deciding if the work is done."

What it is: Actions executed automatically at predefined times, dates or intervals regardless of what was done in the previous run.

How it starts: Provide a schedule *“every 30 minutes,” “daily at 9 AM,” “every Tuesday.” *How it ends: Stop instructions given, duration expires, or schedule removed. Best for: Scheduled reporting, health monitoring, reminders, time-sensitive updates for recurring work that doesn’t have a single “done” state.

This is /loop. It's the clock layer. The work repeats; only the schedule determines cadence.

What it is: AI initiates actions based on detected triggers or changes in external conditions. The AI is watching, not waiting.

How it starts: Set conditions *“notify me if the CI fails,” “respond when a PR is opened,” “alert if error rate exceeds 5%.” *How it ends: You stop monitoring or the trigger condition is permanently resolved. Best for: Opportunity detection, threat monitoring, automated incident response, event-driven workflows.

This is implemented via **Claude Code Routines **GitHub event triggers, webhooks, and MCP connectors that fire when something changes externally.

The progression is a maturity ladder. Most engineers start at Turn-Based and never move. Loop engineering means deliberately choosing Goal-Based or Time-Based for the right tasks — and building Proactive loops for the ones that shouldn’t need human initiation at all.

Theory without demonstration is incomplete. Let’s build something real.

Project : A Python data processing module with intentionally broken code. We use /goal to autonomously fix all failing tests without touching the test files. Then we add /loop to monitor the suite on a recurring schedule.

This project is designed to be reproducible or you can clone it, break the code and run the exact same commands to watch the loop work.

Directory structure we’re building:

self-healing-suite/├── .claude/│   ├── settings.json       ← Hook: block test file modifications│   └── commands/│       ├── goal.md         ← /goal command template│       └── loop.md         ← /loop command template├── src/│   ├── __init__.py│   ├── data_cleaner.py     ← 4 intentional bugs live here│   └── stats_engine.py     ← 2 more bugs here├── tests/│   ├── __init__.py│   ├── test_data_cleaner.py│   └── test_stats_engine.py├── CLAUDE.md               ← Project rules└── pytest.ini

src/data_cleaner.py four bugs planted:

src/stats_engine.py Two more bugs planted in src/stats_engine.py file:

tests/test_data_cleaner.py:

tests/test_stats_engine.py:

A critical constraint of the demo: Claude must fix bugs in src/ only. The tests define the specification they are immutable.

.claude/settings.json:

{  "hooks": {    "PreToolUse": [      {        "matcher": "Edit|Write",        "hooks": [          {            "type": "command",            "command": "python3 -c \"\nimport json, sys\ndata = json.load(sys.stdin)\npath = data.get('tool_input', {}).get('file_path', '')\nif 'tests/' in path:\n    print(f'BLOCKED: {path} is a test file. Fix src/ only.', file=sys.stderr)\n    sys.exit(2)\nsys.exit(0)\n\""          }        ]      }    ]  }}

This is real policy enforcement. If Claude tries to modify a test file to make tests pass (a known shortcut LLMs attempt), the hook blocks the write at the system level and feeds the reason back to Claude.

pytest.ini:

[pytest]testpaths = testspython_files = test_*.pypython_classes = Test*python_functions = test_*addopts = -v --tb=short

Before running /goal, confirm the suite is broken:

Expected output:

Seven failures. Two source files. Six bugs. Let’s let /goal fix them.

Open Claude Code in your project directory:

cd self-healing-suiteclaude

Now set the goal:

what happens next - a turn-by-turn trace:

Turn 1 : Claude runs /pytest test/ -v and reads the all failures. It identifies the failure patterns and starts with test_removes_by_id_field .

**Turn 2 : **Claude reads src/data_cleaner.py , finds Bug 1 (record.get("name") → record.get("id")), edits the file, re-runs pytest. 6 failures remain.

Turn 3 : The evaluator checks the conversation. Reads: “6 tests still failing.” Returns: “No. Tests still failing: 6 remaining. Continue.” Claude continues.

Turn 4 : Claude tackles Bug 2 (normalize_email missing .lower()), fixes it, re-runs. 5 failures remain.

Turn 5–7: Bugs 3, 4, 5 fall in sequence. Each time Claude runs pytest and shows the output.

Turn 8: Bug 6 the bucket_by_percentile remainder bug. Claude rewrites the slice logic to use None for the final bucket. Runs pytest.

Turn 9: pytest tests/ -v26 passed, 0 failed. Claude shows the full output.

Turn 10: Evaluator reads the conversation. Sees the full pytest output with “26 passed.” Returns: “Yes. All 26 tests pass. Goal achieved.”

Session ends. You didn’t type a single thing after /goal.

The project has clean tests. Add /loop to keep it that way.

Setup : Create a monitoring command.

.claude/commands/monitor.md:

The project now has clean tests. Add /loop to keep it that way.

Setup: Create a monitoring command

.claude/commands/monitor.md:

Running the monitor loop:

Or from a non-interactive terminal (useful for CI integration):

This is how the loop will work, in our example it’ll start after every 5m and run the test validation.

Just for demo purpose I’m changing src/data_clearner.py and again planting same bugs.

The health log it produces (.claude/health.log):

[2026-07-09 13:23:36] STATUS: healthy TESTS: 26 passed/26 total[2026-07-09 13:28:26] STATUS: healthy TESTS: 26 passed/26 total[2026-07-09 13:33:18] STATUS: healthy TESTS: 26 passed/26 total[2026-07-09 13:38:51] STATUS: fixed TESTS: 26 passed/26 total[2026-07-09 14:30:58] STATUS: healthy TESTS: 26 passed/26 total

*The mini project (*self-healing-suite) is designed to be cloned and run. Every bug in this article is a real, valid Python bug that produces a real test failure. The fix requires understanding the code, not guessing which is exactly what makes it a good test for autonomous loop reasoning.

The complete self-healing system for this project:

This is functioning, autonomous test maintenance system. The only time a human needs to look at it is when the system explicitly flags needs_human which happens when the bug is architectural, not cosmetic.

The XDA field guide on /goal captured the single most important insight from practitioners:

“If you can’t say what ‘done’ looks like, you don’t have a loop. You have a wish.”

Three principles that separate working /goal deployments from frustrating ones:

The test: if there’s a moment when *“it’s done” *can be verified programmatically, use /goal . If the work never ends and just repeats, use /loop

That’s loop engineering. One finish line. No babysitting.

/goal and /loop are powerful precisely because they run autonomously. That autonomy is also their risk. Token costs in agent loops compound differently than single-turn calls and an unattended loop without circuit breakers is a machine that ships bugs with high confidence and runs up your bill while doing it.

The next article in this series covers production-safe loop design: how to set max_budget_usd, when to use max_turns, the maker/checker pattern with separate verifier sub-agents, and how to design stopping criteria that prevent the four most common loop failure modes.

If you’ve ever woken up to a surprise API bill, that article is for you.

Follow me for more practical engineering takes & usage of AI systems.

Stop Prompting And Start Looping. A Claude Code Engineer’s Guide to /goal and /loop was originally published in Towards AI on Medium, where people are continuing the conversation by highlighting and responding to this story.

── more in #artificial-intelligence 4 stories · sorted by recency
── more on @claude code 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/stop-prompting-and-s…] indexed:0 read:17min 2026-07-09 ·