Interactive search tool for both file content and Git objects, powered by ripgrep, fzf, and optional preview tools like bat/delta.
Compatible with: bash, zsh
- Live search - Results update as you type
- Path + content matching - Searches filenames/paths and file contents by default
- Preview - See file contents with syntax highlighting
- Jump to line - Opens your editor at the exact match
- Multi-select - Open multiple files at once
- Git mode - Search commits, branches, tags, reflog, and stashes in one view
- Diff pager fallback - Uses
delta, thenbat, thencat
# Old way
$ grep -r "searchTerm" .
$ cd path/to/file
$ vim file.js
# ... search again ...
# With umm
$ umm
# type, see results, hit enter
# opens at exact lineRequired:
ripgrep(rg) - Fast file searchfzf- Interactive fuzzy finder- A text editor (set via
$EDITOR, defaults tonvim)
Required for Git mode:
git- Repository search and previews
Recommended:
delta- Recommended for the best Git diff preview (delta->bat->cat)bat- Syntax highlighting in file previews (falls back tosed+ line numbers if unavailable)
# macOS
brew install ripgrep fzf bat nvim
# Ubuntu/Debian
apt install ripgrep fzf bat neovim
# Arch
pacman -S ripgrep fzf bat neovimInstall:
# Clone
git clone https://github.com/difof/umm.git
# For zsh (includes tab completions)
echo 'source /path/to/umm/umm.sh' >> ~/.zshrc
source ~/.zshrc
# For bash
echo 'source /path/to/umm/umm.sh' >> ~/.bashrc
source ~/.bashrcumm # Interactive search in current directory
umm ~/projects # Search in specific directory
umm -p "function" # Start with pattern
umm -p "TODO" ~/projects # Search with pattern in directory
umm --no-filename -p "TODO" # Search content only (disable path matching)
umm -e "*.log" -e "test" # Exclude patterns (gitignore-style globs)
umm -a # Search all files (ignore .gitignore, include hidden)
umm -p "error" -n # Open first match (no UI)
umm -d 3 # Limit search depth
umm -g # Search git objects (commits/branches/tags/reflog/stashes)
umm -g -p "fix" # Start git mode with pattern
umm --git ~/projects/repo # Git search in specific repositoryumm uses ripgrep's smart defaults:
-
Searches content and paths - Query matches file contents and filenames/paths by default
-
Disable path matching with
--no-filename- Restrict search to content (or git objects) only -
Respects
.gitignore- Automatically excludes files/directories listed in.gitignore -
Excludes
.gitdirectory - Never searches inside.gitby default -
Excludes hidden files - Files/directories starting with
.are skipped (except.gitignoreitself) -
Skips binary files - Binary files are automatically detected and excluded
To search everything (override all defaults), use the --all flag.
-p, --pattern REGEXP- Initial search pattern-e, --exclude PATTERN- Exclude file/directory pattern (can be used multiple times)-a, --all- Search all files including .gitignore'd and hidden files--no-filename- Disable filename/path matching-g, --git- Search Git objects in a unified list-n, --noui- Non-interactive mode, open first match directly-d, --max-depth N- Maximum search depth-h, --help- Show help-v, --version- Show version
When -g/--git is enabled, umm shows a single searchable list with Git type-prefixed entries:
commit:recent commit history (up to 1000 entries)branch:local and remote branchestag:tags with subjectsreflog:recent reflog entries (up to 100)stash:stash entriesfile:tracked repository files (enabled by default; disable with--no-filename)
Preview is context-aware by type and uses this diff rendering fallback chain:
Selection output strips the type prefix, so results are easy to pipe:
umm -g -p "commit:" | cut -d' ' -f1 | xargs git show
umm -g -p "branch:" | sed 's/^[* ]*//' | xargs git checkoutCommon (file mode and Git mode):
Ctrl+G/Ctrl+B- Jump to bottom/top of result listAlt+G/Alt+B- Jump to top/bottom of previewShift+Up/Shift+Down- Scroll preview one line up/downAlt+U/Alt+D- Scroll preview half-page up/downCtrl+U/Ctrl+D- Scroll result list half-page up/down
Mode-specific:
- File mode:
Tab/Shift+Tabtoggle multi-select and move - Git mode:
Ctrl+/toggle preview pane
Exclude files or directories using gitignore-style glob patterns:
umm -e "*.log" # Exclude all .log files
umm -e "test" -e "vendor" # Exclude multiple patterns
umm -e "**/node_modules/**" # Exclude nested directories
umm -e "test\ dir" # Escape spaces in patternsBy default, umm respects .gitignore and excludes hidden files (via ripgrep's defaults). Use --all to override:
umm -a # Search everything (ignore .gitignore, include hidden)
umm -a -e ".git" # Search all but exclude .git directory
umm -a -p "SECRET" ~/project # Find sensitive data in all filesumm respects the $EDITOR environment variable and automatically uses the correct syntax for different editors:
# Use your preferred editor
EDITOR=vim umm # Opens with: vim +linenum file
EDITOR=code umm # Opens with: code --goto file:linenum
EDITOR=nano umm # Opens with: nano +linenum file
EDITOR=micro umm # Opens with: micro +linenum file
# Set default in your shell config
export EDITOR=nvim # Add to ~/.bashrc or ~/.zshrcSupported editors: vim, vi, nvim, nano, micro, emacs, code (VSCode), cursor, subl (Sublime Text), and more.
The key to instant updates is fzf's --disabled mode:
fzf --disabled \
--bind "change:reload:sleep 0.05; rg {q} $root"--disabled- fzf delegates ALL search to ripgrep (no local filtering)change:reload:- Every keystroke triggers new ripgrep searchsleep 0.05- Debounce to prevent system overload{q}- Current query from fzf input
Without --disabled, fzf would only filter pre-loaded results. This enables true live search.
bat --color=always \
--highlight-line {2} \
--line-range {2}::15 \
{1}{1}= file path (from--delimiter=:){2}= line number--line-range {2}::15= show line with 15 lines of context
Preview updates as you navigate because fzf re-runs the command with new values.
- Debouncing - Wait 50ms between keystrokes
- Binary skipping - ripgrep skips binary files automatically
- Gitignore respect - ripgrep respects
.gitignoreby default (use--allto override) - Hidden files excluded - Hidden files/directories excluded by default (use
--allto include) - Depth limiting - Optional
--max-depthflag - Smart case - Case-insensitive unless uppercase in query
Command not found:
# Reload your shell config
source ~/.zshrc # for zsh
source ~/.bashrc # for bashNo syntax highlighting:
brew install batSlow on large projects:
umm -d 3 # Limit depth- Fork and create branch:
git checkout -b feat/name - Make changes:
source umm.sh && umm --help - Commit:
git commit -m "feat: description"using conventional commits - Push and create PR
Commit prefixes: feat: fix: docs: refactor: perf: