Skip to content

Tell people when an addon has a newer release - #393

Merged
sivert-io merged 1 commit into
mainfrom
claude/client-addon-update-check
Sep 4, 2026
Merged

Tell people when an addon has a newer release#393
sivert-io merged 1 commit into
mainfrom
claude/client-addon-update-check

Conversation

@sivert-io

Copy link
Copy Markdown
Member

An addon can name where it is published, and the addons page says when that
repository has a release newer than what is installed.

{ "id": "face-framing", "version": "1.0.0", "repository": "Gryt-chat/addon-face-framing" }

The card then shows a v1.1.0 available chip and a button to the release.

Decisions worth arguing with

The button opens the release, it does not install it. Replacing an addon's
files means running whatever that repository publishes next, on the next launch,
in the renderer. Installing that on one click is a different decision from
noticing it exists, and it wants its own thinking about what gets verified
before it runs. This PR does the noticing.

repository is validated where the manifest is read, not where the fetch
happens. A manifest is a file anybody can drop in the addons folder, and this
value decides what gets requested — so the check is the shape: two path segments
of the characters GitHub allows in a name. No scheme, no host, no .., no query
string to point it elsewhere.

No api.github.com. /releases/latest redirects to /releases/tag/<tag>,
so the tag comes out of the Location header of a request that never follows it.
Same approach as the app's own update check, for the same reason — 60
unauthenticated calls an hour, shared with everything else on that address.

Checked when the page opens, not on a timer. Nobody needs to learn an addon
is out of date during a call.

Behaviour at the edges

  • No repository in the manifest: never reports an update. Right default for
    something somebody wrote for themselves.
  • A tag that is not semver: skipped rather than guessed at. latest and
    v2-final are real tag names and neither says anything about ordering.
  • Repository with no releases: /releases/latest redirects to /releases, no
    tag in it, reads as nothing to report.
  • Offline, renamed, deleted, rate-limited: the page is still the page.
  • Older desktop build without the IPC: the renderer checks for the method and
    skips.

Verified

Typecheck and lint pass. I have not exercised it against a real addon with a
real repository — there isn't one yet — so the network path is reasoned rather
than run. Worth pointing at a repo once an addon actually has one.

🤖 Generated with Claude Code

An addon can name where it is published, as `owner/repo`, and the addons page
says when that repository has a release newer than the version installed.

The check runs when the page opens rather than on a timer. Nobody needs to
learn an addon is out of date mid-call, and a check that only runs while
somebody is looking at the answer cannot spend their rate limit in the
background.

It reads the tag out of the redirect on /releases/latest rather than calling
api.github.com, which is the same trick the app's own update check uses and for
the same reason: 60 unauthenticated calls an hour, shared with everything else
on that address.

`repository` is validated where the manifest is read, not where the fetch
happens. A manifest is a file anybody can drop in the addons folder and this
value picks a URL, so the shape is the check: two path segments of the
characters GitHub allows in a name. No scheme, no host, no traversal, no query
string.

The button opens the release. Replacing an addon's files means running whatever
that repository publishes next, so the step where somebody reads it first is
the point rather than a gap. Installing in place is a separate decision and
wants its own thinking about what is verified before it runs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@sivert-io
sivert-io merged commit cde1e38 into main Sep 4, 2026
3 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