mdedit: A Terminal Markdown Editor That Actually Shows You the Rendered Output

I write a lot of markdown. READMEs, documentation, notes, blog posts. It's everywhere. And every tool I've used to edit it has the same problem: it either can't show me the rendered output, or it needs a browser to do it.

Vim and nano are fast but you're staring at raw markup. VS Code works but you're launching an entire IDE for a README. Obsidian is nice but it locks your files in a vault and isn't available over SSH. So I built mdedit, a terminal markdown editor with live rendered preview, side by side, in a single binary.

mdedit demo
mdedit demo

Why Another Markdown Editor

The pitch is simple: edit on the left, see the rendered result on the right, never leave the terminal.

I wanted something that felt like vim (because that's what my hands know) but showed me what the markdown would actually look like. Not the raw asterisks and brackets. The bold text, the headers, the formatted code blocks. And it had to work over SSH, because half the time I'm editing files on a remote box.

Nothing I found hit all three: terminal-native, live preview, vim keybindings. So I wrote one in Rust.

What It Does

You open a file and get a split view. Left side is your editor with syntax highlighting and line numbers. Right side renders the markdown in real time as you type. Headers get sized, lists get bullets, code blocks get formatted, links get colored.

mdedit README.md

That's it. The binary is 2.8MB, starts in under 50ms, and has zero runtime dependencies. No Node, no Python, no config files required.

Vim mode is the default. Normal, insert, visual, command mode all work the way you'd expect. hjkl to move, dd to delete a line, yy to yank, / to search, :w to save. If you prefer something simpler, there's a nano mode with Ctrl+S to save and Ctrl+Q to quit.

Ctrl+P cycles through three layouts: split view, editor only, and preview only. You can drag the divider with your mouse to resize the panes.

layout modes
layout modes

The Stack

I built this with ratatui for the TUI framework, pulldown-cmark for markdown parsing, and syntect for syntax highlighting. The text editor widget is tui-textarea which gives you undo/redo, line numbers, and selection out of the box.

The markdown rendering was the interesting part. I started with tui-markdown but ended up building a custom renderer to get the preview looking right. Proper heading sizes, nested lists, code block styling with the active theme colors, and horizontal rules.

The preview updates are debounced at 80ms so it doesn't re-render on every keystroke, and the preview scroll follows your cursor position so you're always looking at the part of the document you're editing.

Clipboard Over SSH

This was a surprisingly tricky problem. On a local terminal, clipboard is easy. Just shell out to pbcopy on macOS or xclip on Linux. But over SSH, those commands run on the remote machine, not your local one.

The solution is OSC 52, a terminal escape sequence that tells your terminal emulator to put text on the local clipboard. Most modern terminals support it (iTerm2, Alacritty, Kitty, Windows Terminal). mdedit detects whether you're in an SSH session and automatically uses OSC 52 when you are, with DCS passthrough wrapping when you're inside tmux.

Every yank and delete syncs to the system clipboard. Paste reads from it. You don't configure anything.

Live Settings

Type :set in normal mode and you get an interactive settings panel. Arrow keys to navigate, left/right to cycle through themes, Enter to apply. The four built-in themes (ocean, dracula, solarized-light, and gruvbox-dark) preview live as you switch between them, so you can see exactly what you're getting before you commit.

settings panel
settings panel

Hit "Save to config" and it writes to ~/.config/mdedit/config.toml. Next time you open mdedit, your preferences are there. There's also a "Reset defaults" option if you want to go back to the ocean theme and vim mode.

Install

One line:

curl -fsSL https://raw.githubusercontent.com/sho-luv/mdedit/main/install.sh | sh

The install script detects your OS and architecture, downloads the right binary from GitHub Releases, and drops it in /usr/local/bin. Pre-built binaries are available for macOS (Intel and Apple Silicon) and Linux x86_64.

If you have Rust installed, you can also build from source:

cargo install --git https://github.com/sho-luv/mdedit.git

The source is at github.com/sho-luv/mdedit. It's a single Rust crate with no async runtime and no C dependencies.