Your TODO.md, as a live board your AI agents work from.
Write stories in plain markdown — agent loops groom, build, and deliver them while you keep the only two keys that matter: what gets started, and what gets accepted.
LoopBoard is a VSCode extension that renders the open workspace's .loopboard/ tracker as an
interactive board: tick approval checkboxes, answer an AI worker's questions, review delivered
work, and spawn per-model Claude Code loop terminals — without editing markdown by hand.
⚠️ v2.0.0 is breaking — re-initialize your workspace. v2 moved storage from a single rootTODO.mdinto a.loopboard/directory (details below). There is no migration: the extension only recognizes the new layout and ignores a rootTODO.md. RunLoopBoard: Initialize Workspace(or the board's empty-state button) to scaffold.loopboard/, then port any old tasks by hand.
Markdown stays the single source of truth. Every edit re-reads the disk, applies one field-level
patch, and writes the whole file back canonically (atomic temp-file + rename), so humans, the
board, and multiple agent loops can share it safely — now per file. Accepted work is archived to
.loopboard/DONE.md.
.loopboard/
TODO.md slim task index — one entry per active task (id, phase, model, groomer, Q&A)
DONE.md accepted tasks, newest first (created lazily on the first acceptance)
LOOP.md workflow rules + the loop worker instructions the loops read every pass
tasks/<id>.md per-task detail: meta, description, notes, worklog, feedback, delivered
The board composes each card from the slim index entry plus its tasks/<id>.md. A task file is
created on the first detail edit (or the first loop write); on acceptance the index entry moves to
DONE.md while the task file stays in tasks/ as browsable history.
New → Backlog → In Progress → Review → Done (DONE.md)
↕
Feedback
- You describe a story in the "+ New story" composer (free text, no formatting needed) and pick which model grooms it and which model executes it.
- A loop grooms the draft into a full story — title, description, scope — and surfaces any decisions it needs from you as inline questions on the card.
- You promote it with a tick. A matching model loop claims it, works it, and parks it in Feedback whenever it would otherwise have to guess.
- You review the DELIVERED summary — write change-request feedback to send it back, or tick to accept and archive it.
The board performs only the two human gates (promote and accept); everything else is a field patch the loops react to on their next pass. No work starts and nothing ships without your tick.
The activity-bar sidebar is the at-a-glance summary — everything in it is read-only and click- through into the board:
Open this folder in VSCode and press F5 to start the Extension Development Host. The host
opens against this repo, whose .loopboard/ tracker drives the board — if it has none yet, run
LoopBoard: Initialize Workspace (or click the board's empty-state button) to scaffold it. Click
the LoopBoard icon in the activity bar for the sidebar summary, then Open Board (or run
LoopBoard: Open Board).
Node and every other tool run inside Docker — nothing is installed on the host. The host
needs only Docker, make, git, and VSCode. All toolchain commands are wrapped in the Makefile:
make install # npm install (typescript + @types/vscode only) in node:22
make build # tsc -> out/
make test # compile pure modules + run node --test round-trip / merge suites
make package # build a .vsix via @vscode/vsce
Zero runtime dependencies; the webview is vanilla HTML/CSS/JS with a CSP nonce on every script.
- Left rail — phases (New → Done) with counts and an amber attention dot when a phase needs you; per-model Loops with ▶ (start/focus) and ♻ (recycle) buttons; + New story.
- New — tick a task's checkbox to promote it to Backlog.
- Feedback — type an answer under each question; the loop resumes once all are answered.
- Review — read DELIVERED, optionally write review feedback (sends it back), or tick to accept
(confirm) → archived to
DONE.md. - New story composer — write free text, choose the groom/worker models inline; it lands as a
DRAFT:the loop grooms into a story. - Edits save on blur/Enter as field patches. If the file changed on disk under your edit, the disk value wins and a toast tells you.
| Setting | Default | Meaning |
|---|---|---|
loopBoard.permissionMode |
auto |
--permission-mode passed to the claude CLI |
loopBoard.defaultModel |
opus |
model that owns tasks with no model: field |
loopBoard.loopInterval |
1m |
interval used in the injected /loop line |
loopBoard.autoRecycle |
true |
recycle a model's terminal after it finishes a task |
loopBoard.models |
{} |
per-model overrides — customize the --model string, or hide a model |
The four built-in model slots — opus, sonnet, fable, haiku — are what you assign to tasks
(model: / groomer:) and what the sidebar Loops rows spawn. loopBoard.models lets you
override, per slot, the actual string passed as claude --model <string>, and toggle a slot on or
off. Each slot accepts either a string (shorthand for just the --model override) or an
object { "enabled": bool, "model": string }:
An empty or invalid model falls back to the slot's built-in default (the id itself). Overrides may
include the [1m] suffix or org aliases; anything outside [A-Za-z0-9._\[\]-] is rejected before it
reaches the terminal.
Migrating from "Claude TODO Board" (≤ 0.1.1): the extension, command, and settings ids were renamed from
claudeTodo.*toloopBoard.*with no fallback — re-enter any custom settings.json values under the new keys.
The ▶ buttons open a plain VSCode terminal named Claude <Model> in the workspace root and run
claude --model <m> --permission-mode <cfg> with a tiny bootstrap prompt that points the loop at
.loopboard/LOOP.md's Automation section — the standing instructions each loop re-reads every
pass. ♻ disposes and respawns for a fresh context. Loops die with the VSCode window (restart is one
click — all state lives in .loopboard/).
Treat .loopboard/ and workspace settings as trusted input. LoopBoard's core loop points an
autonomous claude session at .loopboard/LOOP.md's Automation block, running with the configured
loopBoard.permissionMode — which may be bypassPermissions. Anything written into LOOP.md (or
the task files it tells the loop to open), or into .vscode/settings.json, therefore steers an
agent that can run commands on your machine. This is inherent to what LoopBoard does, not a bug.
Consequences:
- A
.loopboard/from a source you don't control (a cloned repo, a shared workspace) is a prompt-injection vector with arbitrary-command-execution reach. - Review
.loopboard/LOOP.mdbefore starting a loop in a repo you didn't author, and setloopBoard.permissionModeno higher than you're comfortable running unattended.
VSCode Workspace Trust gates activation, but trusting a repo to open it is not the same as vetting
what its .loopboard/ will tell an agent to do.
MIT
