whi
whi is a smarter which that also lets you rearrange your current shell's PATH safely. Install the shell integration once, run the high level commands (prefer, add, move, switch, clean, delete, undo, redo, reset, diff, apply, save, load, list, rmp, file, source, exit, var, shorthands), and grab the helper shortcuts if you like terse aliases.
Heads up: mutation commands only run after the integration exports
WHI_SHELL_INITIALIZED=1. If you see the integration warning, run the snippet for your shell and add it to your config for persistence.
Install & Integrate
Pick the snippet for your shell and paste it into a terminal. Add the same line to the END of your shell config so it runs on startup after all PATH modifications.
# Bash
# Zsh
# Fish
| # add to the END of ~/.config/fish/config.fish
Important: The integration must be at the END of your config so whi captures your final PATH after all modifications (homebrew, cargo, etc.).
The snippet:
- Loads any previously saved PATH (from
~/.whi/saved_path_*) - Defines helper functions (
whip,whiad,whia,whim,whis,whiu,whir,whil,whiv,whish, etc.) - Exports
WHI_SHELL_INITIALIZED=1sowhiknows it's safe to mutate PATH - Captures the final PATH as your session baseline for undo/diff tracking
Core Commands
All of these operate on the current shell session. Each command prints the updated PATH; the integration captures the string and updates PATH for you.
Querying executables
# Shorthand: whia
# Fuzzy search fallback (if exact match fails)
# Show full path (line separated)
# This is cool ... list all matches, newline, list full path
# with all path entries containing the binary highlighted
Useful flags:
-a/--all-f/--full-l/--follow-symlinks-s/--stat-0/--print0-q/--quiet--silent--color <auto|never|always>--path <PATH>
PATH manipulation
# Add paths to PATH (prepends by default)
# Shorthand: whiad
# Prefer: make an executable win (or add a path)
# The Swiss Army knife - works with index, path, or fuzzy pattern
# Makes minimal changes to achieve the goal
# Move and swap entries by index (1-based)
# Clean duplicates
# Delete entries
History & state management
# Undo/redo/reset PATH changes
# Inspect PATH changes
Persistence & profiles
# Persist PATH to shell config files
# Profile management
Environment variables
# Query environment variables
# Shorthand: whiv
# Show all available shortcuts
# Shorthand: whish
Virtual environments (venv)
whi can create project-specific PATH environments similar to Python virtualenvs or direnv, but for PATH management. This is perfect for projects that need specific tool versions or custom PATH configurations.
# Create whifile from current PATH (like requirements.txt for PATH)
# Activate venv (read whifile and switch PATH)
# Shell shows: [dirname] user@host:~/project $
# Exit venv (restore previous PATH)
How it works:
whi filesnapshots your current PATH into awhifilein the current directorywhi sourcereadswhifileand replaces your PATH (saves old PATH for restore)whi exitrestores your previous PATH- Your shell prompt shows
[venv-name]when active (like Python venvs) - All PATH operations (
prefer,move,delete, etc.) work normally inside venvs - Venv state is session-specific (different terminals = different venv states)
Use cases:
- Lock tool versions per project (e.g., specific Node, Python, Ruby versions)
- Isolate project-specific binaries from global PATH
- Test PATH configurations before applying globally
- Share reproducible development environments via version control
Auto-activation:
You can enable auto-activation in ~/.whi/config.toml:
[]
= true # automatically source whifile when entering directories
When enabled, the shell integration will automatically activate venvs when you cd into directories containing whifile.
Known Issue: Auto-activation currently does not work in Zsh. Bash and Fish work correctly. For Zsh users, please manually run
whi sourcewhen entering directories with awhifile. This will be fixed in a future release.
whifile format (v2 / 0.6.0+): The file uses a directive-based format with multiple PATH and ENV strategies:
# Replace session PATH entirely
!path.replace
/usr/local/bin
/usr/bin
/bin
~/custom/bin
/Users/$USER/.local/bin
# Or prepend to session PATH
# !path.prepend
# ~/my-tools/bin
# Or append to session PATH
# !path.append
# ~/extra/bin
# Set environment variables
!env.set
# Comments are supported
RUST_LOG debug
PROJECT_ROOT $(pwd)
CONFIG_DIR $HOME/.config/myapp
MY_VAR hello world
# Or replace all env vars (whitelist mode)
# !env.replace
# KEEP_THIS value
# AND_THIS value
# Or unset specific vars
# !env.unset
# REMOVE_THIS
# AND_THIS
PATH directives (mutually exclusive):
!path.replace- Replace session PATH entirely with listed paths!path.prepend- Prepend paths to session PATH!path.append- Append paths to session PATH- Each path is on its own line
- Supports shell variable expansion:
$VAR,${VAR},~,$(command) - Variables are expanded when sourcing the venv
ENV directives:
!env.set- Set specific environment variables (default)!env.replace- Replace all env vars (whitelist mode, auto-unsets others)!env.unset- Unset specific variables- Fish-style syntax:
KEY value(space-separated, no=or quotes needed) - Supports shell variable expansion:
$VAR,${VAR},~,$(command),`command` - Values can contain spaces, special characters (
:,=,/, etc.) - Comments start with
# - Variables are set when entering venv, unset when exiting
Legacy format support:
Files with PATH! and ENV! sections (pre-0.6.0) are automatically converted to !path.replace and !env.set for backward compatibility.
Shell prompt behaviour
- bash & zsh: whi prepends "[name]" to your existing prompt.
- fish: the marker appears in the right-hand prompt, and any prior
fish_right_promptoutput still runs before it. - Prompt frameworks (Starship, powerlevel10k, etc.) keep their formatting. Adjust your prompt or redefine
__whi_promptif you want a different placement.
whi --help shows the verbs (prefer, add, move, switch, clean, delete, undo, redo, reset, diff, apply, save, load, list, rmp, file, source, exit, var, shorthands). The integration intercepts those public names and rewrites them to the hidden __… subcommands that actually mutate the environment.
Helper Shortcuts
These are defined by the integration and map directly to the core commands:
# whip: Swiss Army knife for PATH management
# Other shortcuts
Use whichever spelling you prefer—both routes converge in Rust.
Persistence & State
-
Saved PATH files live in
~/.whi/(saved_path_bash,saved_path_zsh,saved_path_fish).whi apply allwrites to all three. Each save creates a*.bakbackup before overwriting. Files use a human-friendly directive format with!path.replaceand!env.setsections (v0.6.0+). LegacyPATH!/ENV!format (pre-0.6.0) and colon-separated files (pre-0.6.0) are automatically detected and supported for backward compatibility. -
Profile storage lives in
~/.whi/profiles/. Each profile is a file in the same human-friendly format as saved PATH files. Usewhi save <name>to save current PATH as a profile,whi load <name>to restore it, andwhi listto see all profiles. You can manually edit these files - use!path.replace/!path.prepend/!path.appendfor PATH directives and!env.set/!env.replace/!env.unsetfor environment variables (all support shell variable expansion). -
Configuration lives in
~/.whi/config.toml. Auto-created on first run with defaults. Controls venv auto-activation and protected paths (preserved duringwhi applyto prevent breaking your shell). -
Session snapshots live in
${XDG_RUNTIME_DIR:-/tmp}/whi-<uid>/session_<ppid>.log(orsession_<ppid>/<venv-dir-hash>.logwhen in a venv). Each PATH modification writes a snapshot (timestamp + full PATH string). The undo/redo system navigates through these snapshots with a cursor. Sessions keep up to 500 snapshots (initial + last 499) and auto-cleanup old sessions after 24 hours. -
Undo cursor lives in
${XDG_RUNTIME_DIR:-/tmp}/whi-<uid>/session_<ppid>.cursor(orsession_<ppid>/<venv-dir-hash>.cursorwhen in a venv). Tracks your position in the snapshot history. No cursor file means you're at the latest state. -
Venv state (when active) is stored in
${XDG_RUNTIME_DIR:-/tmp}/whi-<uid>/session_<ppid>/venv_restore(PATH to restore on exit) andvenv_dir(venv directory path). This is session-specific - each terminal has independent venv state.
How undo/redo works
Every PATH mutation writes a snapshot. The undo system navigates backwards through snapshots, and redo moves forward. If you undo then make a new change, the "future" timeline is discarded (standard undo/redo behavior).
# Example session:
whi diff compares your current PATH to the initial session snapshot, so it shows all changes including manual export PATH=... modifications (not just whi operations).
Notes
-
Mutating commands exit with an instructional message if the integration is missing. Copy the snippet shown, run it, and add it to your shell config for future sessions.
-
The shell integration uses absolute paths to
whi, so it continues to work even if PATH is modified or replaced during initialization. -
If you want to script against
whidirectly, capture stdout and export the string yourself. The integration just automates that for interactive use.
License
MIT License. See LICENSE for details.