A terminal file manager (TUI) written in Rust using ratatui + crossterm.
sb (Shell Buddy) is a keyboard-driven explorer focused on fast local navigation with optional integrations for previews, archive handling, searching, remote mounts, and lightweight Git workflows.
- In-TUI Git workflow — diff preview → status review → commit → push → optional tag, all without leaving the file manager (
G) - Inline path filters — type
^prefix,suffix$, or~containsdirectly in the path bar to live-filter the listing (Tab) - Integration manager with one-key install — see which optional tools are missing and install them via Homebrew without leaving the TUI (
I) - Age encryption — protect or decrypt
.agefiles in-place with a single keypress (p) - Per-file notes — attach notes to any file, stored in a hidden
.sbfile per directory (Ctrl+n) - tmux-aware splits —
iopens a shell + preview pane;Eopens a shell + editor pane (falls back tozellijwhen tmux isn't installed) - Clipboard edit —
Ctrl+eopens the current clipboard contents in$EDITORfor quick manipulation - CLI list/tree modes —
sb -l,sb -t,sb -l2produce TUI-consistent column output;sb <file>skips the TUI and opens with the best available viewer
Build and Run
cargo build
cargo runRelease build:
cargo build --releaseRelease binary path:
target/release/sb
List mode examples:
# Current directory
sb -l
# Include hidden entries
sb -a
sb -la
# Recursive display size + percent share columns
sb -l --total-size
# Full tree output
sb -t
# Tree output limited to depth 2
sb -l2
sb -l 2
# Path can appear before or after --total-size
sb -la /var/log --total-size
sb --total-size -l /var/log
# Open a file directly with the best available previewer/viewer
sb README.md
sb diagram.mmd
# Open a file with pager mode enabled
sb -l README.md
# Open a file in $EDITOR (fallback: nano)
sb -e README.mdCLI List Mode
-l [PATH]: list directory entries and exit.-a [PATH]: same as-l, but includes hidden files.-la [PATH]: same as-l, but includes hidden files.-e [FILE]: open file in$EDITOR(fallback:nano) and exit.-t [PATH]: tree-list recursively (full depth) and exit.-lN [PATH]/-l N [PATH]: tree-list to depthNand exit.--total-size: when used with-l,-a, or-la, shows recursive display size for each entry and a%column with that entry's share of the listed total.
Notes:
PATHis optional and can be placed after-l/-a/-laor after--total-size.- The list output reuses the file manager's auto-calculated owner/group column widths for consistent alignment.
- When invoked as
sb <FILE>, the app skips the TUI and opens the file directly with best-available viewer output (no pager). - When invoked as
sb -l <FILE>, direct file mode uses pager-enabled output.
Installation
cargo install shell-buddybrew install hjelev/tap/sbgit clone https://github.com/hjelev/sb.git
cd sb
cargo install --path .Prebuilt binaries and the auto-installer script are available in GitHub Releases. Use the installer there if you want the fastest setup without building from source.
Core Controls
q/Esc: quit- ```: toggle modes
Enter/Right: open entry / preview fileLeft/Backspace: go to parent / leave mounted view- mouse left-click: select clicked entry
- mouse double left-click: open clicked entry (same behavior as
Right) - mouse right-click: go to parent / leave mounted view (same behavior as
Left) Up/Down/PageUp/PageDown/Home/End: navigationSpace: mark/unmark current entry*: toggle all markscorF5: copy to internal clipboardCtrl+c: copy selected full path(s) to system clipboardCtrl+e: edit system clipboard text in$EDITORv: pastem: move (cut+paste behavior) from internal clipboardd: delete (with confirmation)x: toggle executable bit on selected file(s)p: protect/unprotect file withage(.age)F2orr: rename (or bulk rename withvidirwhen multiple are marked)eorF4: open in$EDITOR(orhexeditfor binary if available)E: split tmux (or zellij) session with shell on the left and$EDITORon the right (Ctrl+eis clipboard edit)n: new file or folder (folder starts with/)Ctrl+n: add/edit note for selected item(s)t: open~/.todoin$EDITOR(creates it if missing)Z: archive create/extract flowC: compare marked file vs cursor file withdeltaG: Git commit workflow with diff preview,git status, commit/push, and optional post-push tag creationo: open with system GUI opener (openon macOS,xdg-open/gio openelsewhere)f: open Search overlay (filename search; uses built-in search iffzfis missing)g: content search (rg, optionalfzfhandoff; falls back to built-in Search content mode whenrgis missing);: open command prompt, run shell command, then wait for keypress before returning to TUIS: SSH/rclone remote pickeri: split shell (left) +lesspreview (right 30%)I: integrations panelb: bookmarks panelCtrl+z: drop to interactive shell in current directory/(in browsing): quick-filter the current folder listing (not available in dual panel mode)Tab(in browsing): edit current path inline; supports/path/^prefix,/path/suffix$, and/path/~containsfiltersTab/Shift+Tabin Help/Search/Bookmarks/Remote Mounts/Sorting/Integrations: cycle tabs forward/backwards: toggle folder size calculation in listingCtrl+s: open sort mode menu+: expand selected/marked non-empty folder(s) by one tree level-: contract selected/marked folder(s) by one tree level- quick
++: expand selected/marked non-empty folder(s) to max depth - quick
--: collapse all opened folders in tree view 0-9: jump to bookmark (SB_BOOKMARK_0..9).: toggle hidden files~: jump to homeh: help overlay
Search Overlay Functions
When Search is open (f or fallback from g):
Up/Down: move result selectionEnter: open selected matchEsc: close SearchCtrl+t: toggle scope betweenFilenameandContent- Query supports regex forms:
re:patternor/pattern/i - Content-mode results render as
path:linewith highlighted matching snippets - Content-mode scanning runs asynchronously (UI remains responsive)
Content limits editor (content scope):
Ctrl+l: open/close limits editorUp/Down: select which limit to editLeft/Rightor-/+: decrease/increase selected limitShift+ adjust: 10x stepr: reset limits from environment/default valuesEnter/Esc: close limits editor
Path Editing and Filters
Press Tab while browsing to edit the current path in place.
- Enter a directory path and press
Enterto jump there. - Add a suffix filter to keep the current directory but narrow visible entries:
/some/path/^foo: names starting withfoo/some/path/bar$: names ending withbar/some/path/~baz: names containingbaz
Escfrom path-edit mode clears the active filter and returns to browsing.
The active filter remains visible in the header until you change directories.
Git Workflow
Press G in a Git working tree to:
- preview the current diff (
deltaside-by-side when available) - view
git status - confirm whether to continue
- enter a commit message inside the TUI
- auto-run
git add --all,git commit, andgit push origin HEAD - optionally press
timmediately after a successful push to create and push a tag
When tagging, the tag input box is prefilled from the latest reachable Git tag when one exists.
Integrations
Required behavior:
less: file viewing fallback$EDITOR: file editing command (defaults tonanoif unset)
Optional integrations (auto-detected, toggle in I panel):
-
In the Integrations panel, pressing
Enteron a missing integration asks for confirmation and can install with Homebrew when available (macOS and Linux/Homebrew). -
Press
/inside the Integrations panel to search/filter the integration list. -
VCS:
git -
Viewers/previews:
bat,glow,mmdflux,jnv,csvlens,hexyl,chafa,viu,sox,pdftotext,asciinema,links -
Diff/edit helpers:
delta,hexedit,vidir,tmux,zellij -
Archives:
zip/unzip,tar,7zfamily (7z/7zz/7zr),rar/unrar,fuse-zip,archivemount -
Security:
age -
Remote mounts:
sshfs,rclone -
Search:
rg,fzf -
Clipboard backends:
wl-copy/wl-paste,xclip,xsel,pbcopy/pbpaste
Remote picker (S) also lists existing local mounted folders discovered under:
/media/$USER/run/media/$USER/mnt/run/user/$UID/gvfs
If an optional tool is not available, the feature is skipped or falls back gracefully.
Environment Notes
NERD_FONT_ACTIVE=1: enable Nerd Font iconsNO_COLOR=1: disable file name colors (modifiers like bold/dim still apply)TERMINAL_ICONS=0: hide all file icons (Nerd Font glyphs and emoji)EDITOR: editor command used bye/F4,E,Ctrl+e, andtSB_BOOKMARK_0...SB_BOOKMARK_9: bookmark directoriesSB_SEARCH_CONTENT_MAX_FILES: built-in Search content-mode max files scanned (default:20000)SB_SEARCH_CONTENT_MAX_HITS: built-in Search content-mode max matches returned (default:2000)SB_SEARCH_CONTENT_MAX_FILE_BYTES: built-in Search content-mode per-file byte cap (default:2097152/ 2 MiB)
Persistent config (~/.config/sb/config, key = value) also supports:
disable_clock = true: replace the header clock with a disk-usage pill- Nerd Fonts and file name colors can be toggled live from the Themes menu (the choice is persisted here alongside the active theme and view mode)
Shell Integration
To enable automatic directory change on exit, add the following function to your shell configuration file (e.g., ~/.bashrc, ~/.zshrc):
sb() {
"$HOME/.cargo/bin/sb" "$@"
if [ -f /tmp/sb_path ]
then
cd "$(cat /tmp/sb_path)"
rm -i -f /tmp/sb_path
fi
}After adding the function, reload your shell configuration:
source ~/.bashrc # or source ~/.zshrcProject Structure
Current code layout is modular:
src/main.rs: app state, event loop, orchestration, and top-level workflowssrc/app_input.rs: input editing helperssrc/app_meta.rs: permissions/owner/group metadata helperssrc/app_render_cache.rs: entry render-cache generationsrc/app_search.rs: built-in search and path-filter matching helperssrc/app_files.rs: file-type classification helperssrc/app_sizes.rs: folder-size and aggregate-size scanning helperssrc/app_git.rs: Git status/background cache helperssrc/app_archive.rs: archive mount and preview lifecycle helperssrc/integration/: integration catalog, probing, rows, and install flowsrc/ui/: CLI output, icons, panels, search spans, and status renderingsrc/util/: shared formatting helpersCargo.toml: dependencies and release profile settings
Dependencies
From Cargo.toml:
ratatui(UI)crossterm(terminal events/raw mode)chrono(timestamps)devicons(file icons)hostname(header prompt)users(owner metadata)clap(present as dependency)regex(search regex mode)rayon(parallel entry render-cache build)unicode-width(display-width-aware list-mode alignment)











