Skip to content

Commit d5c29ed

Browse files
Remove the Ghostty engine (#63)
## Summary Removes the optional Ghostty (`libghostty-vt`) terminal engine. The builtin engine is now the only engine. ## Why - **Builtin already covers it.** Ghostty advertised only `Vt52Keyboard`. Builtin advertises that plus grapheme clusters, row rendition, DRCS, kitty keyboard, modifyOtherKeys, Win32 input, and Sixel/iTerm2/ConEmu/kitty images (see `docs/parity-status.md`). On all 13 vt benchmark workloads the two engines produced identical screens except one `styled` row, which is a builtin bug (a combining mark after a space is dropped) and is not fixed here. - **Ghostty was opt-in only.** It sat behind `experimental.terminalEngine`; builtin was the default. - **Upgrading to 1.4 would have been a regression.** libghostty-vt 1.4.0 makes Windows ingest about 6x slower on any workload that fills scrollback (`scrolling`: 29 → 5 MB/s). The cause is upstream commit `60b43068c` ("reclaim pooled and compressed page memory on Windows"), which calls `DiscardVirtualMemory` on every recycled page. Disabling that one change brought 1.4 back to 35 MB/s. ## What changed - **Code:** deleted `src/Devolutions.Terminal.Ghostty`, `tests/Devolutions.Terminal.Ghostty.Tests`, `native/ghostty`, `.github/workflows/build-ghostty.yml` and `docs/ghostty-engine.md`. - **Settings:** removed `experimental.terminalEngine` (global and per profile) and the two engine pickers in the settings editor. A settings file that still selects `"ghostty"` loads as builtin, and saving leaves the key untouched because saves are diff-based. Tests cover this. - **Packaging:** `ghostty-vt.dll`/`libghostty-vt.so`/`.dylib` and `THIRD-PARTY-NOTICES-GHOSTTY.txt` are no longer shipped or checked in the MSIX, Linux, macOS or NuGet payloads. `GHOSTTY_LIBRARY` is gone from `macos/package.env`. - **Native restore:** `NativeLibraries.targets` and `Restore-NativeLibraries.ps1` now only build `dt-pty-host`, for Linux/macOS RIDs; Windows builds skip the restore step entirely. The Zig pin (unchanged at 0.16.0) moves to `native/zig.json`. - **CI:** cache keys now hash `native/zig.json` and are bumped to `native-v3`, so old caches containing Ghostty sources and binaries aren't restored. - **Benchmarks:** the `vt` suite replaces the `ghostty-vt`/`ghostty` targets with a `control` target. It runs FNV-1a over the same bytes, a serial loop whose speed follows the core clock, and `-Baseline` now gates on builtin/control. `-RequireBeatGhostty`, `-GhosttyBench`, `--no-gate` and the screen-equivalence check are removed. - **Docs:** the Ghostty comparison moved to `docs/history/ghostty-comparison-benchmarks.md`, with a shorter current `docs/performance-benchmarks.md` in its place. README, AGENTS, CONTRIBUTING, NOTICE, parity-status, release, macOS and renderer docs are updated. ## Testing - **Build and tests:** `dotnet build Devolutions.Terminal.slnx -c Release` gives 0 warnings and 0 errors. `dotnet test` passes 3,170 tests with 11 skipped (Windows x64). - **Package self-tests:** `Test-ConPtyPublishLayout.ps1`, `Test-MacOsLegalNotices.ps1` and `Test-PackageBuild.ps1` pass locally. - **Native restore:** a forced `linux-x64` restore downloads Zig 0.16.0 from `native/zig.json` and builds `dt-pty-host`. A `win-x64` restore is a no-op. - **Bench:** a `-Baseline` comparison between two runs works. Absolute builtin speed moved −3.4% while builtin/control moved +2.1%, so the control absorbs machine drift. ## Reviewer notes - **macOS and Linux packaging scripts** were syntax-checked only (`bash -n`, PowerShell parser). This PR's CI is their first real run, and `Test-MacOsPackagingMetadata.ps1` needs `plutil`. - **Intentional "ghostty" mentions:** the bench workload descriptions still credit `ghostty-gen` as the source of the corpus shapes, and the corpus bytes are unchanged so saved baselines stay comparable. `winterm-ghostty` comments refer to an unrelated prior-art project. - **Branch name:** it still says "1.4 upgrade" because the work started as that upgrade. The upgrade edits were discarded in favor of the removal. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 80c15c6 commit d5c29ed

79 files changed

Lines changed: 752 additions & 4894 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/build-ghostty.yml‎

Lines changed: 0 additions & 97 deletions
This file was deleted.

‎.github/workflows/build-terminal.yml‎

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,7 @@ on:
66
- "**"
77
tags:
88
- "v*"
9-
paths-ignore:
10-
- ".github/workflows/build-ghostty.yml"
119
pull_request:
12-
paths-ignore:
13-
- ".github/workflows/build-ghostty.yml"
1410
workflow_dispatch:
1511
inputs:
1612
version:
@@ -142,12 +138,10 @@ jobs:
142138
with:
143139
path: |
144140
artifacts/tools
145-
artifacts/ghostty-src
146-
native/ghostty/*/*
147141
native/linux-pty/*/dt-pty-host
148142
native/noto-emoji/NotoColorEmoji.ttf
149143
# Never restore native sources or reuse binaries built from different inputs.
150-
key: native-v2-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('native/**/*.ps1', 'native/ghostty/ghostty-upstream.json', 'native/linux-pty/dt-pty-host.c', 'native/noto-emoji/noto-emoji.json') }}
144+
key: native-v3-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('native/**/*.ps1', 'native/zig.json', 'native/linux-pty/dt-pty-host.c', 'native/noto-emoji/noto-emoji.json') }}
151145

152146
- name: Set up .NET
153147
uses: actions/setup-dotnet@v4
@@ -199,7 +193,7 @@ jobs:
199193
uses: actions/cache@v4
200194
with:
201195
path: artifacts/tools
202-
key: zig-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('native/Zig.ps1', 'native/ghostty/ghostty-upstream.json') }}
196+
key: zig-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('native/Zig.ps1', 'native/zig.json') }}
203197

204198
- name: Build dt-pty-host for every Unix RID
205199
shell: pwsh
@@ -233,7 +227,7 @@ jobs:
233227
with:
234228
path: |
235229
native/noto-emoji/NotoColorEmoji.ttf
236-
key: native-v2-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('native/**/*.ps1', 'native/ghostty/ghostty-upstream.json', 'native/linux-pty/dt-pty-host.c', 'native/noto-emoji/noto-emoji.json') }}
230+
key: native-v3-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('native/**/*.ps1', 'native/zig.json', 'native/linux-pty/dt-pty-host.c', 'native/noto-emoji/noto-emoji.json') }}
237231

238232
- name: Set up .NET
239233
uses: actions/setup-dotnet@v4
@@ -337,11 +331,9 @@ jobs:
337331
with:
338332
path: |
339333
artifacts/tools
340-
artifacts/ghostty-src
341-
native/ghostty/*/*
342334
native/linux-pty/*/dt-pty-host
343335
native/noto-emoji/NotoColorEmoji.ttf
344-
key: native-v2-${{ runner.os }}-${{ runner.arch }}-${{ matrix.rid }}-${{ hashFiles('native/**/*.ps1', 'native/ghostty/ghostty-upstream.json', 'native/linux-pty/dt-pty-host.c', 'native/noto-emoji/noto-emoji.json') }}
336+
key: native-v3-${{ runner.os }}-${{ runner.arch }}-${{ matrix.rid }}-${{ hashFiles('native/**/*.ps1', 'native/zig.json', 'native/linux-pty/dt-pty-host.c', 'native/noto-emoji/noto-emoji.json') }}
345337

346338
- name: Set up .NET
347339
uses: actions/setup-dotnet@v4
@@ -378,11 +370,9 @@ jobs:
378370
with:
379371
path: |
380372
artifacts/tools
381-
artifacts/ghostty-src
382-
native/ghostty/*/*
383373
native/linux-pty/*/dt-pty-host
384374
native/noto-emoji/NotoColorEmoji.ttf
385-
key: native-v2-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('native/**/*.ps1', 'native/ghostty/ghostty-upstream.json', 'native/linux-pty/dt-pty-host.c', 'native/noto-emoji/noto-emoji.json') }}
375+
key: native-v3-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('native/**/*.ps1', 'native/zig.json', 'native/linux-pty/dt-pty-host.c', 'native/noto-emoji/noto-emoji.json') }}
386376

387377
- name: Set up .NET
388378
uses: actions/setup-dotnet@v4
@@ -411,11 +401,9 @@ jobs:
411401
with:
412402
path: |
413403
artifacts/tools
414-
artifacts/ghostty-src
415-
native/ghostty/*/*
416404
native/linux-pty/*/dt-pty-host
417405
native/noto-emoji/NotoColorEmoji.ttf
418-
key: native-v2-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('native/**/*.ps1', 'native/ghostty/ghostty-upstream.json', 'native/linux-pty/dt-pty-host.c', 'native/noto-emoji/noto-emoji.json') }}
406+
key: native-v3-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('native/**/*.ps1', 'native/zig.json', 'native/linux-pty/dt-pty-host.c', 'native/noto-emoji/noto-emoji.json') }}
419407

420408
- name: Set up .NET
421409
uses: actions/setup-dotnet@v4
@@ -460,11 +448,9 @@ jobs:
460448
with:
461449
path: |
462450
artifacts/tools
463-
artifacts/ghostty-src
464-
native/ghostty/*/*
465451
native/linux-pty/*/dt-pty-host
466452
native/noto-emoji/NotoColorEmoji.ttf
467-
key: native-v2-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('native/**/*.ps1', 'native/ghostty/ghostty-upstream.json', 'native/linux-pty/dt-pty-host.c', 'native/noto-emoji/noto-emoji.json') }}
453+
key: native-v3-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('native/**/*.ps1', 'native/zig.json', 'native/linux-pty/dt-pty-host.c', 'native/noto-emoji/noto-emoji.json') }}
468454

469455
- name: Set up .NET
470456
uses: actions/setup-dotnet@v4

‎.github/workflows/test-iseberg.yml‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,9 @@ jobs:
5757
with:
5858
path: |
5959
artifacts/tools
60-
artifacts/ghostty-src
61-
native/ghostty/*/*
6260
native/linux-pty/*/dt-pty-host
6361
native/noto-emoji/NotoColorEmoji.ttf
64-
key: native-v2-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('native/**/*.ps1', 'native/ghostty/ghostty-upstream.json', 'native/linux-pty/dt-pty-host.c', 'native/noto-emoji/noto-emoji.json') }}
62+
key: native-v3-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('native/**/*.ps1', 'native/zig.json', 'native/linux-pty/dt-pty-host.c', 'native/noto-emoji/noto-emoji.json') }}
6563

6664
- name: Set up .NET
6765
uses: actions/setup-dotnet@v4
@@ -72,7 +70,7 @@ jobs:
7270
shell: pwsh
7371
run: ./scripts/Install-IsebergTestPowerShell.ps1
7472

75-
# A native cache miss downloads Zig and compiles Ghostty; keep that out of the test budget.
73+
# A native cache miss downloads Zig and compiles dt-pty-host; keep that out of the test budget.
7674
- name: Restore native libraries
7775
timeout-minutes: 30
7876
shell: pwsh

‎.gitignore‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,6 @@ Thumbs.db
2727
.DS_Store
2828

2929
## Native libraries built from source (see native/Restore-NativeLibraries.ps1)
30-
native/ghostty/**/*.dll
31-
native/ghostty/**/*.so
32-
native/ghostty/**/*.dylib
33-
native/ghostty/**/*.sha256
3430
native/linux-pty/**/dt-pty-host
3531
native/linux-pty/**/dt-pty-host.exe
3632
native/noto-emoji/NotoColorEmoji.ttf

‎AGENTS.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ already the primary scripting language for Windows packaging in this repo
4747
## Native helpers
4848

4949
- Linux/macOS PTY host: `native/linux-pty` (`dt-pty-host.c`)
50-
- Ghostty VT library: `native/ghostty`
5150
- Windows Explorer/toast helpers: `native/windows-shell`
5251

53-
`dotnet build` restores these for the host RID automatically
54-
(`-p:SkipNativeRestore=true` to skip).
52+
`dotnet build` restores `dt-pty-host` for Linux/macOS host RIDs automatically
53+
(Zig version pinned in `native/zig.json`; `-p:SkipNativeRestore=true` to
54+
skip). Windows builds have nothing to restore.
5555

5656
## Platform packaging entry points
5757

‎CONTRIBUTING.md‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,13 @@ Do not point that tool at this repository.
6969
## Native helpers
7070

7171
- Linux/macOS PTY host: `native/linux-pty` (`dt-pty-host.c`; Zig `cc` on Linux, Apple clang on macOS)
72-
- Ghostty VT library: `native/ghostty` (Zig build of pinned Ghostty)
7372
- Windows Explorer/toast helpers: `native/windows-shell` (MSVC, gitignored `bin/`)
7473

75-
`dotnet build` restores Ghostty and `dt-pty-host` for the host RID (Zig is
76-
downloaded into `artifacts/tools` on first use; a system `zig` of a different
77-
minor version than the pinned one is ignored, so it does not break the build). See
78-
[`native/ghostty/README.md`](native/ghostty/README.md). Pass
74+
`dotnet build` restores `dt-pty-host` for Linux/macOS host RIDs; Windows builds
75+
have nothing to restore. The Zig version is pinned in
76+
[`native/zig.json`](native/zig.json); Zig is downloaded into `artifacts/tools`
77+
on first use, and a system `zig` of a different minor version than the pinned
78+
one is ignored, so it does not break the build. Pass
7979
`-p:SkipNativeRestore=true` to skip.
8080

8181
## macOS
@@ -88,7 +88,7 @@ dotnet test Devolutions.Terminal.slnx
8888
pwsh scripts/Build-MacOsPackage.ps1 osx-arm64 2026.3.0 artifacts/packages
8989
```
9090

91-
`dotnet build` restores Ghostty and `dt-pty-host` for `osx-arm64` / `osx-x64`.
91+
`dotnet build` restores `dt-pty-host` for `osx-arm64` / `osx-x64`.
9292
The PTY host is compiled with Apple clang against the macOS 13 SDK. App-bundle
9393
packaging is Darwin-only; release builds are signed and notarized with a
9494
Developer ID identity (see [docs/macos.md](docs/macos.md) and

‎Devolutions.Terminal.slnx‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
<Project Path="src/Devolutions.Terminal.Connection/Devolutions.Terminal.Connection.csproj" />
44
<Project Path="src/Devolutions.Terminal.Control/Devolutions.Terminal.Control.csproj" />
55
<Project Path="src/Devolutions.Terminal.Core/Devolutions.Terminal.Core.csproj" />
6-
<Project Path="src/Devolutions.Terminal.Ghostty/Devolutions.Terminal.Ghostty.csproj" />
76
<Project Path="src/Devolutions.Terminal.Render/Devolutions.Terminal.Render.csproj" />
87
<Project Path="src/Devolutions.Terminal.Settings/Devolutions.Terminal.Settings.csproj" />
98
<Project Path="src/Devolutions.Terminal.Broker/Devolutions.Terminal.Broker.csproj" />
@@ -27,7 +26,6 @@
2726
<Project Path="tests/Devolutions.Terminal.Connection.Tests/Devolutions.Terminal.Connection.Tests.csproj" />
2827
<Project Path="tests/Devolutions.Terminal.Control.Tests/Devolutions.Terminal.Control.Tests.csproj" />
2928
<Project Path="tests/Devolutions.Terminal.Core.Tests/Devolutions.Terminal.Core.Tests.csproj" />
30-
<Project Path="tests/Devolutions.Terminal.Ghostty.Tests/Devolutions.Terminal.Ghostty.Tests.csproj" />
3129
<Project Path="tests/Devolutions.Terminal.Render.Tests/Devolutions.Terminal.Render.Tests.csproj" />
3230
<Project Path="tests/Devolutions.Terminal.Settings.Tests/Devolutions.Terminal.Settings.Tests.csproj" />
3331
<Project Path="tests/Devolutions.Terminal.Broker.Tests/Devolutions.Terminal.Broker.Tests.csproj" />

‎NOTICE.md‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,6 @@ See the license in the Cascadia Code repository.
1717
Vendored under `native/noto-emoji/`. Licensed under the SIL Open Font License
1818
1.1. See `native/noto-emoji/LICENSE`.
1919

20-
## Ghostty (`libghostty-vt`)
21-
22-
Pinned native VT engine binaries under `native/ghostty/`. See
23-
`native/ghostty/LICENSE` and `docs/ghostty-engine.md`.
24-
2520
## AppImage type-2 runtime
2621

2722
Linux AppImage packages embed a pinned type-2 runtime. See

‎README.md‎

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ as a self-contained **NativeAOT** desktop app, and rendered with **Avalonia 12**
55

66
- **ConPTY** on Windows and a real **forkpty** transport on Linux and macOS
77
- Azure Cloud Shell for remote Azure sessions
8-
- selectable built-in or **Ghostty** VT engine
8+
- a built-in VT engine written in C#
99
- Windows Terminal-compatible `settings.json`, actions, keybindings, and `dt` CLI
1010
- source-integrated **Iseberg** PowerShell ISE profiles, with execution in an
1111
owned PowerShell subprocess and a NativeAOT desktop
@@ -104,18 +104,13 @@ windows is unavailable, and persisted layouts are neither restored nor saved.
104104
It is the per-launch equivalent of Windows Terminal's
105105
`compatibility.isolatedMode` setting, which Windows Terminal 1.23 removed.
106106

107-
Set `"experimental.terminalEngine": "ghostty"` to use the pinned
108-
`libghostty-vt` engine globally. A profile can override it with `"builtin"` or
109-
`"ghostty"`. ConPTY remains the Windows process transport for both engines.
110-
111107
The compiled-XAML settings editor is documented in
112108
[docs/settings-editor.md](docs/settings-editor.md).
113109

114110
## Architecture
115111

116112
```
117113
Devolutions.Terminal.Core VT parser + text buffer + terminal engine
118-
Devolutions.Terminal.Ghostty NativeAOT-safe libghostty-vt engine adapter
119114
Devolutions.Terminal.Render Immutable plans + HarfBuzz/Skia glyph renderer
120115
Devolutions.Terminal.Connection ConPTY + Linux PTY + Azure Cloud Shell + browser shell
121116
Devolutions.Terminal.Settings Layered Windows Terminal-compatible JSON settings

‎docs/advanced-vt-protocols.md‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
> [!NOTE]
44
> Windows local sessions use the bundled Microsoft ConPTY runtime, including
55
> `OpenConsole.exe`, rather than the OS copy that filters Sixel on some Windows
6-
> builds. With the built-in engine, Sixel producers such as `Get-XKCD -Show`
7-
> can render inline images. Other transports must likewise preserve graphics
8-
> payloads; the optional Ghostty engine does not expose image resources.
6+
> builds. Sixel producers such as `Get-XKCD -Show` can therefore render inline
7+
> images. Other transports must likewise preserve graphics payloads.
98
109
`Devolutions.Terminal.Core` parses advanced string protocols without depending on Avalonia,
1110
Skia, Win32, or an image codec. It exposes decoded Sixel pixels and bounded
@@ -140,7 +139,6 @@ delete or reset does not paint stale cached pixels.
140139
- kitty cell/z-index/number-targeted deletes (`d=c/x/y/z/n`) — silent no-op;
141140
the cursor for `f=100` images without `r` stays put because Core retains codec
142141
bytes without decoding dimensions
143-
- Ghostty image projection (the pinned C ABI exposes no image resources)
144142

145143
These gaps avoid remote I/O and renderer/input dependencies while keeping every
146144
implemented parser and downloadable resource path bounded.

0 commit comments

Comments
 (0)