A modern, modal text editor built in Rust. Red combines Vim-inspired editing with modern features - Language Server Protocol support, tree-sitter syntax highlighting, and a sandboxed JavaScript/TypeScript plugin system - in a single self-contained binary that works with zero setup.

This editor is being actively built on a series of streams and videos published to my CoderSauce YouTube channel here:
https://youtube.com/@CoderSauce
It is my intention to keep it stable starting at the first alpha release, but there are no guarantees. As such, use it at your discretion. Bad things can happen to your files, so don't use it yet for anything critical.
If you want to collaborate or discuss red's features, usage or anything, join our Discord:
https://discord.gg/5PWvAUNRHU
brew install codersauce/tap/red
Download the archive for your platform from the latest GitHub release, extract red or red.exe, and place it somewhere on your PATH.
git clone https://github.com/codersauce/red.git
cd red
cargo install --path .
That's it. No configuration step is needed - the default config, themes, and plugins are bundled into the binary.
Once installed, you can start editing files immediately:
red <file-to-edit>
On the first interactive run, Red offers to create a starter config at ~/.config/red/config.toml. You can decline (or run non-interactively) and Red launches with its embedded defaults - a config file is entirely optional.
Red uses Vim-style modal editing. Everything below is the default; all of it can be remapped (see Configuration).
h/j/k/l or arrow keys - Move left/down/up/rightw/b - Move forward/backward by word0/$ - Move to beginning/end of linegg/G - Go to first/last lineCtrl-b/Ctrl-f - Page up/downzz - Center the current line in the view% - Jump to the matching bracket (g% backward, [%/]% for unmatched brackets)Ctrl-o/Tab - Jump back/forward through the jump listgj/gk - Move by screen line when long lines wrapi/a - Insert before/after the cursor (I/A for start/end of line)o/O - Open a new line below/abovex - Delete character; dd - delete line; dw - delete wordu / Ctrl-r - Undo/redop/P - Paste after/before>> / << - Indent/unindent the current lineEsc - Back to Normal modev - Visual mode (character-wise)V - Visual Line modeCtrl-v - Visual Block mode (rectangular selections; I inserts on every selected line)i/a select inside/around a text object: iw for a word, i(, i[, i{, i<, i", i', or i` for delimited text, and a% for a matchit pairy copies, x deletes, p pastes over it/ and ? - Forward/backward search with live preview and highlighted matchesn/N - Repeat search in the same/opposite direction* - Search for the word under the cursor:noh - Clear search highlightsSearch patterns use Rust regex syntax. Behavior (incsearch, hlsearch, wrapscan, ignorecase, smartcase) is configurable. The bundled cool_search plugin clears highlights automatically once you move away from a committed match or enter Insert mode.
K - Hover documentationgd - Go to definitionCtrl-Space - Trigger completion (in Insert mode; completion also triggers as you type)Ctrl-t - Document symbols pickerSpace w - Workspace symbols pickerSpace k - Find referencesDiagnostics from the language server are displayed inline, and LSP progress is shown by the bundled fidget plugin.
Ctrl-p - File pickerCtrl-e - File tree (neotree)Ctrl-j or Space b - Buffer pickerSpace g - Project-wide search (requires rg on your PATH)Space t - Theme browser with live previewCtrl-w s / Ctrl-w v - Split horizontally/verticallyCtrl-w h/j/k/l - Move between windowsCtrl-w w - Next window; Ctrl-w c - close windowCtrl-w = / Ctrl-w _ / Ctrl-w o - Balance/maximize/keep only the current windowSpace Space or Space n / Space p - Next/previous bufferEnter Command mode with : (or ;).
:w [file] - Save (optionally to a new name); :wq - save and quit:q / :q! - Quit / quit discarding changes:e <file> - Open a file; :e! - reload the current file:<number> / :$ - Jump to a line / the last line:bn / :bd - Next/delete buffer (Space p goes to the previous buffer):sp [file] / :vs [file] - Split horizontally/vertically:close / :only - Close the current window / keep only the current window:noh - Clear search highlights:wrap / :nowrap - Enable/disable line wrappingRed works out of the box with sensible embedded defaults. To customize it, use a TOML configuration file at ~/.config/red/config.toml.
Your config is layered on top of the embedded defaults: you only need to write the settings you want to change, and everything else keeps its default value. The starter config that Red offers to create on first run is a commented template to get you going - it is not the source of truth for defaults, so deleting it (or any setting in it) simply falls back to the built-in behavior.
# ~/.config/red/config.toml — only what you want to change
theme = "atom-one-dark.json"
scrolloff = 8
[search]
ignorecase = true
smartcase = true
# Remap or add keybindings; everything not listed keeps its default
[keys.normal]
"Ctrl-s" = "Save"
For the full set of options - cursor shapes per mode, wrapping and scrolling behavior, plugin settings, logging, and more - see the commented default_config.toml, which documents every default exactly as the binary ships it.
Every mode has its own table ([keys.normal], [keys.insert], [keys.visual], …). Bindings map a key to an editor action, a sequence of actions, a nested table for chords, or a plugin command:
[keys.normal]
"u" = "Undo" # single action
"a" = [ { EnterMode = "Insert" }, "MoveRight" ] # sequence
"g" = { "d" = "GoToDefinition" } # chord: g then d
"Ctrl-j" = { PluginCommand = "BufferPicker" } # plugin command
Built-in LSP defaults cover Rust (rust-analyzer), TypeScript/JavaScript (typescript-language-server), Python (pyright), Markdown (marksman), JSON, TOML, and YAML. Servers start only when a matching file is opened, and each one must be installed and on your PATH. Add or override servers in your config:
[lsp.servers.go]
command = "gopls"
language_id = "go"
file_extensions = ["go"]
root_markers = ["go.mod", ".git"]
Bundled plugins are enabled by default. Disable any of them by name, and configure the ones that take options:
disabled_plugins = ["barbecue"]
[plugin_config.lsp_symbols.icons]
enabled = false
Plugins that spawn external processes need an explicit allowlist, e.g. project_search ships with [plugin_permissions.project_search] process = ["rg"].
red [files...] # open one or more files
red -r <path> # set the working directory root
red -c 'wrap = false' # inline TOML config override (repeatable)
red --version # print the installed version
red --runtime-files # list visible plugins/themes and their sources
red --eject <asset> # copy a bundled plugin/theme into your config dir
Red ships with a collection of VSCode-compatible themes bundled into the binary - they work without any files on disk. Reference a theme in your config:
theme = "your_theme_name.json" # the theme's filename
To add your own theme, place a .json theme file in ~/.config/red/themes/. Run red --runtime-files to see every theme Red can currently load, or browse them interactively with Space t.
Red's default plugins and themes are embedded in the binary, so a fresh install has everything it needs and upgrades automatically pick up newer bundled versions. Nothing is copied to your config directory unless you ask for it.
The bundled plugins:
| Plugin ID | File | What it does |
|---|---|---|
barbecue |
barbecue.js |
Breadcrumb bar showing your current location in the code |
buffer_picker |
buffer_picker.js |
Quick switcher for open buffers |
cool_search |
cool_search.js |
Clears search highlights automatically when you move on |
fidget |
fidget.js |
LSP progress indicator |
indent_guides |
indent_guides.js |
Vertical indentation guides |
inlay_hints |
inlay_hints.js |
Inline LSP type and parameter hints |
lsp_symbols |
lsp_symbols.ts |
Document and workspace symbol pickers |
neotree |
neotree.js |
File tree with git status and file icons |
project_search |
project_search.js |
Project-wide text search powered by ripgrep |
session_restore |
session_restore.js |
Reopens your files and layout from the last session |
theme_browser |
theme_browser.js |
Theme picker with live preview |
To turn one off, add its plugin ID to disabled_plugins in your config, e.g. disabled_plugins = ["fidget"].
red --runtime-files
This lists every plugin and theme Red can see and where each one comes from (your config directory, $RED_RUNTIME, or the embedded assets). When the same filename exists in more than one place, the listing shows which source wins.
Files in your config directory take precedence over bundled ones with the same filename. For example, ~/.config/red/plugins/fidget.js replaces the bundled fidget.js.
To start from the bundled version, eject a copy into your config directory:
red --eject plugins/fidget.js # copy a bundled plugin for editing
red --eject themes/mocha.json # copy a bundled theme for editing
red --eject fidget.js # the plugins/ or themes/ prefix is optional
Eject refuses to overwrite an existing file; use red --eject-force <asset> to replace your copy with the bundled version.
Keep in mind that an ejected file shadows the bundled one permanently - if a later Red release improves that plugin or theme, your copy still wins. Delete the file from your config directory to go back to the bundled version.
$RED_RUNTIMEPackagers and developers working from a source checkout can point $RED_RUNTIME at a directory containing plugins/ and themes/ subdirectories. Assets are resolved in this order:
~/.config/red/plugins/foo.js)$RED_RUNTIME/plugins/foo.js or $RED_RUNTIME/themes/foo.jsonNormal users don't need to set this - the embedded assets cover everyday use.
Plugins are JavaScript or TypeScript files running in a sandboxed Deno runtime. A plugin exports an activate function and gets a typed red API object:
export async function activate(red) {
red.addCommand("HelloWorld", async () => {
const { x, y } = await red.getCursorPosition();
red.insertText(x, y, "Hello from a plugin!");
});
}
Commands registered this way can be bound to keys with { PluginCommand = "HelloWorld" }.
The API covers buffer access, cursor control, pickers and dialogs, per-window bars, virtual text decorations, eve