kanban-md

An agent-first, file-based Kanban board for coordinating AI coding agents and
human supervisors. It runs locally as a single binary: no database, server,
account, or SaaS dependency.
How to use it
kanban-md is flexible, but a typical agent-driven setup looks like this:
- Install the tool.
brew install antopolskiy/tap/kanban-md
- Go to your project directory and create a board.
kanban-md init
This creates kanban/config.yml and kanban/tasks/. The interactive setup
offers to add kanban/ to .gitignore; keep it tracked instead if the board
should travel with the repository.
- Install the bundled skills for your agents.
# Install skills locally in this project
kanban-md skill install
# Or install them globally
kanban-md skill install --global
- Create tasks manually, or ask an agent to capture them.
kanban-md add "Set up CI pipeline" --priority high
kanban-md add "Fix login bug" --priority critical
claude "add ticket: there is a bug on the login page when the user enters an invalid email address"
- Start the
kanban-based-development skill with one agent. It will claim a
task, create an isolated worktree, implement and verify the change, merge it,
release the claim, and mark the task done. Once the workflow fits your
project, run more agents and supervise their progress in the TUI.
kanban-md tui
- Adapt the local skill or
AGENTS.md to the repository's own build, review,
and release rules.
Why kanban-md?
Project management tools are designed for humans clicking buttons. kanban-md is designed for AI agents running commands and human supervision.
- Agent-first. Token-efficient output (
--compact), a single-step
pick/claim/move workflow, structured JSON, and installable skills make the
board practical inside non-interactive agent loops.
- Cooperative multi-agent coordination. Claims reduce duplicate work, can be
required by selected columns, and expire automatically when an agent stops
renewing them. Claims are coordination leases, not a security or distributed-
transaction boundary.
- Self-healing task IDs. Commands automatically detect duplicate IDs, filename/frontmatter ID mismatches, and
next_id drift, then repair them before proceeding.
- Plain files. Every task is a Markdown file. Agents, humans, scripts, Git,
and
grep can inspect the same source of truth without API credentials.
- No service dependency. A single binary owns the local workflow; there is
no database server, background daemon, or remote configuration service.
- Skills included. Pre-written skills for using the CLI tool and a multi-agent development workflow. Installable via
kanban-md skill install.
- TUI for observation. A full interactive terminal board with keyboard navigation. It auto-refreshes when task files change on disk.
kanban-md tui
Installation
Homebrew (macOS/Linux)
brew install antopolskiy/tap/kanban-md
Go
go install github.com/antopolskiy/kanban-md/cmd/kanban-md@latest
Homebrew also installs kbmd as a shorthand alias for kanban-md.
Binary downloads
Pre-built binaries for macOS, Linux, and Windows are available on the Releases page.
Quick start
Agents can run these commands for you, but the same interface is useful for
manual work and scripting.
# Initialize a board in the current directory
kanban-md init --name "My Project"
# Create some tasks
kanban-md create "Set up CI pipeline" --priority high --tags devops
kanban-md create "Write API docs" --assignee alice --due 2026-03-01
kanban-md create "Fix login bug" --status todo --priority critical
# List all tasks
kanban-md list
# Filter and sort, highest priority first
kanban-md list --status todo,in-progress --sort priority
# Move a task forward
kanban-md move 3 in-progress
kanban-md move 3 --next
# Edit a task
kanban-md edit 2 --add-tag documentation --body "Cover all REST endpoints"
# View task details
kanban-md show 1
# Done with a task
kanban-md move 1 done
# Or soft-delete it by moving it to archived
kanban-md delete 3 --yes
How it works
Running kanban-md init creates a kanban/ directory:
kanban/
config.yml
tasks/
001-set-up-ci-pipeline.md
002-write-api-docs.md
003-fix-login-bug.md
Each task file is standard Markdown with YAML frontmatter:
---
id: 1
title: Set up CI pipeline
status: backlog
priority: high
created: 2026-02-07T10:30:00Z
updated: 2026-02-07T10:30:00Z
tags:
- devops
---
Optional body with more detail, context, or notes.
When kanban-md updates a task, it retains unrecognized YAML frontmatter
properties, including exact numeric text, tags, lists, and maps with non-string
keys. Anchors, aliases, and nested YAML merges are retained when their bindings
stay entirely within these properties. This lets other tools keep their metadata
through task edits. By default, additional properties do not appear in table,
compact, or JSON output. You can explicitly select scalar values for the
property views below. kanban-md's own fields remain authoritative,
including fields you clear.
An update refuses before changing the task file if an extra property aliases a
canonical field or another anchor that cannot be retained safely. Top-level YAML
merges, top-level alias keys, and custom tags on the whole frontmatter mapping
also require manual editing before an update. A quoted "<<" property is allowed.
Otherwise valid tasks with this metadata remain readable. If startup needs to
repair an inconsistent task ID or filename and cannot safely rewrite its
metadata, the command fails with an error until you correct the task manually.
kanban-md reserializes its own fields after an update. It does not guarantee
comments, indentation, quote style, original key placement, or byte-for-byte
formatting.
The config.yml tracks board settings. A newly initialized board currently
uses schema version 12:
version: 12
board:
name: My Project
tasks_dir: tasks
statuses:
- name: backlog
show_duration: false
- name: todo
- name: in-progress
require_claim: true
- name: review
require_claim: true
- name: done
show_duration: false
- name: archived
show_duration: false
priorities:
- low
- medium
- high
- critical
defaults:
status: backlog
priority: medium
class: standard
claim_timeout: 1h
classes:
- name: expedite
wip_limit: 1
bypass_column_wip: true
- name: fixed-date
- name: standard
- name: intangible
tui:
title_lines: 2
age_thresholds:
- after: 0s
color: "242"
- after: 1h
color: "34"
- after: 24h
color: "226"
- after: 72h
color: "208"
- after: 168h
color: "196"
next_id: 1
config.yml and tasks/*.md are authoritative. activity.jsonl is a
best-effort, bounded audit log, and .lock is a transient coordination file
used by operations that must serialize access. Neither is a hidden database.
Direct task-file edits remain supported, but commands are the claim-aware
mutation path while a task is actively claimed.
Commands
init
Create a new kanban board.
kanban-md init [--name NAME] [--statuses s1,s2,s3] [--wip-limit status:N]
| Flag | Description |
|---|
--name | Board name (defaults to parent directory name) |
--statuses | Comma-separated status list (default: backlog,todo,in-progress,review,done,archived) |
--wip-limit | WIP limit per status (format: status:N, repeatable) |
After creating a board interactively, kanban-md offers to add the board
directory (for example, kanban/) to .gitignore:
- If
.gitignore exists in the board directory parent, the entry is appended.
- If
.gitignore does not exist, it is created with the board directory entry.
create
Create a new task. Aliases: add. Title can be provided as a positional argument or via --title.
kanban-md create "My task" [FLAGS]
kanban-md create --title "My task" --description "Details here" [FLAGS]
| Flag | Default | Description |
|---|
--title | | Task title (alternative to positional argument) |
--status | config default | Initial status |
--priority | config default | Priority level |
--assignee | | Person assigned |
--tags | | Comma-separated tags |
--due | | Due date (YYYY-MM-DD) |
--estimate | | Time estimate (e.g. 4h, 2d) |
--class | config default | Configured class of service |
--parent | | Parent task ID |
--depends-on | | Dependency task IDs (comma-separated) |
--body | | Task description (alias: --description) |
--set-property KEY=LITERAL | | Set a scalar property; repeat for multiple keys |
list
List tasks with filtering and sorting. Aliases: ls.
kanban-md list [FLAGS]
| Flag | Default | Description |
|---|
--status | | Filter by status (comma-separated) |
--priority | | Filter by priority (comma-separated) |
--assignee | | Filter by assignee |
--tag | | Filter by tag |
-s, --search | | Search tasks by title, body, or tags (case-insensitive) |
--blocked | false | Show only blocked tasks |
--not-blocked | false | Show only non-blocked tasks |
--parent | | Filter by parent task ID |
--unblocked | false | Show only tasks with all dependencies satisfied (missing dependency IDs are treated as satisfied) |
--unclaimed | false | Show only unclaimed or expired-claim tasks |
--claimed-by | | Filter by claimant name |
--class | | Filter by class of service |
--archived | false | Show only archived tasks |
--property KEY=LITERAL | | Match one exact typed scalar value; repeat to combine with AND |
--show-property KEY | | Include a selected scalar in table, compact or JSON output; repeat for multiple keys |
--group-by | | Group counts by assignee, tag, class, priority, status, or property:KEY |
--sort | id | Sort by: id, title, status, priority, created, updated, due |
-r, --reverse | false | Reverse sort order |
-n, --limit | 0 | Max results (0 = unlimited) |
show
Show full details of a task. When the task has direct children, the detail view
includes their IDs, statuses, titles, and a terminal/total roll-up. Parent
status remains independently managed; the roll-up is informational only.
kanban-md show ID
kanban-md show ID --archived # include archived children in the roll-up
| Flag | Description |
|---|
--archived | Include archived direct children (hidden by default) |