emacs-libgterm

March 20, 2026 · View on GitHub

Terminal emulator for Emacs built on libghostty-vt, the terminal emulation library from the Ghostty terminal emulator.

This project follows the same architecture as emacs-libvterm but uses Ghostty's terminal engine, which offers:

  • SIMD-optimized VT escape sequence parsing
  • Better Unicode and grapheme cluster support
  • Text reflow on resize
  • Kitty graphics protocol support
  • Active development and maintenance

Status: Early prototype. Fully vibe coded. Only tested on macOS (Apple Silicon). Terminal works with ANSI colors, full key handling, scrollback, cursor sync, and drag-and-drop. Some character width mismatches with Powerline/NerdFont glyphs remain. Here be dragons.

Requirements

  • Emacs 25.1+ compiled with --with-modules (dynamic module support)
  • Zig 0.15.2+ (install via asdf install zig 0.15.2 or ziglang.org)
  • Git (to clone the Ghostty source)

Installation

(use-package gterm
  :straight (:host github :repo "rwc9u/emacs-libgterm" :files ("*"))
  :init
  (setq gterm-always-compile-module t))

Note: The :files ("*") is required so straight.el copies the Zig source files and build system, not just .el files.

use-package + vc (Emacs 30+)

(use-package gterm
  :vc (:url "https://github.com/rwc9u/emacs-libgterm" :branch "main")
  :init
  (setq gterm-always-compile-module t))

Note: use-package :vc copies all files by default, so no extra :files configuration is needed.

use-package + quelpa

(use-package gterm
  :quelpa (gterm :fetcher github :repo "rwc9u/emacs-libgterm" :files ("*"))
  :init
  (setq gterm-always-compile-module t))

use-package + local clone

(use-package gterm
  :load-path "/path/to/emacs-libgterm"
  :init
  (setq gterm-always-compile-module t))

Manual

(add-to-list 'load-path "/path/to/emacs-libgterm")
(require 'gterm)

Then M-x gterm to open a terminal.

What happens on first load

  1. gterm detects the missing compiled module
  2. Automatically clones Ghostty into vendor/ghostty (if not present)
  3. Applies a build patch for macOS compatibility (if needed)
  4. Compiles the Zig dynamic module via zig build
  5. Loads the module

The only prerequisite is having Zig and Git installed. Set gterm-always-compile-module to t to skip the confirmation prompt, or leave it nil to be asked first.

Manual build (optional)

If you prefer to build manually:

git clone https://github.com/rwc9u/emacs-libgterm.git
cd emacs-libgterm
zig build
zig build test  # run tests

Ghostty will be cloned automatically by zig build if not present, or you can clone it yourself:

git clone --depth 1 https://github.com/ghostty-org/ghostty.git vendor/ghostty

Usage

KeyAction
M-x gtermOpen a new terminal
Arrow keysNavigate / command history
C-y / Cmd-VPaste from kill ring
C-c C-kEnter copy mode (select text, y to copy, q to exit)
Shift-PageUp/DownScroll through history (page)
Mouse wheel / TrackpadScroll through history (5 lines)
C-c C-vSnap back to live terminal
C-c C-cSend Ctrl-C to shell
C-c C-dSend Ctrl-D (EOF) to shell
C-c C-zSend Ctrl-Z (suspend) to shell
Drag file from FinderSend file path to terminal

Build Options

# Specify custom Emacs include path (for emacs-module.h)
zig build -Demacs-include=/path/to/emacs/include

# Build with optimizations
zig build -Doptimize=ReleaseFast

Architecture

+----------------+     +---------------------+     +---------------+
|  gterm.el      |---->|  gterm-module.so    |---->|  ghostty-vt   |
|  (Elisp)       |     |  (Zig -> C ABI)     |     |  (Zig lib)    |
|                |     |                     |     |               |
| - PTY mgmt     |     | - Terminal create   |     | - VT parse    |
| - Keybinds     |     | - Feed bytes        |     | - Screen      |
| - Display      |     | - Styled render     |     | - Cursor      |
| - Copy/Paste   |     | - Cursor track      |     | - Scrollback  |
| - Scrollback   |     | - Mode query        |     | - Reflow      |
+----------------+     +---------------------+     +---------------+

Customization

;; Change shell (default: /bin/zsh)
(setq gterm-shell "/bin/bash")

;; Change TERM variable (default: xterm-256color)
(setq gterm-term-environment-variable "xterm-256color")

;; Auto-compile without prompting
(setq gterm-always-compile-module t)

;; Mouse wheel scroll speed (default: 5 lines per event)
(setq gterm-mouse-scroll-lines 5)

Known Issues

  • Character width mismatches — some Unicode characters (Powerline glyphs, NerdFont icons) may render at different widths in Emacs vs the terminal, causing minor alignment issues with fancy prompts
  • No mouse support — programs like htop that use mouse events are not yet supported

License

GPL-3.0 (required for Emacs dynamic modules)