k0-board 0.4.0 → 0.5.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.
Files changed (73) hide show
  1. package/.claude/skills/k0-changelog/SKILL.md +2 -2
  2. package/.claude/skills/k0-discuss/SKILL.md +105 -0
  3. package/.claude/skills/k0-discuss/references/rounds.md +280 -0
  4. package/.claude/skills/k0-epic/SKILL.md +196 -0
  5. package/.claude/skills/k0-links/.claude-plugin/plugin.json +6 -0
  6. package/.claude/skills/k0-links/hooks/hooks.json +1 -0
  7. package/.claude/skills/k0-links/hooks/links.js +128 -0
  8. package/.claude/skills/k0-links/hooks/register.js +204 -0
  9. package/.claude/skills/k0-next/SKILL.md +82 -0
  10. package/.claude/skills/k0-order/SKILL.md +123 -0
  11. package/.claude/skills/k0-plan/SKILL.md +156 -0
  12. package/.claude/skills/k0-split/SKILL.md +169 -0
  13. package/.claude/skills/k0-story/SKILL.md +108 -0
  14. package/.claude/skills/k0-ultracode/SKILL.md +251 -0
  15. package/.claude/skills/k0-ultracode/references/agent-brief.md +71 -0
  16. package/.claude/skills/k0-ultracode/references/modes.md +49 -0
  17. package/.claude/skills/k0-verify/SKILL.md +219 -0
  18. package/.claude/skills/k0-whatsnew/SKILL.md +95 -0
  19. package/.claude/skills/k0-work/SKILL.md +212 -0
  20. package/CHANGELOG.md +361 -1
  21. package/README.md +931 -111
  22. package/bin/k0-board.js +79 -11
  23. package/menubar/K0MenuBar.swift +35 -5
  24. package/package.json +13 -1
  25. package/platform/contract.js +30 -5
  26. package/platform/darwin/terminal.js +230 -56
  27. package/platform/index.js +2 -1
  28. package/platform/linux/index.js +3 -0
  29. package/platform/linux/tray.py +10 -10
  30. package/platform/shared/command.js +19 -3
  31. package/platform/shared/tmux.js +32 -14
  32. package/platform/win32/index.js +5 -2
  33. package/platform/win32/terminal.js +24 -8
  34. package/platform/win32/tray.ps1 +13 -13
  35. package/server/backlog.js +618 -0
  36. package/server/changelog.js +13 -13
  37. package/server/db.js +1800 -146
  38. package/server/files.js +60 -21
  39. package/server/git.js +53 -14
  40. package/server/idle.js +15 -13
  41. package/server/index.js +1251 -186
  42. package/server/launcher.js +122 -14
  43. package/server/machine.js +10 -1
  44. package/server/mirror.js +1048 -0
  45. package/server/prices.js +59 -0
  46. package/server/projects.js +57 -12
  47. package/server/servers.js +22 -1
  48. package/server/sessions.js +5 -5
  49. package/server/settings.js +25 -2
  50. package/server/update.js +324 -0
  51. package/server/usage.js +642 -0
  52. package/server/watcher.js +67 -13
  53. package/server/worktree.js +600 -0
  54. package/server/writer.js +98 -26
  55. package/web/awake.js +62 -0
  56. package/web/base.css +4 -0
  57. package/web/board.css +396 -16
  58. package/web/board.js +1182 -152
  59. package/web/changelog.js +3 -3
  60. package/web/files.js +73 -16
  61. package/web/index.html +109 -12
  62. package/web/list.css +536 -0
  63. package/web/list.js +1015 -0
  64. package/web/mentions.js +27 -9
  65. package/web/recency.js +10 -10
  66. package/web/units.js +1 -1
  67. package/web/usage.css +169 -0
  68. package/web/usage.html +78 -0
  69. package/web/usage.js +447 -0
  70. package/web/view.js +22 -3
  71. package/web/whatsnew.css +211 -0
  72. package/web/whatsnew.html +49 -0
  73. package/web/whatsnew.js +339 -0
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # k0
2
2
 
3
3
  **A board of sticky notes that drives your Claude Code sessions.** One column per project, one
4
- card per piece of work. From a card you open a real terminal, and on the card you see at a
4
+ story per piece of work. From a story you open a real terminal, and on the story you see at a
5
5
  glance whether the session is working, has finished, is asking you something, or has a plan
6
6
  waiting for your approval.
7
7
 
@@ -9,12 +9,15 @@ It exists because of one specific moment: four terminals open, and no way to tel
9
9
  waiting for you without clicking through all four.
10
10
 
11
11
  If you have used a kanban board, an infinite canvas like Miro, and a wall of paper sticky notes,
12
- you have already seen the three pieces k0 is made of: cards standing in columns, a board that pans
12
+ you have already seen the three pieces k0 is made of: stories standing in columns, a board that pans
13
13
  and zooms instead of scrolling, and notes that sit at their own slightly crooked angle. What is
14
- different is what those things are underneath. **A column is a repository, not a stage** — nothing
15
- gets dragged from one to the next; the cards reorder themselves by who is waiting for you.
16
- **A card is a real Claude Code session** — it opens a terminal, it knows what that session is
17
- doing, and it goes on saying so while you are looking somewhere else.
14
+ different is what those things are underneath. **A column is a repository, not a stage** — the
15
+ stories reorder themselves by who is waiting for you, rather than being pushed along a pipeline.
16
+ (One switch in the top bar lays the same stories out as a list instead, for the days you are
17
+ planning rather than working.)
18
+ **A story drives real Claude Code sessions** — it opens a terminal, it knows what that session
19
+ is doing, and it goes on saying so while you are looking somewhere else. A story may have had
20
+ several over its life, one at a time, and it keeps all of them.
18
21
 
19
22
  ![Four columns of paper sticky notes — yellow, blue, amber and green — pinned on a dark wall, each note tilted at its own angle, with a row of small coloured status pills along the top bar.](https://raw.githubusercontent.com/alessio-ragni/k0-board/main/docs/board.jpg)
20
23
 
@@ -23,6 +26,7 @@ doing, and it goes on saying so while you are looking somewhere else.
23
26
  [![License: MIT](https://img.shields.io/badge/License-MIT-informational)](LICENSE)
24
27
 
25
28
  **Contents** · [Install](#install) · [How it is used](#how-it-is-used) ·
29
+ [The backlog](#the-backlog) · [The ChangeLog](#the-changelog) · [What's New](#whats-new) ·
26
30
  [The files of a session](#the-files-of-a-session) · [What it costs](#what-it-costs) ·
27
31
  [Filling the board with what you have already done](#filling-the-board-with-what-you-have-already-done) ·
28
32
  [The statuses](#the-statuses) · [The four modes](#the-four-modes) ·
@@ -95,7 +99,7 @@ only browsers are obliged to know that `.localhost` means this computer — k0 o
95
99
  - **Node 24 or newer.** k0 keeps the board in SQLite through `node:sqlite`, which is built into
96
100
  Node — there is nothing to install and there are no npm dependencies at all.
97
101
  - **Claude Code**, obviously.
98
- - **git**, for the mark on each card that says whether your work is safe.
102
+ - **git**, for the mark on each story that says whether your work is safe.
99
103
  - **macOS**: Xcode Command Line Tools, to build the menu bar icon. Nothing else.
100
104
  - **Linux**: tmux, which is how k0 drives terminals there. Optionally `xdotool` for window
101
105
  placement, and `python3` with PyGObject for the tray icon.
@@ -108,6 +112,7 @@ only browsers are obliged to know that `.localhost` means this computer — k0 o
108
112
  | Open a terminal and run Claude Code in it | ✅ | ✅ tmux | ✅ |
109
113
  | Read the terminal to know when it is ready | ✅ | ✅ | ❌ waits a fixed moment instead |
110
114
  | Leave your prompt in place, unsent | ✅ needs Accessibility | ✅ | ✅ |
115
+ | Rename a running session when its title changes | ✅ needs Accessibility | ❌ when it ends | ❌ when it ends |
111
116
  | Place, resize and raise windows | ✅ | ✅ X11 only | ✅ |
112
117
  | Large text in terminals for driving mode | ✅ | ❌ | ❌ |
113
118
  | Keep the machine awake | ✅ | ✅ | ✅ |
@@ -138,12 +143,19 @@ Nothing on this list happens before you have seen it and said yes. Everything on
138
143
  | **macOS only** — one administrator rule | `/etc/sudoers.d/k0-pmset` | to keep the Mac awake with the lid closed. Asks for your password once, and grants exactly two command lines |
139
144
  | **macOS only** — one key binding | your Terminal profile (backed up first) | so Shift+Enter starts a new line |
140
145
  | **macOS only** — Accessibility for `node` | you grant it by hand, in System Settings | so k0 can place a prompt without sending it |
146
+ | The commands, and the `k0-links` mod, if you want them | `~/.claude/skills/` | Claude Code looks there and in the repository you have open, and nowhere else. Asked once; installing again brings the copies up to date without asking |
141
147
 
142
148
  That last one deserves a sentence of its own: a process with the Accessibility permission can
143
149
  send keystrokes to any application, and here it is granted to your `node`, not to a signed k0
144
150
  app. Skipping it breaks nothing — the prompt gets typed and the session starts by itself.
145
151
 
146
- k0 makes **no network requests**. Not one, not even for a font.
152
+ k0 makes **exactly one network request**, and you can switch it off. Once a day it asks the public
153
+ npm registry what the newest version of `k0-board` is, so the board can mention that there is one.
154
+ The package name is in the address and nothing else is in the request: not the version you are
155
+ running, not your repositories, not your commits, not your board, not an identifier of any kind.
156
+ Nothing is downloaded and nothing is run — k0 cannot update itself. Set `"updateCheck": false` in `~/.k0/config.json` and and no
157
+ socket is opened, ever. Everything else stays as it was: no fonts fetched, no telemetry, no
158
+ `git fetch`.
147
159
 
148
160
  ---
149
161
 
@@ -152,9 +164,13 @@ k0 makes **no network requests**. Not one, not even for a font.
152
164
  ### The board
153
165
 
154
166
  - **+** — at the left, next to k0, and next to every repository name on the board: that one opens
155
- a card with the repository already chosen. Three fields and no more: the repository, a title,
156
- and what Claude should do when it starts. The prompt can be left empty — nothing stops you from
157
- starting the session and typing straight into Claude Code.
167
+ a story with the repository already chosen. Two fields and no more: the repository and a title.
168
+ Nothing is asked about what the story is for, because both ways out of the dialog open a terminal
169
+ and you say it there. (With a backlog behind the board the `+` at the left is a menu of two — a
170
+ story typed here, or an epic told to a terminal — the dialog gains a field for the story's epic,
171
+ and the two buttons are *Discuss* and *Quick Start*. Editing a story that exists adds a list of
172
+ **notes**, which sit on the post-it for you to read and are never sent to Claude Code. It is
173
+ written out [below](#the-two-views).)
158
174
 
159
175
  The repository has to be **picked from the list** (searchable, most used at the top; arrow keys
160
176
  to move, Enter takes the highlighted row): a name typed by hand does not count. On leaving the
@@ -168,19 +184,26 @@ k0 makes **no network requests**. Not one, not even for a font.
168
184
  spaces, and the capitals you typed stay where you put them — `fix api` becomes `Fix-Api`, while
169
185
  `Fix API` stays `Fix-API`. What you see in the field is exactly the name the session will have.
170
186
 
171
- - **the pencil** (top right of a card) — the only way to open the editor: clicking the card
172
- itself does nothing. On a card that is already finished, where there is nothing left to edit,
187
+ - **the pencil** (top right of a story) — the only way to open the editor: clicking the story
188
+ itself does nothing. On a story that is already finished, where there is nothing left to edit,
173
189
  the **bin** takes its place.
174
190
 
175
- Changing the title — only the title; the prompt has nothing to do with it — **immediately**
176
- rewrites the name in the window's title bar, even while the session is running. Inside Claude
177
- Code the real name catches up when the session ends: while the process is alive the transcript
178
- already has an owner, and it would write the old name back over ours.
179
-
180
- - **Start** — opens a new terminal window, runs `claude` in the right repository under the card's
191
+ Changing the title — only the title; the prompt has nothing to do with it — renames the session
192
+ too, in three places at three moments. The window's title bar, **immediately**, session running
193
+ or not. The session itself, if it is still running, **the first time you look at it**: when that
194
+ window is the one in front of you and Claude Code is sitting idle with nothing under the cursor,
195
+ k0 types `/rename` with the new name into it and presses Enter — you will see the command go by.
196
+ It never brings the window up to do that: the keyboard is yours, and a terminal jumping up while
197
+ you type somewhere else would take your next words. And the list of sessions you can resume,
198
+ **when the session ends** — while the process is alive the transcript already has an owner, and
199
+ it would write the old name back over ours. On Linux and Windows the second of the three is
200
+ missing, and `k0-board doctor` says so: there the name catches up when the session ends. The
201
+ same happens when a skill changes the title through the API.
202
+
203
+ - **Start** — opens a new terminal window, runs `claude` in the right repository under the story's
181
204
  name, and puts the prompt in it. You press Enter.
182
205
 
183
- The session is **born in plan mode**, always. On the board the card turns **Planning** as soon
206
+ The session is **born in plan mode**, always. On the board the story turns **Planning** as soon
184
207
  as it gets to work, and amber **Needs approval** when the plan is ready. If you need something
185
208
  else, shift+tab as usual. **Resume** forces nothing: that session already had a mode, and it
186
209
  comes back as it was.
@@ -189,6 +212,11 @@ k0 makes **no network requests**. Not one, not even for a font.
189
212
  never asking anything are two things Claude Code does not do together — the why is
190
213
  [further down](#the-traps).
191
214
 
215
+ Every session, new or resumed, is also born **with Claude Code's task list switched on**. On a
216
+ newer model Claude Code leaves it off unless it is told otherwise, and the commands that plan,
217
+ work and check keep a task per step — so without it they would be asking for a tool that is not
218
+ there.
219
+
192
220
  The window is born **centred on the screen you are using**, at 86% of the free space: the same
193
221
  margin on all four sides, never under a menu bar or a dock. Open more than one and they stack
194
222
  in the middle — double click brings the one underneath back.
@@ -201,12 +229,16 @@ k0 makes **no network requests**. Not one, not even for a font.
201
229
  it. It is what stops you losing track of which window is which.
202
230
 
203
231
  - **Resume** — appears once the terminal has been closed, by you or by k0 after a long silence: it
204
- reopens the same conversation exactly where it was. The card's prompt is **not** put back in —
232
+ reopens the same conversation exactly where it was. The story's prompt is **not** put back in —
205
233
  that conversation answered it hours ago, and typing it in again would be at best something stale
206
234
  in the way.
207
235
 
208
236
  - **Done** — closes the work **and its terminal**, with no questions: undo it with **Reopen**, and
209
- pick the conversation up again with **Resume**. It is not on backlog cards: they never started.
237
+ pick the conversation up again with **Resume**. On a story that has never been started there is
238
+ no terminal to close, and the button is there anyway as long as there is a backlog behind the
239
+ board — a story planned here and then worked on in a terminal you opened yourself has to be
240
+ closable, and `Done` is the only thing in k0 that closes one. With the backlog switched off it
241
+ is not drawn on those stories at all.
210
242
 
211
243
  The session is stopped first and only then is the window closed. Closing a window with `claude`
212
244
  still inside it makes macOS put up the "terminate running processes" dialog, and the window does
@@ -214,7 +246,7 @@ k0 makes **no network requests**. Not one, not even for a font.
214
246
 
215
247
  - **Close** — a link at the end of the row, quieter than the buttons because it is the one you
216
248
  reach for least: it closes the terminal and **not the work**. The session is stopped, its window
217
- goes, and the machine gets the memory back; the card stays exactly where it is, with the colour
249
+ goes, and the machine gets the memory back; the story stays exactly where it is, with the colour
218
250
  it had — the one asking you something stays red, the one holding a plan up stays amber, the one
219
251
  at your turn stays yellow — and **Resume** takes it from there. It is what a dozen windows open
220
252
  and a computer running out of air are answered with.
@@ -222,9 +254,9 @@ k0 makes **no network requests**. Not one, not even for a font.
222
254
  It is **not there while the session is working**: stopping one mid-thought is not memory saved,
223
255
  it is work lost. Wait for it to come back to you, and then close it.
224
256
 
225
- The only thing that asks for confirmation is throwing a card away.
257
+ The only thing that asks for confirmation is throwing a story away.
226
258
 
227
- Cards reorder themselves inside a column: first the ones waiting for you, then the ones grinding
259
+ Stories reorder themselves inside a column: first the ones waiting for you, then the ones grinding
228
260
  away, backlog at the bottom, and among equals the most recent first.
229
261
 
230
262
  ### Moving around
@@ -261,16 +293,16 @@ that is waiting for you is the opposite of what the board is for. A terminal sim
261
293
  **Your turn** is not one of those: it is the resting state of every window you have not closed,
262
294
  and a session you finished with three weeks ago would otherwise hold its column at full width for
263
295
  ever. It folds like anything else — and folding closes nothing, so the terminal is still open and
264
- the card is still exactly where you left it. And **nothing folds while you are looking at it**: within one visit the set of columns can only grow, and the board tidies itself
296
+ the story is still exactly where you left it. And **nothing folds while you are looking at it**: within one visit the set of columns can only grow, and the board tidies itself
265
297
  on the next reload, so a column never disappears out from under your hands.
266
298
 
267
299
  **The last two columns on the right are `Old` and `Others`**, and they are the same list twice
268
300
  over: a `+`, a name and the git mark, in alphabetical order. `Old` is the repositories that have
269
301
  work on the board, just not lately; `Others` is the ones that have no column because they have no
270
- cards at all. **Click a row in `Old` and the column comes back** at full width for the rest of the
302
+ stories at all. **Click a row in `Old` and the column comes back** at full width for the rest of the
271
303
  visit — with everything that was in it, which is why the row itself says nothing about how much
272
304
  that is or how long it has been there. Both columns are also there for the same two things:
273
- getting into the files of a directory you are not working on, and giving birth to the first card
305
+ getting into the files of a directory you are not working on, and giving birth to the first story
274
306
  there with the `+`.
275
307
 
276
308
  Next to a column's `+` there is one more button, which **puts that column away now** instead of
@@ -281,18 +313,18 @@ back to your turn every few seconds and it would spend the session blinking.
281
313
  Unlike the automatic fold, this one is remembered across reloads, until you fetch the column back
282
314
  or something in it wakes up. It **closes nothing**: no session is stopped and no terminal is
283
315
  shut. It is the board that gets smaller, not the work — what closes a session is `Close` or `Done`
284
- on a card.
316
+ on a story.
285
317
 
286
318
  ### The git mark
287
319
 
288
- On every card, next to the repository name, and next to every column name, one symbol says
320
+ On every story, next to the repository name, and next to every column name, one symbol says
289
321
  whether the work is safe: a **dot** with how many files, if there is work that is nowhere yet; an
290
322
  **up arrow** with how many commits, if it is committed but not pushed; a faded **tick**, if
291
323
  everything is saved. Hover to read it in full — branch, files, commits, and how many of those
292
324
  commits belong to that session. **Click it and the files open.**
293
325
 
294
- A card running in an **isolated worktree** has a working tree of its own, so the mark is really
295
- its own. A card working in the base repository shares the working tree with everybody — there the
326
+ A story running in an **isolated worktree** has a working tree of its own, so the mark is really
327
+ its own. A story working in the base repository shares the working tree with everybody — there the
296
328
  dot belongs to the repository, and the only thing that belongs to the session is the commits made
297
329
  since it started, which k0 counts by remembering where `HEAD` was at that moment.
298
330
 
@@ -325,8 +357,9 @@ that asked for it, close every session, restart k0 itself — the server stays u
325
357
  stays green. This is the whole reason it exists: a dev server started inside a session belongs to
326
358
  that session, and dies with it.
327
359
 
328
- **k0 never asks the server whether it is up.** It makes no network requests, here as everywhere
329
- else. "Up" means the process is alive *and* the operating system says it is holding a TCP port
360
+ **k0 never asks the server whether it is up.** Nothing here opens a socket — the one request k0
361
+ makes goes to npm, and it is about versions, not about you. "Up" means the process is alive *and*
362
+ the operating system says it is holding a TCP port
330
363
  open. That is stronger evidence than a reply would be, and it is where the port in the tooltip
331
364
  comes from — k0 never guesses a port, it reads the one your server actually chose.
332
365
 
@@ -339,6 +372,478 @@ as off.
339
372
 
340
373
  ---
341
374
 
375
+ ## The backlog
376
+
377
+ A post-it used to be a name and a prompt. That is enough to start a session and nothing like
378
+ enough to remember why you started it: three weeks later the title says `Fix-Invoicing`, and the
379
+ half hour that decided what *fixed* meant has scrolled off the top of a terminal you have since
380
+ closed.
381
+
382
+ The backlog is the rest of it. Same board, same notes, same gestures — what is added is what the
383
+ work is *about*: what it belongs to, what was settled while you were talking about it, what has
384
+ to be true before it can be called finished, and a check that holds the finished thing up against
385
+ all of that before you are allowed to tick it off.
386
+
387
+ **The board is the menu; the commands are the engine.** Every story says what the one next thing
388
+ to do with it is — *Discuss*, *Plan*, *Work* — and pressing that opens a terminal with
389
+ the command already in it. The work happens there, in Claude Code, and you do not come back to the
390
+ board until it is finished. Almost nothing here is typed into a form.
391
+
392
+ If you want the argument rather than the manual — why a decision has to be an object, what a
393
+ round of questions is for, what the counter-check is really checking — it is in
394
+ [docs/method.md](docs/method.md), and it is a shorter read than this section.
395
+
396
+ ### Before anything else: the commands have to be on your machine
397
+
398
+ Everything below runs on ten commands you type at Claude Code, and Claude Code looks for a
399
+ command in exactly two places: **the repository you have open**, and **your own
400
+ `~/.claude/skills/`**. Neither of those is where npm puts k0. So a command that was not copied out
401
+ is a command that does not exist, however carefully it was written — and every button on the board
402
+ that offers to run one leads nowhere.
403
+
404
+ Copying them out is **one question, asked by the installer**, right after it starts the service:
405
+
406
+ ```
407
+ /k0-epic — an epic, discussed in rounds, then a tree of stories
408
+ /k0-story — one story, straight onto the board
409
+ …
410
+ Install 11 commands and the mod for Claude Code? (Y/n)
411
+ ```
412
+
413
+ Say yes and they are there in every repository you ever open. It is worth saying plainly what
414
+ happens if you do not, because it is what happened to this feature the first time round: the
415
+ commands were written and they worked — inside a clone of k0, and nowhere else on the machine.
416
+ From any other repository the board offered *Discuss*, the terminal opened, and Claude Code had
417
+ never heard of `/k0-discuss`. The whole backlog was invisible for want of one copy step.
418
+
419
+ **If you are not sure you said yes, run `npx k0-board@latest` again.** It asks only about the ones
420
+ that are missing, so somebody who already has them is not asked at all, and somebody who said no
421
+ in a hurry gets the question back. `ls ~/.claude/skills` answers it too.
422
+
423
+ If you **cloned this repository** rather than installing the package, they are already in its
424
+ `.claude/skills/` and there is nothing to do — but only while you are working *in this clone*.
425
+ Copy them out anyway if you use them anywhere else.
426
+
427
+ ### A day with it
428
+
429
+ **You open the board.** Every story that has something to do carries **one button, first in the
430
+ row, saying what that is**: **Discuss**, **Plan**, **Work** — in that order, because that is the
431
+ order the work goes in — or **Resume**, when a terminal was opened on it and then closed. Hover it
432
+ and it says why this and not something else: *It has been discussed and has no plan yet*. There is
433
+ one button and never a menu, and there are three words on the list and no more.
434
+
435
+ There is also a story that carries **no** button, and that is an answer too. A session that is
436
+ running needs nothing suggested about it — the terminal is where the work is, and a double click on
437
+ the note goes there. A story waiting for you to look it over is waiting for a person. A story that
438
+ is finished is finished. Filling any of those in with a command would be k0 inventing work.
439
+
440
+ k0 works that out and the page never does. It is the same reasoning `/k0-next` does, in the same
441
+ place, so the button on the note and the answer the command gives can never drift apart.
442
+
443
+ **You press it.** A terminal opens in that repository and `/k0-plan K42` — the line you would have
444
+ typed yourself — goes in with it, already sent: k0 wrote that line out of a button you pressed, so
445
+ there is nothing on it for you to read over first, and a prompt left sitting unsent under the
446
+ cursor is a window that did nothing.
447
+
448
+ **Or you take the short way in.** **Quick Start** is the other road out of a story and it is not
449
+ the same road: it opens a terminal on that repository with *nothing* in it and leaves the typing to
450
+ you. That is the whole of it — no discussion, no plan, no command. It sits at the end of the row as
451
+ a quiet link on a story that has a suggestion, and it is the plain button on one that has not.
452
+
453
+ Only `/k0-work` counts as the work having begun. Press *Discuss* or *Plan* and the story stays
454
+ where it was until the discussion or the plan moves it itself — otherwise walking away from a
455
+ discussion half way through would leave a story sitting in `Working` with nothing worked on.
456
+
457
+ **You work in the terminal, and only in the terminal.** The discussion asks its rounds and writes
458
+ each one down as it is answered; the plan comes back for your approval with the standing decisions
459
+ written into it as constraints; `/k0-work` opens a worktree, does the work, keeps the log, and
460
+ merges it back; `/k0-verify` walks the result past every decision one at a time. None of that
461
+ needs the board. You can leave the tab open and watch the rounds land — it follows a live
462
+ discussion once a second — but nothing asks you to.
463
+
464
+ **You come back, and the button has moved on.** A story you discussed now says *Plan*. One you
465
+ planned says *Work*. One whose terminal you closed says *Resume*, and picks the conversation up
466
+ where it was rather than starting a second one beside it.
467
+
468
+ **Double click the note to go where the work is.** Its terminal if one is running; the conversation
469
+ it left behind if the terminal was closed; a fresh session if there was never one. It is the same
470
+ gesture on every note, which is what makes it worth having — and if the window has been closed by
471
+ hand while the session is still thinking, k0 goes and looks for it by name before it tells you
472
+ anything, and offers to open it again when there is really nothing left to find.
473
+
474
+ **Done is yours and nothing else's.** No command sets it and no gesture sets it: when the work is
475
+ really finished you press **Done** on the note, and it closes the terminal with it. A story that
476
+ came through its counter-check clean is offered no command at all — there is nothing left for one
477
+ to do, and the only thing in front of it is you pressing Done. `/k0-verify` and `/k0-split` are
478
+ still there and still do what they always did: they are commands you type, on the days you want
479
+ them, rather than advice the board pushes at you.
480
+
481
+ **Things arrive during the day, and they do not interrupt this.** Something you already know you
482
+ want is `/k0-story` in whatever terminal you have open — you say it, it lands on the board with a
483
+ key of its own, and adding *and start it* opens the session in the same breath. Something big
484
+ enough that you do not yet know what it is made of is `/k0-epic`: ten minutes of questions in
485
+ rounds, everything settled written down as it is settled, and only at the end a tree of stories
486
+ proposed for your approval — it creates none of them until you have said yes. Both are on the
487
+ board's `+` as well, which is a small menu now: **Story** opens the dialog you know, with one
488
+ field added for its epic; **Epic** asks which repository and then opens a terminal running
489
+ `/k0-epic`, because an epic is told, not typed.
490
+
491
+ ### The two views
492
+
493
+ The switch in the top bar, in among the filters, says **Kanban** or **List**. It changes the shape
494
+ of what you are looking at and never what you are looking at: the state pills, the repository and
495
+ the epic lane apply to both, so switching back and forth is free and nothing appears or vanishes
496
+ under you.
497
+
498
+ **Kanban is for working.** It is the board you already know — one column per repository, notes
499
+ that reorder themselves by who is waiting for you. With a backlog behind it a note grows four
500
+ marks and no more: its **key**; the **epic** it belongs to, as a small label in the epic's own
501
+ colour, worked out from the key so there is nothing to choose and nothing to keep in step; a
502
+ **flag** in the bottom corner; and a warning when something it **waits on** is not finished.
503
+
504
+ The flag is put on and taken off **from the note itself** — it is the mark and the target both,
505
+ and it mirrors the pencil at the other corner. It is invisible until the pointer is on the note,
506
+ because an outline sitting on every note all the time is a mark that is everywhere and therefore
507
+ marks nothing. Once it is on it stays on, and the note takes a border and its key and title take
508
+ the flag's colour with it: the point of flagging something is finding it again from across the
509
+ room, and a fifteen-pixel glyph cannot be seen from there.
510
+
511
+ **Click an epic's label and the board becomes that epic.** A strip appears under the top bar with
512
+ its key, its title, its repository, a progress bar and `4 of 11 done`, and the way back out. Inside
513
+ the lane the label is not drawn on the notes — everything in here belongs to the same epic, and
514
+ saying so eleven times says nothing. The lane survives a reload: going into an epic is a decision
515
+ about where you are working, and a page that forgets it every time you press F5 is a page you stop
516
+ going into. The progress is counted over the epic's stories, not over the notes a filter left on
517
+ screen, and it is not weighted: eleven stories with one done is 1 of 11, however big the one was.
518
+ Anything else is an estimate, and an estimate here is a lie with a progress bar drawn round it.
519
+
520
+ **List is for planning.** The same stories as rows, three levels deep and every repository at
521
+ once: a thin heading per repository, an epic that opens and closes with its progress bar — and,
522
+ while a discussion is running on it, which round that is on — and under it its stories, with tasks
523
+ indented beneath the story they were cut from. Stories belonging to no epic are grouped at the
524
+ end. A row carries key, title, state, flag, how many decisions are still standing, how much of
525
+ the checklist has passed, and the same next-step button. Which epics you left open is remembered.
526
+
527
+ **Click a row and the story opens beside it**, not underneath: the counter-check first, then why
528
+ it exists, the rounds with their questions and answers, the decisions with the verdict each one
529
+ got, the plan, the checklist and the log — with a line under the title saying both what it waits
530
+ for and what is waiting for it, each key a way into that story. Beside rather than below, because
531
+ the point of a list is to run down it, and a panel that pushes the rows off the bottom of the page
532
+ loses the thing you were comparing against. Click an epic and the epic opens the same way — the
533
+ rounds it was argued out in, and the decisions every story under it is held to. That is the only
534
+ place that conversation can be watched, because it happens before a single story of it exists.
535
+
536
+ Two things in this view write rather than read, and they are the two you do while *looking* at a
537
+ backlog rather than while working on one: **the next step, started from the end of a row**, and **a
538
+ checklist line you have just watched work with your own eyes** — ticked in the panel, and recorded
539
+ as yours rather than the model's, which is the difference the checklist exists to keep.
540
+
541
+ **Dragging a row moves it.** Up and down to change the order, onto another epic's heading to move
542
+ it there, onto `No epic` to take it out of one. That is the whole of it: **dragging never changes
543
+ state.** A state is a road the work walks, and walking it by dropping a piece of paper somewhere
544
+ was always the wrong gesture — states move from the terminal, and from the Done button.
545
+
546
+ ### The ten commands
547
+
548
+ Ten you type, and the installer offers eleven — these ten plus
549
+ [`/k0-import`](#filling-the-board-with-what-you-have-already-done) — and one more thing that is not a
550
+ command at all, [the `k0-links` mod](#what-claude-points-at-one-click-away). `/k0-whatsnew` and
551
+ `/k0-changelog` are deliberately not on that list: k0 runs those two itself, out of its own
552
+ directory, and you never type them.
553
+
554
+ | | |
555
+ |---|---|
556
+ | `/k0-story` | one story, straight onto the board — the fast door |
557
+ | `/k0-epic` | the long way in: rounds, decisions, then a tree of stories you approve |
558
+ | `/k0-discuss` | the same rounds against a story that already exists |
559
+ | `/k0-split` | a story that will not close, cut into tasks that inherit its decisions |
560
+ | `/k0-plan` | plan mode, with the standing decisions written into the plan as constraints |
561
+ | `/k0-work` | the worktree, the work, the log as it goes, and the merge back |
562
+ | `/k0-ultracode` | a whole epic, or one story, run by a manager with agents under it |
563
+ | `/k0-verify` | the counter-check |
564
+ | `/k0-next` | what to pick up now, and why |
565
+ | `/k0-order` | priority and dependencies, dictated: *K51 to the top, K42 waits on K37, flag K19* |
566
+
567
+ These ten are also the only ten a button on the board may start. They are written out by name in
568
+ the server and checked against that list before anything reaches a command line — and it is a list
569
+ and not a directory listing on purpose: a folder arriving in your skills directory, from a clone or
570
+ a package or an installer, must not thereby become something a web page can ask k0 to run.
571
+
572
+ `/k0-next` is worth one sentence of its own, because the answer is not the model's. k0 works out
573
+ what to pick up — a live session first, then something in `Review` and the one that has been
574
+ sitting there longest, then what is not waiting on unfinished work, then the flag, then how far
575
+ along it is, then the order you put the board in — and hands over the story with the sentence that
576
+ says why. Ask twice and you get the same answer, which is not true of anything a model reasons out
577
+ each time.
578
+
579
+ **Dependencies are a note, not a lock.** Nothing refuses to start a story that is waiting on
580
+ another one: the note is marked, the button that starts the work asks you once and then goes
581
+ ahead, and the story sinks down `/k0-next`. A backlog that will not let you work on what you want
582
+ is a backlog you stop using.
583
+
584
+ ### An epic, a story, a task
585
+
586
+ **A story is one post-it**, and it is the thing you work on. Everything the board already does it
587
+ still does: a story opens a terminal, drives the session in it, and says what that session is
588
+ doing.
589
+
590
+ **An epic is a reason** with several stories under it — an area, a feature, a rewrite. It lives in
591
+ exactly one repository, because a piece of work that spans two of them is two pieces of work with
592
+ a wish in the middle.
593
+
594
+ **A task is a story that was cut out of another one.** It is not a different kind of thing: same
595
+ table, same rules, same key — a story that turned out too big to close gets split, not turned into
596
+ another species. A task takes its parent's epic unless you give it one of its own, because a task
597
+ planned outside the epic its parent sits in would be planned blind to every decision that shaped
598
+ the whole thing.
599
+
600
+ ### The key, and where it sits
601
+
602
+ Every epic, story and task gets a **key**: `K` plus a number, `K42`. It is counted per repository,
603
+ shared between epics and stories, and it is **never reused and never reassigned** — not when the
604
+ story moves under another epic, not when you delete it, not when the repository is renamed. Two
605
+ repositories can both have a `K42`, and that is intended: a key means something inside its
606
+ repository and nowhere else. Move a story to another repository and it is given a key from *that*
607
+ repository, rather than carrying a number into a place that already has one.
608
+
609
+ Beside it there is a **position**: `1.12.1`. The first epic, its twelfth story, that story's first
610
+ task. The position is worked out fresh every time it is shown and never stored, so it cannot
611
+ disagree with the tree it describes — move a story and its position moves with it.
612
+
613
+ The key is the name you say out loud; the position is where the thing is sitting today. When you
614
+ say `K42` to a command it knows what you mean, whatever the board has been rearranged into since.
615
+
616
+ ### Why a story is not a session
617
+
618
+ This is the one change underneath everything else, and it is worth a paragraph.
619
+
620
+ A card used to *be* a session: one note, one conversation, and ticking the note off ended both. So
621
+ a piece of work you came back to twice was two notes, and the first one was a note about a
622
+ conversation nobody could remember.
623
+
624
+ Now a story keeps **every session it has had**, one at a time, over as long as it takes. And it
625
+ carries two different clocks, which used to be one column fighting itself:
626
+
627
+ - **the story's state** — `Backlog` · `Discussed` · `Planned` · `Working` · `Review` · `Done` —
628
+ which is where the *work* is;
629
+ - **the session's status** — working, planning, holding a plan up, asking you something, your turn
630
+ — which is what a *terminal* is doing this second.
631
+
632
+ No transition is required. Any state may follow any other, and `Backlog` straight to `Done` is a
633
+ legal thing to do that nothing will warn you about — a backlog that argues with you about the road
634
+ is a backlog you route around. `Working` sets itself when a session goes live. `Review` is where
635
+ `/k0-verify` puts a story when it starts checking it. **`Done` is only ever yours**: nothing in k0
636
+ sets it, and the Done button on the note is still what confirms it.
637
+
638
+ The post-it itself still draws one word and one colour, exactly as before — the two clocks put
639
+ back together. Nothing about the board you know got louder.
640
+
641
+ ### Rounds, and why they say how many are left
642
+
643
+ A round is one small group of questions — four at the most — with your answers written down before
644
+ the next one is asked.
645
+
646
+ Each round opens by saying where it is: **"Round 3 of about 8"**. The number comes from counting
647
+ the things where a different answer would produce different work, and it is recalculated after
648
+ every answer, because answers both close questions and open them. When it moves, it says so in the
649
+ same breath — *round 4 of about 6, two of the questions answered themselves* — and never drifts in
650
+ silence. A count that quietly becomes twelve after promising eight is a count you stop believing,
651
+ and once you stop believing it you start answering to get it over with.
652
+
653
+ It stops when no remaining question would change the work, which is stricter than it sounds and is
654
+ the only test being applied: a question worth asking is one whose two answers lead to two different
655
+ builds. There is a hard ceiling of **fifteen rounds**. At fifteen it stops wherever it is, shows
656
+ you the list of what it never got to in your own words, and says the story is recorded as it stands
657
+ and can be picked up whenever you like. A discussion that reaches fifteen is telling you the story
658
+ is really two, and it says that as well.
659
+
660
+ **Every round is written to k0 before the next question is asked.** Not at the end, not on a save.
661
+ A terminal that dies at round three does not take the first three with it, and neither does a
662
+ session that runs out of context in the middle — which is the one that actually happens, and the one
663
+ nobody thinks about until the second time.
664
+
665
+ ### Decisions
666
+
667
+ What comes out of the rounds is not a summary. It is a row of **decisions**, one complete sentence
668
+ each, numbered — `D1`, `D2` — and written in your language, about behaviour rather than about
669
+ implementation. A decision that names a function is one you cannot check without opening the code,
670
+ and six months from now you will not open the code.
671
+
672
+ A decision is **never rewritten**. When you change your mind, the new decision *supersedes* the old
673
+ one and both stay, the old one crossed through and pointing at what replaced it. This is the whole
674
+ reason they are objects and not paragraphs: the point is to hold the work up against what was
675
+ actually said at the time, and prose you can edit afterwards proves nothing.
676
+
677
+ An epic's decisions belong to the epic, and every story under it **inherits** them rather than being
678
+ handed a copy. They are shown with the epic's key in front — `K7·D3` — so it is obvious a rule came
679
+ down from above and applies to everything in the lane. Inheriting rather than copying is what makes
680
+ changing your mind work: supersede `K7·D3` on the epic and it is superseded for all eleven stories
681
+ at once, where eleven copies would have forked the first time one of them was touched.
682
+
683
+ An epic is discussed and decided before a single story of it exists, which is why its decisions
684
+ have to be able to live on the epic. That is not a detail: it is the main way anybody uses this.
685
+
686
+ And when something you say now contradicts something you settled earlier, the discussion **stops
687
+ there and asks** — naming the decision it clashes with, saying which of the two it thinks should
688
+ stand, and why. Writing both down and carrying on is how you end up with two rules that disagree
689
+ and no way of knowing which one the work followed.
690
+
691
+ ### The counter-check
692
+
693
+ Here is what this is for.
694
+
695
+ You explain a piece of work to a model, properly, for half an hour. It asks good questions — some
696
+ of the answers surprise you, because you did not know what you wanted until it asked. It says it
697
+ has understood, and it has: the summary it gives back is better than the one you would have
698
+ written. Then it builds something that quietly contradicts half of it. Not all of it, and not
699
+ obviously. One thing you settled at minute twenty is simply not there, and something you ruled out
700
+ is there instead. You notice three days later, and by then you cannot even prove you said it.
701
+
702
+ That half hour did not merely fail to help. It cost you the half hour and it bought a false
703
+ confidence that the thing was understood, which is worse than knowing it was not, because you
704
+ stopped watching.
705
+
706
+ `/k0-verify` is the thing that was missing. When the work is done it takes the decisions **one at a
707
+ time** — the story's own and the ones it inherited — and records a verdict for each: **kept**,
708
+ **violated**, or **not applicable**, with the evidence. A file and a line, or a sentence saying why
709
+ the decision does not apply here. Never a summary standing in for the row, because a summary is
710
+ where the one that was broken goes to hide.
711
+
712
+ Three rules make it worth something rather than a ceremony:
713
+
714
+ - **A run is the whole set or it is not a run.** One that answers nine decisions of ten is refused
715
+ and told which one it passed over. `na` is a verdict; silence is not. A check that reports a
716
+ clean sweep of whatever it happened to look at is worse than no check.
717
+ - **A run never overwrites the one before it.** Runs are numbered and they all stay, so you can see
718
+ that something was broken, then fixed, rather than only that it is fine now.
719
+ - **A story cannot be marked `Done` while a decision a run found broken has not been answered
720
+ since.** It is read decision by decision and not run by run: a later run that finds the same
721
+ decision kept closes it, and a later run that says nothing about it, or says it does not apply,
722
+ leaves it exactly where it was. This is the only refusal in the whole feature, and it applies to
723
+ whatever is asking: the Done button on the note, the one at the end of a row in the list, a
724
+ command. It comes back as a sentence saying which decision, from which run, and what to do about
725
+ it.
726
+
727
+ There are exactly two ways to answer it, and both are honest: **put the work right and run the
728
+ counter-check again**, or **supersede the decision** if it turns out the decision was the thing that
729
+ was wrong. What you cannot do is talk past it: a story with a broken decision is drawn on the board
730
+ so that it cannot be scrolled past, and pressing Done on it comes back with the sentence rather than
731
+ the story closed.
732
+
733
+ There is also a **checklist** on the story — what has to be true for it to be finished. `/k0-verify`
734
+ does itself everything a machine can do, runs the project's tests, drives the browser when the thing
735
+ is a web application, and leaves you only the lines that genuinely need a person.
736
+
737
+ ### `/k0-work` and the worktree
738
+
739
+ `/k0-work` gives the session a working copy of its own: a git worktree under
740
+ `<repo>/.claude/worktrees/`, on a branch named after the story, opened **from the branch you are
741
+ standing on** — not from `main`, not from `origin`. You keep working in the repository, the session
742
+ works next door, and at the end its branch comes back in as one merge commit and the copy is
743
+ destroyed. The folder is kept out of git's way through `.git/info/exclude`, never by writing in
744
+ your `.gitignore`.
745
+
746
+ Everything the board starts opens in the story's **own repository**, never in a worktree. `/k0-work`
747
+ makes one when it needs one, and it is the only command here that does: the others talk about the
748
+ story rather than change it, and a discussion held inside somebody else's working copy is a
749
+ discussion about a copy.
750
+
751
+ It will not open one over uncommitted work, and it says how much there is. And three things it
752
+ never does, each of which has already cost somebody a day:
753
+
754
+ - **It never pushes and never opens a pull request.** The merge stops on this machine. Publishing
755
+ is a decision you make when you are ready to make it.
756
+ - **It never resolves a conflict.** There is no way for a program to tell a conflict it resolved
757
+ correctly from one it resolved plausibly, and taking a side to make the command succeed throws
758
+ away something somebody typed. A conflict stops everything and says which files.
759
+ - **It never runs tests, a build or a dev server in there.** A worktree copies the code but not the
760
+ untracked files around it, so the `.env` somebody copies across carries the *base* repository's
761
+ port — and a test runner that finds a server already listening on it uses that one, goes green,
762
+ and tells you the new code passes when what it tested was the old checkout. Tests run on the base
763
+ branch, after the merge.
764
+
765
+ That last rule has one honest edge. Merging commits whatever the session left pending, a commit
766
+ runs your repository's own hooks, and a `pre-commit` hook that runs the whole suite is normal. k0
767
+ does not step round it with `--no-verify` — a commit that only went through because k0 avoided your
768
+ hooks has not been checked at all — so the hook does run, next door, with the wrong `.env` beside
769
+ it. k0 says so when it happens rather than being quiet about it.
770
+
771
+ ### `/k0-ultracode`: the same work, with a manager over it
772
+
773
+ On a note that is ready to be worked on, next to **Work**, there is a quieter word: **Ultracode**.
774
+ It is the same act at a larger size. One session becomes a **manager**: it cuts the story's plan
775
+ into **assignments**, gives each one to an **agent** working in a copy of the repository of its own,
776
+ brings the work back one piece at a time, and only then — on your branch, where the code on the disk
777
+ is the code that was merged — runs the tests, has the result read by an agent that wrote none of it,
778
+ and walks the story past every decision. It is offered on an epic too, from the epic's panel, and
779
+ that is what it is really for: story after story, each one finished before the next one starts.
780
+
781
+ Before it does anything it asks you two questions and never asks again. **How much rope** —
782
+ *interactive*, where every question an agent brings back reaches you while it is warm; *checkpoint*,
783
+ which stops at the cut, before the merge and on a red test run; or *autonomous*, which goes to the
784
+ end and comes back with the list of everything it decided on your behalf. And **how hard** — two,
785
+ three or five agents at a time, one repair attempt or two, one pair of fresh eyes or three. Both
786
+ answers go into the Log, so a terminal you closed halfway through is picked up again on the same
787
+ terms rather than on new ones.
788
+
789
+ What it does not do is the point of the shape. It never pushes. It never runs anything inside a
790
+ worktree, for the reason above. It never presses **Done** — the stories come back sitting in
791
+ `Review`, counter-checked, waiting for you. And it stops: the repair attempts are spent and then it
792
+ tells you what is still broken, having merged everything that works. A run that never ends is not
793
+ thoroughness, it is a run nobody can plan around.
794
+
795
+ ### The `.k0/` folder
796
+
797
+ Each repository with a backlog grows a `.k0/` folder: a `README.md` explaining itself, one file per
798
+ epic under `epics/`, one per story or task under `stories/`. A story file opens with its header —
799
+ key, epic, state, flag, what it waits on, the sessions it has lived through — and then
800
+ **Why**, the **Prompt**, the **Discussion** round by round, the **Decisions**, the **Plan**, the
801
+ **Verification** run by run with its checklist, and the **Log**. An epic's file is the same header,
802
+ its own **Why**, **Discussion** and **Decisions**, and then the list of its stories with a line
803
+ saying how far it has got.
804
+
805
+ The database is the source of truth and these are printed from it — whole, every time the story
806
+ changes, never diffed cleverly — so a file cannot end up claiming something the board does not. But
807
+ they are files, so they diff, they review, and they go in the commit with the work they describe.
808
+ Write in them if you like: anything you put under a heading k0 does not print is left exactly where
809
+ you put it, and so is a line you add to the header at the top and a note you leave under the title.
810
+
811
+ **Commit the folder.** It is the only copy of this that outlives the database, and it is the way
812
+ back: open a repository k0 has no stories for and it reads the folder in and rebuilds them, keys
813
+ and all. That is the reason the files exist at all — the rest is a pleasant side effect.
814
+
815
+ The folder is written **only** inside `.k0/` — never your `.gitignore`, never a line anywhere else
816
+ in your repository — and a test walks the tree afterwards to prove nothing else appeared. The one
817
+ other thing that ever writes into a repository is `/k0-work`, which you have to ask for: it is
818
+ written out in full under [What it reads, and what it never
819
+ does](#what-it-reads-and-what-it-never-does).
820
+
821
+ One thing to expect: the git mark on that column will go from a tick to a dot the day the folder
822
+ first appears. That is honest — there is something there that is not committed yet — and committing
823
+ it puts the mark back.
824
+
825
+ ### Switching it off
826
+
827
+ The whole feature is one line in `~/.k0/config.json`, the same file the idle timeout lives in:
828
+
829
+ ```json
830
+ { "backlog": false }
831
+ ```
832
+
833
+ and the board is exactly the board it has always been: nothing extra on a note, no next-step
834
+ button, no Kanban/List switch in the bar, no lanes, **no `.k0/` folder created in any repository**,
835
+ and the commands say plainly that the backlog is switched off rather than reporting an empty one.
836
+ Telling somebody their backlog is empty when it is really turned off is the one answer worse than
837
+ no answer. The `+` goes back to being a plain `+` that opens the story dialog, with no menu behind
838
+ it and no epic on the form.
839
+
840
+ It is in that file and not in k0's database on purpose: a switch you would need `sqlite3` to reach
841
+ is not a switch. k0 re-reads the file whenever it changes, so nothing has to be restarted, and
842
+ deleting the line puts the default back. `"updateCheck": false` is its neighbour — [the one that
843
+ stops the npm question](#what-installing-it-changes).
844
+
845
+ ---
846
+
342
847
  ## The ChangeLog
343
848
 
344
849
  The git mark answers "is this safe" for one repository, right now. The **ChangeLog** answers a
@@ -359,7 +864,7 @@ page that comes up empty after every weekend is a page you stop opening.
359
864
  **Only what you touched in that window appears.** A repository that has been dirty since March
360
865
  and that you have not opened since is not news, and a summary that repeats it every morning is
361
866
  one nobody is still reading by Thursday. Something has to have happened there — a commit, a file
362
- saved, a card moved — before k0 will tell you what is still outstanding in it. And only **your**
867
+ saved, a story moved — before k0 will tell you what is still outstanding in it. And only **your**
363
868
  commits are counted: k0 asks git which email you commit with in that repository and shows that
364
869
  person's day, so a repository shared with other people still tells you about yours.
365
870
 
@@ -369,9 +874,10 @@ not believe the paragraph above it.
369
874
 
370
875
  ### Who writes it
371
876
 
372
- k0 does not. **k0 makes no network requests**, and that is worth more than a better paragraph: a
373
- model of its own would mean a key to keep, an account to configure, and your commit messages
374
- leaving this machine.
877
+ k0 does not. **Nothing about your work leaves this machine**, and that is worth more than a better
878
+ paragraph: a model of its own would mean a key to keep, an account to configure, and your commit
879
+ messages going out over a wire. The one request k0 makes is to the npm registry, asking after its
880
+ own version; it carries no commits, no repository names and no identifier.
375
881
 
376
882
  It does not need one. If you are running k0 you already have Claude Code installed, signed in and
377
883
  paid for — that is the whole point of the board — so the model is already here. k0 works out the
@@ -380,7 +886,7 @@ on the board, and there is nothing to set up: the skill that does the writing sh
380
886
  package, the same way `/k0-import` does.
381
887
 
382
888
  It is written **in your language**, without a setting anywhere, because it is written out of your
383
- own commit messages and card titles.
889
+ own commit messages and story titles.
384
890
 
385
891
  Nothing is saved. Every time you open the page it is written again, and changing the window
386
892
  writes it again — which is why there is no stale summary to clear and no history to prune.
@@ -390,11 +896,121 @@ saying why the rest is missing.
390
896
 
391
897
  ---
392
898
 
899
+ ## What's New
900
+
901
+ k0 updates by having its files replaced under it. You restart, everything looks the same, and
902
+ whatever changed is in a file called `CHANGELOG.md` that nobody opens. So the version you are
903
+ running drifts away from the one you learned, and the new thing sits there unused because you
904
+ never found out it was there.
905
+
906
+ A small **mark appears next to `k0`** in the top bar for exactly two reasons: k0 moved on while you
907
+ were not looking, or npm says there is a version newer than the one installed here. Hover it and it
908
+ says which. **It never opens the page by itself** — it sits next to the name and waits, and it goes
909
+ out when you have read the page, not when you close the tab.
910
+
911
+ The page says which two versions it stands between — *you had k0 0.3.1, you are running 0.4.0 now,
912
+ two versions later* — and then says what that means in prose, written by your own Claude out of the
913
+ changelog entries in between. Two controls, and both of them change who it is being written for
914
+ rather than what is in it: **the language**, and **how technical** — `Plain`, `Normal` or `Nerd`.
915
+ Both are remembered, because coming back to find the page in a language you do not read is the
916
+ whole page wasted.
917
+
918
+ Underneath, folded open from the first moment, are the changelog entries themselves, exactly as
919
+ they were written. While the prose is being written they are what there is to read; afterwards they
920
+ are what you check it against.
921
+
922
+ It is the same machinery as the ChangeLog, and it has the same shape: nothing is stored, no model
923
+ of k0's own, no key and no account — the Claude Code you already pay for does the writing, on this
924
+ machine. Nothing is downloaded either. k0 cannot update itself; the most it can do is say a newer
925
+ version exists, and leave `npx k0-board@latest` to you.
926
+
927
+ ---
928
+
929
+ ## Usage: what your sessions consumed
930
+
931
+ The icon with three bars, next to the ChangeLog's, opens a page that answers a question Claude Code
932
+ leaves you to guess at: **where did the week go?** You switch between models, between efforts,
933
+ between one agent and a whole workflow, and between accounts, and the only thing you ever see is a
934
+ limit arriving.
935
+
936
+ A week at a time, Monday to Sunday, with the arrows to go back:
937
+
938
+ - **what each day would have cost at the API price list**, stacked by model. With a subscription
939
+ you do not pay this — it is the one scale on which a Fable hour and a Sonnet hour can be put side
940
+ by side, and the page says so;
941
+ - **how full each account's weekly limit was**, as a line per account, and the five-hour limit as
942
+ it was last seen;
943
+ - the week split **by model and effort** (fast mode is a row of its own), by **who did the work** —
944
+ the conversation itself, its subagents, or a workflow's agents — by **repository** and by
945
+ **account**;
946
+ - and every **session**, the most expensive first: the model and effort it ran on, when it started,
947
+ how long Claude actually worked on your turns (not how long the window was open), its tokens, its
948
+ cost, its estimated share of the weekly limit, and how many times a limit stopped it. A session k0
949
+ started or imported links to its story, which opens on the board.
950
+
951
+ **It costs nothing to find out.** No model is asked and nothing goes over the network: Claude Code
952
+ already writes every reply's token counts, model and effort into the transcripts on your disk, and
953
+ k0 reads them as they grow — the history first, a few megabytes at a time so the board never
954
+ stalls, and after that once a minute. The first time, the page says how much history is still left
955
+ to read.
956
+
957
+ Two things are not in the transcripts, and the page is straight about both:
958
+
959
+ - **Which account a reply came from.** Claude Code only records the account signed in *now*. k0
960
+ writes down every change of account it sees from the moment it is running, and the statusline
961
+ snippet below writes down the account of every session it draws. Everything before that stays
962
+ **"Unknown account"** — it is not guessed.
963
+ - **How full the limits are.** Claude Code tells the statusline and keeps it nowhere else. So the
964
+ statusline has to write it down:
965
+
966
+ ### The limits: a few lines in your statusline
967
+
968
+ If you have a statusline command, add this to it, where it has read Claude Code's JSON from standard
969
+ input into `input` (Node, no packages; the same idea works in any language). It appends a line to
970
+ `~/.k0/usage/limits.jsonl` only when a number has changed, and never breaks the bar if anything
971
+ fails:
972
+
973
+ ```js
974
+ try {
975
+ const fs = require('fs'), path = require('path'), os = require('os')
976
+ const data = JSON.parse(input), rl = data.rate_limits
977
+ if (rl && (rl.five_hour || rl.seven_day)) {
978
+ const pick = (w) => (w ? { pct: w.used_percentage, resets_at: w.resets_at } : null)
979
+ const now = { five_hour: pick(rl.five_hour), seven_day: pick(rl.seven_day) }
980
+ const dir = path.join(os.homedir(), '.k0', 'usage'), seen = path.join(dir, '.last')
981
+ const sig = JSON.stringify([data.session_id, now])
982
+ let last = ''
983
+ try { last = fs.readFileSync(seen, 'utf8') } catch {}
984
+ if (sig !== last) {
985
+ const a = JSON.parse(fs.readFileSync(path.join(os.homedir(), '.claude.json'), 'utf8')).oauthAccount || {}
986
+ const account = { uuid: a.accountUuid, email: a.emailAddress, org_type: a.organizationType, tier: a.organizationRateLimitTier }
987
+ fs.mkdirSync(dir, { recursive: true })
988
+ fs.appendFileSync(path.join(dir, 'limits.jsonl'),
989
+ JSON.stringify({ at: Date.now(), session_id: data.session_id, account, model: data.model?.id, ...now }) + '\n')
990
+ fs.writeFileSync(seen, sig)
991
+ }
992
+ }
993
+ } catch {}
994
+ ```
995
+
996
+ Claude Code only passes the limits to the statusline on a subscription, and only after the first
997
+ reply of a session. Without the snippet the page works the same, with the limits chart empty and a
998
+ note saying why.
999
+
1000
+ The share of the weekly limit next to each session is an **estimate**, and marked with `≈`: the
1001
+ statusline says how full the week is, not who filled it, so each rise is shared among the sessions
1002
+ that account ran in that hour, in proportion to their cost.
1003
+
1004
+ The prices are Anthropic's published API rates, dated in the source. A model k0 does not have a
1005
+ price for is counted in tokens and shown as `?` in dollars — never as free.
1006
+
1007
+ ---
1008
+
393
1009
  ## The files of a session
394
1010
 
395
1011
  The git mark is also the door: clicking it opens a file viewer **in another tab**, and the board
396
1012
  stays where it is. Where there is no mark — a repository without git, or git that has not answered
397
- yet — a **lens** takes its place, so every card and every column still leads in.
1013
+ yet — a **lens** takes its place, so every story and every column still leads in.
398
1014
 
399
1015
  Files on the left, what they say on the right, and a divider in between that you can drag.
400
1016
 
@@ -403,6 +1019,18 @@ a real repository code is 95% of the files, and among two thousand `.tsx` files
403
1019
  were after cannot be found. This closes nothing off: a code file reached by a link inside a
404
1020
  document still opens, and so do images — and the configuration is one switch away, below.
405
1021
 
1022
+ A **generated directory** — `out/`, `dist/`, `build/` — is walked into like any other, and the
1023
+ documents in it are listed like any others: the PDFs, and the pages you open with a double click.
1024
+ A document is a document wherever it was made, and it has to be findable by name. What stays out
1025
+ is the configuration a build leaves lying there, and the directories that hold nothing anybody
1026
+ reads — `node_modules` and its like — which are not walked into at all.
1027
+
1028
+ There is **one exception, and only one**: where git is in charge, git decides. k0 reads a
1029
+ directory your `.gitignore` names only to go and fetch the finished documents from it — the PDFs,
1030
+ the Word files — never the pages, because a real site's ignored `dist/` is four thousand pages and
1031
+ not one of them is the file you went looking for. Where git names the directory itself, everything
1032
+ in it comes through, pages included.
1033
+
406
1034
  At the top come the **folders**, then the files, in three groups:
407
1035
 
408
1036
  - **Changed** — what this session has touched: files still hanging in the working tree plus the
@@ -503,9 +1131,14 @@ the summary in the chat says what it touched and **names the files already**. Cl
503
1131
  the top, paste that piece of conversation, press **Find the files**, and the list on the left
504
1132
  narrows to the files that text names.
505
1133
 
506
- It looks **only for the names written down**, not for the subject: no index, no server, no
507
- waiting — the file listing is already in the browser. The price is stated: a file the chat talks
508
- about without ever naming does not come out, and for that there is the search above.
1134
+ It looks **only for the names written down**, not for the subject: no index and no waiting — the
1135
+ file listing is already in the browser. The price is stated: a file the chat talks about without
1136
+ ever naming does not come out, and for that there is the search above.
1137
+
1138
+ One question does go out, and only one: when the text writes a name **in full** and the listing has
1139
+ no such file, the disk is asked about those names and no others. That is how a document under an
1140
+ ignored directory comes out of a paste — the listing never saw it, but a text naming a file names
1141
+ it whole.
509
1142
 
510
1143
  The results come in two groups, because they are two different degrees of certainty:
511
1144
 
@@ -536,10 +1169,45 @@ The hard part is not finding the names, it is choosing **which**. In a repositor
536
1169
  directory up, and so on to the top. If it is still ambiguous, **it does not become a link**:
537
1170
  better nothing than sending you to the wrong README.
538
1171
 
539
- Files the listing does **not** show open too. `out/`, `dist/`, `node_modules/` stay out of the
540
- listing — in a code repository they are generated — but in a directory of documents `out/` holds
541
- the real PDFs. When it is a document naming them, that file counts. Hidden directories really do
542
- stay out: `.claude/` is configuration, not something to read.
1172
+ Files the listing does **not** show open too. Where git rules, a directory your `.gitignore` names
1173
+ gives the listing only its finished documents — so a page under an ignored `dist/` is not in it.
1174
+ Named inside a document it still counts: the document said so, not the directory. Hidden
1175
+ directories really do stay out: `.claude/` is configuration, not something to read.
1176
+
1177
+ ### What Claude points at, one click away
1178
+
1179
+ The same idea, one step earlier: in the Claude Code session itself. Claude says "open
1180
+ `localhost:4321/projects/furniture/`", "the photos are in `docs/projects/sideboard-140/`", "the
1181
+ manual is `README.md`", or publishes an artifact and talks about it by its title — and in the
1182
+ terminal all of that was dead text. With the `k0-links` mod installed, and **while k0 is running**,
1183
+ everything the last reply pointed at is in a row **just above the prompt**, and **one plain click**
1184
+ on an entry opens it:
1185
+
1186
+ | | What the reply wrote | Opens in |
1187
+ |---|---|---|
1188
+ | 🌐 | an address — `https://…`, `localhost:4321/…`, `alessioragni.com/projects/…` | the browser, in a new tab |
1189
+ | 📁 | a folder, relative to the repository or written in full | Finder |
1190
+ | 📄 | a document the viewer shows — Markdown, HTML, text, PDF, Word… | this viewer, in a new tab |
1191
+ | ✦ | the title of an artifact this session published | its claude.ai page |
1192
+
1193
+ Code files and a repository's own name stay out of the row: they are not places you go to. A
1194
+ domain counts as an address only with a path after it — `alessioragni.com` alone is usually the
1195
+ name of a repository.
1196
+
1197
+ **Claude's reply is left exactly as Claude Code draws it.** The macOS Terminal cannot open a link
1198
+ drawn inside the text — it shows the words, and a click does nothing — and redrawing every reply to
1199
+ get around that would have changed a screen that works. The row is the mod's own space, and its
1200
+ entries are buttons, which Claude Code itself receives the click for. That needs Claude Code's
1201
+ **fullscreen** view (`"tui": "fullscreen"` in `~/.claude/settings.json`, or `/config`), where the
1202
+ mouse reaches it; in the classic view the row is still there, and ctrl+x tab then Enter opens an
1203
+ entry.
1204
+
1205
+ It is a **mod**, a small piece of code Claude Code runs inside itself, and the installer copies it
1206
+ into `~/.claude/skills/k0-links` together with the commands, behind the same question. So it is
1207
+ there in **every** Claude Code session on the machine, not only the ones a story opened — new
1208
+ sessions pick it up when they start, an open one with `/reload-plugins` — and it does nothing at
1209
+ all while k0 is off. Documents become entries only in **a repository k0 knows**; elsewhere the
1210
+ addresses, folders and artifacts still do.
543
1211
 
544
1212
  ### On paper
545
1213
 
@@ -565,11 +1233,11 @@ kernel's own verdict, plus one added rule: amber when memory in use goes over 90
565
1233
  the whole picture, including **what is heavy and is not k0**: if the machine is struggling because
566
1234
  of Chrome it is fair to know that, instead of closing sessions for nothing.
567
1235
 
568
- On every card there is **what that session weighs**. Not the `claude` process: everything it has
1236
+ On every story there is **what that session weighs**. Not the `claude` process: everything it has
569
1237
  dragged along — the MCP servers, the Chromes they open, a `tsc` started from a commit hook. That
570
- is where the memory goes, and it is the thing no other tool can attribute to the right card.
1238
+ is where the memory goes, and it is the thing no other tool can attribute to the right story.
571
1239
 
572
- Only one card is red, the heaviest, and only while the machine is struggling: if they were all
1240
+ Only one story is red, the heaviest, and only while the machine is struggling: if they were all
573
1241
  red they would say nothing.
574
1242
 
575
1243
  Two things said plainly. The CPU is the CPU of **right now**, worked out from the difference in
@@ -578,7 +1246,7 @@ which on an old session says nothing about this minute. And summing the memory o
578
1246
  counts shared memory twice, so the total is a little generous: it is the usual approximation, and
579
1247
  it is the right one for the question that matters — which one do I close to feel better.
580
1248
 
581
- And once you have decided, **`Close` on that card is how you give the memory back**: the session
1249
+ And once you have decided, **`Close` on that story is how you give the memory back**: the session
582
1250
  is stopped and its window goes, the work stays on the board as it was, and `Resume` picks the
583
1251
  conversation up where it left off. Nothing has to be declared finished to stop weighing.
584
1252
 
@@ -586,6 +1254,40 @@ Reading the process table costs little on a calm machine and a lot on a struggli
586
1254
  exactly when you look at it. So it is sampled every three seconds, and **only while the board is
587
1255
  open**.
588
1256
 
1257
+ ### And what k0 costs
1258
+
1259
+ The chip measured everybody but itself, which is the one thing a program running under launchd for
1260
+ weeks should be least able to hide. Hover it and the last line is **k0's own weight, its CPU, how
1261
+ often it asks git anything, how many queries it is holding, and how hard the watching loop is
1262
+ currently running**.
1263
+
1264
+ That loop is the whole of k0's cost, and it now runs at the pace the work deserves. With a session
1265
+ open — or with you in front of the board — it goes round every two seconds. With neither, there is
1266
+ nothing it could see change, so it drops to **once a minute** and k0 stops costing anything on a
1267
+ machine nobody is using. Pressing anything wakes it at once, so nothing ever waits on it.
1268
+
1269
+ The git marks follow the same rule. Every repository on the board used to be asked `status` and
1270
+ `rev-list` every five seconds, all night; now the full list is only asked while you are looking,
1271
+ away from the board only the repositories a session is actually working in, and a reading is good
1272
+ for half a minute. Nothing in a repository changes faster than that unless you make it.
1273
+
1274
+ ### And what the page downloads
1275
+
1276
+ The other half of the bill is paid by the browser, and it was the larger one. The board asked for
1277
+ everything k0 knows once a second and got it: two thirds of a megabyte, six hundred stories with
1278
+ their whole "Why" and their whole plan, most of them finished weeks ago and hidden from view. Over
1279
+ a day with one tab open that came to **fifty-six gigabytes**, to draw post-its that had not moved.
1280
+
1281
+ Now the board sends back a stamp of the answer it already has, and when the answer would be the
1282
+ same — which on a board nobody is touching is every round of every day — the server says so in a
1283
+ couple of hundred bytes and sends nothing else. When something really did change, what goes out is
1284
+ only what a post-it draws, compressed. The long texts come with the story's own panel, when you
1285
+ open one, where they were always read from anyway.
1286
+
1287
+ A still board also stops asking so often: after a few rounds saying nothing moved it drops to one
1288
+ in four seconds, and the first thing that moves — or your coming back to the tab — puts it
1289
+ straight back to one.
1290
+
589
1291
  ### And the ones you forget, k0 closes for you
590
1292
 
591
1293
  The paragraph above assumes you noticed. Most of the time nobody does: the window that is costing
@@ -593,7 +1295,7 @@ you a gigabyte is the one you stopped thinking about yesterday. So **after twelv
593
1295
  nothing happening, k0 does that `Close` itself** — the session is stopped, its window goes, and the
594
1296
  memory comes back.
595
1297
 
596
- Nothing is lost by it. The card stays exactly where it is with the status it had, and **Resume**
1298
+ Nothing is lost by it. The story stays exactly where it is with the status it had, and **Resume**
597
1299
  picks the conversation up where it was. That is the whole reason this is safe: a closed terminal
598
1300
  has never been a lost session.
599
1301
 
@@ -609,12 +1311,12 @@ rest is left alone, and each for its own reason:
609
1311
  there may be a command of yours running in it; k0 cannot see what it is, so k0 does not touch it.
610
1312
  On the board it reads as yellow like any other, which is exactly why this one has to be said.
611
1313
 
612
- And a window you were using an hour ago is never closed, whatever the card's history says. k0 has
1314
+ And a window you were using an hour ago is never closed, whatever the story's history says. k0 has
613
1315
  four clocks for a session — two of its own and two Claude Code keeps — and **the newest one wins**.
614
1316
  Being wrong in that direction leaves a window open until tomorrow; being wrong the other way closes
615
1317
  a terminal you were about to go back to.
616
1318
 
617
- A card k0 tidied away says so: where one you closed yourself reads *session closed*, this one reads
1319
+ A story k0 tidied away says so: where one you closed yourself reads *session closed*, this one reads
618
1320
  *closed automatically*. Same italic, same place, one word different.
619
1321
 
620
1322
  And the memory chip at the end of the top bar says it is watching, and from when: **RAM 79% · CPU
@@ -633,17 +1335,17 @@ settings file changes it, and **`0` switches it off** — see below.
633
1335
 
634
1336
  An empty board is no help in getting your bearings. The installer offers to do this on the first
635
1337
  run; afterwards, `/k0-import` from a Claude Code session picks up the sessions that already
636
- happened — including the ones opened by hand, outside k0 — and puts them on the board as cards:
1338
+ happened — including the ones opened by hand, outside k0 — and puts them on the board as stories:
637
1339
  the last 14 days, at most the 10 most recent per repository. `/k0-import 30 5` changes the two
638
1340
  numbers.
639
1341
 
640
1342
  The difference between the two is the writing. The installer uses the name the session already
641
1343
  had, or the first few words of the first prompt. `/k0-import` has Claude read the conversation and
642
1344
  write a title and a description in the language it was held in. That description is the line in
643
- italics under the title on the note, and importing is the only thing that writes one: a card you
1345
+ italics under the title on the note, and importing is the only thing that writes one: a story you
644
1346
  write yourself has a title and a prompt, which is all it needs.
645
1347
 
646
- Imported cards are born yellow — *Your turn*: **Resume** reopens the conversation where it was,
1348
+ Imported stories are born yellow — *Your turn*: **Resume** reopens the conversation where it was,
647
1349
  **Done** clears it away. Being dead sessions they do not light the tray icon. Running it again
648
1350
  skips the ones already imported.
649
1351
 
@@ -656,8 +1358,12 @@ real machine that separated 145 genuine sessions from 867 automated ones, and it
656
1358
 
657
1359
  ## The statuses
658
1360
 
659
- A card **is** the colour of its status — there is nothing else to read. On the left is the code in
660
- the database, then how it reads on screen.
1361
+ A story **is** the colour of its status — there is nothing else to read. On the left is the code
1362
+ k0 speaks internally — the API, the menu bar icon and the colours in `web/base.css` all say these
1363
+ seven words — then how it reads on screen. None of the seven is a column in the database: `BACKLOG`
1364
+ and `COMPLETED` are worked out from the story (no session, and closed), and the other five belong
1365
+ to the live session, not to the story. See [`docs/database.md`](docs/database.md) for where each
1366
+ half really lives.
661
1367
 
662
1368
  | | | | |
663
1369
  |---|---|---|---|
@@ -679,12 +1385,12 @@ How awake the machine has to stay while sessions are working. It is a **scale of
679
1385
  four switches: each includes the one before it, and exactly **one** is always lit. Clicking the lit
680
1386
  one again does nothing — you leave a mode, you do not switch it off.
681
1387
 
682
- | Icon | Mode | The machine | The screen | The text |
1388
+ | Icon | Mode | The machine | The screen | The text and the windows |
683
1389
  |---|---|---|---|---|
684
1390
  | two **z** | **Sleep** | sleeps as it normally would | goes off | normal |
685
1391
  | a **palm tree** | **Away** | does not sleep, not even with the lid closed | may sleep and lock | normal |
686
1392
  | a **nerd face** with glasses | **Nerd** | does not sleep | **stays on** | normal |
687
- | a **car** | **Driving** | does not sleep | **stays on** | **large**, here and in the terminals |
1393
+ | a **car** | **Driving** | does not sleep | **stays on** | **large**: the text here and in the terminals, and the terminals fill the screen |
688
1394
 
689
1395
  The four icons do not describe the machine: they describe **where you are**. Asleep, away, at the
690
1396
  desk, watching from across the room. That is where the order comes from, and it is why the second
@@ -694,9 +1400,9 @@ one is a palm tree and not a technical symbol: the mode does not say "the machin
694
1400
  The four buttons are at the end of the board's bar, or four ticked entries in the tray menu. They
695
1401
  are the same control: changed on one side, the other catches up within a couple of seconds.
696
1402
 
697
- **Nerd** and **Driving** do exactly the same things to the machine: the only difference is the size
698
- of the text. Nerd is "I am sitting here programming", Driving is "I glance at it from across the
699
- room".
1403
+ **Nerd** and **Driving** do exactly the same things to the machine: the only difference is how big
1404
+ everything is — the text, and the terminal windows it sits in. Nerd is "I am sitting here
1405
+ programming", Driving is "I glance at it from across the room".
700
1406
 
701
1407
  ### Why an idle inhibitor is not enough
702
1408
 
@@ -720,7 +1426,7 @@ it does not do.
720
1426
  no business rewriting behind your back. The switch reports itself unavailable, and `k0-board
721
1427
  doctor` says where to change it yourself.
722
1428
 
723
- ### Large text, and windows that do not move
1429
+ ### Large text, and windows to match
724
1430
 
725
1431
  In Driving the **text inside the terminals** goes from the profile's size to 22, the board's from
726
1432
  17 to 22 pixels, and the **things you click** grow too — the `+`, the git lens, the corner pencil
@@ -732,16 +1438,27 @@ they reorder by urgency, reddest to the left. On a screen you glance at, two or
732
1438
  visible at a time and the most urgent one has to come to you. Full screen you have them all in
733
1439
  front of you already, and a board that reshuffles itself while you work only loses your place.
734
1440
 
735
- **The windows do not move.** New ones are born centred at 86% as always; ones already open do not
736
- shift by a pixel — if you had dragged one to the other monitor, there it stays. Terminals already
737
- open change size **immediately**, not only the ones you open next.
1441
+ **The windows grow with the text.** In Driving a terminal takes the whole free screen; leave
1442
+ Driving and it goes back to the usual 86% centred, with the text back at the profile's size. It is
1443
+ one gesture and not two, and it lands on the terminals **already open**, not only on the ones you
1444
+ open next.
738
1445
 
739
- That the window does not move **is not free**, and it is the least obvious part of this whole
740
- chapter: Terminal.app keeps rows and columns when the font changes and resizes the window to
741
- match — going from 12 to 22 turns a 700×500 window into 1378×856, measured. So the bounds are read
742
- first, the font is changed, and **its own** bounds are put back.
1446
+ It used to be the opposite, and the reason is worth keeping in mind: Terminal.app holds rows and
1447
+ columns when the font changes and resizes the window to match — going from 12 to 22 turns a 700×500
1448
+ window into 1378×856, measured — so k0 read each window's own bounds first and put them back, and
1449
+ nothing moved. What that left behind was a window holding 22 point text in a box measured for 12.
1450
+ Half a gesture is worse than none, so the size of the text and the size of the window now travel
1451
+ together, and the price is said plainly: **a window you had dragged onto another screen comes back
1452
+ to the middle of the main one.**
743
1453
 
744
- k0 touches **only its own windows**, the ones born from a card.
1454
+ **All of them, every time.** k0 asks Terminal once for the windows it has open and changes those
1455
+ that are its own, rather than asking after every window id it has ever written down. On a board
1456
+ with two hundred stories almost every one of those ids names a window closed weeks ago, and asking
1457
+ after them one at a time took seven seconds — long enough to be cut short halfway, which left half
1458
+ the terminals large, half of them small, and nothing said about it anywhere. Walking the windows
1459
+ that exist takes about a second and does not grow with the board.
1460
+
1461
+ k0 touches **only its own windows**, the ones born from a story.
745
1462
 
746
1463
  ### What it remembers, and what it looks at
747
1464
 
@@ -830,7 +1547,7 @@ Worth knowing:
830
1547
 
831
1548
  Two side effects of the Cmd+V k0 uses to write your prompt, worth knowing:
832
1549
 
833
- - the card's prompt replaces whatever was on your clipboard (if the paste fails, the clipboard is
1550
+ - the story's prompt replaces whatever was on your clipboard (if the paste fails, the clipboard is
834
1551
  put back);
835
1552
  - to paste, the terminal is brought to the front for an instant: if you happen to be **dictating**
836
1553
  at that moment, the dictation lands in there and sticks to the prompt.
@@ -859,7 +1576,7 @@ itself on the next round: nothing to restart.
859
1576
 
860
1577
  | | |
861
1578
  |---|---|
862
- | `closeIdleTerminalsAfterHours` | How long a yellow card's terminal may sit there before k0 closes it and gives the memory back. `12` if you say nothing. **`0` switches it off.** Anything under an hour is treated as an hour — below that this stops being a tidy-up and starts closing windows while you are using them. |
1579
+ | `closeIdleTerminalsAfterHours` | How long a yellow story's terminal may sit there before k0 closes it and gives the memory back. `12` if you say nothing. **`0` switches it off.** Anything under an hour is treated as an hour — below that this stops being a tidy-up and starts closing windows while you are using them. |
863
1580
 
864
1581
  Delete a line to go back to its default; a file k0 cannot read is ignored altogether and the
865
1582
  defaults hold, rather than k0 refusing to start over a stray comma.
@@ -887,49 +1604,103 @@ platform/
887
1604
  shared/ what more than one of them needs: tmux, running commands, reading a process
888
1605
  table, and reading who is holding which port
889
1606
  server/
890
- index.js the http server, the API, and the watching loop that runs every second
1607
+ index.js the http server, the API, and the watching loop — every two seconds while a
1608
+ session is running or somebody is at the board, once a minute when neither, and
1609
+ awake at once on anything you press
891
1610
  guard.js who is allowed to talk to this server at all: the Host and the Origin
892
- db.js SQLite (node:sqlite): the card, session_event, pref and dev_server tables —
1611
+ db.js SQLite (node:sqlite): the only file that talks to it. epic, story, session,
1612
+ decision, round, check_item, dependency, session_event and the rest —
893
1613
  docs/database.md
1614
+ backlog.js the model: epics, stories, tasks, decisions, dependencies, the order, and
1615
+ what to pick up next. Pure logic over db.js — no http, no disk
1616
+ mirror.js writes and re-reads <repo>/.k0/, the readable copy of the backlog. It writes
1617
+ nowhere else, ever, and a test proves it. No domain logic
1618
+ worktree.js a session working copy of its own: open it from the branch you are on, merge
1619
+ it back, destroy it. Never a push, never a pull request, never a conflict
1620
+ resolved for you, and it never runs tests or a build in there
1621
+ update.js the one request k0 makes — what npm says the newest version is — and the
1622
+ version jump that puts the mark next to k0 in the top bar
894
1623
  paths.js where the board, the logs, the settings and the cache live
895
1624
  settings.js the few things you can change, and the file that is the list of them —
896
1625
  ~/.k0/config.json, written out with everything in it and re-read when it changes
897
1626
  idle.js which terminals have sat still long enough to be closed and given back. Only the
898
1627
  deciding: it kills nothing, so every rule in it can be proved without a machine
899
1628
  watcher.js reads Claude Code's own files and derives the statuses; also renames a session
1629
+ usage.js reads what every session consumed out of its transcripts, a few megabytes at a
1630
+ time and only what is new, plus the statusline's limit samples and which account
1631
+ is signed in; adds it up by the hour for the Usage page. Never asks a model
1632
+ prices.js the API price list the Usage page's dollars come from, dated; a model not on it
1633
+ has no price rather than a zero one
900
1634
  git.js the only one that talks to git: what is committed, what is pushed, whose it is,
901
1635
  and — for the ChangeLog — what the commits actually said
902
1636
  changelog.js gathers what happened in a window, out of git and out of session_event. Decides
903
1637
  which repositories are worth mentioning at all, and stores nothing
904
1638
  writer.js hands those facts to the Claude Code already on this machine and gets the words
905
- back. The only place k0 starts a model, and it never leaves the machine to do it
1639
+ back. The only place k0 starts a model, and it never leaves the machine to do
1640
+ it. Keyed by skill and by window, so the ChangeLog and the What is New page can
1641
+ be writing at the same time without cancelling each other
906
1642
  launcher.js starts and resumes sessions, through the platform's terminal
907
1643
  servers.js the dev server of a repository: what starts it, whether it is up, and on what
908
1644
  port. The only thing k0 starts that is meant to outlive k0
909
- mode.js the four modes: how awake to keep the machine, and whether the text goes large
910
- projects.js the repositories, in the order you last used them
911
- sessions.js digs already-lived sessions out of the transcripts, to import as cards
1645
+ mode.js the four modes: how awake to keep the machine, and whether text and windows go
1646
+ large. How large is `launcher.js`, which is what talks to the terminal
1647
+ projects.js the repositories, in the order you last used them — and which directories k0 is
1648
+ allowed to open at all, which is one answer and not one per endpoint
1649
+ sessions.js digs already-lived sessions out of the transcripts, to import as stories
912
1650
  files.js the only one that reads the projects' disk — and the only one that writes back
913
1651
  into it: what is there, what changed, what it says, and the one small write
914
- machine.js the only one that looks at processes and memory: what it all costs, and who is costing it
1652
+ machine.js the only one that looks at processes and memory: what it all costs, and who is
1653
+ costing it — k0's own process included, which is the only honest way to publish
1654
+ a number like that
915
1655
  pdf.js the document on paper, printed by a headless browser
916
- web/ the three pages (html, css, js served exactly as they are)
1656
+ web/ the four pages (html, css, js served exactly as they are)
917
1657
  index.html the board — board.js, board.css, view.js. A note is never taller than it is
918
1658
  wide: the title, the age and the buttons always show, the text in the middle is
919
1659
  what gets clipped
1660
+ list.js the same stories as rows, list.css beside it: the other shape of the same page,
1661
+ not a page of its own. Handed the stories the board is already showing, so the
1662
+ filters cannot mean two things, and the story you open follows a live discussion
1663
+ by asking .../live once a second, the cadence the rest of k0 already uses
920
1664
  files.html the file viewer — files.js, files.css
921
- changelog.html what you have been doing — changelog.js, changelog.css. The only page in k0 you
922
- read top to bottom instead of looking at, so it is the only one that scrolls
923
- base.css colours, fonts and scale: the house variables, shared by all three pages
1665
+ changelog.html what you have been doing — changelog.js, changelog.css. Read top to bottom
1666
+ instead of looked at, so it is one of the three pages that scroll
1667
+ whatsnew.html what changed in k0 between the version you had and this one — whatsnew.js,
1668
+ whatsnew.css. Reached from the mark next to k0, and never opened by itself
1669
+ base.css colours, fonts and scale: the house variables, shared by all of them
1670
+ awake.js the one place that repeats anything: a job that runs only while its tab is in
1671
+ front of you, and takes a fresh reading the moment you come back to it. A page
1672
+ nobody can see must not be asking the server anything — asking is also how the
1673
+ server learns somebody is watching
924
1674
  md.js markdown laid out, written by hand because nothing here is compiled
925
1675
  recency.js which repositories are still warm, and which fold away into `Old`
926
- fuzzy.js searching the names: the letters you type, in the order you type them
1676
+ fuzzy.js searching the names: the letters you type, in the order you type them — the
1677
+ file viewer, the repository the new story goes in, and the repository menu on
1678
+ the bar, which is drawn here rather than left to the system
927
1679
  mentions.js which of a repository's files a piece of text names
928
1680
  refs.js what a name written inside a document points at, and which of the nine READMEs
929
1681
  json.js a JSON file as a tree that folds, and the search that opens the right branches
930
1682
  conf.js an .env as the table it always was, and YAML/TOML/INI with their parts told apart
931
1683
  .claude/skills/
932
1684
  k0-import/ the skill that fills the board with sessions you have already had
1685
+ k0-epic/ the long way in: rounds of questions, decisions, then a tree of stories
1686
+ k0-story/ one story, fast path, no ceremony
1687
+ k0-discuss/ an existing story, discussed in rounds until nothing more would change it
1688
+ k0-split/ a story too big to close, split into tasks that inherit its decisions
1689
+ k0-plan/ plan mode, with the standing decisions injected as constraints
1690
+ k0-work/ the worktree, the work, the Log as it goes, and the merge back
1691
+ k0-ultracode/ the manager: a plan cut into assignments, an agent and a worktree each, and every
1692
+ story tested and counter-checked before the next one starts
1693
+ k0-verify/ the counter-check: every decision one by one, the checklist, the outcome
1694
+ k0-next/ what to pick up now, and why — the server decides, not the model
1695
+ k0-order/ priority and dependencies, dictated
1696
+ k0-links/ not a skill but a mod: hooks Claude Code runs inside itself. At the end of each
1697
+ reply it finds the addresses, folders and documents the reply named, asks the
1698
+ disk what each path is and k0, on loopback, which documents its viewer has
1699
+ (POST /api/files/exist), adds the artifacts the session published, and draws them
1700
+ as buttons in the row above the prompt; a press runs the system's `open`. It never
1701
+ touches the reply. links.js is the pure half, tested by npm test; nothing in it
1702
+ may come from k0's own folders, because it is copied out alone
1703
+ k0-whatsnew/ the What is New page, written from the changelog entries k0 hands it
933
1704
  k0-changelog/ the one that turns the facts of a stretch of work into something readable. k0
934
1705
  calls it by itself when the ChangeLog is opened, so it is in the package too
935
1706
  changelog/ the one that writes the changelog and the documentation when work is finished.
@@ -938,7 +1709,9 @@ web/ the three pages (html, css, js served exactly as they are)
938
1709
  the road out: the documents, the tests, the commit, the push, and the tag that
939
1710
  publishes. Also for whoever works on k0, and also not in the package
940
1711
  docs/
941
- database.md the shape of the database as it is now: the four tables, column by column
1712
+ database.md the shape of the database as it is now, table by table, column by column
1713
+ method.md why a decision has to be an object, what a round of questions is for, and
1714
+ what the counter-check is actually checking
942
1715
  testing.md how the tests are written, run and measured, and what is left untested on purpose
943
1716
  test/ npm test — Node's own runner, no framework. See docs/testing.md
944
1717
  harness.mjs check(label, got, want), and the sections the labels are grouped under
@@ -946,27 +1719,52 @@ test/ npm test — Node's own runner, no framework. See docs/testing.
946
1719
 
947
1720
  ### What it reads, and what it never does
948
1721
 
949
- k0 reads your repositories. It writes into one of them in exactly one place: the pencil in the
950
- file viewer, on a configuration file or a note that is already there. That write is deliberately
951
- narrow — no code, no new files, no deletions — it carries the file's own permissions across, it
952
- lands as a rename so an interrupted save leaves the old file whole, and it refuses outright if the
953
- file has changed on disk since the page read it.
1722
+ k0 reads your repositories. It writes into one in three places, and all three are named here
1723
+ because a tool that writes where you did not expect it is a tool you stop leaving running.
1724
+
1725
+ The first is the pencil in the file viewer, on a configuration file or a note that is already
1726
+ there. That write is deliberately narrow — no code, no new files, no deletions — it carries the
1727
+ file's own permissions across, it lands as a rename so an interrupted save leaves the old file
1728
+ whole, and it refuses outright if the file has changed on disk since the page read it.
1729
+
1730
+ The second is the `.k0/` folder, and only ever inside it: the readable copy of that repository's
1731
+ backlog, rewritten whenever a story changes. Never your `.gitignore`, never a file beside it, and
1732
+ a test walks the tree afterwards to prove nothing else appeared. With the backlog switched off the
1733
+ folder is never made at all.
1734
+
1735
+ The third only happens when you ask for it, and it is `/k0-work` opening a worktree. That one is
1736
+ the largest thing k0 does to a repository, so it is worth reading twice: it adds a worktree under
1737
+ `.claude/worktrees/`, it writes two lines into `.git/info/exclude` so that directory does not show
1738
+ up as something you forgot to commit, and at the end it commits inside the worktree and merges
1739
+ that branch into the branch you were standing on. It never pushes, never opens a pull request, and
1740
+ never resolves a conflict on your behalf — where it cannot merge cleanly it stops and says so.
1741
+ None of it happens unless you run `/k0-work`.
954
1742
 
955
- k0 does not emulate a terminal and installs no hooks. It reads two things Claude Code already
956
- writes for itself:
1743
+ k0 does not emulate a terminal and installs no settings hooks. The one thing it puts inside Claude
1744
+ Code is [the `k0-links` mod](#what-claude-points-at-one-click-away), and only if you
1745
+ said yes: it draws a row above the prompt, never touches a reply, and talks to nobody but k0 on the
1746
+ loopback address. Beyond that k0 reads what Claude Code already writes for itself:
957
1747
 
958
1748
  - `~/.claude/sessions/<pid>.json` — live status (`busy`, `idle`, `waiting` with the reason for the
959
1749
  wait) and the session id;
960
1750
  - `~/.claude/projects/<project>/<session>.jsonl` — the transcript, read incrementally, which is
961
- where you can tell whether you are inside a plan.
1751
+ where you can tell whether you are inside a plan — and, for the Usage page, what every reply
1752
+ consumed, the subagents' and workflows' transcripts beside it included.
962
1753
 
963
- Sessions are launched with `--session-id` (k0 chooses the id, so the card ↔ session link is
964
- certain), `-n` for the name, `--resume` to pick one up, and `--permission-mode plan` on new ones.
1754
+ For the Usage page alone, two more: the account in `~/.claude.json`, read again only when that file
1755
+ changes, and `~/.k0/usage/limits.jsonl`, which your statusline writes if you gave it the snippet.
965
1756
 
966
- The ChangeLog runs Claude Code a second way: `claude -p /k0-changelog`, with the facts on
967
- standard input and no terminal at all. It is the one time k0 starts a model, and it still opens
968
- no socket of its own — the request is Claude Code's, made with your own account, from your own
969
- machine. Those runs cannot come back as cards: `sessions.js` drops `claude -p` when it looks for
1757
+ Sessions are launched with `--session-id` (k0 chooses the id, so the story ↔ session link is
1758
+ certain), `-n` for the name, `--resume` to pick one up, and `--permission-mode plan` on new ones.
1759
+ Both kinds start with `CLAUDE_CODE_ENABLE_TODO_TOOLS=1` in their environment, set on the command
1760
+ line the terminal is handed — `env` in front of `claude` on macOS and Linux, `$env:` before it on
1761
+ Windows.
1762
+
1763
+ The ChangeLog and the What's New page run Claude Code a second way: `claude -p` on the skill that
1764
+ writes them, with the facts on standard input and no terminal at all. Those are the only times k0
1765
+ starts a model, and they still open no socket of k0's own — the request is Claude Code's, made
1766
+ with your own account, from your own machine. Both pages can be writing at once without either
1767
+ cancelling the other. Those runs cannot come back as stories: `sessions.js` drops `claude -p` when it looks for
970
1768
  sessions to import, which is also how it tells a hundred and forty real sessions from eight
971
1769
  hundred automated ones.
972
1770
 
@@ -984,6 +1782,12 @@ Field notes the code takes for granted.
984
1782
  of the two flags changes nothing — the session starts in `bypassPermissions` and there is no
985
1783
  trace of a plan. It looks like it works, which is what makes it a trap. The only way to really
986
1784
  start inside a plan is `--allow-dangerously-skip-permissions`.
1785
+ - **On a newer model Claude Code starts with no task tools.** It offers `TaskCreate`, `TaskUpdate`
1786
+ and the rest only to a list of older models, or when `CLAUDE_CODE_ENABLE_TODO_TOOLS=1` is in the
1787
+ environment, and Opus 5 is not on the list. Nothing says so up front: the model calls
1788
+ `TaskCreate`, is told it is disabled for the session, and carries on without. The variable is
1789
+ read once, when the process starts, so a session opened before k0 set it gets the tools only by
1790
+ being resumed.
987
1791
  - **While a dialog is open, the call that caused it is not yet in the transcript.** A plan to
988
1792
  approve and a question are told apart by the `waitingFor` field of the session file:
989
1793
  `permission prompt` is the plan, `input needed` is the question.
@@ -991,10 +1795,17 @@ Field notes the code takes for granted.
991
1795
  replaced by `-`, truncated at 200 characters with a hash on the end. That is lossy: `my_project`
992
1796
  and `my-project` become the same name, so the working directory is always read from inside the
993
1797
  transcript, never by reversing the directory name.
994
- - **A session's name lives in two places** — the session file, rewritten by the live process, and
995
- the end of the transcript, in `custom-title` and `agent-name` lines that Claude Code rewrites
996
- every turn. **The last one wins.** So renaming a closed session means appending another copy; a
997
- live one would have the old name written back over it.
1798
+ - **A session's name lives in three places** — the process's own memory, the session file it
1799
+ rewrites (`name`, with `nameSource: "user"` when `-n` or `/rename` set it), and the end of the
1800
+ transcript, in `custom-title` and `agent-name` lines that Claude Code rewrites every turn.
1801
+ **The last one wins.** So renaming a closed session means appending another copy; a live one
1802
+ would have the old name written back over it, and the only way into a live one is its own
1803
+ `/rename` command — typed at the keyboard. Written into the terminal as one block (Terminal's
1804
+ `do script`, a paste) the same line reaches it as a message, and the model answers that it
1805
+ cannot rename the session. The session file is how k0 knows the command took.
1806
+ - **The transcript is not always under the repository's slug.** A session that moves into a
1807
+ worktree writes under the worktree's slug from then on, and a story only knows the repository —
1808
+ so a rename looks in the work path, then the repository, then walks the projects directory.
998
1809
  - **The session file appears before the interface is ready to receive.** Writing at that moment
999
1810
  loses the first characters and swallows the Enter. So k0 waits until it can see the input box —
1000
1811
  and where a platform cannot read a terminal's screen, it waits a fixed moment and says so.
@@ -1035,11 +1846,11 @@ Field notes the code takes for granted.
1035
1846
  The order is the fresher of two histories. The first is `~/.claude.json`, where Claude Code notes
1036
1847
  when you opened each one — but `lastStartTime` is rewritten when the session *ends*, so on its own
1037
1848
  it only tells you about the past. The second is k0's own database, which moves when you create or
1038
- edit a card and on every status change of a live session. That is what brings the repository you
1849
+ edit a story and on every status change of a live session. That is what brings the repository you
1039
1850
  are working in right now to the top.
1040
1851
 
1041
1852
  The list holds directories with a `.git`, directories you have already worked in even if they are
1042
- not repositories, directories with a card, directories with a document inside them — and **empty
1853
+ not repositories, directories with a story, directories with a document inside them — and **empty
1043
1854
  ones**.
1044
1855
 
1045
1856
  Empty ones belong because an empty directory under your home is one you just made, and it cannot
@@ -1048,8 +1859,8 @@ in `Others` with its `+`. Anything starting with a dot does not make it full, or
1048
1859
  file manager would be enough to make it disappear again.
1049
1860
 
1050
1861
  **A column lives as long as its directory does.** If that directory is gone — deleted, renamed, an
1051
- external disk unmounted — the column does not appear, and neither do its cards. **Hiding is not
1052
- deleting**: the cards stay in the database, and if the directory comes back so do they.
1862
+ external disk unmounted — the column does not appear, and neither do its stories. **Hiding is not
1863
+ deleting**: the stories stay in the database, and if the directory comes back so do they.
1053
1864
 
1054
1865
  ---
1055
1866
 
@@ -1061,11 +1872,20 @@ HTML files from your repositories are shown in a sandbox with no permissions. Th
1061
1872
  and no token: anything already running as you on this machine can reach the API, and that is worth
1062
1873
  knowing rather than glossing over.
1063
1874
 
1875
+ **One request leaves this machine, and it is about k0 rather than about you.** Once a day k0 asks
1876
+ the public npm registry what the newest version of `k0-board` is, so the board can say there is
1877
+ one. The package name is in the address and nothing else — nothing about you, your repositories,
1878
+ your commits or your board — nothing is downloaded, and `"updateCheck": false` in `~/.k0/config.json` switches it off entirely.
1879
+
1064
1880
  The full picture, and how to report a problem privately, is in [SECURITY.md](SECURITY.md).
1065
1881
 
1066
1882
  ## What is not here yet
1067
1883
 
1068
- Checkboxes inside a card. In the viewer the listing is documents and configuration: code opens if
1884
+ Ticking a line off on the post-it itself: a story's checklist is written by `/k0-verify`, and the
1885
+ place to work through it is the story's panel in the list. Writing a decision, discussing one and
1886
+ superseding one are still done by talking to Claude — the board says which of those to do next and
1887
+ opens the terminal on it, but nothing on the page writes a decision.
1888
+ In the viewer the listing is documents and configuration: code opens if
1069
1889
  you arrive at it from a link, but it is not browsable and the text search does not look at it.
1070
1890
  Only configuration and notes can be edited, one file at a time — nothing is diffed, no file is
1071
1891
  created or deleted, and you cannot talk to them; for that you open the repository with Claude.