goal-loop
Bootstrap a goal-driven self-improving AutoNudge loop from a goal plus an anchor directory, then run the board autonomously until the Definition of Done is met.
SKILL.mdskills/goal-loop/SKILL.md
GitHubgoal-loop
Thin orchestration skill on top of self-nudge-loop. One extra file
(GOAL.md) and one extra script (scaffold.sh) that calls the underlying
self-nudge-loop scaffold and appends goal-specific conventions.
What you get
After running this skill's scaffold.sh, the anchor directory contains:
<anchor>/
├── GOAL.md ← your goal statement + issue-discovery rules (this skill)
├── LOOP.md ← DoD placeholder + REST arming recipe (from self-nudge-loop)
├── README.md ← directory map (from self-nudge-loop)
└── board/ ← kanban-md board, 6 columns (only when kanban-md is installed)
The loop agent re-reads GOAL.md + LOOP.md every cycle — but only because
the nudge you arm tells it to (step 4 under "Run it"): LOOP.md's own nudge never
names GOAL.md. That's the "mission briefing" — everything else is session state.
When to use
- User sets a concrete, verifiable goal ("get this test suite to 100% pass", "migrate all callers off module X", "drain DLQ Y").
- You want the agent to discover issues itself (grep TODO/FIXME, failed tests, open tickets) and convert them to board cards.
- You trust the agent to run for 10+ cycles autonomously without human per-step review.
When NOT to use
- One-off fix → just use the agent directly
- Already-defined backlog → use
self-nudge-loop/scaffold.shdirectly - Goal cannot be expressed as ≤5 shell-checkable DoD criteria → split the goal first
Prerequisites
kanban-md CLI — required for the board operations the loop agent runs
every cycle (its list, pick, create, move, edit and handoff
subcommands). It is a single-binary Go tool from
github.com/antopolskiy/kanban-md.
Install (pick one):
# Homebrew (macOS/Linux) — recommended, auto-updates
brew install antopolskiy/tap/kanban-md
# Go (if you already have Go on PATH)
go install github.com/antopolskiy/kanban-md/cmd/kanban-md@latest
# Pre-built binary from GitHub Releases
# https://github.com/antopolskiy/kanban-md/releases
# download the linux/amd64 (or matching) tarball, extract to ~/.local/bin/
Verify:
command -v kanban-md
The loop's commands were written for and checked against kanban-md 0.37.0; the
cycle uses its list, pick, create, move, edit and handoff subcommands.
If a newer kanban-md rejects one with unknown flag, compare that subcommand's
--help output with the command; the self-nudge-loop skill's commands and its
test are where they are kept in step.
If kanban-md is not on PATH, the scaffold skips board/ creation and
prints a warning. Install the CLI before arming a goal loop; this skill requires
the board for automatic claim and handoff.
The current scaffold also requires a readlink implementation that supports
-f (GNU coreutils). Stock macOS readlink does not provide that flag.
Kiro Crew autonudge_stop MCP tool — included with Kiro Crew. Used
by the agent to self-halt when DoD is met; no extra install is required.
Run it
From a repo checkout (this skill and its scaffold.sh are repo-checkout-only, so
the path below exists only where KIROCREW_PROJECT_DIR names such a checkout):
cd ~/.kiro/crew/skills/goal-loop
./scaffold.sh \
--project my-goal-name \
--anchor-dir /abs/path/to/goal/anchor \
--goal "Get MyService integration tests to green on AL2023"
Then:
- Open
<anchor>/LOOP.md— fill in 5 shell-checkable DoD criteria. - Open
<anchor>/GOAL.md— replace<PROJECT_TREE>and confirm the issue-discovery sources (defaults: tree grep, failed tests, user-reported issues). Add/remove. ls <anchor>/STOPmust say "No such file".- Arm the loop with LOOP.md's "Ready-to-paste nudge", prefixed with the line
Every cycle, read <anchor>/GOAL.md first; its rules override this nudge where they differ.(the scaffold prints it). Without that line the agent never reads GOAL.md and follows LOOP.md's nudge alone, including its "all blocked" exit. Arm viamonitor_start(message, interval_secs, max_cycles, max_runtime_secs)from a live session, the UI 🎯 "Set a goal", orPOST /api/autonudge. Revise a running loop in place withPATCH /api/autonudge/{loop_id}(ormonitor_update), which keeps its cycle count;DELETE /api/autonudge/{loop_id}stops it.
The goal-loop cycle (what the agent does)
LOOP.md's nudge plus GOAL.md (read first, per the armed prefix) instruct the agent to, every cycle:
- STOP / DoD checks first — if STOP exists or all DoD criteria met, call
autonudge_stopand stop. - Resume or claim work —
kanban-md --dir <BOARD> list --claimed-by loop-<project> --json; resume a held card if any (a blocked one: release it as described under "not stop conditions" below and pick instead), otherwisekanban-md --dir <BOARD> pick --claim loop-<project> --status todoto claim the next unblocked todo. Keep the same project claimant every cycle. If none, go to 3. - Discover issues — run the discovery sources from GOAL.md. For each
finding not already on the board,
kanban-md create. Then pick. - Execute one atomic step on the claimed card (≤5 tool calls).
- Record — edit card body with
<UTC> cycle-<n>: <verb> <outcome>, and callsession_ledger_recordwith the phase,nextas a concrete intent, and any approach tried and rejected. The ledger survives context compaction; a card's Cycle Log does not. On resume, readsession_ledger_readbefore re-deriving state from the board. When the card is ready for human approval, move it to Review withkanban-md --dir <BOARD> handoff <id> --claim loop-<project> --note "<summary>" --release(--releasedrops the claim so the next cycle's--claimed-byscan does not resume a card already in Review). - Notify on milestones only — a phase boundary, blocker or completion, via
send_message. With nosessionargument it is a dashboard notification; passsession="slack"(or another channel) for an owner DM. No per-cycle tick.
Operating invariants
Inherited verbatim from self-nudge-loop/LOOP.md §"Operating invariants".
See that file. The short list:
If the armed nudge has gone stale, revise it with
monitor_updaterather than re-arming, which loses the cycle countNever
git pushNever read credential files as text
Never hand-edit kanban .md files — use
kanban-mdCLIOne cycle = one atomic step
Stay silent in chat unless DoD met, hard blocker, or STOP tripped
Persistence rule (CRITICAL)
The agent self-stops in exactly three cases:
- User stop — the configured
STOPsentinel exists → callautonudge_stop(reason="sentinel"). - Goal achieved — all DoD criteria in
LOOP.mdcheck green → callautonudge_stop(reason="DoD met"). - Unrecoverable infrastructure error — the host/tooling itself is
broken in a way the agent cannot route around: disk full, network
partition, auth provider down for >3 cycles, kanban-md binary missing
from PATH mid-loop, kernel OOM, etc. Log one-line diagnosis to the
Cycle Log and call
autonudge_stop(reason="infra: <what>").
The service may also deactivate the loop on its finite cycle/runtime bounds or an approval stall. Those are bounded stops, not evidence that the goal succeeded.
Everything else is a problem to solve, not a reason to halt. Examples of things that are NOT stop conditions:
- Test failures, build errors, lint errors → fix them, that's the job
- "I don't know how" → read code, grep, check logs, try a smaller probe, add a research card to the board, read a skill for context
- A card seems blocked → split it, unblock dependencies, or mark the
blocker explicit with
kanban-md --dir <BOARD> edit <id> --block "<reason>" --release(it drops the claim, so the--claimed-byresume scan stops returning the card) and pick a different card - A tool returned an error → read the error, correct the invocation, retry
- The goal feels unreachable → re-read GOAL.md, decompose into smaller cards, run discovery again
- You already tried X twice → try Y; if Y fails, try Z; never stop on "tried twice"
- It's late in the cycle budget → keep working; the service enforces
max_cycles, not you
The agent never creates the user's STOP sentinel itself. It calls
autonudge_stop only for the three cases above; service-enforced bounds remain
independent. When in doubt: keep going, find another angle, create a new card,
and tick.
Extension points (future)
--seed-backlog <file>— pre-populate the board from a newline-delimited list of card titles--agent <name>— write anagent:hint to GOAL.md so loops launched from chat pick up a specialist--discovery <source>— multi-select: grep, taskei, tod-failures
Out of scope for v1. Ship the tiny version, iterate when you hit a real missing feature.