local-kanban 1.6.3
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/CHANGELOG.md +381 -0
- package/LICENSE +21 -0
- package/README.md +144 -0
- package/README.ru.md +144 -0
- package/bin/kb +306 -0
- package/bin/local-kanban +217 -0
- package/ecosystem.example.cjs +25 -0
- package/package.json +52 -0
- package/public/app.js +18 -0
- package/public/boot-fallback.js +3 -0
- package/public/drawer-sync.js +14 -0
- package/public/favicon-180.png +0 -0
- package/public/favicon-32.png +0 -0
- package/public/favicon-64.png +0 -0
- package/public/favicon.ico +0 -0
- package/public/favicon.svg +6 -0
- package/public/icon-192.png +0 -0
- package/public/icon-512.png +0 -0
- package/public/icon-maskable-192.png +0 -0
- package/public/icon-maskable-512.png +0 -0
- package/public/index.html +138 -0
- package/public/js/board.js +698 -0
- package/public/js/chaos.js +247 -0
- package/public/js/core.js +821 -0
- package/public/js/dash.js +114 -0
- package/public/js/drawer.js +919 -0
- package/public/js/horizon.js +140 -0
- package/public/js/init.js +208 -0
- package/public/js/project.js +338 -0
- package/public/js/settings.js +905 -0
- package/public/js/sidebar.js +640 -0
- package/public/js/sse.js +386 -0
- package/public/manifest.webmanifest +32 -0
- package/public/offline.html +39 -0
- package/public/style.css +1247 -0
- package/public/sw.js +31 -0
- package/scripts/raycast/open-kanban.sh +18 -0
- package/scripts/update.js +43 -0
- package/skills/deploy/SKILL.md +70 -0
- package/skills/kanban/SKILL.md +217 -0
- package/src/backup.js +111 -0
- package/src/bus.js +10 -0
- package/src/config.js +40 -0
- package/src/db.js +321 -0
- package/src/error-handler.js +11 -0
- package/src/file-snapshot.js +22 -0
- package/src/origin-guard.js +32 -0
- package/src/pm2-services.js +31 -0
- package/src/query-params.js +17 -0
- package/src/repo-base.js +23 -0
- package/src/restore.js +153 -0
- package/src/routes/dashboard.js +132 -0
- package/src/routes/events.js +30 -0
- package/src/routes/horizons.js +66 -0
- package/src/routes/projects.js +532 -0
- package/src/routes/skills.js +116 -0
- package/src/routes/system.js +285 -0
- package/src/routes/tasks.js +477 -0
- package/src/schema.sql +135 -0
- package/src/server.js +100 -0
- package/src/skills.js +119 -0
- package/src/sync/github.js +265 -0
- package/src/sync/worker.js +136 -0
- package/src/task-shape.js +29 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Notable changes, newest first. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
|
|
4
|
+
and the project uses [semantic versioning](https://semver.org/).
|
|
5
|
+
|
|
6
|
+
## [1.6.3]
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
|
|
10
|
+
- **A commercial invoice is asked for by email now, not through a public issue.** Wanting to pay
|
|
11
|
+
for something you use at work is not a thing anyone should have to announce in public, and the
|
|
12
|
+
first line of an invoice request is the company name. `docs/COMMERCIAL.md` names an address
|
|
13
|
+
instead, and asks for the two things an invoice needs: the country and how many people use the
|
|
14
|
+
board.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- **The install section described a question the wizard never asks.** It said the wizard asks
|
|
19
|
+
*where* to put the Claude Code skills. There is no choice of place — the path is
|
|
20
|
+
`~/.claude/skills` — and the question is whether to install them at all; it installs two, the
|
|
21
|
+
board's own skill and the deploy one. Both READMEs now describe what the program actually does.
|
|
22
|
+
|
|
23
|
+
## [1.6.2]
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- **A quiet ask for companies that use the board at work.** It stays MIT-licensed and free for
|
|
28
|
+
everyone — nothing is switched off, nothing to activate, and it still never contacts a server —
|
|
29
|
+
but if the board earns you money, $12 a year per person keeps it maintained. The ask is one line
|
|
30
|
+
in the README and one row in Settings → About, both pointing at `docs/COMMERCIAL.md`, which spells
|
|
31
|
+
out what this is and, just as plainly, what it is not: not a licence purchase, not a support
|
|
32
|
+
contract, and not a subscription that switches anything off when it lapses.
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
|
|
36
|
+
- **The bulk-registration script sent you to a file that does not exist.** `contrib/bootstrap.js`
|
|
37
|
+
loads a registry of projects from `contrib/seed-projects.json`, and when that file was missing it
|
|
38
|
+
told you to run `contrib/seed-from-panel.js` first — a script that is git-ignored and has never
|
|
39
|
+
been in the repository, as `contrib/README.md` says a few lines below. The directory is not part
|
|
40
|
+
of the published package, but it is part of the repository, so the first thing a reader of a fresh
|
|
41
|
+
clone was told to do could not be done at all. The message now names
|
|
42
|
+
`contrib/seed-projects.example.json`, which sits right next to the script: copy it, edit it, run
|
|
43
|
+
the script. Only `slug` and `name` are required, and a test keeps the example in step with the
|
|
44
|
+
fields the script actually reads — an example promising fields that are silently ignored is the
|
|
45
|
+
same broken promise, only quieter.
|
|
46
|
+
|
|
47
|
+
## [1.6.1]
|
|
48
|
+
|
|
49
|
+
### Fixed
|
|
50
|
+
|
|
51
|
+
- **The buttons in the skills section could act on the previous skill instead of the one on
|
|
52
|
+
screen.** Creating a skill left two requests in flight — the section re-renders and opens its
|
|
53
|
+
first row, then the code opens the new skill — and whichever answered last owned the panel's
|
|
54
|
+
state. In that gap the page showed the new skill while "load the shared version" fetched the text
|
|
55
|
+
of another one and "delete" would have removed it: with the guard deliberately switched off, 19
|
|
56
|
+
frames out of 30 showed one skill's row above another skill's path. An answer that is no longer
|
|
57
|
+
the current one is now discarded, the section opens exactly one skill instead of two, and the
|
|
58
|
+
buttons stay disabled until its text has arrived.
|
|
59
|
+
|
|
60
|
+
## [1.6.0]
|
|
61
|
+
|
|
62
|
+
### Changed
|
|
63
|
+
|
|
64
|
+
- **The skills section lists only what the board is about.** A skills directory holds every skill
|
|
65
|
+
its owner uses in Claude Code — most of it has nothing to do with the board — and burying the rest
|
|
66
|
+
behind a "show the others" line was not enough: the section is about deploy instructions. It now
|
|
67
|
+
shows the board's own skill and deploy skills: the shared one, the ones registered projects use,
|
|
68
|
+
and the ones created here. The full list is still where it is needed — in the deploy-skill picker
|
|
69
|
+
on the project page.
|
|
70
|
+
- **A skill created from the board no longer disappears from the list.** Nothing on disk tells a
|
|
71
|
+
skill created here apart from the rest of the library, so the board now remembers its own.
|
|
72
|
+
Entering the name of a skill that already exists adopts it into the list instead of failing —
|
|
73
|
+
without that, a skill outside those groups could be neither opened nor deleted.
|
|
74
|
+
|
|
75
|
+
### Added
|
|
76
|
+
|
|
77
|
+
- **A skill can be deleted from the settings**, with the resolved path in the confirmation and a
|
|
78
|
+
snapshot of the file kept beforehand. **A skill that is a symlink loses only the link** — the file
|
|
79
|
+
it points to usually lives in another repository and is left alone; the dialog says so before you
|
|
80
|
+
press the button, not after.
|
|
81
|
+
|
|
82
|
+
### Fixed
|
|
83
|
+
|
|
84
|
+
- **"Load the shared version" no longer answers with a raw error on your own skill.** The board has
|
|
85
|
+
no shared version of a skill it does not ship, so the button is simply disabled there and says why.
|
|
86
|
+
|
|
87
|
+
## [1.5.0]
|
|
88
|
+
|
|
89
|
+
### Added
|
|
90
|
+
|
|
91
|
+
- **The deploy skill of a project is picked from a list instead of typed in.** The field took a
|
|
92
|
+
free-form name, so a typo left the project without a deploy and said nothing; now it offers the
|
|
93
|
+
skills the board actually found, plus "not set", plus a line explaining what the field is for. A
|
|
94
|
+
name that is stored but not installed stays in the list, marked as such, rather than quietly
|
|
95
|
+
disappearing on the next save.
|
|
96
|
+
- **A skill can be created from the settings.** "New skill" asks for a name and writes the file; if
|
|
97
|
+
this package ships a skill under that name, the file starts as that shared version — so taking the
|
|
98
|
+
ready-made one and starting your own are the same action with a different name. The new skill
|
|
99
|
+
shows up in the project's deploy-skill list immediately.
|
|
100
|
+
- **The project's own notes and its skill are editable where they are shown.** The viewer opened
|
|
101
|
+
from project settings was deliberately read-only, which was the wrong call: a rule is worked out
|
|
102
|
+
while doing a task, and writing it into `CLAUDE.md` belongs right there. Saving takes the same
|
|
103
|
+
lock as a skill — it confirms the resolved path, the server checks that path itself, and the
|
|
104
|
+
previous contents are snapshotted into the data directory first.
|
|
105
|
+
|
|
106
|
+
### Changed
|
|
107
|
+
|
|
108
|
+
- **The skills list is grouped.** A skills directory holds everything its owner uses in Claude Code,
|
|
109
|
+
most of it unrelated to the board. The section now leads with the board's own skill and the deploy
|
|
110
|
+
skills of registered projects, and keeps the rest behind a "other Claude skills" line.
|
|
111
|
+
|
|
112
|
+
## [1.4.1]
|
|
113
|
+
|
|
114
|
+
### Fixed
|
|
115
|
+
|
|
116
|
+
- **A skill used by a dozen projects broke its own row in the new "Skills" section.** The label
|
|
117
|
+
listed every project by name, so it wrapped onto a second line and pushed the size and date off
|
|
118
|
+
the right edge of the list. Past two projects the label now counts them ("used by 12 projects")
|
|
119
|
+
and the names move into the tooltip.
|
|
120
|
+
|
|
121
|
+
## [1.4.0]
|
|
122
|
+
|
|
123
|
+
### Added
|
|
124
|
+
|
|
125
|
+
- **Project settings are a page inside the project instead of a popup at the cursor.** The popup
|
|
126
|
+
was 250 pixels wide with its own scrollbar and a collapsible "paths & deploy" block, and it had
|
|
127
|
+
long stopped fitting what belongs there — seven registry fields. The same places open it (the
|
|
128
|
+
`⋯` button in the topbar, a right-click on a board in the sidebar); clicking `⋯` again, or Esc,
|
|
129
|
+
goes back to the board.
|
|
130
|
+
- **The page shows what Claude reads before it starts working:** the project's own `CLAUDE.md`
|
|
131
|
+
(plus `README.md` and the like when they exist) and the deploy skill it uses — the shared one or
|
|
132
|
+
its own — with absolute paths, a copy button and a read-only viewer. A missing `CLAUDE.md` is
|
|
133
|
+
listed too: that absence is worth knowing, since the agent will start the task without those
|
|
134
|
+
notes.
|
|
135
|
+
- **A "Skills" section in the settings.** Skills are the instructions Claude actually reads, and
|
|
136
|
+
they live outside the board, in `~/.claude/skills`; until now the board only wrote them once, at
|
|
137
|
+
install time, and never mentioned them again. The section lists every skill it can find, says
|
|
138
|
+
which projects use which, and shows the text of the selected one.
|
|
139
|
+
- **Loading the shared version of a skill and writing it to disk are two separate buttons.** A
|
|
140
|
+
skill directory is often a symlink to a file in another repository — a customised copy somebody
|
|
141
|
+
keeps deliberately — so a single "update" button would silently overwrite it. Loading only fills
|
|
142
|
+
the editor and names the source (GitHub, or the copy that shipped with the package) and the
|
|
143
|
+
language; saving is a second, explicit step that asks about the resolved path it is about to
|
|
144
|
+
overwrite, and keeps a snapshot of the previous contents in the data directory first.
|
|
145
|
+
|
|
146
|
+
## [1.3.2]
|
|
147
|
+
|
|
148
|
+
### Fixed
|
|
149
|
+
|
|
150
|
+
- **The GitHub sync stopped as soon as a label differed only in capitalisation.** GitHub treats
|
|
151
|
+
label names as case-insensitive; the board compared them exactly. A board whose repository
|
|
152
|
+
already had, say, `NoClaude` while the palette asks for `noclaude` did not recognise it, tried to
|
|
153
|
+
create it, and GitHub answered "a label with that name already exists" — which brought down the
|
|
154
|
+
whole issue creation, so every task after that reported "the issue does not exist yet" and the
|
|
155
|
+
error log filled up. Dropping `--force` in 1.3.0 is what exposed it: `--force` never complained
|
|
156
|
+
about a label that was already there. A label that already exists is no longer treated as a
|
|
157
|
+
failure at all, and a repository whose labels could not be listed is retried on the next
|
|
158
|
+
operation instead of being written off until a restart.
|
|
159
|
+
|
|
160
|
+
## [1.3.1]
|
|
161
|
+
|
|
162
|
+
Three fixes found by testing the previous release rather than by using it — each one a place where
|
|
163
|
+
the 1.3.0 change was right in intent and incomplete in reach.
|
|
164
|
+
|
|
165
|
+
### Fixed
|
|
166
|
+
|
|
167
|
+
- **A board with its own data directory could not create a project folder.** Keeping an isolated
|
|
168
|
+
instance out of the owner's live `~/claude-projects` (1.3.0) moved project folders next to the
|
|
169
|
+
data directory — but nothing ever created that directory, so the first "create a folder" answered
|
|
170
|
+
with an error and the feature simply did not work for anyone who chose a custom data directory
|
|
171
|
+
during setup. The failure was also invisible: it never reached the error log.
|
|
172
|
+
- **The dashboard funnel still counted archived boards.** Archiving was made to remove a board from
|
|
173
|
+
every card and every total, and it does — except for the bar chart of how many tasks sit at each
|
|
174
|
+
stage, which was left counting the archived board's tasks. On one screen that put a set of
|
|
175
|
+
consistent numbers next to one inconsistent one.
|
|
176
|
+
- **A deleted issue was retried instead of failing.** The list of GitHub answers that mean "this
|
|
177
|
+
will never succeed" spelled the article one way, and GitHub writes it the other way for half the
|
|
178
|
+
entries — so an issue that no longer exists was treated as a passing network problem and retried
|
|
179
|
+
fifteen times before giving up.
|
|
180
|
+
|
|
181
|
+
## [1.3.0]
|
|
182
|
+
|
|
183
|
+
A full audit of the board — stability, performance and error handling — went through every part of
|
|
184
|
+
it, and this release is the answer to it. The headline is the tab you leave open all day: it used
|
|
185
|
+
to go quiet without ever saying so.
|
|
186
|
+
|
|
187
|
+
### Added
|
|
188
|
+
|
|
189
|
+
- **The board tells you when a change did not save.** With the server down, the board used to stay
|
|
190
|
+
silent: a dragged card slid into its new column and drifted back on its own two seconds later, a
|
|
191
|
+
description you typed went nowhere, and the title of a new task vanished without a trace — the
|
|
192
|
+
only record was a failed request in the console, because the error report itself goes to the
|
|
193
|
+
server that is down. A change that cannot reach the server now rolls back, lights up a "not
|
|
194
|
+
saved" badge in the header, and is sent again as soon as the connection returns.
|
|
195
|
+
- **Archived boards can be brought back.** Archiving hid a board from the sidebar and there was no
|
|
196
|
+
way back short of a raw HTTP request. Settings now has an Archive section listing what was
|
|
197
|
+
archived, with a button to restore it.
|
|
198
|
+
- **`local-kanban skills` refreshes the Claude Code skills.** Installed from npm they were copied
|
|
199
|
+
once and then never updated by anything, so the board moved forward while the instructions the
|
|
200
|
+
agent reads stayed on an older version.
|
|
201
|
+
- **Search covers the whole description.** It only ever looked at the first 180 characters, so a
|
|
202
|
+
word further in was simply not found — no result, no error, no hint that the search was partial.
|
|
203
|
+
|
|
204
|
+
### Fixed
|
|
205
|
+
|
|
206
|
+
- **A tab that lost its event stream never noticed.** The check for a dead stream ran only when the
|
|
207
|
+
window was hidden or refocused — and the board is normally visible and focused all day, so
|
|
208
|
+
neither ever happened. After a laptop sleep or a network timeout the board froze: finished tasks
|
|
209
|
+
did not appear, and anything done from the frozen board overwrote what had happened meanwhile.
|
|
210
|
+
Liveness is now checked on a timer, and a stream that recovers on its own catches up on what it
|
|
211
|
+
missed.
|
|
212
|
+
- **A burst of events left only the last one.** Five tasks created in a row showed up as one; five
|
|
213
|
+
tasks moved in a row left four cards sitting in their old column — which is worse, because a
|
|
214
|
+
missing card is visible and a card in the wrong column is not. Every event in a burst is now
|
|
215
|
+
applied.
|
|
216
|
+
- **The task panel overwrote changes made elsewhere.** It sent every field it held on any edit,
|
|
217
|
+
while only refreshing the status, so setting a priority or a label from the CLI or another tab
|
|
218
|
+
was rolled back within half a second. It now sends only what actually changed, shows what came
|
|
219
|
+
from elsewhere, and closes itself if the task was deleted.
|
|
220
|
+
- **Every board render held on to the previous one.** Memory grew with each redraw for as long as
|
|
221
|
+
the tab stayed on one board — tens of megabytes over a day of activity.
|
|
222
|
+
- **A task forgotten in a working column counted the whole time as work.** One task left in
|
|
223
|
+
"doing" over a weekend turned the week's work time into fiction. A single stretch is now capped,
|
|
224
|
+
and a capped number is marked as approximate instead of pretending to be exact.
|
|
225
|
+
- **Two snapshots taken in the same second destroyed each other,** leaving a zero-byte file under
|
|
226
|
+
the final name that was listed, downloadable and counted as a backup.
|
|
227
|
+
- **A failing daily backup said nothing.** With the snapshot directory unwritable the board started
|
|
228
|
+
normally, took no snapshots, logged nothing, and tried again six hours later. The Backups section
|
|
229
|
+
now shows the last success and the last failure, and a failure is retried in minutes.
|
|
230
|
+
- **Attachments were in no backup at all.** Images are now mirrored alongside the snapshots and
|
|
231
|
+
restored into the preview board.
|
|
232
|
+
- **A board opened from a backup could outlive the one that started it,** holding a port and
|
|
233
|
+
serving a full copy of every task with nothing left to stop it.
|
|
234
|
+
- **Uploading a backup buffered the whole file in memory** and lifted the size limit from every
|
|
235
|
+
other route as a side effect. The body is now streamed to disk and the limit is scoped.
|
|
236
|
+
- **The error log washed itself out.** A few hundred identical broken requests erased the whole
|
|
237
|
+
ring, real failures included; repeats are now collapsed with a counter. A genuine server failure
|
|
238
|
+
also reaches the process log — previously its only copy was the table, and if that table was the
|
|
239
|
+
problem, the board pointed at a section that answered with the same failure.
|
|
240
|
+
- **Malformed input answered 500 instead of 400** on ten routes, and in one of them a request could
|
|
241
|
+
come back 200 while writing the wrong value into a project field.
|
|
242
|
+
- **`kb` could not tell a refusal from a failure.** A board erroring on a request exited with the
|
|
243
|
+
same code as a lawful refusal, and a reply that was not JSON — what you get when the address
|
|
244
|
+
points at something else — exited zero and reported a move that never happened.
|
|
245
|
+
- **GitHub sync could create a second issue for one task** if the process restarted at the wrong
|
|
246
|
+
moment, and an unparsed answer from `gh` started stamping out new ones. An ordinary network
|
|
247
|
+
failure was also filed as permanent and never retried, and labels recoloured by hand were reset
|
|
248
|
+
on every restart.
|
|
249
|
+
- **Archiving a project hid it from the sidebar only.** Its cards stayed on the combined board, its
|
|
250
|
+
tasks stayed in "waiting for you", and it was still named in the top projects.
|
|
251
|
+
- **Dashboard windows were cut in UTC but drawn in local days,** so the edge of the week fell in
|
|
252
|
+
the middle of a day that the calendar showed in full. The header and the dashboard also counted
|
|
253
|
+
the same week by different rules.
|
|
254
|
+
- **A board with its own data directory still used the live project folder of the account,** listed
|
|
255
|
+
it and created folders in it.
|
|
256
|
+
- **A relative or `~`-prefixed data directory** created a real directory named `~` and then died on
|
|
257
|
+
a raw stack trace.
|
|
258
|
+
- **The install check in CI passed on a package that installs but does not open,** and it was not
|
|
259
|
+
called on the publishing path at all.
|
|
260
|
+
- **A broken database died on a raw driver stack** instead of pointing at the snapshots next to it.
|
|
261
|
+
- **A group drag that was refused explained nothing** — the reason was computed, translated and
|
|
262
|
+
thrown away.
|
|
263
|
+
- **Deleting the demo project left its attachments on disk,** still served over a direct link.
|
|
264
|
+
|
|
265
|
+
### Performance
|
|
266
|
+
|
|
267
|
+
Groundwork for larger boards; on a board of a couple of thousand tasks the difference today is a
|
|
268
|
+
few milliseconds. The task list no longer reads full descriptions off disk to return a 180-character
|
|
269
|
+
preview, the link map is built only for the tasks being shown, the dashboard stops scanning the whole
|
|
270
|
+
event log for one minimum, project counters got a covering index, and an edit that changes neither
|
|
271
|
+
the column nor the order redraws one card instead of the whole board. Search input is debounced.
|
|
272
|
+
|
|
273
|
+
## [1.2.1]
|
|
274
|
+
|
|
275
|
+
### Fixed
|
|
276
|
+
|
|
277
|
+
- **Creating a task threw an error every single time.** The board splits its frontend into ES
|
|
278
|
+
modules, and two of them wrote to a variable owned by another module. An import is a read-only
|
|
279
|
+
binding, so the assignment threw a `TypeError` and took the rest of the function with it. Three
|
|
280
|
+
things were broken by it at once: a freshly created card was never scrolled into view, the board
|
|
281
|
+
refresh that follows creation never ran, and the sync badge stopped updating — which also meant
|
|
282
|
+
a board with no GitHub sync configured still promised "creating issue…" on every new task. Each
|
|
283
|
+
creation also left an entry in the error log; on a board in daily use they were 82 of the last
|
|
284
|
+
100 records.
|
|
285
|
+
- **A task deleted in another tab filled the error log.** The panel re-reads the task it shows on
|
|
286
|
+
every board refresh, so a task deleted elsewhere logged the same "task not found" line again and
|
|
287
|
+
again. Opening one now says so plainly, closes the panel and refreshes the board, and the
|
|
288
|
+
periodic re-read no longer treats an expected miss as a failure.
|
|
289
|
+
|
|
290
|
+
## [1.2.0]
|
|
291
|
+
|
|
292
|
+
### Added
|
|
293
|
+
|
|
294
|
+
- **A long status history no longer buries the rest of the task.** A task that has been moved
|
|
295
|
+
around for weeks collects a couple of dozen timeline rows, and they pushed everything else in
|
|
296
|
+
the panel out of view. Anything longer than six entries now shows the three most recent ones
|
|
297
|
+
with an arrow to expand the rest — and to fold them back.
|
|
298
|
+
|
|
299
|
+
### Fixed
|
|
300
|
+
|
|
301
|
+
- **`kb info` crashed on a project whose pm2 services were stored as a plain string.** The field
|
|
302
|
+
is documented as "a comma-separated string or JSON" and both forms exist in real databases, but
|
|
303
|
+
every reader parsed it as JSON only: the command exited with an error instead of printing the
|
|
304
|
+
project, `GET /api/projects/:slug/status` answered 500, and the project settings showed an empty
|
|
305
|
+
pm2 field that the next save would have wiped. Both forms are now read, and new values are
|
|
306
|
+
stored in one canonical shape.
|
|
307
|
+
|
|
308
|
+
### Changed
|
|
309
|
+
|
|
310
|
+
- `package.json` no longer declares a `test` script. The tests are not part of the published
|
|
311
|
+
package, so inside an installed one the command exited successfully having run nothing at all —
|
|
312
|
+
a green check for a check that never happened. Tests are run from a clone with `node --test`.
|
|
313
|
+
|
|
314
|
+
## [1.1.0]
|
|
315
|
+
|
|
316
|
+
### Changed
|
|
317
|
+
|
|
318
|
+
- **Node 22 is now the minimum, and installing on a current Node no longer builds from source.**
|
|
319
|
+
The database driver is a native module that ships prebuilt binaries per Node version. The
|
|
320
|
+
pinned version had them for Node 18 through 23 only, so anyone installing on Node 24 LTS or 26
|
|
321
|
+
— which is what you get if you install Node today — silently fell through to compiling the
|
|
322
|
+
driver locally: minutes of waiting, a C++ toolchain required, and an outright failure on a
|
|
323
|
+
machine that has none. The driver is updated to a release with binaries for Node 22, 24, 25 and
|
|
324
|
+
26, `engines` states that range, and CI now tests both ends of it plus a real install on the
|
|
325
|
+
current LTS. Node 20 drops out of the range: the new driver has no binaries for it and Node 20
|
|
326
|
+
itself stopped receiving releases in March 2026.
|
|
327
|
+
|
|
328
|
+
## [1.0.2]
|
|
329
|
+
|
|
330
|
+
### Fixed
|
|
331
|
+
|
|
332
|
+
- **The bundled Raycast command did not work.** `scripts/raycast/open-kanban.sh` ships in the
|
|
333
|
+
package, and the export step removed its `@raycast.title` and `@raycast.description` lines as
|
|
334
|
+
if they were prose. They are not — Raycast parses them, and without a title it never registers
|
|
335
|
+
the command. The script is now written in English and the export refuses to drop a directive.
|
|
336
|
+
|
|
337
|
+
### Changed
|
|
338
|
+
|
|
339
|
+
- `package.json` no longer advertises `bootstrap` and `seed:panel`. Neither could run from an
|
|
340
|
+
installed package: one points into a directory that is not shipped, the other at a file that
|
|
341
|
+
was never in the repository. The `contrib/` helpers are run directly from a clone.
|
|
342
|
+
|
|
343
|
+
## [1.0.1]
|
|
344
|
+
|
|
345
|
+
### Fixed
|
|
346
|
+
|
|
347
|
+
- **The board could not be stopped.** Neither `Ctrl+C` nor `SIGTERM` had any effect — only
|
|
348
|
+
`SIGKILL` did. A module-level signal listener was registered on import and did nothing, which
|
|
349
|
+
is enough to cancel Node's default terminate-on-signal. Handlers now live only for as long as
|
|
350
|
+
the thing they clean up, and they exit explicitly.
|
|
351
|
+
- **"Stop" on a restored backup lied.** The second board opened from an uploaded backup ignored
|
|
352
|
+
the stop button, the thirty-minute expiry and the next upload — same root cause — so preview
|
|
353
|
+
boards piled up, each still serving a copy of the data on an open port.
|
|
354
|
+
- **The wizard's manual instructions assumed a git clone.** Anyone who installed from npm was
|
|
355
|
+
told to run `npm link` and to symlink `skills/` from a directory they do not have; `kb` ships
|
|
356
|
+
with the package and the wizard already copies the skills. The final step now branches on how
|
|
357
|
+
the board was installed.
|
|
358
|
+
- Missing Russian translation for the dashboard "Streak" card, which never went through the
|
|
359
|
+
translation layer at all.
|
|
360
|
+
- `npm run update` printed git's raw `fatal: not a git repository` before its own explanation of
|
|
361
|
+
how to update an npm install.
|
|
362
|
+
- The release preflight reported "something was committed straight to main" when the real problem
|
|
363
|
+
was that no local `main` branch existed.
|
|
364
|
+
|
|
365
|
+
### Changed
|
|
366
|
+
|
|
367
|
+
- The README no longer claims parts of the settings are Russian-first — English is the source
|
|
368
|
+
language of the interface and a string with no translation stays English.
|
|
369
|
+
|
|
370
|
+
## [1.0.0]
|
|
371
|
+
|
|
372
|
+
First public release. A local kanban board built to work in tandem with Claude Code: the human
|
|
373
|
+
plans and accepts, Claude takes tasks from the queue through the `kb` CLI and stops at review.
|
|
374
|
+
|
|
375
|
+
- Board, dashboard, chaos capture, horizon and calendar views; drag and drop, task links,
|
|
376
|
+
checklists, attachments, comments with images.
|
|
377
|
+
- `kb` — a token-efficient CLI for the whole task loop (`take`, `show`, `mv`, `review`, `done`).
|
|
378
|
+
- Optional one-way GitHub mirror: every task becomes an issue, every project a Projects v2 board.
|
|
379
|
+
- SQLite with versioned migrations, a pre-migration snapshot and rotating backups.
|
|
380
|
+
- Local-first by design: binds to loopback, checks request origin, ships no external resources.
|
|
381
|
+
- English and Russian interface, installed and set up by `npx local-kanban`.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dannylamao
|
|
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,144 @@
|
|
|
1
|
+
# local-kanban
|
|
2
|
+
|
|
3
|
+
[](https://github.com/lamaohub/local-kanban/actions/workflows/test.yml)
|
|
4
|
+
|
|
5
|
+
A local kanban board built for working **in tandem with Claude Code**: the human plans and accepts tasks, Claude takes them from the queue, does the work and reports back — all through a token-efficient CLI called `kb`. Optionally mirrors everything to GitHub (issues + Projects v2).
|
|
6
|
+
|
|
7
|
+
Русская версия — [README.ru.md](README.ru.md).
|
|
8
|
+
|
|
9
|
+

|
|
10
|
+
|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
## Why
|
|
14
|
+
|
|
15
|
+
- **A queue for Claude, not just a board.** Statuses model the real loop: `backlog → todo → prep → doing → deploy → review → done`. Claude pulls the next task with `kb take`, works, and stops at *review* — accepting is always the human's call.
|
|
16
|
+
- **Local-first.** Everything lives in a single SQLite file on your machine. GitHub sync is optional and off until you configure it.
|
|
17
|
+
- **Honest metrics.** Work time is measured only while Claude actually works; the dashboard shows streaks, cycle time and what's waiting for you.
|
|
18
|
+
|
|
19
|
+
## Security model — read this first
|
|
20
|
+
|
|
21
|
+
The server listens on **127.0.0.1 only** and has **no authentication**. The board is strictly local: your machine is the trust boundary. **Never expose the port to the network** (no reverse proxies, no `0.0.0.0`, no port forwarding). Third-party integrations should run on the same machine and talk to `127.0.0.1` (see [docs/API.md](docs/API.md)).
|
|
22
|
+
|
|
23
|
+
## Requirements
|
|
24
|
+
|
|
25
|
+
- **Node.js ≥ 22** (macOS or Linux) — 24 LTS or newer is what most people have
|
|
26
|
+
- Optional, only for GitHub sync: [`gh` CLI](https://cli.github.com/) authenticated with the `project` scope:
|
|
27
|
+
`gh auth login && gh auth refresh -s project`
|
|
28
|
+
|
|
29
|
+
## Install
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install -g local-kanban
|
|
33
|
+
local-kanban # setup wizard
|
|
34
|
+
local-kanban start # board at http://localhost:3100
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The wizard asks for the port, the data directory, whether you want GitHub sync, and whether to install the two Claude Code skills — the board's own and the deploy one — into `~/.claude/skills`. Every question has a default, so Enter-Enter-Enter is enough. It also writes `ecosystem.config.cjs` for autostart under [pm2](https://pm2.keymetrics.io/).
|
|
38
|
+
|
|
39
|
+
`local-kanban start` takes `--port <N>` and `--data <dir>`. Data lives in `~/.local-kanban` by default, outside the package directory, so updating the package never touches your board.
|
|
40
|
+
|
|
41
|
+
From source:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
git clone <repo-url> local-kanban && cd local-kanban
|
|
45
|
+
npm install
|
|
46
|
+
npx local-kanban # setup wizard (optional)
|
|
47
|
+
npm start # board at http://localhost:3100
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
To get the `kb` command globally: `npm link` (or `npm install -g .`).
|
|
51
|
+
|
|
52
|
+
First launch shows an empty dashboard with an optional **demo project** — one click creates it, one click removes it.
|
|
53
|
+
|
|
54
|
+
### Let Claude finish the setup
|
|
55
|
+
|
|
56
|
+
The last step of the first-run wizard shows a ready-made prompt (in the board's language). Paste it
|
|
57
|
+
into Claude Code and it will walk you through the rest — check that `kb` works, ask whether you want
|
|
58
|
+
the GitHub mirror, register your first projects with their paths and deploys, and verify the result.
|
|
59
|
+
The same prompt lives in **Settings → About**, so you can come back to it later.
|
|
60
|
+
|
|
61
|
+
### Claude Code skills
|
|
62
|
+
|
|
63
|
+
The repo ships two skills for Claude Code in `skills/`:
|
|
64
|
+
|
|
65
|
+
- `skills/kanban` — teaches Claude the task workflow (`kb take` → work → `kb review`);
|
|
66
|
+
- `skills/deploy` — a generic deploy flow driven by the project registry (`kb info`).
|
|
67
|
+
|
|
68
|
+
Install by symlink or copy:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
ln -s "$(pwd)/skills/kanban" ~/.claude/skills/kanban
|
|
72
|
+
ln -s "$(pwd)/skills/deploy" ~/.claude/skills/deploy
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## GitHub sync (optional)
|
|
76
|
+
|
|
77
|
+
Set the owner and issues repo in **Settings → Sync** on the board (or env `KB_GH_OWNER` / `KB_GH_REPO`). Without them the board runs in local-only mode: no queue, no warnings. With them, every task becomes an issue and every project gets a `kb: <slug>` GitHub Project with matching columns. Sync is one-way (board → GitHub) and runs in the background.
|
|
78
|
+
|
|
79
|
+
## Updating
|
|
80
|
+
|
|
81
|
+
From npm:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npm install -g local-kanban@latest
|
|
85
|
+
local-kanban skills # refresh the Claude Code skills — they are a copy, not a link
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
From a clone:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npm run update # git pull + npm install + pm2 restart (if applicable)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Your data is never touched by updates: `data/` is gitignored and schema migrations run automatically on start — **with a pre-migration snapshot** saved to `data/backups/pre-migrate/` before anything changes.
|
|
95
|
+
|
|
96
|
+
**Rollback:** stop the server, restore the latest file from `data/backups/` (daily) or `data/backups/pre-migrate/` over `data/kanban.db`, then `git checkout <previous tag>` and start again.
|
|
97
|
+
|
|
98
|
+
Releases live in `main` (stable, tagged); day-to-day development happens in `dev`.
|
|
99
|
+
|
|
100
|
+
## Environment variables
|
|
101
|
+
|
|
102
|
+
| Variable | Default | Meaning |
|
|
103
|
+
|---|---|---|
|
|
104
|
+
| `PORT` | `3100` | HTTP port (bound to 127.0.0.1) |
|
|
105
|
+
| `KB_DATA_DIR` | `./data` | data directory (SQLite, attachments, backups) |
|
|
106
|
+
| `KB_LOCAL_ROOT` | `~/claude-projects` | root folder scanned for local projects |
|
|
107
|
+
| `KB_URL` | `http://127.0.0.1:3100` | board URL for the `kb` CLI |
|
|
108
|
+
| `KB_GH_OWNER` / `KB_GH_REPO` | — | GitHub sync target; empty = sync off (can also be set in Settings) |
|
|
109
|
+
| `KB_PANEL_URL` | — | custom HTTP source of service statuses; empty = local `pm2 jlist` |
|
|
110
|
+
| `KB_PANEL_INFO` | — | optional path to an external panel's info.json for category sync |
|
|
111
|
+
| `KB_SSE_MAX` | `20` | cap on concurrent SSE connections |
|
|
112
|
+
| `KB_SKILLS_EXTRA` | — | extra skill root directories, `:`-separated |
|
|
113
|
+
|
|
114
|
+
The legacy names `PANEL_URL` and `PANEL_INFO` (without the prefix) still work as a fallback.
|
|
115
|
+
|
|
116
|
+
## Metrics and the `noclaude` label
|
|
117
|
+
|
|
118
|
+
Tasks done **by hand** (without Claude) get the `noclaude` label — they are counted separately on the dashboard and excluded from Claude's metrics (work time, cycle, completion %), which would otherwise be skewed by their zero work time. The label is optional and can be added later. Manual tasks are also allowed to jump straight to *review*/*done*.
|
|
119
|
+
|
|
120
|
+
## Extending
|
|
121
|
+
|
|
122
|
+
The full HTTP API and the SSE event stream are the official extension point — build bots, stats, integrations as separate programs, no plugins inside the page. See [docs/API.md](docs/API.md).
|
|
123
|
+
|
|
124
|
+
## Development
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
node --test # DB isolated via KB_DATA_DIR
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the dev setup, branch flow and the schema-migration rule. The architecture is described in [ARCHITECTURE.md](ARCHITECTURE.md), and what changed between versions in [CHANGELOG.md](CHANGELOG.md).
|
|
131
|
+
|
|
132
|
+
## UI language
|
|
133
|
+
|
|
134
|
+
English is the source language of the interface; Russian comes as a translation. The board follows your system language and can be switched in **Settings → General** — a string with no translation yet stays English rather than leaking into the wrong locale.
|
|
135
|
+
|
|
136
|
+
## Using it at work
|
|
137
|
+
|
|
138
|
+
The board is MIT-licensed and free for everyone: nothing is switched off and there is nothing to
|
|
139
|
+
activate. If it earns you money — inside a company, or on paid client work — $12 a year per person
|
|
140
|
+
keeps it maintained. A request, not a rule: [docs/COMMERCIAL.md](docs/COMMERCIAL.md).
|
|
141
|
+
|
|
142
|
+
## License
|
|
143
|
+
|
|
144
|
+
[MIT](LICENSE).
|