Ghostel.el: Terminal emulator powered by libghostty
Ghostel.el: Terminal emulator powered by libghostty
Ghostel is a high-performance terminal emulator for Emacs that leverages libghostty-vt—the same powerful VT engine utilized by the Ghostty terminal.
🏗️ Architecture & Design
Ghostel employs a dual-layer architecture inspired by emacs-libvterm, splitting responsibilities between a low-level native module and high-level Elisp:
- Native Module (Zig): Manages the terminal state, handles rendering, and processes local PTY I/O.
- Elisp Layer: Controls buffers, commands, keymaps, and integration with remote processes.
While it follows the libvterm philosophy, it replaces the engine with Ghostty's modern implementation. This means libvterm's limitations are gone, replaced by:
- Kitty graphics and keyboard protocols.
- Advanced Styling: Rich underlines and OSC 8 hyperlinks.
- Color Queries: Support for OSC 4, 10, and 11.
- Synchronized Output: Support for DEC 2026.
🛠️ Installation & Setup
The native module is handled automatically on the first run, meaning most users don't need a compiler installed.
Installation Methods
- Option 1: Automatic Injection (Best for ease of use).
- Option 2: Manual Configuration (Best for permanent remote environments).
Using use-package (Emacs 30+):
(use-package ghostel
:vc (:url "https://github.com/dakra/ghostel"
:lisp-dir "lisp"
:rev :newest))
;; Note: :lisp-dir is mandatory for Emacs 31.1
Using :load-path:
(use-package ghostel :load-path "/path/to/ghostel/lisp")
Manual Setup:
(add-to-list 'load-path "/path/to/ghostel/lisp")
(require 'ghostel)
;; Run M-x ghostel to start
Native Module Management
The behavior for missing modules is governed by ghostel-module-auto-install (defaults to ask).
M-x ghostel-download-module: Fetches the latest compatible binary.C-u M-x ghostel-download-module: Allows selecting a specific release tag.M-x ghostel-module-compile: Builds the module from source.
⌨️ Configuration & Keybindings
Customizing the Experience
Users can tailor Ghostel to their workflow. For example, to mimic eshell history navigation or integrate with project.el:
(use-package ghostel
:bind (:map ghostel-mode-map
("M-p" . (lambda () (interactive) (ghostel-send-key "p" "ctrl")))
("M-n" . (lambda () (interactive) (ghostel-send-key "n" "ctrl")))
("C-c C-k" . ghostel-backward-kill-word))
:map project-prefix-map
("m" . ghostel-project-list-buffers))
:config
(defun ghostel-send-C-k-and-kill ()
"Kills to end of line and sends C-k to terminal."
(interactive)
(kill-ring-save (point) (line-end-position))
(ghostel-send-key "k" "ctrl"))
(add-to-list 'project-switch-commands '(ghostel-project "Ghostel" ) t)
(add-to-list 'project-switch-commands '(ghostel-project-list-buffers "Ghostel buffers" ) t)
(add-to-list 'ghostel-eval-cmds '("magit-status-setup-buffer" magit-status-setup-buffer)))
;; Extensions
(use-package ghostel-eshell :hook (eshell-load . ghostel-eshell-visual-command-mode))
(use-package ghostel-compile :hook (after-init . ghostel-compile-global-mode))
(use-package ghostel-comint :hook (after-init . ghostel-comint-global-mode))
;; For Evil users
(use-package evil-ghostel :after (ghostel evil) :hook (ghostel-mode . evil-ghostel-mode))
Shell Integration
Local sessions (bash, zsh, fish) have directory tracking and prompt navigation enabled by default. To trigger Emacs functions from the shell, add them to ghostel-eval-cmds and update your .bashrc:
Pro Tip: Use the
INSIDE_EMACSenvironment variable to create shell aliases that talk back to Emacs.
if [[ "$INSIDE_EMACS" = 'ghostel' ]]; then
# Open file in Emacs
e() { ghostel_cmd find-file-other-window "$@" ; }
# Open Dired
dow() { ghostel_cmd dired-other-window "$@" ; }
# Open Magit for current dir
gst() { ghostel_cmd magit-status-setup-buffer "$( pwd )" ; }
fi
🕹️ Input Modes
Ghostel utilizes five distinct input modes (similar to eat.el):
| Mode | Behavior | Key Characteristic |
|---|---|---|
| Semi-char | Default | Forwards most keys to the terminal. |
| Line | Like M-x shell | Buffer is standard Emacs; sends whole line on RET. |
| Emacs | Live Navigation | Standard Emacs buffer; terminal continues to update. |
| Copy | Frozen Navigation | Terminal output is paused for stable text selection. |
Seamless Transitions: With ghostel-readonly-fast-exit set to t, you can jump into Copy Mode (via C-c C-t), select your text, and immediately return to the terminal session by typing any character or copying the text. Mouse selection and hyperlink navigation (C-c C-p) also trigger this automatically.
📋 Requirements & Compatibility
System Requirements:
- Emacs: (must support dynamic modules).
- OS: macOS, Linux, FreeBSD, or Windows.
Pre-built Binary Support:
aarch64-macos/x86_64-macosaarch64-linux/x86_64-linuxx86_64-freebsdaarch64-windows/x86_64-windows
If you are building from source or using an unsupported platform, Zig 0.15.2 is required.