Joakim 26dcf49f41 N/A
2026-10-13 12:13:00 +02:00
N/A
2026-10-13 12:13:00 +02:00
N/A
2026-10-13 12:13:00 +02:00
2026-10-12 22:00:15 +02:00
N/A
2026-10-13 11:04:53 +02:00

TUI

A small keyboard-driven terminal UI for browsing directories and executing ordinary shell commands defined in .tui files.

The important design choice is that TUI does not execute actions inside a Python subprocess. It hands the generated commands back to the Bash process that started tui. This keeps the commands visible in Bash history and gives actions the normal shell environment.

Requirements

  • Debian/Linux with Bash
  • Python 3
  • PyYAML (python3-yaml on Debian)
  • curses from the normal Python installation

Install the Debian dependency if necessary:

sudo apt install python3-yaml

Installation

Unpack the project and run:

./install.sh

The installer installs TUI under:

~/.local/lib/tui/

and adds the shell integration to:

~/.bashrc

The integration is therefore loaded automatically for interactive Bash sessions, including the normal Debian login/terminal startup path.

After installation, start a new terminal/login session, or run:

source ~/.bashrc

Then:

tui

Use -a to include hidden files and directories:

tui -a

The installer does not overwrite an existing ~/.tui.

-a / --all is a command-line option, so the shell integration preserves it when the TUI restarts after an action.

.tui configuration

TUI searches for the nearest .tui starting in the current directory and walking upwards, but never above $HOME.

A configuration contains keys and actions:

keys:
  up: up
  down: down
  left: parent
  right:
    folder: enter
    file:
      - "*.zip": list-zip

  ctrl-k:
    b: mark-begin
    k: mark-end
    m:
      file:
        - "*": move

actions:
  list-zip:
    command:
      - unzip -l <path>
      - read -rp "Press Enter to continue..."

  move:
    command: mv -v <path> <dir>

Rules are evaluated from top to bottom; the first matching glob wins.

Substitutions

Token Meaning
<name> basename of the target
<path> full path of the target
<dir> directory currently displayed by TUI, with trailing /

Navigation

The default example configuration uses:

  • ↑ / ↓ — move cursor
  • Enter / → — execute the configured action
  • ../ — synthetic parent-directory entry at the top of every listing
  • ← — move the cursor to ../; pressing ← again enters the parent directory
  • Enter on ../ — enter the parent directory
  • navigation cannot move above the directory containing the applicable .tui file
  • hidden files and directories are hidden by default; tui -a shows them
  • file and directory colors follow the usual GNU ls --color=yes conventions for common file types
  • Ctrl-K B — set selection start
  • Ctrl-K K — set selection end
  • Ctrl-K C — copy marked files/folders
  • Ctrl-K M — move marked files
  • Ctrl-K Y — delete marked files/folders
  • Ctrl-C — quit

Marking

Marks are stored as absolute paths and belong to the TUI session, not to the current directory.

For example:

/home/joakim/notes/
  A.txt   *
  B.txt   *
  work/

Entering work/ does not clear the marks. Returning to the parent directory shows A.txt and B.txt as marked again.

Marks in different directories can coexist. If A.txt is marked, then TUI is moved to work/, Ctrl-K M operates on the original absolute path while using the current directory as the destination:

mv -v /home/joakim/notes/A.txt .

A mark is removed automatically only when its target no longer exists.

Ctrl-K B and Ctrl-K K define a contiguous selection in the directory being viewed. Changing directory clears the temporary selection endpoints but does not clear the already marked paths.

Shell integration

When an action is triggered, TUI writes the generated commands to a temporary file and exits with a private handoff status. The tui() Bash function then executes them.

For example:

actions:
  list-zip:
    command:
      - unzip -l <path>
      - read -rp "Press Enter to continue..."

The flow is:

TUI
  ↓
unzip -l archive.zip
  ↓
read -rp "Press Enter..."
  ↓
TUI

TUI is not redrawn between commands belonging to the same action.

Every command is also inserted into Bash history. If one command fails, the remaining commands in that action are not executed. TUI prints the exit code and waits for:

Press Enter to continue...

before returning to TUI, so an error cannot disappear immediately.

The shell wrapper uses pushd/popd so the command runs in the directory shown by TUI without permanently changing the user's Bash working directory.

Security note

Action strings are intentionally ordinary Bash commands and are executed with eval by the user's Bash shell. .tui files should therefore be treated as executable configuration and only used from directories/configurations you trust.

Development

Run a syntax check with:

python3 -m py_compile tui/tui.py

For development without installing:

source tui/tui-shell.bash
tui

The example configuration is in tui/example.tui.

Version

Use tui -v or tui --version to verify the installed TUI version.

v3 menu

Press M to open the action menu. The menu is generated entirely from the current .tui file, so a directory can provide its own context-specific operations.

The example configuration defines ordinary file operations and Git operations that appear when the current directory is inside a Git worktree.

The top-level keys are also configurable in .tui:

keys:
  a: toggle-all
  q: quit
  m: menu

Menu entries support:

menu:
  - label: "Git: pull"
    key: p
    action: git-pull
    selection: none
    when: git

selection can be auto, current, marked or none.

Available generic when conditions include always, git, not-git, file, folder, marked, multiple, exists:<path>, missing:<path>, glob:<pattern>, plus all, any and not expressions.

Actions that operate on the current directory rather than a file can use:

actions:
  git-pull:
    target: none
    command: git pull

This keeps the Python code generic: menu presentation, labels, shortcuts, conditions and shell commands belong in .tui.

Floating action menu

Press M to open the configured action menu. The menu is rendered as a floating overlay over the browser. It is positioned above or below the current cursor when possible, so the selected file remains visible.

Menu labels, shortcuts, actions, and context conditions are defined in .tui; the Python UI engine does not contain Git-specific menu definitions.

All user-visible TUI text is English.

Description
No description provided
Readme 133 KiB
Languages
Python 83.9%
Shell 16.1%