Skip to content
Oeiuwq Faith Blog OpenSource Porfolio

eval-exec/neomacs

NEO Emacs: A GPU-powered Emacs written in Rust with a modern display engine. Aiming for modern design/multi-threaded Elisp, 10x performance and 100% Emacs compatibility. πŸš€ Inline 4K images/4K videos/WPEWebKit using GPU acceleration, DMA-BUF, ZERO-COPY. Rich animation effects support.

eval-exec/neomacs.json
{
"createdAt": "2026-02-03T08:45:40Z",
"defaultBranch": "main",
"description": "NEO Emacs: A GPU-powered Emacs written in Rust with a modern display engine. Aiming for modern design/multi-threaded Elisp, 10x performance and 100% Emacs compatibility. πŸš€ Inline 4K images/4K videos/WPEWebKit using GPU acceleration, DMA-BUF, ZERO-COPY. Rich animation effects support.",
"fullName": "eval-exec/neomacs",
"homepage": "https://neomacs.org",
"language": "Emacs Lisp",
"name": "neomacs",
"pushedAt": "2026-03-20T00:49:52Z",
"stargazersCount": 548,
"topics": [
"elisp",
"emacs",
"lisp",
"neomacs",
"rust",
"wgpu",
"winit"
],
"updatedAt": "2026-03-20T00:49:55Z",
"url": "https://github.com/eval-exec/neomacs"
}

β€œI started Neomacs because I love Emacs, I respect Emacs, and I want to evolve the legendary Emacs into the ultimate modern powerhouse.” β€” Eval Exec

✨ β€œWhile other editors can save your files, only Emacs can save your soul.” ✨

NEOMACS banner

Status: Alpha Rust 1.93.1 License: GPL-3.0

Neomacs is a long-term project that takes significant ongoing work to build, test, and maintain. If you want to support its development, please consider sponsoring it on ❀️ GitHub Sponsors.

Note: Neomacs is in active alpha development. Expect rough edges, breaking changes, and missing features. Contributions and bug reports are very welcome!

Fork notice: Neomacs is a hard fork of GNU Emacs, forked from commit 705c0e3729. The changes are too invasive to ever be accepted upstream, so we did not preserve the original git history to keep the repository lightweight. If you need the full Emacs git history for reference, open an issue, and we can re-add it.

Why a fork, not from scratch? Neomacs aims for 100% compatibility with official GNU Emacs β€” every config, package, and workflow should just work. By forking, we keep the original Emacs C code as a reference and test oracle: we can verifying that each Rust rewrite produces identical behavior, ensuring nothing breaks as subsystems are replaced one by one.


Emacs is a 40-year-old C codebase that hasn’t kept up with modern hardware or software engineering:

  • Display engine β€” ~50,000 lines of C in xdisp.c, designed for text terminals in the 1980s. CPU-only rendering, no GPU acceleration, no native video/animations, no smooth visual effects
    • Large images β€” rendering slows down significantly
    • Video playback β€” not natively supported
    • Modern animations β€” no smooth cursor movement, buffer transitions, or visual effects
    • Web content β€” limited browser integration
    • GPU utilization β€” everything runs on CPU while your GPU sits idle
  • Elisp performance β€” no inline caching, stop-the-world GC, dynamic dispatch overhead. Even with native-comp (AOT), Elisp lacks runtime JIT optimization, speculative inlining, and concurrent GC β€” leaving significant performance on the table
  • Unsafe C codebase β€” ~300,000 lines of unsafe C with manual memory management, monolithic architecture (runtime and editor entangled), single-threaded design that prevents real concurrency

Throw it all away and start fresh.

Neomacs is rewriting Emacs from the ground up in Rust β€” starting with the display engine and expanding to the core:

  • GPU display engine (done) β€” ~4,000 lines of Rust replacing ~50,000 lines of legacy C, powered by wgpu (Vulkan/Metal/DX12/OpenGL)
  • Rust layout engine (done) β€” bypasses xdisp.c entirely, reads buffer text via FFI and computes layout in Rust
  • Inline video/images/WebKit (done) β€” 4K video, GPU-decoded images, and WPE WebKit browser views embedded directly in buffers
  • 21 scroll effects, 8 cursor modes, 10 buffer transitions (done) β€” GPU-accelerated animations running on the render thread at display refresh rate
  • Zero-copy DMA-BUF (done) β€” efficient GPU texture sharing (Linux)
  • Rewrite entire Emacs core in Rust (in progress) β€” replacing all ~300,000 lines of C with safe, modern Rust: Elisp runtime, evaluator, bytecode VM, GC, buffer/window/frame subsystems, and all editor internals
  • True multi-threaded Elisp (planned) β€” real concurrency for the Lisp machine, not just cooperative threading
  • 10x performance, and 100% Emacs compatibility. (planned) β€” Rust-optimized Lisp machine with JIT compilation and inline caching

🎬 Neomacs youtube video

Neomacs Showcase Video

https://github.com/user-attachments/assets/85b7ee7b-3f4a-4cd2-a84f-86a91d052f11

Round corner box face attribute

GPU-decoded directly β€” no CPU cost, won’t block Emacs main thread.

Inline 4K images in Emacs buffer

GPU backend, DMA-BUF zero-copy.

Inline WPE WebKit browser in Emacs buffer

GPU-backed terminal emulator embedded in Emacs buffer.

Inline Alacritty terminal in Emacs buffer

DMA-BUF zero-copy, GPU backend β€” no CPU cost.

https://github.com/user-attachments/assets/275c6d9a-fced-44f6-8f43-3bbd2984d672


FeatureDescription
GPU Text RenderingHardware-accelerated text via wgpu (Vulkan/Metal/DX12/OpenGL)
Video PlaybackGStreamer + VA-API hardware decode with DMA-BUF zero-copy
Cursor Animations8 modes with 7 movement styles and configurable spring trail
Scroll Animations21 scroll effects with 5 easing functions
Buffer Transitions10 buffer-switch effects (crossfade, slide, page-curl, etc.)
DMA-BUF Zero-CopyGPU-to-GPU texture sharing via Vulkan HAL (no CPU readback)
Inline ImagesGPU-accelerated image rendering in buffers
Inline WebKitWPE WebKit browser views embedded in buffers

All animations run on the GPU render thread at display refresh rate, independent of the Emacs redisplay. Configure everything from Elisp.

8 particle/visual modes (Neovide-inspired):

ModeDescription
noneNo animation, instant movement
smoothSmooth interpolated movement (default)
railgunParticles shoot backward from cursor
torpedoComet-like trail follows cursor
pixiedustSparkly particles scatter around cursor
sonicboomShockwave ring expands from cursor
rippleConcentric rings emanate outward
wireframeAnimated outline glow

7 movement styles controlling how the cursor interpolates between positions:

StyleDescription
exponentialSmooth deceleration, no fixed duration (uses speed param)
springCritically-damped spring, Neovide-like feel (default)
ease-out-quadGentle deceleration curve
ease-out-cubicStronger deceleration curve
ease-out-expoSharp deceleration curve
ease-in-out-cubicSmooth S-curve
linearConstant speed

The spring style also supports a 4-corner trail effect where leading corners snap ahead and trailing corners stretch behind, controlled by a trail-size parameter (0.0-1.0).

10 buffer-switch effects triggered when the visible buffer changes:

EffectDescription
noneInstant switch
crossfadeAlpha blend between old and new (default)
slide-left/right/up/downDirectional slide transitions
scale-fadeScale and fade
pushNew buffer pushes old buffer out
blurBlur transition
page-curl3D page-turning effect

21 scroll animation effects organized into categories:

#EffectCategoryDescription
0slide2DContent slides in scroll direction (default)
1crossfade2DAlpha blend between old and new positions
2scale-zoom2DDestination zooms from 95% to 100%
3fade-edges2DLines fade at viewport edges
4cascade2DLines drop in with stagger delay
5parallax2DLayers scroll at different speeds
6tilt3DSubtle 3D perspective tilt
7page-curl3DPage turning effect
8card-flip3DCard flips around X-axis
9cylinder-roll3DContent wraps around cylinder
10wobblyDeformationJelly-like deformation
11waveDeformationSine-wave distortion
12per-line-springDeformationEach line springs independently
13liquidDeformationNoise-based fluid distortion
14motion-blurPost-processVertical blur during scroll
15chromatic-aberrationPost-processRGB channel separation
16ghost-trailsPost-processSemi-transparent afterimages
17color-temperaturePost-processWarm/cool tint by direction
18crt-scanlinesPost-processRetro scanline overlay
19depth-of-fieldPost-processCenter sharp, edges dim
20typewriter-revealCreativeLines appear left-to-right

5 scroll easing functions:

#EasingDescription
0ease-out-quadStandard deceleration (default)
1ease-out-cubicStronger deceleration
2springCritically damped spring with overshoot
3linearConstant speed
4ease-in-out-cubicSmooth S-curve
;; All-in-one configuration:
;; (neomacs-set-animation-config
;; CURSOR-ENABLED CURSOR-SPEED CURSOR-STYLE CURSOR-DURATION
;; CROSSFADE-ENABLED CROSSFADE-DURATION
;; SCROLL-ENABLED SCROLL-DURATION
;; &optional SCROLL-EFFECT SCROLL-EASING TRAIL-SIZE)
;; Example: spring cursor, crossfade buffer switch, page-curl scroll with spring easing
(neomacs-set-animation-config t 15.0 'spring 150 t 200 t 150 7 2 0.7)
;; Example: fast linear cursor, no crossfade, wobbly scroll
(neomacs-set-animation-config t 20.0 'linear 100 nil 200 t 200 10 0 0.0)

Neomacs aims to be the most capable and beautiful Emacs ever built, rewriting its internals in Rust:

  • Rich media β€” 4K video, PDF rendering, image manipulation directly in buffers
  • GPU-native β€” hardware-accelerated rendering, shader effects, 120fps animations
  • GPU terminal β€” Rust-based terminal emulator replacing slow term.el/ansi-term/vterm
  • Cross-platform β€” Linux (Vulkan), macOS (Metal), Windows (Vulkan/DX12)
  • Rust core β€” rewrite Emacs C internals in Rust for memory safety and performance
  • Multi-threaded Elisp β€” true concurrency for the Lisp machine, enabling parallel Elisp execution
  • 10x faster Elisp β€” Rust-optimized Lisp interpreter/compiler to dramatically speed up Elisp

The goal: Make Emacs as powerful and beautiful as it deserves to be.


Neomacs is rewriting Emacs from C to Rust with clean module boundaries. The goal is a layered architecture where the Elisp runtime is a self-contained core, editor subsystems are independent modules communicating through defined APIs, and the rendering engine runs on a separate GPU thread.

The rendering engine and layout engine are already in Rust. The Emacs C core still runs the Elisp evaluator, GC, and editor subsystems β€” connected to Rust via FFI channels.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Neomacs (Rust) β”‚
β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Elisp Runtime Core β”‚ β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚ β”‚ β”‚ Evaluator β”‚ β”‚ Bytecode VM β”‚ β”‚ GC/Allocatorβ”‚ β”‚ β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚ β”‚ β”‚ LispObject β”‚ β”‚Symbol Table β”‚ β”‚ Type System β”‚ β”‚ β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚ β”‚
β”‚ β–Ό β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Runtime API β”‚ β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚ β”‚ β”‚register_typeβ”‚ β”‚register_rootβ”‚ β”‚define_func β”‚ β”‚ β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚ β”‚ β”‚ run_hook β”‚ β”‚ specbind β”‚ β”‚signal_error β”‚ β”‚ β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚ β”‚
β”‚ β–Ό β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Editor Modules β”‚ β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”β”‚ β”‚
β”‚ β”‚ β”‚ Buffer β”‚ β”‚ Window β”‚ β”‚ Frame β”‚ β”‚Keyboardβ”‚ β”‚Processβ”‚β”‚ β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”˜β”‚ β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”β”‚ β”‚
β”‚ β”‚ β”‚ Font β”‚ β”‚ Image β”‚ β”‚File IO β”‚ β”‚ Reader β”‚ β”‚ Data β”‚β”‚ β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”˜β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚ β”‚
β”‚ β–Ό β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Rendering Engine β”‚ β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚ β”‚ β”‚Layout Engineβ”‚ β”‚wgpu Rendererβ”‚ β”‚ Animations β”‚ β”‚ β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚ β”‚ β”‚ winit β”‚ β”‚ WebKit β”‚ β”‚ GStreamer β”‚ β”‚ β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Threading β”‚ β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚ β”‚ β”‚EmacsThread β”‚ β”‚RenderThreadβ”‚ β”‚ β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚ β”‚ β”‚ β–² β”‚ β”‚
β”‚ β”‚ β”œβ”€β”€ FrameGlyphBuffer (crossbeam) β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚ β”‚ └── InputEvent (crossbeam) ────────────────────┐ β”‚ β”‚
β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Backends β”‚ β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚ β”‚ β”‚ Vulkan β”‚ β”‚ Metal β”‚ β”‚ DX12/GL β”‚ β”‚ β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Design principles:

  • Elisp Runtime Core is a self-contained Rust crate. It owns LispObject, the evaluator, bytecode VM, GC, specpdl, and symbol table. It does NOT know about buffers, windows, frames, or any editor concept.
  • Runtime API is a trait-based interface. Editor modules register their types (with GC trace descriptors), roots, and primitives. The GC traces registered types generically β€” no hardcoded mark_kboards() or mark_terminals().
  • Editor Modules are independent. Each owns its data structures and exposes them to Lisp through the Runtime API. Modules do not reach into each other’s internals.
  • Rendering Engine runs on a separate GPU thread, communicating via crossbeam channels (FrameGlyphBuffer down, InputEvent up). Already implemented.
  • Memory safety without garbage collection
  • Zero-cost abstractions for high-performance rendering
  • Excellent FFI with C (Emacs core)
  • Modern tooling (Cargo, async, traits)
  • Growing ecosystem for graphics (wgpu, winit, cosmic-text)
  • Cross-platform β€” single API for Vulkan, Metal, DX12, and OpenGL
  • Safe Rust API β€” no unsafe Vulkan/Metal code in application
  • WebGPU standard β€” future-proof API design
  • Active development β€” used by Firefox, Bevy, and many others

For an in-depth analysis of the current Emacs C architecture, why it’s hard to rewrite, and why Elisp is slow, see [docs/elisp-core-analysis.md]!(docs/elisp-core-analysis.md).


  • Emacs source (this is a fork)
  • Rust (stable, 1.92+)
  • GStreamer (optional, for video playback β€” the video feature)
  • WPE WebKit (optional, for inline browser β€” the wpe-webkit feature, Linux only)
  • VA-API (optional, for hardware video decode on Linux)

The Rust display engine has optional features that can be selectively enabled:

FeatureDefaultDescription
videoyesGStreamer video playback
wpe-webkityesWPE WebKit browser embedding (Linux only)
neo-termyesGPU terminal emulator

To build without a feature, use --no-default-features and list only the features you want.

Build commands in this README are run from the repository root. There is no ./rust/ subdirectory.

Terminal window
# Optional (recommended): use the repo dev shell (handles all dependencies)
nix develop --accept-flake-config
# Build Neomacs
cargo build --release --manifest-path neomacs-bin/Cargo.toml
# Run
./target/release/neomacs
Terminal window
# Install dependencies
sudo pacman -S --needed \
base-devel autoconf automake texinfo clang git pkg-config \
gtk4 glib2 cairo \
gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad \
wpewebkit wpebackend-fdo \
wayland wayland-protocols \
mesa libva \
libjpeg-turbo libtiff giflib libpng librsvg libwebp \
ncurses gnutls libxml2 sqlite jansson tree-sitter \
gmp acl libxpm \
libgccjit
# Install Rust (if not already installed)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Build Neomacs
cargo build --release --manifest-path neomacs-bin/Cargo.toml
# Run
./target/release/neomacs

macOS support is experimental β€” see issue #22 for status.

WPE WebKit is Linux-only, so you must disable it. GStreamer is optional.

Terminal window
# Install dependencies (Homebrew)
brew install autoconf automake texinfo pkgconf \
glib cairo \
gstreamer gst-plugins-base gst-plugins-good \
jpeg-turbo libtiff giflib libpng librsvg webp \
gnutls libxml2 sqlite jansson tree-sitter gmp
# Install Rust (if not already installed)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Build Neomacs
cargo build --release --manifest-path neomacs-bin/Cargo.toml \
--no-default-features --features neo-term
# Run
./target/release/neomacs

This defaults to full mode and already applies:

  • AUTO_INSTALL_DEPS=1
  • RUST_FEATURES='video,neo-term'
  • NEOMACS_CONFIGURE_FLAGS='--without-ns --with-file-notification=no --with-native-compilation=no --with-neomacs'
Terminal window
docker build -f Dockerfile.arch -t neomacs-build-arch .
docker build -f Dockerfile.ubuntu --build-arg UBUNTU_VERSION=22.04 -t neomacs-build-ubuntu22 .
docker build -f Dockerfile.ubuntu --build-arg UBUNTU_VERSION=24.04 -t neomacs-build-ubuntu24 .
docker build -f Dockerfile.debian --build-arg DEBIAN_VERSION=bookworm -t neomacs-build-debian .

Dockerfile.arch is the original Arch Linux environment. Dockerfile.ubuntu and Dockerfile.debian default to Rust features "video,neo-term" (WPE WebKit disabled for broader package compatibility).

If your distro/repo has WPE WebKit dev packages, enable browser embedding:

Terminal window
docker build -f Dockerfile.ubuntu \
--build-arg UBUNTU_VERSION=24.04 \
--build-arg RUST_FEATURES="video,neo-term,wpe-webkit" \
-t neomacs-build-ubuntu24-wpe .

Neomacs uses nix-wpe-webkit for the WPE WebKit dependency. Pre-built binaries are available via Cachix (~60MB download instead of ~1 hour build).

The flake.nix includes nixConfig for the Cachix cache. Pass --accept-flake-config to use it automatically, or configure it system-wide:

NixOS β€” add to your configuration (e.g., /etc/nixos/configuration.nix):

{
nix.settings.substituters = [ "https://nix-wpe-webkit.cachix.org" ];
nix.settings.trusted-public-keys = [ "nix-wpe-webkit.cachix.org-1:ItCjHkz1Y5QcwqI9cTGNWHzcox4EqcXqKvOygxpwYHE=" ];
}

Non-NixOS β€” add to ~/.config/nix/nix.conf:

extra-substituters = https://nix-wpe-webkit.cachix.org
extra-trusted-public-keys = nix-wpe-webkit.cachix.org-1:ItCjHkz1Y5QcwqI9cTGNWHzcox4EqcXqKvOygxpwYHE=

Option 1 β€” Trust the nixConfig in flake.nix (simplest):

Terminal window
nix build --accept-flake-config
# Or enter development shell
nix develop --accept-flake-config

Option 2 β€” Pass Cachix flags directly:

Terminal window
nix build \
--extra-substituters "https://nix-wpe-webkit.cachix.org" \
--extra-trusted-public-keys "nix-wpe-webkit.cachix.org-1:ItCjHkz1Y5QcwqI9cTGNWHzcox4EqcXqKvOygxpwYHE="

Note: Both options require your user to be in trusted-users in /etc/nix/nix.conf (e.g., trusted-users = root @wheel your-username), or configure the cache system-wide as shown above.

Terminal window
cargo build --release --manifest-path neomacs-bin/Cargo.toml

  • Linux – primary supported platform. The steps above document a validated Arch Linux workflow, but other distributions should follow similar dependency installation with their package manager.
  • macOS – experimental. See issue #22 for status.
  • Windows – planned.
  • Mobile (Android/iOS) – planned.
  • WebAssembly (WASM) – planned.

The Rust display engine rewrite is complete β€” the Rust layout engine is now the only rendering path, bypassing xdisp.c entirely. See [docs/rust-display-engine.md]!(docs/rust-display-engine.md) for the design document.

Completed:

  • GPU text rendering, face resolution, syntax highlighting
  • Display properties, overlays, invisible text, line numbers
  • Mode-line, header-line, tab-line
  • Variable-width fonts, BiDi text layout
  • Word-wrap, truncation, fringes, margins
  • Images, video, WebKit embedding

In progress:

  • Rewriting the entire Emacs C core in Rust (Elisp runtime, evaluator, bytecode VM, GC, buffer/window/frame subsystems)
  • macOS and cross-platform support
  • TUI (terminal) renderer

Planned:

  • True multi-threaded Elisp
  • JIT compilation and inline caching for 10x Elisp performance

Contributions welcome! Areas where help is needed:

  • Graphics programmers β€” shader effects, rendering optimizations
  • Rust developers β€” architecture, performance, safety
  • Emacs hackers β€” Lisp API design, integration testing
  • Documentation β€” tutorials, API docs, examples

Built with:

  • wgpu β€” Cross-platform GPU rendering (Vulkan/Metal/DX12/GL)
  • winit β€” Cross-platform window management
  • cosmic-text β€” Pure Rust text shaping
  • GStreamer β€” Video playback with VA-API
  • ash β€” Vulkan bindings for DMA-BUF import
  • Inspired by Neovide cursor animations

GNU General Public License v3.0 (same as Emacs)

Star History Chart