# 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`, `move`, `switch`, `clean`, `delete`, `undo`, `redo`, `reset`, `diff`, `apply`, `save`, `load`), 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
```bash
cargo install whi
```
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
# Bash
eval "$(whi init bash)" # add to the END of ~/.bashrc (or the file you source)
# Zsh
eval "$(whi init zsh)" # add to the END of ~/.zshrc
# Fish
```bash
whi node # show the first match (with PATH index)
whi --all node # list every match
# This is cool ... list all matches, newline, list full path
# with all path entries containing the binary highlighted
whi --full cargo
```
Useful flags:
- `-a/--all`
- `-f/--full`
- `-l/--follow-symlinks`
- `-s/--stat`
- `-0/--print0`
- `-q/--quiet`
- `--silent`
- `--color <auto|never|always>`
- `--path <PATH>`
`whi --help` shows the verbs (`prefer`, `move`, `switch`, `clean`, `delete`, `undo`, `redo`, `reset`, `diff`, `apply`, `save`, `load`, `list`, `rmp`). 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:
```bash
whip cargo github release # -> whi prefer ...
whim 12 1 # -> whi move ...
whis 4 9 # -> whi switch ...
whic # -> whi clean
whid 3 9 # -> whi delete ...
whiu # -> whi undo
whiu 3 # -> whi undo 3
whir # -> whi redo
whir 2 # -> whi redo 2
whil work # -> whi load work
whia python # -> whi --all python
```
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 all` writes to all three. Each save creates a `*.bak` backup before overwriting.
- **Profile storage** lives in `~/.whi/profiles/`. Each profile is a file containing a colon-separated PATH string. Use `whi save <name>` to save current PATH as a profile, `whi load <name>` to restore it, and `whi list` to see all profiles.
- **Session snapshots** live in `${XDG_RUNTIME_DIR:-/tmp}/whi-<uid>/session_<ppid>.log`. 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`. Tracks your position in the snapshot history. No cursor file means you're at the latest 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).
```bash
# Example session:
$ whi move 5 1 # snapshot 1 (initial is snapshot 0)
$ whi delete 3 # snapshot 2
$ whi undo # cursor moves to snapshot 1
$ whi undo # cursor moves to snapshot 0 (initial)
$ whi redo # cursor moves to snapshot 1
$ whi prefer cargo 2 # snapshot 3 (snapshot 2 discarded, new timeline)
$ whi reset # back to snapshot 0, cursor cleared
```
`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.
- Profile loading includes self-protection: if a profile doesn't contain the current `whi` directory, it's silently appended to prevent losing access to `whi` itself.
- If you want to script against `whi` directly, capture stdout and export the string yourself. The integration just automates that for interactive use.
## License
MIT