Personal Kanban
A file-based personal kanban board for VSCode. The entire board state lives in plain text files inside your project — no database, no server, no account required.
Features
- Git-friendly — one card changed = one file changed; commit your board alongside your code
- File-based — board state is human-readable Markdown you can edit directly in a pinch
- AI-readable — structured so an AI can understand board state without special tooling
- Drag and drop — move cards between columns and reorder within a column
- Inline editing — double-click any card to edit (markdown supported)
- Tag system — write
#tagname anywhere in a card and tags appear automatically
- Live sync — editing
manifest.json externally refreshes the board instantly
- Lead time & cycle time — done cards show lead time (creation → done); the metadata popup shows both lead time and cycle time (in-progress → done)
- Hooks — run Node.js scripts on board events (card moved, WIP exceeded, etc.)
Commands
| Command |
Description |
Personal Kanban: Init Board |
Creates .personal-kanban/ in the workspace root with a default manifest.json, cards/, archive/, and scripts/ folders |
Personal Kanban: Open Board |
Opens the Kanban board webview panel |
Open the Command Palette (Cmd+Shift+P / Ctrl+Shift+P) and type Personal Kanban to find both commands.
Board Structure
Running Personal Kanban: Init Board creates:
{workspace-root}/
└── .personal-kanban/
├── manifest.json ← source of truth for column order and card placement
├── GUIDELINES.md ← editable workflow guidelines
├── cards/
│ └── {id}.md ← one file per active card
├── archive/
│ └── {id}.md ← archived cards (moved from Done)
└── scripts/
├── lib.js ← shared helpers (notify, readPayload)
├── card-created.js
├── card-edited.js
├── card-deleted.js
├── card-moved.js
├── card-reviewed.js
├── cards-archived.js
└── wip-alert.js
The default columns are Backlog, Refined, In Progress, Review, and Done. To change column names, reorder, or add columns, edit manifest.json directly.
manifest.json shape
{
"version": 4,
"name": "my-project",
"columns": [
{ "id": "backlog", "label": "Backlog", "wip_limit": null, "cards": [] },
{ "id": "refined", "label": "Refined", "wip_limit": null, "cards": [] },
{ "id": "in-progress", "label": "In Progress", "wip_limit": 1, "cards": ["20260326-b7c2"] },
{ "id": "review", "label": "Review", "wip_limit": null, "cards": [] },
{ "id": "done", "label": "Done", "wip_limit": null, "cards": [] }
]
}
Card IDs are stored directly in each column's cards array. wip_limit triggers a wip.violated hook event when a column exceeds its limit.
Note: tags, scripts, hooks, and showCardAge (lead time badge) are read from VSCode settings (.vscode/settings.json) and are not stored in manifest.json.
Card file shape
Cards live in cards/{id}.md as YAML frontmatter followed by a Markdown body:
---
id: 20260326-b7c2
created_at: 2026-03-26T10:00:00.000Z
active_at: 2026-03-27T09:00:00.000Z
done_at: 2026-03-28T15:00:00.000Z
branch: feature/card-title
---
#feature
# Card title
Description text.
- The first line of the body should be space-separated
#tags.
- The card title is the first H1 (
#) heading.
active_at is stamped automatically when the card is first moved to the in-progress column.
done_at is stamped automatically each time the card is moved to the done column.
branch is set when work begins on a card and cleared after the branch is merged.
- Archived cards are identical in format and live in
archive/{id}.md.
Card IDs
Cards are identified by YYYYMMDD-xxxx (UTC date + 4 random hex chars), e.g. 20260326-b7c2.
Usage
- Open a project folder in VSCode.
- Run
Personal Kanban: Init Board — creates the .personal-kanban/ folder.
- Run
Personal Kanban: Open Board to view the board.
- Click + Add card at the bottom of any column to create a card.
- Single-click a card to read it. Double-click to edit.
- Press
Ctrl+S or click away to save. Press Escape to discard changes.
- Drag cards between columns or reorder within a column.
- Hover a card and click the delete button to remove it (confirmation required).
- Use the Archive Done button to move all Done cards to
archive/.
Add #tagname anywhere in a card's content. Tags are extracted at render time and displayed on the card face. Configure tag colors and sort weights in VSCode settings (see below).
Editing the board manually
manifest.json is the source of truth. You can edit it directly — the board refreshes automatically when the file changes.
VSCode Settings
Init Board writes default values to .vscode/settings.json if not already present.
"personal-kanban.tags": {
"bug": { "color": "#e11d48", "weight": 10 },
"feature": { "color": "#2563eb", "weight": 5 },
"chore": { "color": "#6b7280", "weight": 1 },
"urgent": { "color": "#f97316", "weight": 20 }
}
color is a hex string used to tint the tag badge. weight controls sort order — higher weight cards sort to the top of their column.
This setting is edited as JSON. VSCode provides inline validation and autocomplete for color and weight fields thanks to the bundled schema.
Tag color target
"personal-kanban.tagColorTarget": "tag"
Controls where tag colors are applied on a card. Configurable from the Settings UI as a dropdown. Options:
| Value |
Effect |
tag (default) |
Colors the tag chip itself |
card-border |
Colors the card's left border using the dominant tag |
card-background |
Tints the card background using the dominant tag |
The dominant tag is the one with the highest weight.
Board folder name
"personal-kanban.boardFolderName": ".personal-kanban"
Name of the folder (relative to the workspace root) where board data is stored. Change this if .personal-kanban conflicts with another tool. Configurable from the Settings UI as a text field.
Note: If you change this after Init Board has run, rename the existing folder to match.
Show lead time
"personal-kanban.showCardAge": true
When true (default), done cards display their lead time — the duration from creation to done — as a small badge below the card ID. Formatted as 0m, 4h, 3d, or 2w. Set to false to hide it. Configurable from the Settings UI as a checkbox.
The card metadata popup (ⓘ button) also shows cycle time — the duration from when the card entered in-progress to when it was moved to done.
Enable hooks
"personal-kanban.enableHooks": true
When false, no hook scripts are executed on board events. Useful for disabling all hook side-effects without removing the script and hook configuration. Configurable from the Settings UI as a checkbox.
Scripts & Hooks
Scripts are Node.js files that receive a JSON event payload via stdin. Define them under personal-kanban.scripts and bind them to events under personal-kanban.hooks:
"personal-kanban.scripts": {
"card-moved": { "file": "scripts/card-moved.js" },
"card-reviewed": { "file": "scripts/card-reviewed.js" },
"wip-alert": { "file": "scripts/wip-alert.js" }
},
"personal-kanban.hooks": {
"card.moved": ["card-moved"],
"card.reviewed": ["card-reviewed"],
"wip.violated": ["wip-alert"]
}
All paths are relative to .personal-kanban/.
Hook events
| Event |
Payload fields |
card.created |
card_id, card_title, column |
card.edited |
card_id, card_title |
card.deleted |
card_id, card_title, last_column |
card.moved |
card_id, card_title, from_column, to_column, branch |
card.reviewed |
card_id, card_title, from_column, branch |
wip.violated |
column_id, wip_limit, current_count |
cards.archived |
column |
Every payload also includes event (the event name) and timestamp (ISO-8601).
The sample scripts in scripts/ show how to read the payload and fire OS notifications using scripts/lib.js. Customize them freely.
Claude Code Integration
This project includes a /personal-kanban skill for Claude Code. It lets Claude read and manage the board directly — no manual JSON editing required.
Skill commands
| Command |
Description |
/personal-kanban |
Show board status: all columns, card counts, and titles |
/personal-kanban list |
List all cards grouped by column with tag, title, and branch |
/personal-kanban start |
Move the top card from Refined (or Backlog) to In Progress |
/personal-kanban review |
Push branch, move active In Progress card to Review |
/personal-kanban done [title] |
Merge the card's branch, move card to Done |
/personal-kanban new #tag Title |
Create a new card directly in In Progress |
/personal-kanban raise #tag Title |
Raise a new card from a review finding |
Workflow
Backlog → Refined → In Progress → Review → Done → (archive)
↑ ↓
branch saved branch merged
to card metadata and deleted
/personal-kanban start — picks the top refined card, creates a git branch, saves the branch name to metadata.branch.
- Work is committed on the branch with small, focused commits.
/personal-kanban review — pushes the branch and moves the card to Review. The branch is not merged yet.
- You review the work in your own time. When satisfied, drag the card to Done or run
/personal-kanban done.
/personal-kanban done — reads metadata.branch from the card, merges into main, deletes the branch, and clears the branch field.
- Use Archive Done to sweep completed cards out of view.
Multiple cards can be in Review simultaneously, each with their own branch tracked in metadata.branch.
Development
Prerequisites
Setup
npm install
npm run build
Available scripts
| Script |
Description |
npm run build |
Compile extension to dist/extension.js |
npm run watch |
Rebuild on file changes |
npm run lint |
Run ESLint |
npm run typecheck |
Type-check without emitting |
Running locally (F5 debug)
- Open this repository in VSCode.
- Press
F5 — this launches an Extension Development Host window.
- In that new window, open any folder, then run the
Personal Kanban: commands.
Deploy script
Use scripts/deploy.sh for both local installs and marketplace publishing.
Local install (dev build)
./scripts/deploy.sh
Packages the extension with name personal-kanban-dev and display name Personal Kanban (Dev), then installs it. Because the extension ID differs from the published version (TGBY.personal-kanban vs TGBY.personal-kanban-dev), both can be installed simultaneously in VSCode — useful for comparing dev changes against the released build.
Publish to marketplace
./scripts/deploy.sh --publish
Bumps the patch version, publishes to the VS Code Marketplace using AZURE_PAT from .env, and commits the version bump. Requires AZURE_PAT set in a .env file at the repo root.
Prerequisites
vsce is installed automatically if missing. Alternatively:
npm install -g @vscode/vsce
Source layout
src/
├── extension.ts — activation, command registration, Init Board scaffold
├── BoardPanel.ts — webview panel (HTML, CSS, JS, message handling)
├── hooks.ts — hook dispatcher: reads scripts/hooks from manifest, spawns Node scripts
├── io.ts — file I/O: manifest reader/writer, card reader/writer, file watcher
└── types.ts — TypeScript interfaces for manifest and card shapes