kandown 0.3.3 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,226 +1,257 @@
1
1
  <p align="center">
2
- <img src="logo.svg" width="128" height="128" alt="Kandown logo">
2
+ <img src="logo.svg" width="140" height="140" alt="Kandown logo">
3
3
  </p>
4
4
 
5
- # Kandown
5
+ <h1 align="center">Kandown</h1>
6
6
 
7
- A file-based Kanban engine backed by plain markdown. Zero backend, zero database, no account, AI-agent friendly.
8
-
9
- Kandown installs a self-contained web app into a project folder. The app reads and writes local markdown files through the browser File System Access API, so your board stays in your repo, remains git-diffable, and can be edited by humans or AI agents without a hosted service.
7
+ <p align="center">
8
+ <strong>File-based Kanban board backed by plain Markdown.</strong><br>
9
+ Zero backend · Zero database · No account · AI-agent friendly
10
+ </p>
10
11
 
11
- ## Why
12
+ <p align="center">
13
+ <a href="https://www.npmjs.com/package/kandown"><img src="https://img.shields.io/npm/v/kandown?color=cb3837&label=npm" alt="npm version"></a>
14
+ <a href="https://www.npmjs.com/package/kandown"><img src="https://img.shields.io/npm/dm/kandown?color=blue" alt="npm downloads"></a>
15
+ <img src="https://img.shields.io/badge/license-MIT-green" alt="MIT License">
16
+ <img src="https://img.shields.io/badge/languages-48-purple" alt="48 languages">
17
+ <img src="https://img.shields.io/badge/local--first-100%25-orange" alt="100% local-first">
18
+ </p>
12
19
 
13
- Most kanban tools trap your data in their cloud. Kandown does the opposite: all state lives in `.kandown/` as markdown and JSON.
20
+ <p align="center">
21
+ <a href="#-quick-start">Quick Start</a> ·
22
+ <a href="#-features">Features</a> ·
23
+ <a href="#-cli-commands">CLI</a> ·
24
+ <a href="#-board-tui">Board TUI</a> ·
25
+ <a href="#-ai-agent-integration">AI Agents</a> ·
26
+ <a href="#-keyboard-shortcuts">Shortcuts</a> ·
27
+ <a href="#-development">Development</a>
28
+ </p>
14
29
 
15
- The core architecture keeps task state in the task files themselves:
30
+ ---
16
31
 
17
- - `tasks/<id>.md` stores the full task context and board state: title, status, order, metadata, subtasks, notes, and completion reports.
18
- - `kandown.json` stores project preferences such as board columns, theme mode, skin, font, agent behavior, notifications, and enabled fields.
32
+ ## 🚀 Quick Start
19
33
 
20
- That task-first model matters for AI tools. Moving or completing a task means editing one markdown file, not synchronizing an index and a detail file.
34
+ ### 1. Install globally
21
35
 
22
- ## Install & Use
36
+ ```bash
37
+ npm i -g kandown
38
+ ```
23
39
 
24
- If Kandown is published on npm:
40
+ ### 2. Initialize in any project
25
41
 
26
42
  ```bash
27
43
  cd my-project
28
- npx kandown init
44
+ kandown init
45
+ ```
46
+
47
+ ### 3. Launch your board
48
+
49
+ ```bash
50
+ kandown
29
51
  ```
30
52
 
31
- This creates:
53
+ > That's it. A local web UI opens in your browser, and an interactive board TUI appears in your terminal. All your data stays in `.kandown/` as plain markdown — versioned with git, readable by humans and AI agents alike.
54
+
55
+ ---
56
+
57
+ ## 💡 Why Kandown?
58
+
59
+ Most kanban tools trap your data in their cloud. Kandown does the opposite.
32
60
 
33
- ```text
61
+ | Traditional Kanban | Kandown |
62
+ |---|---|
63
+ | ☁️ Cloud-hosted, needs an account | 📁 100% local, no account |
64
+ | 🔒 Proprietary data format | 📝 Plain Markdown + JSON |
65
+ | 💰 Paid plans for teams | 🆓 Free & open-source (MIT) |
66
+ | 🤖 No AI integration | 🤖 AI-agent native (Claude, Codex, Gemini…) |
67
+ | 🔄 Requires sync/internet | 📂 Git-diffable, offline-first |
68
+ | 🏗️ Backend, database, infra | 🚫 Zero backend, zero dependencies |
69
+
70
+ **Your tasks are just `.md` files.** Move them, `grep` them, edit them in Vim, let an AI agent process them — they're yours.
71
+
72
+ ---
73
+
74
+ ## 📦 What Gets Installed
75
+
76
+ Running `kandown init` creates a `.kandown/` folder in your project:
77
+
78
+ ```
34
79
  .kandown/
35
- ├── kandown.html # single-file web app, built from dist/index.html
36
- ├── kandown.json # project preferences, columns, notifications, and appearance
37
- ├── tasks/ # per-task markdown files and board state
38
- ├── AGENT.md # short AI-agent rules
39
- └── README.md # user-facing project-local guide
80
+ ├── kandown.html Single-file web app (opens in any browser)
81
+ ├── kandown.json Project preferences, columns, appearance
82
+ ├── tasks/ One markdown file per task (source of truth)
83
+ ├── AGENT.md AI-agent quick reference
84
+ └── README.md Project-local user guide
40
85
  ```
41
86
 
42
- It also copies `AGENT_KANDOWN.md` to the project root and adds a reference to `AGENTS.md` / `CLAUDE.md` when possible, so AI tools know how to work with the board.
43
-
44
- To use the board:
45
-
46
- 1. Open `.kandown/kandown.html` in Chrome, Edge, Brave, or Opera.
47
- 2. Select the project folder when prompted.
48
- 3. Grant read/write permission.
49
-
50
- Firefox and Safari do not currently support the required File System Access API.
51
-
52
- ## Features
53
-
54
- - **File-over-app**: Markdown and JSON are the source of truth.
55
- - **Zero backend**: No server, database, login, or sync vendor.
56
- - **AI-agent optimized**: Task files are the single source of truth.
57
- - **Board and list views**: Toggle with `⌘1` / `⌘2`.
58
- - **Column status icons**: Board columns use Tabler icons beside titles so states like Backlog, In Progress, Review, and Done are easier to scan.
59
- - **Column color accents**: Columns can use expanded translucent background colors, including black variants.
60
- - **Custom columns**: Add, rename, and delete columns from the board; unknown task statuses appear as temporary columns until added to settings.
61
- - **Drag and drop**: Move cards between columns with optimistic file writes.
62
- - **Guarded card deletion**: Hover a card and click the trash icon twice to delete a task without opening the drawer.
63
- - **Task drawer**: Edit title, enabled metadata fields, subtasks, and body content via a WYSIWYG markdown editor (Wysimark).
64
- - **Content search**: Search titles, ids, task body, subtasks, tags, assignee, and priority with highlighted previews.
65
- - **Command palette**: `⌘K` / `Ctrl+K` for task search and quick actions.
66
- - **Owner type filtering**: Separate human tasks from AI-agent tasks.
67
- - **Dense settings**: Sidebar search, compact setting controls, and hover help explain project options.
68
- - **Configurable notifications**: Chrome permission, status-change alerts, debounced task-edit alerts, subtask-completion alerts, and in-page sound cues.
69
- - **External-change detection**: Warns when a task file is modified outside the app and offers Reload / Overwrite / Cancel choices via ConflictModal.
70
- - **Appearance system**: Project-level `auto` / `light` / `dark`, built-in skins, fonts, animated WebGL backgrounds (LiquidEther fluid simulation), and local font presets.
71
- - **Recent projects**: Stored in IndexedDB so local handles can be reopened quickly.
72
- - **i18n**: 48 languages supported.
73
- - **Single-file publish artifact**: Vite bundles the web UI into `dist/index.html`.
74
-
75
- ## Keyboard Shortcuts
87
+ It also copies `AGENT_KANDOWN.md` to the project root and wires it into your `AGENTS.md` / `CLAUDE.md` so AI agents know how to manage your board automatically.
76
88
 
77
- | Key | Action |
89
+ ---
90
+
91
+ ## ✨ Features
92
+
93
+ ### Board & Views
94
+
95
+ | Feature | Description |
78
96
  |---|---|
79
- | `⌘K` / `Ctrl+K` | Open command palette |
80
- | `⌘1` / `Ctrl+1` | Board view |
81
- | `⌘2` / `Ctrl+2` | List view |
82
- | `N` | New task |
83
- | `R` | Reload files from disk |
84
- | `/` | Focus task search |
85
- | `Esc` | Cancel the drawer or close the command palette |
86
- | `⌘S` / `Ctrl+S` | Save current task in the drawer |
87
- | `⌘⌫` / `Ctrl+Backspace` | Delete current task in the drawer after confirmation |
97
+ | 🗂️ Board view | Horizontal kanban with drag-and-drop between columns |
98
+ | 📋 List view | Dense table-like view with the same filters & search |
99
+ | 🔍 Content search | Search titles, body, subtasks, tags, assignee, priority — with highlighted previews |
100
+ | ⌨️ Command palette | `⌘K` / `Ctrl+K` for quick actions and task lookup |
101
+ | 🏷️ Custom columns | Add, rename, delete columns — unknown statuses appear as temp columns |
102
+ | 🗑️ Guarded deletion | Double-click the trash icon to delete — no accidental losses |
88
103
 
89
- ## CLI
104
+ ### Task Management
105
+
106
+ | Feature | Description |
107
+ |---|---|
108
+ | ✏️ Rich task drawer | Edit title, metadata, subtasks, and body via WYSIWYG markdown editor |
109
+ | ☑️ Subtasks | Full checklist support with progress tracking on cards |
110
+ | 📊 Metadata fields | Priority, assignee, tags, due date, owner type — toggle each on/off |
111
+ | 👤 Owner filtering | Separate human tasks from AI-agent tasks |
112
+ | ⚡ External-change detection | Warns when a file was modified outside the app (Reload / Overwrite / Cancel) |
113
+
114
+ ### Appearance & UX
115
+
116
+ | Feature | Description |
117
+ |---|---|
118
+ | 🎨 5 built-in skins | Kandown, Graphite, Sage, Cobalt, Rose |
119
+ | 🌗 Theme modes | Auto, Light, Dark |
120
+ | 🔤 5 font stacks | Inter, System, Serif, Mono, Rounded |
121
+ | 🌊 Animated backgrounds | WebGL fluid simulation (LiquidEther) |
122
+ | 🔔 Notifications | Browser + in-page sound alerts for status changes, edits, subtask completions |
123
+ | 🌍 48 languages | Full i18n support |
124
+ | 📌 Recent projects | Stored in IndexedDB for quick reopening |
125
+
126
+ ---
127
+
128
+ ## 🖥️ CLI Commands
129
+
130
+ ### Installation
131
+
132
+ **Always install globally first:**
133
+
134
+ ```bash
135
+ npm install -g kandown
136
+ ```
137
+
138
+ Then run from any project directory. Upgrades are automatic — just run `kandown` again.
139
+
140
+ ### Usage
90
141
 
91
142
  ```bash
92
- # Start the local HTTP web UI + open the interactive board TUI (recommended)
93
- npx kandown
94
- npx kandown --port 3000
95
-
96
- # Board TUI only (no browser)
97
- npx kandown board
98
-
99
- # Initialize kandown in the current project
100
- npx kandown init
101
- npx kandown init --path docs/tasks
102
- npx kandown init --no-agents
103
- npx kandown init --force
104
-
105
- # Other commands
106
- npx kandown update
107
- npx kandown settings
143
+ kandown [command] [options]
108
144
  ```
109
145
 
110
146
  ### Commands
111
147
 
112
- | Command | Purpose |
148
+ | Command | Description |
113
149
  |---|---|
114
- | *(none)* | Start a local HTTP server for `.kandown/kandown.html`, open the web UI in your default browser, and launch the board TUI. |
115
- | `board` | Open the interactive kanban board TUI only (no browser). |
116
- | `init` | Create `.kandown/`, copy templates, copy the built web app, and install agent docs. |
117
- | `update` | Replace an installed `kandown.html` with the current package build. |
118
- | `settings` | Open the Ink-based terminal settings editor for `kandown.json`. |
119
- | `help` | Print CLI help. |
150
+ | `kandown` | Launch web UI + board TUI (recommended daily workflow) |
151
+ | `kandown init` | Initialize Kandown in the current project |
152
+ | `kandown board` | Open the board TUI only (no browser) |
153
+ | `kandown settings` | Open the terminal settings editor |
154
+ | `kandown update` | Update `kandown.html` to the latest version |
155
+ | `kandown help` | Print CLI help |
120
156
 
121
- The bare `kandown` command uses a zero-dependency Node.js HTTP server. It tries `http://localhost:2048` first, then scans through port `2060` if earlier ports are busy. Use `--port <number>` to request a specific port.
157
+ ### Init Options
122
158
 
123
- ### Board TUI
159
+ | Flag | Description |
160
+ |---|---|
161
+ | `--path <dir>` | Install `.kandown` at a custom location |
162
+ | `--force` | Overwrite existing installation |
163
+ | `--no-agents` | Skip AI agent docs setup |
124
164
 
125
- The board TUI is a full-screen terminal kanban built with [Ink](https://github.com/vadimdemedes/ink). It renders the same columns and tasks as the web UI, and lets you launch an AI agent on any task directly from the terminal.
165
+ ### Serve Options
166
+
167
+ | Flag | Description |
168
+ |---|---|
169
+ | `--port <number>` | Use a specific port (default: auto-scan 2048–2060) |
170
+
171
+ ---
172
+
173
+ ## 📟 Board TUI
174
+
175
+ The board TUI is a full-screen terminal kanban built with [Ink](https://github.com/vadimdemedes/ink). Same columns and tasks as the web UI — plus the ability to launch AI agents on any task.
126
176
 
127
177
  ```
128
178
  KANDOWN tmux My Project
129
- ────────────────────────────────────────────────────────────────
179
+ ──────────────────────────────────────────────────────────────
130
180
  Backlog (3) │ Todo (2) │ In Progress │ Review (1) │ Done
131
181
  ──────────────│──────────────│──────────────│────────────│──────
132
182
  ▸ t9 │ t16 │ (empty) │ t18 │ ...
133
- t10 │ t7 │ │
183
+ t10 │ t7 │ │
134
184
  t11 │ │
135
185
  ```
136
186
 
137
- **Navigation:**
187
+ ### TUI Navigation
138
188
 
139
189
  | Key | Action |
140
190
  |---|---|
141
191
  | `h` / `l` or `←` / `→` | Move between columns |
142
- | `j` / `k` or `↑` / `↓` | Move between tasks within a column |
143
- | `Enter` | Open task detail view (scrollable) |
144
- | `a` | Open agent picker for the focused task |
145
- | `r` | Reload task files from disk |
146
- | `q` / `Esc` | Quit (or go back from detail / picker) |
147
-
148
- **Agent picker** (`a` key): shows only agents currently installed in your `PATH`. Selecting one:
149
- 1. Sets the task frontmatter `status` to **In Progress**.
150
- 2. Constructs a system prompt from `AGENT_KANDOWN.md` + the task file.
151
- 3. Writes context to `/tmp/kandown-<id>-context.md` for reference.
152
- 4. If inside **tmux**: opens the agent in a new 50%-wide right pane (the TUI stays visible).
153
- 5. If not in tmux: exits the TUI and hands the terminal to the agent.
154
-
155
- **Supported agents** (auto-detected via `which`):
156
-
157
- | Agent | Binary | Notes |
192
+ | `j` / `k` or `↑` / `↓` | Move between tasks |
193
+ | `Enter` | Open task detail (scrollable) |
194
+ | `a` | Launch AI agent picker |
195
+ | `r` | Reload files from disk |
196
+ | `q` / `Esc` | Quit or go back |
197
+
198
+ ---
199
+
200
+ ## 🤖 AI Agent Integration
201
+
202
+ Press `a` in the board TUI to launch an AI agent on the selected task. Kandown auto-detects installed agents and builds a context-rich prompt from `AGENT_KANDOWN.md` + the task file.
203
+
204
+ ### Supported Agents
205
+
206
+ | Agent | Binary | Launch mode |
158
207
  |---|---|---|
159
- | Claude Code | `claude` | Interactive session with initial prompt |
160
- | OpenAI Codex | `codex` | Interactive session |
161
- | Gemini CLI | `gemini` | `-p` flag for initial prompt |
162
- | Goose | `goose` | `run --text` for non-interactive |
163
- | Aider | `aider` | `--message` for initial prompt |
164
- | OpenCode | `opencode` | TUI, context written to `/tmp` |
208
+ | **Claude Code** | `claude` | Interactive session with initial prompt |
209
+ | **OpenAI Codex** | `codex` | Interactive session |
210
+ | **Gemini CLI** | `gemini` | `-p` flag for initial prompt |
211
+ | **Goose** | `goose` | `run --text` for non-interactive |
212
+ | **Aider** | `aider` | `--message` for initial prompt |
213
+ | **OpenCode** | `opencode` | TUI, context written to `/tmp` |
165
214
 
166
- ## Project Architecture
215
+ ### How it works
167
216
 
168
- ```text
169
- kandown/
170
- ├── bin/
171
- │ ├── kandown.js # npm CLI entrypoint (hand-rolled, no deps)
172
- │ └── tui.js # generated TUI bundle from tsup
173
- ├── src/
174
- │ ├── App.tsx # web app shell and global shortcuts
175
- │ ├── main.tsx # React/Vite browser entrypoint
176
- │ ├── cli/ # Ink terminal UI source
177
- │ │ ├── tui.tsx # Ink entrypoint — alternate screen buffer
178
- │ │ ├── app.tsx # TUI screen router (board, settings)
179
- │ │ ├── lib/
180
- │ │ │ ├── config.ts # kandown.json reader/writer
181
- │ │ │ ├── board-reader.ts # Node fs task scanner + moveTaskToColumn
182
- │ │ │ ├── agents.ts # AI agent registry, detection, prompt builder
183
- │ │ │ └── launcher.ts # Process spawning (tmux / direct exec)
184
- │ │ └── screens/
185
- │ │ ├── board.tsx # Interactive kanban board TUI
186
- │ │ ├── agent-picker.tsx # Agent selection overlay
187
- │ │ └── settings.tsx # Settings editor TUI
188
- │ ├── components/ # React UI components (web only)
189
- │ ├── hooks/ # small React hooks
190
- │ ├── lib/ # domain model, parser, serializer, store, theme, filesystem
191
- │ ├── logo.svg
192
- │ └── styles/ # Tailwind layers and CSS tokens
193
- ├── templates/ # files copied by `kandown init`
194
- │ ├── AGENT_KANDOWN.md # full agent instructions (copied to project root)
195
- │ └── AGENT_KANDOWN.md # agent instructions (single source of truth)
196
- ├── dist/index.html # generated single-file web app
197
- ├── tailwind.config.js
198
- ├── vite.config.ts
199
- ├── tsup.config.ts
200
- └── package.json
201
- ```
217
+ 1. Selecting an agent sets the task status to **In Progress**
218
+ 2. A system prompt is built from `AGENT_KANDOWN.md` + the task file
219
+ 3. Context is written to `/tmp/kandown-<id>-context.md`
220
+ 4. **In tmux**: opens in a 50%-wide split pane (TUI stays visible)
221
+ 5. **Without tmux**: exits TUI and hands the terminal to the agent
202
222
 
203
- ## Runtime Flow
223
+ > **Tip:** AI agents can also edit task files directly — Kandown detects external changes and syncs automatically.
204
224
 
205
- 1. `main.tsx` mounts `App`.
206
- 2. `App` renders the header and either `EmptyState`, `Board`, `ListView`, or `SettingsPage`.
207
- 3. The user selects a folder with the File System Access API.
208
- 4. `filesystem.ts` resolves or creates `.kandown/`, `tasks/`, and `kandown.json`.
209
- 5. `store.ts` loads config, applies appearance tokens, scans task files, and keeps recent project handles in IndexedDB.
210
- 6. `parser.ts` converts task markdown into typed board/task data.
211
- 7. React components render the board/list/drawer.
212
- 8. Mutations go back through store actions, then through `serializer.ts` and `filesystem.ts`.
225
+ ---
226
+
227
+ ## ⌨️ Keyboard Shortcuts
228
+
229
+ ### Web UI
230
+
231
+ | Shortcut | Action |
232
+ |---|---|
233
+ | `⌘K` / `Ctrl+K` | Command palette |
234
+ | `⌘1` / `Ctrl+1` | Board view |
235
+ | `⌘2` / `Ctrl+2` | List view |
236
+ | `N` | New task |
237
+ | `R` | Reload from disk |
238
+ | `/` | Focus search |
239
+ | `Esc` | Close drawer / palette |
240
+ | `⌘S` / `Ctrl+S` | Save task in drawer |
241
+ | `⌘⌫` / `Ctrl+Backspace` | Delete task (with confirmation) |
242
+
243
+ ---
213
244
 
214
- ## Data Model
245
+ ## 📄 Data Model
215
246
 
216
- ### `tasks/<id>.md`
247
+ ### Task files — `tasks/<id>.md`
217
248
 
218
- Task files store rich context and board state.
249
+ Each task is a standalone markdown file with YAML frontmatter:
219
250
 
220
251
  ```markdown
221
252
  ---
222
253
  id: t1
223
- title: Full task title
254
+ title: Implement user auth
224
255
  status: Todo
225
256
  order: 0
226
257
  priority: P1
@@ -230,25 +261,24 @@ created: 2026-04-10
230
261
  ownerType: human
231
262
  ---
232
263
 
233
- # Task title
264
+ # Implement user auth
234
265
 
235
266
  ## Context
236
-
237
- Why this task exists.
267
+ Why this task exists and what it solves.
238
268
 
239
269
  ## Subtasks
240
-
241
- - [ ] First step
242
- - [x] Second step
270
+ - [ ] Set up OAuth provider
271
+ - [x] Create user model
272
+ - [ ] Add session middleware
243
273
 
244
274
  ## Notes
245
-
246
- Extra details.
275
+ Extra details, links, decisions.
247
276
  ```
248
277
 
249
- ### `kandown.json`
278
+ ### Configuration — `kandown.json`
250
279
 
251
- Project-level preferences:
280
+ <details>
281
+ <summary>Full default configuration</summary>
252
282
 
253
283
  ```json
254
284
  {
@@ -287,315 +317,182 @@ Project-level preferences:
287
317
  }
288
318
  ```
289
319
 
290
- Disabled fields are hidden from the task drawer, cards, list view, and metadata filters. `board.defaultPriority` only applies when `fields.priority` is enabled, and `board.defaultOwnerType` only applies when `fields.ownerType` is enabled.
291
-
292
- Notifications are driven by a 500ms polling file watcher that computes SHA-256 hashes of task file content to detect external changes. Status changes fire when task frontmatter `status` changes, task edit notifications fire after `notifications.editDebounceMs` with a minimum 2 second delay, and subtask completion notifications fire when a checklist item flips from open to done. Browser notifications require Chrome permission; sound notifications play inside the open board tab.
293
-
294
- ## Appearance Architecture
295
-
296
- Kandown uses shadcn-compatible CSS variables without depending on shadcn components. The app keeps its own source components, while Tailwind aliases point at token variables.
297
-
298
- Important pieces:
299
-
300
- - `src/lib/theme.ts` defines skin ids, font ids, token maps, validators, and `applyProjectTheme`.
301
- - `tailwind.config.js` maps `background`, `foreground`, `card`, `primary`, `secondary`, `muted`, `accent`, `destructive`, plus legacy aliases like `bg`, `fg`, and `border`.
302
- - `src/styles/globals.css` provides default CSS variables and shared component classes.
303
- - `src/components/SettingsPage.tsx` exposes mode, skin, and font controls per project.
304
- - `src/components/LiquidEther.tsx` provides an animated WebGL fluid simulation background (GPU-accelerated, available as a background option in appearance settings).
320
+ </details>
305
321
 
306
- Supported theme modes:
307
-
308
- | Value | Behavior |
322
+ | Section | Key options |
309
323
  |---|---|
310
- | `auto` | Follow `prefers-color-scheme`. |
311
- | `light` | Force light tokens. |
312
- | `dark` | Force dark tokens. |
313
-
314
- Built-in skins:
324
+ | `ui` | Language (48 locales), theme mode, skin, font |
325
+ | `board` | Task ID prefix, default priority/owner |
326
+ | `fields` | Toggle visibility of priority, assignee, tags, due date, owner type |
327
+ | `notifications` | Browser alerts, sound cues, debounce timing |
315
328
 
316
- | Skin | Intent |
317
- |---|---|
318
- | `kandown` | Crisp neutral default, close to the original UI. |
319
- | `graphite` | Soft gray surfaces. |
320
- | `sage` | Calm green-gray planning palette. |
321
- | `cobalt` | Cool blue accent, restrained surfaces. |
322
- | `rose` | Warm ink with a restrained rose accent. |
329
+ Disabled fields are hidden from cards, list view, the task drawer, and metadata filters.
323
330
 
324
- Built-in fonts:
325
-
326
- | Font | Stack |
327
- |---|---|
328
- | `inter` | Inter-first sans stack. |
329
- | `system` | Native platform sans stack. |
330
- | `serif` | Editorial serif stack. |
331
- | `mono` | Monospace stack. |
332
- | `rounded` | Rounded system stack. |
333
-
334
- ## Web Modules
331
+ ---
335
332
 
336
- ### App Shell
333
+ ## 🌐 Browser Support
337
334
 
338
- | File | Role |
335
+ | Browser | Supported |
339
336
  |---|---|
340
- | `src/main.tsx` | Mounts React and global CSS. |
341
- | `src/App.tsx` | Composes the web UI and owns global keyboard shortcuts. |
337
+ | Chrome | |
338
+ | Edge | |
339
+ | Brave | ✅ |
340
+ | Opera | ✅ |
341
+ | Firefox | ❌ (no File System Access API) |
342
+ | Safari | ❌ (no File System Access API) |
342
343
 
343
- ### Components
344
+ > **Server mode** (run `kandown` from the CLI, no browser install needed) works in all browsers — it proxies file operations through a local REST API, bypassing the File System Access API requirement.
344
345
 
345
- | File | Main exports | Description |
346
- |---|---|---|
347
- | `Board.tsx` | `Board` | Horizontal kanban view, filtering, drag state, search-match forwarding. |
348
- | `Column.tsx` | `Column` | One kanban column, Tabler status icon, drop target, create-task button, empty state. |
349
- | `Card.tsx` | `Card` | Task card with progress, metadata, guarded hover deletion, drag handlers, and search previews. |
350
- | `ListView.tsx` | `ListView` | Dense table-like view sharing the same filters/search cache as board view. |
351
- | `Drawer.tsx` | `Drawer` | Task detail editor for title, enabled frontmatter metadata, subtasks, and body content. |
352
- | `MarkdownEditor.tsx` | `MarkdownEditor` | WYSIWYG markdown body editor (Wysimark) for task body content. |
353
- | `SubtaskItem.tsx` | `SubtaskItem` | Editable markdown checklist row. |
354
- | `FilterBar.tsx` | `FilterBar` | Search input, owner filter, active chips, clear action. |
355
- | `CommandPalette.tsx` | `CommandPalette` | Quick actions, task lookup, content search, keyboard navigation. |
356
- | `SettingsPage.tsx` | `SettingsPage` | Dense project settings with sidebar search, compact controls, and contextual hover help. |
357
- | `Header.tsx` | `Header` | Project switcher, view controls, settings link, reload, new task. |
358
- | `EmptyState.tsx` | `EmptyState` | First-run folder picker and recent projects. |
359
- | `Toaster.tsx` | `Toaster` | Animated notification stack. |
360
- | `Icons.tsx` | `Icon` | Local SVG icon set for app chrome; board column status glyphs use `@tabler/icons-react`. |
361
- | `ConflictModal.tsx` | `ConflictModal` | Warns when a task file was modified externally; offers Reload / Overwrite / Cancel. |
362
- | `LiquidEther.tsx` | `LiquidEther` | WebGL fluid simulation background (animated, GPU-accelerated). |
363
-
364
- ### Store And Domain Logic
365
-
366
- | File | Main exports | Description |
367
- |---|---|---|
368
- | `src/lib/types.ts` | `DEFAULT_CONFIG`, domain types | Shared TypeScript contracts for board, tasks, config, filters, search, and appearance. |
369
- | `src/lib/store.ts` | `useStore` | Zustand state machine for project loading, board mutations, drawer editing, search cache, config, and toasts. |
370
- | `src/lib/filesystem.ts` | File and IndexedDB helpers | Browser File System Access API and recent-project persistence. |
371
- | `src/lib/parser.ts` | Markdown parsers/search | Parses board/task markdown, extracts/reinjects subtasks, and searches cached task content. |
372
- | `src/lib/serializer.ts` | Markdown writers | Serializes board and task data back to markdown. |
373
- | `src/lib/theme.ts` | Theme engine | Applies project-level light/dark tokens, skins, and font stacks. |
374
- | `src/lib/i18n/index.ts` | i18n setup | 48-locale translation system with per-project language preference. |
375
- | `src/lib/watcher.ts` | File watcher | 500ms polling watcher with SHA-256 content hashing to detect external file changes and drive reloads/notifications. |
376
- | `src/hooks/useAnimatedNumber.ts` | `useAnimatedNumber` | Spring-animated numeric display for task counts. |
346
+ ---
377
347
 
378
- ## Important Functions
348
+ ## 🎨 Appearance
379
349
 
380
- ### `src/lib/store.ts`
350
+ ### Skins
381
351
 
382
- | Function/action | Description |
383
- |---|---|
384
- | `openFolder` | Prompts for a project folder, resolves `.kandown`, saves recent project, loads config and board. |
385
- | `openRecentProject` | Reopens an IndexedDB-stored project handle after permission verification. |
386
- | `loadConfig` | Reads `kandown.json`, merges defaults, applies theme tokens. |
387
- | `updateConfig` | Optimistically updates config, applies appearance immediately, writes `kandown.json`. |
388
- | `reloadBoard` | Scans task files, derives columns from task statuses, and eagerly loads task content for small boards. |
389
- | `moveTask` | Optimistically moves a task between columns and writes task frontmatter `status` / `order`, rolling back on failure. |
390
- | `reorderInColumn` | Reorders tasks within one column by writing task frontmatter `order`. |
391
- | `addColumn` / `renameColumn` / `deleteColumn` | Manage `board.columns` in config and update affected task files. |
392
- | `createTask` | Creates a task markdown file with initial frontmatter. |
393
- | `deleteTask` | Deletes the task file and clears cached content/search matches. |
394
- | `openDrawer` | Reads one task detail file and prepares editable drawer state. |
395
- | `saveDrawer` | Writes full task detail content and closes the drawer. |
396
- | `saveDrawerMetadata` | Autosaves task detail content and reloads derived board metadata/progress. |
397
- | `setFilter` | Updates filters and lazily loads task contents for search queries. |
398
- | `loadTaskContents` | Reads task files into the content-search cache. |
399
- | `computeSearchMatches` | Produces per-task search matches for board/list previews. |
400
- | `toast` | Adds transient UI messages. |
401
-
402
- ### `src/lib/notifications.ts`
403
-
404
- | Function | Description |
352
+ | Skin | Description |
405
353
  |---|---|
406
- | `getBrowserNotificationPermission` | Reads browser notification permission and reports unsupported browsers. |
407
- | `requestBrowserNotificationPermission` | Prompts Chrome-compatible browsers from the Settings page. |
408
- | `emitKandownNotification` | Dispatches enabled browser notifications and in-page sound cues. |
409
- | `playNotificationSound` | Plays generated Web Audio cues without external assets. |
354
+ | `kandown` | Crisp neutral default |
355
+ | `graphite` | Soft gray surfaces |
356
+ | `sage` | Calm green-gray planning palette |
357
+ | `cobalt` | Cool blue accent, restrained surfaces |
358
+ | `rose` | Warm ink with rose accent |
410
359
 
411
- ### `src/lib/parser.ts`
360
+ ### Theme Modes
412
361
 
413
- | Function | Description |
362
+ | Mode | Behavior |
414
363
  |---|---|
415
- | `parseSimpleYaml` | Parses Kandown's limited frontmatter format. |
416
- | `parseTaskFile` | Splits a task markdown file into frontmatter and body. |
417
- | `taskToBoardTask` | Converts parsed task frontmatter/body into compact card metadata. |
418
- | `buildColumnsFromTasks` | Groups parsed task files into configured and temporary columns. |
419
- | `extractSubtasks` | Pulls markdown checklist lines out of a subtask section. |
420
- | `injectSubtasks` | Writes edited subtasks back into a task body. |
421
- | `searchTaskContent` | Searches title, subtasks, body, tags, assignee, and priority with contextual snippets. |
364
+ | `auto` | Follows system `prefers-color-scheme` |
365
+ | `light` | Force light theme |
366
+ | `dark` | Force dark theme |
422
367
 
423
- ### `src/lib/filesystem.ts`
368
+ ### Fonts
424
369
 
425
- | Function | Description |
426
- |---|---|
427
- | `supportsFileSystemAccess` | Detects required browser API support. |
428
- | `pickProjectDirectory` | Prompts for a project folder and opens or creates `.kandown`. |
429
- | `getKandownHandle` | Resolves `.kandown` from a remembered project directory handle. |
430
- | `ensureTasksDir` | Ensures `.kandown/tasks` exists. |
431
- | `readConfigFile` / `writeConfigFile` | Load and save `kandown.json`. |
432
- | `listTaskIds` | Scans `.kandown/tasks/*.md` and returns task IDs. |
433
- | `readTaskFile` / `writeTaskFile` / `deleteTaskFile` | Manage per-task markdown files. |
434
- | `saveRecentProject` / `listRecentProjects` / `removeRecentProject` | Manage recent project handles in IndexedDB. |
435
- | `verifyPermission` | Requests read/write permission for a stored handle. |
436
-
437
- ### `src/lib/theme.ts`
438
-
439
- | Function | Description |
370
+ | Font | Stack |
440
371
  |---|---|
441
- | `normalizeThemeMode` | Validates persisted theme mode. |
442
- | `normalizeSkinId` | Validates persisted skin id. |
443
- | `normalizeFontId` | Validates persisted font id. |
444
- | `applyProjectTheme` | Applies resolved light/dark class, dataset metadata, font stack, and CSS variables. |
372
+ | `inter` | Inter-first sans stack |
373
+ | `system` | Native platform sans stack |
374
+ | `serif` | Editorial serif stack |
375
+ | `mono` | Monospace stack |
376
+ | `rounded` | Rounded system stack |
445
377
 
446
- ## CLI Architecture
378
+ ---
447
379
 
448
- The npm CLI lives in `bin/kandown.js`.
380
+ ## 🛠️ Development
449
381
 
450
- | Function | Description |
451
- |---|---|
452
- | `help` | Prints usage and commands. |
453
- | `openInBrowser` | Opens `kandown.html` non-blocking in the system default browser. |
454
- | `findKandownDir` | Locates `.kandown/` walking up from cwd. |
455
- | `copyRecursive` | Copies template directories into `.kandown`. |
456
- | `findAgentsFile` | Detects existing AI-agent instruction files. |
457
- | `appendAgentReference` | Adds a Kandown task-management section to an existing agent file. |
458
- | `createAgentsFileIfMissing` | Creates `AGENTS.md` when no agent instructions exist. |
459
- | `parseArgs` | Parses shared CLI flags such as `--path`, `--force`, and `--port`. |
460
- | `cmdInit` | Installs `.kandown`, templates, config, web app, and agent docs. |
461
- | `cmdUpdate` | Updates `kandown.html` from `dist/index.html`. |
462
- | `createServeServer` | Creates the local HTTP server for the web UI, including placeholder `/api/*` routing. |
463
- | `cmdServe` | Serves `kandown.html` over localhost, injects `window.__KANDOWN_ROOT__`, opens the browser, and launches the board TUI. |
464
- | `cmdTui` | Launches a named TUI screen (`board`, `settings`). |
465
-
466
- The terminal UI source lives under `src/cli/` and is bundled into `bin/tui.js` by `tsup`.
467
-
468
- | File | Description |
469
- |---|---|
470
- | `src/cli/tui.tsx` | Ink entrypoint — alternate screen buffer, renders the `App` shell. |
471
- | `src/cli/app.tsx` | TUI screen router (`board`, `settings`). |
472
- | `src/cli/lib/config.ts` | Node-side `kandown.json` reader/writer with dot-path accessors. |
473
- | `src/cli/lib/board-reader.ts` | Node fs wrapper around task scanning: `readBoard`, `readTask`, `readAgentDoc`, `moveTaskToColumn`. |
474
- | `src/cli/lib/agents.ts` | Agent registry (claude, codex, gemini, goose, aider, opencode), detection via `which`, `buildPrompt`. |
475
- | `src/cli/lib/launcher.ts` | Process spawning: tmux split-pane or direct exec, auto-moves task to In Progress. |
476
- | `src/cli/screens/board.tsx` | Interactive kanban board TUI — column navigation, task detail, agent picker integration. |
477
- | `src/cli/screens/agent-picker.tsx` | Agent selection overlay component. |
478
- | `src/cli/screens/settings.tsx` | Terminal settings editor for `kandown.json`. |
479
-
480
- ## Development
382
+ ### Setup
481
383
 
482
384
  ```bash
385
+ git clone https://github.com/vava-nessa/kandown.git
386
+ cd kandown
483
387
  pnpm install
484
- pnpm dev # web UI (Vite dev server)
485
- pnpm build # full build: web + CLI
388
+ pnpm dev # Web UI at localhost:5173
486
389
  ```
487
390
 
488
391
  ### Scripts
489
392
 
490
393
  | Script | Description |
491
394
  |---|---|
492
- | `pnpm dev` | Start the Vite dev server for the web UI at `localhost:5173`. |
493
- | `pnpm dev:cli` | Watch-mode build for the CLI TUI — rebuilds `bin/tui.js` on every file change. |
494
- | `pnpm build` | Full build: typecheck → Vite web app → CLI TUI bundle. |
495
- | `pnpm build:cli` | Build `src/cli/tui.tsx` into `bin/tui.js` (one-shot). |
496
- | `pnpm preview` | Preview the Vite production build. |
497
- | `pnpm typecheck` | Run TypeScript compiler without emitting files. |
395
+ | `pnpm dev` | Vite dev server for the web UI |
396
+ | `pnpm dev:cli` | Watch-mode build for the CLI TUI |
397
+ | `pnpm build` | Full build: typecheck → web app → CLI TUI |
398
+ | `pnpm build:cli` | One-shot CLI TUI build |
399
+ | `pnpm preview` | Preview the Vite production build |
400
+ | `pnpm typecheck` | TypeScript check without emitting |
498
401
 
499
- ### Developing the Web UI
402
+ ### Dev Workflow (CLI / TUI)
500
403
 
501
404
  ```bash
502
- pnpm dev
503
- # → open http://localhost:5173
504
- # → select any folder that has a .kandown/ directory when prompted
505
- ```
506
-
507
- Hot-reload is fully supported. Changes to `src/` reflect immediately in the browser.
508
-
509
- ### Developing the CLI / Board TUI
510
-
511
- The CLI TUI is built with [Ink](https://github.com/vadimdemedes/ink) (React for terminals) and bundled by `tsup`.
512
-
513
- **Recommended dev workflow** — two terminals:
514
-
515
- ```bash
516
- # Terminal 1: watch-rebuild on every save
405
+ # Terminal 1 — watch and rebuild on save
517
406
  pnpm dev:cli
518
407
 
519
- # Terminal 2: run the board TUI after each rebuild
408
+ # Terminal 2 test the board TUI
520
409
  node bin/kandown.js board
521
410
 
522
- # Or run the bare command (local web server + browser + board):
523
- node bin/kandown.js
524
-
525
- # Use a fixed local web UI port:
411
+ # Or full experience (web server + browser + TUI):
526
412
  node bin/kandown.js --port 3000
527
413
  ```
528
414
 
529
- `pnpm dev:cli` watches all files under `src/cli/` and `src/lib/` (shared parsers). After saving a file, re-run `node bin/kandown.js board` in the second terminal to see the updated TUI.
530
-
531
- **Testing a specific screen:**
532
-
533
- ```bash
534
- # Board TUI (new)
535
- node bin/kandown.js board
536
-
537
- # Settings TUI
538
- node bin/kandown.js settings
415
+ ### Build Output
539
416
 
540
- # Init in a temp project to test installation
541
- mkdir /tmp/test-kandown && cd /tmp/test-kandown
542
- node /path/to/kandown/bin/kandown.js init
543
- node /path/to/kandown/bin/kandown.js
544
- ```
417
+ | File | Purpose |
418
+ |---|---|
419
+ | `dist/index.html` | Single-file web app → copied as `kandown.html` |
420
+ | `bin/tui.js` | Bundled Ink TUI → used by `kandown board` and `kandown settings` |
545
421
 
546
- **Iterating on the agent picker** — if you don't have any AI agents installed, the picker will show "No agents found". To test the picker UI regardless, temporarily add a dummy agent to the `AGENTS` array in `src/cli/lib/agents.ts` pointing to a binary that exists (e.g. `echo`).
422
+ ---
547
423
 
548
- **Testing tmux integration:**
424
+ ## 🏗️ Architecture
549
425
 
550
- ```bash
551
- # Start a tmux session if you're not in one
552
- tmux new-session -s dev
426
+ <details>
427
+ <summary>Project structure</summary>
553
428
 
554
- # Then run kandown — the agent picker should offer tmux split-pane launch
555
- node bin/kandown.js board
429
+ ```
430
+ kandown/
431
+ ├── bin/
432
+ │ ├── kandown.js # CLI entrypoint (hand-rolled, no deps)
433
+ │ └── tui.js # Generated TUI bundle (tsup)
434
+ ├── src/
435
+ │ ├── App.tsx # Web app shell + global shortcuts
436
+ │ ├── main.tsx # React/Vite browser entrypoint
437
+ │ ├── cli/ # Ink terminal UI source
438
+ │ │ ├── tui.tsx # Ink entrypoint (alternate screen buffer)
439
+ │ │ ├── app.tsx # TUI screen router
440
+ │ │ ├── lib/ # Node-side helpers (config, board, agents, launcher)
441
+ │ │ └── screens/ # board.tsx, agent-picker.tsx, settings.tsx
442
+ │ ├── components/ # React UI components (web)
443
+ │ ├── hooks/ # React hooks
444
+ │ ├── lib/ # Domain model, parser, serializer, store, theme, i18n
445
+ │ └── styles/ # Tailwind layers + CSS tokens
446
+ ├── templates/ # Files copied by `kandown init`
447
+ ├── dist/index.html # Generated single-file web app
448
+ ├── vite.config.ts
449
+ ├── tsup.config.ts
450
+ └── package.json
556
451
  ```
557
452
 
558
- ### Build Output
559
-
560
- `pnpm build` regenerates:
561
-
562
- - `dist/index.html` — single-file web app, copied into target projects as `kandown.html`.
563
- - `bin/tui.js` — bundled Ink TUI, used by `kandown board` and `kandown settings`.
453
+ </details>
564
454
 
565
- Always build before publishing. The published package is intentionally small and includes only `dist/`, `bin/`, `templates/`, `README.md`, and `LICENSE`.
455
+ <details>
456
+ <summary>Runtime flow</summary>
566
457
 
567
- ## Browser Support
458
+ 1. `main.tsx` mounts the React app
459
+ 2. `App` renders header + board / list / settings / empty state
460
+ 3. User selects a folder → File System Access API (or server mode)
461
+ 4. `filesystem.ts` resolves `.kandown/`, `tasks/`, `kandown.json`
462
+ 5. `store.ts` loads config, applies theme, scans tasks, saves recent project handles
463
+ 6. `parser.ts` converts task markdown into typed data
464
+ 7. Mutations flow back through store → `serializer.ts` → `filesystem.ts`
568
465
 
569
- Kandown requires the File System Access API. Supported browsers:
466
+ </details>
570
467
 
571
- - Chrome
572
- - Edge
573
- - Brave
574
- - Opera
468
+ <details>
469
+ <summary>Key modules</summary>
575
470
 
576
- Unsupported:
471
+ | Module | Role |
472
+ |---|---|
473
+ | `src/lib/store.ts` | Zustand state machine — project loading, board mutations, drawer, search, config |
474
+ | `src/lib/filesystem.ts` | File System Access API + IndexedDB helpers |
475
+ | `src/lib/parser.ts` | Markdown parsing, subtask extraction, content search |
476
+ | `src/lib/serializer.ts` | Markdown serialization |
477
+ | `src/lib/theme.ts` | Theme engine — skins, fonts, CSS variables |
478
+ | `src/lib/watcher.ts` | 500ms polling watcher with SHA-256 hashing for external change detection |
479
+ | `src/lib/i18n/index.ts` | 48-locale translation system |
577
480
 
578
- - Firefox
579
- - Safari
481
+ </details>
580
482
 
581
- ## Design Constraints
483
+ ---
582
484
 
583
- - The app must remain local-first and backend-free.
584
- - Markdown stays the canonical data format.
585
- - Task files are the canonical source of truth.
586
- - Board columns belong in `kandown.json`.
587
- - UI state that is project-specific belongs in `kandown.json`.
588
- - Browser-only convenience state, such as recent handles, can live in IndexedDB.
589
- - The installed web app should remain a single file.
485
+ ## 📐 Design Constraints
590
486
 
591
- ## Publishing
487
+ - **Local-first, backend-free** — no servers, no sync vendors
488
+ - **Markdown is the canonical data format** — always human-readable
489
+ - **Task files are the single source of truth** — no index files to sync
490
+ - **Single-file web app** — `kandown.html` bundles everything
491
+ - **Project config in `kandown.json`** — columns, appearance, fields, notifications
492
+ - **Browser state in IndexedDB** — only for convenience (recent project handles)
592
493
 
593
- ```bash
594
- pnpm build
595
- npm login
596
- npm publish --access public
597
- ```
494
+ ---
598
495
 
599
- ## License
496
+ ## 📜 License
600
497
 
601
- MIT
498
+ [MIT](LICENSE) — use it, fork it, ship it.