A file manager for the terminal, written on Arlecchino: two panels over a local disk, an SFTP server or an FTP one, with tabs, leader keys and a command line of its own. The function keys stay where they have always been, but little else stops there.
dotnet run --project src/Arlecchino.Commander -- C:\some\folder C:\another
Every tag builds a native binary for Windows, macOS and Linux on both architectures, compiled ahead
of time — one file, nothing to install, no .NET on the machine required. They are on the
releases page. A version is the year,
the month and which release of that month it is, so 2026.8.1 is the first release of August 2026
and the number says how old the binary in hand is.
- Two panels.
Tabswitches between them,Enteropens,Spacemarks. The panel that has the focus is the one the operations work from. The cursor moves onjandkas well as the arrows, andhandl—←and→too — leave the folder and enter the one under the cursor, which is where those keys are worth more than on swapping panels. - Sorting, behind
s.s hs js korder the panel by name, size or date, ands lturns the order around whichever column it is on. A click on a column head does the same. - The function keys.
F2tabs,F3view,F4edit,F5copy,F6move,Shift+F6rename,F7make folder,F8delete,F9menu,F10quit — andF1lists every key at once, what the framework answers to everywhere beside what the panels bound for themselves. - Tabs. Each one holds two panels of its own, so a second pair of folders — or a server on one
side — is a tab away rather than a place you have to navigate back to. They live behind
t:t kopens one andt jcloses it,t handt lstep between them, andt olists them all. The band along the top shows what each one is connected to and takes a click on it, on its×, or on the+at the end. Too many tabs for the band shortens the names first and then scrolls, with‹and›for the ones off either side; going to a tab always brings it back into view.F2lists them too, and the palette finds a tab by name — typing the name of a server goes to the tab that is on it. - Going somewhere, behind
g. A leader spends one key and gives back the alphabet:g handg lwalk back and forward through the folders the panel has been in.g ug og mjump to the top, the middle and the bottom of the panel,g bsends the other panel here andg ysends it into the folder under the cursor. Which way a key goes is where it sits rather than what it stands for. Once the leader is pressed, the keys that finish it are listed over the command line, in the shape the settings use to offer their own words, so nothing here has to be remembered. Nothing needs a key a laptop does not have: whereCtrl+PgUpandCtrl+PgDnread well they still leave and enter a folder, but only as a second way in. - Getting around the way Midnight Commander does.
/searches as you type, jumping to the name as it is typed,+and-mark and unmark by shell pattern, and*inverts the marks. - Find file.
Ctrl+F7asks for a name and walks down from the panel — over SFTP as readily as over a disk. What is typed is looked for anywhere in a name, unless it spells a shell pattern of its own. Results fill in while the walk runs,F3stops it, andEntersends the panel to the file it found. - Everything in one list.
Ctrl+Kopens a palette holding every menu entry, every tab and every key the screen answers to, narrowing as you type — so nothing has to be found by remembering which menu it was filed under. - Doing something to what is on the panel, behind
x.x csets permissions — through SFTP's own request, FTP'sSITE CHMOD, or the file mode on a Unix disk —x ohands achownto the shell where the panel is looking,x sandx lmake a symbolic or a hard link into the other panel,x dmarks in both panels every file the other one does not have the same of,x ishows the invisible files, andx rreads both panels again. - The clipboard, behind
c.c cputs the marked paths on it, whole and one to a line,c fthe names with their extensions,c nthe names without them, andc dthe folder the panel is looking at. None of it is what a selection dragged over the panel would give you: the panel draws names cut to the width of a column, and what is copied is what the file is called. It is a leader rather than a modifier because every modifier worth reaching for belongs to the terminal —Ctrl+Shift+Cis the terminal's own copying and never arrives, andCtrl+Cstops things. What is copied goes out through the terminal as OSC 52 and throughwl-copy,xclipor whichever of their kind is installed, since a terminal with the sequence switched off drops it without a word. - Panels that keep up by themselves. A file made, written or deleted by something else — another
window, a build, a download — turns up in the panel with no key pressed. On a disk the operating system
says so; on a server, which says nothing, the folder on screen is read again every few seconds and
compared with what the panel has, and nothing is asked of it while it is carrying files. The panels of a
tab that is not on screen stop watching until it is come back to, and
watch offstops all of it. - A viewer on
F3. A file is read without leaving the panels: a picture as a picture, drawn through the terminal's own graphics protocol where there is one and in half-blocks where there is not; a Markdown file as what its marks say — headings, lists, quotes, code blocks, tables and links, wrapped to the panel rather than to the width the file was written at, with the pictures it names read from beside it and drawn in place; anything else as text, and anything with a zero byte in it as a hex dump. A file on a server is read the same way, since what the viewer is handed is a stream either way — and a picture the document names somewhere on the web is named rather than fetched, since fetching it would tell whoever wrote the document that the file had been opened. - A real editor on
F4. There is no editor of our own: the terminal is handed to the one the settings name — the screen steps aside, the editor gets the keyboard and the screen to itself, and the panel is read again when it exits. Files on this machine only; a panel showing a server says so. - Settings, behind
!. The same row the command line uses, opened by an exclamation mark, with a box above it listing what can be set, what each of them is now and what it is for — narrowing as you type,Tabfinishing the word, and a name on its own filling in its current value so it can be edited rather than retyped.editor vimkeeps the editor, andwatch 5how often a server is read again. What is kept lives in~/.config/arlecchino.commander/settings.toml(or underXDG_CONFIG_HOME), written the moment something changes rather than on the way out — a file manager is quit by closing the terminal as often as by pressing the key for it. With nothing set,$VISUALand$EDITORare what the editor already is. - A command line under the panels, behind
:. The panel keeps the letters until the colon asks for them, which is what leaves a key free to be a key.Enterruns what was typed where the panel is looking — on the server itself when that panel is connected —Escapegives the keyboard back,cdmoves the panel instead of a shell that would forget it,Ctrl+PandCtrl+Ywalk the history,x nputs the name under the cursor on the line,x pthe folder,x tthe marked names, andCtrl+Oreads back everything the commands printed. - Commands that ask something back. What a command prints arrives as it prints it, and its input is
left open, so a command that stops mid-line on a question is answered rather than waited on. The
question opens as a dialog wherever in the application you are, and the dialog is the only way to
answer it: what is typed there is hidden as it is typed, and nothing of it reaches the command line,
which goes on being for commands.
x abrings the question back where the dialog was closed on it. Where there is no terminal to be had — on a server, on a machine that has no such thing —sudois spelledsudo -Son the way out, since otherwise it looks for one and gives up before it has asked.x esays there is no more input, asCtrl+Ddoes at a terminal. Nothing answered is written into the roll: what went is shown as dots. - Commands that want the screen. A command runs at a terminal of the application's own making rather
than on a pipe, and what it does with that terminal is watched. Nothing is guessed from the name it was
typed under — a list of the names of editors is a list that is always one program short. A program that
means to draw says so itself in the first thing it writes: it swaps onto the second screen a terminal
keeps, or turns the mouse on, or asks the keyboard for the arrows, or simply puts the cursor where it
wants it. At that moment the screen steps aside exactly as it does for the editor on
F4, the program has the keyboard and the terminal to itself, and the panels come back when it ends. An editor typed on the command line, a pager, a list of processes, a box a package manager puts up: all of them work, and none of them are known about. Everything else goes on as it was — the lines land in the roll, and a question opens a dialog. Linux makes that terminal out of a pair of ends and Windows out of a console of its own, and neither the watching nor the handing over knows the difference; macOS has no dialect here yet, and runs its commands on pipes until it does. - Servers. A panel connects over SFTP or FTP and browses it exactly as it browses a disk; copying
between the two panels is the same key whichever side is which.
g dputs the panel back on the disk when you are done with the server. - Hosts from
~/.ssh/config.g nlists theHostentries and opens one, reusing itsHostName,User,PortandIdentityFile, or the default keys in~/.sshwhen it names none. - Commands over SSH. The
Commandmenu runs one on the connected host and shows what it said. - Work that does not freeze the screen. Copy, move and delete run in the background with a bar,
the file being worked on, and
Ctrl+X Escto stop; each reports itself as a notification that turns into what came of it, with the errors readable in full behindEnter.
The application renders one frame and exits, which is what the screenshots and the CI check are made of:
dotnet run --project src/Arlecchino.Commander -- --frame 120x30 --left . --right src
--keys F9,Enter plays keys before the frame is drawn, --connect sftp://user@host/path?key=… (or
--connect myhost for a ~/.ssh/config entry) opens a panel on a server first, and --wait 2000
gives the network time to answer.
The framework is a submodule under lib/Arlecchino, and nothing compiles without it:
git clone --recurse-submodules https://github.com/The1fEst/Arlecchino.Commander.git
A clone that already exists picks it up with git submodule update --init. After that:
dotnet build Arlecchino.Commander.slnx --configuration Release
The framework builds from source with the application, so a change made in lib/Arlecchino is in the
next build. Moving to a newer framework is git -C lib/Arlecchino pull and a commit of the new
revision here.
Most of the tests run wherever they are put; one project of them cannot. The tests in
tests/Arlecchino.Commander.Tests.Carries give the screen away the way the application does, which is
something done to the terminal the application is running in — and a test host has none worth giving.
So each of them opens one — the console this machine opens a program in, Windows Terminal, and WezTerm,
each under pwsh, powershell and cmd — with a program inside that takes the screen. A key is
pressed at the real keyboard from outside, and what the console looked like before and after is read
back and compared. A machine missing one of those terminals says so in the run's output and is passed
over, as does one with nobody logged into it, where a terminal that draws a window has no one to draw
it for; a machine that is not Windows passes over all of them. The console is on every machine of the
kind and needs nobody logged in, which is the one the build tries.
dotnet test tests/Arlecchino.Commander.Tests.Carries
A window opens for the length of each try, which is why they live apart:
dotnet test tests/Arlecchino.Commander.Tests is everything else and opens none.
The screenshots are taken by tools/shots.cs, which draws each frame itself onto a window of its own
making. Every scene is taken unless some are named:
dotnet run tools/shots.cs viewer connect help
show walks the same scenes in this terminal instead, one key apart, so a frame can be read as the
terminal draws it. shoot walks them on its own and has macOS photograph the window each frame is
drawn in — the real font and the shadow the system puts under a window — into assets/screenshots,
which is where the pictures above come from; q between two pictures stops it. Both take the names of
scenes as well. It wants kitty with remote control on, since that is what names the window to capture,
and the first run asks for permission to record the screen:
dotnet run tools/shots.cs shoot viewer connect help
tape records the animation this README opens with, and it is photographed the same way:
one run of the application plays the whole script and hands back every frame with the milliseconds it
is to be held for, then each frame is written to this window and captured. ffmpeg binds them into an
APNG — every color the terminal drew and the shadow under the window, neither of which fits in a GIF's
256 — and a frame wider than 1400 pixels is scaled down to that, so the file stays the size a README
can carry. It wants ffmpeg on the path, and a window around 120 columns reads best:
dotnet run tools/shots.cs tape
MIT.













