CommanderTUI
Dual-pane terminal file manager: compare two folders, sync them, or move files/folders between them (and to USB/SMB/any mounted path) — with a phosphor-green 80s-terminal look and a short modem-style boot animation.
Status: v1.0.0 — 40/40 tests passing. MIT licensed.
Why this exists
A safe, simple alternative to heavier dual-pane file managers. It was written after an earlier attempt of the same idea had to be scrapped for running an unauthenticated local HTTP server. This project deliberately:
- Never opens a network port. Pure terminal UI (Textual), no HTTP server, no webview.
- Never does a raw
rm -rf. Deletes always go through the desktop trash (send2trash→gio trash→ manual move into~/.local/share/Trash, in that order). - Never overwrites in place. Copies stream into a hidden
.tmpfile next to the destination and are committed withos.replace— a crash or Ctrl+C never leaves a half-written file. - Never guesses on a conflict. Two-way sync copies each side's exclusive files automatically, but a file changed on both sides is always shown to you, never auto-resolved.
Install
Arch Linux / Omarchy. An AUR package is on the way (yay -S commandertui).
Until then, build it from the PKGBUILD in this repo. makepkg pulls in
everything it needs:
git clone https://github.com/juniorbarchini-oss/commandertui.git
cd commandertui/packaging/arch
makepkg -si
Remove it with sudo pacman -R commandertui.
Other distros. It is a regular Python package (Python 3.11+):
pipx install git+https://github.com/juniorbarchini-oss/commandertui.git
From a source checkout (development):
python3 -m venv .venv && .venv/bin/pip install -e . -r requirements-dev.txt
bin/commandertui [left-dir] [right-dir]
Run
| Command | What it does |
|---|---|
cmdrtui |
Opens it in its own terminal window. This is also what the CommanderTUI app-launcher entry runs |
commandertui |
Runs it inside the terminal you are in |
commandertui DIR1 DIR2 |
Opens with those two folders side by side |
cmdrtui uses your desktop's default terminal (xdg-terminal-exec). If that
isn't available it tries foot, alacritty, kitty and ghostty. The window
always gets the app-id/class commandertui, so a window-manager rule can
float it. It needs about 1174x637 px to fit every key hint. On Hyprland:
# hyprland.conf
windowrulev2 = float, class:^(commandertui)$
windowrulev2 = size 1174 637, class:^(commandertui)$
windowrulev2 = center, class:^(commandertui)$
-- Omarchy Lua config (~/.config/hypr/hyprland.lua)
o.window("^commandertui$", { float = true, center = true, size = { 1174, 637 } })
Keys
| Key | Action |
|---|---|
Tab |
Switch active pane |
↑/↓, Enter |
Navigate, open directory |
Backspace |
Go to parent directory |
Space |
Mark/unmark item under cursor |
F5 |
Copy marked (or item under cursor) to the other pane |
F6 |
Move marked to the other pane |
F7 |
Create a folder in the active pane |
F8 / Delete |
Delete marked (to trash) |
i |
Size: file/folder count and total bytes of marked items (background, Esc stops it) |
h |
Show/hide hidden (dot) files in both panes |
p |
Places: jump to a mounted drive (USB/SMB/rclone) or saved bookmark |
c |
Compare: full recursive diff between the two panes' current folders |
r |
Refresh both panes |
q |
Quit |
While a copy/move runs, the progress window shows two bars (current file
and whole job, by bytes) plus speed in Mb/s and time left. Esc asks to
cancel: finished files stay, the file in progress is discarded (never left
half-written), and a move never removes a source it didn't fully copy.
Places lists only what is mounted right now: USB drives
(/run/media, /media, /mnt — checked with ismount, so an empty
on-demand mount point doesn't show), GVFS/Nautilus network shares, FUSE
mounts inside $HOME (e.g. rclone mount), and saved bookmarks.
Inside Compare:
| Key | Action |
|---|---|
m |
Mirror: make right identical to left |
u |
Update: copy new/changed left → right, never deletes |
b |
Two-way: propagate each side's exclusive changes; conflicts (changed on both sides) are listed, never guessed |
Space |
Mark a row for manual handling |
c |
Copy marked rows in whichever direction they diverge |
Esc |
Back to the panes |
Every bulk or destructive action shows a plain-language summary (count of
operations, total bytes) and requires y to confirm.
Architecture
commandertui/
├── models.py # FileEntry, DiffEntry, OperationQueue, QueuedOp
├── scanner.py # os.scandir recursive tree walk
├── diff.py # pure comparison: left-only / right-only / modified / identical
├── plan.py # diff -> OperationQueue (mirror / update / two-way)
├── sync.py # atomic copy/move (streamed, tmp+replace), checksum verify
├── trash.py # 3-layer safe delete (send2trash / gio trash / manual)
├── executor.py # runs an OperationQueue against the filesystem
├── bookmarks.py # detected mounts (USB/SMB/rclone) + saved places
├── theme.py # green/amber phosphor palettes
├── boot.py # startup "modem" reveal animation
├── widgets.py # FilePanel: one pane's directory listing
├── modals.py # Confirm / Places / Input / Size / Message screens
├── progress_screen.py # two-bar transfer progress + cancel
├── run_queue.py # confirm -> run queue in a worker thread
├── compare_screen.py # full diff view + bulk/manual sync actions
├── app.py # CommanderApp: wires panes + keybindings
└── cli.py # argument parsing, entrypoint
Tests
pip install -r requirements-dev.txt
pytest
black commandertui tests # formatter, line length set in pyproject.toml
Engine (scanner/diff/plan/sync/executor) is fully unit tested against a real
filesystem (tmp_path). The UI has smoke tests via Textual's Pilot
(boot sequence dismisses, pane switching, mark→copy→confirm end to end).
Not in scope
No file preview, no deduplication engine, no desktop GUI wrapper — those are different problems.
Credits
Designed and tested by Humberto Barchini. The code was written together with Claude (Anthropic) through Claude Code: Claude Sonnet 5 built the first version, Claude Opus 5.5 did most of v0.2 and the v1.0 packaging.
License
MIT — see LICENSE.
Release files for commandertui 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| commandertui-1.0.0.tar.gz | 32.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| commandertui-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 64.9 kB
Release files / commandertui-1.0.0.tar.gz
| Download URL | commandertui-1.0.0.tar.gz |
|---|---|
| Size | 32.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4c8a69aef8b35dc3b0c15bca46dcbc780732f9321094f877549f2f24d25c8059
|
|
BLAKE2b-256 checksum How to use checksums |
201a78005ba3d968c035fd56e780aa6e37976de6606be8e6b0f64b3f34bc8148
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.
Transparency logRelease files / commandertui-1.0.0-py3-none-any.whl
| Download URL | commandertui-1.0.0-py3-none-any.whl |
|---|---|
| Size | 32.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6b04ff2b690d11aa20aed9221e546494c9dbe78bad706f969dc821ca0dc9d204
|
|
BLAKE2b-256 checksum How to use checksums |
782796dfc36b65b91c656d4006dc2f5903be01f9c63699b3ec4f3c084eed4089
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.
Transparency log