Prebuilt libghostty-vt (the VT parser / terminal state machine cut from ghostty-org/ghostty), built by this repo's CI and published as GitHub Release assets — so downstream consumers (e.g. fizzyedit/ghostty) can depend on it as a normal Zig package instead of checking in a ~17MB static archive.
ghostty's own build.zig requires Zig 0.15.x. Projects that consume libghostty-vt (like the
fizzy plugin toolchain) are on Zig 0.16, under which ghostty's build does not compile (std.Build
API drift) — so it can't be built in-tree as a normal dependency. This repo solves that by being
the one place that still runs Zig 0.15.x: its CI checks out a pinned ghostty commit, builds
libghostty-vt with 0.15.x for every target platform, and republishes the result as a release
so nothing needs Zig 0.15 (or the giant binary) downstream.
This repo's own vX.Y.Z tags are an independent version for the package, unrelated to
ghostty's own version numbers — see "Why a pinned commit, not a tag" below.
On every vX.Y.Z tag push, .github/workflows/release.yml:
- Checks out
ghostty-org/ghosttyat the pinned ref (seeGHOSTTY_REF_DEFAULTin the workflow). - Builds
libghostty-vtwith Zig 0.15.2 (zig build -Demit-lib-vt -Doptimize=ReleaseFast) for:- macos-universal — arm64+x86_64 fat binary via ghostty's own xcframework step (needs a
real macOS runner + Xcode for
lipo/xcodebuild). - linux-x86_64, linux-aarch64 — cross-compiled from
ubuntu-latest. - windows-x86_64, windows-aarch64 — built on
windows-latest.
- macos-universal — arm64+x86_64 fat binary via ghostty's own xcframework step (needs a
real macOS runner + Xcode for
- Assembles one combined package: shared
include/ghostty/...headers (identical across targets — pure C API, nothing platform-generated) + one static lib per target underlib/<target>/+ aGHOSTTY_COMMITfile recording the exact ghostty commit built, plus the trivialbuild.zig/build.zig.zonfrompackage/so the tree fetches as a normal Zig package. - Publishes
ghostty-vt-vX.Y.Z.tar.gzas a release asset on the tag.
The static-lib / VT-only-xcframework build support we depend on (-Demit-lib-vt, see
src/build/Config.zig upstream) has not shipped in any tagged ghostty release — confirmed
absent as of v1.3.1, ghostty's latest tag at time of writing. It only exists on ghostty's main
branch. So GHOSTTY_REF_DEFAULT in the workflow pins an exact commit SHA on main, not a
release tag. When bumping it, re-verify -Demit-lib-vt still exists at the new SHA (grep
src/build/Config.zig for emit_lib_vt) before repinning — and re-check whether it has since
shipped in a tagged release, which would let this go back to tracking tags.
In the consumer's build.zig.zon:
.dependencies = .{
.ghostty_vt = .{
.url = "https://github.com/fizzyedit/ghostty_vt/releases/download/v0.1.0/ghostty-vt-v0.1.0.tar.gz",
.hash = "...", // from `zig fetch --save <url>`
},
},In build.zig, pick the lib subpath for the current target and link it:
const ghostty_vt = b.dependency("ghostty_vt", .{});
const vt_lib = switch (target.result.os.tag) {
.macos => "lib/macos-universal/libghostty-vt.a",
.windows => switch (target.result.cpu.arch) {
.aarch64 => "lib/windows-aarch64/ghostty-vt-static.lib",
else => "lib/windows-x86_64/ghostty-vt-static.lib",
},
.linux => switch (target.result.cpu.arch) {
.aarch64 => "lib/linux-aarch64/libghostty-vt.a",
else => "lib/linux-x86_64/libghostty-vt.a",
},
else => @panic("unsupported target for ghostty_vt"),
};
lib.root_module.addIncludePath(ghostty_vt.path("include"));
lib.root_module.addObjectFile(ghostty_vt.path(vt_lib));
lib.root_module.link_libc = true;- Update
GHOSTTY_REF_DEFAULTin.github/workflows/release.ymlto the new ghostty commit SHA (or tag, once-Demit-lib-vtships in a release). - Bump this repo's own version and push a tag (e.g.
v0.2.0) — independent of ghostty's version. - Once the release finishes, run
zig fetch --save https://github.com/fizzyedit/ghostty_vt/releases/download/<tag>/ghostty-vt-<tag>.tar.gzin the consuming repo to update itsbuild.zig.zonurl+hash.
The C API is explicitly work-in-progress/unstable upstream — expect to review binding code
(e.g. src/c.zig in the plugin) whenever you bump this pin.