Skip to content

cowork-deck v0.3.0

Choose a tag to compare

@github-actions github-actions released this 12 Aug 12:54
· 158 commits to dev since this release
6b6b7b3

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.jsonl in 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, never open: a .jsonl is 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-disabled rather than disabled, 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 macOS show() is makeKeyAndOrderFront:, 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 browser did nothing (#252) — no browser, no navigation, no
    feedback. A Tauri v2 webview has nowhere to open a target="_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
    opens http/https in 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 in docs/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 against main.
  • 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.