4.0 KiB
OpenCode Updates
The updates Worker serves all selected artifacts for a channel.
curl 'https://opencode.ai/update/api/latest'
curl 'https://opencode.ai/update/api/latest/cli'
curl 'https://opencode.ai/update/api/latest/cli/npm'
The same Worker also serves the original https://update.opencode.ai hostname without
the /update prefix. Admin forms, pagination, and redirects preserve the request's mount.
Minimum releases
Each channel/name/distribution can mark one retained artifact as minimum, independently
of its active artifact. Set or clear it from the admin page. Publishing a new active
release preserves the minimum marker.
Clients send their running version as ?current=<version> and use the CLI's default
User-Agent: opencode/<channel>/<version>/cli. When current is absent, the service
parses that User-Agent or the older opencode/<version> format.
The caller's channel comes from the default User-Agent, or from a preview version
such as 0.0.0-beta-18955 when that channel is absent. If an identified caller channel
differs from the requested channel, the service serves the active release without
applying the minimum. Historical next and beta count as the same channel.
A caller below the minimum receives that exact
artifact; callers at or above it receive the active artifact. An unparseable caller
version receives the minimum. Requests with neither version source receive the active
artifact. All three public API paths apply the same selection and use Cache-Control: no-store because responses can depend on the User-Agent.
Version comparison uses semver, normalizing preview run numbers to numeric prerelease
identifiers and historical next versions to beta. The /api/next channel also
resolves to beta.
Choose a minimum that older clients can install and that can itself consume the active
release. For the CLI package migration, retain a package-aware release published as
@opencode-ai/cli as the minimum before activating releases under @opencode/cli.
Both admin mounts must be protected by the same Cloudflare Access self-hosted application:
- Public hostname/path:
update.opencode.ai/admin* - Public hostname/path:
opencode.ai/update/admin* - Policy: allow the OpenCode team identity group
Configure Access before deploying the new Worker route. The Worker has workers_dev
and preview URLs disabled; it is exposed through its custom hostname and the /update routes.
Request logging
Every request reaching the Worker emits an unsampled event at request start to the shared production
Cloudflare lake stream through the EVENTS Pipelines binding. Events use
source: "update", type: "request", an ISO timestamp, and a payload containing
the method, path, useragent, ip (from Cloudflare's CF-Connecting-IP header),
country, and Cloudflare colo. The path is normalized without /update so both mounts
share the existing analytics paths. Query strings, request bodies, cookies, and authorization
headers are not included. Response status and duration are not recorded.
Delivery runs in waitUntil without delaying the response. Delivery failures are
logged but do not fail requests or retry; this is not lossless audit logging.
Requests blocked before reaching the Worker are not recorded.
The stream ID in wrangler.jsonc comes from the lake.stream output of the
anomalyco/platform/production Pulumi stack. Update the binding if that stream is
replaced. The stream is shared across release channels because the update service
has a single public deployment.
Publishing
GitHub Actions publishes artifacts through POST https://opencode.ai/update/api/publish
using a short-lived OIDC token with audience https://update.opencode.ai. The original
hostname and token audience remain supported. The Worker accepts only tokens signed by
GitHub for repository ID 975734319, owner ID 66570915, and .github/workflows/publish.yml
on configured publishing refs.
Apply migrations and deploy from this directory:
bun run db:migrate
bun run deploy