logo
Kurashizu Blogwhere ideas flow
  • Home
  • News
  • Blog
  • About
  • Home
  • News
  • Blog
  • About

© 2026 Kurashizu. All rights reserved.

Admin·New Post·Service Status
Powered by Cloudflare·01.11.26
← Back to news

Ghostel.el: Terminal emulator powered by libghostty

Original article
dakra.github.io|192 points|30 comments|by signa11|Jul 12, 2026

MELPA MELPA Stable CI Release License: GPL-3.0-or-later VT engine: libghostty-vt

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_EMACS environment 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):

ModeBehaviorKey Characteristic
Semi-charDefaultForwards most keys to the terminal.
LineLike M-x shellBuffer is standard Emacs; sends whole line on RET.
EmacsLive NavigationStandard Emacs buffer; terminal continues to update.
CopyFrozen NavigationTerminal 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: ≥28.1\ge 28.1≥28.1 (must support dynamic modules).
  • OS: macOS, Linux, FreeBSD, or Windows.

Pre-built Binary Support:

  • aarch64-macos / x86_64-macos
  • aarch64-linux / x86_64-linux
  • x86_64-freebsd
  • aarch64-windows / x86_64-windows

If you are building from source or using an unsupported platform, Zig 0.15.2 is required.