Skip to content
Development
Skill

/build-until-pass

Use when a build, typecheck, lint, or test command is failing and you want the agent to drive it to green on its own — run the check, read the errors, apply the smallest fix, re-run, repeat until exit code 0. Stops the human from being the while-loop (run → read error → fix one

BOOST
From plugin
lich-skills
23112 skills
Install
$ npx -y skills add lichamnesia/lich-skills --skill build-until-pass --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/build-until-pass

Context preview

The summary Claude sees to decide when to auto-load this skill.

Use when a build, typecheck, lint, or test command is failing and you want the agent to drive it to green on its own — run the check, read the errors, apply the smallest fix, re-run, repeat until exit code 0. Stops the human from being the while-loop (run → read error → fix one

SKILL.md

build-until-pass.SKILL.md
name: build-until-pass
description: Use when a build, typecheck, lint, or test command is failing and you want the agent to drive it to green on its own — run the check, read the errors, apply the smallest fix, re-run, repeat until exit code 0. Stops the human from being the while-loop (run → read error → fix one line → run again) and stops the agent from bulldozing huge speculative rewrites between checks.

Build Until Pass

A bounded self-correcting loop: run the project's check command, capture its errors, apply the **smallest** diff that addresses the first failure, re-run, and repeat until it exits 0 — or until a hard attempt cap is hit.

The core principle: **the check command is the judge, not you.** You do not declare the build "basically fixed." Green is `exit code 0`. Anything else is red, and red means another round.

This is the engineering-discipline counterpart to "run it and hope." The cap exists so the agent backs off instead of burning tokens thrashing on an error it cannot fix without human input.

When to Use

  • A build / compile / bundle command fails and the cause is mechanical

(type errors, missing imports, signature mismatches, bundler config)

  • `tsc`, `cargo build`, `go build`, `npm run build`, `vite build` exits non-zero
  • A typecheck or lint gate is red and you want it green before committing
  • A focused test suite is failing and each failure points at a clear fix
  • CI went red on a build/typecheck step and you're reproducing locally
  • You catch yourself copy-pasting errors back to the agent one at a time

When NOT to Use

  • You don't know the check command yet — find it first (see Phase 0)
  • The failure is a genuine *logic* bug needing investigation, not a mechanical

fix → use `debug-hypothesis` instead, then come back here to confirm green

  • The fix requires a product/design decision only a human can make
  • The "fix" would mean deleting tests, `// @ts-ignore`-ing real errors, or

loosening types to silence the compiler → that's cheating the judge, not passing it (see Anti-rationalizations)

  • The build passes already — there's nothing to loop on

The Loop

            ┌─────────────────────────────────────────────┐
            │  attempt > MAX_ATTEMPTS (default 10)?        │
            │  → STOP, report what's left, ask the human   │
            └──────────────────────┬──────────────────────┘
                                   │ no
   RUN CHECK ──▶ green? ──yes──▶  DONE (exit 0, report rounds used)
       ▲             │
       │             │ no (red)
       │             ▼
       │      READ ERRORS  ──▶  FIX SMALLEST  ──▶  re-RUN
       │      first failure     minimal diff,        │
       │      only, verbatim    no refactor          │
       └──────────────────────────────────────────────┘
                    one round = one fix + one re-run

Hard rules:

1. **Green is `exit code 0` from the check command.** Not "looks fixed," not "the error I saw is gone." Run it and read the exit status. 2. **One round = one targeted fix + one re-run.** Do not fix five unrelated things, then run once. You won't know which fix helped or broke something. 3. **Minimal diff per round.** Touch only the lines the current error points at. No drive-by refactors, no reformatting, no renaming. 4. **Hard attempt cap (default 10).** When hit, STOP and hand back to the human. Do not raise your own cap to "just try a few more." 5. **Report each round.** One line: `round N/MAX — <errors remaining> — <what I changed>`. 6. **Never silence the judge.** Suppressing an error (`@ts-ignore`, `any`, deleting a test, `|| true`) is not a pass. See Anti-rationalizations.

Phase 0: LOCK THE CHECK COMMAND

**Goal.** Know exactly what command defines "green" before you touch any code.

**Steps.**

1. Identify the check command. Look at, in order: the user's instruction, the project's CI config (`.github/workflows/*`), `package.json` scripts, `Makefile`, `justfile`, the build tool's convention. 2. If multiple are plausible (`build` vs `typecheck` vs `test`), pick the one the user named; if unstated, pick the narrowest one that reproduces the reported failure, and state your choice. 3. Run it **once, unmodified**, to capture the baseline failure and confirm it actually fails. A check that already passes means there's nothing to do. 4. Set `MAX_ATTEMPTS` (default 10 unless the user gave a number).

**Exit criteria.**

  • [ ] Exact check command written down (copy-pasteable)
  • [ ] Baseline run captured — confirmed non-zero exit
  • [ ] `MAX_ATTEMPTS` set

**Common Rationalizations**

| Excuse | Reality | |---|---| | "I'll just run `npm run build`, it's always that" | It's `tsc -b` in half of repos and a custom script in the other half. Read `package.json` — 5 seconds saves a loop spent fixing the wrong thing. | | "I don't need the baseline, I know it fails" | Then capturing it costs one run and proves the failure mode you're about to fix is the one that's actually there. | | "I'll set the cap later" | No cap means no stop condition. Set it now or the loop has no floor. |

Phase 1: RUN CHECK

**Goal.** Get the current ground truth: exit code + full error output.

**Steps.**

1. Run the locked check command. Do not modify flags between rounds — same command every round, or the judge moved. 2. Read the **exit code**. `0` → jump to Done. Non-zero → continue. 3. Capture the error output. If it's long, focus on the **first** error block — later errors are often downstream of the first and vanish once it's fixed.

**Exit criteria.**

  • [ ] Check command run unmodified
  • [ ] Exit code read explicitly (not inferred from log text)
  • [ ] First failure identified verbatim (file:line + message)

Phase 2: FIX SMALLEST

**Goal.** Apply the minimum change that resolves the first failure.

**Steps.**

1. Locate the first error's `file:line`. Read the surrounding code. 2. Apply the smallest correct fix: add the missing import, fix the type, matc

Read more
Ships withlich-skills

Personal skill collection for Claude Code, Gemini CLI, and OpenAI Codex — by @LichAmnesia. Telegraph-style, opinionated, no filler. Engineering judgment skills plus high-leverage utility tools. 中文版:README-zh.md

Get the whole plugin
Stats
231
Stars
26
Forks
Maintained
Maintenance
TypeScript
Language
MIT
License
4mo ago
Last commit
6mo ago
Created
10d ago
Added

Repo: lichamnesia/lich-skills

Other skills on lich-skills.