Open source · MIT · Python 3.11+

Your coding plan is billed by the month, and consumed by the hour.

Vibe Board spends the hours you are not awake for. Point it at any repository: it turns a plan into tickets, launches one agent per ticket into its own git worktree, tests every branch before it merges, and waits out rate limits by itself instead of stopping.

Get started View on GitHub no database · no bundler · no cloud
127.0.0.1:8000 — the board reads and writes files in your repo
The Vibe Board kanban: tickets across To do, Claimed, In review, Done and Blocked, with spend, active agents, tokens and needs-attention counters above.
19
runs
$29.29
total spend
548,378
tokens
163m
agent time
One real project's history, broken down by ticket, agent, model and outcome. A fleet you cannot cost is a fleet you cannot run — so the board shows you this by default.

The problem

You hit the limit at 4pm. The window reopens at 9pm, and by then you are not there. The next morning you relaunch by hand and re-explain the project to a fresh agent whose context was cut.

The subscription is paid for whether or not anyone is awake to use it. The gap between what you bought and what you can actually consume is not a model problem — it is an orchestration problem, and it is the one this project exists to close.

Press Finish the project and the board works the backlog until nothing is launchable — then tells you honestly whether that means done, blocked, or waiting on your review.

autopilot — unattended completion
The autopilot panel showing the supervisor loop, its current ticket, and quota waiting state.

A limit is not a failure — it is a known future timestamp. When every account is cooling, the supervisor sleeps until the earliest reset and resumes by itself. That single behaviour is the largest recovery of otherwise-idle plan hours the board makes.

It survives being cut

Every transition is written to .vibe/runtime/autopilot.json before it is acted on, so a supervisor killed by a closing lid is resumable — and "what was it doing" is a file read. It also holds the machine awake while a run is in flight, and lets it sleep again the moment it goes idle.

It stops itself

Retries are bounded, waiting is bounded, and a board with nothing launchable ends the run rather than spinning. With no test command configured nothing is merged at all — every branch parks for review, and autopilot says so before it starts rather than after.

Then it tells you

Desktop notification, webhook, or an appended log — any combination, per project. The webhook is the one that reaches someone who has walked away, which is the case autopilot exists for; the log is the only one that leaves a record.

What you get

A control plane, not another chat window.

Everything below is a screenshot of the running board, not a mockup.

The agents view: one run per ticket with its worktree, branch and live status.

Launch a whole sprint at once

One agent per ticket, each in its own worktree and branch. Auto mode runs to completion; duo mode parks and waits for you. Runs survive a crash, because every run is a file on disk.

Telemetry: cost, tokens, duration and outcome per run.

See the bill

Cost, tokens, duration and outcome for every run — and a warehouse that merges every project into one local SQLite file, so "what did last week cost across all of them" is a query, not ten dashboards. Reported costs are used verbatim and labelled as reported; the rest is labelled an estimate.

Review and merge: agent branches with diffs and commits.

Nothing merges unreviewed

Every agent branch with its diff and its commits. The suite runs on that branch's own worktree, and merging refuses rather than forces — no conflicted mess left in your index.

Needs attention: runs classified by why they stalled.

Know what is stuck, and why

Rate limit, permission denial, crash, or a real test failure — classified, not dumped, with the ones the board can safely fix marked as such. Agent blockers arrive as a queue you can act on, not as text buried in a log.

New project wizard turning a description into a full plan.

Idea → full project plan

Brief, spec, architecture, sprints, tickets, agent roles, protocol. From a document, or from one sentence. The transformation is a versioned prompt library, so the same input regenerates the same structure. No source document? The intake stage is told so, and raises open questions instead of inventing answers.

Locks and worktrees: nine agent slots with their branches and ports.

Nine agents, nine sandboxes

A worktree, a branch and its own port range per slot. Advisory locks serialise the genuinely shared files, so two agents never believe they own the same code.

Project settings showing the token-compression addon layer.

Cut what runs cost

Plug in token-compression tools per project. The board verifies they actually engaged before crediting them with anything — an addon that could not engage is not recorded on the run it did not touch.

Proof runs: test suite results and scripted browser walkthroughs per ticket.

Prove it actually works

Run the suite from the board, and script Playwright walkthroughs that drive the running app, record a video and assert on what they see. The spec is the recorded claim that a ticket works; the result is whether it still does. Requirement coverage is tracked from the ticket IDs.

The three ideas behind it

Boring where it counts.

Everything is a file in your repo

Board, tickets, run records, locks. No database, no daemon that must have been running. Kill the server mid-run and a fresh process reads the files back and knows exactly what was in flight, what stalled, and what is waiting on a human.

The core has zero dependencies

Python 3.11 and the standard library. It boots on a bare machine. The UI is one HTML file — no CDN, no bundler, not a single network request to render the page you are looking at.

It is honest about numbers

A compression tool that failed to engage is not credited on the run it did not touch. A board whose remaining tickets are all blocked is reported as blocked, not done. Only done means done.

How parallelism stays safe

The overlap check runs before the wave, not after the merge.

Every ticket declares a role, a lane, and the files it owns. A lane is one agent's serial queue; files_owned is an exclusive claim.

Containment counts, not just equality — a ticket owning api/app/core/ collides with one owning api/app/core/config.py. This is the check that stops the most expensive failure a parallel fleet has: two agents editing the same file, one silently losing its work at merge time.

# non-zero exit on a real conflict
vibe-board check-overlap myproject S1 S2

# a lane is one agent's serial queue
# files_owned is an exclusive claim
# containment counts, not just equality

When an agent cannot proceed without touching something it does not own, it writes a blocker rather than widening its own scope — and the board shows those blockers as a queue, not as buried text in a log.

Accounts and models

It runs on the plans and CLIs you already have.

No API key, no separate billing relationship. Runs bill to whichever coding CLI is already signed in — and if you keep more than one login, the board routes around whichever one is tired.

A config directory is not an account

Two directories can share one login. Scheduling two concurrent runs onto them is scheduling two runs onto a single quota pool — and you find out when both stall. The board groups by the login's own accountUuid, read from each config directory, never by directory path.

A run can be pinned to a specific account, so work continues on a second plan when the first hits its limit. Accounts can be detected, added by hand, enabled, disabled, or marked as cooling down.

No provider exposes remaining quota. The board does not pretend otherwise — it tracks what it can actually observe, and says a limit was hit rather than predicting one.

two config directories, one account
The Models drawer: two Claude accounts and a Kimi provider. The 'dev' account lists two config directory paths and two launchers under a single entry.

dev here is one account reached by two directories and two launchers — grouped, so the board never schedules two runs onto it believing they are independent.

vibe-board accounts detect
vibe-board accounts disable claude2
vibe-board accounts set-status claude1 cooling_down
Driver profile Drives
claudeClaude Code CLI against Anthropic
claude-compatibleSame binary, another compatible endpoint
kimiKimi CLI, cost estimated
genericAny other CLI, via an argv template

Kimi's credentials file is detected but never read — that is exactly the kind of file this tool should not be pulling into anyone's context.

The orchestrator

Ask where things stand — at turn one or turn two hundred.

Press Briefing and the orchestrator answers from the board, the run records and the autopilot state as they are at that moment — not from a transcript of everything you have ever said to it. That keeps the answer accurate, and keeps it cheap: the same price on the two-hundredth question as on the first.

Per-ticket chats are scoped to their ticket and thrown away when it closes. No conversation on the board grows without bound.

Chat cannot launch anything. The orchestrator runs in plan permission mode: it reads, reasons and recommends, but never edits files or dispatches agents as a side effect of a reply. Launching stays an explicit action. A chat box that can silently mutate the project is a far larger trust surface than one that only talks.

the orchestrator drawer, scoped to this board
The Orchestrator drawer open beside the board, with quick actions for a status summary, a board sweep, what is blocked, and what to dispatch next.

Orientation is bought once

An agent starting on a repository spends its first several turns finding out where things are. Cut that run mid-ticket and the orientation dies with the context — the next attempt buys it again. On a fixed-price plan that re-derivation is often the majority of a short run.

So it gets written down

When a ticket closes, what it established goes to .vibe/skills/: the files it actually changed, the commands that worked, the notes it left. Later agents whose own files_owned overlap get those notes in their opening prompt.

Without a second model call

It is extracted from the run's own record, not generated. An accelerator costing a model call per ticket would fail exactly when the quota is exhausted — which is precisely when resuming matters most.

Safe by construction

A worktree is not a security boundary.

An agent that can run commands can run any command. A git worktree isolates which files it edits — it does not stop curl, rm, or reading ~/.ssh. So run the fleet in a container, where the agent sees your repository and nothing else.

printf 'VIBE_UID=%s\nVIBE_GID=%s\nPROJECT_DIR=%s\n' \
  "$(id -u)" "$(id -g)" ~/code/my-project > .env

docker compose build
docker compose run --rm board add /work/project --name project
docker compose up                    # → http://127.0.0.1:8000

Unprivileged user holding your uid, all capabilities dropped, no-new-privileges. Files the agent writes belong to you, not root.

There is a middle setting, too. By default an agent may write files in its worktree but not run commands; bypassPermissions lets it run anything. Between them, allowed_tools takes an allowlist — so an agent can run its tests and its git commands, and nothing else:

[runtime]
permission_mode = "acceptEdits"
allowed_tools = "Bash(git*) Bash(pytest*) Bash(npm test*)"

Two things the container deliberately does not do. It does not restrict network access — the agent must reach a model API, so it can reach other things too. And it mounts your coding-CLI credentials, because a run has to authenticate as somebody. Both are stated plainly in the security policy rather than left for you to discover.

60 seconds

From a repository with no plan to a board full of tickets.

You need Python 3.11+, git, and a logged-in coding CLI on your PATH — by default claude. No API key: runs bill to whichever plan that CLI is already signed into.

git clone https://github.com/troumba-ai/vibe-board && cd vibe-board
alias vibe-board="PYTHONPATH=$PWD/src python3 -m vibeboard"

vibe-board add ~/code/my-project --name myproject
vibe-board init myproject --description "What I'm building, in one sentence."
vibe-board promote myproject
vibe-board serve --project myproject          # → http://127.0.0.1:8000

Already have sprint files? Skip init and point the config at them. No install step, because the core is the standard library and nothing else — a pip install release is coming, and until it lands the clone above is the supported path.

The integration surface

One file in your repo, and a CLI that does the rest.

A target repository carries a single .vibe/config.toml: where its board lives, how it names worktrees and ports, which lock keys are its hot set, which driver and permission mode to use. Written by vibe-board add and safe to edit by hand — the board preserves your comments.

Ticket ids do not have to look like S1-T1; the pattern is yours. Secrets are referenced as ${VAR} from the board's own environment, so the committed file never holds one.

The project registry lives outside your repositories, at ~/.vibe/projects.toml. Nothing about the board is global state you have to keep in sync.

vibe-board add · list · remove          projects
vibe-board serve · status               the board

vibe-board agent start · list · stop    runs
vibe-board autopilot start · status · stop

vibe-board init · promote               idea → plan
vibe-board check-overlap                before a wave

vibe-board accounts list · detect · enable
             · disable · set-status · add · remove
vibe-board addons list · enable · disable
             · doctor · savings
vibe-board telemetry sync · report · query
vibe-board demo list · run

Where it is going

Shipped, and next.

Shipped: project registry, agent runtime, initializer, proof runs, telemetry warehouse, multi-account routing, compression addons, container image, and autopilot — unattended completion with quota waiting, skill reuse and notifications.

Ticket graph next

Machine-readable depends_on, a derived board, per-ticket threads, and wave computation from the real dependency graph.

Model strategies next

Which model runs which ticket, as a named policy: routing by lane, a frontier model gating a cheaper one, escalation on repeated failure.

Measurement next

Cost preview before dispatch, ticket replay from a pinned commit, scope violations enforced as a merge gate.

MCP server next

Expose the board's operations as MCP tools, so an orchestrating agent drives the fleet directly.

Compression benchmarking next

Answer "does this tool pay off on my code" from measured runs rather than vendor claims.

Authored demo specs next

Demos run and record today, but their specs are written by the agent that built the ticket, or by hand. Deriving a walkthrough from the ticket and the shipped UI — and keeping it honest as the UI moves — is not built.

Hosted autopilot next

The local loop is bounded by one machine being awake and one plan's quota. Neither is a property of the design, and removing them is infrastructure — not a feature withheld from the open-source version.