惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

E
Exploit-DB.com RSS Feed
S
SegmentFault 最新的问题
aimingoo的专栏
aimingoo的专栏
H
Help Net Security
N
Netflix TechBlog - Medium
F
Fortinet All Blogs
人人都是产品经理
人人都是产品经理
G
Google Developers Blog
Last Week in AI
Last Week in AI
U
Unit 42
A
Arctic Wolf
博客园_首页
Engineering at Meta
Engineering at Meta
D
DataBreaches.Net
C
CXSECURITY Database RSS Feed - CXSecurity.com
罗磊的独立博客
B
Blog RSS Feed
W
WeLiveSecurity
Security Latest
Security Latest
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
腾讯CDC
Help Net Security
Help Net Security
NISL@THU
NISL@THU
T
The Blog of Author Tim Ferriss
博客园 - 叶小钗
S
Security @ Cisco Blogs
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Spread Privacy
Spread Privacy
T
Threat Research - Cisco Blogs
Google Online Security Blog
Google Online Security Blog
C
CERT Recently Published Vulnerability Notes
F
Full Disclosure
GbyAI
GbyAI
Hacker News: Ask HN
Hacker News: Ask HN
P
Proofpoint News Feed
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
雷峰网
雷峰网
P
Privacy & Cybersecurity Law Blog
Scott Helme
Scott Helme
Google DeepMind News
Google DeepMind News
T
Tor Project blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Apple Machine Learning Research
Apple Machine Learning Research
MongoDB | Blog
MongoDB | Blog
O
OpenAI News
T
Threatpost
A
About on SuperTechFans
TaoSecurity Blog
TaoSecurity Blog
T
The Exploit Database - CXSecurity.com

Show HN

暂无文章

GitHub - vidarh/rubyterm: Tiny ruby terminal for X11
vidarh · 2026-06-16 · via Show HN

A terminal emulator written entirely in Ruby — including a pure-Ruby X11 client to talk to the X server and a pure-Ruby font renderer.

There is no C extension and no libvte; the escape-sequence interpreter, the screen buffer, the rendering and the X11 protocol handling are all Ruby.

It is still rough and opinionated, but it now runs as an installable gem with a rubyterm executable, renders with a damage-driven pipeline (scrollback, text selection/copy, truecolor and UTF-8 all work), and is split into a reusable terminal engine that can be driven without X11 at all.

NOTE: Escape-code coverage is partial (VT100/VT102 plus a useful chunk of xterm), font handling is basic, and the keymap is limited. It is slow, though it is my main driver. Full-screen apps mostly work; some will still misbehave. I have specific ideas about direction, so if you'd like to contribute, talk to me first (vidar@hokstad.com) or fork — I won't promise to merge changes we haven't discussed.

Screenshots of Ruby-in-Ruby-in-Ruby-...

Rubyterm

This shows Rubyterm running on my Ruby based WM, running Rubyterm with a text-based-backend that renders a a terminal to text (so it can run in any terminal), running my editor Re editing the Rubyterm example. The text is rendered using the pure-Ruby TrueType font renderer Skrift, and connected to my X11 server using the Pure-X11 Ruby X11 bindings (no libX or XCB, just pure Ruby socket code).

Architecture

The code is deliberately small and split along clean seams so the pieces are independently usable and testable:

  • Engine — the escape interpreter (Term), the damage tracker (TrackChanges), the columnar screen buffer (TermBuffer) and the escape/UTF-8 parsers. No pixels, no X11; drivable headlessly.
  • Backends — anything implementing the small drawing interface:
    • Window — the pure-Ruby X11 backend (the real terminal);
    • AnsiBackend — re-emits to an ANSI/escape stream (run a terminal inside another terminal; see examples/terminal_in_terminal.rb);
    • BitmapWindow — rasterises glyphs with skrift into an in-memory RGB buffer (headless rendering / visual testing, PNG output).
  • ApplicationRubyTerm (in lib/rubyterm/app.rb), which owns the X window, the pty controller and the input/blink/flush threads and wires the engine to the X11 backend. bin/rubyterm runs it.

Rendering is damage-driven: writing a cell only mutates the buffer and bumps a per-cell generation; a flush walks the damage and redraws just the changed cells. A flood of output (an accidental cat of a large file) is jump-scrolled — interpreted across many chunks and painted once.

For the full picture and the rationale behind the layering, see:

  • docs/architecture-review.md — the architecture critique, the phased refactoring plan, and the Ruby performance notes (with measured results).
  • docs/seams.md — the layer seams: the screen-operation API and the backend drawing protocol.

Installation

Dependencies are managed with Bundler.

skrift and skrift-x11 are developed alongside this project and are pulled from git. To build against a local checkout instead of the pushed branch, set a per-machine local override (kept out of the repo):

bundle config set --global local.skrift     /path/to/skrift
bundle config set --global local.skrift-x11 /path/to/skrift-x11

Running

bundle exec rubyterm                 # start a terminal running your $SHELL
bundle exec rubyterm bash -lc htop   # ...or run a specific command

With some luck you'll get a terminal window. Once the gem (and its dependencies) are installed system-wide, the rubyterm executable can be run directly.

Configuration

Configuration is read from ~/.config/rterm/config.toml (TOML). See example-config.toml for a complete example. If the file is absent, defaults are used.

  • shell — path to the shell to launch. Defaults to $SHELL, then /bin/sh. Example: shell = "/bin/bash".
  • fonts — fonts to use, in priority order; later fonts cover glyphs missing from earlier ones. Each entry may be a direct path ("~/fonts/MyFont.ttf"), a file in ~/.local/share/fonts/, or a name resolved via fc-match ("monospace", "monospace:weight=bold").
  • fontsize — font size in points (e.g. fontsize = 24).
  • width / height — initial window size in pixels; the terminal grid is derived from it and the font cell size. Defaults to 1000 x 600 (~80×24 at the default font); on a big display, e.g. width = 2000 / height = 1200.
  • deccolm — how the 80/132-column DECCOLM switch is realised: "font" (rescale the glyph cell, the default) or "window" (ask the WM to resize).
shell = "/bin/zsh"
fonts = [
  "FiraCode-Regular.ttf",   # programming font
  "unifont-15.0.06.ttf",    # Unicode fallback
  "monospace"               # system fallback
]
fontsize = 24

Development

rake test          # the minitest unit/integration suite
rake run           # run the terminal (alias for bin/rubyterm)

There is a deterministic test harness for terminal correctness: it runs cases through the engine and an oracle (tmux), diffs the resulting screen state, and gates regressions with a ratchet. It can also record and replay real applications, and run an instrumented live terminal with a debug socket.

ruby harness/cli.rb run   --case cases/synthetic/dch.bin --oracle tmux
ruby harness/cli.rb sweep --cases cases --oracle tmux --ratchet ratchet.json

Direction

Where I want to take this:

  • Keep the engine fully decoupled from the pty and X11 so Ruby applications can instantiate a "terminal" with an IO object as its interface — the first consumer being my own text editor — and package the engine as a gem. (The split exists; the gem and the editor migration are in progress.)
  • Make the terminal complete enough to run most Unix command-line tools: a reasonably complete, Unicode-aware xterm/VT100.
  • Keep the code small but understandable. Terseness is valued only while it preserves readability.

Resources