Skip to main content

dunders — Norton Commander–style terminal file manager, text editor, and LLM-agent CLI built on Textual.

Project description

dunders

Terminal · Your · Universal · Intelligence

A Norton Commander–style terminal file manager, text editor, and LLM-agent CLI for the modern shell — built on Textual.

The name dunders is the four QWERTY keys right after qwery — picked in the same spirit as vim's hjkl. The CLI command is dunders.

dunders brings back the dual-pane workflow of mc / Far Manager — but with a real windowing layer (Turbo Vision–inspired), code folding, recordable macros, a command palette, and an embedded LLM/agent CLI mode.

Status: alpha. Core file-manager and editor are usable; agent/CLI mode is a stub.

Quick install (any OS — one line)

Installs uv if you don't have it, then installs dunders (plus the __ / __w launchers) into an isolated environment — no system Python needed.

Linux / macOS / WSL (bash/zsh):

curl -LsSf https://astral.sh/uv/install.sh | sh && export PATH="$HOME/.local/bin:$PATH" && uv tool install --force git+https://github.com/tumikosha/dunders.git

Windows (PowerShell):

irm https://astral.sh/uv/install.ps1 | iex; $env:Path = "$env:USERPROFILE\.local\bin;$env:Path"; uv tool install --force git+https://github.com/tumikosha/dunders.git

Then run dunders. (Already have uv? Just uv tool install git+https://github.com/tumikosha/dunders.git.)

Features

  • Dual-pane file manager with sort, multi-select, quick-search, and the classic NC F-key bar (F3 view, F4 edit, F5 copy, F6 move, F7 mkdir, F8 delete, F9 menu, F10 quit).
  • Embedded text editor with split view, search & replace, fold-by-indent, and bracket/region folding rules.
  • Recordable macros with persistent storage.
  • Hex viewer for binary or large files (mmap-backed, switches in automatically above 4 MiB).
  • Turbo Vision–style windowing layer (dunders.windowing) — reusable in other Textual apps. Tile, cascade, maximize, modal dialogs, command palette, themable via YAML.
  • Mouse support everywhere, including the menu bar and status bar.
  • LLM agent / CLI mode (in progress) — bring your own model.

Install

Zero-Python install via uv (recommended)

uv is a single static binary. It installs Python for you, then installs dunders into an isolated environment and puts the dunders command on your PATH. No system Python required.

# 1. Install uv (one-liner, no Python needed)
curl -LsSf https://astral.sh/uv/install.sh | sh        # macOS / Linux
# Windows PowerShell:
#   powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# Or via package manager: brew install uv  /  pipx install uv  /  scoop install uv

# 2. Install dunders (uv fetches Python 3.12+ automatically if missing)
uv tool install dunders

# 3. Run
dunders

Try it once without installing:

uvx --from dunders dunders          # downloads, runs in a temp env, then forgets

Upgrade / uninstall:

uv tool upgrade dunders
uv tool uninstall dunders

If you already have Python 3.12+

pipx install dunders            # preferred — isolated, on $PATH
# or, inside an active venv:
pip install dunders

Requires Python 3.12+ in any path above.

Usage

dunders                  # two-panel file manager (default)
dunders path/to/dir      # file manager seeded at a directory
dunders path/to/file     # open a file in the editor
dunders --cli            # agent / CLI mode (stub)

Short launchers

Two extra console scripts are installed alongside dunders, differing only in how embedded shell commands hand off the terminal:

Command Terminal mode Platform
__ relay — persistent relay subshell Linux / macOS
__w suspend — suspend + subprocess, no persistent session cross-platform (use this on Windows)

Both take the same arguments (files open in cascaded editor windows; a lone directory or no args open the mc-style file manager) and accept --suspend explicitly; __w is just __ --suspend.

Inside the app:

Key Action
F3 View file (hex if binary/large)
F4 Edit file
F5 / F6 Copy / Move selected items
F7 / F8 Mkdir / Delete
F9 / F10 Menu / Quit
Tab Switch panel
Shift+Tab Cycle desktop windows
Alt+L / Alt+R Focus left / right panel
Ctrl+K Command palette

Editor-scoped keys (Save, Find/Replace, Split, Fold, Record macro) appear in the status bar when an editor window has focus.

Development

git clone https://github.com/tumikosha/dunders dunders
cd dunders
uv sync --extra dev          # or: pip install -e '.[dev]'

pytest                       # full suite
pytest -k fold_engine        # by keyword
ruff check

The repository ships a standalone windowing demo to exercise the framework without the file-manager layer:

python -m dunders.windowing.demo

Project layout

The PyPI distribution is named dunders; the importable Python package and the CLI command are both dunders.

dunders/
├── app.py            # DundersApp shell — wires menus, panels, dispatcher
├── main.py           # entry point (argparse)
├── fm/               # file-manager domain (panels, dialogs, file ops)
├── windowing/        # Turbo Vision–style framework on Textual
│   ├── core/         # buffer, fold engine, macros, search
│   ├── editor/       # embeddable editor widget + content
│   ├── themes/       # palette loader + modern_dark default
│   └── demo/         # standalone framework demo
├── themes/           # dark.yaml / light.yaml palettes
└── config/defaults.py

See CLAUDE.md for an architecture deep-dive aimed at contributors and AI coding assistants.

Terminal limitations on macOS

macOS Terminal.app does not report several modifier+key combinations to the application, so some editor shortcuts can't reach dunders there:

  • Shift+↑ / Shift+↓ / Shift+Home / Shift+End — selection by line / to start/end of line. Terminal.app sends the same sequence as the unmodified key, so the selection variant never arrives.
  • Cmd+C, Cmd+↑ / Cmd+↓ — the terminal intercepts Cmd shortcuts itself and never forwards them.

You can confirm what your terminal sends with cat -v (press the combo, then Ctrl+C to quit): if Shift+↑ prints ^[[A (same as plain ) the modifier is being dropped.

Two fixes:

  1. Use a terminal that supports the kitty keyboard protocol — iTerm2, Ghostty, Kitty, WezTerm. These deliver Shift+arrows and Cmd+arrows/Cmd+C out of the box, no configuration needed. (Recommended.)

  2. Remap the keys in Terminal.app — Settings → Profiles → your profileKeyboard+, with Action Send Text (\033 is the Esc character):

Key Modifier Send Text
Shift \033[1;2A
Shift \033[1;2B
Home Shift \033[1;2H
End Shift \033[1;2F

Cmd+C can't be remapped this way (Terminal.app keeps it for its own Copy). In the editor and command line use Ctrl+C to copy instead — in the command line Ctrl+C copies the current selection and otherwise cancels/clears, like a shell.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dunders-0.1.0.tar.gz (183.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dunders-0.1.0-py3-none-any.whl (228.4 kB view details)

Uploaded Python 3

File details

Details for the file dunders-0.1.0.tar.gz.

File metadata

  • Download URL: dunders-0.1.0.tar.gz
  • Upload date:
  • Size: 183.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for dunders-0.1.0.tar.gz
Algorithm Hash digest
SHA256 f46b995d1ff9c0c035b64315fc93ad969b489322ae824d02271ad8a6dff6930e
MD5 e437df2d9d25ddcff9f465315cdaa10f
BLAKE2b-256 89aeca1705c24f8e99ea295ab63ba9c328fec1a6464ca3d9e00755ba632ef21f

See more details on using hashes here.

File details

Details for the file dunders-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: dunders-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 228.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for dunders-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8be685512af2a7a9fba77956f49794b53edac393867fdb6103461c63151d8c2c
MD5 c959a28d440a6a467d3fc6fc818357cd
BLAKE2b-256 ae8a80e8a20438769774a85b1628a9d97a2ccdc0166741432a4c54099cf2da08

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page