The terminal is the third seat at the board, and today it only redraws when you press a key: someone moving a card on the web page is invisible in ssh until you touch the keyboard. The event stream in the live-board issue cannot help here — src/tty.ts is a separate process on a pty, and an in-process bus does not cross processes — so the terminal follows the board by reading a cheap revision from the same SQLite file.
Done looks like
[ ] src/db.ts exposes boardRevision(boardId): number, a single indexed read that changes on every change to that board — a card added, edited, moved or deleted, a column added, renamed, moved or deleted, the board renamed, and an undo — and does not go backwards. Derive it from a counter bumped in the same transaction as the write, not from MAX(action.id): undo deletes the newest action and the undo log is trimmed, so the log is not a clock.
[ ] src/tty.ts checks the revision about twice a second while idle and redraws only when it moved. When nothing is happening it costs one small query per tick and no board read.
[ ] A redraw does not disturb the person: an open prompt keeps its text and caret, the filter stays, and the cursor stays on the card it was on (find it by id and clamp; never jump to 0). A card that vanished under the cursor leaves the cursor at the nearest remaining card.
[ ] The boards list redraws the same way when a board is created or renamed elsewhere.
[ ] The timer never keeps the process alive: q and ^C exit immediately and cleanly, and the interval is unref'd or cleared.
[ ] README.md says the terminal follows the same board live, that it polls because a pty is a different process from the web server's in-process stream, and keeps printing the connect command from FORGE_APP_SSH verbatim.
[ ] Tests: boardRevision moves after each kind of mutation and after undo, and is stable when nothing happened; the redraw decision is a small pure function (shouldRedraw(previous, next) or similar) tested without a pty; the cursor-keeping rule is tested as a pure function over a card list too.
A revision read on a tight loop turns the quietest client into the heaviest — keep it one indexed query and only re-read the board when it moved. Redrawing mid-prompt eats what someone was typing. process.stdout.write of a full-screen redraw while a prompt is open flickers; draw on change, not on the tick. A revision derived from the action log breaks the moment the log is trimmed or undone.
Blocked by the transactional write path, because the revision bump has to happen inside the same transaction as the write it describes.
Suggested brief: scout (instant feedback in a small surface, with tests).
The terminal is the third seat at the board, and today it only redraws when you press a key: someone moving a card on the web page is invisible in
sshuntil you touch the keyboard. The event stream in the live-board issue cannot help here —src/tty.tsis a separate process on a pty, and an in-process bus does not cross processes — so the terminal follows the board by reading a cheap revision from the same SQLite file.Done looks like
src/db.tsexposesboardRevision(boardId): number, a single indexed read that changes on every change to that board — a card added, edited, moved or deleted, a column added, renamed, moved or deleted, the board renamed, and anundo— and does not go backwards. Derive it from a counter bumped in the same transaction as the write, not fromMAX(action.id): undo deletes the newest action and the undo log is trimmed, so the log is not a clock.src/tty.tschecks the revision about twice a second while idle and redraws only when it moved. When nothing is happening it costs one small query per tick and no board read.qand ^C exit immediately and cleanly, and the interval is unref'd or cleared.README.mdsays the terminal follows the same board live, that it polls because a pty is a different process from the web server's in-process stream, and keeps printing the connect command fromFORGE_APP_SSHverbatim.boardRevisionmoves after each kind of mutation and afterundo, and is stable when nothing happened; the redraw decision is a small pure function (shouldRedraw(previous, next)or similar) tested without a pty; the cursor-keeping rule is tested as a pure function over a card list too.bun testpasses.Files
src/db.ts,src/tty.ts,src/tty.test.ts(new),README.md.Risks
A revision read on a tight loop turns the quietest client into the heaviest — keep it one indexed query and only re-read the board when it moved. Redrawing mid-prompt eats what someone was typing.
process.stdout.writeof a full-screen redraw while a prompt is open flickers; draw on change, not on the tick. A revision derived from the action log breaks the moment the log is trimmed or undone.Blocked by the transactional write path, because the revision bump has to happen inside the same transaction as the write it describes.
Suggested brief: scout (instant feedback in a small surface, with tests).