Skip to content

File-based kanban board CLI and TUI for multi-agent workflows. Skills included.

License

Notifications You must be signed in to change notification settings

antopolskiy/kanban-md

Repository files navigation

kanban-md

CI Release Go Version Latest Release codecov Go Reference Go Report Card License: MIT

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.

Demo

How to use it

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:

  1. Install the tool
brew install antopolskiy/tap/kanban-md
  1. Go to your project directory and create a board there
kanban-md init

This will create a kanban/ directory and a config.yml file. I also usually add it to .gitignore.

  1. 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
  1. 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"
  1. Kick off /kanban-based-development skill 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
  1. Adjust the local skill / AGENTS.md to steer the agents in a way that would make sense for this project.

Why kanban-md?

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 pick command atomically finds, claims, and moves the next available task.
  • 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, and grep all 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 tui

Interactive 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

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 --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.

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: 4

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, kanban-md prompts 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 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

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

Show full details of a task.

kanban-md show ID

edit

Modify 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

move

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

handoff

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

Delete a task. Aliases: rm.

kanban-md delete ID [--yes]
kanban-md delete 1,2,3 --yes       # batch delete

Prompts for confirmation in interactive terminals. Use --yes (-y) to skip the prompt (required in non-interactive contexts like scripts). Batch delete always requires --yes.

archive

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 archive

To see archived tasks:

kanban-md list --archived
kanban-md list --status archived

board

Show 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)

pick

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.

agent-name

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-progress

metrics

Show 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

log

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

config

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 value

Available 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

context

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.

Interactive TUI

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 columns

Set tui.hide_empty_columns in config.yml to control the default behavior.

Note: Older releases shipped a standalone kanban-md-tui binary. It has been retired — use kanban-md tui instead.

In create/edit dialogs, text fields support cursor-based editing (←/→, Home/End, Backspace, Delete).

Keyboard shortcuts

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

Global flags

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)

Output format

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.

Configuration

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 list

Custom statuses

Define 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.

Custom priorities

Edit config.yml directly to customize priorities:

priorities:
  - trivial
  - normal
  - urgent
  - showstopper
defaults:
  priority: normal

Shell completions

Generate 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-Expression

Agent skills

kanban-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 show

Skills 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.

Multi-agent workflow

kanban-md is designed for concurrent work by multiple agents (AI or human) through claims and classes of service.

Claims

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 backend

Classes of service

Tasks 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-30

Swimlanes

Group 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 distribution

Design principles

Agent-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.

Development

# 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

License

MIT