Skip to content

Releases: realvinn/stoke

0.9.6 — two silent data-loss bugs, a fire that looks like fire, and the quiet states

Choose a tag to compare

@github-actions github-actions released this 13 Sep 06:11
v0.9.6
214dd99

The relaunch that came back dead is fixed. Resuming a session reuses the
same status key as the one it replaces, and the relaunch fires the kill without
waiting for it — so the old claude's exit handler could land after the
replacement had written its settings file, delete it, and leave the new CLI to
exit with "Settings file not found". Whether it happened at all depended on how
long the old process took to die, which is why it looked random for months. The
files have an owner now, and a dying predecessor cannot clean up its successor.

npm run check was deleting the live files of every Stoke session on the
machine
— dev and installed alike — on every run, for five weeks. The
statusLine test swept the real shared directory with a clock set seven years
ahead, so every real file looked stale by definition. Its comment claimed
"entirely hermetic" because the clock was fake; the directory was real,
which is what made the fake clock dangerous. It sweeps its own fixtures now and
asserts that a bystander survives.

Those two together explain a note that had sat in the project's own docs for
months saying this was harmless and telling people not to investigate.

The installer no longer promises root an install that cannot start. Electron
refuses to run as root on Linux and aborts inside Chromium's startup, before any
of Stoke's code exists — so nothing in the app can catch it or explain it. The
installer warns before the download instead, while interrupting is still free,
and says both ways out. A new --preflight prints what the script makes of a
machine without resolving or downloading anything, which is also what lets the
Linux branches be tested from a Mac.

The campfire was redrawn. The old one built its flames out of ( ) and read
as loose punctuation; the new one is a white-hot bed that never moves with
interleaved tongues leaning in a draught above it. Picked from four independent
designs, judged rendered.

"Up to date" is a badge with a timestamp, in both update panels. A version
line with no timestamp is indistinguishable from one written at boot and never
refreshed — which is exactly what a stale checker looks like. It refuses to
appear over an error, a download in flight, a version that could not be read, or
a pinned channel sitting behind latest.

Keystrokes nobody claimed now go to the terminal. Click the usage chip, type,
and the characters used to be delivered correctly to a button, which did nothing
with them. Chords, text fields and overlays are all still theirs.

Providers stops storing keys that did nothing. The OpenAI and xAI keys were
injected into every session and could not affect it — Claude Code speaks neither
wire format. Codex CLI, Grok CLI and OpenCode are detected instead, so you can
see what the machine has.

Also: the Stoke mark in the title bar can be turned off, and two "Why?"
disclosures are gone — one hid the machine's own LAN addresses behind a summary
click, which is the one moment a collapsed hint costs more than it saves.
-----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgRMU791FgMe8r+DfqyzVBFQ6kaz
8vnoPpPI8Ui7gGH3MAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
AAAAQDRXuWK1f6pxh/dWs/FnnhsYQdH/zjVtq6/3HET7HZXTg80Oflc7rGQSw6h4aN/0Gb
lUeNC9qoxp5WFhRi3BqA4=
-----END SSH SIGNATURE-----

0.9.5 — install it with one line, on every platform, and bring your own key

Choose a tag to compare

@github-actions github-actions released this 12 Sep 10:25

Three streams landed since 0.9.4.

One-line install. stoke.vinn.dev is a single Cloudflare Worker whose only
job is deciding which of three bodies a request gets: the shell script, the
PowerShell script, or the page. Both scripts verify what they downloaded before
running it, and each keeps its whole body inside a function called on the last
line, because a piped sh executes as it reads. verify:install runs the
shipped script rather than reading it. The installers now light a campfire on
first run and on an upgrade — decided from a version, not a boolean, so an
upgrade counts too — and it is skipped under reduced motion.

Every platform, from one list. A release used to be whatever the machine
the tag was cut on could build, which is why every previous release shipped the
Windows exe and little else. Each of win-x64, win-arm64, mac-arm64, mac-x64 and
linux-x64 now builds on its own native runner: npm installs only the
@lydell/node-pty-<platform>-<arch> matching the build host and node-pty
resolves that at runtime, so a cross-arch build produces an installer that
launches and then throws on the first session, with no build error anywhere.
The per-job update manifests are merged rather than flattened — Windows x64 and
arm64 both write latest.yml — and a gate refuses to publish a release whose
feeds cannot update somebody. Linux x64 is built but has never been booted;
treat it as experimental.

Bring your own key. Settings → Providers takes an Anthropic console key,
OpenRouter, or any Anthropic-compatible gateway, plus OpenAI and xAI keys for
Codex and Grok. This exists because a GUI launched from the Dock or Start menu
sees none of your shell-profile exports. The keys are stored in plain text in
Stoke's own settings.json, like the rest of your settings.

Three defects in that panel were found and fixed before it shipped. A key
pasted into it used to be thrown away when Escape closed the sheet — while the
auth mode it was pasted for was kept, so every new session then refused to
start naming the field you had just filled in. Its test suite was written and
registered nowhere, so it ran on no machine and in no CI. And the headless
runner behind the worklog ignored the settings entirely, so the users the panel
exists for got working tabs and a worklog that could not authenticate.

Also: the context ring reads at a glance, tabs drag the way Chrome's do, and
sidebar search reaches inside a project.

0.9.4 — tabs drag the way Chrome's do, the context ring reads at a glance, and search reaches inside a project

Choose a tag to compare

@github-actions github-actions released this 12 Sep 05:45
v0.9.4
354fe3e

Four things you can see, and one that only shows up when Claude works on this
repo. Every one of them was driven in the running app over CDP before it landed,
which is how the bugs listed under each were found.

Tabs drag the way Chrome's do. Dragging a tab used HTML5 drag-and-drop, so
what followed the pointer was Chromium's translucent bitmap, free to wander over
the terminal and out of the window, while the tabs underneath stayed put until
the pointer crossed a neighbour's centre — at which point one jumped a whole slot
with no animation. Between 100 and 290 px of travel bought you nothing at all.
The real tab moves now, locked to the strip and clamped to it, and its neighbours
slide aside as it passes them. Pressing a tab selects it immediately, releasing
settles it into the gap, Escape puts everything back, and the strip scrolls
itself when you reach its edge. The order is committed once, on release, instead
of on every slot crossed. Terminal panes are rendered in an order a reorder
cannot change, so moving the tab you are working in no longer moves the xterm
node out from under your focus.

The context ring reads at a glance. It ran on two thresholds with the healthy
state drawn in the brand accent, and it was never allowed to turn red. It has
four bands now, on the percentage you can actually read on screen: green to 30,
orange to 60, red to 80, and from 81 a solid red disc. The colours are solved per
theme against the page behind them rather than reused from the warning palette,
which renders gold and salmon on the dark themes. The status bar, the sidebar,
the launcher and the phone all take the same rule from one module instead of
three hand copies.

Bypass mode stops shouting. With bypassPermissions as your default, every tab
carried a dashed amber ring forever — an alarm colour for a setting, at ten times
the contrast of the ring it was drawn on, in the same tone as the arc inside it.
It is a row of slate beads in the theme's own neutral now, and any bead the arc
would touch is dropped rather than half-covered. Amber is left for things that
are actually happening.

Every plan-limit bar is the same length again. Each row of the usage panel
laid out its bar and its reset text on one line, with the text column sized to
its own content — so the bar got whatever was left. A row reading "ahead · resets
Mon 09:00 · in 3d 14h" left it exactly 0 px, and the percentages slid 139 px
sideways down the panel. The text sits on its own line now and the bar has the
one below it, so every bar starts and ends in the same place at every interface
scale, and the pace marker is comparable between rows.

Search reaches inside a project. The sidebar matched project names, paths and
labels, and nothing else: chats were invisible until you expanded the project
holding them. It now indexes every session's title and opening message across
every project — reading only the first and last chunk of each transcript, about
115 ms for the 95 on this machine — and shows the matching chats under their
project with the hit highlighted. Cmd+K had its own matcher that ignored folder
labels, so a renamed project could not be found by the name you gave it; both
surfaces share one rule now.

Working notes. CLAUDE.md is 27 KB rather than 155 KB, because Claude Code
injects it into every session and every subagent before a word is typed. Each
gotcha's full text moved, byte for byte, into path-scoped rule files under
.claude/rules/ that load only when the code they describe is opened; CLAUDE.md
keeps one checked line each, so the numbers cited across 62 files still resolve.
Two review passes over that move caught index lines that would have misled
whoever read them, and corrected claims the code had outgrown.
-----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgRMU791FgMe8r+DfqyzVBFQ6kaz
8vnoPpPI8Ui7gGH3MAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
AAAAQEzN1yj5NGZxwxRkK8fSw5A9WQ2l735g9IhqR2LK+Xmqi4JvWkYZdck2tOx5PzW561
wCle6WV5Wh0Sf6pq2fCg4=
-----END SSH SIGNATURE-----

0.9.3 — a suite that could never fail now can, Windows gets its status line back, and a dozen races close

Choose a tag to compare

@github-actions github-actions released this 02 Sep 15:51
v0.9.3

Everything here came out of auditing the app subsystem by subsystem, so it is
mostly defects that were quiet rather than features. The two that matter most
are about the checks themselves.

The colour suite could not fail. verify-color.mts counted its failures,
printed FAIL on every failing line, and never set an exit code — so npm run check and the release gate both went green whatever it found. It is the only
automated check for the contrast maths, the theme ladder's floors and the
accent-ink derivation. And the CI job's hand-written list of suites had drifted
out of step with npm run check for the second time, so the theme generator,
file-drop quoting and the phone link were enforced locally and gated no release.
That list is derived from the check chain now, so it cannot drift again.

The statusLine shim never ran on Windows machines with Git for Windows
installed
— which is the CLI's own preferred configuration. A PowerShell call
operator was being prepended unconditionally, and a leading & is a syntax
error in a POSIX shell. Those machines had no context ring, no plan-limit
figures, no activity dot, no notifications, and lost their own configured status
line too. Stoke detects the interpreter now, mirroring the CLI's own locator.

Phone access. The WebSocket had none of the size discipline the HTTP paths
were deliberately given, and a resize frame could hand node-pty a nine-digit
dimension. The bearer key stayed in the phone's URL bar and history forever
instead of being stripped once the cookie was set. And "Require Cloudflare
Access" claimed in three places to admit only tunnel traffic when it checks that
the headers are present and cannot verify their signature — it says what it does
now. Every screen also paints the desktop's real theme, rather than only the
terminal.

Races and leaks. Two Claude Code settings written at once silently dropped
one, with both reported as saved. Resume and Start again lacked the guard the
relaunch pill got in 0.9.0 — and "Resume all" followed by "Close them" would
drop every tab and then have each one reappear with a live process behind it.
"Resume all" also stole the selection to whichever session started last. A
manual "Update now" could run a second claude update beside the automatic one.
The docked browser was never destroyed with its window, and the six-hourly
update timer was never cleared, so both accumulated across close-and-reopen on
macOS. A crashed browser tab now recovers instead of sitting there dead.

Settings. Dragging any of seven sliders wrote the whole settings file
synchronously on the main thread on every tick, blocking every session's output
with it. Closing the sheet with Escape threw away whatever you were typing in an
SSH or profile field, because unmount fires no blur. And the Interface scale box
snapped the whole UI to its minimum on the first keypress, because an empty
number field reads as zero.

Colour and the meter. Hovering a primary button dropped its label below the
contrast floor on 28 of 108 theme-and-accent combinations, including one shipped
theme's own accent. The theme editor had two controls labelled "Accent colour"
writing different state, and its contrast report was silent on five of the
seventeen tokens it invites you to override. The context ring was not counting
the last reply's tokens, so it understated how full the window was between
turns — the one direction this codebase treats as dangerous.

The worklog. Rejecting a proposal is the only thing that stops the scan
offering it again, and the button for it had been left behind by an earlier
refactor: the IPC worked and nothing in the app called it. Proposals piled up
with no way to clear them while the title bar counted them and opened an
unrelated report. Reject is back, "Review all" shows everything pending, and the
copy names what it actually opens.
-----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgRMU791FgMe8r+DfqyzVBFQ6kaz
8vnoPpPI8Ui7gGH3MAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
AAAAQCCE/H6B8w3TPZMqt1dZ0UHu5WULluopmvTjVgch3nRtOCytd/VQMjjbiIG/ohC3MI
xA3KtsWhVqpbtufKFsggQ=
-----END SSH SIGNATURE-----

0.9.2 — the usage chip keeps its numbers, files can be dropped on the terminal, and the launcher stops cutting off its own top

Choose a tag to compare

@github-actions github-actions released this 02 Sep 10:07
v0.9.2
c9454a2

Usage
"The usage chip never works" turned out to be three separate faults,
none of which was the endpoint being unavailable. Measured while the
account route was answering 200 with real figures and the panel read
"Usage unavailable (429)".

Opening a tab evicted the numbers. Which statusLine reading answers
for the account-wide limits was chosen by arrival time alone, but a
payload states no rate limits until its session's first API response
lands — so a newly opened tab wrote the newest payload on the machine,
stated nothing, and took a live session's figures with it. This is
almost certainly the one you hit most, because opening a tab is the
trigger.

A failed read deleted the numbers it failed to refresh. The failure
snapshot carries no windows, it replaced the cache outright, and the
meter let the error veto data already in hand.

The fifteen-minute backoff was Stoke's invention, not Anthropic's. A
429 at 18:08 put the chip out until 18:23 while the same token got a
200 at 18:16. Retry-After is now honoured exactly when sent, and
otherwise the wait starts at a minute and doubles.

Terminal
Dropping a file types its path, quoted for the platform — the shortest
way to hand Claude Code a screenshot. Multiple files come in
space-separated, a tab dragged across the terminal is ignored, and
dropping a file anywhere else in the app can no longer navigate the
whole window to it.

Launcher
Expanding "Launch options" clipped the top of the card with no way to
scroll to it: at a 320px pane the top sat 273px above the visible area
at scrollTop 0, and the browser did not count the clipped part, so
scrolling could never reach it.
-----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgRMU791FgMe8r+DfqyzVBFQ6kaz
8vnoPpPI8Ui7gGH3MAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
AAAAQL4YBoBDVxN7itaSHSDckr3Y9jKxMV68QBCRjlu5eU0k9KYNk/qZMqcx2oNQ91V1fL
dTg5rB/hu7U7ugKS/peQs=
-----END SSH SIGNATURE-----

0.9.1 — the phone link points where you chose, Cloudflare has a setup wizard, and the usage chip comes back

Choose a tag to compare

@github-actions github-actions released this 02 Sep 07:49
v0.9.1
744c348

Mostly fixes, and two of them were things Stoke was doing to itself.

  • The transport is a choice again. Saving a hostname used to pin the "Reach
    it from" picker to Cloudflare Tunnel permanently — the other two segments lit
    nothing when pressed — because a three-way choice was inferred from two
    booleans plus a non-empty string. Worse, the link followed the same rule: with
    a hostname saved and no tunnel running, the QR code encoded https://<host>/
    while the server listened on your LAN, so it pointed at a name nothing served.
    There is an explicit preference now; the binds mean only what the socket
    listens on. A running tunnel still wins over everything, because that is a
    fact about now rather than about a config file.

  • Setting up a Cloudflare Tunnel is five steps that say where you are stuck,
    instead of a box printing four commands. Each step reports what it found, runs
    itself where that is possible, and quotes cloudflared rather than paraphrasing
    when it fails. What each step can detect is not uniform and the panel says so:
    install and login are local facts, whether the tunnel exists is a live API
    call and so has a third answer — "could not ask" — and the DNS route cannot be
    read back at all.

  • Error 1033 gets named where you can see it. tunnel route dns refuses to
    overwrite an existing record, so a hostname that ever pointed anywhere keeps
    pointing there while Stoke runs a different tunnel and draws a QR code for the
    name. The panel now says so beside the code, with the remedy, and "Replace the
    existing record" is offered on the first attempt rather than only after a
    failure. It also says that a Cloudflare Access policy is a separate layer and
    not the cause — turning Access off would expose the hostname and change
    nothing about the 1033.

  • A restarted tunnel no longer orphans the old one. cloudflared shuts down
    gracefully on SIGTERM, draining for up to its grace period, so a restart left
    two connectors serving one tunnel — and when the old one finally exited it
    cleared Stoke's handle on its replacement. The panel then said "not running"
    while it was running, Stop had nothing to kill, and quitting could not clean it
    up either.

  • The chip works again with no session running. It was reading an expired
    token out of ~/.claude/.credentials.json while a live one sat in the login
    Keychain, and returning "sign-in has expired" without ever making the request.
    It compares freshness now rather than preferring a location. The 30-second
    poll was never broken — it was faithfully re-fetching the same error, which
    looks identical to not polling at all.

  • A rate-limited chip says when it will try again, and stops offering a "Try
    again" button that could only return the same cached failure.

  • The close button belongs to the tab, not to the end of the title. It sat
    wherever the title happened to end and moved every time Claude renamed the
    session, which is the one thing a close button must never do.
    -----BEGIN SSH SIGNATURE-----
    U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgRMU791FgMe8r+DfqyzVBFQ6kaz
    8vnoPpPI8Ui7gGH3MAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
    AAAAQHXMa95i49PLIIq5AN/oDAhtGzuQXJEEi/9skDDCxdtFsrNGM0iW9boKlrVO2DNEvM
    Yyfn4+EFbVcLfVsaEEDAc=
    -----END SSH SIGNATURE-----

0.9.0 — the terminal is a terminal again, the theme follows your Mac, and Stoke tells you whose move it is

Choose a tag to compare

@github-actions github-actions released this 02 Sep 05:23
v0.9.0
a03bcf9

The largest release so far. Sixteen commits, most of them about how the app
reads rather than what it does.

  • It fills its pane, edge to edge. The rounded card that shipped in 0.8 is now
    a setting rather than the default: it is a deliberate look, and it is worth
    turning on with a wallpaper behind the window, which is what it was built for.

  • A Terminal settings pane: font, size, line height, letter spacing, cursor
    style and blink, bold weight, a contrast floor, inner padding, smooth
    scrolling, and that frame.

  • Copy mode is gone. Shift-drag, Option-drag, right-click Copy, Copy screen and
    OSC 52 already covered everything it did, and it took Escape away from the
    pane while it was on.

  • Cmd+Shift+V pastes an image from the clipboard into the prompt.

  • Follow your system: pick a dark theme and a light one, and macOS chooses. Both
    picks stay marked in the grid; clicking a card sets the one matching its own
    appearance.

  • Six new built-ins — Lantern, Graphite, Lagoon, Rosé, Ink and Mist — and two
    new dials behind them: a page colour, so a dark theme can actually read as
    teal or rose rather than as a grey with a coloured accent, and a true black.

  • A wallpaper behind the window, with the surfaces translucent over it.

  • The theme picker draws each theme as a miniature window rather than a swatch.

  • Stoke knows whose move it is. The CLI's own hooks report when a turn starts,
    when it ends and when Claude is asking for something; the tab strip shows a
    dot, the status bar says so in words, and an OS notification can be raised for
    a session you are not looking at.

  • The usage chip says how much of each plan window is left and when it comes
    back, rather than how much has been spent.

  • Phone access is one press. "Open on phone" mints a key, picks the tailnet or
    the LAN, starts the server and shows a code that actually resolves — and the
    phone paints the desktop's own palette.

  • Every tab is one width, so the strip stops rearranging itself when Claude
    renames a session.

  • Dragging a tab moves it live, rather than ghosting it and drawing a dashed
    rectangle where it would land.

  • Next and previous tab on Shift+Cmd+] and [, and the selected tab is scrolled
    into view.

  • The launcher folds its four launch options behind a summary of what they say,
    and offers recent projects when nothing is selected.

  • The sidebar shows a dot on any folder with a session running and a Start
    button on hover, and renamed folders keep their name in the tab strip.

  • "Resume all" on the restore bar.

  • The Claude Code pane's fifteen rows are five groups.

  • Focus moves into the sheet and Tab stays inside it.

  • Hidden projects are listed and restorable one at a time.

  • Advanced folded into Updates; the always-on schema-version warning is a note.

  • The menu indents its rows under their headings.

  • An expanded sidebar row listed the selected project's sessions rather than its
    own, so clicking one resumed a session in a different folder.

  • The restore bar's "Start fresh" killed every tab including live sessions.

  • Closing several tabs at once closed one of them, with the others' processes
    already terminated.

  • The launcher and the Sessions pane were two writers on the same four launch
    defaults, so changing one in Settings left the other launching with the old
    value until a restart.

  • Cmd+K picked a project and appeared to do nothing when a session was in front.

  • Ask Claude typed into tabs whose process had exited.

  • Two next-tab presses in one frame moved the selection one tab.
    -----BEGIN SSH SIGNATURE-----
    U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgRMU791FgMe8r+DfqyzVBFQ6kaz
    8vnoPpPI8Ui7gGH3MAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
    AAAAQKCuChjEbzm6x3Bq7K+zeK1mitLRSZtQpsQS09sgljNiV5kPRUFZ1gefTU/VkeY2SY
    +ZZGmhPew1lyzlpkr/2wY=
    -----END SSH SIGNATURE-----

0.8.0 — a theme editor that previews on the real window, and a settings sheet you can find things in

Choose a tag to compare

@github-actions github-actions released this 01 Sep 23:13
v0.8.0
98e8108

Custom themes without hand-writing forty-three colours. Until now a custom theme meant
typing a customThemes block into settings.json by hand, which the Appearance hint
cheerfully described as the way to do it. There is an editor now, and it edits a five-field
seed — appearance, neutral hue, tint, accent, name — and generates the rest.

That is the design rather than a simplification. Offering forty-three colour fields would
rebuild exactly what the twelve-step ladder replaced: the old hand-picked palette passed
every suite in the repo while its borders measured APCA Lc 0.00 against their own page. A
seed cannot express that, and a suite sweeps the full slider range in both appearances to
keep it that way. Any single token can still be overridden — someone who opens a colour
field and types a value means it — and what the override costs is reported by name, ground
and contrast floor rather than silently dropped.

The preview is the whole window, not a swatch grid. Every rule reads its colour from a
custom property, so a draft repaints the sidebar, tab strip, status bar and dialog together,
which is the only way to see a border go invisible against a hovered row. Colours read and
write as OKLCH, HSL, RGB or hex.

The theme generator the code always claimed existed. themes.ts opened by saying every
hex in it was generated from one hue plus one accent and told the reader to regenerate. That
generator was not in the repository and never had been — the two functions it needed had
zero callers — so the documented way to change a theme could not be followed and the only
one that worked was hand-editing a hex, the single thing the ladder exists to forbid. It
exists now, and it reproduces all six shipped palettes byte-for-byte.

It also answers "the themes all look the same", which turned out to be measurable rather
than taste: the neutral chroma step was C 0.0022 — imperceptible by its own comment — so the
hue had almost nothing to act on, and Ember and Clay shipped an identical page and text
colour while nominally being a warm grey and a terracotta. Themes take a tint now, defaulting
to exactly the historical value, with a ceiling measured against the contrast floor.

A settings sheet with a shape. The ten nav rows were ordered by how often a section gets
opened, which reads as arbitrary because frequency is invisible; they are grouped now, with
updates at the end. The fifteen Claude Code rows are no longer folded behind a disclosure —
that existed when the sheet was one flat column and has had nothing to justify it since the
sheet grew sections.

Three menus stop sliding in sideways. The shared pop animation began at translate: -50%,
which is only correct for an element that already rests there. Exactly one of its four users
did. The context menu, voice strip and copy strip each swooped across half their own width on
every appearance — 88px for the context menu, which is why it read as a smeared outline
rather than as a menu in the wrong place.

Stoke says when the CLI's update channel is behind. Following autoUpdatesChannel stopped
the panel advertising updates claude update would refuse, and left it with nothing to say
about the pin itself. Measured on a real machine: installed 2.1.237, stable at 2.1.236,
latest at 2.1.258 — the updater declining correctly, the panel reporting nothing to install
correctly, claude doctor finding no issues, and the CLI twenty-two releases behind with
nothing anywhere saying so. The gap is now reported alongside the channel's own version, with
one press to switch and update. Stoke never switches it unasked: a deliberate stable is a
legitimate choice.
-----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgRMU791FgMe8r+DfqyzVBFQ6kaz
8vnoPpPI8Ui7gGH3MAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
AAAAQLFx2gepFZnIP/XRzdHJC9LbtoQ4mWmbZMJLTz0Dmrn6UGGEg+snh0BLo4XdCuzAoH
pm9qK96s1K9eXQ9BCiUAI=
-----END SSH SIGNATURE-----

0.7.11 — Stoke finds the CLI even when the login shell will not say where it is

Choose a tag to compare

@github-actions github-actions released this 01 Sep 00:38
v0.7.11
9cc8c5c

"Could not find the claude executable" while claude --version answers
perfectly well from a terminal, cured only by quitting and reopening. If you
have ever seen that, this is the release for it.

A GUI app launched from Finder or the Dock inherits PATH=/usr/bin:/bin:/usr/sbin:/sbin
and nothing else. Claude Code installed through a version manager — mise, asdf,
fnm — lives in a directory that only reaches PATH once the shell hook in your
.zshrc has run, so Stoke asked a login shell for its PATH and searched that.

That probe was the only channel: a mise install appears in none of the ten
directories Stoke fell back to. It has a five-second timeout, and a heavy
.zshrc — pyenv, starship, fzf, zoxide, syntax highlighting, anything touching
a sleeping external disk — can spend it. Worse, a failed probe was cached for
the life of the process, so one slow launch left Stoke unable to find claude
until it was restarted, which is exactly why it felt random.

  • The shim directories are searched directly. mise, asdf and fnm all publish
    a shim directory that needs no shell hook at all — ~/.local/share/mise/shims/claude
    runs correctly with nothing but the four system directories on PATH. Naming
    them means the login-shell probe is an optimisation again instead of a single
    point of failure. MISE_DATA_DIR, ASDF_DATA_DIR, FNM_DIR and
    XDG_DATA_HOME are honoured, and shims outrank /usr/local/bin so a stale
    copy from an old install cannot win.

  • A failed probe is retried after 30 seconds instead of never. Starting a
    session re-probes, so trying again is now a real fix rather than a restart.

  • The error message stopped lying. "Install Claude Code" is bad advice when
    the CLI is installed and the probe is what failed — following it means
    reinstalling something that already works. When the probe is the cause the
    message says so. All four places that can miss share one message now,
    including the one you actually hit when starting a session.

  • Every suite npm run check runs is now gated in CI too. Four had drifted out,
    including the new one, so the release gate was checking less than a local run.

Nothing else in the app changed, and there is no migration — install over the
top.
-----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgRMU791FgMe8r+DfqyzVBFQ6kaz
8vnoPpPI8Ui7gGH3MAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
AAAAQOplScQnyVu767L+eTdzsaKB9uUenSGF/jxFdvEqkibSoxw6FdzaCdvFwZu7TLwIiA
31Ddi+smfk8VXxTnwcdwM=
-----END SSH SIGNATURE-----

0.7.1 — the CLI update panel tells the truth, and a session can move to a new CLI without losing the chat

Choose a tag to compare

@github-actions github-actions released this 31 Aug 23:12
v0.7.1
29a8237

Stoke followed the wrong update channel. checkForUpdate read the npm
latest dist-tag while claude update follows autoUpdatesChannel from
~/.claude/settings.json. On a machine pinned to stable those were fifteen
releases apart, so the panel advertised an update the CLI would always decline —
and then blamed your package manager for it, advice claude doctor flatly
contradicts. Stoke already drew that setting; one half of the app wrote the key
and the other half never read it. It reads the configured channel now, names a
channel that publishes nothing rather than substituting a number, and refuses to
auto-update when the CLI's own updates are switched off.

A running session is stuck on the claude it started with. Updating the CLI
leaves every open chat on the old binary, indefinitely, with nothing saying so.
The status bar now offers relaunch on <version> when the session in front is
behind the installed one: it stops the process and resumes the same conversation
on the new version, in the same tab. SSH tabs and --continue tabs are refused
with a reason rather than silently, because neither can be resumed safely.

Three bugs fixed on the way, two of them long-standing:

  • The context meter read 200k for any resumed 1M session — the payload naming
    it is deleted with the old process and rewritten a second later, and nothing
    recomputed the window once the transcript stopped moving. Measured at
    125k/200k · 63% while the payload on disk said 1000000. This affected the
    paused-tab Resume too, since tab restore existed.
  • verify-tabs.mts printed its own tally two thirds of the way up, so a third of
    the file could print FAIL and still exit 0.
  • The relaunch pill could be double-clicked into five tabs and five claude
    processes resuming one transcript.

macOS auto-update from 0.7.0 works: same signing certificate, so no manual
install this time.
-----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgRMU791FgMe8r+DfqyzVBFQ6kaz
8vnoPpPI8Ui7gGH3MAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
AAAAQKE4MQawCb86dcC/Yl8r2Pkvhtz4B7tuFYE9VIGHTx30FeEyNSbHnUBaiINj1Irli4
mtpYSJOQoOvi3x1pt3OAc=
-----END SSH SIGNATURE-----