Skip to content

Storybloq/Until

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

do-until

Convergence-loop tool for Claude Code. Automates "do, check, repeat" cycles using a Stop hook and state file.

/until "Fix all lint warnings"

The same Claude session does the action and the check. A Stop hook reads a state file between turns and either intercepts the stop with a new prompt or lets the agent finish. The loop ends when the agent reports approve or hits an iteration cap.

Requires Claude Code (the Stop hook only fires inside Claude Code sessions), Node.js 20+, macOS or Linux.

Install

npm install -g do-until
do-until setup

do-until setup installs three things: the /until slash command at ~/.claude/commands/until.md, the Stop hook wrapper at ~/.until/bin/do-until-hook-stop, and a Stop hook entry in ~/.claude/settings.json. Run do-until setup --remove to uninstall all three.

Usage

In Claude Code, type /until followed by your task:

/until "Make all tests pass"
/until --max 3 "Fix all TypeScript errors"
/until --check "npm run lint exits 0" "Fix lint warnings"

Type do-until in bash for CLI commands:

do-until status          # show active sessions
do-until cancel --session <id>

The slash command is /until (no shell involved). The CLI binary is do-until (avoids bash keyword conflict with until).

How it works

  1. /until writes action + check to temp files, calls do-until start
  2. Agent works on the task, then naturally ends its turn
  3. Stop hook fires, transitions state to CHECK, and re-prompts the agent with the check instructions
  4. Agent verifies its work, calls do-until report --session <id> --verdict approve|request_changes
  5. If request_changes: loop back to step 2 with the findings included in the next prompt
  6. If approve: the agent stops, done

The loop also ends without approve in three ways:

  • max iterations reached: the agent receives a closure prompt to summarize what was done and what remains
  • agent fails to report a verdict after 3 reminders: same closure prompt
  • manual cancel: do-until cancel --session <id> clears state and ends the loop silently

Agents can use it on themselves

The same loop works whether a human types /until or an agent calls do-until start directly via Bash. Agents tend to declare work done before it's verified; wrapping ambiguous-success tasks in a do-until loop forces the agent to grade against a falsifiable check before exiting. Useful for multi-file refactors, migrations, and "fix all X" tasks where iteration 1 usually leaves residue.

mkdir -p "$HOME/.until/tmp"
STAGE=$(mktemp -d "$HOME/.until/tmp/XXXXXX")
echo "Refactor X to use Y" > "$STAGE/action.txt"
echo "tests pass and no occurrences of X remain" > "$STAGE/check.txt"
do-until start --action-file "$STAGE/action.txt" --check-file "$STAGE/check.txt" --max 5

From there the Stop hook takes over: agent works, hook injects the check prompt, agent verifies, reports a verdict. Same mechanics as the slash command.

To make this the default discipline for an agent, add a line to CLAUDE.md: For multi-file refactors, migrations, and similar "fix all X" tasks, wrap the work in do-until start so verification is enforced, not optional.

Convergence quality

do-until works best with falsifiable checks: lint exits 0, tests pass, typecheck clean, specific string absent from output. The same model writes the code and grades it, so its blind spots are not caught independently. Subjective checks ("is this well-designed?") expose that weakness; anchor on mechanical evidence instead.

Troubleshooting

  • do-until status lists active sessions with state and iteration count
  • do-until cancel --session <id> clears a stuck session
  • Session state lives in ~/.until/sessions/<id>/state.json; the per-session event log is at ~/.until/sessions/<id>/log.jsonl
  • Hook errors are appended to ~/.until/last-error.log
  • If a loop misbehaves, check ~/.claude/settings.json for other synchronous Stop hooks that may conflict

Privacy

All data stays local in ~/.until/. No telemetry, no cloud sync. do-until cancel --session <id> clears state and logs.

About

Bring while-loops to Claude. Wraps any task in a do/check/repeat loop that terminates on a falsifiable verdict. Stop-hook driven loop.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors