A small sized(<1MB), hackable terminal editor written in C.
Modal by default, but ships Emacs and VSCode keymaps you can swap to at runtime. Tree-sitter highlights, ripgrep / fzf integrations, window splits, tmux runner pane, OSC 52 clipboard, LSP. Every user-facing feature is a plugin you can rip out, fork, or replace.
One line install:
curl -fsSL https://github.com/42dotmk/hed/releases/latest/download/install.sh | bashand follow the prompts.
The installer asks two things:
-
Source or binary? Binary is faster (one download, ready to run). Source clones the repo into
~/.local/share/hed, builds it, and symlinkshedandtsiinto~/.local/bin— pick this if you want to hack on plugins (or the core editor itself). -
Optional tools? Offers to download portable static
fzfandripgrepbinaries into the same~/.local/bin, then lets you pick tree-sitter grammars to install for syntax highlighting.
No sudo. No package manager. Everything ends up under
~/.local/.
After install, make sure ~/.local/bin is on your PATH:
export PATH="$HOME/.local/bin:$PATH"and
Then run hed and you're in.
If you want to skip the installer:
git clone --recursive https://github.com/42dotmk/hed.git
cd hed
makeThe Makefile will:
- Compile the binary and place it in
build/hed - Download portable
fzfandripgrepintobuild/bin - If you have
cargoandnode, it'll install plugins inplugins/that need it (copilot-language-serverfor:copilot login, etc.) - Symlink
build/hedinto~/.local/bin(for convenience)
Every user-facing feature is a plugin in plugins/<name>/.
| Plugin | What it does |
|---|---|
aishell |
Toggle a tmux pane running your AI assistant (Claude, Copilot, etc.) — configurable spawn command |
auto_pair |
Auto-insert matching brackets and quotes |
autosave |
Idle/timer autosave to per-cwd cache dir, with recovery prompt on reopen |
clipboard |
OSC 52 yank to system clipboard (works over SSH) |
core |
Default : command set (:q, :w, :e, :bn, :fzf, :rg, …) |
copilot |
GitHub Copilot ghost-text suggestions via copilot-language-server, with a [copilot] alternatives pane |
ctags |
Ctags integration for symbol navigation |
dired |
oil.nvim-style directory browser |
emacs_keybinds |
Modeless Emacs keymap (C-a/C-e, M-x, C-x cluster) |
example |
Starter template — copy and rename for your own |
fmt |
:fmt runs an external formatter on the buffer |
git |
Git integration |
hed_themes |
Theme management |
keymap |
:keymap and :keymap-toggle for runtime swap |
lsp |
LSP client (work in progress) |
mail |
Mail integration |
mail_git_patch |
Git patch mail integration |
man |
Manual pages viewer |
markdown |
Markdown rendering support |
multicursor |
Extra cursors that mirror every keypress (:mc_add_below, :mc_add_above) |
open |
File opening utilities |
pickers |
Fuzzy pickers |
quickfix_preview |
Live preview of the quickfix entry under the cursor |
reload |
:reload rebuilds and execs the new binary |
scratch |
:scratch ephemeral unnamed buffer |
sed |
:sed <expr> pipes the buffer through external sed |
selectlist |
Selection list functionality |
session |
Save / restore the open-buffer list per cwd |
shell |
:shell / ! prompt; capture tokens splice stdout into the buffer or yank register |
smart_indent |
Carry indent onto new lines |
tags |
Tags integration |
tmux |
Runner pane integration |
translate |
Translation support |
treesitter |
Syntax highlighting; grammars via dlopen |
viewmd |
Markdown live preview in the browser |
vim_keybinds |
Default modal Vim keymap |
vscode_keybinds |
Modeless VSCode keymap (Ctrl+S, shift-arrow selection) |
whichkey |
While a multi-key chord is in progress, list the candidate completions in a 1–4 column table |
yazi |
Launch the yazi file manager as a chooser; selected paths open as buffers |
cp -r plugins/example plugins/myplugin- Rename
example→mypluginin the source files - Add
plugin_load(&plugin_myplugin, 1)tosrc/config.c - Build with
make
See plugins/example/README.md for the
full recipe and the plugin contract.
Keep your plugin set anywhere on disk and point the build at it:
make PLUGINS_DIR=$HOME/my-hed-pluginshedA new buffer comes up.
:eto open files:qto quit:wto save
Try :fzf to explore the project.
-
Modal editing (Vim-style) by default, but also ships Emacs and VSCode keymaps you can swap to at runtime (use
:keymapto switch) -
Tree-sitter syntax highlighting (with grammar via
dlopen) -
Fzf integration for fuzzy file and command search
-
Tmux runner pane (to test snippets, open REPLs, etc.)
-
OSC 52 clipboard (to yank to system clipboard, works over SSH)
-
LSP integration (work in progress)
-
Split windows, reloads, sessions
-
Git, mail, AI shell, file manager (Yazi)
-
Auto-save, auto-recover, backup, undo/redo
Hed is for you if:
- You like to read documentation, not just code
- You want a single binary with no dependencies (except Tmux)
- You like to hack on your editor, not just use it
- You are a plugin developer or plugin consumer
- You want to reinvent the editor or tune your own
The editor was built for one thing: to be a framework and a template, not a feature-rich text editor.
plugins/ # all user-facing functionality (see catalogue above)
main.c— Entry pointeditor.c— Core editor logicconfig.c— Initializer, pluginskeybinds.c— Key mappingscommands.c— Command handlingbuffer.c— Buffer operationshooks.c— Event systemterminal.c— ANSI renderering, Tmuxutils/— Various helpers (search, fzf, etc.)
plugins/
├── aishell/ # AI shell (like Claude, Copilot)
├── auto_pair/ # Auto-insert matching brackets and quotes
├── autosave/ # Idle/timer autosave
├── clipboard/ # OSC 52 yank to system clipboard
├── core/ # Default `:` commands
├── copilot/ # GitHub Copilot
├── ctags/ # Ctags integration
├── dired/ # oil.nvim-style directory browser
├── emacs_keybinds/ # Emacs keymap
├── example/ # Plugin template
├── fmt/ # External formatter
├── git/ # Git integration
├── hed_themes/ # Theme management
├── keymap/ # Runtime keymap swap
├── lsp/ # LSP client (experimental)
├── mail/ # Mail integration
├── mail_git_patch/ # Git patch mail
├── man/ # Manual page viewer
├── markdown/ # Markdown rendering
├── multicursor/ # Extra cursors
├── open/ # File opening utilities
├── pickers/ # Fuzzy pickers
├── quickfix_preview/ # Quickfix preview
├── reload/ # Reload binary
├── scratch/ # Scratch buffer
├── sed/ # External sed
├── selectlist/ # Selection list
├── session/ # Session management
├── shell/ # Shell integration
├── smart_indent/ # Carry indent onto new lines
├── tags/ # Tags integration
├── tmux/ # Tmux runner pane
├── translate/ # Translation support
├── treesitter/ # Tree-sitter syntax highlighting
├── viewmd/ # Markdown preview
├── vim_keybinds/ # Vim keymap
├── vscode_keybinds/ # VSCode keymap
├── whichkey/ # Which-key tooltip
└── yazi/ # Yazi file manager
To customize, edit src/config.c:
void config_init() {
plugin_load(&plugin_core, 1);
plugin_load(&plugin_vim_keybinds, 1);
plugin_load(&plugin_emacs_keybinds, 0); // registered, swappable
plugin_load(&plugin_vscode_keybinds, 0);
plugin_load(&plugin_treesitter, 1);
plugin_load(&plugin_clipboard, 1);
plugin_load(&plugin_dired, 1);
plugin_load(&plugin_tmux, 1);
plugin_load(&plugin_aishell, 1);
plugin_load(&plugin_copilot, 1);
plugin_load(&plugin_example, 0); // registered, swappable
// Add your own plugins here.
// plugin_load(&plugin_myplugin, 1);
// Personal overrides — last-write-wins, beats plugin defaults.
// cmapn(" ff", "fzf"); // override plugin keymap
// cmapn(" q", "quit"); // override plugin keymap
}All keybindings are user-overridable. Default is:
:keymapto switch between Vim, Emacs, VSCode:pluginsto list currently loaded plugins:reloadto rebuild and exec the new binary
Yes. The LSP client is in plugins/lsp/ and is not yet enabled by default.
In src/config.c, after plugin_load statements, use
cmapn(" key", "command") to override or map keys.
See the plugins/example/README.md to get
started.
heds— A simple, hackable terminal web browser to complementhedheds— A web browser for the terminal to complementhedhed-fzf— Fzf integration forhedhed-shell— Shell integration forhedhed-tmux— Tmux integration forhed
MIT