whi
Stupid simple PATH management
whi is a powerful which replacement with PATH manipulation. Find executables, see all matches, and reorder your PATH with simple shell commands.
Key Feature: Session-Based with Optional Persistence
By default, whi only modifies your current shell session. Changes are temporary and safe to experiment with. When you're happy with your PATH, use whi diff to review changes and whi save to persist them.
# 1. Manipulate PATH in current session (temporary)
# 2. Review changes before saving
# 3. Persist changes across new terminal sessions
)
# Open new terminal → your changes are still there!
This workflow prevents accidental PATH corruption and lets you experiment freely.
Features
- Session-based by default: Changes only affect current shell, safe to experiment
- Persistence when you want it: Use
whi diffto review,whi saveto persist - Better than which: Shows winner by default, all matches with
-a - PATH manipulation: Move, swap, delete, clean duplicates, and prefer executables
- Path-based operations: Add/prefer paths directly, supports tilde expansion and relative paths
- Fuzzy matching: Zoxide-style pattern matching for paths (no quotes needed)
- Winner indication: Clearly marks which executable would actually run with color
- PATH indices (
-i): Shows the PATH index for each match - Full PATH listing (
-f): Displays complete PATH with indices - Follow symlinks (
-l): Resolves and shows canonical targets - File metadata (
-s): Shows inode, device, size, and modification time - Combinable flags: Unix-style flag combining (e.g.,
-ais,-ifl) - Pipe-friendly: Quiet by default, all output to stdout
- Zero dependencies: Only libc for isatty(3)
Installation
From crates.io:
Or build from source:
Quick Start
Shell Integration (Recommended)
whi provides shell integration that gives you commands to manipulate your PATH directly in your current shell session. Without shell integration, whi --move and similar commands would only output a new PATH string - they can't modify your actual shell's PATH variable.
To enable shell integration, add this to your shell config:
Bash (~/.bashrc):
Zsh (~/.zshrc):
Fish (~/.config/fish/config.fish):
whi init fish | source
The whi init <shell> command outputs shell-specific functions that you can evaluate/source. This provides seven powerful commands:
-
whim FROM TO- Move PATH entry from index FROM to index TO -
whis IDX1 IDX2- Swap two PATH entries -
whip NAME TARGET- Make executable win, or add path to PATH# Index-based (original) # Path-based (new) # Fuzzy matching (new, no quotes needed) # Path-only (new, like fish_add_path) -
whic- Clean duplicate PATH entries (keeps first occurrence) -
whid TARGET...- Delete PATH entries by index, path, or fuzzy pattern# Index-based (original) # Path-based (new) # Fuzzy matching (new, deletes ALL matches) -
whia NAME- Show all matches with indices (shortcut forwhi -ia) -
whii [NAME]- Show PATH entries or matches with indices (shortcut forwhi -i)
Important: These commands only modify your current shell session. Changes are temporary until you use whi save to persist them.
Basic Usage
View all PATH entries (with or without indices):
Find an executable (like which) - shows only the winner:
See all matches with -a:
With PATH indices using -i (or use whia cargo shortcut):
Follow symlinks with -l to see what they point to:
Show detailed metadata with -s:
Combine flags for all matches with indices and symlinks:
PATH Manipulation Examples
See which cargo is winning and make a different one win:
Move PATH entries to reorder them:
Swap two PATH entries:
Clean duplicate entries:
Delete specific entries:
Making Changes Persistent
All the commands above only affect your current shell session. To make changes permanent:
# 1. Make changes in your current session
# 2. Review what changed
# 3. Save changes (persists across new terminal sessions)
)
# Or save to all shells at once
)
)
)
After running whi save, your changes are automatically loaded in new terminal sessions. The saved PATH is stored in ~/.whi/saved_path_<shell> and loaded by a single line added to your shell config file.
You can experiment safely because changes are session-only until you explicitly save them.
Understanding whi diff
The whi diff command shows what changed between your current session and the saved PATH. It uses intelligent markers to distinguish different types of changes:
Basic diff (whi diff) - Shows only explicit changes:
Full diff (whi diff full) - Shows everything including implicit shifts:
Diff markers explained:
+(green) - New path added to your PATH-(red) - Path removed (viawhidor duplicate removed bywhic)↕(cyan) - Path explicitly moved by you usingwhim,whis, orwhipM- Path implicitly moved (shifted as a side effect of your operations) - full mode onlyU- Path unchanged (same position as saved) - full mode only
Session tracking: whi tracks all operations in your current shell session (whim, whis, whip, whic, whid) to accurately distinguish between changes you explicitly made versus paths that shifted as a side effect. This makes whi diff highly accurate in showing what you actually changed.
Use cases:
# Quick check - see only what you explicitly changed
# Detailed review - see everything including ripple effects
# Compare with saved PATH from a specific shell
Other Usage Examples
Read multiple names from stdin:
|
Check multiple executables at once:
Show all PATH entries (with or without indices):
Use custom PATH:
Command-Line Options
Flags
Short flags can be combined Unix-style (e.g., -ai = -a -i, -ais = -a -i -s).
-a, --all- Show all PATH matches (default: only winner)-f, --full- Show all matches + full PATH listing (implies-a; directories with matches highlighted in color)-i, --index- Show PATH index next to each entry-l, -L, --follow-symlinks- Resolve and show canonical targets-o, --one- Only print the first match per name-s, --stat- Include inode/device/mtime/size metadata-0, --print0- NUL-separated output for use with xargs-q, --quiet- Suppress non-fatal stderr warnings--silent- Print nothing to stderr, use exit codes only--show-nonexec- Also list files that exist but aren't executable-h, --help- Print help information
PATH Manipulation (Session Only)
These commands output a modified PATH string to stdout. Use shell integration (see above) to actually modify your current shell's PATH. Changes are temporary until you use whi save.
-
--move <FROM> <TO>- Move PATH entry from index FROM to index TO -
--swap <IDX1> <IDX2>- Swap PATH entries at indices IDX1 and IDX2 -
--prefer <NAME> <TARGET>or--prefer <PATH>- Make executable win or add path# Index-based # Path-based (adds path at winning position if not present) # Fuzzy matching (must match exactly one path) # Path-only (like fish_add_path) -
--clean/-c- Remove duplicate PATH entries (keeps first occurrence) -
--delete <TARGET>.../-d- Delete PATH entries by index, path, or fuzzy pattern# Index-based # Path-based # Fuzzy matching (deletes ALL matches)
Persistence
-
whi save [SHELL]- Save current PATH persistently -
whi diff [SHELL|full]- Show differences between current and saved PATHDiff markers:
+(green) - Added paths-(red) - Removed paths (including duplicates fromwhic)↕(cyan) - Explicitly moved paths (whim/whis/whip)M- Implicitly shifted paths (full mode only)U- Unchanged paths (full mode only)
After whi save, changes persist across new terminal sessions. Use whi diff to review changes before saving.
Other Options
-
--path <PATH>- Override environment PATH string -
--color <WHEN>- Colorize output:auto,never,always[default: auto]
Shell Integration Command
whi init <SHELL>- Output shell integration code for bash, zsh, or fish
Exit Codes
0- All names found1- At least one not found2- Usage error3- I/O or environment error
Examples
Find all versions of Python in PATH:
Check which node would run with indices:
Use with xargs to check executables:
|
Find all versions with metadata:
Show all PATH entries with indices:
Prefer cargo from a specific path (adds if needed):
Add a path to PATH (like fish_add_path):
Use fuzzy matching to prefer bat from GitHub release:
Delete all temporary build paths:
Comparison with which
| Feature | which |
whi |
|---|---|---|
| Show first match | ✓ | ✓ (default) |
| Show all matches | Some versions with -a |
✓ With -a |
| Show PATH indices | ✗ | ✓ With -i |
| Full PATH listing | ✗ | ✓ With -f |
| Follow symlinks | Some versions | ✓ With -l/-L |
| File metadata | ✗ | ✓ With -s |
| PATH manipulation | ✗ | ✓ With shell integration |
| Clean duplicates | ✗ | ✓ With whic |
| Delete entries | ✗ | ✓ With whid |
| Session-based changes | ✗ | ✓ Safe to experiment |
| Persistent changes | ✗ | ✓ With whi save |
| Intelligent diff | ✗ | ✓ With whi diff (tracks explicit vs implicit changes) |
| Combinable flags | ✗ | ✓ |
| Multiple names | ✓ | ✓ |
| Stdin input | ✗ | ✓ |
| Pipe-friendly | Varies | ✓ |
Why?
Ever wonder:
- Which version of
pythonornodeis actually running? - How to make a different version win without editing shell configs?
- What other versions exist on your PATH?
- What's the actual order of your PATH directories?
- How to safely experiment with PATH changes without breaking things?
whi answers all these questions and lets you:
- Experiment safely with session-only changes
- Review before committing with
whi diff - Persist when ready with
whi save - Manipulate PATH on the fly without manually editing config files
License
MIT
Author
Alexander Knott alexander.knott@posteo.de