██████╗ ██╗███╗   ██╗██╗   ██╗██╗███╗   ███╗
██╔══██╗██║████╗  ██║██║   ██║██║████╗ ████║
██████╔╝██║██╔██╗ ██║██║   ██║██║██╔████╔██║
██╔══██╗██║██║╚██╗██║╚██╗ ██╔╝██║██║╚██╔╝██║
██████╔╝██║██║ ╚████║ ╚████╔╝ ██║██║ ╚═╝ ██║
╚═════╝ ╚═╝╚═╝  ╚═══╝  ╚═══╝  ╚═╝╚═╝     ╚═╝

vim grammar.
batteries included.

A modal TUI editor in Rust with tree-sitter, LSP, and fuzzy pickers baked into a single binary. No plugin manager. No 400-line init.lua. No 18-month-old GitHub issue blocking your formatter. You install binvim, you edit text. That's it.

$ brew install binvim
v0.1 · ready lang rust deps tree-sitter, tokio, ratatui platforms linux · macos · *bsd license MIT
+-- § WHY · vs neovim 37 lines

Neovim is excellent. But every install begins with a ~/.config/nvim archeology dig: Lua versus Vimscript, lazy.nvim vs packer vs paq, mason for LSPs, conform for formatters, nvim-cmp for completion, treesitter parsers that quietly desync from the Neovim version you upgraded last Tuesday. binvim ships the answers.

// the current situation

  • Pick a plugin manager. Pick a config language. Pick a colourscheme bootstrap.
    Then maintain three different ecosystems forever.
  • :Mason, :LspInstall, :TSInstall, :checkhealth — four different install surfaces.
  • Treesitter parsers compile against the runtime. Upgrade Neovim → re-install everything.
  • Completion stack: nvim-cmp · cmp-nvim-lsp · cmp-buffer · cmp-path · LuaSnip · friendly-snippets…
    Six plugins to autocomplete a variable name.
  • Telescope works great. After 14 dependencies and a Rust toolchain for the sorter.
  • Format on save? Pick: null-ls (deprecated) → none-ls → conform.nvim → guard.nvim → …

// binvim

  • One binary.
    Nothing to bootstrap. No package manager-of-the-month.
  • :health tells you what's attached and what isn't.
    That's the whole diagnostic surface.
  • Tree-sitter grammars are compiled into the binary. Upgrade binvim, parsers ship with it.
  • Completion is a feature, not a stack. LSP + buffer-words, on by default.
  • Fuzzy file / buffer / grep pickers on <space>. Built in.
  • Format on save via biome & .editorconfig. :fmt if you'd rather drive it.

// caveat: binvim is opinionated. It does not have a plugin API. If you want a 200-plugin fortress, stay on Neovim — it is the better tool for that job. binvim is for the developer who opened their config file last week and felt tired.

+-- § FEATURES 5 cards · folded
01 / EDITING

Modal editing, faithfully

Normal · insert · visual (charwise, linewise, blockwise). Operators, text objects, marks, registers, dot-repeat, undo tree, macros. The grammar you already speak.

w b eiw a"ciw@q
02 / SYNTAX

Tree-sitter, compiled in

Rust, TS/TSX, JS, JSON, Go, HTML, CSS, Markdown, C#. Grammars baked into the binary — upgrade binvim and your parsers come with it.

rustts/tsxgohtmlcssmdc#
03 / LSP

Real LSP, multi-server

Diagnostics, hover, completion, goto-definition. Primary + auxiliary servers fan out per buffer — Tailwind layers on top of CSS / HTML / JSX / Vue / Svelte / Astro automatically.

rust-analyzertsservergoplstailwind
04 / PICKERS

Fuzzy everywhere

Files, buffers, live grep — all on the leader. No telescope-extension folder, no fzf shim, no node bridge. Just a fast fuzzy matcher and a list.

<space><space>b<space>g
05 / FORMAT

Format on save

Biome handles JS/TS/JSX/TSX/JSON/JSONC. .editorconfig directives applied on save (final newline, trailing whitespace). :fmt drives it manually.

biome.editorconfig:fmt
06 / VISIBILITY

Whitespace visible

Every space, tab, NBSP, and EOL surfaces as a muted glyph (·   ¬) in the overlay colour. You see what the file actually contains.

·¬
+-- § KEYS · leader + ex two tables
// leader bindings · <leader> = <space>
file picker — fuzzy across the project root
b
buffer switcher — everything currently open
g
live grep — ripgrep-grade, in-process
K
LSP hover under the cursor
gd
goto definition
^x
trigger completion (in insert mode)
// ex commands · type : in normal mode
:health
scratch buffer: version · CPU/RAM · attached LSPs · Tailwind detection
:fmt
run the configured formatter on the active buffer
:noh
clear search highlight
:e <path>
edit a file (relative or absolute)
:bd
close the current buffer
:s/pat/repl/g
substitute on the current line; %s/.../.../g for buffer
+-- § CONFIG · ~/.config/binvim/config.toml optional · 21 lines
» ~/.config/binvim/config.tomltoml · 21L · 538B# missing or malformed → defaults to baked-in Catppuccin Mocha
schema_version = 1

[colors]
# hex (#rrggbb) or a named crossterm colour. dotted suffixes
# match more specifically before falling back to the head.
keyword          = "#cba6f7"
"keyword.return" = "Magenta"
string           = "#a6e3a1"

[start_page]
lines = [
    "  hello, world  ",
    "  press : to start ",
]

[whitespace]
# space=· tab=→ nbsp=⎵ eol=¬   on by default
show = true
+-- § INSTALL · external tools all optional

binvim spawns these on demand. Each is optional — when a binary isn't on $PATH (or in a relevant node_modules/.bin/) the editor just skips that capability.

// tool
// purpose
// install
rust-analyzer
Rust LSP
$ rustup component add rust-analyzer
typescript-language-server
JS / TS / JSX / TSX LSP
$ npm i -g typescript-language-server typescript
gopls
Go LSP
$ go install golang.org/x/tools/gopls@latest
vscode-css-language-server
CSS / SCSS / Less LSP
$ npm i -g vscode-langservers-extracted
vscode-html-language-server
HTML LSP
$ npm i -g vscode-langservers-extracted
@tailwindcss/language-server
Tailwind class-name completion
$ npm i -g @tailwindcss/language-server
astro-ls
Astro LSP
$ npm i -g @astrojs/language-server
OmniSharp / rzls
C# / Razor LSP
$ via dotnet tooling
@biomejs/biome
JSON LSP + JS/TS/JSON formatter
$ npm i -D @biomejs/biome (project-local)

// resolution order: project-local node_modules/.bin/  →  $PATH. Global installs lose to project-local devDependencies, which is what you want.