kandown 0.1.0
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/LICENSE +21 -0
- package/README.md +595 -0
- package/bin/kandown.js +539 -0
- package/bin/tui.js +1257 -0
- package/dist/apple-touch-icon.png +0 -0
- package/dist/favicon.svg +7 -0
- package/dist/index.html +6456 -0
- package/dist/manifest.json +17 -0
- package/package.json +73 -0
- package/templates/AGENT.md +102 -0
- package/templates/AGENT_KANDOWN.md +146 -0
- package/templates/AGENT_KANDOWN_COMPACT.md +65 -0
- package/templates/README.md +48 -0
- package/templates/kandown.json +34 -0
- package/templates/tasks/t1.md +30 -0
- package/templates/tasks/t2.md +32 -0
- package/templates/tasks/t3.md +13 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vanechacha
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,595 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="logo.svg" width="128" height="128" alt="Kandown logo">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# Kandown
|
|
6
|
+
|
|
7
|
+
> **⚠️ This project is not finished yet. V1 coming soon.**
|
|
8
|
+
|
|
9
|
+
A file-based Kanban engine backed by plain markdown. Zero backend, zero database, no account, AI-agent friendly.
|
|
10
|
+
|
|
11
|
+
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.
|
|
12
|
+
|
|
13
|
+
## Why
|
|
14
|
+
|
|
15
|
+
Most kanban tools trap your data in their cloud. Kandown does the opposite: all state lives in `.kandown/` as markdown and JSON.
|
|
16
|
+
|
|
17
|
+
The core architecture keeps task state in the task files themselves:
|
|
18
|
+
|
|
19
|
+
- `tasks/<id>.md` stores the full task context and board state: title, status, order, metadata, subtasks, notes, and completion reports.
|
|
20
|
+
- `kandown.json` stores project preferences such as board columns, theme mode, skin, font, agent behavior, notifications, and enabled fields.
|
|
21
|
+
|
|
22
|
+
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.
|
|
23
|
+
|
|
24
|
+
## Install & Use
|
|
25
|
+
|
|
26
|
+
If Kandown is published on npm:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
cd my-project
|
|
30
|
+
npx kandown init
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
This creates:
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
.kandown/
|
|
37
|
+
├── kandown.html # single-file web app, built from dist/index.html
|
|
38
|
+
├── kandown.json # project preferences, columns, notifications, and appearance
|
|
39
|
+
├── tasks/ # per-task markdown files and board state
|
|
40
|
+
├── AGENT.md # short AI-agent rules
|
|
41
|
+
└── README.md # user-facing project-local guide
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
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.
|
|
45
|
+
|
|
46
|
+
To use the board:
|
|
47
|
+
|
|
48
|
+
1. Open `.kandown/kandown.html` in Chrome, Edge, Brave, or Opera.
|
|
49
|
+
2. Select the project folder when prompted.
|
|
50
|
+
3. Grant read/write permission.
|
|
51
|
+
|
|
52
|
+
Firefox and Safari do not currently support the required File System Access API.
|
|
53
|
+
|
|
54
|
+
## Features
|
|
55
|
+
|
|
56
|
+
- **File-over-app**: Markdown and JSON are the source of truth.
|
|
57
|
+
- **Zero backend**: No server, database, login, or sync vendor.
|
|
58
|
+
- **AI-agent optimized**: Task files are the single source of truth.
|
|
59
|
+
- **Board and list views**: Toggle with `⌘1` / `⌘2`.
|
|
60
|
+
- **Column status icons**: Board columns use Tabler icons beside titles so states like Backlog, In Progress, Review, and Done are easier to scan.
|
|
61
|
+
- **Column color accents**: Columns can use expanded translucent background colors, including black variants.
|
|
62
|
+
- **Custom columns**: Add, rename, and delete columns from the board; unknown task statuses appear as temporary columns until added to settings.
|
|
63
|
+
- **Drag and drop**: Move cards between columns with optimistic file writes.
|
|
64
|
+
- **Guarded card deletion**: Hover a card and click the trash icon twice to delete a task without opening the drawer.
|
|
65
|
+
- **Task drawer**: Edit title, enabled metadata fields, subtasks, and body content.
|
|
66
|
+
- **Content search**: Search titles, ids, task body, subtasks, tags, assignee, and priority with highlighted previews.
|
|
67
|
+
- **Command palette**: `⌘K` / `Ctrl+K` for task search and quick actions.
|
|
68
|
+
- **Owner type filtering**: Separate human tasks from AI-agent tasks.
|
|
69
|
+
- **Dense settings**: Sidebar search, compact setting controls, and hover help explain project options.
|
|
70
|
+
- **Configurable notifications**: Chrome permission, status-change alerts, debounced task-edit alerts, subtask-completion alerts, and in-page sound cues.
|
|
71
|
+
- **Appearance system**: Project-level `auto` / `light` / `dark`, backgrounds, built-in skins, and local font presets.
|
|
72
|
+
- **Recent projects**: Stored in IndexedDB so local handles can be reopened quickly.
|
|
73
|
+
- **Single-file publish artifact**: Vite bundles the web UI into `dist/index.html`.
|
|
74
|
+
|
|
75
|
+
## Keyboard Shortcuts
|
|
76
|
+
|
|
77
|
+
| Key | Action |
|
|
78
|
+
|---|---|
|
|
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 |
|
|
88
|
+
|
|
89
|
+
## CLI
|
|
90
|
+
|
|
91
|
+
```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
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Commands
|
|
111
|
+
|
|
112
|
+
| Command | Purpose |
|
|
113
|
+
|---|---|
|
|
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. |
|
|
120
|
+
|
|
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.
|
|
122
|
+
|
|
123
|
+
### Board TUI
|
|
124
|
+
|
|
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.
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
KANDOWN tmux My Project
|
|
129
|
+
────────────────────────────────────────────────────────────────
|
|
130
|
+
Backlog (3) │ Todo (2) │ In Progress │ Review (1) │ Done
|
|
131
|
+
──────────────│──────────────│──────────────│────────────│──────
|
|
132
|
+
▸ t9 │ t16 │ (empty) │ t18 │ ...
|
|
133
|
+
t10 │ t7 │ │
|
|
134
|
+
t11 │ │
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**Navigation:**
|
|
138
|
+
|
|
139
|
+
| Key | Action |
|
|
140
|
+
|---|---|
|
|
141
|
+
| `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_COMPACT.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 |
|
|
158
|
+
|---|---|---|
|
|
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` |
|
|
165
|
+
|
|
166
|
+
## Project Architecture
|
|
167
|
+
|
|
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_COMPACT.md # condensed version for CLI prompt injection
|
|
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
|
+
```
|
|
202
|
+
|
|
203
|
+
## Runtime Flow
|
|
204
|
+
|
|
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`.
|
|
213
|
+
|
|
214
|
+
## Data Model
|
|
215
|
+
|
|
216
|
+
### `tasks/<id>.md`
|
|
217
|
+
|
|
218
|
+
Task files store rich context and board state.
|
|
219
|
+
|
|
220
|
+
```markdown
|
|
221
|
+
---
|
|
222
|
+
id: t1
|
|
223
|
+
title: Full task title
|
|
224
|
+
status: Todo
|
|
225
|
+
order: 0
|
|
226
|
+
priority: P1
|
|
227
|
+
tags: [backend, security]
|
|
228
|
+
assignee: chacha
|
|
229
|
+
created: 2026-04-10
|
|
230
|
+
ownerType: human
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
# Task title
|
|
234
|
+
|
|
235
|
+
## Context
|
|
236
|
+
|
|
237
|
+
Why this task exists.
|
|
238
|
+
|
|
239
|
+
## Subtasks
|
|
240
|
+
|
|
241
|
+
- [ ] First step
|
|
242
|
+
- [x] Second step
|
|
243
|
+
|
|
244
|
+
## Notes
|
|
245
|
+
|
|
246
|
+
Extra details.
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### `kandown.json`
|
|
250
|
+
|
|
251
|
+
Project-level preferences:
|
|
252
|
+
|
|
253
|
+
```json
|
|
254
|
+
{
|
|
255
|
+
"ui": {
|
|
256
|
+
"language": "en",
|
|
257
|
+
"theme": "auto",
|
|
258
|
+
"skin": "kandown",
|
|
259
|
+
"font": "inter"
|
|
260
|
+
},
|
|
261
|
+
"agent": {
|
|
262
|
+
"suggestFollowUp": false,
|
|
263
|
+
"maxSuggestions": 3
|
|
264
|
+
},
|
|
265
|
+
"board": {
|
|
266
|
+
"taskPrefix": "t",
|
|
267
|
+
"defaultPriority": "P3",
|
|
268
|
+
"defaultOwnerType": "human"
|
|
269
|
+
},
|
|
270
|
+
"fields": {
|
|
271
|
+
"priority": false,
|
|
272
|
+
"assignee": false,
|
|
273
|
+
"tags": false,
|
|
274
|
+
"dueDate": false,
|
|
275
|
+
"ownerType": false,
|
|
276
|
+
"tools": false
|
|
277
|
+
},
|
|
278
|
+
"notifications": {
|
|
279
|
+
"browser": false,
|
|
280
|
+
"sound": false,
|
|
281
|
+
"soundId": "soft",
|
|
282
|
+
"statusChanges": true,
|
|
283
|
+
"taskEdits": true,
|
|
284
|
+
"subtaskCompletions": true,
|
|
285
|
+
"editDebounceMs": 2000
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
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 the same file watcher that reloads the board. 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
|
+
|
|
305
|
+
Supported theme modes:
|
|
306
|
+
|
|
307
|
+
| Value | Behavior |
|
|
308
|
+
|---|---|
|
|
309
|
+
| `auto` | Follow `prefers-color-scheme`. |
|
|
310
|
+
| `light` | Force light tokens. |
|
|
311
|
+
| `dark` | Force dark tokens. |
|
|
312
|
+
|
|
313
|
+
Built-in skins:
|
|
314
|
+
|
|
315
|
+
| Skin | Intent |
|
|
316
|
+
|---|---|
|
|
317
|
+
| `kandown` | Crisp neutral default, close to the original UI. |
|
|
318
|
+
| `graphite` | Soft gray surfaces. |
|
|
319
|
+
| `sage` | Calm green-gray planning palette. |
|
|
320
|
+
| `cobalt` | Cool blue accent, restrained surfaces. |
|
|
321
|
+
| `rose` | Warm ink with a restrained rose accent. |
|
|
322
|
+
|
|
323
|
+
Built-in fonts:
|
|
324
|
+
|
|
325
|
+
| Font | Stack |
|
|
326
|
+
|---|---|
|
|
327
|
+
| `inter` | Inter-first sans stack. |
|
|
328
|
+
| `system` | Native platform sans stack. |
|
|
329
|
+
| `serif` | Editorial serif stack. |
|
|
330
|
+
| `mono` | Monospace stack. |
|
|
331
|
+
| `rounded` | Rounded system stack. |
|
|
332
|
+
|
|
333
|
+
## Web Modules
|
|
334
|
+
|
|
335
|
+
### App Shell
|
|
336
|
+
|
|
337
|
+
| File | Role |
|
|
338
|
+
|---|---|
|
|
339
|
+
| `src/main.tsx` | Mounts React and global CSS. |
|
|
340
|
+
| `src/App.tsx` | Composes the web UI and owns global keyboard shortcuts. |
|
|
341
|
+
|
|
342
|
+
### Components
|
|
343
|
+
|
|
344
|
+
| File | Main exports | Description |
|
|
345
|
+
|---|---|---|
|
|
346
|
+
| `Board.tsx` | `Board` | Horizontal kanban view, filtering, drag state, search-match forwarding. |
|
|
347
|
+
| `Column.tsx` | `Column` | One kanban column, Tabler status icon, drop target, create-task button, empty state. |
|
|
348
|
+
| `Card.tsx` | `Card` | Task card with progress, metadata, guarded hover deletion, drag handlers, and search previews. |
|
|
349
|
+
| `ListView.tsx` | `ListView` | Dense table-like view sharing the same filters/search cache as board view. |
|
|
350
|
+
| `Drawer.tsx` | `Drawer` | Task detail editor for title, enabled frontmatter metadata, subtasks, and body content. |
|
|
351
|
+
| `SubtaskItem.tsx` | `SubtaskItem` | Editable markdown checklist row. |
|
|
352
|
+
| `FilterBar.tsx` | `FilterBar` | Search input, owner filter, active chips, clear action. |
|
|
353
|
+
| `CommandPalette.tsx` | `CommandPalette` | Quick actions, task lookup, content search, keyboard navigation. |
|
|
354
|
+
| `SettingsPage.tsx` | `SettingsPage` | Dense project settings with sidebar search, compact controls, and contextual hover help. |
|
|
355
|
+
| `Header.tsx` | `Header` | Project switcher, view controls, settings link, reload, new task. |
|
|
356
|
+
| `EmptyState.tsx` | `EmptyState` | First-run folder picker and recent projects. |
|
|
357
|
+
| `Toaster.tsx` | `Toaster` | Animated notification stack. |
|
|
358
|
+
| `Icons.tsx` | `Icon` | Local SVG icon set for app chrome; board column status glyphs use `@tabler/icons-react`. |
|
|
359
|
+
|
|
360
|
+
### Store And Domain Logic
|
|
361
|
+
|
|
362
|
+
| File | Main exports | Description |
|
|
363
|
+
|---|---|---|
|
|
364
|
+
| `src/lib/types.ts` | `DEFAULT_CONFIG`, domain types | Shared TypeScript contracts for board, tasks, config, filters, search, and appearance. |
|
|
365
|
+
| `src/lib/store.ts` | `useStore` | Zustand state machine for project loading, board mutations, drawer editing, search cache, config, and toasts. |
|
|
366
|
+
| `src/lib/filesystem.ts` | File and IndexedDB helpers | Browser File System Access API and recent-project persistence. |
|
|
367
|
+
| `src/lib/parser.ts` | Markdown parsers/search | Parses board/task markdown, extracts/reinjects subtasks, and searches cached task content. |
|
|
368
|
+
| `src/lib/serializer.ts` | Markdown writers | Serializes board and task data back to markdown. |
|
|
369
|
+
| `src/lib/theme.ts` | Theme engine | Applies project-level light/dark tokens, skins, and font stacks. |
|
|
370
|
+
| `src/hooks/useAnimatedNumber.ts` | `useAnimatedNumber` | Spring-animated numeric display for task counts. |
|
|
371
|
+
|
|
372
|
+
## Important Functions
|
|
373
|
+
|
|
374
|
+
### `src/lib/store.ts`
|
|
375
|
+
|
|
376
|
+
| Function/action | Description |
|
|
377
|
+
|---|---|
|
|
378
|
+
| `openFolder` | Prompts for a project folder, resolves `.kandown`, saves recent project, loads config and board. |
|
|
379
|
+
| `openRecentProject` | Reopens an IndexedDB-stored project handle after permission verification. |
|
|
380
|
+
| `loadConfig` | Reads `kandown.json`, merges defaults, applies theme tokens. |
|
|
381
|
+
| `updateConfig` | Optimistically updates config, applies appearance immediately, writes `kandown.json`. |
|
|
382
|
+
| `reloadBoard` | Scans task files, derives columns from task statuses, and eagerly loads task content for small boards. |
|
|
383
|
+
| `moveTask` | Optimistically moves a task between columns and writes task frontmatter `status` / `order`, rolling back on failure. |
|
|
384
|
+
| `reorderInColumn` | Reorders tasks within one column by writing task frontmatter `order`. |
|
|
385
|
+
| `addColumn` / `renameColumn` / `deleteColumn` | Manage `board.columns` in config and update affected task files. |
|
|
386
|
+
| `createTask` | Creates a task markdown file with initial frontmatter. |
|
|
387
|
+
| `deleteTask` | Deletes the task file and clears cached content/search matches. |
|
|
388
|
+
| `openDrawer` | Reads one task detail file and prepares editable drawer state. |
|
|
389
|
+
| `saveDrawer` | Writes full task detail content and closes the drawer. |
|
|
390
|
+
| `saveDrawerMetadata` | Autosaves task detail content and reloads derived board metadata/progress. |
|
|
391
|
+
| `setFilter` | Updates filters and lazily loads task contents for search queries. |
|
|
392
|
+
| `loadTaskContents` | Reads task files into the content-search cache. |
|
|
393
|
+
| `computeSearchMatches` | Produces per-task search matches for board/list previews. |
|
|
394
|
+
| `toast` | Adds transient UI messages. |
|
|
395
|
+
|
|
396
|
+
### `src/lib/notifications.ts`
|
|
397
|
+
|
|
398
|
+
| Function | Description |
|
|
399
|
+
|---|---|
|
|
400
|
+
| `getBrowserNotificationPermission` | Reads browser notification permission and reports unsupported browsers. |
|
|
401
|
+
| `requestBrowserNotificationPermission` | Prompts Chrome-compatible browsers from the Settings page. |
|
|
402
|
+
| `emitKandownNotification` | Dispatches enabled browser notifications and in-page sound cues. |
|
|
403
|
+
| `playNotificationSound` | Plays generated Web Audio cues without external assets. |
|
|
404
|
+
|
|
405
|
+
### `src/lib/parser.ts`
|
|
406
|
+
|
|
407
|
+
| Function | Description |
|
|
408
|
+
|---|---|
|
|
409
|
+
| `parseSimpleYaml` | Parses Kandown's limited frontmatter format. |
|
|
410
|
+
| `parseTaskFile` | Splits a task markdown file into frontmatter and body. |
|
|
411
|
+
| `taskToBoardTask` | Converts parsed task frontmatter/body into compact card metadata. |
|
|
412
|
+
| `buildColumnsFromTasks` | Groups parsed task files into configured and temporary columns. |
|
|
413
|
+
| `extractSubtasks` | Pulls markdown checklist lines out of a subtask section. |
|
|
414
|
+
| `injectSubtasks` | Writes edited subtasks back into a task body. |
|
|
415
|
+
| `searchTaskContent` | Searches title, subtasks, body, tags, assignee, and priority with contextual snippets. |
|
|
416
|
+
|
|
417
|
+
### `src/lib/filesystem.ts`
|
|
418
|
+
|
|
419
|
+
| Function | Description |
|
|
420
|
+
|---|---|
|
|
421
|
+
| `supportsFileSystemAccess` | Detects required browser API support. |
|
|
422
|
+
| `pickProjectDirectory` | Prompts for a project folder and opens or creates `.kandown`. |
|
|
423
|
+
| `getKandownHandle` | Resolves `.kandown` from a remembered project directory handle. |
|
|
424
|
+
| `ensureTasksDir` | Ensures `.kandown/tasks` exists. |
|
|
425
|
+
| `readConfigFile` / `writeConfigFile` | Load and save `kandown.json`. |
|
|
426
|
+
| `listTaskIds` | Scans `.kandown/tasks/*.md` and returns task IDs. |
|
|
427
|
+
| `readTaskFile` / `writeTaskFile` / `deleteTaskFile` | Manage per-task markdown files. |
|
|
428
|
+
| `saveRecentProject` / `listRecentProjects` / `removeRecentProject` | Manage recent project handles in IndexedDB. |
|
|
429
|
+
| `verifyPermission` | Requests read/write permission for a stored handle. |
|
|
430
|
+
|
|
431
|
+
### `src/lib/theme.ts`
|
|
432
|
+
|
|
433
|
+
| Function | Description |
|
|
434
|
+
|---|---|
|
|
435
|
+
| `normalizeThemeMode` | Validates persisted theme mode. |
|
|
436
|
+
| `normalizeSkinId` | Validates persisted skin id. |
|
|
437
|
+
| `normalizeFontId` | Validates persisted font id. |
|
|
438
|
+
| `applyProjectTheme` | Applies resolved light/dark class, dataset metadata, font stack, and CSS variables. |
|
|
439
|
+
|
|
440
|
+
## CLI Architecture
|
|
441
|
+
|
|
442
|
+
The npm CLI lives in `bin/kandown.js`.
|
|
443
|
+
|
|
444
|
+
| Function | Description |
|
|
445
|
+
|---|---|
|
|
446
|
+
| `help` | Prints usage and commands. |
|
|
447
|
+
| `openInBrowser` | Opens `kandown.html` non-blocking in the system default browser. |
|
|
448
|
+
| `findKandownDir` | Locates `.kandown/` walking up from cwd. |
|
|
449
|
+
| `copyRecursive` | Copies template directories into `.kandown`. |
|
|
450
|
+
| `findAgentsFile` | Detects existing AI-agent instruction files. |
|
|
451
|
+
| `appendAgentReference` | Adds a Kandown task-management section to an existing agent file. |
|
|
452
|
+
| `createAgentsFileIfMissing` | Creates `AGENTS.md` when no agent instructions exist. |
|
|
453
|
+
| `parseArgs` | Parses shared CLI flags such as `--path`, `--force`, and `--port`. |
|
|
454
|
+
| `cmdInit` | Installs `.kandown`, templates, config, web app, and agent docs. |
|
|
455
|
+
| `cmdUpdate` | Updates `kandown.html` from `dist/index.html`. |
|
|
456
|
+
| `createServeServer` | Creates the local HTTP server for the web UI, including placeholder `/api/*` routing. |
|
|
457
|
+
| `cmdServe` | Serves `kandown.html` over localhost, injects `window.__KANDOWN_ROOT__`, opens the browser, and launches the board TUI. |
|
|
458
|
+
| `cmdTui` | Launches a named TUI screen (`board`, `settings`). |
|
|
459
|
+
|
|
460
|
+
The terminal UI source lives under `src/cli/` and is bundled into `bin/tui.js` by `tsup`.
|
|
461
|
+
|
|
462
|
+
| File | Description |
|
|
463
|
+
|---|---|
|
|
464
|
+
| `src/cli/tui.tsx` | Ink entrypoint — alternate screen buffer, renders the `App` shell. |
|
|
465
|
+
| `src/cli/app.tsx` | TUI screen router (`board`, `settings`). |
|
|
466
|
+
| `src/cli/lib/config.ts` | Node-side `kandown.json` reader/writer with dot-path accessors. |
|
|
467
|
+
| `src/cli/lib/board-reader.ts` | Node fs wrapper around task scanning: `readBoard`, `readTask`, `readAgentDoc`, `moveTaskToColumn`. |
|
|
468
|
+
| `src/cli/lib/agents.ts` | Agent registry (claude, codex, gemini, goose, aider, opencode), detection via `which`, `buildPrompt`. |
|
|
469
|
+
| `src/cli/lib/launcher.ts` | Process spawning: tmux split-pane or direct exec, auto-moves task to In Progress. |
|
|
470
|
+
| `src/cli/screens/board.tsx` | Interactive kanban board TUI — column navigation, task detail, agent picker integration. |
|
|
471
|
+
| `src/cli/screens/agent-picker.tsx` | Agent selection overlay component. |
|
|
472
|
+
| `src/cli/screens/settings.tsx` | Terminal settings editor for `kandown.json`. |
|
|
473
|
+
|
|
474
|
+
## Development
|
|
475
|
+
|
|
476
|
+
```bash
|
|
477
|
+
pnpm install
|
|
478
|
+
pnpm dev # web UI (Vite dev server)
|
|
479
|
+
pnpm build # full build: web + CLI
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
### Scripts
|
|
483
|
+
|
|
484
|
+
| Script | Description |
|
|
485
|
+
|---|---|
|
|
486
|
+
| `pnpm dev` | Start the Vite dev server for the web UI at `localhost:5173`. |
|
|
487
|
+
| `pnpm dev:cli` | Watch-mode build for the CLI TUI — rebuilds `bin/tui.js` on every file change. |
|
|
488
|
+
| `pnpm build` | Full build: typecheck → Vite web app → CLI TUI bundle. |
|
|
489
|
+
| `pnpm build:cli` | Build `src/cli/tui.tsx` into `bin/tui.js` (one-shot). |
|
|
490
|
+
| `pnpm preview` | Preview the Vite production build. |
|
|
491
|
+
| `pnpm typecheck` | Run TypeScript compiler without emitting files. |
|
|
492
|
+
|
|
493
|
+
### Developing the Web UI
|
|
494
|
+
|
|
495
|
+
```bash
|
|
496
|
+
pnpm dev
|
|
497
|
+
# → open http://localhost:5173
|
|
498
|
+
# → select any folder that has a .kandown/ directory when prompted
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
Hot-reload is fully supported. Changes to `src/` reflect immediately in the browser.
|
|
502
|
+
|
|
503
|
+
### Developing the CLI / Board TUI
|
|
504
|
+
|
|
505
|
+
The CLI TUI is built with [Ink](https://github.com/vadimdemedes/ink) (React for terminals) and bundled by `tsup`.
|
|
506
|
+
|
|
507
|
+
**Recommended dev workflow** — two terminals:
|
|
508
|
+
|
|
509
|
+
```bash
|
|
510
|
+
# Terminal 1: watch-rebuild on every save
|
|
511
|
+
pnpm dev:cli
|
|
512
|
+
|
|
513
|
+
# Terminal 2: run the board TUI after each rebuild
|
|
514
|
+
node bin/kandown.js board
|
|
515
|
+
|
|
516
|
+
# Or run the bare command (local web server + browser + board):
|
|
517
|
+
node bin/kandown.js
|
|
518
|
+
|
|
519
|
+
# Use a fixed local web UI port:
|
|
520
|
+
node bin/kandown.js --port 3000
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
`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.
|
|
524
|
+
|
|
525
|
+
**Testing a specific screen:**
|
|
526
|
+
|
|
527
|
+
```bash
|
|
528
|
+
# Board TUI (new)
|
|
529
|
+
node bin/kandown.js board
|
|
530
|
+
|
|
531
|
+
# Settings TUI
|
|
532
|
+
node bin/kandown.js settings
|
|
533
|
+
|
|
534
|
+
# Init in a temp project to test installation
|
|
535
|
+
mkdir /tmp/test-kandown && cd /tmp/test-kandown
|
|
536
|
+
node /path/to/kandown/bin/kandown.js init
|
|
537
|
+
node /path/to/kandown/bin/kandown.js
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
**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`).
|
|
541
|
+
|
|
542
|
+
**Testing tmux integration:**
|
|
543
|
+
|
|
544
|
+
```bash
|
|
545
|
+
# Start a tmux session if you're not in one
|
|
546
|
+
tmux new-session -s dev
|
|
547
|
+
|
|
548
|
+
# Then run kandown — the agent picker should offer tmux split-pane launch
|
|
549
|
+
node bin/kandown.js board
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
### Build Output
|
|
553
|
+
|
|
554
|
+
`pnpm build` regenerates:
|
|
555
|
+
|
|
556
|
+
- `dist/index.html` — single-file web app, copied into target projects as `kandown.html`.
|
|
557
|
+
- `bin/tui.js` — bundled Ink TUI, used by `kandown board` and `kandown settings`.
|
|
558
|
+
|
|
559
|
+
Always build before publishing. The published package is intentionally small and includes only `dist/`, `bin/`, `templates/`, `README.md`, and `LICENSE`.
|
|
560
|
+
|
|
561
|
+
## Browser Support
|
|
562
|
+
|
|
563
|
+
Kandown requires the File System Access API. Supported browsers:
|
|
564
|
+
|
|
565
|
+
- Chrome
|
|
566
|
+
- Edge
|
|
567
|
+
- Brave
|
|
568
|
+
- Opera
|
|
569
|
+
|
|
570
|
+
Unsupported:
|
|
571
|
+
|
|
572
|
+
- Firefox
|
|
573
|
+
- Safari
|
|
574
|
+
|
|
575
|
+
## Design Constraints
|
|
576
|
+
|
|
577
|
+
- The app must remain local-first and backend-free.
|
|
578
|
+
- Markdown stays the canonical data format.
|
|
579
|
+
- Task files are the canonical source of truth.
|
|
580
|
+
- Board columns belong in `kandown.json`.
|
|
581
|
+
- UI state that is project-specific belongs in `kandown.json`.
|
|
582
|
+
- Browser-only convenience state, such as recent handles, can live in IndexedDB.
|
|
583
|
+
- The installed web app should remain a single file.
|
|
584
|
+
|
|
585
|
+
## Publishing
|
|
586
|
+
|
|
587
|
+
```bash
|
|
588
|
+
pnpm build
|
|
589
|
+
npm login
|
|
590
|
+
npm publish --access public
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
## License
|
|
594
|
+
|
|
595
|
+
MIT
|