An agents-first file-based Kanban. Built for multi-agent workflows to allow AI agents work in parallel without clashing. Ultra-fast single binary CLI. Agent skills included. Lean and future-proof: no database, no server, no SaaS — just files.
kanban-md is a flexible tool, and you can use it in many ways. Here is one of the ways I use it in my own projects:
- Install the tool
brew install antopolskiy/tap/kanban-md- Go to your project directory and create a board there
kanban-md initThis will create a kanban/ directory and a config.yml file. I also usually add it to .gitignore.
- Install skills for your agents
# install skills locally in this project -- I prefer this
kanban-md skill install
# install skills globally (home directory)
kanban-md skill install --global- Create tickets manually, or ask your agents do it for you
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"- Kick off
/kanban-based-developmentskill in a single agent and observe how it behaves. It should claim a task, create a worktree, implement, test, commit, release the claim and mark the task as done. When confident, kick off the skill in multiple agents -- they will work in parallel without clashing. You should see the progress in the TUI.
kanban-md tui- Adjust the local skill / AGENTS.md to steer the agents in a way that would make sense for this project.
Project management tools are designed for humans clicking buttons. kanban-md is designed for AI agents running commands and human supervision.
- Agents-first. Token-efficient output formats (
--compact), atomic claim-and-move operations (pick --claim), and installable agent skills that teach agents how to use the board — out of the box. - Multi-agent safe. Claims provide cooperative locking so multiple agents can work the same board without stepping on each other. Claims expire automatically, and the
pickcommand atomically finds, claims, and moves the next available task. - Self-healing task IDs. Commands automatically detect duplicate IDs, filename/frontmatter ID mismatches, and
next_iddrift, then repair them before proceeding. - Plain files. Every task is a Markdown file. Agents, humans, scripts, and
grepall work equally well. No API tokens, no authentication, no rate limits. - Zero dependencies at runtime. A single static binary. No database, no server, no config 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 tuibrew install antopolskiy/tap/kanban-mdgo install github.com/antopolskiy/kanban-md/cmd/kanban-md@latestHomebrew also installs kbmd as a shorthand alias for kanban-md.
Pre-built binaries for macOS, Linux, and Windows are available on the Releases page.
Note: normally, you wouldn't run the CLI commands directly. Your agents will do that for you.
# 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
kanban-md list --status todo,in-progress --sort priority --reverse
# 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 delete it
kanban-md delete 3 --yesRunning 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.The config.yml tracks board settings:
version: 3
board:
name: My Project
tasks_dir: tasks
statuses:
- backlog
- todo
- name: in-progress
require_claim: true
- name: review
require_claim: true
- done
- archived
priorities:
- low
- medium
- high
- critical
wip_limits:
in-progress: 3
review: 2
classes:
- name: expedite
wip_limit: 1
bypass_column_wip: true
- name: fixed-date
- name: standard
- name: intangible
claim_timeout: 1h
defaults:
status: backlog
priority: medium
class: standard
next_id: 4Create 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, kanban-md prompts to add the board directory (for example, kanban/) to .gitignore:
- If
.gitignoreexists in the board directory parent, the entry is appended. - If
.gitignoredoes not exist, it is created with the board directory entry.
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 |
backlog | Initial status |
--priority |
medium | Priority level |
--assignee |
Person assigned | |
--tags |
Comma-separated tags | |
--due |
Due date (YYYY-MM-DD) | |
--estimate |
Time estimate (e.g. 4h, 2d) | |
--class |
standard | Class of service (expedite, fixed-date, standard, intangible) |
--parent |
Parent task ID | |
--depends-on |
Dependency task IDs (comma-separated) | |
--body |
Task description (alias: --description) |
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 |
--group-by |
Group results by field (assignee, tag, class, priority, status) | |
--sort |
id | Sort by: id, status, priority, created, updated, due |
-r, --reverse |
false | Reverse sort order |
-n, --limit |
0 | Max results (0 = unlimited) |
Show full details of a task.
kanban-md show IDModify an existing task.
kanban-md edit ID [FLAGS]
kanban-md edit 1,2,3 --priority high # batch edit| Flag | Description |
|---|---|
--title |
New title (renames the file) |
--status |
New status |
--priority |
New priority |
--assignee |
New assignee |
--add-tag |
Add tags (comma-separated) |
--remove-tag |
Remove tags (comma-separated) |
--due |
New due date (YYYY-MM-DD) |
--clear-due |
Remove due date |
--estimate |
New time estimate |
--body |
New body text (replaces entire body) |
--append-body, -a |
Append text to task body |
--timestamp, -t |
Prefix a timestamp line when appending |
--started |
Set started date (YYYY-MM-DD) |
--clear-started |
Clear started timestamp |
--completed |
Set completed date (YYYY-MM-DD) |
--clear-completed |
Clear completed timestamp |
--parent |
Set parent task ID |
--clear-parent |
Clear parent |
--add-dep |
Add dependency task IDs (comma-separated) |
--remove-dep |
Remove dependency task IDs (comma-separated) |
--block |
Mark task as blocked with reason |
--unblock |
Clear blocked state |
--claim |
Claim task for an agent (set claimed_by) |
--release |
Release claim on task |
--class |
Set class of service |
Change a task's status.
kanban-md move ID [STATUS]
kanban-md move ID --next
kanban-md move ID --prev
kanban-md move 1,2,3 todo # batch move| Flag | Description |
|---|---|
--next |
Advance to next status in the configured order |
--prev |
Move back to previous status |
--claim |
Claim task for an agent |
Hand off a task for review. Moves to review status, appends a note, and optionally blocks/releases.
kanban-md handoff ID --claim NAME [--note TEXT] [--block REASON] [-t] [--release]| Flag | Description |
|---|---|
--claim |
Claim name (required) |
--note |
Handoff note to append to body |
--timestamp, -t |
Prefix a timestamp line to the note |
--block |
Mark task as blocked with reason |
--release |
Release claim after handoff |
Delete a task. Aliases: rm.
kanban-md delete ID [--yes]
kanban-md delete 1,2,3 --yes # batch deletePrompts for confirmation in interactive terminals. Use --yes (-y) to skip the prompt (required in non-interactive contexts like scripts). Batch delete always requires --yes.
Soft-delete a task by moving it to the archived status. Archived tasks are hidden from all normal commands (list, board, metrics, context, TUI) but remain on disk.
kanban-md archive ID
kanban-md archive 1,2,3 # batch archiveTo see archived tasks:
kanban-md list --archived
kanban-md list --status archivedShow a board summary with task counts per status, WIP utilization, blocked/overdue counts, and priority distribution. Aliases: summary.
kanban-md board
kanban-md board --watch # live-update on file changes| Flag | Default | Description |
|---|---|---|
-w, --watch |
false | Live-update the board on file changes (Ctrl+C to stop) |
--group-by |
Group by field (assignee, tag, class, priority, status) |
Atomically find and claim the next available task. Designed for multi-agent workflows where agents need exclusive task assignment.
kanban-md pick --claim agent-1
kanban-md pick --claim agent-1 --status todo --move in-progress
kanban-md pick --claim agent-1 --tags backend
kanban-md pick --claim agent-1 --no-body| Flag | Default | Description |
|---|---|---|
--claim |
(required) | Agent name to claim the task for |
--status |
all non-terminal | Source status(es) to pick from (comma-separated) |
--move |
Also move picked task to this status | |
--tags |
Only pick tasks matching at least one tag | |
--no-body |
false | Show only the pick confirmation line (skip full task details) |
By default, pick prints the one-line confirmation and then the full task details (same as show, including body) so agents do not need a follow-up show command.
The pick algorithm selects from unclaimed, unblocked tasks with satisfied dependencies, prioritizing by class of service (expedite > fixed-date > standard > intangible), then by priority within each class. Fixed-date tasks are further sorted by earliest due date.
Generate a random two-word name for use with --claim. Uses the system dictionary when available, with a built-in word list as fallback.
kanban-md agent-name
# → quiet-storm
kanban-md pick --claim $(kanban-md agent-name) --status todo --move in-progressShow flow metrics: throughput, average lead/cycle time, flow efficiency, and aging work items.
kanban-md metrics [--since YYYY-MM-DD]| Flag | Default | Description |
|---|---|---|
--since |
Only include tasks completed after this date |
Show the activity log of board mutations (create, move, edit, delete, block, unblock).
kanban-md log [FLAGS]| Flag | Default | Description |
|---|---|---|
--since |
Show entries after this date (YYYY-MM-DD) | |
--limit |
0 | Maximum number of entries (most recent) |
--action |
Filter by action type (create, move, edit, delete, block, unblock) | |
--task |
Filter by task ID |
View or modify board configuration.
kanban-md config # show all config values
kanban-md config get KEY # get a single value
kanban-md config set KEY VALUE # set a writable valueAvailable keys:
| Key | Writable | Description |
|---|---|---|
board.name |
yes | Board name |
board.description |
yes | Board description |
defaults.status |
yes | Default status for new tasks |
defaults.priority |
yes | Default priority for new tasks |
defaults.class |
yes | Default class of service for new tasks |
statuses |
no | List of statuses |
priorities |
no | List of priorities |
tasks_dir |
no | Tasks directory name |
wip_limits |
no | WIP limits per status |
claim_timeout |
yes | Claim expiration duration (e.g. 1h, 30m) |
classes |
no | Class of service definitions |
tui.title_lines |
yes | Number of title lines shown in TUI cards |
tui.hide_empty_columns |
yes | Hide columns with zero tasks in TUI |
tui.age_thresholds |
no | TUI age color thresholds |
next_id |
no | Next task ID |
version |
no | Config schema version |
Generate a markdown summary of the board state for embedding in context files (e.g. CLAUDE.md, AGENTS.md).
kanban-md context # print to stdout
kanban-md context --write-to AGENTS.md # write/update in file
kanban-md context --sections blocked,overdue # limit sections
kanban-md context --days 14 # recently completed lookback| Flag | Default | Description |
|---|---|---|
--write-to |
Write context to file (creates or updates in-place) | |
--sections |
all | Comma-separated section filter |
--days |
7 | Recently completed lookback in days |
Available section names: in-progress, blocked, overdue, recently-completed.
When using --write-to, the context block is wrapped in HTML comment markers (<!-- BEGIN kanban-md context --> / <!-- END kanban-md context -->). If the file already contains these markers, only the block between them is replaced — all other content is preserved.
kanban-md tui opens a full interactive terminal board with keyboard navigation. It auto-refreshes when task files change on disk.
If no board exists in the current directory, kanban-md tui can initialize one and then offers to add that board directory to .gitignore.
kanban-md tui # launch from any directory with a kanban/ board
kanban-md tui --dir PATH # point to a specific kanban directory
kanban-md tui --hide-empty-columns # override config and hide empty columns
kanban-md tui --show-empty-columns # override config and show empty columnsSet tui.hide_empty_columns in config.yml to control the default behavior.
Note: Older releases shipped a standalone
kanban-md-tuibinary. It has been retired — usekanban-md tuiinstead.
In create/edit dialogs, text fields support cursor-based editing (←/→, Home/End, Backspace, Delete).
| Key | Action |
|---|---|
h / l |
Move between columns |
j / k |
Move between tasks within a column |
Enter |
View task details |
c |
Create task in current column |
e |
Edit selected task (same 4-step flow as create) |
m |
Move task to a different status (picker dialog) |
n / p |
Move task to next / previous status |
d |
Delete task (with confirmation) |
r |
Refresh board |
? |
Show help |
q / Ctrl+C |
Quit |
These work with any command:
| Flag | Description |
|---|---|
--json |
Force JSON output |
--table |
Force table output (default) |
--compact / --oneline |
Compact one-line-per-record output |
--dir |
Path to kanban directory (overrides auto-detection) |
--no-color |
Disable color output (also respects NO_COLOR env var) |
The default output format is table (human-readable). Use flags to switch:
# Default: table
kanban-md list --status todo
# Compact: one line per task, ideal for AI agents
kanban-md list --compact
# JSON: for scripting and piping
kanban-md list --json | jq '.[].title'Set the KANBAN_OUTPUT environment variable to change the default: json, table, compact, or oneline.
Override priority: --json/--table/--compact flags > KANBAN_OUTPUT env var > table default.
kanban-md discovers its config by walking upward from the current directory, similar to how git finds .git/. This means you can run commands from any subdirectory in your project.
Use --dir to point to a specific board:
kanban-md --dir /path/to/kanban listDefine your own workflow columns:
kanban-md init --statuses "open,in-progress,blocked,closed"The order matters — it defines the progression for move --next and move --prev, and the sort order for list --sort status.
Edit config.yml directly to customize priorities:
priorities:
- trivial
- normal
- urgent
- showstopper
defaults:
priority: normalGenerate completions for your shell:
# bash
source <(kanban-md completion bash)
# zsh
kanban-md completion zsh > "${fpath[1]}/_kanban-md"
# fish
kanban-md completion fish | source
# PowerShell
kanban-md completion powershell | Out-String | Invoke-Expressionkanban-md ships with installable skills that teach AI agents how to use the board. Skills are auto-triggered prompt files that give agents command references, decision trees, and workflows — so they manage tasks correctly without you writing custom instructions.
Two skills are included:
| Skill | Description |
|---|---|
| kanban-md | Command reference, decision trees, and workflows for managing tasks via CLI. Auto-triggered when an agent encounters task-related work. |
| kanban-based-development | Full autonomous development workflow — multi-agent claim semantics, git worktrees for isolation, and a strict status lifecycle (in-progress → review → done). |
# Install skills for all detected agents (Claude Code, Codex, Cursor, OpenClaw)
kanban-md skill install
# Check if installed skills are up to date
kanban-md skill check
# Update skills to match current CLI version
kanban-md skill update
# Preview skill contents
kanban-md skill showSkills are versioned to match the CLI. When you upgrade kanban-md, skill check tells you if your installed skills are outdated, and skill update brings them in sync.
kanban-md is designed for concurrent work by multiple agents (AI or human) through claims and classes of service.
Claims provide cooperative locking — an agent claims a task before working on it, preventing other agents from picking the same task. Claims expire after the configured timeout (default: 1 hour).
Statuses with require_claim: true (default: in-progress and review) enforce that every move or edit includes --claim <name>. This prevents accidental anonymous moves in multi-agent environments.
# Agent picks next available task
kanban-md pick --claim agent-1 --move in-progress
# Move to review (require_claim enforced — must include --claim)
kanban-md move 5 review --claim agent-1
# Agent finishes and releases
kanban-md edit 5 --release
kanban-md move 5 done
# Another agent picks from a specific queue
kanban-md pick --claim agent-2 --status todo --tags backendTasks can have a class of service that affects WIP limits and pick priority:
| Class | Behavior |
|---|---|
| expedite | Bypasses column WIP limits. Has its own board-wide WIP limit (default: 1). Picked first. |
| fixed-date | Picked by earliest due date within its priority tier. |
| standard | Default class. Normal WIP and priority rules. |
| intangible | Picked last. For background/maintenance work. |
kanban-md create "Critical hotfix" --class expedite --priority critical
kanban-md create "Q2 deadline feature" --class fixed-date --due 2026-06-30Group board or list views by any field to see work distribution:
kanban-md board --group-by assignee # who is working on what
kanban-md board --group-by class # class of service breakdown
kanban-md list --group-by tag # work by tag
kanban-md list --group-by priority # priority distributionAgent-first, human-friendly. Every feature is designed to work in non-interactive, piped, multi-agent contexts first. Humans get a TUI and table output; agents get --compact (70% fewer tokens than JSON) and atomic operations like pick --claim.
Files are the API. The CLI is a convenience layer over a simple file format. You can always fall back to editing files directly — the tool will pick up changes.
No hidden state. Everything is in config.yml and the task files. There's no database, no cache, no lock file. Two agents can work on the same board by editing different files and merging via git.
Minimal by default. The core CLI does one thing — manage task files — and stays out of the way. The interactive TUI is built in (kanban-md tui). The tool doesn't sync, notify, or integrate with external services. Git handles collaboration; file watchers handle live updates.
# Build
make build
# Run all tests (unit + e2e)
make test
# Run only e2e tests
make test-e2e
# Lint
make lint
# Lint with autofix
make lint-fix
# Full pipeline
make all
