Skip to content

Release 5.8.0 — Remote Control - #67

Merged
serialexperimentslainnnn merged 9 commits into
mainfrom
develop
Aug 28, 2026
Merged

serialexperimentslainnnn merged 9 commits into
mainfrom
develop

Conversation

@serialexperimentslainnnn

Copy link
Copy Markdown
Owner

Publishes 5.8.0. Merging this cuts the tag and ships to the Marketplace, unattended.

What ships

Remote Control. A chat running in the IDE can be driven from claude.ai or the Claude mobile
app, and Claude keeps executing locally the whole time. A phone button in the chat's button row,
left of the guard's shield, and a Remote control row in the settings menu. Neither lights up until
the CLI has accepted, and a refusal names its reason on the button and in the chat.

The slash command is closed in the mode this plugin launches the binary in. The control request
behind it is not, and that is what the plugin sends. Neither that subtype nor the withdrawal frame
below is declared in the vendored SDK types, so both were verified against the binary.

A permission answered from the phone now closes its card here. The binary withdraws the prompt
it left with the host over a top-level control_cancel_request frame; the parser had no entry for
that type and dropped it, so the card stayed forever. Found by using the feature, fixed and
validated by hand.

The drift baseline is reconciled. checkDrift still recorded SDK 0.3.233 and binary 2.1.233
against tools at 0.3.250 and 2.1.250. Surface reports fully covered once the withdrawal frame was
modelled. The vendored SDK is protocol reference and ships to nobody.

Gates, run locally on this tree

JVM tests and koverVerify, detekt, spotlessCheck, ESLint, Prettier, 616 frontend tests, npm audit
on the distributed scope at 0 vulnerabilities, verifyPlugin, checkDrift, and the packaging
assertions: 0 node_modules entries in the zip, and LICENSE, THIRD-PARTY-NOTICES.md and the
licences directory present in the jar.

CI on the develop PR was green on the three jobs it runs plus CodeQL.

Validated by hand

Installed in PyCharm and exercised end to end, including approving a call from the phone and
watching the card close, and the refusal path against an account without Remote Control.

The release workflow reads the version from build.gradle.kts, and the README
states it twice as user-facing text: the badge and the name of the artifact
buildPlugin writes. All three move together or the README describes a zip
that no build produces.
The bump missed a fourth place the version is written. PluginIdentity is the
one the plugin announces on every outbound request, and the descriptor cannot
be read at runtime without an internal API this build refuses to ship, so the
constant is hand-kept and PluginIdentityTest is what keeps it honest. It went
red on 5.7.0 against a 5.7.1 build, which is the test doing its job.
The slash command is closed in the mode this plugin launches, and answers
"isn't available in this environment". The control request behind it is not:
the binary takes a remote_control subtype carrying an enabled flag, and runs
the bridge itself with the session credential. That is the same shape as the
btw command, which is a side_question request rather than the command it
looks like.

The reply rides SessionControlClient.send instead of SessionQueries.ask,
because a success comes back with no payload at all. Ask decodes the payload
whether the request succeeded or failed, so a toggle built on it would paint
itself on after a refusal and never say so.

Two ways in, one path: the composer's phone button and the settings menu row
both emit the same settingsToggle key, so there is one destination to keep
honest rather than two that can disagree.
The binary answers the enable request with an error when the account or the
organisation has Remote Control switched off, so the host state was already
right. What lied was the page.

The settings row flipped itself on the click, before the host had answered.
That is correct for every other row in this menu, because they write to the
settings document and cannot be refused; this is the first one whose
destination can say no. Rows may now declare themselves host-owned, and the
page leaves those alone until the state it is sent says otherwise.

The composer button had no way to fail. It stayed off after a refusal with
the reason reachable only by reading the transcript, which is the same as
failing silently for anyone who was watching the button they just pressed.
The refusal now travels to the page and the button wears it.
Remote Control is a new capability, not a repair, so the release is a minor.
The number is written in four places and the release workflow greps only the
first of them, which is why the other three are moved in the same commit.

The changelog section is the one the release job extracts for the GitHub
Release, and the release notes are what the Marketplace shows as What's New.
Both name what the feature needs to work, because the refusal a user is most
likely to meet is an account or organisation that has Remote Control off.
Approving a call from the phone left the card sitting in the chat forever.
With Remote Control on, the binary forwards the prompt to claude.ai as well,
and when the remote answers it withdraws the one it left here — over a
top-level control_cancel_request frame carrying the request_id it echoes.
The parser had no entry for that type, so it fell through to Other and was
dropped, and nothing ever took the card down.

The withdrawal writes no reply. The binary already has its answer and is no
longer waiting, so answering a request that was retracted would be inventing
a second verdict. It closes the review diff the same way a rejection does,
because a card that leaves without closing it strands the pane.

This is the connected surface the feature commit missed: enabling Remote
Control adds an inbound frame the plugin never had to understand before.
checkDrift had not been run since the tools moved: it recorded SDK 0.3.233
and binary 2.1.233 against a machine running 0.3.250 and 2.1.250. A drift
gate whose baseline is stale reports on a protocol nobody is speaking.

The detector updates the tools itself before reporting, which is what moved
the lockfile here. The vendored SDK is protocol reference and ships to
nobody, and package.json already allowed the newer one, so the range is
unchanged. The surface came back fully covered once the withdrawal frame was
modelled.
Its own section in the user guide and an entry at the top of What's new.
Says what the feature needs before it will work, because the account and
organisation gates are the refusal a reader is most likely to meet, and says
plainly that the guard still decides first on this machine — connecting a
phone changes who can answer a permission, never what the chat may do.
…ontrol

feat: drive a chat from claude.ai with Remote Control (5.8.0)
@serialexperimentslainnnn
serialexperimentslainnnn merged commit a639559 into main Aug 28, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant