Skip to content

questdb/middle-manager

Repository files navigation

Middle Manager TUI

A dual-panel file manager for the terminal, inspired by Far Manager and Norton Commander. Built in Rust with ratatui.

Designed to handle very large files — the hex editor and text editor both use sliding buffers and lazy scanning, so opening a 10 GB log file is instant.

image

Features

File Manager

  • Dual-panel layout with directory listings (name, size, date, permissions)
  • File operations: copy (F5), move (F6), rename (Shift+F6), mkdir (F7), delete (F8), archive (Shift+F5)
  • Directory size calculation (F3) — async recursive scan with live progress, works on selections
  • Multi-file selection with Shift+Up/Down (toggle) and Insert key for batch operations
  • Far Manager-style dialogs with keyboard navigation (copy, mkdir, delete, rename)
  • Quick search — just start typing to jump to a file, Enter to open
  • Go-to-path (Ctrl+G) — type a path to navigate instantly, with zsh-style tab completion (case-insensitive, overlay dropdown)
  • Fuzzy file search (Ctrl+F) — recursively finds files by partial/misspelled names, ranked by match quality, opens in editor
  • Search in files (Ctrl+S) — ripgrep-powered content search with file filter, regex support, tree view results, Enter opens editor at match line with search term highlighted
  • Clipboard copy — Ctrl+C copies filename, Ctrl+P copies full path (OSC 52)
  • All dialog inputs support text selection (Shift+arrows), Ctrl+A select all, Ctrl+C copy, Ctrl+X cut, Ctrl+Z undo, Ctrl+Shift+Z redo
  • Sort by name, size, or date (F9), persisted across restarts
  • Mouse support — click to select, double-click to open, scroll wheel to navigate
  • Filesystem watcher — panels auto-refresh on external changes (kqueue/inotify, zero-cost idle)
  • Persistent state — panel paths, sort preferences, search queries, open panels, and split sizes survive restarts

Git Integration

  • Git status markers per file: modified, + added, - deleted, renamed, ? untracked, ! conflict
  • Branch name with glyph in panel title
  • Ahead/behind remote counts (↑N ↓M)
  • Repo-wide status summary in panel title (● 6 + 3 ? 7)
  • GitHub PR status with CI check indicators (PR #42 ✓ / / ), merged ( magenta) and closed ( red) states
  • Shared git cache across panels, fully async git status + PR queries (instant startup, never blocks UI)
  • Uses --no-optional-locks to avoid index.lock conflicts with other tools
  • File name coloring based on git status

Connectivity (Ctrl+T) [experimental]

  • Browse remote filesystems in the dual-panel file manager
  • 8 protocols: SSH, SFTP, SMB, WebDAV, S3/S3-compatible, GCS, Azure Blob Storage, NFS
  • Unified connection dialog with protocol tabs (Alt+Left/Right to cycle)
  • Cross-panel copy/move between local and any remote (F5/F6)
  • Remote file editing: F3/F4 downloads to temp, edits locally, uploads on save
  • Create files (Shift+F7) and directories (F7) on remote
  • Delete (F8), rename (Shift+F6) on remote
  • Saved connections: F2 in dialog saves for quick reconnect
  • Background connections with progress display and 30-second timeout
  • Auto-disconnect: Ctrl+T on a remote panel returns to local
  • All protocols shell out to system CLI tools (ssh, sftp, smbclient, curl, aws, gcloud, az, mount)
  • S3-compatible: MinIO, Backblaze B2, Cloudflare R2, DigitalOcean Spaces via --endpoint-url
  • Azure: connection string support, container browsing, Azurite-compatible
  • Debug logging: set MM_DEBUG=1 for shell command tracing

Session Persistence (--session)

  • middle-manager --session <name> creates/attaches to persistent tmux sessions
  • Survive terminal disconnects; reattach from any device via SSH
  • Session manager dialog (Ctrl+Y): create, attach, kill sessions
  • Detach with backtick then d (tmux prefix set to ` to avoid conflicts)
  • Nested session detection prevents tmux-in-tmux issues

Settings (Shift+F1)

  • Theme switcher: Far Manager (Classic) and QuestDB Dark
  • QuestDB Dark: deep purple-black backgrounds with rose-pink accents
  • Theme persisted across restarts

CI Panel (F2)

  • Tree view of CI checks with expand/collapse
  • GitHub Actions and Azure DevOps support
  • Expand a check to see its steps with status markers (✓ ✗ ○ –)
  • Download step logs and open in the built-in editor
  • Async fetching with animated spinners — never blocks the UI
  • Per-panel CI (left and right panels can each have their own CI view)
  • Tab/Shift+Tab cycles focus forward/backward through all panels
  • PageUp/PageDown/Home/End for fast scrolling through long check lists
  • Alt+Up/Down to resize split, Alt+Enter to maximize/restore
  • Mouse click support for selecting items in the tree
  • Failed checks sorted to top for quick access
  • PR number displayed in panel title
  • Ctrl+E: Extract all failures — downloads failed test logs, parses failure patterns (Rust, Java, Go, Python, Jest), writes consolidated Markdown report
  • Azure DevOps test results API (instant, no log download) with PAT auth support
  • GitHub API rate limit monitoring

Shell Panel (Ctrl+O)

  • Spawns your default $SHELL at the bottom of the active panel
  • Full PTY emulation — colors, cursor, scrollback all work
  • Independent per-side (left and right panels can each have their own shell)
  • Text selection: click-drag, double-click (word), triple-click (line)
  • Ctrl+C copies selection to clipboard (sends SIGINT when no selection)
  • Alt+Up/Down to resize split, Alt+Enter to maximize/restore
  • F1 switches focus back to file panel, Ctrl+O closes
  • Auto-closes when the shell exits
  • Restored on restart

Archive (Shift+F5)

  • Create tar.zst, tar.gz, tar.xz, or zip archives from selected files
  • Smart auto-naming: common prefix detection, dominant extension, parent dir fallback
  • Format picker: Space to cycle through formats
  • Background compression with progress bar in status bar
  • Symlink-safe traversal, collision resolution, UTF-8 safe naming

Parquet Viewer

  • Auto-detected when opening .parquet files (F4 / Enter)
  • Tree view: file metadata, key-value metadata (JSON pretty-printed), schema, row groups with column details
  • Column statistics: null count, distinct count, min/max values formatted with logical types
  • Tabular alignment for schema fields, column info, and metadata keys
  • Table view (Tab): scrollable data grid with row group lazy loading
  • Encoding names displayed as Plain, RleDictionary, DeltaBinaryPacked, etc.
  • Handles pre-epoch timestamps correctly

Claude Code Panel (F12)

  • Spawns claude maximized on the opposite panel, using the active panel's directory
  • Full PTY emulation via custom VT terminal emulator — colors, cursor, alternate screen all work
  • All keystrokes (including Tab) forwarded to Claude Code
  • 10,000-line scrollback buffer with trackpad/mouse scroll (like Ghostty/iTerm2)
  • Text selection: click-drag, double-click (word), triple-click (line)
  • Ctrl+C copies selection to clipboard (sends SIGINT when no selection)
  • F5 opens file:line references from terminal output in the built-in editor
  • F1 switches focus back to file panel, F12 closes
  • Restored on restart with claude -c (continues last session)
  • Auto-closes when Claude exits
  • Coalescing wakeup mechanism — terminal output renders immediately without flooding the event loop
  • Zero-allocation render loop with direct buffer writes

Hex Editor (F4 / Enter on binary files)

  • Auto-detects binary files (null byte check in first 8 KB)
  • VS Code-style layout: offset | hex bytes | ASCII decode
  • 256 KB sliding buffer for arbitrarily large binaries
  • Cursor navigation with arrow keys, Home/End, PgUp/PgDn
  • Edit hex nibbles (0-9, A-F) or ASCII characters (Tab to switch sides)
  • Modifications stored as in-place overlay — only changed bytes in memory
  • Save writes only modified bytes (sorted sequential I/O)
  • Undo/redo (Ctrl+Z / Ctrl+Shift+Z) per-nibble
  • Search hex patterns (F7) with forward/backward, wrap-around
  • Go to offset (g) with hex address input
  • Selection with Shift+arrows, Ctrl+A select all, Ctrl+C copy
  • Data inspector: select 1/2/4/8 bytes to see decimal values in both endiannesses (u/i/float)
  • Cursor tracking: hex and ASCII panes mirror cursor position
  • Mouse click to position cursor in hex or ASCII pane
  • Unsaved changes prompt on close
  • Zero-allocation render loop with pre-computed lookup tables

Built-in Editor (F4 / Enter on text files)

  • Line-level piece table — only edited lines live in memory
  • Opens and navigates multi-GB files with no delay
  • Tree-sitter syntax highlighting for Rust, Java, Python, JavaScript/TypeScript, JSON, Go, C, Bash, TOML
  • Hybrid highlighting: files under 10 MB get a cached full parse (always accurate); larger files use a context-window approach
  • Search (F7) with forward/backward, case-sensitive toggle, wrap-around
  • Undo/redo (Ctrl+Z / Ctrl+Shift+Z): operation-based with minimal deltas, word-level grouping, 10K entry cap
  • Streaming byte-level search — seeks directly to cursor position, no full-file scan
  • Search results highlighted; Shift+F7 repeats last search
  • Text selection with Shift+arrow keys
  • Word navigation with Ctrl+Left/Right (Linux) or Option+Left/Right (Mac)
  • Mouse click to position cursor, mouse scroll
  • Ctrl+C to copy to system clipboard (OSC 52)
  • Ctrl+A to select all
  • Ctrl+K / Ctrl+Y to delete line
  • Ctrl+Up/Down or Alt+PageUp/PageDown to jump to top/bottom of file
  • F2 / Ctrl+S to save — uses byte-range copying for unmodified segments
  • Ctrl+G for go-to-line
  • Unsaved changes dialog on all exit paths (Esc, F10, Ctrl+Q)
  • Dynamic line number width (scales with file size)
  • Configurable cursor shape in theme
  • Shift+F4 opens $EDITOR instead

UI

  • Multiple themes: Far Manager (Classic) and QuestDB Dark — switch with Shift+F1
  • Centralized theme system — all colors in one file (src/theme.rs), including syntax highlighting and git status colors
  • Thread-local cached theme access for zero-overhead rendering
  • Consistent dialog styling with shared helpers (padding, separators, buttons, checkboxes)
  • Contextual footer — shows relevant key hints for the active panel/mode
  • Panel border titles with path (shortened with ~), git info, and CI status
  • Active/inactive panel focus with visual border and title color changes
  • Dialog drop shadows
  • Quit confirmation dialog (F10)
  • Panic hook that restores the terminal before printing errors
  • Cursor shape restored to terminal default on exit

Install

macOS

brew install questdb/middle-manager/mm

Linux

curl -fsSL https://mm.questdb.io | sh

Or install from a package:

# Debian / Ubuntu — download .deb from the latest release
sudo dpkg -i middle-manager_*.deb

# Fedora / RHEL — download .rpm from the latest release
sudo rpm -i middle-manager-*.rpm

Packages and tarballs for all platforms are available on the releases page.

Build from source

git clone https://github.com/questdb/middle-manager.git
cd middle-manager
cargo build --release
./target/release/middle-manager

Usage

middle-manager                       # Normal launch
middle-manager --session <name>      # Launch in a persistent tmux session
middle-manager --list-sessions       # List active middle-manager sessions
MM_DEBUG=1 middle-manager            # Enable debug logging to ~/.config/middle-manager/debug.log

Key Bindings

Panels

Key Action
Up / Down Navigate
Shift+Up / Shift+Down Toggle selection and move
Insert Toggle selection on current item
Left / Home Jump to top
Right / End Jump to bottom
Enter Open directory / open file (editor / hex / parquet)
Backspace Go to parent directory
Tab Switch panel forward (cycles through CI/terminal panels)
Shift+Tab Switch panel backward
Ctrl+F Fuzzy file search (opens in editor)
Ctrl+G Go to path (with tab completion)
Ctrl+S Search in files (ripgrep-powered)
Ctrl+C Copy filename to clipboard
Ctrl+O Toggle shell panel
Ctrl+P Copy full path to clipboard
F2 Toggle CI panel
F3 Calculate directory / selection size
F4 Open file (editor / hex / parquet)
Shift+F4 Edit file ($EDITOR)
F5 Copy (operates on selection if active)
Shift+F5 Create archive (tar.zst/gz/xz/zip)
F6 Move (operates on selection if active)
Shift+F6 Rename
F7 Create directory
Shift+F7 Create (touch) file
F8 Delete (operates on selection if active)
F9 Cycle sort
F10 Quit (with confirmation)
F11 Open PR in browser
Ctrl+T Open Connectivity dialog (remote connections)
Ctrl+Y Open session manager (tmux sessions)
F12 Toggle Claude Code panel (maximized, opposite side)
Shift+F1 Open settings (themes)
Type chars Quick search

CI Panel

Key Action
Up / Down Navigate tree
PageUp / PageDown Page through tree
Home / End Jump to top / bottom
Right Expand check (load steps)
Left Collapse check / jump to parent
Enter Expand/collapse check, or download step log
Ctrl+E Extract all test failures to Markdown file
o Open check in browser
Alt+Up / Alt+Down Resize panel split
Alt+Enter Maximize / restore panel
Tab / Shift+Tab Switch panel forward / backward
F2 Close CI panel
Mouse click Select item and focus panel

Shell Panel

Key Action
All keys (incl. Tab) Forwarded to the shell
Mouse drag Select text
Double-click / Triple-click Select word / line
Ctrl+C Copy selection (or SIGINT if none)
Scroll / Trackpad Scroll through scrollback buffer
Alt+Up / Alt+Down Resize panel split
Alt+Enter Maximize / restore panel
F1 Switch focus to file panel
Ctrl+O Close shell panel
F10 Quit (with confirmation)

Claude Code Panel

Key Action
All keys (incl. Tab) Forwarded to Claude Code
Mouse drag Select text
Double-click / Triple-click Select word / line
Ctrl+C Copy selection (or SIGINT if none)
Scroll / Trackpad Scroll through scrollback buffer
F5 Open file:line reference in editor
F1 Switch focus to file panel
F12 Close Claude Code panel
F10 Quit (with confirmation)

Search Results Panel

Key Action
Up / Down Navigate results
PageUp / PageDown Page through results
Home / End Jump to top / bottom
Enter Open file in editor at match line
Right Expand file matches
Left Collapse file / jump to parent from match
Tab / Shift+Tab Switch panel
Esc Close search results
Scroll / Trackpad Scroll results
Mouse click Select result and focus panel
F10 Quit (with confirmation)

Connectivity Dialog (Ctrl+T)

Key Action
Alt+Left / Alt+Right Cycle protocol (SSH/SFTP/SMB/WebDAV/S3/GCS/Azure/NFS)
Tab Cycle protocol (SSH/SFTP) or switch fields (others)
Enter Connect
F2 Save connection for quick access
Del Remove saved connection
Esc Close

SSH / SFTP Panel

Key Action
All keys (incl. Tab) Forwarded to SSH session
Scroll / Trackpad Scroll through scrollback buffer
Alt+Up / Alt+Down Resize panel split
Alt+Enter Maximize / restore panel
F1 Switch focus to file panel
Ctrl+T Close SSH panel / disconnect SFTP
F10 Quit (with confirmation)

Session Manager (Ctrl+Y)

Key Action
Up / Down Navigate sessions
Enter Attach to selected session
n Create new session
d / Delete Kill selected session
Esc Close

Dialog Inputs (all dialogs)

Key Action
Shift+Left/Right Select text
Shift+Home/End Select to start/end
Ctrl+A Select all
Ctrl+C Copy selection to clipboard
Ctrl+X Cut selection
Ctrl+Z Undo
Ctrl+Shift+Z Redo
Delete Delete forward
Mouse click Focus input field

Hex Editor

Key Action
Arrow keys Move cursor
Home / End Start / end of row
Ctrl+Home / Ctrl+End Start / end of file
PgUp / PgDn Page through file
0-9, A-F Edit hex nibble
Tab Switch hex / ASCII editing
Shift+arrows Select bytes
Ctrl+A Select all
Ctrl+C Copy selection
g / Ctrl+G Go to offset (hex)
F7 / Ctrl+F Search hex pattern
n / N Find next / previous
Ctrl+S / F2 Save
Ctrl+Z / Ctrl+Shift+Z Undo / Redo
Mouse click Position cursor (hex or ASCII pane)
q / Esc Close (prompts if unsaved)
F10 Quit (with confirmation)

Parquet Viewer

Key Action
Up / Down Navigate tree / scroll table
Right / Enter Expand node
Left Collapse node / jump to parent
PgUp / PgDn Page through tree or table
Home / End Jump to top / bottom
Tab Toggle tree / table view
g Go to row
q / Esc Close

Editor

Key Action
Arrow keys Move cursor
Ctrl+Left / Right Word skip (Linux)
Option+Left / Right Word skip (Mac)
Home / End Line start / end
Ctrl+Up / Ctrl+Down File start / end
Alt+PageUp / Alt+PageDown File start / end (Mac: Fn+Opt+Up/Down)
PgUp / PgDn Page up / down
Shift+arrows Select text
Ctrl+A Select all
Ctrl+C Copy selection to clipboard
Ctrl+Z Undo
Ctrl+Shift+Z Redo
Ctrl+K / Ctrl+Y Delete line
Ctrl+G Go to line:col
Ctrl+F / F7 Search
Shift+F7 Find next (repeat last search)
F2 / Ctrl+S Save
Esc Close editor (prompts if unsaved)
Mouse click Position cursor
Mouse scroll Scroll

Architecture

src/
  main.rs           Terminal setup, event loop, panic hook
  app.rs            App state machine, action dispatch, all modes
  action.rs         Action enum (every possible user intent)
  event.rs          Background thread event polling, coalescing wakeup mechanism
  terminal.rs       Embedded terminal: PTY lifecycle, key encoding (shell + Claude)
  parquet_viewer.rs Parquet file viewer: metadata tree, column stats, table data decoding
  file_search.rs    File content search: ripgrep engine (ignore + grep-searcher), streaming results
  text_input.rs     Reusable text input: selection, undo/redo, cut/copy, horizontal scroll
  ci.rs             CI panel: check/step fetching, log download, failure extraction
  remote_fs.rs      RemoteFs trait: common interface for all remote protocols
  sftp.rs           SFTP connection (shells out to sftp CLI)
  smb_client.rs     SMB connection (shells out to smbclient)
  webdav.rs         WebDAV connection (shells out to curl + quick-xml)
  s3.rs             S3 connection (shells out to aws s3api)
  gcs.rs            GCS connection (shells out to gcloud storage)
  azure_blob.rs     Azure Blob connection (shells out to az CLI)
  nfs_client.rs     NFS connection (mount + local FS delegation)
  ssh.rs            SSH host config, ~/.ssh/config parsing
  session.rs        tmux session management
  saved_connections.rs  Saved connection store (JSON)
  debug_log.rs      Debug logging (MM_DEBUG=1)
  state.rs          Persistent state (JSON, ~/.config/middle-manager/)
  syntax.rs         Tree-sitter syntax highlighting with hybrid caching
  theme.rs          Centralized color scheme (panel, editor, git, syntax, dialog)
  editor.rs         Built-in editor with line-level piece table and streaming search
  hex_viewer.rs     Hex editor with sliding buffer, modifications overlay, undo/redo, search
  watcher.rs        Filesystem watcher (kqueue/inotify via notify crate)
  panel/
    mod.rs          Panel state, directory reading, navigation, multi-file selection
    entry.rs        File entry metadata and formatting
    sort.rs         Sort by name/size/date
    git.rs          Git status cache, branch/ahead-behind, async PR queries
    github.rs       GitHub PR info via gh CLI
  vt/
    mod.rs          Custom VT terminal emulator (replaces vt100 crate)
    parser.rs       ANSI/VT escape sequence parser (CSI, OSC, DEC private modes)
    screen.rs       Terminal screen state: cursor, scrollback, resize
    grid.rs         Cell grid with O(1) scroll via ring buffer
    cell.rs         Cell storage with attributes
    attrs.rs        SGR text attributes and color handling
    color.rs        Color types (16, 256, RGB)
  fs_ops/
    mod.rs          Copy, move, delete, mkdir, rename (with nested path support)
    archive.rs      Archive creation (tar.zst, tar.gz, tar.xz, zip) with progress
  ui/
    mod.rs          Top-level layout, mode routing, split CI panels
    panel_view.rs   Panel table rendering with git status column and tree title
    ci_view.rs      CI panel tree rendering with expand/collapse
    header.rs       Header margin
    terminal_view.rs  Terminal panel rendering (VT screen to ratatui spans)
    file_search_dialog.rs  Search-in-files dialog (path, term, filter, regex)
    search_results_view.rs  Search results tree view (files + matching lines)
    footer.rs       Contextual function key hints (normal / CI / terminal mode)
    dialog.rs       Simple dialogs (delete, rename) with cursor navigation
    dialog_helpers.rs  Shared dialog rendering (frame, buttons, checkboxes, separators)
    mkdir_dialog.rs Far Manager-style mkdir dialog with "process multiple names"
    copy_dialog.rs  Far Manager-style copy/move dialog
    search_dialog.rs  Editor search dialog (query, direction, case sensitivity)
    editor_view.rs  Editor rendering with syntax highlighting and selection
    hex_view.rs     Hex editor rendering with zero-allocation lookup tables
    parquet_view.rs Parquet viewer rendering (tree + table modes)
    archive_dialog.rs  Archive format picker dialog
    shadow.rs       Transparent dialog drop shadows

The editor uses a line-level piece table: the file stays on disk, split into segments. Unmodified segments reference the original file by byte offset. Edited lines are stored in memory. On save, unmodified segments are copied as byte ranges (fast), and only edited segments are written from memory. This makes editing a 10 GB file with a few changes practical.

The search engine streams raw file bytes in 4 MB chunks, using the sparse line index to seek directly to the cursor position. Forward search reads sequentially; backward search reads in reverse chunks. No per-line file I/O, no full-file scan.

The CI panel fetches data asynchronously — check lists, step details, and log downloads all run in background threads. The UI shows animated spinners and never blocks. GitHub Actions and Azure DevOps are both supported, with per-job log downloads (no full-run zip).

Roadmap

This project is in early development. Things we're considering:

  • Undo/redo in editor
  • Hex editor with search, undo/redo, data inspector
  • File permissions dialog
  • Configurable key bindings
  • Multiple color schemes
  • Archive browsing (tar, zip)
  • Built-in terminal panel
  • FTP/SFTP support
  • Plugin system

We'd love to hear what you want. Open an issue to request features, report bugs, or share ideas.

Contributing

Contributions are welcome! Please open an issue to discuss before sending large PRs.

License

Licensed under the Apache License 2.0.

About

A dual-panel file manager TUI inspired by Far Manager, built in Rust

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors