Skip to content
xsyetopz edited this page Oct 19, 2026 · 2 revisions

Goal

This page tells how the goal slice of the core plugin claudetto works. A user reads it to set a goal with /goal. A contributor reads it before an edit of slices/goal/.

What It Does for You

The slice replaces the built-in /goal with a goal engine. A goal is a list of steps. Each step has a title and a list of checks. At the end of each turn, the engine runs the checks of the current step. If a check fails, the engine starts the next turn with only the failing checks. If all checks pass, the engine goes to the next step. After the last step, the goal is done and the engine clears the state.

The built-in evaluator reads only the conversation, so it cannot run a check. The engine can run a command, read a file, or ask a small model.

The state is in .claudetto/goal.json of the project root.

How to Use It

/goal answers with no model turn. The text after /goal is one of these:

Text Effect
A condition Makes a goal of one step and starts the first turn.
A name that ends in .md Makes a goal from the steps of that plan file.
status or nothing Shows the step, each check with its last result, and the limits.
pause Pauses the goal.
resume Resumes a paused goal from its current step. The counts of turns and cost restart.
skip Skips the current step.
step N Moves to step N, from 1 to the count of steps.
clear Clears the goal.

The typeahead and /help show the text of the goal engine for /goal.

Checks

Kind Passes when
run The command exits with 0. The engine runs it with sh -c in the project root.
file The file exists, and it holds the text when the check has one.
judge A small model answers yes to the claim, with the answer of the turn as facts.

A run check ends after RUN_TIMEOUT_MS (300,000 ms) and counts as failed. The state keeps the last OUTPUT_TAIL_CHARS (1,500) characters of the output, because the error is at the end. A judge check that fails to answer counts as failed.

How a Condition Becomes Checks

  • If the text has only code spans in backticks, with ,, ;, and, or spaces between them, each span is a run check.
  • If the text starts with a code span, that span is a run check, and the whole text is one judge check.
  • Otherwise the whole text is one judge check.

Plan Files

A heading of level 2 or 3 that starts with a number and a point is a step. For example, ## 8b. Rewrite the page. Each Check: line below the heading, with an optional - before it, gives the checks of that step by the rules above. A plan file with no such heading gives an error.

Limits You Can Set

Flags in the text after /goal set the limits. A value must be a number above 0. A limit that is left out is no limit, except --stall.

Flag Meaning Default
--max-turns N The goal stops after N turns. None
--budget $X or N% The goal stops at a cost of X USD, or at N percent of a plan limit. None
--until TIME The goal stops at HH:MM (the next such time), a date, or a date and time. None
--stall N The goal stops after N turns in a row with the same failing checks and output. 3 (STALL_DEFAULT)

Digits do not count when the engine compares the output of two turns, so a changed time does not hide a stall. A stop pauses the goal, writes the reason to the log, and tells Claude the reason (max-turns, budget, until, or stall) and the step. The user can fix the cause and run /goal resume.

Built-In Parts That Are Off

  • The hook denies the ProposeGoal tool and tells Claude that the user sets a goal with /goal.
  • The prompt slice leaves out the goal_status attachment.

Hooks

Hook Filter What it does
turn.complete None Runs the checks and sets the next prompt. It ignores a subagent turn, a turn that is not an answer, and a paused goal.
command.run /goal Answers the command.
command.describe /goal Gives the text of the engine.
tool.call ProposeGoal Denies the tool.

Cost

The goal slice makes /goal run real checks. A goal is a list of steps, and each step has checks, such as a command that must pass. Claude keeps working until the checks pass.

See Also

Clone this wiki locally