Ndx is a native Windows graphical client for Neovim, written in C++20. It renders Neovim's UI with DirectWrite and Direct2D and adds Windows-focused features such as TSF input method support, font fallback lists, and optional cursor and scrolling animations.
Ndx is a personal project based on the earlier Nvy codebase. Its history and the point where Ndx-specific development began are documented at the end of this README.
2026-10-03.15-41-03.mp4
- Native Windows rendering with DirectWrite and Direct2D
- Text Services Framework (TSF) support for IMEs, including inline composition text and a cursor-following candidate window
- Comma-separated
guifontfont lists, with fallback fonts for missing glyphs - Optional animated cursor, cursor effects, smooth scrolling, and smooth cursor blinking
- Fullscreen and a borderless window, toggled from Neovim; Ctrl+mouse wheel to zoom
- Transparent background with the Windows 11 Mica or Acrylic backdrop
- Drag and drop files to open them; hold Ctrl while dropping to open them in a new window
- Command-line options for window placement, geometry, fonts, and the Neovim executable
- Windows
- Neovim (
nvim.exe), preferably a recent release - To build: Visual Studio with the C++ workload, CMake, Ninja, and a recent Windows SDK
From PowerShell:
git clone https://github.com/fanlusky/Ndx.git
cd Ndx
.\scripts\build.ps1 # Release -> build\release\Ndx.exe
.\scripts\build.ps1 -Config Debug # Debug -> build\debug\Ndx.exe
.\scripts\build.ps1 -Clean -Run # Clean build, then launchThe script enters the MSVC x64 developer environment when needed. You can also configure and build with CMake and Ninja directly:
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build buildNdx starts Neovim as its editing backend. It sets g:ndx = 1, which you can use to customize your Neovim configuration when running inside Ndx.
Set the font in your Neovim configuration, for example:
set guifont=CaskaydiaCove\ Nerd\ Font,Source\ Han\ Sans\ SC:h12The first installed font is used as the main font; later fonts provide glyph fallback. The font size can be specified with :h12. The Lua equivalent is:
vim.opt.guifont = { "CaskaydiaCove Nerd Font", "Source Han Sans SC", ":h12" }Available command-line options:
| Option | Description |
|---|---|
--maximize |
Start maximized |
--fullscreen |
Start fullscreen |
--position=<x>,<y> |
Set the initial window position, for example --position=500,200 |
--position=center |
Center the window on its monitor at startup, excluding the taskbar |
--geometry=<cols>x<rows> |
Set the initial grid size, for example --geometry=80x25 |
--disable-ligatures |
Disable font ligatures |
--disable-fullscreen |
Ignore g:ndx_fullscreen |
--linespace-factor=<float> |
Set line spacing, for example --linespace-factor=1.2 |
--cursor-timeout=<int> |
Hide the cursor after the given idle time in milliseconds |
--neovim-bin=<path> |
Use a specific nvim.exe path |
The command-line options can also be set in %LOCALAPPDATA%\Ndx\config.toml, which is read at startup. Options given on the command line take precedence over the file.
position = "center" # or "500,200"
geometry = "100x30" # <cols>x<rows>
maximize = false
fullscreen = false
disable_ligatures = false
disable_fullscreen = false
linespace_factor = 1.2
cursor_timeout = 3000 # milliseconds, 0 turns it off
neovim_bin = 'C:\Program Files\Neovim\bin\nvim.exe'Only top-level key = value lines with strings, numbers and booleans are supported. Write Windows paths in single quotes, or double the backslashes inside double quotes, since "C:\nvim" would turn \n into a line break. Problems such as unknown options or invalid values are listed in a message box at startup, and the remaining options still apply.
Set g:ndx_fullscreen to true or false to enter or leave fullscreen; with --fullscreen it starts out true. Set g:ndx_borderless to true to hide the title bar, and back to false to show it again. The text stays where it is and the window keeps its shadow, rounded corners, snapping and resizing from its edges. Both can be changed while Ndx is running. Ndx has no shortcuts for them, Alt+Enter is passed to Neovim as <M-CR>. Bind keys to toggle them, for example:
if vim.g.ndx then
vim.keymap.set({ "n", "i", "v", "t" }, "<F11>", function() vim.g.ndx_fullscreen = not vim.g.ndx_fullscreen end)
vim.keymap.set({ "n", "i", "v", "t" }, "<M-CR>", function() vim.g.ndx_borderless = not vim.g.ndx_borderless end)
endWithout a title bar, move the window with Win+arrow keys or Alt+Space, then Move.
Set g:ndx_background_opacity to a value between 0 and 1 to make the background transparent. It applies to the Normal background, and to highlights using the same color, such as floating windows of many colorschemes; other backgrounds, the text and the cursor stay opaque. Set g:ndx_backdrop to choose what shows through:
| Value | Backdrop |
|---|---|
"none" (default) |
Nothing, the windows and the desktop behind Ndx |
"mica" |
Mica, tinted by the desktop wallpaper |
"mica_alt" |
Mica Alt, a stronger tint |
"acrylic" |
Acrylic, a frosted glass blurring the windows behind Ndx |
if vim.g.ndx then
vim.g.ndx_backdrop = "acrylic"
vim.g.ndx_background_opacity = 0.6
endBoth can be changed while Ndx is running. The backdrops need Windows 11 22H2 or later and are replaced by a plain color by Windows while the window isn't focused. With a backdrop but an opacity of 1, only the title bar shows it. While the background is transparent, text is drawn with grayscale antialiasing instead of ClearType, which needs an opaque background.
Colorschemes with a transparent background option, such as catppuccin's transparent_background or tokyonight's transparent, work too. They clear the background of Normal and usually of floats and sidebars, which Neovim then reports to GUIs as black, or white with background=light. Ndx draws that color with g:ndx_background_opacity like any other Normal background, so with an opacity of 0 the whole editor shows the backdrop unchanged, and higher values darken it. A Mica setup with catppuccin:
-- options.lua
vim.g.ndx_backdrop = "mica"
vim.g.ndx_background_opacity = 0.0
-- the catppuccin plugin spec
opts = { transparent_background = true }Animations are off by default. Enable them in your Neovim Lua configuration:
vim.g.ndx_cursor_animation = true
vim.g.ndx_cursor_vfx_mode = "railgun" -- or a list, e.g. { "railgun", "sonicboom" }
vim.g.ndx_scroll_animation = true
vim.g.ndx_neon_text = true -- glow around text; disabled by default
vim.g.ndx_neon_radius = 7.0 -- glow radius in pixels (0.5–40)
vim.g.ndx_neon_intensity = 0.2 -- glow strength (0–2)Ndx supports cursor movement animation, cursor particle effects, smooth cursor blinking, and smooth scrolling. The settings use the corresponding Neovide names with an ndx_ prefix. For example, g:ndx_cursor_animation_length controls cursor movement duration and g:ndx_scroll_animation_length controls scroll duration. Unset settings use their defaults. Smooth scrolling follows Neovim window scroll events; moving floating windows are not animated.
Set g:ndx_cursor_trail_in_insert_mode to false to keep only a plain smooth cursor glide while typing, like the smooth caret in Word: in insert mode the cursor moves without stretching into a trail and no particle effects are shown. Normal mode keeps the full animation. It is true by default. Typing moves of up to two characters use g:ndx_cursor_short_animation_length (default 0.04); raise it, for example to 0.08, for a more visible glide.
g:ndx_cursor_normal_mode_animation_length sets the cursor movement duration, in seconds, outside of insert mode (normal, visual and so on), for example vim.g.ndx_cursor_normal_mode_animation_length = 0.3. It also applies to short moves of up to two characters such as h and l, which then no longer use g:ndx_cursor_short_animation_length. When unset (or set to a negative value or nil), g:ndx_cursor_animation_length is used. It can be changed at runtime.
Set g:ndx_neon_text to true or false to toggle the text glow while Ndx is running. It is off by default. Like the glow in GriddyCode, each piece of text gets a soft aura in its own color, added to the background in linear light. The text itself stays sharp and keeps its colors.
g:ndx_neon_radius is the blur radius of the aura in pixels (default 7.0); small values smear the glyphs, large ones pool into blobs of color. g:ndx_neon_intensity controls brightness (default 0.2, with 0 removing the glow). Both can be changed while Ndx is running; out-of-range values are clamped.
Ndx retains the original project's MIT license and copyright notice; see LICENSE. The upstream project that this codebase builds on is Nvy by Rasmus Ishøy Michelsen.
Ndx-specific development began at commit 3ffe894, “Replace IMM32 IME handling with TSF”, whose parent is 367190e. The project was renamed to Ndx in the following commit, 7f5a7d6, “Rename to Ndx, support guifont font lists, fix startup with file arguments.”
Original project reference: RMichelsen/Nvy.