Skip to content

Chat On Steroids 2.0.0

Choose a tag to compare

@github-actions github-actions released this 24 Aug 15:21
· 9 commits to main since this release

Windows installers for both architectures are attached below. Download the one that matches your
PC, then reload the browser extension — the app and the extension are versioned together and
the app refuses a mismatched copy.

  • Chat-On-Steroids-Setup-x64.exe — Intel/AMD
  • Chat-On-Steroids-Setup-arm64.exe — Arm (Snapdragon, Surface Pro X)
  • Chat-On-Steroids-Extension.zip — the extension on its own, for loading unpacked
  • SHA256SUMS.txt — checksums for all three

This is the first published release to carry the goal loop. It supersedes 1.9.9, which was tagged
in the repository but never published.

Why 2.0

Not because of what is on screen. Three modules that production no longer reached were deleted
outright, exec_command began refusing shell text it used to run against the wrong filesystem
dialect, and two process launchers stopped handing connector credentials to their children.
Anything built against the removed internals, or against the old pass-through behaviour, will
notice. The user-facing surface is the same one 1.9.9 described.

The goal loop

A second model reads each finished ChatGPT answer and writes your next message for you, until it
decides the thing you asked for is done — at which point it writes nothing at all. Off by default,
and it needs an OpenRouter API key, which is the one credential in this app a model can cause to
be spent.

The trust boundary is where the work splits. The page owns the one judgement only a browser can
make — that the turn is really over — using the same four-signal barrier a compaction brief waits
on: the stop control gone, the answer no longer growing, the tool rail still, and the app
reporting no local call open, held for eight seconds. A reply that fires early types "what about
the tests" into a chat that is still writing them, and the model then answers it as if it were a
correction. Everything after the barrier is the app's: the context, the key, the request, and one
draft per generation.

What leaves this machine is only your messages and ChatGPT's final answers — not tool calls, not
their results, not the interim commentary a turn produces while it works. A recorded session holds
file contents and command output, and none of that is anybody's next chat message.

The compaction button on the composer is a gear now, opening a small settings sheet in ChatGPT's
own type and hairline: a switch each for automatic compaction and the goal loop, and Compact &
resume now
as its single action. The panel above the composer says what the loop is doing, and a
failure shows its code rather than going quiet.

What was fixed

The full write-up is in docs/bughunt-follow-up-2026-08-24.md. Credible leads that were reviewed
but not reproducible enough to fix are tracked privately rather than published — see SECURITY.md.

  • A patch that moved a file onto itself deleted it. apply_patch writes the destination then
    removes the source, so source.txt and ./source.txt wrote the new contents and immediately
    unlinked them. Move verification now compares resolved identities and refuses before anything is
    mutated.
  • A glob starting with * searched a virtual root instead of your workspace. With no literal
    prefix before the first wildcard, *.ts and **/*.ts quietly asked a different question — and
    answered it successfully, which is the worse half.
  • A malformed Goal stream record could be typed into the composer as a finished reply. A
    truncated sentence was promoted to a message at EOF. A malformed record is now a protocol
    failure: the stream is cancelled and no draft is exposed.
  • Compact & Resume, automatic compaction and Goal startup used the capped UI list as an
    ownership index
    , so a valid older conversation came back session_not_recorded. All three now
    use the durable catalog.
  • Editing a Chat setting could be undone by a background status push. Home controls had a
    focused-dirty guard; the Chat sheet did not, so a half-typed threshold or worker count could be
    wiped mid-edit.
  • Virtual app paths inside shell text ran against the wrong filesystem dialect. PowerShell
    reads /workspace/file as a drive-root path, not this app's approved virtual root. exec_command
    now refuses that and names the two fallbacks that work.
  • A broken desktop helper could keep input authority while its replacement started, because
    its post-start error path skipped the retirement barrier that every other failure waits on.
  • "Extension folder opened" was shown when it had not. Electron reports shell.openPath
    failure as a resolved error string, and the handler discarded it.
  • Renderer redirects are vetoed as well as navigations; swarm:clearAgent validates its id at the
    IPC boundary; read charges the base64 it actually emits against its output budget; Fiber no
    longer skips assistant turns without a data-turn-id, nor swallows a message on a second id
    collision; and recovery hints stopped suggesting fixes for causes the command did not contain.

Security

Tunnel children inherited ambient connector credentials. The OpenAI tunnel client spread raw
process.env and cloudflared inherited the environment implicitly, so starting the app from a
credential-bearing terminal passed unrelated provider secrets into both children. Both launch
paths now use the shared environment scrubber, and the OpenAI path adds back only its own
control-plane key, the local MCP URL and its discovery headers.

Build

Built and smoke-tested on native Windows x64 and ARM64 runners, with the full typecheck-and-test
gate — 49 suites, 1,411 tests — green on both. noUnusedLocals and noUnusedParameters are now
permanently on; they are what surfaced most of the dead code this release removes.

Beta despite the version number. Behaviour may still change between releases.