# bmrk — Bookmark Manager and Directory Navigator
**A fast, compact TUI for directory navigation and bookmark management.**
[](LICENSE)
[](https://crates.io/crates/bmrk)
---
## 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 — 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:**
```bash
cargo install bmrk
```
**From source:**
```bash
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:
```powershell
notepad $PROFILE
```
If the file does not exist yet, create it first:
```powershell
New-Item -ItemType File -Force $PROFILE
```
3. Add the following line to your profile:
```powershell
. "C:\path\to\bmrk\bm.ps1"
```
4. Reload the profile:
```powershell
. $PROFILE
```
5. Test:
```powershell
bm --version
bm
```
---
#### `bm.sh` — bash, zsh (and fish via comment)
**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. The file's header comment also contains a ready-to-use fish function for
`~/.config/fish/functions/bm.fish`.
**Installation — bash:**
1. Copy the `bmrk` binary to a directory on your PATH:
```bash
cp target/release/bmrk ~/.local/bin/
```
2. Source the wrapper from your shell config:
```bash
echo 'source /path/to/bmrk/bm.sh' >> ~/.bashrc
```
3. Reload and test:
```bash
source ~/.bashrc
bm --version
bm
```
**Installation — zsh:**
Same steps as bash, but add to `~/.zshrc` instead of `~/.bashrc`.
**Installation — fish:**
Fish uses its own function-file format and cannot source `bm.sh` directly. Instead, copy the fish
function from the comment block at the top of `bm.sh` into a new file:
```
~/.config/fish/functions/bm.fish
```
Fish picks up functions in that directory automatically — no reload step needed. Test with:
```bash
bm --version
bm
```
---
## Usage
```bash
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 - # 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)
| `j` / `↓` | Move down |
| `k` / `↑` | Move up |
| `l` / `→` | Expand directory |
| `h` / `←` | Collapse directory; go to parent if already collapsed |
| `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 |
| `m` | Create bookmark |
| `'` | Select bookmark |
| `d` | Disk selection |
---
## 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.
```toml
[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>)
[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]
go_to_parent = ["u"]
go_back = ["Backspace"]
quit = ["q"]
exit = ["Esc"]
search = ["/"]
create_bookmark = ["m"]
select_bookmark = ["'"]
select_disk = ["d"]
```
---
## 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 path** → `cd` 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)
| `bm` (TUI → `q`) | `/selected/path` | `cd` there |
| `bm myproject` | `/bookmarked/path` | `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` | `bmrk x.y.z` | Print it (passthrough)|
| `bm` (TUI → Esc) | _(empty)_ | Do nothing |
---
## License
MIT — see [LICENSE](LICENSE).
See [CHANGELOG.md](CHANGELOG.md) for version history.