Skip to content

vscode: a Download writ button - #4

Open
sajonaro wants to merge 1 commit into
mainfrom
download-button
Open

sajonaro wants to merge 1 commit into
mainfrom
download-button

Conversation

@sajonaro

@sajonaro sajonaro commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

Why

Without writ-lsp the extension only highlights syntax. The one fix it offered was an opam pin typed into a terminal, which needs an OCaml toolchain and minutes of building just to get an editor working. writ already publishes a release tarball for each Linux architecture, with a checksum beside it. That tarball holds everything the extension needs: writ-lsp, the writ CLI the verbs run, and the standard library where the resolver looks for it.

What

A Download writ button appears in three places:

  • the Writ panel
  • the "no language server" error message
  • the Command Palette, as Writ: Download writ

Clicking it does this:

  1. Picks a release. It takes the release tagged with this extension's version. If that version was never released, it falls back to the latest release, and the panel's version verdict reports the difference.
  2. Downloads and verifies it. It fetches the tarball for this platform and checks its .sha256. On a mismatch the download is deleted, not unpacked.
  3. Installs it privately. It unpacks into the extension's global storage, renaming into place in one step so an interrupted download never counts as an install. Nothing goes on PATH, and uninstalling the extension removes it.
  4. Starts it. The client restarts through the same reload a changed setting uses, now one function in extension.js.

A hand-installed writ always wins. A download is the last place the extension looks, after PATH. For the same reason, the panel offers the button only when there's no server at all, or when the server in use is itself a download. Anywhere else the download would never run, so those cases get the opam option instead.

macOS and Windows have no release tarball yet, so they are pointed to opam.

Verified

  • New tests: test/download.test.js adds 25 offline checks for tarball names, checksum parsing, what counts as an install and in what order, search-order placement, and when the panel offers the button. Putting a download ahead of PATH on purpose makes two of them fail.
  • Live download: with WRIT_DOWNLOAD_LIVE=1, the test downloads the real v0.2.0 release and runs it. All 28 checks succeed.
  • Command wiring: a script stubs the VS Code API and calls the real command. The progress messages appear, the extension reloads, and the resolver switches to the downloaded server and its CLI.
  • Downstream CI: writ's downstream workflow ran on this branch, and every suite succeeded. The extension's six test files there report 25, 23, 49, 21, 30 and 8 checks.
  • Not done: I haven't clicked the button inside a running VS Code. That needs a manual check before merging.

Worth knowing

  • Version mismatch on first download. The extension is 0.1.0 and writ's only release is v0.2.0, so today the download takes 0.2.0 and the panel shows a mismatch. Running scripts/version.sh --from-writ before the next extension release makes the two match exactly.

🤖 Generated with Claude Code

Without writ-lsp the extension highlights and does nothing else, and the only
fix it offered was an opam pin typed into a terminal: an OCaml toolchain and
minutes of building, for someone who wanted an editor. writ already publishes
a release tarball per Linux architecture, with a .sha256 beside it, and the
tarball holds everything the extension needs: writ-lsp, the `writ` the verbs
run, and the stdlib at share/writ/lib, where the resolver looks relative to
the binary.

src/download.js fetches the tarball for this platform, verifies its checksum
and unpacks it into the extension's global storage, renaming it into place in
one step so an interrupted download never counts as an install. It takes the
release tagged with this extension's version, or the latest release when that
version was never released; the panel's version verdict then says so.

A download is the LAST candidate in locate.candidates, after PATH: a writ
installed by hand is a choice someone made, and a download is the fallback
for having none. For the same reason the panel offers the button only with no
server at all, or when the server in use is itself a download. Anywhere else
it would fetch an engine that never runs, so those cases get the opam route.

The button appears in the panel, in the "no language server" error, and as
Writ: Download writ in the Command Palette. After a download the client is
restarted through the same reload a changed setting uses, now one function
in extension.js. Platforms with no tarball (macOS, Windows) are told to use
opam.

test/download.test.js covers the tarball names, checksum parsing, what counts
as an install and their order, the search-order placement, and when the panel
offers the button. WRIT_DOWNLOAD_LIVE=1 also downloads the real release and
runs it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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