Editor support
Extensions wiring editors to the ghtmx toolchain. Each is a thin client:
syntax highlighting is local, and everything else โ live diagnostics,
route-aware completion, hover, go to definition โ comes from ghtmx lsp
(FR-080โFR-084), so behavior stays identical across editors.
| Editor | Directory | Highlighting | LSP wiring |
|---|---|---|---|
| VS Code | vscode/ |
TextMate grammar | vscode-languageclient launching ghtmx lsp |
| Neovim | nvim/ |
Vim syntax file | vim.lsp.start launching ghtmx lsp |
| JetBrains | jetbrains/ |
Shared TextMate bundle | Platform LSP API launching ghtmx lsp |
All three highlight the ghtmx-native constructs: templ, fragment,
and event declarations, htmx attributes, and route bindings
(hx-post={ handlers.CreateItem }).
The binaries are not bundled
Installing an extension installs no binaries. Every integration spawns
ghtmx lsp off your PATH, and that server in turn needs gopls for the
embedded Go โ it looks on PATH, then in ~/go/bin, then in
~/.local/bin. Those last two are where a default Go toolchain puts
things, so it usually just works; with a customized GOBIN or GOPATH,
put that directory on your PATH. Install both first (Linux, macOS, WSL):
curl -fsSL https://raw.githubusercontent.com/go-monolith/ghtmx/main/scripts/install.sh | bash
That script is a wrapper around the release-archive install path; see
the root README.md for the manual steps and the
Windows route. It installs the newest release, which pre-1.0 is not
guaranteed to fall in the module series the extension was tested
against โ set GHTMX_VERSION to pin.
For VS Code it is the whole setup rather than half of it: with the
code CLI on PATH and the extension not yet installed, the script asks
whether to add it and installs the .vsix off the same release. The
name of that file carries the extension version, not the module tag, so
the script reads it from the release's asset list rather than computing
it. Answering anything but y installs nothing; --no-interactive
suppresses the question, GHTMX_INSTALL_VSCODE=1 answers it yes, and
GHTMX_SKIP_VSCODE=1 skips the step. Unlike the binary archives, the
.vsix has no entry in checksums.txt โ that file is written before
the editor artifacts are attached โ so TLS to github.com is all that
stands behind it.
The VS Code extension also offers to run the script from the error it
shows when the server will not start, and from the command palette as
ghtmx: Install ghtmx and gopls. It passes --no-interactive there:
the extension doing the asking is already installed, so the offer would
be noise.
The VS Code TextMate grammar
(vscode/syntaxes/ghtmx.tmLanguage.json) is the single source of
truth; the JetBrains bundle ships a byte-identical copy, enforced by
editors_test.go. One caveat: the grammar's source.go, source.css,
and source.js includes resolve against grammars the host editor
provides, so embedded-language coloring varies by editor (VS Code's
built-ins cover them; JetBrains falls back to plain text inside
embedded regions).
Versioning
Extension versions are related to the ghtmx module version by series:
- An extension versioned
X.Y.*is developed and tested against the ghtmx module seriesvX.Y.*and itsghtmx lsp. - Extension PATCH releases are extension-only fixes and never require a
module update; module PATCH releases never change the LSP surface, so
any
X.Y.*extension works with anyvX.Y.*module. - When a module MINOR release changes the LSP surface (new
capabilities, changed completion behavior), each extension gets a
matching
X.Y.0release, even if its own code is unchanged.
Current compatibility:
| Extension | Version | ghtmx module series |
|---|---|---|
VS Code (vscode/package.json) |
0.1.0 | v0.1 |
| Neovim (released with the repository) | 0.1.0 | v0.1 |
JetBrains (jetbrains/build.gradle.kts) |
0.1.0 | v0.1 |
editors_test.go pins the VS Code and JetBrains versions to this table.
Release path
- Verify the LSP against the target module version: the protocol suite
and latency gate (
go test ./cmd/ghtmx/lspcmd/, task 56) must be green at the module tag being released. - Bump each extension's version per the policy above and update the compatibility table here.
- Package and publish per editor โ see
vscode/README.md,nvim/README.md, andjetbrains/README.md.
The extensions stay out of the Go module's own build: packaging them
needs Node (VS Code) or a JDK (JetBrains), and the engine's constitution
keeps those out of the module pipeline. editors_test.go validates
their structure with the standard Go toolchain instead.
They are packaged in CI, though, by .github/workflows/editors.yml:
- A release attaches three artifacts โ
ghtmx-vscode-<version>.vsix,ghtmx-jetbrains-<version>.zip, andghtmx-nvim-<version>.tar.gzโ so an editor can be installed from the release page without a Node or JDK toolchain locally. - Each is packaged independently, so a packaging failure costs one
artifact rather than all three. The JetBrains build is the likeliest
to fail: it resolves an IntelliJ platform from JetBrains'
repositories. A release can therefore be published with an asset
missing โ the workflow run goes red, but the release itself carries no
sign of it, so check the
editorsrun if an expected asset is absent. - Each is built from its own manifest, not stamped with the module tag.
A
0.1.0extension attached tov0.1.4is the versioning policy working as intended: anyX.Y.*extension serves anyvX.Y.*module. - A pull request touching
editorsbuilds all three without uploading, so a packaging break surfaces on the PR rather than mid-release.