Building a GUI Inside the Terminal: Experimenting with a Graphical Interface for Neovim

TJ built a graphical Neovim in under 10 days using embedded mode + GPUI, with arrow references, Markdown preview, and a Linear panel.
ThePrimeagen team member TJ demonstrated an experimental project that fully decouples Neovim's editor core from its rendering layer using embedded mode, handing off display to GPUI — the Rust GUI framework from the Zed team. The stack spans C, Rust, TypeScript, and Lua, with Bun enabling GUI plugin hot-reloading. Highlights include arrow-based reference visualization, a live bidirectional Markdown preview, and embedded Cursor session and Linear issue panels. Judges scored it 6–7 out of 10, praising the arrow references as genuine graphical integration while noting excessive floating overlays and lack of animation.
During a TheStandup livestream from ThePrimeagen's team, member TJ demonstrated a rather controversial experiment: layering a true graphical interface (GUI) on top of the terminal editor Neovim, then asking fellow member Casey to judge — does it feel more like a GUI or a TUI? Beneath this seemingly playful challenge lies a fundamental question that terminal editors have long grappled with: where exactly is the expressive ceiling of a text-based interface?
Why You Can Layer a GUI on Top of a Terminal Editor
Traditional terminal editors (TUIs) are constrained by the terminal itself — they can only draw interfaces using Unicode characters, and what they can render is entirely determined by which characters and protocols the terminal supports. In recent years, solutions like the kitty graphics protocol have enabled terminals to render actual images, but building rich graphical interactions remains deeply challenging overall.
TJ's approach sidesteps this limitation. Neovim offers an "embedded mode": it can run as a process hosted by another program. In this mode, Neovim no longer handles drawing itself to the terminal — instead, it simply reports the editor's state to the outside world, receives incoming events, and sends back the updated state. This mechanism has long been one of Neovim's core goals. Early projects like Firenvim already used a similar approach to embed Neovim inside web page input fields for editing long-form text.

In other words, the editor's "brain" and its "display" are completely decoupled. TJ exploited exactly this to hand off the rendering layer to an external program, breaking free from the character-grid constraint.
Neovim's embedded (or headless) mode is essentially a natural extension of its RPC architecture. When launched with the --embed or --headless flag, Neovim exposes a MessagePack-RPC interface over standard I/O or a Unix socket. An external host program can call any Neovim API, subscribe to UI update events (UI Events), and inject keystrokes and commands. This interface is called the "ext_ui" protocol, and it was intentionally designed to support any language and any rendering backend. Building on this foundation, the community has already produced mature GUI frontends like Neovide (Rust/OpenGL) and goneovim (Go/Qt) — neither of which modifies Neovim itself; they simply act as rendering hosts. TJ's project uses GPUI as its rendering backend, following the same path, with the key differences being the addition of a hot-reload layer and deeper tooling integration.
The Tech Stack: A "Polyglot" Project Across Four Languages
The technology choices in this project reflect the current vibe-coding ecosystem quite faithfully. The underlying Neovim is written in C; the GUI rendering layer uses GPUI, an immediate-mode graphics framework built in Rust by the Zed team; Bun is brought in to run a subsystem for hot-reloading GUI plugins — so you don't have to recompile the entire editor when tweaking plugin behavior; and Neovim's own configuration scripts are in Lua.
C, Rust, TypeScript, and Lua all on the same stage — TJ jokingly called himself "a bit of a polyglot." He also admitted that the project was built largely with AI assistance to move fast, and that many implementation details "you'd just have to ask the LLM." The layered strategy of "iterate quickly in JavaScript first, then push hot-path logic down to Rust once the approach is validated" is a direct benefit of the hot-reload architecture.
GPUI is a Rust GUI framework open-sourced by the Zed editor team, built around an "immediate mode" rendering philosophy: every frame re-describes the entire interface state from scratch, rather than maintaining a persistent component tree (retained mode). The classic example of immediate mode is Dear ImGui — the upside is extremely simple state management, where the UI is purely a function of the current data with no complex diffing or reconciliation logic; the trade-off is that every frame fully traverses all UI descriptions, placing higher demands on GPU throughput. GPUI builds on this foundation with deep optimizations for text editing: subpixel font rendering, GPU-accelerated text layout, and low-latency input handling — which is part of why Zed is known for its speed. TJ chose GPUI over more general-purpose frameworks like egui or Tauri because of its maturity in text-dense scenarios and its native compatibility with the Rust ecosystem.
From "Popup" to "True Integration": The GUI Dividing Line
The demo unfolded in order from "mundane to impressive." At the baseline level, all standard Neovim operations work as expected — Telescope, split windows, everything. On top of that, TJ added several graphical features: a native-style right-click context menu (great for operations you only use once a month and don't want to memorize a shortcut for), a floating Markdown preview window, and rich-text rendering with syntax-highlighted code, sequence diagrams, tables, and images.

Worth emphasizing: the Markdown preview is not a read-only popup — it's a live, bidirectional sync with the actual Neovim buffer. Editing inside the preview modifies the same buffer. This directly addresses a pain point Prime mentioned: LLMs love outputting tables and sequence diagrams, but those are nearly impossible to read in plain Vim.
What finally got Casey to agree "this really is a GUI" was the reference-finding feature: when you look up the references to a symbol, the editor literally draws arrows from the current location to every reference point. "Just follow the lines — anyone can use it." This kind of visualization — completely impossible inside a character grid — became the centerpiece of the entire demo. Other highlights included real-time drag-to-resize, a visual color scheme editor (drag-to-preview with zero lag), and connecting lines between text and icons in hover tooltips.
Editors Talking to Each Other: Cursor and Linear Integration
The project also demonstrated cross-tool collaboration. TJ showed an embedded Cursor session picker that lets you browse, render, and continue multiple Cursor conversations. He even ran a daemon process allowing different Neovim instances to communicate with each other via the Cursor SDK, then forwarding messages to his own machine via Tailscale.

Another highlight was the embedded Linear GUI, which lets you view and manage your team's issues directly from inside Neovim. TJ was candid about the limitations, though: state updates don't have webhook support yet, bidirectional sync hasn't been implemented, and you can only refresh manually. He added that this project "has only been worked on for less than 10 days," and many features are still in rough shape.

The Verdict and the Deeper Question
The three judges ultimately gave scores ranging from 6 to 7 out of 10 (where 10 represents "most GUI-like"). Casey gave 7 points, saying the arrow-based reference visualization was what made him feel it was "truly integrated," but that overall the floating-overlay approach dominated, there were no animated transitions, and he didn't see deeply fused scenarios like "generating graphical feedback alongside the code as you type." Trash and Prime each gave 6. Prime joked that this GUI was "too fast" — it was missing the GUI "essence" of perceptible input latency.
The points of debate were genuinely interesting. At one point TJ wanted to score based on "usefulness," which Casey firmly pushed back on, arguing that "the point of a GUI was never about being useful." This seemingly tongue-in-cheek exchange actually cuts to the heart of the long-standing divide between terminal purists and GUI advocates — TUIs pursue maximum efficiency and minimal distraction; GUIs pursue expressiveness and visualization. The boundary between the two is now being probed anew by combinations like "embedded rendering + AI-accelerated rapid prototyping."
This project may not be "the future of editors," but it clearly demonstrates one thing: when the rendering layer is decoupled from the editor core, and when AI dramatically lowers the cost of prototyping, those graphical experiments that were once "theoretically feasible but not worth anyone's time" are becoming genuinely accessible.
The term "vibe coding" was used by TJ in the video to describe his development approach for this project — a style of programming that relies heavily on AI assistance, driven by rapid feel (vibe) and immediate feedback rather than upfront careful design. The term was popularized by Andrej Karpathy in early 2025 to describe the workflow that emerges when developers collaborate with LLMs: "describe intent → accept the generation → quickly validate → keep iterating." Its core impact is a dramatic drop in the barrier to prototyping: cross-language glue code, integrating unfamiliar APIs, one-off debugging scripts — work that used to require extensive documentation lookup can now often be completed within a few rounds of conversation. TJ's candid admission that many project details required "asking the LLM" is a perfect illustration of this development mode — humans maintain architectural control while delegating the bulk of concrete implementation to the model. This is precisely why a project spanning four languages (C, Rust, TypeScript, Lua) was able to produce a demonstrable prototype in under 10 days.
Related articles

Felix Rieseberg Personal Homepage
Felix Rieseberg's personal homepage sparks attention on Hacker News. This article covers the Slack engineer's technical background, the rise and fall of nativefier, and the value of a developer homepage as a tech calling card.

@ai-sdk/vue 3.0.306 Patch Release Syncs with [email protected] Update
@ai-sdk/vue 3.0.306 released, synced with [email protected]. A routine patch release for the Vercel AI SDK ecosystem with no public API changes; the Vue adapter layer stays version-aligned with the core package.

Gemini 4 Argon API Launches: The Era of Million-Token Output Begins
Google launches Gemini 4 Argon with sparse MoE architecture, up to 1M output tokens, and a 68.90% Vals Index score, available across API, AI Studio, and the Gemini app.