Marunja CleeCode

clee — ~/project

CleeCode

your terminal IDE

File tree, editor tabs, terminals, LLM integration and document rendering — written in Rust, driven from mouse and keyboard.

Use your coding agent — claude, codex, opencode, gemini — on the subscription you already pay for, with no API tokens to buy. It runs inside the editor, its edits visible live in your buffers.

No API key to configure, to keep safe, or to pay per token. No GUI editor can say that whole sentence.

Subscription login and API keys both work, because the editor never touches credentials at all: the agent in the pane is the real CLI and authenticates itself, with the login or the key it finds in your environment. There is no field to paste a secret into, and nothing to steal in the config.

Install GitHub

macOS, Linux and Windows · MIT · release notes

CleeCode in action: editing a file with the tree on the left and terminals below

The agent inside

One key opens it beside your work. The other half was telling it what only the editor knows.

Ctrl+Shift+A opens the agent drawer: a panel down the right of the window, in whatever you were already doing. Empty, it is the launcher — claude, codex, opencode and gemini written large, arrows and Enter to start one, the ones you do not have shown anyway and dimmed, so the empty drawer is also where you find out what CleeCode runs. Pinned it is a column of the layout and everything makes room for it; set to autocollapse it paints itself over the frames and withdraws the moment the keyboard goes back to your work. Dismissing it is not killing it: the agent goes on running and the conversation is where you left it. There is nothing to install and nothing to configure: this is a real pty, and all four are terminal programs. The agent is the TUI you already have, not a chat window rebuilt inside an editor.

With one running, that same Ctrl+Shift+A hands it whatever you are looking at — the selection, the diagnostic under the cursor, or the line the cursor is on — written at its prompt as path:line. And then it stops. Nothing is ever submitted: the text sits at the prompt and Enter is yours to press once you have read what you are about to ask. The way back was always there, since an agent prints file:line all day and a double-click opens it.

The files it rewrites reload on their own, the arrived lines lit green in the gutter until you type again or press Esc. A buffer with your unsaved edits never reloads itself: your work wins over the agent's, always. Follow mode — off until you ask for it — opens the files it touched beside your work without ever taking the keyboard; it watches the difference between two git status sweeps, so an agent and a sed in a shell trip it identically.

And the editor can answer back. clee --mcp makes CleeCode an MCP server with four read-only tools: open_files, selection, diagnostics, and open_file, which shows a file beside your work without touching your keyboard. One line of configuration per agent:

claude mcp add clee -- clee --mcp

codex, opencode and gemini take one line each in their own config file — the shapes are in the tour. The Claude Code line is the one verified against a running agent; the other three are written from those projects' documented shapes. Nothing writes to a buffer: reading has no risk and is offered generously, writing needs your consent, and the way to ask for it is not built yet.

Pictures, PDFs, Markdown

A terminal editor that shows you the file, not a description of it.

A .png gets a tab that draws it — real pixels, not a blank read-only buffer and not a wall of coloured blocks. An animated .gif plays there too, at the speed the file itself asks for, looping for as long as the tab is on screen. A PDF opens as pages you turn with the arrow keys. A Markdown file opens as a document beside its source.

Two photographs open as tabs in CleeCode, with the same picture rendered through chafa in a terminal pane below
The same file twice: real pixels in the tab above, and chafa putting it into a terminal pane below, with the Run button beside it. The difference is the point — and it is not the terminal's fault.

A program running inside a pane never talks to your terminal directly: it talks to the emulator in between, which turns everything into a grid of cells before repainting it, and graphics sequences do not survive that trip. CleeCode's pixels take the other road — out on the same channel as the rest of the interface, arriving at the host terminal intact. Which is also why the same picture keeps showing over an ssh session: what travels on the wire is the editor's output, not that of a program buried in a shell.

A LaTeX source on the left and its typeset PDF page on the right, inside CleeCode
Edit the .tex, press Run, and the page beside it is the one you just typeset — it re-renders in place. On a preview tab the button says Refresh instead, because there the file is generated and can come out different.

Every preview carries a navigation bar along its bottom edge: the page arrows, go to jump to a page by number, - and + for zoom, 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. 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.

Markdown source on the left and the rendered document on the right, two tabs onto one file
Two tabs onto one file, not two copies: the glyph in the strip tells them apart, and typing in the source moves the document beside it without a save. So the two can never disagree about what the file says.

Best in a terminal that can draw pictures — Ghostty, kitty, WezTerm or iTerm2 — which is where it looks like these screenshots. Elsewhere pictures fall back to coloured half-blocks and Markdown to styled terminal text: less to look at, nothing missing. Previews reach for a few outside tools (poppler for PDF pages, pandoc or typst for Markdown as a real document); none is required, and without them CleeCode says so in the tab rather than leaving it blank.

Octave & Python

A live numeric session, with the panel beside it that no terminal gives you.

clee -w octave or clee -w pylab starts the interpreter you already have — in a terminal you can type into — and puts a second window beside it showing what that session holds: every variable with its size, class and range, filling in by itself whenever a command finishes.

The Octave workspace: the script on the left, a figure as a tab, the prompt below and the variables panel beside
One window: the script on the left, figure(1) arriving as the fig1.png tab, the Octave prompt below it and the workspace panel beside — x and y with their size, class and range, listed without asking.

Nothing CleeCode wants to know is typed at your prompt. Your transcript stays a record of what you did, and a busy interpreter is never interrupted mid-computation to answer a question about itself. Ctrl+Shift+X sends a cell to the running session, plots arrive as tabs beside the script that drew them, Ctrl+Shift+I looks inside a variable, and Ctrl+Shift+P sets a breakpoint — where the panel shows the frame's variables rather than the session's.

The pylab workspace: a matplotlib figure as a tab, the session below and its variables beside
The same arrangement in Python. ▶ Run on plot.py did not start a fresh interpreter: it typed exec(open(...).read()) at the prompt that was already there, so the session kept everything the file made — which is what the panel on the right is listing, and what lets the next line you type carry on from where the script left off.

Everything works in both languages and almost none of it works the same way underneath. The full walkthrough says what is different between the two, and what is not built yet.

The day's work

Tabs, a split, git, and search that knows the whole project.

syntect highlighting over two-face's grammars — 200-odd languages, the ones written this decade included — multi-file tabs, a split editor sharing one pool of buffers, find and replace with regular expressions, project-wide search, code folding, and a column selection that writes: with a rectangle up, a printable key puts its character on every line of the block.

Words already in your buffers are offered as you type, along with what a language server suggests where one is installed — after a dot, in magenta, the names no amount of reading the file could have found — and its errors underlined where they are, with the message for the line you are on at the right of the status bar. When the line is clean, that spot says what the thing under the cursor is instead: the type, or one line of the signature. Nothing is pressed for it.

The commands you reach for every hour are all there. Ctrl+Shift+J goes to a definition and Ctrl+Shift+L comes back, a stack deep; Ctrl+Shift+Y lists every use of the name under the cursor and Ctrl+Shift+V the symbols of the file, both as filterable pickers. Ctrl+Shift+Q formats the buffer as a single edit and a single undo.

The two commands that write follow the git panel's discipline rather than the language server's enthusiasm. Ctrl+Shift+C renames the symbol under the cursor: the server's answer touches nothing until it has been shown to you as a diff, and then applies atomically, one undo step per buffer. Replace-in-project is the same shape widened to files nobody has opened — a second field in the search box, a preview grouped by file, open buffers taking one Ctrl+Z each and files on disk rewritten through a temporary file and a rename. There is no undo for that half, so the count is said out loud. Six refusals have a sentence each, because a rename that quietly skips a file is worse than one that will not run.

Ctrl+Shift+D opens a git panel that stages, commits, switches branch and draws the history as a graph — all of it through git on PATH rather than a library, so what the panel does is what the terminal beside it would do: hooks run, commits are signed, credential helpers are asked. Fetch, pull and push are typed into one of your shells rather than run behind the panel, and that is the point rather than a shortcut: they can stop to ask for a passphrase, a two-factor code or a host key, and a modal panel has nowhere to put such a question. A terminal is exactly the thing that can ask it.

It does not close on you

A broken terminal costs you that terminal, at most.

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, and the details go to ~/.config/cleecode/panic.log. Files changed underneath you are reloaded only when they are not dirty; a binary or non-UTF-8 file opens read-only rather than being corrupted on save; and every write goes out through a temporary file and a rename.

The shield keeps the process alive; it cannot help against a SIGKILL or a stack overflow, so those are covered separately. Every few seconds the buffers you have changed since the last tick are copied into a recovery folder under ~/.config/cleecode — the config directory and not the temp one, because this data exists precisely to outlive the process. At the next start a picker offers back anything newer than the file on disk, including the unnamed buffer that no session file could have remembered. Enter restores it dirty: saving stays a decision, and one Ctrl+Z is the version on disk.

That promise is tested the only way it can be: a driver kills the editor with kill -9 and watches the text come back. Not a unit test — the real binary, really killed.

Nine themes, and the far end of an ssh

The IDE that works over ssh with nothing to install on the far end.

Five dark themes and four light ones. The button beside the background toggle on the menu bar opens the list, or View → Theme… if your hands are on the keyboard. The choice is written out at once, because the reason to reach for it is usually that the screen has become hard to read, and having to make it again next session would be its own small misery.

The nine themes: CleeCode, Turbo, Solarized Dark, Eighties, Mocha, CleeCode Light, Solarized Light, Ocean Light and GitHub
Turbo is the blue screen, for anyone who learned to program on one: a light bar over a dark field, and the initial of each menu entry in red. The four light ones paint their own surface — they have to, or their dark text lands on whatever your terminal's background is. The dark ones do not have to, so on a translucent terminal they stay translucent unless you ask otherwise.

That is the ground CleeCode stands on. Not VS Code's, and not Zed's: one binary, batteries included, the mouse working, the compiler's output clickable — on a server you reached over ssh, with nothing installed at the far end and nothing to configure before the first hour is useful. The git panel deliberately speaks the old spellings (reset HEAD --, stash save) because a long-lived server reached over ssh is exactly where the newer commands are missing. Drop a file onto a terminal inside an ssh session and it goes up with scp.

English and Italian throughout, menus and built-in manual included. The at the right-hand end of the menu bar fills in the background, for a translucent terminal with something bright behind it — which is worth knowing the other way round too: by default CleeCode paints no background of its own, so a translucent terminal shows your desktop through the editor.

Install

Three lines on macOS and Linux.

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. On older Homebrew the command does not exist and is not needed — skip it and install. The formula builds from source: well under a minute on macOS, longer on Linux, where it also pulls libxcb.

Prebuilt binaries

Attached to every release, each built on the architecture it names.

  • macOS arm64

    Apple silicon. The supported platform: where CleeCode is developed, tested and released.

  • macOS x86_64

    Intel Macs.

  • Linux x86_64

    Needs glibc and libxcb — libxcb1 on Debian/Ubuntu, libxcb on Fedora/Arch. For Alpine or musl, build from source.

  • Linux arm64

    An Ampere or Graviton server, and a 64-bit Raspberry Pi OS. Same libxcb note.

  • Windows x86_64

    Compiles and starts in CI. Not yet driven daily by anybody — treat it as experimental, and bug reports are welcome.

Outside macOS the binaries are experimental: 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.

From source

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

cargo install --locked --git https://github.com/msavox/cleecode

That puts clee in ~/.cargo/bin, so make sure it is on your PATH. Then clee --install-font installs the bundled Nerd Font for the file tree's icons, and on macOS clee --install-app builds CleeCode.app so the editor can live in the Dock like any other.

What this page describes. Everything above is built and tested — nothing here is a plan. Some of it landed after the last tag and ships in the next release: the refactoring commands, replace-in-project and crash recovery are on master now, so cargo install --locked --git has them today, while Homebrew and the attached binaries follow the last tagged version. The release notes say which is which, release by release.