Two small corrections found while checking 0.4-alpha's deploy. wrangler.jsonc claimed the slashless form redirects with a 301; measured against the live site it is a 307. The code is the host's choice rather than anything this repo sets, so the post-deploy check now says to confirm that it redirects at all — the property the site depends on — and records the observed code beside it rather than asserting one. Card 43 already describes the two test_boards_sync failures a team-mode checkout sees, and still describes them correctly; only its pointer into the test file had drifted — reload() sits at 598 now, not 481. config.py:53-69 is still exact. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Bench
A live kanban for coding-agent work: task files in stage directories are
the only source of truth; a stdlib-only board narrates everything that
happens to them — agents working in git worktrees, PRs opening on review,
CI and Copilot state on the cards, drives of the app from a task's own
branch, and an archive that is never a delete. Work that is a run of
related cards rather than one is a phase: a card that lists its
cards, an integration branch of its own, and members branched from it,
run one at a time and merged back on green — ending in a single PR into
main for a human. Turn on team mode
(BOARD_SYNC=1) and the truth is origin/main: moves commit and push
themselves, every board pulls on a beat, and the person who claimed a
card first keeps it.
Docs: bench.12vectors.com — guides, concepts, and a settings reference, every page of it generated from this repository's own markdown, so what the docs say and what bench does cannot drift apart.
bench's own board, running on this repository. Three agents at work, each on its own branch — and every one of them stops at review.
Install into a repo
mkdir .task-manager && curl -L \
https://github.com/12vectors/bench/releases/latest/download/bench.tar.gz \
| tar -xz -C .task-manager
./.task-manager/start.sh # wires the project (idempotent) and serves
No token, no clone: releases are curated artifacts that never contained bench's own cards or settings, so the board starts empty by construction.
The first run asks the two questions it cannot answer for you — solo or
team, and which agent adapter — and writes manager/local/.env from the
documented example, so every other setting is discoverable in your own
copy. What runs your tests is read off the project rather than asked
(package.json → npm test, and so on); nothing recognisable leaves
BOARD_AGENT_COMMANDS empty, and that is the key to set before an agent
can run them. Bare Enter takes the default
throughout; with no terminal (CI, a script) it asks nothing and
install.py --setup asks later.
Commit .task-manager/ into the host repo — core is vendored on purpose,
so clones work offline and updates show up in the host's own diffs.
The workflow brief ships as .task-manager/AGENTS.md — the cross-vendor
name coding agents read natively — with CLAUDE.md beside it as a one-line
compatibility pointer. Both live inside .task-manager/, so a host repo's
own root AGENTS.md is never touched.
Update
./.task-manager/update.sh # latest release
BENCH_REF=v2 ./.task-manager/update.sh # an exact release tag
The artifact is stamped with the repo it was built from, so updating
needs no configuration; BENCH_SOURCE=<owner/repo> in
manager/local/.env overrides the stamp. Updates replace
manager/core/ and the top-level scripts wholesale and touch nothing
else — tasks, plans, reference, and everything under manager/local/
(your driver, commands, prompt overrides, settings, state) survive every
update. Then python3 .task-manager/install.py and restart the board.
If the source repo has no published release yet, update.sh says so and
changes nothing.
Working on bench itself
git clone git@github.com:12vectors/bench.git && cd bench && ./start.sh
A clone carries bench's own cards and local/ content — that is dev mode,
not an install. (Installing from a clone anyway works: install.py
clears the shipped cards on its first boot in a host repo.) Releases are
built by ./release.sh from the manifest at
manager/core/release-manifest: tag = v<VERSION>, one stable asset
name (bench.tar.gz), contents at the tarball root — the two things the
install one-liner above depends on.
The three-layer law
Core knows about tasks, worktrees, PRs and events. It knows nothing about
any particular app (drivers do: manager/local/driver/start), agent
vendor (adapters do: manager/core/adapters/), or project
(manager/local/ does).
The consequence is what makes an update safe: update.sh replaces
manager/core/ wholesale, and everything a project taught bench about
itself lives outside it. Full docs in AGENTS.md — the file
the docs site is cut from, and the one an agent working in your repo
reads; the adapter contract in
manager/core/adapters/README.md.
License
MIT.
