Skip to content

Repository files navigation

CleeCode 🐢

An editor, a file tree and real terminals in one window. Written in Rust, driven from the keyboard, with the mouse as an alternative rather than the only way.

Best in a terminal that can draw pictures — Ghostty, kitty, WezTerm or iTerm2 — where pictures, PDFs and Markdown are shown as themselves rather than as coloured blocks. It works anywhere; those are where it looks like the screenshots.

By Matteo Savoia (msavox).

CleeCode in action

Installing

macOS and Linux — Homebrew

brew tap msavox/clee
brew trust msavox/clee
brew install clee

brew trust exists from Homebrew 6 onwards, and there it is required rather than a formality: a formula is Ruby code Homebrew executes locally, so it refuses to load one from a third-party tap until you trust the source — tapping alone doesn't grant that. Without it you get Refusing to load formula msavox/clee/clee from untrusted tap. On older Homebrew the command does not exist (Unknown command: brew trust) and is not needed: skip it and install.

If brew tap itself fails with git@github.com: Permission denied (publickey), that is not about this tap — a global git rule is rewriting HTTPS URLs to SSH and you have no key on that machine. git config --global --get-regexp 'url\..*\.insteadof' shows it.

The formula builds from source (well under a minute on macOS; longer on Linux, where it also pulls libxcb). Homebrew on Linux uses the same tap and CI verifies that install on Ubuntu, but only the install is tested.

Prebuilt binaries

macOS arm64/x86_64 and x86_64 Linux and Windows builds are attached to each release. Outside macOS they're experimental: CI checks they start, nothing more. The Linux binary needs glibc and libxcb — install libxcb1 (Debian/Ubuntu) or libxcb (Fedora/Arch) if it fails to start. For Alpine/musl, build from source.

Optional extras

Previews reach for a few outside tools. None is required — without them CleeCode shows less rather than failing, and says so in the tab instead of leaving it blank.

brew install poppler # PDF pages (ghostscript works too)
brew install pandoc typst # Markdown as a real document, pictures and all
brew install chafa # a picture inside a terminal pane

Without a graphics-capable terminal (see the top of this file), pictures fall back to coloured half-blocks and Markdown to styled terminal text — less to look at, nothing missing.

From source

Needs a Rust toolchain 1.85+ (edition 2024). On Linux the clipboard also needs the X11/xcb headers; on Windows, the MSVC toolchain plus Desktop development with C++.

# Debian/Ubuntu
sudo apt install build-essential pkg-config libxcb1-dev libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev
# Fedora
sudo dnf install gcc pkgconf-pkg-config libxcb-devel
# Arch
sudo pacman -S base-devel libxcb
cargo install --locked --git https://github.com/msavox/cleecode

That puts clee in ~/.cargo/bin (%USERPROFILE%\.cargo\bin), so make sure it's on your PATH.

From a clone

cargo build --release
./target/release/clee # the last project, its open files and your layout
./target/release/clee src/main.rs # current directory, with a file pre-opened
./target/release/clee ./some-dir # that directory as the project root
./target/release/clee -w work # open the saved workspace called "work"
./target/release/clee -w # list the saved workspaces
./target/release/clee -e notes.md # just that file, everything else hidden
./target/release/clee --help # usage, --version, --install-font

An argument skips the startup splash; the splash only shows on a bare clee or with -w, where it names the workspace being opened.

Nerd Font icons

The file tree's icons need a Nerd Font. CleeCode bundles JetBrainsMono Nerd Font Mono and can install it:

./target/release/clee --install-font

It copies the font into your per-user font directory (~/Library/Fonts, ~/.local/share/fonts, or %LOCALAPPDATA%\Microsoft\Windows\Fonts), points Ghostty at it if present on macOS/Linux, and registers it on Windows. Restart your terminal afterwards — or just point your terminal at a Nerd Font you already have.

What it does

CleeCode main view

The demo and most stills are replayed from docs/demo.tape and docs/shots.tape, so they are re-made after a UI change rather than left to go stale. The preview shots below are taken by hand: they need a terminal that can draw pictures, and the recorder has none.

Editing

syntect highlighting, line numbers, multi-file tabs, undo with coalescing, find and replace, go-to-line, code folding, auto-indent and auto-closing brackets. Selection works with the mouse or the keyboard, goes to the system clipboard, and can be rectangularAlt+drag for a column selection over ragged text.

Ctrl+L splits the editor into two independent editors sharing one pool of buffers: each half has its own tabs, no file is in both strips at once, and closing the last tab of a half closes the split rather than leaving it empty. Files changed underneath you are reloaded when they are not dirty, and a binary or non-UTF-8 file opens read-only rather than being corrupted on save. Scrollbars appear inside the frame while the view moves or the pointer rests on them, and they are working controls: drag the thumb, click the groove to jump, click the end arrows to step a line.

Pictures, PDFs and Markdown open as themselves. A .png gets a tab that draws it — real pixels on a terminal with a graphics protocol (kitty, iTerm2, sixel), coloured half-blocks elsewhere — instead of the blank read-only buffer a binary file used to give. A PDF opens as pages, turned with the plain arrow keys, and re-renders in place when the file changes: edit the .tex, press Run, and the page beside it is the one you just typeset.

Every preview carries a navigation bar along its bottom edge: the page arrows, go to jump to a page by number, - and + for zoom, and fit or wide to size the page to the pane or to its width. Each control is labelled with its own key, so the bar is also the reminder of how to work without the mouse — though the wheel zooms as well, and the scrollbars drag. Documents get one control pictures do not, dark, which inverts the page for reading at night: inverting a photograph is not a reading aid, it is just a wrong photograph. The setting is remembered between sessions.

A picture in a tab, and the same picture through chafa in a terminal

The same file twice: real pixels in the tab, and chafa putting it into a terminal pane with the Run button beside it.

Markdown gets a live preview beside the source — one file, two tabs, one copy of the text, so the two can never disagree about what it says. Where pandoc is installed it is a real document, pictures the text refers to included; elsewhere it falls back to styled terminal text. CleeCode draws all of it itself, so it works over ssh too.

A LaTeX source and its typeset PDF side by side

Edit the .tex, press Run, and the page beside it is the one you just typeset. On a preview tab the button says Refresh instead, because there the file is generated and can come out different.

Markdown source and its rendered document

Two tabs onto one file. The glyph in the strip tells them apart, and typing in the source moves the document beside it without a save.

For a one-off edit there is clee -e FILE: the editor and nothing else, leaving your saved layout and session untouched.

Split editor view

Terminals that are real

Each terminal window is a tiled pane holding one or more tabbed shells, on proper ptys — ssh, vim, claude all work. Panes can be renamed, given a startup command, resized by dragging the seam, and they collapse when their shell exits.

The keys respect that: a focused terminal keeps every Ctrl chord for the program running in it. Ctrl+J is Enter to a shell, Ctrl+E is end-of-line, and the editor does not steal either.

Each shell keeps its scrolled-off output. The wheel walks back through it, typing returns to the live end, and output arriving while you read back does not drag the page away. The same scrollbar the editor has shows where in the history you are.

▶ Run runs the current file in an idle terminal. The button beside it says what Run will use on this file and changes it: the venv selector on a .py file, and on any file type the run command for its extension — {file}, {dir}, {name} and {stem} to build it, so a .tex file can typeset and open its own PDF, and chafa will put a .png in a terminal pane beside its output. A command can be shared by every project or kept in the project's own .cleecode.toml, which wins and is meant to be committed with it. Interpreters off PATH go under [interpreter_paths].

Workspaces

Save a whole set-up under a name: project root, open files, frame sizes, and the terminal windows with their tab names and startup commands. Reopening one brings the shells back already running claude, octave, npm run dev. Open it from the Workspace menu or straight from the shell with clee -w NAME; the name it is running under sits in the corner of the menu bar.

Each is one hand-editable TOML file under ~/.config/cleecode/workspaces/, so they travel between machines. A built-in Default layout is always there and cannot be deleted or overwritten. A bare clee never reopens a named workspace — that stays a deliberate act — but it does restore the project, its open files and the layout you left.

Finding your way

Nothing needs to be memorised. Ctrl+P fuzzy-searches every action in the app and shows the key that would have done it; Ctrl+O does the same for files, and a query starting /, ~, ./ or ../ turns it into a filesystem browser.

Command palette

There is a full menu bar behind Ctrl+Shift+B, context menus on right-click, and a manual that travels with the binary — Ctrl+Shift+M, English or Italian, with diagrams.

Built-in manual

There is also a man clee.

The frame around it

A file tree with per-type Nerd Font icons and git status dots, live refresh, create/rename/delete and drag & drop (dropped onto a terminal inside an ssh session, files go up with scp). Three layout presets, a resizable everything, and a settings panel that applies changes live. English and Italian throughout, including the manual.

Layout and Run menus

It does not close on you

CleeCode hosts long-running shells, so a crash costing you an ssh session or a build would be the worst thing it could do. An internal failure is contained and reported in the status line rather than ending the process: a broken terminal costs you that terminal, at most. Details go to ~/.config/cleecode/panic.log.

Key bindings

KeyAction
Ctrl+Alt+←Go to the frame that lies in that direction — sidebar, either half of a split editor, or a tiled terminal, whichever is there. Ctrl+Alt rather than plain Ctrl because macOS keeps Ctrl+arrow for Mission Control and Spaces
Ctrl+Tab / Ctrl+Shift+TabOr cycle the frames, the way Cmd+Tab cycles windows
Ctrl+Shift+← / Previous / next tab inside the focused frame
Ctrl+Shift+↑ / Previous / next terminal window, whatever the layout
Ctrl+Shift+MThe built-in manual
Ctrl+Shift+BOpen the menu bar (then arrows and Enter)
Ctrl+Shift+OSettings
Ctrl+Shift+G / right-clickContext menu for the focused frame
Ctrl+Shift+RRun the current file
Ctrl+Shift+T / Ctrl+Shift+KNew terminal tab / close this shell
Ctrl+Shift+NNew terminal window
Ctrl+Shift+UResize mode (arrows grow the focused frame, Shift+arrow shrinks)
Ctrl+Shift+FFold/unfold the block under the cursor
Ctrl+LToggle split editor (Ctrl+Alt+←/ moves between the panes)
Ctrl+S / Ctrl+Shift+SSave / save all (an unnamed buffer asks for a name; Save As is in the File menu)
Ctrl+Shift+WSave the current workspace (open and delete are in the View menu)
Ctrl+Shift+EName the focused terminal and give it a startup command
Ctrl+E / Ctrl+JToggle sidebar / terminal panel
Ctrl+BShow/hide the menu bar
Ctrl+W / Ctrl+DClose current tab (prompts if unsaved)
Ctrl+QQuit (prompts if any file is unsaved)
Ctrl+C/X/V/ACopy / cut / paste / select all (in the editor)
Ctrl+Z / Ctrl+YUndo / redo (Ctrl+Shift+Z also redoes)
Alt+Left / Alt+RightMove by word (Ctrl+arrow too, where the OS allows it)
Ctrl+Backspace / Ctrl+DeleteDelete the word before / after the cursor
Ctrl+P / Ctrl+OCommand palette / quick open (both fuzzy)
Ctrl+F / Ctrl+GFind and replace / go to line
Ctrl+KToggle line comment
Alt+Up / Alt+DownMove the current line up / down
Alt+Shift+DownDuplicate the current line
Tab / Shift+TabIndent / outdent
Alt+dragColumn selection (also in the Edit menu, then Shift+arrows)

In the file tree: ↑↓ move, expand, collapse or jump to parent, Enter / double-click opens a file or reroots a folder (.. walks up), n / N create a file / folder, e renames, Delete removes with confirmation, H toggles hidden files.

There are deliberately no function keys and no PageUp/PageDown — on a laptop both need Fn — and no Alt+letter chords, because macOS only sends Option as Meta on US keyboard layouts, so on any other one they never arrived at all. Ctrl+Shift is the application's layer, and it is safe inside a terminal for a structural reason: no terminal can encode Ctrl+Shift for the program running in a pane, so nothing there is listening for it.

The same list, with more detail, is in the built-in manual (Ctrl+Shift+M) and in man clee.

Requirements

macOS is the supported platform — where CleeCode is developed, tested and released. Linux and Windows are written for throughout (paths, clipboard, shell, fonts, venvs) and compile in CI, where the binary is also started to confirm it links and launches. Beyond that nobody has used the editor there, so those builds are experimental and bug reports are welcome.

Built on ratatui/crossterm, with arboard for the clipboard, sysinfo for the process inspection behind Run and scp-on-drop, and dirs for config and font paths. Terminal panes launch $SHELL (falling back to /bin/bash) on Unix and %ComSpec% on Windows.

Status

Personal project, actively evolving.

License

MIT. The bundled font (assets/fonts/) is a Nerd Font-patched build of JetBrains Mono under the SIL Open Font License 1.1 and keeps its own terms.

About

CleeCode: a terminal IDE written in Rust — micro-style editor, file tree, integrated terminals, syntax highlighting, classic drop-down menu bar

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages