The build time claim in the blog post is dubious, part of the problem is CGO isn't fast, but also if build time was really a motivator the null build path is entirely unoptimized for objects with long build times:
cached null (no changes) build:
~github/unstablebuild/rune % make
pre-commit not installed; skipping git hook setup
cd cmd/buildstamp && CGO_ENABLED=1 go build -ldflags="-X unstable.build/rune/internal/debug.Tag=$(git describe --tags) -X unstable.build/rune/internal/debug.Commit=$(git rev-parse --short HEAD) -X unstable.build/rune/internal/debug.BuildDate=2026-09-11T20:16:22Z -X unstable.build/rune/internal/debug.Package=six" -o ../../bin/buildstamp
cd cmd/extension_chaos && CGO_ENABLED=1 go build -ldflags="-X unstable.build/rune/internal/debug.Tag=$(git describe --tags) -X unstable.build/rune/internal/debug.Commit=$(git rev-parse --short HEAD) -X unstable.build/rune/internal/debug.BuildDate=2026-09-11T20:16:22Z -X unstable.build/rune/internal/debug.Package=six" -o ../../bin/extension_chaos
cd cmd/extension_color_palette && CGO_ENABLED=1 go build -ldflags="-X unstable.build/rune/internal/debug.Tag=$(git describe --tags) -X unstable.build/rune/internal/debug.Commit=$(git rev-parse --short HEAD) -X unstable.build/rune/internal/debug.BuildDate=2026-09-11T20:16:22Z -X unstable.build/rune/internal/debug.Package=six" -o ../../bin/extension_color_palette
cd cmd/extension_fuzzy_search && CGO_ENABLED=1 go build -ldflags="-X unstable.build/rune/internal/debug.Tag=$(git describe --tags) -X unstable.build/rune/internal/debug.Commit=$(git rev-parse --short HEAD) -X unstable.build/rune/internal/debug.BuildDate=2026-09-11T20:16:22Z -X unstable.build/rune/internal/debug.Package=six" -o ../../bin/extension_fuzzy_search
cd cmd/extension_go && CGO_ENABLED=1 go build -ldflags="-X unstable.build/rune/internal/debug.Tag=$(git describe --tags) -X unstable.build/rune/internal/debug.Commit=$(git rev-parse --short HEAD) -X unstable.build/rune/internal/debug.BuildDate=2026-09-11T20:16:22Z -X unstable.build/rune/internal/debug.Package=six" -o ../../bin/extension_go
cd cmd/extension_python && CGO_ENABLED=1 go build -ldflags="-X unstable.build/rune/internal/debug.Tag=$(git describe --tags) -X unstable.build/rune/internal/debug.Commit=$(git rev-parse --short HEAD) -X unstable.build/rune/internal/debug.BuildDate=2026-09-11T20:16:22Z -X unstable.build/rune/internal/debug.Package=six" -o ../../bin/extension_python
cd cmd/extension_rtc && CGO_ENABLED=1 go build -ldflags="-X unstable.build/rune/internal/debug.Tag=$(git describe --tags) -X unstable.build/rune/internal/debug.Commit=$(git rev-parse --short HEAD) -X unstable.build/rune/internal/debug.BuildDate=2026-09-11T20:16:22Z -X unstable.build/rune/internal/debug.Package=six" -o ../../bin/extension_rtc
cd cmd/extension_rust && CGO_ENABLED=1 go build -ldflags="-X unstable.build/rune/internal/debug.Tag=$(git describe --tags) -X unstable.build/rune/internal/debug.Commit=$(git rev-parse --short HEAD) -X unstable.build/rune/internal/debug.BuildDate=2026-09-11T20:16:22Z -X unstable.build/rune/internal/debug.Package=six" -o ../../bin/extension_rust
cd cmd/extension_zig && CGO_ENABLED=1 go build -ldflags="-X unstable.build/rune/internal/debug.Tag=$(git describe --tags) -X unstable.build/rune/internal/debug.Commit=$(git rev-parse --short HEAD) -X unstable.build/rune/internal/debug.BuildDate=2026-09-11T20:16:22Z -X unstable.build/rune/internal/debug.Package=six" -o ../../bin/extension_zig
cd cmd/runefox && CGO_ENABLED=1 go build -ldflags="-X unstable.build/rune/internal/debug.Tag=$(git describe --tags) -X unstable.build/rune/internal/debug.Commit=$(git rev-parse --short HEAD) -X unstable.build/rune/internal/debug.BuildDate=2026-09-11T20:16:22Z -X unstable.build/rune/internal/debug.Package=six" -o ../../bin/runefox
cd cmd/sshshop && CGO_ENABLED=1 go build -ldflags="-X unstable.build/rune/internal/debug.Tag=$(git describe --tags) -X unstable.build/rune/internal/debug.Commit=$(git rev-parse --short HEAD) -X unstable.build/rune/internal/debug.BuildDate=2026-09-11T20:16:22Z -X unstable.build/rune/internal/debug.Package=six" -o ../../bin/sshshop
cd cmd/walkbench && CGO_ENABLED=1 go build -ldflags="-X unstable.build/rune/internal/debug.Tag=$(git describe --tags) -X unstable.build/rune/internal/debug.Commit=$(git rev-parse --short HEAD) -X unstable.build/rune/internal/debug.BuildDate=2026-09-11T20:16:22Z -X unstable.build/rune/internal/debug.Package=six" -o ../../bin/walkbench
make 35.90s user 5.88s system 191% cpu 21.846 total 1975848 rss
vs. cached non-null (changed) build: ~github/zed-industries/zed % touch crates/zed/src/zed.rs
~github/zed-industries/zed % cargo build
Compiling zed v1.18.0 (/home/raggi/src/github.com/zed-industries/zed/crates/zed)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 8.42s
cargo build 10.15s user 9.34s system 228% cpu 8.531 total 7930312 rss
Build times are a valid thing to care about and talk about, but the claims implied don't stand up to scrutiny.
As a sibling comment pointed out this isn't comparing the same things. I'll try to provide a better comparison.
On a warm build on my machine, after editing a string in Zed's `crates/zed/src/zed.rs` and editing a string in Rune's `./cmd/rune/main.go`
Zed: `cargo build --release`: 284s (debug 30s)
Rune: `go build ./cmd/rune`: 15s
note I'm using a release build in Cargo to make it a bit fairer as all builds are "release" builds in Go.
You just compiled 9 extensions, a purpose built benchmark program, a toy ssh shop I built, a toy TUI browser and Rune, in serial. It's right there in the output. Try `go build ./cmd/rune` for a fair comparison.
Similar reflection, I ran `kitten __benchmark__ --render` in rune, the CPU time spent was 1:55. I ran the same in a libghostty based terminal emulator and spent 0:44 on CPU.
I say this only because yes you can do engineering to meet the benchmark without dropping to deeper systems layers, but closing the gap on efficiency is hard. I'm not saying this to be a downer on your project - an IDE and VTE in Go are a fun project to have around, but the blog post makes implied claims of equivalence with moderate investment - but I think that's limited to single benchmark chasing. I say this as a polyglot who's day job is a Go based program that would be far easier to optimize in a systems language.
If you're going to run a benchmark, at least post the results. I was planning on writing up a different blog post about the terminal optimization journey, but I actually used `kitten __benchmark__ --render` quite a lot to optimize it:
rune --version Rune v1.2.1 (HEAD is 40bf9cc1)
Results: Only ASCII chars : 1.13s @ 177.2 MB/s Unicode chars : 1.44s @ 123.2 MB/s CSI codes with few chars : 2.95s @ 33.9 MB/s Long escape codes : 6.25s @ 125.5 MB/s Images : 2.76s @ 193.1 MB/s
/Applications/Alacritty.app/Contents/MacOS/alacritty --version alacritty 0.13.1 (fe2a3c5)
Results: Only ASCII chars : 1.97s @ 101.4 MB/s Unicode chars : 1.26s @ 140.3 MB/s CSI codes with few chars : 1.26s @ 79.3 MB/s Long escape codes : 5.22s @ 150.1 MB/s Images : 1.34s @ 399.3 MB/s
ghostty --version Ghostty 1.3.2-main-+aa21caeaa
Results: Only ASCII chars : 354.9ms @ 563.5 MB/s Unicode chars : 815.42ms @ 217.0 MB/s CSI codes with few chars : 1.23s @ 81.6 MB/s Long escape codes : 6.39s @ 122.8 MB/s Images : 680.84ms @ 783.4 MB/s
Ran just now, on a Macbook Pro M4 Max 128Gb.
Rune doesn't support the kitty graphics protocol, so ignore the Images bench results.