Show HN: Shitty – fast terminal. Memory-unsafe and faster than yours
摘要
Shitty 是一个用 C++23 编写的终端模拟器,主打低延迟、快速启动和可预测资源占用,通过 Vulkan(Linux)或 Metal(macOS)在 GPU 上渲染单元格。作者给出与 alacritty、kitty、ghostty 的对比基准,声称在可打印 ASCII 和随机字节两类负载下吞吐量领先;项目包含 5000 余项测试、支持大量 VT 与 xterm 扩展、Unicode 字素簇、多种颜色与键盘 / 鼠标协议,并默认锁定剪贴板与窗口访问。它自包含单个小二进制,内置字体,可在无字体系统启动。构建依赖较多(Python、Ragel、glslangValidator 等),Linux 需要 Vulkan 与 Wayland,macOS 使用 Metal。项目是 Zutty 的硬分叉与重写,许可证正从 GPL 过渡到 MIT,旧代码仍为 GPLv3-or-later,新贡献为双许可。
荐读理由
这是个可实际装来用的终端,性能数据给得实打实——同屏对比里吞吐比 alacritty 快约两成,随机字节最坏情况快近一倍,而且有 5000+ 测试和 fuzz 兜底。你日常跑命令、看日志能直接受益,它把状态放 CPU、用 Vulkan/Metal 做渲染的架构思路也能抄到你自己项目里。
原文
Shitty
Blazingly fast. Memory-unsafe and faster than yours.
Shitty is built for low latency, fast startup, and predictable resource use. It keeps terminal state on the CPU and renders cells with native compute backends: Vulkan on Linux and Metal on macOS.
Performance
100MB catted through the GUI on an Apple-silicon MacBook, every terminal equalized first: Menlo 12pt, the same 14x28px cell, an 80x24 grid, 500 lines of scrollback. Best wall time of three runs.
Printable ASCII (the scroll path):
| terminal | wall | user | throughput |
|---|---|---|---|
| shitty | 0.81s | 0.50s | ~118 MiB/s |
| alacritty 0.17.0 | 0.96s | 0.78s | ~99 MiB/s |
| kitty 0.48.2 | 1.28s | 0.95s | ~75 MiB/s |
| ghostty 1.3.1 | 1.49s | 1.60s | ~64 MiB/s |
Random bytes (the parser's worst case, invalid UTF-8 throughout):
| terminal | wall | user | throughput |
|---|---|---|---|
| shitty | 1.88s | 1.79s | ~51 MiB/s |
| alacritty 0.17.0 | 3.07s | 2.92s | ~31 MiB/s |
| ghostty 1.3.1 | 4.63s | ~7.0s | ~21 MiB/s |
| kitty 0.48.2 | - | - | - |
kitty sits the random payload out: it reacts to the embedded escape junk with title changes and bells instead of drawing. Reproduce with dev/compare.py, which verifies the equalized setup from inside every terminal before measuring anything.
Why
Fast. See the tables above;
dev/compare.pyreproduces them.Correct. More than 5,000 tests, harvested from over a dozen suites - kitty, esctest, xterm's vttests, vttest, tack, libvterm, libtsm, alacritty, ghostty, contour, konsole, mosh - and driven black-box through a real PTY.
Flicker-free. Resize frames render inside the same transaction as the bounds change; updates are damage-driven.
Indestructible. The parser state machine is total and fuzzed with committed corpora:
cat /dev/urandomis a benchmark here, not a crash report.Unicode done right. Cells are grapheme clusters, not codepoints: emoji sequences, variation selectors, combining marks, wide CJK.
Self-contained. One small binary, no windowing toolkit, fonts embedded - it starts on a machine with no fonts installed at all.
Locked down by default. Applications cannot read selections or drive the host window unless explicitly allowed.
Features
VT52 through VT5xx controls and widely used xterm extensions.
Primary and alternate screens, primary-screen scrollback, margins, tabs, rectangular operations, protected cells, and synchronized output.
Reflow of primary-screen scrollback when the terminal width changes.
Unicode grapheme clusters, combining characters, emoji sequences, and double-width characters.
DEC single-width, double-width, and double-height lines.
16-colour, 256-colour, and 24-bit colour, including underline colour and extended underline styles.
Legacy, modifyOtherKeys, and Kitty keyboard protocols.
X10, VT200, UTF-8, SGR, SGR-pixel, and urxvt mouse protocols.
Linear and rectangular selection, primary selection, clipboard integration, OSC 52 policy, and OSC 8 hyperlinks.
Shell integration, notifications, progress reports, and in-band resize reporting.
Lazy glyph rasterization, a persistent GPU glyph cache, and damage-driven compute rendering.
Shitty uses UTF-8 internally and exports TERM=xterm-256color to child processes. The host must provide the corresponding terminfo entry.
Requirements
Shitty is written in C++23 and built with Clang. The bundled libstd needs -std=c++26, which the Apple command-line-tools clang does not know: on macOS install LLVM from Homebrew and point the build at it (export CC="$(brew --prefix llvm)/bin/clang", same for CXX with clang++). Every build requires:
Python 3, Ragel 6, and
glslangValidator;librsvg (
rsvg-convert), which renders the icon at build time;pkg-config;
utf8proc 2.9 or newer;
POSIX threads and PTY support.
The exact libstd revision used by Shitty is bundled in third_party/libstd and built as part of the same graph.
Linux additionally requires FreeType, HarfBuzz, Wayland client headers, xkbcommon, wayland-scanner, and Vulkan headers and loader. macOS requires SPIRV-Cross and uses CoreText, Cocoa, Metal, and IOSurface from the system SDK.
Brotli and simdutf are optional: Brotli only satisfies FreeType's static-link dependency chain where that applies, and simdutf 6.5 or newer accelerates Base64 over the always-available scalar implementation. Font families are resolved by CoreText on macOS and by Fontconfig (optional) on Linux; explicit font file paths work everywhere, whichever backend rasterizes them.
Linux requires a working Vulkan driver and Wayland compositor at runtime. macOS uses the native Metal driver. The native window and event-loop layer is built from third_party/plt; the terminal does not depend on a generic windowing toolkit.
The complete imported conformance suite additionally needs ncurses, Perl, and vttest.
Build
Build the default install group:
./build
Common build options:
./build -j 8
./build -B .build-debug
CPPFLAGS=-DDEBUG ./build
Run
Start the default shell:
./st
Run a command:
./st -e tmux new-session
Choose the initial terminal size and scrollback capacity:
./st -geometry 120x36 -saveLines 5000
Choose fonts:
./st -font 'DejaVu Sans Mono' -fontsize 16
./st -font 'DejaVu Sans Mono' -font 'Noto Sans Mono CJK JP'
-font accepts a family name or an explicit font file path and may be repeated: later fonts serve as fallbacks, picked per cluster by glyph coverage. Regular, bold, italic, and bold-italic faces resolve automatically. A vendored monospace-and-emoji trio is embedded in the binary as the last resort, so the terminal starts even on a system with no fonts installed at all.
Use ./st -v to print the build version without opening a window, ./st -help for the main option list, and ./st -listres for advanced terminal, colour, clipboard, and window-policy options. Boolean flags use -flag to enable and +flag to disable. SHITTY_FONT_SIZE sets the default font size; -fontsize takes precedence.
During a session, Cmd+=/Cmd+-/Cmd+0 on macOS (Ctrl+Shift+=/ Ctrl+-/Ctrl+0 on Linux) raise, lower, and restore the font size. Font resizing preserves the terminal's rows and columns by resizing the window to the new cell dimensions.
By default, applications cannot read local selections through OSC 52 and cannot manipulate or query the host window. These operations can be enabled explicitly for trusted applications.
Install
Homebrew (macOS, Apple silicon)
brew install pg83/tap/shitty
The tap tracks the latest release automatically. The same portable binary (st-darwin-arm64.tar.gz, nothing dynamically linked outside the system) is attached to every GitHub release.
Linux
The executable is named st; the desktop application and icon are named shitty:
install -Dm755 ./st /usr/local/bin/st
install -Dm644 shitty.desktop \
/usr/local/share/applications/shitty.desktop
install -Dm644 shitty.svg \
/usr/local/share/icons/hicolor/scalable/apps/shitty.svg
Exec=st is resolved through PATH, while Icon=shitty is resolved through the active icon theme.
Nix
A flake provides the shitty package and a development shell:
nix build # ./result/bin/st
nix run # run st directly
nix develop # clang toolchain + build dependencies
Add the package to a NixOS system from the flake overlay or via:
{
inputs.shitty.url = "github:pg83/shitty";
# ...
environment.systemPackages = [ inputs.shitty.packages.${system}.default ];
}
shell.nix remains available for nix-shell without flakes.
Tests
Run the full native and imported conformance suite:
./build test
Run only the native black-box suite:
./build test_suite
Run the same normal and sanitizer chains as GitHub CI:
nix build -L --no-link .#checks.x86_64-linux.build &&
nix build -L --no-link .#checks.x86_64-linux.tests
nix build -L --no-link .#checks.x86_64-linux.build-asan &&
nix build -L --no-link .#checks.x86_64-linux.tests-asan
nix build -L --no-link .#checks.x86_64-linux.build-ubsan &&
nix build -L --no-link .#checks.x86_64-linux.tests-ubsan
Build an instrumented copy of the complete suite and generate LCOV, text, and browsable HTML reports:
nix build -L -o result-coverage .#checks.x86_64-linux.coverage
xdg-open result-coverage/html/index.html
The same report is attached to every GitHub coverage run and uploaded to Codecov for per-file and pull-request coverage.
The native suite drives a dedicated headless st_test binary through a real raw PTY and checks externally visible terminal snapshots and output. The production st binary does not expose the test control entry point.
Known limits
Shitty does not currently implement bidirectional text layout or inline graphics protocols such as sixel. Some historical DEC and xterm extensions are intentionally outside the supported profile.
License transition and authorship
Shitty is a hard fork and complete rewrite of Zutty. The original Zutty terminal emulator was created by Tom Szilagyi. Shitty keeps that lineage, but replaces the architecture, renderer, platform integration, testing strategy, and project identity.
Shitty is moving from the imported GPL baseline to an MIT-only codebase. It does not intend to retain the GPL as the final project license.
The source snapshot first imported into this repository, and code predating that snapshot, remains licensed under GPLv3-or-later. New Shitty contributions are dual-licensed under GPLv3-or-later and MIT. While GPL-only imported material remains in the tree, distribution of the combined work is still subject to the GPL.
See LICENSE, LICENSE.GPL3, LICENSE.MIT, and CONTRIBUTING.md for the exact terms and contribution policy.
Tom Szilagyi is the original author of Zutty, from which Shitty descends. Shitty retains his copyright notices where historical code lineage requires them; subsequent work is copyright of the Shitty contributors.
这条对你有帮助吗?