bmrk

A fast TUI for directory navigation and bookmark management


Keywords
bookmarks, cli, directory, navigation, tui, command-line-tool, cross-platform, crossterm, directory-navigation, file-navigation, fuzzy-finder, fzf, productivity, ratatui, rust, shell, terminal
License
MIT

Documentation

bmrk — Bookmark Manager and Directory Navigator

A fast, compact TUI for directory navigation and bookmark management.

License Crates.io CI


What is bmrk?

bmrk is a compact inline TUI that fits in 8 rows and never takes over your terminal screen. Navigate directories, manage bookmarks, search for folders and files — all from the keyboard.

The binary is bmrk. The shell wrapper bm wraps it and handles cd automatically — because a process cannot change its parent shell's directory, a thin wrapper is required (the same approach used by fzf, zoxide, and autojump).


Features

  • Compact inline mode — 8 rows, no fullscreen takeover, terminal fully restored on exit
  • Bookmarks — save and jump to favorite directories; bm myproject navigates instantly
  • Interactive tree view — directory navigation with expand/collapse
  • Fuzzy search — fast asynchronous search with intelligent matching
  • Disk selection — browse and switch between all drives/mount points (d key)
  • Mouse support — click, double-click, scroll
  • Customizable — TOML configuration with theme presets and custom colors

Installation

Step 1 — Install the bmrk binary

From crates.io:

cargo install bmrk

From source:

git clone https://github.com/holgertkey/bmrk.git
cd bmrk
cargo build --release

The binary is at target/release/bmrk (Linux/macOS) or target\release\bmrk.exe (Windows).


Step 2 — Set up the bm wrapper

The repository includes three ready-made wrapper files. Each one integrates bmrk with a specific shell so that cd works correctly. Pick the file that matches your environment.


bm.bat — Windows CMD

What it does. bm.bat is a batch script that runs bmrk.exe and redirects its stdout to a temporary file. If the captured output is a valid directory path, it calls cd /d to change the current session's directory. Non-directory output (help text, version, bookmark lists) is printed as-is. The previous directory is saved in %BMRK_PREV_DIR% so that bm - can return to it. Flags that do not trigger navigation (-h, --help, -v, --version, -l, --list, -a, --add, -c, -d, --del) are passed straight through to bmrk.exe.

Installation:

  1. Copy bmrk.exe and bm.bat to the same directory that is on your PATH (e.g. C:\Users\<YourName>\bin\).

  2. If that directory is not on your PATH yet, add it and open a new CMD window:

    setx PATH "%PATH%;C:\Users\<YourName>\bin"
    
  3. Test:

    bm --version
    bm
    

bm.ps1 — Windows PowerShell

What it does. bm.ps1 defines a bm function for PowerShell. It runs bmrk.exe, captures stdout to a temporary file, and calls Set-Location if the result is a valid directory path. The previous directory is stored in $env:BMRK_PREV_DIR for bm - support. Pass-through flags (-h, --help, -v, --version, -l, --list, -a, --add, -c, -d, --del) are forwarded directly to bmrk.exe without any cd logic. Compatible with Windows PowerShell 5.1 and PowerShell 7+.

Installation:

  1. Copy bmrk.exe to a directory on your PATH (e.g. C:\Users\<YourName>\bin\).

  2. Open your PowerShell profile for editing:

    notepad $PROFILE

    If the file does not exist yet, create it first:

    New-Item -ItemType File -Force $PROFILE
  3. Add the following line to your profile:

    . "C:\path\to\bmrk\bm.ps1"
  4. Reload the profile:

    . $PROFILE
  5. Test:

    bm --version
    bm

bm.sh — bash, zsh

What it does. bm.sh defines a bm function for POSIX-compatible shells (bash and zsh). It runs bmrk via command substitution, captures stdout, and calls cd when the result is a valid directory. The previous directory is stored in $BMRK_PREV_DIR for bm - support. Any output that is not a directory path (help text, version, bookmark list) is echoed to the terminal unchanged. For fish, use bm.fish instead (see below).

Installation — bash:

  1. Copy the bmrk binary to a directory on your PATH:

    cp target/release/bmrk ~/.local/bin/
    # or: sudo cp target/release/bmrk /usr/local/bin/
  2. Source the wrapper from your shell config:

    echo 'source /path/to/bmrk/bm.sh' >> ~/.bashrc
  3. Reload and test:

    source ~/.bashrc
    bm --version
    bm

Installation — zsh:

Same steps as bash, but add to ~/.zshrc instead of ~/.bashrc.


bm.fish — fish

What it does. bm.fish defines a bm function for fish. Fish uses its own function-file format and cannot source bm.sh directly, so this is a separate file. It runs bmrk, captures stdout, and calls cd when the result is a valid directory. The previous directory is stored in $BMRK_PREV_DIR for bm - support. Any output that is not a directory path (help text, version, bookmark list) is echoed to the terminal unchanged.

Installation:

  1. Copy the bmrk binary to a directory on your PATH:

    cp target/release/bmrk ~/.local/bin/
    # or: sudo cp target/release/bmrk /usr/local/bin/
  2. Copy or symlink bm.fish into fish's functions directory:

    cp /path/to/bmrk/bm.fish ~/.config/fish/functions/bm.fish
    # or, to keep it in sync with the repo:
    ln -s /path/to/bmrk/bm.fish ~/.config/fish/functions/bm.fish
  3. Fish picks up functions in that directory automatically — no reload step needed. Test with:

    bm --version
    bm

Usage

bm                          # Open interactive TUI (compact, 8 rows)
bm /path/to/dir             # Open TUI at specific directory
bm myproject                # Jump to bookmark (cd directly, no TUI)
bm myproject/src/app        # Jump into a sub-directory of a bookmark
bm -                        # Return to previous directory

# Bookmark management
bm -l                       # List all bookmarks
bm -a work                  # Save current directory as 'work'
bm -a work /some/path       # Save specific path as 'work'
bm -d work                  # Remove bookmark 'work'

bm -v / --version           # Print version
bm -h / --help              # Print help

Keyboard shortcuts (inside TUI)

Key Action
j / Move down
k / Move up
l / Expand directory
h / Collapse directory; go to parent once collapsed (from the root row, always goes to parent)
u Go to parent directory
Backspace Go back (undo last navigation)
Enter Go into directory (change root)
q Exit and cd to selected dir
Esc Exit without cd
/ Search
Tab Quick jump (type a folder name to jump to it)
m Create bookmark
' Select bookmark
d Disk selection
c Copy selected item's path to clipboard

Configuration

Config file is created automatically on first run:

  • Linux/macOS: ~/.config/bmrk/config.toml
  • Windows: %APPDATA%\bmrk\config.toml

Bookmarks are stored as bookmarks.json in the same directory. A background-built directory index cache lives alongside them as dir_index.txt — it's a performance optimization, not user data, so it's safe to delete to force a rebuild.

[appearance]
theme = "default"       # default, gruvbox, nord, tokyonight, dracula, obsidian
max_name_length = 80    # Truncate long names in the middle (0 = disabled)
icons = "unicode"       # "unicode" (▼▶) or "ascii" (v>)
show_cursor_path = true # Show the selected item's full path in the header (Tab mode too)

[appearance.colors]
# header_path_color = "cyan"       # Path/label in the header row
# header_hints_color = "darkgray"  # Key hints in the header row
# directory_color = "gray"         # Directory names; also the header icon (▼)
# See docs/configuration.md for all available color fields

[behavior]
show_hidden = true
follow_symlinks = true
mouse_scroll_lines = 1

[keybindings]
search = ["/"]
create_bookmark = ["m"]
select_bookmark = ["'"]
select_disk = ["d"]
go_to_parent = ["u"]
copy_path = ["c"]
go_back = ["Backspace"]
quit = ["q"]
exit = ["Esc"]

[index]
enabled = true       # Background directory index accelerating Tab/`/` under `roots`
refresh_hours = 24   # Rebuild once the cached index is older than this
# roots = ["/home/username"]                       # Defaults to the home directory
# ignore_dirs = ["node_modules", "target", ".git"] # Replaces the default skip-list, not merged

How the wrapper works

bmrk writes its TUI to stderr (visible in the terminal) and the selected directory path to stdout. The wrapper captures stdout via a temp file (CMD: set /p; PowerShell/bash: $t):

  • If captured output is a valid directory pathcd to it (saves previous dir for bm -)
  • If output is empty (Esc pressed) → do nothing
  • Otherwise → print the output as-is (help, version, bookmark list)
Command bmrk stdout Wrapper action
bm (TUI → q) /selected/path cd there
bm myproject /bookmarked/path cd there
bm myproject/sub /bookmarked/path/sub cd there
bm - (no bmrk call) cd to previous dir
bm -l Bookmarks: … (text) Print it (passthrough)
bm -a work Bookmark 'work' added: … Print it (passthrough)
bm -d work Bookmark 'work' removed Print it (passthrough)
bm --help Help text Print it (passthrough)
bm -v Version + build info Print it (passthrough)
bm (TUI → Esc) (empty) Do nothing

License

MIT — see LICENSE.

See CHANGELOG.md for version history.