pls reruns your previous shell command with sudo prepended, while keeping the shell-specific history lookup where it belongs: in the shell you are currently using.

Install
|
Windows PowerShell:
powershell -ExecutionPolicy Bypass -c "irm https://github.com/iamrajjoshi/pretty-please/releases/latest/download/pretty-please-installer.ps1 | iex"
| Method | Command | Status |
|---|---|---|
| Homebrew | brew install iamrajjoshi/tap/pls |
wired through cargo-dist |
| Cargo | cargo install pretty-please --bin pls |
available |
| Shell installer | `curl ... | sh` |
| PowerShell installer | irm ... | iex |
generated on release |
| Nix | nix run github:iamrajjoshi/pretty-please |
included via flake.nix |
| AUR | yay -S pls-git |
included as packaging/aur/PKGBUILD |
| Scoop | community manifest welcome | not automated yet |
Setup
Hook pls into your shell once so the zero-argument form can see your live, in-session command history.
pls init fish | source
Add-Content $PROFILE 'Invoke-Expression (& pls init pwsh)'
pls init nu | save --append ~/.config/nushell/config.nu
Usage
Rerun the last command with sudo:
$ mkdir /var/my-app
mkdir: /var/my-app: Permission denied
$ pls
Wrap an explicit command directly:
$ pls systemctl restart nginx
Print shell completions:
$ pls completions zsh > _pls
Compatibility
| Shell | macOS | Linux | Windows |
|---|---|---|---|
| bash | yes | yes | via WSL/Git Bash |
| zsh | yes | yes | via WSL |
| fish | yes | yes | via WSL |
| pwsh | yes | yes | yes |
| nu | yes | yes | yes |
pls assumes a sudo executable exists on PATH. If it does not, pls fails fast with a friendly error instead of guessing.
Why This Split Exists
The shell function handles one thing only: reading the most recent in-memory command from your current shell session. The Rust binary handles everything portable:
- refusing shell builtins like
cdorexport - avoiding
sudo sudo ... - skipping
sudowhen already root - printing init snippets and completions
- staying tiny enough to ship as a single CLI binary
Comparison
| Tool | What it does well | Why pls exists |
|---|---|---|
sudo !! |
tiny bash/zsh trick | shell-specific, brittle outside history-expansion shells |
| shell alias/function only | zero dependencies | hard to test, hard to distribute, hard to support across shells |
thefuck |
broad command correction | much heavier than a single "rerun with sudo" primitive |
pls |
one job, cross-shell, tiny binary | purpose-built for "that should have been sudo" |
FAQ
Does pls work with pipes and redirects?
Mostly the same way a manual sudo <previous command> does: sudo only applies to the leftmost command in a pipeline. A shell-wrapped mode can come later.
Why not just alias sudo !!?
Because !! is not portable, history access differs wildly between shells, and distributing a tested cross-shell tool is nicer than copy-pasting five different dotfile snippets.
Why is the crate called pretty-please if the binary is pls?
Because pls is already taken on crates.io, while pretty-please stays publishable and still lets the installed command remain pls.
Development
The demo GIF is generated from demo.tape with VHS, and the release pipeline is powered by cargo-dist.
License
Licensed under either of:
- Apache License, Version 2.0, (LICENSE-APACHE)
- MIT license (LICENSE-MIT)
at your option.