cowork-deck v0.3.0
A scenario used to leave nothing behind. sessions.json dropped the entry when
the tile closed, so a schedule that fired at 03:00 into a session nobody was
there to watch was unrecoverable by morning — the only surviving trace anywhere
was one row per scenario in schedule_state.json, written by the scheduler and
only for scheduled fires. This release gives scenario runs a journal and a
screen to read it on.
What people get
Scenario run history (#217, in three parts: #218, #219, #220). Every run is
journalled — how it started, how long it took, and the final assistant message —
and a History screen beside Terminals / Board / Pull requests lists them
newest first, filterable by scenario and by trigger.
- The journal is
runs.jsonlin the app data dir, one appended line per event.
Append-only, because a store that truncates before it writes cannot be
trusted with a file written on every launch; versioned per line, because
after an upgrade the file physically holds lines from several app versions and
a header would lie about the ones below it. - Rows carry snapshots, not lookups: the name, icon, expanded prompt and
parameter values as they were. Renaming a scenario, deleting it, or deleting
its workspace cannot rewrite the past. - A row that produced nothing says which nothing it was — still running, no
session started (with the scheduler's reason), no transcript ever reported, or
the transcript is gone. Never an empty box: the run happening and the run
producing nothing are different facts. A conversation that was/cleared
since says so out loud rather than presenting a stranger's tail as its result. - Three actions on a row, and deliberately no fourth. Go to the session
while it is still live, switching workspace first if it is running in another
one. Re-run, through the usual "Launch parameters" form with the recorded
values pre-filled and selected — never silent, because a scenario's parameters
may name a branch, a target or a person — and reconciled against the scenario
as it stands now, so a placeholder the prompt has since lost is dropped and
one it has gained comes up empty. Reveal the transcript in the file
manager, reveal only, neveropen: a.jsonlis not handed to whatever is
registered for it. - Where an action cannot work the control says why, on itself and in its
accessible name — a scenario that was deleted, a workspace that was, a
transcript that was never written.aria-disabledrather thandisabled, so
the reason is reachable without a mouse. - History is immutable. No row can be edited or deleted; a journal whose
rows can be revised answers nothing. Erasing exists at one granularity —
a scenario's history wholesale, from the head of the screen while it is
narrowed to that scenario, so the rows it erases are the ones on screen. - Recording can be switched off, and the screen says so rather than looking
empty. Retention is the last 100 runs per scenario, pruned at app start —
a time window would keep three records for a monthly job and two thousand for
an hourly one. - The scenario's sidebar row grows a state dot for how its last run went, which
opens the history narrowed to that scenario. An indicator and nothing else —
that row has learned this lesson once already, when one ⏰ was both a status
badge and a real launch, and reaching for information started a session.
Shift+Enter writes a second line (#234). It used to submit the
half-written message. xterm maps Enter to a bare CR whatever modifiers are
held, so Shift+Enter reached claude byte-identical to Enter and claude
did the only thing a bare CR allows. The app is the terminal here, so it now
makes the binding every real terminal makes — the one claude's own
/terminal-setup writes into iTerm2 and VS Code: ESC + CR. Alt/Option+Enter
and Ctrl+Enter map to the same newline, since neither can mean anything else
and they are what a person tries next. Plain Enter still submits, and zoom
keeps its binding — Cmd+Enter on macOS, Ctrl+Shift+Enter on Windows and
Linux.
Two defects fixed
- The status pill took the keyboard every five seconds (#203) — and did it
precisely while a session sat waiting for an answer, which is the state the
pill exists to report. On macOSshow()ismakeKeyAndOrderFront:, and a
focusable window duly became the key window on every poll tick. The pill is
now built non-focusable, and the count is only emitted when it actually
changes. Typing into a terminal is no longer interrupted. Open in browserdid nothing (#252) — no browser, no navigation, no
feedback. A Tauri v2 webview has nowhere to open atarget="_blank"link, so
the navigation was simply dropped. Five other links were dead the same way:
the pull request row, the GitHub screen, links and images in rendered
markdown, the diff drawer, and a card. All six now go through one gate that
openshttp/httpsin the system browser and refuses everything else. The
capability grants URL-opening scoped to those two schemes and nothing more —
a URL out of a pull request description must never be able to name a file to
run.
Housekeeping, no behaviour attached
- 44 spec and plan documents retired (#253) — the record of a workflow this
project no longer uses. Work is scoped in GitHub issues and decisions are
recorded indocs/adr/; a standalone spec was a third, unmaintained account
of intent. Four code comments that cited one for a measurement now state the
measurement inline. - The first two ADRs (#216) — how connected social accounts will hold
credentials, and who uses them over what. Both are inputs to #205; the
"the app stores no tokens" invariant is narrowed rather than deleted. - Where agents look things up (#202) — the issue tracker, the five canonical
triage labels, and the domain-doc layout, written down so a skill does not
guess and open a pull request againstmain. - The README gains the Features bullet the history screen shipped without.
Known, and tracked
Found while building this, left out on purpose:
- #235 — the history screen reads an unreadable journal as an empty one.
- #236 — no test covers the history screen's boot-level wiring.
- #249 — an unpinned scheduled scenario runs in whichever workspace happened
to be active. The form says so; saying so is not the fix. - #255 — every modifier+key pair other than the three now translated still
collapses. The real answer is negotiating the kitty keyboard protocol.
Still open from v0.2.0: #199 (after /clear, restart and auto-restore
resume the pre-clear conversation), #195 (a non-UTF-8 transcript reports
zero tokens and no name, silently), #194 (a renamed card tile loses the ☑
that says which card it is on).
Install
macOS — download the .dmg for your architecture (aarch64 for
Apple Silicon, x64 for Intel), drag the app to Applications, then
clear the quarantine flag once:
xattr -cr /Applications/cowork-deck.app
Linux — download the .AppImage, chmod +x it and run, or
install the .deb.
The app checks this page for updates on launch and installs them
in place; the xattr step is first-install only.