skill
agent-kanban
agent-kanban is a project-scoped task board that lets multiple AI agent sessions share one source of truth, and pick up each other's work when they crash.
Set up
Skills are installed by placing their folder where your agent loads skills.
The download comes from github.com/ArnoChenFx/agent-kanban itself, not from our server, so what you get is exactly what its author published.
Install instructions come from the README
README
synced Oct 26, 2026agent-kanban
English · 中文 · For developers · 开发者文档
A project-scoped task board that lets multiple AI agent sessions share one source of truth — and pick up each other's work when they crash.
The problem
You are running several coding agents against one repository. Maybe you run a main session plus a few subagents. Maybe an agent dies halfway through a task: a network blip, an OOM kill, a closed laptop, a SIGKILL from a supervisor.
What usually survives is work in a terminal scrollback that nobody can read later:
- Agent A was halfway through rewriting the auth layer. That context lived only in Agent A's prompt window.
- Agent B sees a task titled "fix auth" and starts from zero, or worse, starts conflicting with A.
- Nobody knows which of the three open branches is stale.
- The task list lives in a TODO file, the reasoning in the agent's output, the status in your head.
Every restart is archaeology.
What agent-kanban does
It gives each agent a lease on a task, an append-only event log, and a handoff protocol — so a new session can start with the previous session's actual context instead of a task title.
┌──────────┐ claim ┌───────────┐ write ┌──────────┐
│ session │ ─────────► │ task │ ──────────► │ progress │
│ A │ │ T-0007 │ │ 60%, ... │
└────┬─────┘ └─────┬─────┘ └────┬─────┘
│ │ │
│ lease expires, or agent crashes │
▼ ▼ ▼
┌────────────────────────────────────────────────────────────┐
│ event log (append-only, the single source of truth) │
└────────────────────────────────────────────────────────────┘
│ │
│ handoff │ rebuild
▼ ▼
┌──────────┐ ┌──────────┐
│ handoff │ ─────────► │ session │ agent-kanban resume T-0007
│ note │ │ B │ → gets the handoff + timeline
└──────────┘ └──────────┘
Four ideas carry the whole design:
1. Task ownership is a lease, with an expiry.
agent-kanban task claim T-0007 gives the current session a time-boxed lease (15 min by default). Progress and checklist items are preserved. When the lease runs out, whether the agent crashed, was killed, or just walked away, the server reclaims the task automatically. The next context call tells the new session the card is up for grabs. Nobody has to run a cleanup script.
2. The event log is the source of truth; the board is a projection.
Every state change is an event: task_created, task_progress, handoff_created, plan_superseded. The tasks and plans tables are derived. That means agent-kanban rebuild can recompute the entire board from the log and diff it field by field against what's stored:
$ agent-kanban rebuild
agent-kanban replayed 412 events (23ms)
Recomputed: tasks 18 · deps 6 · plans 4 · handoffs 5
✗ found 4 drifts (the stored projections ≠ the result recomputed from the events)
tasks.T-0012 field status
stored: todo
recomputed: doing
... and 3 more
Fix: agent-kanban rebuild --write --force
(--write overwrites tasks/plans/handoffs/task_deps with the event stream)
$ agent-kanban rebuild --write --force
agent-kanban replayed 412 events (19ms)
Recomputed: tasks 18 · deps 6 · plans 4 · handoffs 5
✓ the projections match the event stream exactly
the projections have been overwritten with the recomputed result
If the log and the projection ever disagree, you find out then, rather than six weeks later.
3. Handoffs are written by the agent, not generated by the system.
When a session stops, it writes a handoff: what's done, what's next, what's blocked, what open questions remain. agent-kanban resume shows that first. Crash-generated handoffs exist as a fallback, and they explicitly say "the previous holder is unreachable", so you never mistake a dead session's guesses for a live one's instructions.
4. Plans are versioned rather than overwritten.
agent-kanban plan save always creates a new version and marks the old one superseded. agent-kanban plan history shows the chain; agent-kanban plan at --ts shows what was in effect at any moment. When a task is done and someone asks "why did we do it this way?", the answer is still there.
Quick start
Option A — one-line install (no runtime required)
# macOS / Linux
curl -fsSL https://raw.githubusercontent.com/ArnoChenFx/agent-kanban/main/install/install.sh | bash
# Windows (PowerShell)
irm https://raw.githubusercontent.com/ArnoChenFx/agent-kanban/main/install/install.ps1 | iex
The script detects your platform, downloads the matching binary, installs it to a
per-user directory (~/.local/bin, or %LOCALAPPDATA%\Programs\agent-kanban on
Windows) and adds it to your PATH. No administrator rights, no sudo. Re-run the
same command to upgrade.
agent-kanban init # create a board in the current directory
agent-kanban install-protocol # teach your agents to use the board
agent-kanban serve # → http://127.0.0.1:7788/
Pin a version with AGENT_KANBAN_VERSION=0.1.5. There is no Linux arm64 binary;
the script tells you so and points you at Docker, which is multi-architecture.
Prefer to download by hand? The binary is self-contained (the Bun runtime, the database schema and the whole web UI are embedded). Get it from Releases:
chmod +x agent-kanban-linux-x64 # macOS: agent-kanban-darwin-arm64 · Windows: agent-kanban-windows-x64.exe
./agent-kanban-linux-x64 init
./agent-kanban-linux-x64 serve
To upgrade later, run agent-kanban update (or --check first to peek). It fetches the latest release, verifies it against the published .sha256, replaces the binary in place, and keeps the previous one as <name>.old. When running from source or in Docker, it prints the matching upgrade path instead.
Option B — from source
Requires Bun ≥ 1.4.2.
bun install
bun run build:binary # build frontend, embed assets, compile
./dist/agent-kanban init
./dist/agent-kanban serve
Option C — Docker
cp .env.example .env
# Set KANBAN_ADMIN_TOKEN — generate one: openssl rand -hex 16
docker compose up -d
The image does not ship a compiled binary. It runs the TypeScript sources directly on oven/bun, so there is no build step in the image and only one copy of the Bun runtime.
Compose pulls the published image from GitHub Container Registry — releases push to GHCR only, never to Docker Hub. The image reference is pinned in docker-compose.yml; edit that one line to use a different tag or namespace. KANBAN_BIND and KANBAN_PORT control how far the server is reachable and which host port it binds.
Daily use
# 1. Start a session (registers who you are)
agent-kanban session start --agent pi-main --harness pi
# 2. Read the situation — this is the first thing you should do
agent-kanban context
# → your handoffs, what you're working on, what you could claim
# 3. Claim a task (acquires the lease)
agent-kanban task claim T-0007
# 4. Work, and keep the board honest as you go
agent-kanban task progress T-0007 --pct 60 --note "Storage layer rewritten"
agent-kanban task check T-0007 --item "Add migration test"
# 5. Stuck? Say so, and the lease is released
agent-kanban task block T-0007 --reason "Waiting on API key from ops"
# 6. Stepping away? Leave a real handoff
agent-kanban handoff --task T-0007 \
--summary "Auth rewrite done, token refresh left" \
--next "Start from refreshToken(); see plan v2" \
--blockers "Needs staging API key" \
--open "Rotate refresh tokens on every use?"
# 7. Done
agent-kanban task done T-0007 --note "Tests green"
agent-kanban session end
Coming back after a crash
agent-kanban context # what's mine, what's free, who crashed
agent-kanban resume T-0007 # take over: handoff + full timeline injected
You get the previous session's notes, the ordered list of every change made to the task, and the current plan version — not a blank card titled "fix auth".
Several agents in one directory
Each agent gets its own identity automatically, so two agents in the same checkout stay separate without exporting anything:
# terminal 1 # terminal 2
agent-kanban session start --agent pi-main --harness pi
agent-kanban context # agent-b: same thing, separate session
The identity comes from a per-session variable the agent harness already exports, and lands in
.kanban/sessions/<key>, one file per agent. The old single .kanban/session file is used only by
processes that have no such variable, so a keyless shell never borrows someone else's identity.
| Agent tool | Variable it exports |
|---|---|
| pi | PI_SESSION_ID |
oh-my-pi (omp) | PI_SESSION_FILE (a path — only the file name is used) |
| Claude Code | CLAUDE_CODE_SESSION_ID |
| Grok | GROK_SESSION_ID |
| Codex | CODEX_SESSION_ID (the root session, not the thread) |
| DeepSeek Harness | DSH_SESSION_ID (only present for agent-initiated shell calls) |
| Qoder | none — no automatic session identity |
| anything else | any <TOOL>_SESSION_ID in the environment is picked up automatically |
If your agent tool exports nothing usable (cursor-agent doesn't, as of this writing), or you want to be explicit, set the key yourself:
export KANBAN_SESSION_KEY=my-agent # any stable unique value
agent-kanban session start --agent codex-main --harness codex
session start prints the identity it picked, so you can confirm two agents really did land on
different keys:
session_id : s-ayj4se
agent : pi-main (pi)
identity : pi-01a0debe-ca55-752e-895f-c20eb141ac19
The web board
agent-kanban serve hosts a real UI on port 7788. It serves the board, the admin page, and the
same API the CLI talks to — one data path, no second source of truth.
agent-kanban serve # → http://127.0.0.1:7788/
agent-kanban serve --port 9000 --host 0.0.0.0 # --host 0.0.0.0 needs the TLS note below
agent-kanban serve --reap-interval 30 # how often the server reaps dead sessions
Getting in — every /api/* needs a token
The browser has no ambient authority, so the first screen asks for a token. There are exactly three ways to get one:
| Where the token comes from | How |
|---|---|
| Admin token, auto-generated | The first serve on a machine prints it once and writes it to .kanban/config.toml under [server] admin_token. If it came from KANBAN_ADMIN_TOKEN it is never printed — read the file. |
| Project token, issued | agent-kanban admin token create --project my-app --name "CI runner" — prints the plaintext exactly once. |
| A shareable link | http://host:7788/?key=k_…&project=my-app — read from the URL, then stripped from it. |
Paste the token into the login card. The project field is optional: leave it blank and the board picks the first project the token can reach. A token may be granted several projects, which is what the switcher in the header is for.
| Token type | Reaches |
|---|---|
| Project token | only the projects it was explicitly granted |
| Admin token | every project, plus project and token management |
What the board does
- 7 swimlanes — Backlog, Todo, Doing, Blocked, In Review, Done, Cancelled
- Drag and drop with state-machine validation; an illegal move is rejected with the reason
- Task drawer — overview (description, checklist item by item with who ticked it, dependencies/parent), timeline, handoffs, plan version history
- Live updates via SSE, with cursor resume after a reconnect
- Multi-project switcher, light/dark mode
- Chinese / English UI — one click in the header, on both the board and the admin page (
/admin), sharing a single preference; first visit follows the browser language - Shareable links —
?key=…&project=…; parameters are stripped from the URL after reading
The web UI and the CLI operate on the same data through the same code path. Anything you can do in the browser, an agent can do from its shell.
The admin page at /admin
Create projects, issue tokens, change which projects a token may reach, revoke tokens. Revocation takes effect on the next request — there is no session to expire.
/admin requires an admin token. A project token gets 403 with the reason spelled out, which
is deliberate: forbidden means "valid token, wrong role, go get another one", while invalid means
"go get a fresh token" — different problems, different fixes.
If the frontend was never built, serve falls back to a built-in placeholder page that lists the
API surface instead of pretending to be a board: GET /api/health (no auth), POST /api/op
(needs X-Kanban-Key or Authorization: Bearer), POST /api/stream-ticket + GET /api/stream
(SSE), and /admin.
Before you expose it
serve does not terminate TLS and binds 127.0.0.1 by default. Put it behind a TLS terminator
before binding 0.0.0.0 — without TLS, tokens travel in plaintext. See Security.
In Docker the board is on the same port as the API; KANBAN_PORT sets the host port and
KANBAN_BIND the host-side bind address (the container itself always listens on 0.0.0.0).
The browser keeps your token in localStorage so a refresh does not log you out. The price is that
XSS can read it, which is why this project forbids innerHTML outright.
Sharing a board across machines
One agent-kanban serve process can host many projects. Each project is fully isolated: its own tasks, its own tokens, its own ID space (T-0001 starts at 1 in every project).
# On the server machine
agent-kanban serve # prints the admin token once
agent-kanban admin project add my-app
agent-kanban admin token create --project my-app --name "CI runner"
# → k_a1b2c3...
# On a client machine: write <project>/.kanban/config.toml
mode = "remote"
[server]
url = "https://kanban.example.com"
token = "k_a1b2c3..."
[project]
key = "my-app"
agent-kanban config show # confirm what resolved and where it came from
agent-kanban task list # no flags needed from here on
Or set it up in one command:
agent-kanban config init --server https://kanban.example.com --project my-app --key k_a1b2c3
Configuration
Everything lives in <project>/.kanban/config.toml.
| Setting | CLI flag | Environment variable | Default |
|---|---|---|---|
| Server URL | --server | KANBAN_SERVER | derived from the project directory |
| Project key | --project | KANBAN_PROJECT | derived from the project directory |
| Access token | --key | KANBAN_KEY | — |
| Mode | — | KANBAN_MODE | remote if a server is set, else local |
| Database path | --db | KANBAN_DB | <project>/.kanban/kanban.db |
| Session ID | --session | KANBAN_SESSION | .kanban/sessions/<identity-key>, else .kanban/session |
| Identity key | — | KANBAN_SESSION_KEY | harness session variable (PI_SESSION_ID, CLAUDE_CODE_SESSION_ID, …) |
Two flags affect every command, so they work before or after the subcommand: --json for machine-readable output, and --no-color to disable ANSI colors. In CI, set NO_COLOR=1 instead.
Server-side: KANBAN_HOST, KANBAN_PORT, KANBAN_WEB_DIR, KANBAN_ADMIN_TOKEN. In Docker, KANBAN_BIND controls the host-side bind address (127.0.0.1 or 0.0.0.0). Note that the container itself always listens on 0.0.0.0, so this variable is what actually decides how far the server is reachable.
Precedence: CLI flags > environment variables > config.toml > derived defaults.
An empty environment variable counts as unset, not as an empty value. Otherwise
export KANBAN_SERVER=would silently shadow a perfectly goodconfig.tomland quietly create a new empty local database.
Security
serve does not terminate TLS, and binds to 127.0.0.1 by default.
That is deliberate. Most deployments of a tool like this already sit behind an existing HTTPS terminator: a corporate gateway, nginx, a Kubernetes Ingress, or a network reachable only over VPN. Shipping a container that renews certificates introduces a failure mode (expired cert means total outage) that most users do not need.
If you expose it, put it behind a TLS terminator. Without TLS, tokens travel in plaintext.
| Token type | Access |
|---|---|
| Project token | Only the projects it is explicitly granted |
| Admin token | Every project, plus project and token management |
KANBAN_ADMIN_TOKEN must be k_ followed by 32 lowercase hex characters. A malformed value fails at startup rather than at first use, because a misconfigured credential that only breaks later is the worst kind.
When it comes from the environment, the token is neither written to config.toml nor printed to the log.
No endpoint accepts a token in the URL. Headers (X-Kanban-Key or Authorization: Bearer)
are the only way in; browsers that cannot set headers on EventSource exchange a 60-second
single-use ticket at POST /api/stream-ticket first. A token in a query string ends up in
proxy access logs, container logs, Referer, and browser history, so ?key= is rejected
everywhere — including on the SSE path. The one legitimate use of ?key= is a shareable link
to the board itself (http://host:7788/?key=…&project=…), which the frontend reads once and
strips from the address bar before making any API call.
Command reference
| Command | Purpose |
|---|---|
agent-kanban init | Create the local board (.kanban/) |
agent-kanban install-protocol | Write the agent collaboration protocol into the project's AGENTS.md |
agent-kanban mcp | Run the MCP server (stdio) so an agent can call the board as tools |
agent-kanban session start | end | list | heartbeat | Session lifecycle |
agent-kanban task add | list | show | claim | progress | block | done | … | Task operations |
agent-kanban board | Swimlane view in the terminal |
agent-kanban context | Read the situation: board + handoffs + suggested actions |
agent-kanban resume <task> | Take over a task; injects handoff and timeline |
agent-kanban handoff | Write a handoff (summary / next / blockers / open) |
agent-kanban plan save | show | list | history | at | attach | Versioned plans |
agent-kanban rebuild [--write] | Replay the event log and verify the projection |
agent-kanban doctor [--deep] | Consistency self-check and repair |
agent-kanban export [--out <dir>] | Export the event journal (one file per day) |
agent-kanban import <dir> [--dry-run] | Rebuild the database from a journal (cross-machine migration) |
agent-kanban snapshot | Write a human-readable board snapshot |
agent-kanban compact [--keep-days 30] | Trim old events (snapshots first) |
agent-kanban config show | init | set | use | path | Configuration |
agent-kanban project list | Query projects (local database) |
agent-kanban admin project … | token … | Project and token management |
agent-kanban update [--check] | Self-update the binary from GitHub Releases (checksum-verified) |
agent-kanban serve | Run the HTTP + SSE server |
Run agent-kanban <command> --help for the full option list.
Exit codes
These are a published contract. Agents branch on them, so the meanings never change.
| Code | Name | Meaning | What to do |
|---|---|---|---|
0 | OK | Success | — |
1 | USAGE | Bad arguments | Read details.usage and fix the command |
2 | STATE | Task missing, illegal transition, missing required --reason | Do not retry as-is |
3 | CONFLICT | Task is held by another session with a live lease | Work on something else, or wait. Do not reach for --force |
4 | BUSY | Database is locked | Back off and retry, at most 3 times |
5 | NOT_INIT | No .kanban/ directory, or schema needs migrating | Run agent-kanban init |
6 | INTERNAL | Bug | Report it, do not retry |
7 | AUTH | Missing key, wrong key, or project not found | Fix your credentials |
Agents should branch on the code (or the error.name string in --json output), never on message text.
Letting an agent drive the board
Option 1 — the protocol file (works with any agent)
agent-kanban install-protocol # writes a managed block into <project>/AGENTS.md
agent-kanban install-protocol --check # CI guard: exits 2 if missing or outdated
The block sits between <!-- agent-kanban:begin --> and <!-- agent-kanban:end --> and is the only
thing the command touches, so you can keep your own conventions in the same file. agent-kanban doctor reports when the installed block is behind the CLI version.
Any agent that reads AGENTS.md (or CLAUDE.md, or whatever your harness looks for) then
knows to run agent-kanban session start and agent-kanban context before touching code. Use
--file to write somewhere else, for example --file .cursor/rules/kanban.mdc.
Option 2 — MCP tools
pi mcp add agent-kanban -- cmd agent-kanban mcp
claude mcp add agent-kanban -- cmd agent-kanban mcp
Already in this repo: .mcp.json at the project root registers the local build, so any
harness that reads standard MCP files picks it up with no extra setup. Start the
harness from the project root — the command path is relative to its working
directory, and the board itself is found by walking up from there.
{
"mcpServers": {
"kanban": {
"command": "kanban",
"args": ["mcp"]
}
}
}
29 tools, all thin wrappers over the same core the CLI uses:
| Group | Tools |
|---|---|
| Session | kanban_session_start / kanban_bootstrap / kanban_session_end |
| Tasks | kanban_task_list / get / create / claim / progress / note / block / unblock / complete / review / release / cancel / reopen / remove |
| Dependencies | kanban_task_dep_add / dep_remove / dep_list |
| Recovery | kanban_resume / kanban_handoff |
| Plans | kanban_plan_save / show / list / history / diff |
| Board | kanban_board / kanban_doctor |
Per-tool parameters are in docs/plan/002-接口契约.md §3.2, which also lists the operations that are deliberately not exposed to agents (project and token management, among others) and why.
The recovery flow an agent is expected to run:
kanban_session_start(agent_name="pi-fix") → s-4k9d2m
kanban_bootstrap(session_id="s-4k9d2m") → handoffs, your cards, unattended cards
kanban_resume(session_id="s-4k9d2m", task_id="T-0007")
kanban_plan_show(task_id="T-0007")
kanban_task_progress(..., pct=80)
kanban_handoff(..., summary="...", next_step="...")
kanban_session_end(session_id="s-4k9d2m")
Every tool returns { ok, data, next_actions }; failures return { ok: false, error } with
the same code and name the CLI would exit with, so an agent can branch on them the same way.
Option 3 — the agent skill
A skill is the third option, and it is the one that teaches an agent the workflow rather than
the interface. The protocol file says "run agent-kanban context first"; the skill says what to do when
task claim returns exit code 3, that task progress doubles as lease renewal, and that
doing → done needs --force so you go through review instead. It ships the parts an agent
keeps getting wrong as reference files: the full command reference, the MCP tool mapping, the
local-versus-remote differences, and a troubleshooting table keyed by exit code.
npx skills add ArnoChenFx/agent-kanban --skill agent-kanban # install
Skills live in this repo under skills/, so the install works on any project, not just this one.
Install it into a project that already has a board, then pair it with whichever of the two options
above your agent uses. The three are complementary: the skill teaches, the protocol file enforces,
the MCP tools give it hands.
When to reach for this
Good fit:
- More than one agent session working the same repo
- Tasks long enough to span a context window
- Work that gets interrupted (CI, laptop closed, agent restarted)
- A team that wants to see what the agents are doing without tailing logs
Poor fit:
- A single agent on a short task. The overhead is not worth it
- Work that must not be shared with a server. Use local mode, no server needed
- Anything needing a real multi-user permissions model. Tokens are project-scoped, not user-scoped
FAQ
The database is not in git. Is that safe?
Yes, and losing it is recoverable. .kanban/kanban.db is a SQLite file: a build
artifact, awkward to merge. It is not in .gitignore by accident.
That file holds only token hashes, never a token itself — the id column is an
independent random reference (t_…), and authentication compares sha256(token)
against key_hash. An older version stored the token in id itself, which meant any
copy of the database — a backup, an export, a screenshot — handed out every live
credential.
Upgrading from that version needs no action for those tokens (the hash was always
computed correctly, so they keep working), but no migration rewrites the old rows: they
still display masked, and the admin page cannot grant or revoke them. Manage those from
the CLI (agent-kanban admin token revoke <token> — for an old row its id is the
token), or issue a new one and revoke the old. Details in Develop.md.
What is in git is .kanban/journal/ — the append-only event log, one JSON line per
change, grouped into daily files. Since events are the source of truth and the board is
just a projection, replaying that log on a fresh machine reproduces everything: tasks,
checklists, plans, handoffs, dependencies, the lot. agent-kanban rebuild --write does exactly
that, which is the same mechanism that lets it prove its own consistency.
# on the old machine
agent-kanban export --out .kanban/journal
# on the new one
agent-kanban init
agent-kanban import .kanban/journal
agent-kanban rebuild --write --force
Project keys are derived from directory names, so they differ between machines.
import rewrites events onto the current project and tells you it did; pass
--keep-project to preserve the original keys instead.
Can I just copy the .db file to another machine?
Usually yes, as long as the path does not change. But it is a live database, so copy it
while the server is stopped, and it will not merge with anything already on the target.
Prefer export / import: it is mergeable, diffable, and safe to run while the server is
up.
What if the event log has a gap?
agent-kanban doctor reports the inconsistency, and agent-kanban rebuild shows exactly which fields
disagree. It will not overwrite anything unless you pass --write --force, so a gap in the
history can never silently wipe your board.
Two agents grabbed the same task. What happens?
One wins. The loser gets exit code 3 together with the current holder's name, progress,
and last action, and should pick something else. --force exists for the case where you
have decided a human confirmed the override; it leaves a task_reclaimed event behind.
An agent died mid-task. How do I pick it up?
agent-kanban context lists cards whose holder has gone stale, then agent-kanban resume T-0007
takes it over. Progress and checklist survive, and the previous holder's handoff is
injected. If they left a handoff, you can take over even before the lease expires —
writing a handoff means yielding.
How do I move everything to a shared server?
Run agent-kanban serve on the box, create a project, issue a token, and point clients at it
with .kanban/config.toml. Each project is isolated, and each token only reaches the
projects it was granted.
The board has been running for months and the database grew large.
agent-kanban compact --keep-days 30. It writes a snapshot first, then drops old events —
keeping everything from the last N days, anything belonging to a live task, and a floor of
1000 rows regardless of age. The trimmed history survives only in that snapshot.
Is it safe to expose to a network?
serve binds 127.0.0.1 and does not terminate TLS by default. Put it behind a TLS
terminator before exposing it: without TLS, tokens go over the wire in plaintext. See
Security.
Documentation
- Develop.md — architecture, data model, build, release, verification
License
MIT