▎CMeDit

The terminal editor you already know how to use.

Drop-down menus, full mouse support, and the shortcuts your fingers already know — drawn in character cells, over SSH if you like. No modes, no new muscle memory. Ctrl+S saves, Ctrl+F finds, Ctrl+Q quits. That's the whole tutorial.

Free & open source (GPL-3.0) · one binary, zero runtime dependencies · Linux, macOS & Windows

Fig. 1 — Menus, mouse, a resizable file explorer, clickable status bar. Everything visible, everything discoverable; you will never look up how to exit. Shown in the dark theme, which inherits your terminal's own background — five more ship built in, worn by the figures below.

Why CMeDit

A desktop editor's manners. A terminal's metabolism.

Nothing to memorise. Modeless, like every desktop app you've ever used: Shift+arrows select, double-click picks a word, Ctrl+C and Ctrl+V talk to your system clipboard — across SSH too.

A real interface. Fuzzy file open (Ctrl+P), a command palette, go-to-definition (F12), project-wide find & replace staged for review, and live lint squigglies from the tools already on the machine — ruff, eslint, shellcheck — with no language server to install.

Instant, everywhere. One self-contained binary that starts in milliseconds and runs identically on your laptop, a container, or a server on the far side of an ocean.

The part nobody believes

A working spreadsheet. Actual photographs.

CMeDit looks at a file's bytes before it decodes them, so a file opens as what it is — on a machine you reached by SSH, over a link you can't paste through. CSVs open as a real, editable grid. Pictures open as pictures, in 24-bit colour. PDFs reflow as readable documents, archives list without unpacking, and a 281 MB log opens paged at 32 MB resident.

cmedit exports/orders.csv
A B C D 1 order_id region amount status 2 10412 eu-west 8,940.00 shipped 3 10387 us-east 4,102.50 pending 4 10305 ap-south 1,988.75 shipped 5 10510 eu-west 412.00 refunded
orders.csv · tableCell C2 · sorted ↓ C
Alt+S Sort  Alt+T Text view  ^S Save
Fig. 2 — A .csv is a grid: frozen header, numeric-aware sort, draggable columns. 300,000 rows edit at full speed; saving writes proper RFC 4180. In the flashbang theme — pure white on any terminal.
cmedit uploads/starry-night.jpg
starry-night.jpgJPEG 1280×1014 · colour
a ASCII  drag Zoom  Esc Fit
Fig. 3 — Two pixels per cell in 24-bit colour on any terminal; real pixel resolution on kitty or sixel. Every decoder written from first principles — nothing to install. In the midnight theme's deep navy.
cmedit ~/docs/spec.pdf
────────────────────────────────────────── 4. Objects An object is an unordered collection of zero or more name/value pairs, where a name is a string and a value is a string, number, boolean, null, object, or array. object = begin-object [ member *( sep member ) ] end-object
spec.pdf  [2/3]Page 3 of 16 · PDF
[ Prev  ] Next  ^G Go to page
Fig. 4 — A PDF is glyphs at coordinates; CMeDit puts the document back together — columns, paragraphs, bold and italic — and reflows it to your window. Encrypted files say so rather than pretending. In the graphite theme.
cmedit dist/release.zip
Name Size Saved Modified ▾ release/ bin/cmedit 9.4 MB 62% 07-30 14:02 man/cmedit.1 18 KB 71% 07-30 14:02 README.md 11 KB 64% 07-28 09:41 LICENSE 34 KB 77% 06-02 17:19
release.zip · archive4 entries
Enter Open entry  ^W Close
Fig. 5 — .zip, .jar, .docx and .epub list as a sorted tree read from the archive's own table of contents. A 10 GB archive costs the same two short reads as a 10 KB one. In the cherry-blossom theme.

These views are projections, never serialised back: a format the reader doesn't fully model can never be written over your file. What you edit is always the thing you opened — and anything too big to edit opens in a paged viewer whose memory doesn't depend on the file's size.

Real-time diagnostics, no language server

Linting that already knew how to run.

CMeDit auto-detects the linters already on the machine — ruff, flake8, eslint, stylelint, shellcheck, pyright — and re-lints about half a second after you stop typing. Your unsaved buffer streams to the tool over stdin, so the squigglies reflect what's on screen; your pyproject.toml or eslint config applies because the tool runs from your workspace root. No LSP install, no extension marketplace, no per-host server process.

you@prod: cmedit ~/api/src/parse.py
21from pathlib import Path
22import json
23
24def parse_events(rows):
25 out = []
26 for r in rows:
27 try:
28 out.append(r["ts"])
29 except:
30 continue
31 return out
● parse.py  1E 1WLn 29, Col 9  INS  UTF-8  LF
E722 [ruff] do not use bare except
Fig. 6 — Nothing was configured: ruff was on $PATH, CMeDit noticed, ran it on the buffer, and drew the underlines. Rest the cursor on a marker and the message shows in the hint bar — no tooltip clobbers the code you're reading. Works over SSH the same way, because there's nothing to install on either end. In the light theme, which follows your terminal's background — auto switches between light and dark when your system does.

The remote-work superpower

Do work over SSH that terminals aren't supposed to be able to do.

An SSH session is the fastest way to be on a machine, and usually the most limiting. CMeDit closes the gap: the workflows that normally force you to scp files home, mount remote drives, or install a remote IDE server just… work, in the terminal you already have open.

$ ssh you@prod $ cmedit exports/orders.csv # a spreadsheet, in your terminal $ cmedit build/flamegraph.png # yes, this works too $ cmedit docs/contract.pdf # and this $ cmedit /var/log/app.log # 281 MB? paged, 32 MB resident

Nothing to install on the remote end. One static-friendly binary; no plugin marketplace, no per-host server process, no version skew.

Clipboard that crosses the wire. Copy in CMeDit on the server, paste on your laptop, via the OSC 52 escape.

Frugal with your bandwidth. The renderer diffs frames and uses hardware scroll regions, so a one-line scroll costs a few bytes — high-latency links feel dramatically better. Kick off a long search and CMeDit pings you with a desktop notification when it's done, even from the far end of a session.

Engineering, not vibes

Fast because every byte is on purpose.

No UI framework sits between CMeDit and the terminal, so it controls exactly what gets drawn, when, and how it travels — which is why high-latency SSH links feel local.

RenderingRepaints only the cells that changed, one write per frame, tear-free. A one-line scroll costs a few bytes.
Big filesMulti-megabyte files open instantly; a 281 MB, four-million-line log sits at ~32 MB resident.
SearchThe regex engine is linear-time by construction — (a+)+b cannot hang a project-wide search.
Long sessionsHistories are bounded and memory is flat: open a 32 MB CSV, close it, and you're back where you started.
Plain terminalsCapabilities are probed at startup and upgrades are opt-in by evidence. A dumb terminal gets a plain, correct stream.

Get it

Clone, make, edit.

$ git clone https://github.com/appmakernetwork/cmedit $ cd cmedit && make # needs GHC 9.0+, nothing else $ ./cmedit . # open the current folder as a workspace

Builds offline; the only dependencies ship with the compiler. The result is a single binary you can drop onto any machine, including the ones you SSH into. CMeDit is written in Haskell, a language with a storied tradition of producing white papers instead of products — out of respect for that tradition, this release ships with both.