# Ghostel: a real VT engine inside an Emacs buffer

> Ghostel is an Emacs terminal emulator built on libghostty-vt, the VT engine from the Ghostty terminal, with true colour, synchronized output, the Kitty keyboard and graphics protocols, and shell integration for bash, zsh, fish and nushell. It suits an Emacs user who wants a terminal that is not a window, and it ships a prebuilt native module so no toolchain is needed.

**dakra/ghostel** — Terminal emulator powered by libghostty

- Repository: https://github.com/dakra/ghostel
- Stars: 1,017 · Forks: 64
- Language: Emacs Lisp
- License: GPL-3.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/dakra-ghostel

## The engine is the point

Ghostel is a terminal emulator for Emacs powered by libghostty-vt, the VT engine behind the Ghostty terminal. The project states its aims as featureful, fast, dependable and correct, and those four words map onto one architectural decision.

Some terminal emulators inside an editor are not real terminal emulators. They are screen scrapers that capture the output of a subprocess, interpret a subset of the escape sequences, and try to draw the result in a buffer. That approach breaks on the applications that matter most, because a full screen TUI program redraws the whole screen with cursor positioning, colour changes and partial erases in a way that a simple emulator cannot track.

Ghostel does not do that. It links the actual VT engine that Ghostty uses, so the parsing of escape sequences, the handling of screen regions and the state of the terminal are handled by the same code that runs a standalone Ghostty. That is why the feature list can include synchronized output, which is the protocol a program uses to tell a terminal to withhold partial frames while it redraws, and it is why true colour and the Kitty graphics protocol work as they do.

The screenshots in the README make the point concretely. btop is shown running in a Ghostel buffer with true colour and full TUI rendering, and yazi is shown previewing an image inside a Ghostel buffer through the Kitty graphics protocol. Neither of those is a plausible target for a screen-scraping emulator.

The licence is GPL-3.0-or-later, the primary language is Emacs Lisp, and the release history shows a fast cadence, v0.59.0 on 2026-10-19, v0.58.0 on 2026-10-15 and v0.57.0 on 2026-10-09, with the last push to the main branch on the same day as v0.59.0.

## Installing it, with no toolchain required

The quick start is short, and the requirement that matters is stated in the same breath as the install.

The requirements are Emacs 28.1 or newer with dynamic module support, on macOS, Linux, FreeBSD, Android or Termux, or native Windows. On first use Ghostel offers to download a prebuilt native module, and the README states plainly that no toolchain or build step is required.

That last point is what makes this practical for anyone but a Zig developer. The native module is the part that talks to libghostty-vt, and a C library usually means either a compiler on your machine or a prebuilt binary. Ghostel ships the prebuilt one, and the Windows release binaries are built for common native Windows Emacs builds on x86_64 and aarch64, with optional ConPTY support files from the Microsoft redistributable console runtime included, which the README says can improve latency and correctness compared with older inbox Windows ConPTY versions.

The install itself is the standard MELPA recipe:

```emacs-lisp
(use-package ghostel
  :ensure t)
```

and then M-x ghostel opens a terminal. There are badges for MELPA and for MELPA Stable, so the package is on both the rolling and the stable archive.

For anyone who wants the source path instead, the repository has a build.zig and a build.zig.zon, which is the Zig build system, so the native module is written in Zig and the Elisp side is the part that talks to Emacs.

## The feature list, and what shell integration buys you

The features section lists synchronized output, true color, the Kitty keyboard and graphics protocols, hyperlinks, desktop notifications, progress reports and a lot more.

Two of those are worth pausing on. Hyperlinks means a terminal program can emit a clickable link and Emacs can act on it, which is a small thing that makes documentation and tool output much nicer. Desktop notifications and progress reports cover the case where a long running command finishes while you are looking at something else, which in an editor is a different situation than in a standalone terminal.

Then there is shell integration, and the README says it all works out of the box for bash, zsh, fish and nushell. Directory tracking and prompt navigation are the two named features. Directory tracking is the one that makes an in-editor terminal feel native, because it means the shell tells the editor where you are, so a project-aware command runs in the right directory without you cd-ing first. Prompt navigation is the other direction, letting the editor move the shell cursor.

Four shells supported out of the box is a deliberate choice and a good one. Most in-editor terminals implement integration for one or two shells, and the ones that cover more usually do it with a fragile snippet. The documentation also compares Ghostel against vterm, the Emacs libvterm package, and eat, and there is a comparison section in the docs at dakra.github.io/ghostel.

The README notes that the feature list is not exhaustive and points to the documentation for the full list, which is the right place to look if you need to know whether a specific protocol is supported.

## Keybindings, functions and the semi-char mode

The fuller example in the README is the part that shows how this is meant to be used rather than merely installed.

```emacs-lisp
(use-package ghostel
  :bind (("C-x m" . ghostel)
         :map ghostel-semi-char-mode-map
         ("C-s"  . consult-line)
         ("C-k"  . my/ghostel-send-C-k-and-kill)
         ;; I'm used to go up/down the shell history with M-n/p from eshell
         ;; Simulate this behavior in ghostel by sending C-p and C-n
         ("M-p" . (lambda () (interactive) (ghostel-send-key "p" "ctrl")))
         ("M-n" . (lambda () (interactive) (ghostel-send-key "n" "ctrl"))))
  :config
  (defun my/ghostel-send-C-k-and-kill ()
    "Send `C-k' to ghostel.
Like normal Emacs `C-k'.  Kill to end of line and put content in kill-ring."
    (interactive)
    (kill-ring-save (point) (line-end-position))
    (ghostel-send-key "k" "ctrl"))
```

Two ideas are visible here. The first is ghostel-send-key, which sends a key sequence to the running program, and that is the primitive the whole integration rests on. The comment about simulating eshell's M-n and M-p by sending C-p and C-n makes the pattern explicit: you can bind an Emacs key to a sequence the program expects, and the terminal receives it as if you had typed it.

The second is the semi-char mode, which is a separate keymap that applies while the terminal has focus but still lets you reach Emacs commands. That is the design decision that makes an embedded terminal usable rather than a trap, and consulting the map is what the C-s binding above demonstrates, with consult-line bound inside the terminal.

The example also shows a custom function, my/ghostel-send-C-k-and-kill, that sends C-k to the terminal while performing the Emacs-side kill to end of line and putting the content in the kill-ring. It is a good illustration of the intended division of labour, since the Emacs side keeps its own semantics and the terminal side keeps its own.

## Extensions that ship in the box, and the two that do not

The extensions section is where Ghostel stops being a terminal and starts being part of an Emacs setup.

Several extensions ship with the Ghostel package with no separate install, and you enable what you want. ghostel-eshell makes eshell-visual-commands run in a Ghostel buffer. ghostel-compile runs all compile commands in a Ghostel buffer. ghostel-shell-command replaces async-shell-command with a Ghostel version. ghostel-comint replaces comint's built-in ansi-color-process-output with Ghostel's VT parser, which is the clearest statement of the whole project's value in one line. And ghostel-org adds a ghostel: Org link type, and ghostel-ime adds support for Quail based input methods such as Korean Hangul, Japanese and Chinese.

Two integrations live in separate packages instead. consult-ghostel, from MELPA, adds a terminal picker with live preview and create-on-miss, and with a prefix argument the pickers behave like ghostel and ghostel-project, where C-u creates a new terminal. consult-ghostel-mode also adds a Ghostel group to consult-bookmark, adds hidden ghostel sources to consult-buffer, and makes consult-line match across soft line wraps in ghostel buffers. There is a separate evil-ghostel extension for Evil users.

The history integration is worth one detail, because it is a small design decision. consult-ghostel-history picks from the shell's own command history and types the selection into the terminal, replacing what is already on the command line, and the history is retrieved per shell. If you use a history manager, you point the shell's entry in ghostel-shell-history-commands at it, and the example given is atuin:

```emacs-lisp
(setf (alist-get 'zsh ghostel-shell-history-commands)
      "atuin history list --cmd-only --print0 --reverse false")
```

That is a pluggable point rather than a hardcoded shell history, which is the right way round for a tool whose users arrive with their own history setup already in place.

## Conclusion

Adopt Ghostel if you live in Emacs and want a terminal buffer that handles full TUI applications properly, because embedding libghostty-vt means the escape sequence handling is a real VT implementation rather than a screen-scraping approximation. Do not adopt it as a general terminal replacement, since it lives inside an Emacs session. Before you install, check that your Emacs has dynamic module support and is 28.1 or newer, and on first use let it download the prebuilt native module rather than building from source, since the project says no toolchain or build step is required.

## FAQ

### What is Ghostel and what does it use as its terminal engine?

Ghostel is a terminal emulator for Emacs powered by libghostty-vt, the VT engine behind the Ghostty terminal. Because it links a real VT implementation rather than scraping output, it supports synchronized output, true colour, the Kitty keyboard and graphics protocols, hyperlinks, desktop notifications and progress reports.

### How do I install Ghostel?

You need Emacs 28.1 or newer with dynamic module support. Install from MELPA with `(use-package ghostel :ensure t)` and then run M-x ghostel. On first use Ghostel offers to download a prebuilt native module, and the README states that no toolchain or build step is required.

### Which shells does Ghostel support shell integration for?

Bash, zsh, fish and nushell work out of the box for directory tracking and prompt navigation. The shell history is retrieved per shell, and you can point ghostel-shell-history-commands at a history manager such as atuin.

### Can I use Ghostel with Evil mode and with Consult?

Yes, through separate packages. evil-ghostel adds Evil integration to Ghostel buffers, and consult-ghostel adds a terminal picker with live preview and create-on-miss, adds a Ghostel group to consult-bookmark, and makes consult-line match across soft line wraps. The core package also ships extensions for eshell visual commands, compile, async-shell-command, comint and Org links.

## Sources

- [dakra/ghostel on GitHub](https://github.com/dakra/ghostel)
- [Issues](https://github.com/dakra/ghostel/issues)
- [License: GPL-3.0](https://github.com/dakra/ghostel/blob/main/LICENSE)
- [README](https://github.com/dakra/ghostel/blob/main/README.md)
- [Releases](https://github.com/dakra/ghostel/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/dakra-ghostel
