# Kandown, complete documentation > A free, open-source, local Kanban for long-running AI agent work. Every task is a Markdown file, managed from the web, TUI, or CLI. Generated from https://kandown.dev: 16 pages. --- # Introduction *Getting started, https://kandown.dev/docs/introduction* What Kandown is, what it deliberately is not, and who it is for. Kandown drops a `tasks/` folder into your project and gives you three ways to work with it: a polished web board, a full terminal UI, and a scriptable CLI. All three read and write the same plain Markdown files. There is no server to run, no database to migrate, no account to create and no sync service to trust. If you can read a folder of text files, you can read your board. > **Tip** > Prefer to poke at it first? The [web app](https://kandown.dev/app) runs the real application in your > browser with no login. It opens on a sample project that resets on reload. In a compatible > browser, choose **Open project** to work directly with a local Kandown folder. ## The three ideas ### Your data is just files One `.md` file per task, one folder, versioned in git. Nothing to export because nothing was ever imported. Open a task in your editor, `grep` your backlog, write a shell script against it, hand the folder to a colleague; it is all the same operation on the same files. There is no index, no cache and no manifest. The directory *is* the state. Move a file between folders and the board moves with it; delete one and the task is gone. That constraint is enforced deliberately across the codebase (see [Architecture](https://kandown.dev/docs/project/architecture.md)). ### Agents are first-class users Most tools bolt AI on as an integration: an API key, a plugin, a webhook. Kandown assumes an agent is simply another user of the board, and gives it the same affordances as you. `kandown work` prints everything an agent needs: the rules, your project instructions, a live board digest, and the computed next actionable task, as Markdown on stdout. Every task command is non-interactive, JSON-capable and offline. See [For AI agents](https://kandown.dev/docs/agents/overview.md). ### Local-first, actually The board runs from a small daemon bound to `127.0.0.1` with a per-project token. Task commands never touch the network. The web UI ships as a single self-contained HTML file you can open from anywhere, including from a USB stick on a machine with no internet. ## What Kandown is not > **Note** > Being clear about the boundaries saves you evaluating it for the wrong job. - **Not a team server.** There is no realtime multiplayer, no permissions model and no hosted instance. Collaboration happens the way it does for the rest of your repo: through git. - **Not a project-management suite.** No burndown charts, no sprint ceremonies, no time tracking. - **Not a hosted service.** Nothing to sign up for, and nothing that can shut down and take your data with it. ## Who it is for Developers who already live in a repository and want their task list to live there too, and anyone running AI coding agents who needs a shared, durable place for those agents to pick up work, report on it, and hand it back. ## Next Install it, then run through the [quick start](https://kandown.dev/docs/quick-start.md); it takes about two minutes. --- # Installation *Getting started, https://kandown.dev/docs/installation* Requirements, install methods, and how Kandown keeps itself up to date. ## Requirements Node.js **18 or newer**. That is the entire list: no database, no runtime service, no global configuration. Check what you have: ```bash node --version ``` ## Install Kandown is published to npm as [`kandown`](https://www.npmjs.com/package/kandown). ```bash npm install -g kandown ``` Any package manager works: ```bash pnpm add -g kandown yarn global add kandown bun add -g kandown ``` ### Without installing `npx` runs it directly, which is useful for trying it out or for one-off CI commands: ```bash npx kandown init npx kandown list --json ``` > **Tip** > For day-to-day use, install globally. The `npx` path re-resolves the package on every call, which > adds a noticeable delay to commands you run in a loop. ## Verify ```bash kandown --version kandown doctor ``` `kandown doctor` is the one to reach for when something looks wrong. It checks your config file, the daemon state, port availability and the frontmatter of every task, and tells you what to do about each problem it finds. ## Updates Interactive runs check npm for a newer version at most **once every 24 hours**, and install it silently when one is found. The check is skipped entirely: - for every task command (`list`, `create`, `move`, …), - for `kandown daemon`, - whenever stdout is not a terminal, so it never fires in CI or inside an agent loop. To turn it off completely: ```bash export KANDOWN_NO_UPDATE=1 ``` You can also update on demand. This refreshes both the CLI and the `kandown.html` bundled in the current project: ```bash kandown update ``` If you have several projects open, bring their daemons onto the current version in one go: ```bash kandown daemon refresh-all ``` ## Uninstall ```bash npm uninstall -g kandown ``` Your `tasks/` folder and `.kandown/` config stay exactly where they are; they are just files, and removing the tool does not touch them. --- # Quick start *Getting started, https://kandown.dev/docs/quick-start* From an empty project to a running board, a first task, and an agent that can pick it up. Two minutes, four commands. ## 1. Initialize ```bash cd my-project kandown init ``` This creates two folders at your project root: ``` tasks/ # your tasks, the source of truth ├── t1.md # one Markdown file per task └── archive/ # archived tasks live here .kandown/ # config + web UI + workflow data ├── kandown.json # columns, theme, notifications, agents ├── kandown.html # the web app, one self-contained file ├── kandown_work.md # optional: your project's agent instructions └── workflows/ # optional: installed or local workflow packages ``` It also appends a single line to your `AGENTS.md` / `CLAUDE.md` pointing agents at `kandown work`: one line, not a block of rules that will go stale. > **Note** > Tasks live at the project root rather than inside `.kandown/` so that config and data stay > cleanly separated. Upgrading from an older layout? The CLI moves them for you on first run. ## 2. Open the board ```bash kandown ``` This starts a small local daemon, opens the **web board** in your browser and a **terminal UI** in your shell. Both are live views of the same files. The daemon outlives the terminal UI on purpose; quit the TUI and your browser tab keeps working. Stop it with d in the TUI, or: ```bash kandown daemon stop ``` Prefer no browser at all? `kandown board` gives you the terminal UI only. ## 3. Create a task From the web board, press N. From the terminal UI, press n. From a script: ```bash kandown create "Refactor auth middleware" -p P1 -t backend -a chacha ``` That prints the new task's id (and nothing else) on stdout, so you can capture it: ```bash ID=$(kandown create "Add rate limiting" -p P1) kandown move "$ID" "In progress" ``` The quick-add box in the UI parses the same information out of one line: ``` Fix login p1 #backend @chacha due:friday ``` ## 4. Point an agent at it ```bash kandown work ``` Everything an agent needs, as Markdown on stdout: the rules, your project instructions, a live board digest, and the next actionable task (computed as the unblocked task closest to done with the highest priority. Wire it into an MCP-capable client instead, if you prefer: ```bash claude mcp add kandown -- kandown mcp ``` Or select a task in the terminal UI and press a to launch Claude Code, Codex, Gemini CLI, Goose, Aider or OpenCode directly on it. ## 5. Commit Tasks are files, so they belong in your history: ```bash kandown commit -m "tasks: plan the auth refactor" ``` That stages `tasks/` and `.kandown/kandown.json` and commits them. Plain `git add` works exactly as well; the command is a convenience, not a requirement. ## Where to go next - [Tasks](https://kandown.dev/docs/guides/tasks.md): fields, subtasks, dependencies, templates - [For AI agents](https://kandown.dev/docs/agents/overview.md): the part that makes Kandown different - [CLI reference](https://kandown.dev/docs/reference/cli.md): every command and flag --- # Tasks *Using the board, https://kandown.dev/docs/guides/tasks* Creating tasks, the fields they carry, subtasks with reports, dependencies, and templates. A task is a single Markdown file in `tasks/`. Everything below is a description of what goes in that file: the UI, the terminal and the CLI are three editors for the same thing. ## Creating a task ### Quick-add syntax The fastest path in both the web board and the terminal UI is one line of text. Kandown parses the metadata out of it: ``` Fix login p1 #backend #security @chacha due:friday ``` | Token | Sets | |---|---| | `p1` … `p4` | Priority | | `#tag` | A tag (repeat for several) | | `@name` | Assignee | | `due:friday`, `due:2026-08-01` | Due date, natural language or ISO | Everything left over becomes the title. ### From the CLI ```bash kandown create "Refactor auth middleware" \ --priority P1 \ --tag backend --tag security \ --assignee chacha \ --to "In progress" ``` The command prints the new id on stdout and nothing else, so `$( … )` captures exactly one value. Add `--json` if you want the whole task object back. ## Fields | Field | Meaning | |---|---| | `id` | Stable identifier. Auto-generated, or set with `--id` | | `title` | Task title | | `status` | Board column, from `board.columns` in `kandown.json` | | `order` | Sort position within the column | | `priority` | `P1`-`P4`, highest to lowest | | `tags` | Free-form labels | | `assignee` | A username or an agent name | | `ownerType` | `human` or `ai`, drives owner filtering | | `due` | Due date; drives the due-date banner | | `epic` | Groups related tasks; available as a group-by | | `depends_on` | Ids of tasks blocking this one | | `created` | Creation date | | `report` | Completion summary in Markdown, shown prominently in the UI | ## Subtasks Subtasks are a plain Markdown checklist under a `## Subtasks` heading: ```markdown ## Subtasks - [x] Extract the token parser report: Moved to src/auth/token.ts, added unit tests for expiry. - [ ] Cover the refresh path with tests - [ ] Delete the legacy middleware ``` Two things make them more than a checklist: - **Per-step descriptions**: indented prose under a step, for context that does not belong in the title. - **`report:` lines**: what actually happened when the step was completed. This is the field that turns a finished task into a work log rather than a row of green ticks, and it is where agents are expected to write their results. In the UI, subtasks can be reordered from the keyboard and each carries its own description and report editor. ## Dependencies ```yaml depends_on: [t7, t12] ``` A task with unresolved dependencies **cannot be moved to the terminal column**. The gate lives in the shared core, so the refusal is identical whether the move comes from a drag in the browser, an `m` in the terminal UI, or `kandown move` in a script; the CLI cannot route around what the UI refuses. Blocked tasks are annotated as such in the board digest that agents read, so an agent picking up work never selects something it cannot finish. ## Owner type Every task is owned by a `human` or an `ai`. It is a filter, not a permission: it lets you look at "what am I doing" and "what are the agents doing" separately on a shared board. ## Templates Recurring shapes (a bug report, a release checklist, a spike) can be saved as templates and applied when creating a task, so the subtask list and default fields come pre-filled. ## Archiving and deleting Archiving moves the file to `tasks/archive/`. It stays readable, greppable and in git; it simply leaves the active board. ```bash kandown move t14 archived ``` Deleting removes the file. In the web UI, deletion is guarded behind a double-click, and a whole column can be archived or deleted in bulk when you are cleaning up. ## External changes Kandown watches the task folder. If you edit a task in your editor, or an agent writes to it while the board is open, the change is detected and surfaced rather than silently overwritten. --- # Board & views *Using the board, https://kandown.dev/docs/guides/board-and-views* The web interface: kanban and list views, filtering, search, the command palette and keyboard shortcuts. Running `kandown` opens the web board at `http://localhost:5176` (the port is configurable). It is served by a local daemon as a single self-contained HTML file. ## Two views ### Board The default: a horizontal kanban with drag-and-drop between columns. Columns are freely editable: rename them, reorder them, add or remove them in Settings, and every task's `status` follows. The last column is the **terminal column**. Moving a task there is what triggers the dependency gate described in [Tasks](https://kandown.dev/docs/guides/tasks.md#dependencies). ### List A sectioned list with filters and sorting, better suited to a large backlog than a wide board. Switch with ⌘1 and ⌘2. ## Finding things **Search** (/) is full-text across titles, bodies, subtasks, tags, assignee and priority, not just titles. **Filters** narrow by status, tag, assignee, priority and owner type. Owner filtering is the one worth remembering on a shared board: it separates your work from your agents' at a glance. **Group by** reorganises either view by priority, assignee or epic. **Command palette** (⌘K) is the fastest way to reach any of the above, plus task creation and navigation. ## Editing a task Opening a task gives you a WYSIWYG Markdown editor for the body, with structured controls for the fields alongside it. The `report` field is rendered prominently on a board that agents write to, the completion report is usually the thing you actually want to read. ## Due dates Tasks with a `due` date surface in a banner when they come due or run late, so a date you set three weeks ago does not quietly pass. ## Bulk operations A whole column can be archived or deleted in one action, which is how you clear a `Done` column at the end of a cycle without touching twenty files. ## Keyboard shortcuts | Keys | Action | |---|---| | ⌘K | Command palette | | ⌘1 / ⌘2 | Board view / list view | | N | New task | | / | Search | | R | Reload from disk | | ⌘S | Save | | ⌘⌫ | Delete | | Esc | Close the current panel | ## The daemon The board is served by a per-project daemon that outlives the terminal UI, so closing your shell does not close your browser tab. ```bash kandown daemon status kandown daemon start kandown daemon stop kandown projects # every open kandown project on this machine ``` It binds to `127.0.0.1` only and mints a random per-project API token at startup (see [Configuration § security](https://kandown.dev/docs/reference/configuration.md#security). --- # Terminal UI *Using the board, https://kandown.dev/docs/guides/terminal-ui* The keyboard-driven board that works over SSH, with no browser involved. ```bash kandown board ``` A full kanban board in your terminal. Same files, same dependency gate, same everything; it is not a reduced view of the web UI, it is a peer of it. It is the interface to reach for when you are on a remote machine, when you live in a terminal multiplexer, or when you simply do not want a browser tab open for a task list. ## Keys | Key | Action | |---|---| | j / k | Move between tasks | | h / l | Move between columns | | n | New task | | e | Edit the task in `$EDITOR` | | m | Move to another column | | / | Fuzzy search | | f | Cycle filters | | a | Launch an agent on this task | | g | Send the task to your agent hook | | x | Archive | | D | Delete | | d | Toggle the web daemon | | r | Reload from disk | | ? | Cheatsheet | > **Tip** > e opens the raw Markdown file in `$EDITOR`. Since the file *is* the task, anything your > editor can do (macros, multiple cursors, a spell checker) works on your board. ## Mouse The TUI is mouse-aware where terminals allow it: click to select, and **drag a task between columns** to move it. ## Over SSH Nothing about the terminal UI needs a local browser or a display server, so it works unchanged over SSH. The web daemon is separate and optional; toggle it with d if you also want the browser board, and forward the port if you want to reach it from your laptop: ```bash ssh -L 5176:localhost:5176 you@server ``` ## Settings ```bash kandown settings ``` A terminal settings editor covering the same configuration as the web Settings page: columns, theme, notifications, agents and the `kandown work` output. --- # Appearance *Using the board, https://kandown.dev/docs/guides/appearance* Themes, custom themes in JSON, density and motion tokens, fonts, languages and notifications. ## Themes 38 themes ship built in, including Vercel, Linear, Claude, Apple, Stripe, Catppuccin, Dracula, Nord, Terminal and Synthwave. Each comes in **light**, **dark** and **auto** (auto following your operating system. ### Custom themes A theme is a JSON object of design tokens, so you can define your own without touching the source: ```json { "name": "My theme", "colors": { "bg": "#0c1d17", "surface": "#142a22", "border": "#1e372e", "text": "#e8f0ea", "textMuted": "#96a89e", "accent": "#88e138" } } ``` Paste it into Settings → Appearance → Custom theme. It is stored in `.kandown/kandown.json`, so it travels with the project and lands in git with everything else. ## Tokens Beyond colour, the look is driven by four tokenised scales you can set independently: | Token | Effect | |---|---| | Radius | Corner rounding across cards, inputs and panels | | Shadows | Elevation, from flat to pronounced | | Density | Vertical rhythm; compact fits considerably more on screen | | Motion | Animation intensity, down to none | Five font stacks are available, covering system UI, geometric sans and monospace-forward looks. > **Note** > Setting motion to none is also the right choice on a machine where the animated background costs > you frames. Kandown additionally honours the OS-level `prefers-reduced-motion` setting. ## Animated background An optional WebGL background renders behind the board. It is off by default on low-power settings and can be disabled entirely in Settings. ## Languages The interface is translated into **48 languages**. English is the source of truth; every other locale is translated from it. Missing or awkward wording in your language is a genuinely useful contribution; locale files are plain JSON under `src/lib/i18n/locales/`. See [Contributing](https://kandown.dev/docs/project/contributing.md). ## Notifications Browser notifications and sounds can be enabled per project, for due dates and board changes. Both are off until you turn them on, and neither leaves your machine. --- # For AI agents *AI agents, https://kandown.dev/docs/agents/overview* How agents get full board context in one command, why stdout is data-only, and how to wire Kandown into an agent loop. This is the part that makes Kandown different from a task list with an AI feature bolted on, so it is worth two minutes. The design assumption is simple: **an agent is another user of the board**, not an integration. It gets the same context you do, through an interface built for how agents actually work: one command that returns everything, and output you can pipe. ## One command for context ```bash kandown work ``` That prints one deterministic document. Its fixed order starts with Kandown's immutable safety core, then real column roles and available commands, enabled extension summaries, the active workflow, tracking cadence, additive skills, global and project instructions, and finally a targeted task context or compact board digest. One call, full context. `kandown init` adds a single line to your `AGENTS.md` / `CLAUDE.md` pointing at it, a pointer rather than a block of rules copied in to go stale. That distinction is the whole point: rules that live in the CLI are upgraded when the CLI is upgraded. ### Tuning the output Settings has three tabs: **Workflow**, **Skills**, and **Kandown Work**. A project selects one exclusive workflow and may add compatible skills. Instruction detail and task-tracking cadence are independent. Freely named columns receive semantic roles, and the preview is the exact shared compiler output used by the CLI and agent launcher. The complete compiler budget remains visible across all three tabs. **Read everything** opens a full-screen rendered Markdown view of the exact document, with estimated tokens, words and characters. Individual workflow protocols, guides, templates, skills and project instructions also show their estimated token cost. Tokenization varies by model, so Kandown labels these counts as estimates. > **Tip** > Use `caveman` detail with `economy` tracking for tight loops, or `complete` with `live` tracking > for high-risk and long-running work. The safety invariants remain present in every mode. ## The output contract This is the part that makes Kandown safe to script: > **stdout carries data only** (ids, JSON, tables). Everything decorative (`✓ Created…`, warnings, > errors) goes to **stderr**. So `$(kandown create …)` captures exactly one id, and `--json | jq` never chokes on a checkmark. Exit code `0` on success, non-zero on failure. ```bash kandown list --json | jq '.[] | select(.priority=="P1")' ID=$(kandown create "Refactor auth middleware" -p P1 -t backend) kandown move "$ID" "In progress" kandown commit -m "tasks: add auth refactor" ``` ## Offline task work Task commands never contact a registry. Store access is explicit: opening a store or running a store/install/update command may fetch approved GitHub metadata. Workflow packages are pinned to a release or commit, checksum-verified, validated, and updated only after a displayed diff. The update check that *does* exist is skipped whenever stdout is not a terminal, so it can never fire in an automated context. Set `KANDOWN_NO_UPDATE=1` if you want it gone entirely. ## Keeping the board honest A board an agent writes to is only useful if what it writes is true. Two mechanisms help: - **`report:` lines on subtasks and the task `report` field** are where an agent records what it actually did. A completed task should read as a work log, not a row of ticks. - **The dependency gate** refuses to move a blocked task to the terminal column, from any interface. An agent cannot mark work done that depends on work that is not. ## Reading these docs as an agent This documentation is published as plain Markdown as well as HTML, so an agent does not have to parse a React page to follow an instruction. | URL | What you get | |---|---| | `/llms.txt` | The install command and a linked index of every page | | `/llms-full.txt` | The entire documentation in one request | | any docs URL + `.md` | That page's Markdown source (`/docs/agents/mcp` → `/docs/agents/mcp.md`) | All three are generated from the same source as the pages themselves on every deploy, so they cannot fall behind what the site says. ## Where to go next - [Project instructions](https://kandown.dev/docs/agents/instructions.md): teaching agents your project's specifics - [Launching agents](https://kandown.dev/docs/agents/launching.md): handing a task to Claude Code, Codex, Goose and others - [MCP server](https://kandown.dev/docs/agents/mcp.md): driving the board over the Model Context Protocol --- # Project instructions *AI agents, https://kandown.dev/docs/agents/instructions* Teaching agents your project's specifics through .kandown/kandown_work.md, and why it beats pasting rules into AGENTS.md. `kandown work` compiles Kandown's immutable core, the selected workflow, active skills, and live board context. What it cannot infer reliably is anything unique to **your** project. That is what `.kandown/kandown_work.md` is for. ## The file ``` .kandown/ └── kandown_work.md ``` Plain Markdown, optional and empty by default. Whatever you put in it is inserted after global instructions and before the final task or board context. ## What belongs in it Things an agent cannot infer from your code, and will otherwise get wrong: ```markdown ## Stack - pnpm, always. Never npm or yarn; the lockfile is pnpm's. - Vitest for tests: `pnpm test`. There is no jest config despite the old comments. ## Conventions - Conventional commits, imperative mood, English. - No `any` in TypeScript. Use `unknown` plus a type guard. - UI strings are authored in English and translated from there. ## Working style - Update the task file as you go, not at the end. Check off subtasks with a `report:` line as each one lands. - Be token-efficient: do not re-read files you have already read this session. ## Do not touch - `bin/*.js` and `CODEMAP.md` are build output. Edit `src/` and regenerate. ``` ## What does not belong in it - **The generic Kandown rules.** They are already served by the CLI, and duplicating them means one copy will drift. - **Anything derivable from the repository.** File structure, dependency lists and past fixes are cheaper for the agent to read directly than for you to maintain in prose. - **Secrets.** This file is committed with the rest of `.kandown/`. ## Why not just put it in AGENTS.md? You can, and for a lot of projects that is fine. Two reasons to prefer `kandown_work.md`: 1. **It reaches every interface.** `kandown work`, the MCP server and the "launch an agent" flow all include it. An agent invoked from the board gets your rules whether or not it was told to read `AGENTS.md`. 2. **It stays adjacent to the board.** Instructions about *how to work the board* live next to the board, and travel with it. > **Note** > `kandown init` adds one line to your `AGENTS.md` / `CLAUDE.md` pointing at `kandown work`. Keep > that line. It is what tells an agent the command exists in the first place. ## Checking what an agent will see ```bash kandown work ``` Run it yourself. It is the exact text your agent receives. Settings → Agent → Kandown Work shows the same compiler preview and lets you edit this file directly. --- # Launching agents *AI agents, https://kandown.dev/docs/agents/launching* Handing a task to Claude Code, Codex, Gemini CLI, Goose, Aider or OpenCode, and wiring your own tooling through the agent hook. ## From the board Select a task in the terminal UI and press a. Kandown assembles the task context and launches the agent you choose on it. | Agent | Binary | Launch mode | |---|---|---| | Claude Code | `claude` | interactive session | | OpenAI Codex | `codex` | interactive session | | Gemini CLI | `gemini` | `-p` initial prompt | | Goose | `goose` | `run --text`, non-interactive | | Aider | `aider` | `--message` initial prompt | | OpenCode | `opencode` | TUI, context written to `/tmp` | Each entry launches differently because each CLI expects a different shape of input (an interactive session where that is the natural mode, a one-shot prompt where it is not). Only agents whose binary is on your `PATH` are offered. ## Your own tooling Anything else (an IDE, a bot, an internal queue, a webhook into your own orchestrator) connects through the **agent hook**. Press g in the terminal UI (or use *Send to Agent* in the web board) and Kandown posts the task to your endpoint. ```bash export KANDOWN_AGENT_HOOK_URL="https://example.internal/agents/kandown" export KANDOWN_AGENT_HOOK_LABEL="Send to Orchestrator" export KANDOWN_AGENT_HOOK_HEADERS='{"Authorization":"Bearer $TOKEN"}' ``` | Variable | Effect | |---|---| | `KANDOWN_AGENT_HOOK_URL` | Endpoint that receives the task | | `KANDOWN_AGENT_HOOK_LABEL` | Custom label for the button | | `KANDOWN_AGENT_HOOK_HEADERS` | JSON object of extra headers | > **Warning** > The hook is the one part of Kandown that makes an outbound network request, and it does so only > when you press the key. Point it somewhere you trust; the task body goes with it. ## In a loop, without the UI The board does not have to be involved at all. `kandown work` plus the task commands are enough to drive an agent from a script: ```bash #!/usr/bin/env bash set -euo pipefail CONTEXT=$(kandown work) NEXT=$(kandown list --json | jq -r '[.[] | select(.status=="Todo")][0].id // empty') [ -z "$NEXT" ] && { echo "nothing actionable" >&2; exit 0; } kandown move "$NEXT" "In progress" claude -p "$CONTEXT Work on task $NEXT. Update the task file as you go." ``` Two properties make this reliable: task commands never touch the network, and stdout is data-only, so the `$( … )` captures above hold exactly what you expect (see [the output contract](https://kandown.dev/docs/agents/overview.md#the-output-contract). --- # MCP server *AI agents, https://kandown.dev/docs/agents/mcp* Exposing the board over the Model Context Protocol, and when to prefer it over plain CLI calls. Kandown ships a Model Context Protocol server, so MCP-capable clients can read and modify the board as structured tools rather than by shelling out. ## Running it ```bash kandown mcp ``` The server speaks MCP over **stdio**: it is meant to be launched by a client, not run in a terminal by hand. It operates on the Kandown project of its working directory. ## Registering it With Claude Code: ```bash claude mcp add kandown -- kandown mcp ``` Other clients take a command and arguments in their own configuration format; the command is always `kandown` with the single argument `mcp`, launched from your project directory. ## MCP or the CLI? Both drive the same core, so this is a question of which fits your client. **Prefer MCP when** your agent runs inside a client with native MCP support and benefits from typed tool schemas (the model gets argument validation and discoverability for free, instead of having to compose shell commands correctly). **Prefer the CLI when** you are scripting, running in CI, orchestrating agents yourself, or using a tool without MCP support. It is also the better choice for tight loops: a shell call with `--json` is about as cheap as an operation gets. > **Note** > There is no functional cliff between them. The parser, the dependency gate and the daemon module > each exist once and are shared by every interface; anything the MCP server refuses, the CLI > refuses too. ## Context first Whichever transport you use, start the session with the board context: ```bash kandown work ``` MCP gives an agent the *ability* to act on the board. `kandown work` gives it the rules, your project instructions and the digest that tell it **what to act on** (see [For AI agents](https://kandown.dev/docs/agents/overview.md). --- # CLI reference *Reference, https://kandown.dev/docs/reference/cli* Every Kandown command, its flags, and the output contract that makes them safe to script. ## The output contract Before the commands, the rule that governs all of them: > **stdout carries data only** (ids, JSON, tables). Everything decorative (`✓ Created…`, warnings, > errors) goes to **stderr**. Exit code `0` on success, non-zero on failure. So `$(kandown create …)` captures exactly one id, and `--json | jq` never chokes on a checkmark. ## Interactive | Command | Description | |---|---| | `kandown` | Web UI + terminal board | | `kandown init` | Initialize in the current project | | `kandown board` | Terminal UI only, no browser | | `kandown settings` | Terminal settings editor | | `kandown doctor` | Diagnose config, daemon, ports, task frontmatter | | `kandown help` | Full help | ## Tasks Non-interactive, agent- and CI-friendly. | Command | Description | |---|---| | `kandown list` | List tasks | | `kandown show ` | Print a task file's raw content | | `kandown create "title"` | Create a task | | `kandown move ` | Move to a column, or to `archived` | | `kandown assign [name]` | Assign, or unassign by omitting the name | | `kandown commit [-m msg]` | `git add tasks/ .kandown/kandown.json` + commit | | `kandown export` | JSON or CSV out | | `kandown import` | Trello JSON or Markdown in | ### `kandown list` ```bash kandown list [-s status] [-a assignee] [-t tag] [-p priority] [--archived] [--json] ``` | Flag | Effect | |---|---| | `-s`, `--status` | Filter by column | | `-a`, `--assignee` | Filter by assignee | | `-t`, `--tag` | Filter by tag | | `-p`, `--priority` | Filter by `P1`-`P4` | | `--archived` | Include archived tasks | | `--json` | Emit JSON instead of a table | ```bash kandown list --json | jq '.[] | select(.priority=="P1") | .title' ``` ### `kandown create` ```bash kandown create "title" [-p priority] [-a assignee] [-t tag …] [--to status] [--id custom-id] [--json] ``` | Flag | Effect | |---|---| | `-p`, `--priority` | `P1`-`P4` | | `-a`, `--assignee` | Assignee name | | `-t`, `--tag` | A tag; repeat for several | | `--to` | Target column (defaults to the first) | | `--id` | Use a specific id instead of generating one | | `--json` | Print the whole task object rather than just the id | ```bash ID=$(kandown create "Refactor auth middleware" -p P1 -t backend -t security) ``` ### `kandown move` ```bash kandown move kandown move t14 archived # archive ``` Moving to the terminal column fails, with a non-zero exit code, while any `depends_on` entry is unresolved. See [Tasks § dependencies](https://kandown.dev/docs/guides/tasks.md#dependencies). ### `kandown work` Prints the full agent context (rules, project instructions, live board digest and the next actionable task) as Markdown on stdout. Documented in [For AI agents](https://kandown.dev/docs/agents/overview.md). Pass a task id to replace the board digest with focused task context: ```bash kandown work t42 ``` ### `kandown workflow` ```bash kandown workflow list kandown workflow show kandown-standard kandown workflow template kandown-standard [template-id] kandown workflow use diagnose-and-fix kandown workflow validate ./my-workflow kandown workflow pack ./my-workflow --output my-workflow.kandown-workflow.md kandown workflow import ./my-workflow.kandown-workflow.md ``` Store access is explicit through `workflow store`, `install`, and `update`. Updates print a diff first and require `--confirm` before replacing an immutable store package. ### `kandown mcp` Starts the stdio MCP server. See [MCP server](https://kandown.dev/docs/agents/mcp.md). ## Daemon & maintenance | Command | Description | |---|---| | `kandown daemon status` | Is this project's daemon running, and on what port | | `kandown daemon start` | Start it | | `kandown daemon stop` | Stop it | | `kandown daemon refresh-all` | Restart outdated daemons on the current CLI version | | `kandown projects` | List every open Kandown project on this machine | | `kandown update` | Update the CLI and the project's `kandown.html` | > **Tip** > `kandown doctor` is the first thing to run when something is off. It checks config, daemon state, > port availability and every task's frontmatter, and tells you how to fix what it finds. ## Environment variables | Variable | Effect | |---|---| | `KANDOWN_NO_UPDATE=1` | Disable the background update check (recommended in CI) | | `KANDOWN_DEBUG=1` | Print full stack traces instead of a one-line summary | | `KANDOWN_AGENT_HOOK_URL` | Endpoint that receives tasks from *Send to Agent* / TUI g | | `KANDOWN_AGENT_HOOK_LABEL` | Custom label for the agent hook button | | `KANDOWN_AGENT_HOOK_HEADERS` | JSON object of extra headers for the hook request | --- # Data model *Reference, https://kandown.dev/docs/reference/data-model* The complete shape of a task file: frontmatter fields, body conventions, and the folder layout. One task, one file, no index. This page is the full specification of that file. ## Folder layout ``` tasks/ # the source of truth ├── t1.md ├── t14.md └── archive/ # archived tasks, still readable and in git └── t3.md .kandown/ ├── kandown.json # columns, theme, notifications, agents ├── kandown.html # the web app, one self-contained file ├── kandown_work.md # optional project agent instructions ├── workflows/ # optional local workflow packages ├── skills/ # optional local Markdown skill packages └── daemon.json # runtime state + API token (gitignored) ``` There is no index, cache or manifest anywhere. The directory listing *is* the board state. ## A task file ```markdown --- id: t1 title: Implement user auth status: Todo priority: P1 tags: [backend, security] assignee: chacha depends_on: [t7] created: 2026-04-10 --- # Implement user auth ## Context Why this task exists. ## Subtasks - [x] Create user model report: Added src/models/user.ts with the schema and migrations. - [ ] Set up OAuth provider ``` ## Frontmatter fields | Field | Type | Meaning | |---|---|---| | `id` | string | Stable identifier. Validated before it touches the filesystem | | `title` | string | Task title | | `status` | string | Board column, from `board.columns` in `kandown.json` | | `order` | number | Sort position within the column | | `priority` | `P1`-`P4` | Highest to lowest | | `tags` | string[] | Free-form labels | | `assignee` | string | A username or an agent name | | `ownerType` | `human` \| `ai` | Drives owner filtering | | `due` | date | Due date; drives the due-date banner | | `epic` | string | Groups related tasks; available as a group-by | | `depends_on` | string[] | Ids of tasks blocking this one | | `created` | date | Creation date | | `report` | string | Completion summary in Markdown, shown prominently in the UI | Unknown keys are preserved rather than stripped, so you can carry your own metadata through Kandown without it being eaten on the next write. ## Body conventions The body is ordinary Markdown. Two headings are given meaning: ### `## Context` Prose explaining why the task exists. Rendered as the task description. ### `## Subtasks` A Markdown checklist. Each item may carry an indented description and a `report:` line: ```markdown ## Subtasks - [x] Extract the token parser The old middleware parsed tokens inline, which made it untestable. report: Moved to src/auth/token.ts, added unit tests for expiry. - [ ] Cover the refresh path with tests ``` `report:` is the field that turns a completed task into a work log. Agents are expected to fill it in as they go (see [For AI agents](https://kandown.dev/docs/agents/overview.md#keeping-the-board-honest)). ## Invariants Three rules the codebase enforces, worth knowing if you script against the files: 1. **Task state lives in `tasks/*.md` and nowhere else.** No second source of truth, ever. 2. **The dependency gate, the parser and the daemon module each exist once** and are shared by the web UI, the terminal UI and the CLI. All three behave identically. 3. **Archiving is a move, not a deletion.** `tasks/archive/` is still git history you can read. ## Editing files directly Entirely supported; it is the point. Kandown watches the folder, detects external changes and surfaces them rather than overwriting. If you write a task by hand, `id`, `title` and `status` are the only fields you need; everything else has a sensible default. Run `kandown doctor` afterwards to have the frontmatter of every task validated. --- # Configuration *Reference, https://kandown.dev/docs/reference/configuration* kandown.json, environment variables, the update check, and the daemon's security model. ## `.kandown/kandown.json` Per-project configuration: columns, theme, notifications, workflow selection and `kandown work` compiler settings. It is a plain JSON file, committed with your repository, so a colleague who clones the project gets your board setup with it. Edit it through **Settings** in the web board, `kandown settings` in the terminal, or by hand. ### Columns Column names are free-form. Each column has a semantic role (`backlog`, `ready`, `active`, `review`, `terminal`, or `custom`) plus optional agent guidance. The dependency gate protects the column with the `terminal` role. Legacy configs without roles retain last-column compatibility. If several columns share a role, board order wins and the first matching column is authoritative. ### Themes 38 built-in themes plus custom themes defined as JSON, along with radius, shadow, density, motion and font-stack tokens. See [Appearance](https://kandown.dev/docs/guides/appearance.md). ### Workflow and agent output `workflow.active` selects one exclusive package. `workflow.skills` adds compatible Markdown skills, while `workflow.trackingCadence` controls update frequency independently from `agent.workOutput.detailMode`. The immutable core cannot be removed or reordered. See [For AI agents](https://kandown.dev/docs/agents/overview.md#tuning-the-output). ## `.kandown/kandown_work.md` Your project's agent instructions, injected into `kandown work`. See [Project instructions](https://kandown.dev/docs/agents/instructions.md). ## Environment variables | Variable | Effect | |---|---| | `KANDOWN_NO_UPDATE=1` | Disable the background update check (recommended in CI) | | `KANDOWN_DEBUG=1` | Print full stack traces instead of a one-line summary | | `KANDOWN_AGENT_HOOK_URL` | Endpoint that receives tasks from *Send to Agent* / TUI g | | `KANDOWN_AGENT_HOOK_LABEL` | Custom label for the agent hook button | | `KANDOWN_AGENT_HOOK_HEADERS` | JSON object of extra headers for the hook request | ## The update check Interactive runs check npm for a newer version at most once every 24 hours and install it silently when one is found. It is skipped: - for every task command, - for `kandown daemon`, - whenever stdout is not a terminal. In other words it cannot fire in CI or inside an agent loop. `KANDOWN_NO_UPDATE=1` removes it entirely. ## Security The local daemon binds to **`127.0.0.1` only** and mints a random **per-project API token** at startup. The token is stored in the gitignored `.kandown/daemon.json` and injected into the page it serves. Every route except the read-only `GET /api/daemon` identity check requires that token, so an unrelated browser tab cannot reach your tasks by scanning localhost ports (a real attack against naive local servers. Task ids are validated before they touch the filesystem, which closes the path traversal that "id" parameters invite. > **Warning** > `.kandown/daemon.json` holds a live credential and is gitignored for that reason. If you have > custom ignore rules, make sure it stays out of your commits. ## What leaves your machine Nothing, with exactly two exceptions, both of which you control: 1. **The update check**, which contacts the npm registry (disabled with `KANDOWN_NO_UPDATE=1`). 2. **The agent hook**, which posts a task to your own endpoint (only when you press the key, and only to the URL you set. No telemetry, no analytics, no account, no sync. --- # Architecture *Project, https://kandown.dev/docs/project/architecture* How the pieces fit together: the shared core, three interfaces, the daemon, and the invariants that keep them honest. This page is the map. The authoritative, always-current version lives in [`docs/ARCHITECTURE.md`](https://github.com/vava-nessa/kandown/blob/main/docs/ARCHITECTURE.md) in the repository; this is the version worth reading before you have cloned anything. ## The shape ``` ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ Web UI │ │ Terminal UI │ │ CLI │ │ (kandown.html) │ (bin/tui) │ │ (bin/kandown)│ └───────┬──────┘ └───────┬──────┘ └───────┬──────┘ │ │ │ └────────┬────────┴────────┬────────┘ │ │ ┌─────▼─────┐ ┌─────▼─────┐ │ daemon │ │ shared │ │ module │─────│ core │ └───────────┘ └─────┬─────┘ │ ┌─────▼─────┐ │ tasks/*.md│ └───────────┘ ``` Three interfaces, one core, one storage layer that is the filesystem. ## The shared core The task parser, the dependency gate and the daemon module **each exist exactly once**. Every interface calls the same implementation. This is the single most important structural decision in the project. It means: - the web board and `kandown move` cannot disagree about whether a move is legal, - a bug fixed in the gate is fixed in all three places, - there is one place to read when you want to know how something behaves. ## The daemon A small per-project HTTP server. It serves `kandown.html`, exposes the task API, and outlives the terminal UI so closing your shell does not close your browser tab. It binds to `127.0.0.1`, mints a per-project token at startup, and requires that token on every route except a read-only identity check. See [Configuration § security](https://kandown.dev/docs/reference/configuration.md#security). ## Storage `tasks/*.md`, and nothing else. No index, no cache, no manifest, no sidecar database. Every read walks the folder. On a board of a few hundred tasks that is fast enough to be unnoticeable, and the property it buys (that the directory is the state, with no way for a cache to be wrong) is worth far more than the microseconds. ## Invariants The rules that must not be broken, restated from the repository: 1. **Task state lives in `tasks/*.md` and nowhere else.** No second source of truth. 2. **The gate, the parser and the daemon module exist once** and are shared by all three interfaces. 3. **Generated files are never edited by hand.** `bin/*.js`, `CODEMAP.md`, and `src/lib/version.ts` are build output; edit the source and regenerate. 4. **UI text is authored in English.** Every other locale is translated *from* English, never into it. 5. **Every source file carries a JSDoc header** with `@file` and `@description`. `CODEMAP.md` is generated from those headers and CI fails when one is missing. ## Finding your way around the code The repository generates its own map: - **`CODEMAP.md`**: every source file with a one-line summary, generated from the JSDoc headers. Read this before grepping. - **`CODEMAP.json`**: the same data, plus symbols. Look a symbol up here instead of searching. - **`graphify query ""`**: asks what depends on what. ## Next [Contributing](https://kandown.dev/docs/project/contributing.md) covers the workflow: setting up, the build commands, and what CI checks before it will accept a change. --- # Contributing *Project, https://kandown.dev/docs/project/contributing* Setting up the repository, the build commands, the rules CI enforces, and where help is most useful. Contributions are welcome. Kandown is MIT licensed and developed in the open at [github.com/vava-nessa/kandown](https://github.com/vava-nessa/kandown). ## Setup ```bash git clone https://github.com/vava-nessa/kandown.git cd kandown pnpm install # also installs the git hooks pnpm dev # web UI at localhost:5176 ``` pnpm, not npm; the lockfile is pnpm's. ## Read these first In this order, before your first change: | Document | What it gives you | |---|---| | `AGENTS.md` | The project's rules, including which files are generated | | `CODEMAP.md` | Every source file with a one-line summary, generated from JSDoc | | `docs/ARCHITECTURE.md` | How the pieces fit and which invariants not to break | | `docs/RELEASE.md` | The release runbook | Then run `kandown work` in the repository. It prints the current agent rules plus a live board digest and the next actionable task. ## Commands | Script | Description | |---|---| | `pnpm dev` | Vite dev server for the web UI | | `pnpm dev:app` | Full build, then launch the CLI; the realistic dev loop | | `pnpm dev:cli` | Watch-mode build of the CLI/TUI bundles | | `pnpm build` | Version inject, typecheck, web, then CLI | | `pnpm typecheck` | TypeScript, no emit | | `pnpm codemap` | Regenerate `CODEMAP.md` / `CODEMAP.json` | | `pnpm codemap:check` | Fail if the codemap is stale or a file lacks `@description` | Git hooks install themselves on `pnpm install`: pre-commit regenerates and stages the codemap, post-commit refreshes the local dependency graph. Neither can fail a commit. ## The two rules that trip people up ### Never edit a generated file They are committed because they ship, so editing one appears to work (until the next `pnpm build` silently erases it). | Never edit | Edit instead | |---|---| | `bin/kandown.js` | `src/cli/cli.ts` | | `bin/tui.js` | `src/cli/tui.tsx` | | `src/lib/version.ts` | `package.json` (version field) | | `CODEMAP.md`, `CODEMAP.json` | the JSDoc headers, then `pnpm codemap` | `CODEMAP.md` flags each of these inline, at the moment you go looking for it. ### Every source file carries a JSDoc header `@file`, `@description`, and `@functions` / `@exports` where they help. This is not decoration: `CODEMAP.md` is built from these headers and `pnpm codemap:check` (run in CI) **fails** when a file has no `@description`. Coverage is at 100%; keep it there. Write the header *after* the feature works, not before. Explain **why** and **when it runs**, not just what it is. > **Tip** > The short version of both rules: `bin/*.js` are build output, not source. Edit `src/`. ## Commits Conventional commits, imperative mood, subject wrapped at 72 characters, one logical change per commit. The body explains *why*; the diff already shows what. ``` feat(board): add group-by epic The backlog grew past the point where priority grouping was useful. Epics were already in the data model but had no view. ``` Types: `feat`, `fix`, `chore`, `refactor`, `perf`, `style`, `docs`, `test`, `build`, `ci`, `revert`. Breaking changes go in a `BREAKING CHANGE:` footer. ## Where help is most useful - **Translations.** 48 languages ship, and most were machine-assisted. A native speaker fixing awkward wording in `src/lib/i18n/locales/` is a genuinely high-value change. English is the source of truth: translate *from* it, never into it. - **Agent integrations.** New CLI agents in the launcher, or improvements to the `kandown work` output for a client you use daily. - **Bug reports with a task file attached.** Since tasks are plain files, a reproduction is usually one `.md` you can paste into an issue. ## Documentation site This site lives in `website/` in the same repository, and every docs page has an **Edit this page on GitHub** link at the bottom. Content is MDX under `website/src/content/docs/`; adding a page means creating the file and adding a line to `website/src/content/nav.ts`. ---