A modern Windows PATH environment variable & command catalog manager. Automatically prevents PATH bloat, creates short commands for any runnable script or binary, organizes PowerShell completions, and diagnoses PATH health.
- Single Shim Directory on PATH: Stops Windows PATH from growing uncontrollably. Instead of adding every tool folder to PATH,
pathmanlinks executables and scripts into a single unified shim directory (%LOCALAPPDATA%\PathManager\shims). - Link Any Runnable: Turn
.exe,.cmd,.bat,.ps1,.py, or custom scripts into native terminal commands (pathman link .\script.py). - Raw
REG_EXPAND_SZRegistry Updates: Modifies User PATH directly in Windows Registry (HKCU\Environment) while preserving unexpanded environment variables (%SystemRoot%,%USERPROFILE%). Never callssetx(preventingsetx's 1024-character truncation and data loss). - PowerShell Tab Completions Organizer: One folder (
%LOCALAPPDATA%\PathManager\completions\) plus one$PROFILEhook. Pathman does not invent your tool's Tab completions; it stores.ps1completers you generate and loads them in every new pwsh. Useregister-file,register-command, or a best-effortfrom-help. - Resolution Tracer (
pathman why): Traces command resolution across PathManager shims, PowerShell functions, Machine PATH, User PATH, PATHEXT, and WindowsApps Store aliases to explain which binary runs and identify shadowing conflicts. - Doctor & Health Diagnostics (
pathman doctor): Checks PATH character limits (GUI limit 2047, Cmd limit 8191, Win32 limit 32767), detects dead directories (with non-blocking 200ms UNC network timeouts), discovers duplicates, and repairs drift with--repair. - Instant Rollback (
pathman undo): Snapshots catalog and User PATH before every mutation. Undo mistakes with a single command.
From PowerShell (do not run as Administrator):
irm https://github.com/jag-a-i/PathMan/releases/latest/download/install.ps1 | iexThat downloads the self-contained win-x64 zip from GitHub Releases, puts pathman on your User PATH, and registers completions in this session. From a clone (needs the .NET 8 SDK):
.\install.ps1# Link a PowerShell script
pathman link .\hello.ps1
# Link a Python script
pathman link .\my_tool.py
# Link with a custom command name
pathman link "C:\CustomTools\downloader_v2.exe" dlOpen any terminal or use your current session immediately:
hello
my_tool --help
dlPathman is a mailbox for completion scripts, not a completions author. After install you get:
- A folder:
%LOCALAPPDATA%\PathManager\completions\ - One marked block in
$PROFILEthat, on every new pwsh:- prepends the shim directory to
$env:PATH(so linked names win inside PowerShell) - dot-sources every
*.ps1in that folder - registers Tab completion for the
pathmanCLI itself
- prepends the shim directory to
Linked commands (pathman link .\hello.ps1) do not automatically get Tab completion. Completers only exist if a .ps1 is in the folder.
install.ps1 already runs pathman completions install and registers the pathman completer in the current session. Later shells pick up the hook from $PROFILE. If Tab does nothing, run pathman doctor — a missing hook is reported as INFO with the fix command.
pathman completions install # pwsh 7+ ($HOME\Documents\PowerShell\...)
pathman completions install --windows-powershell # Windows PowerShell 5.1
. $PROFILE # load in this sessionIf the profile file cannot be written, Pathman prints the snippet to paste. Completions are PowerShell scripts, so they are trusted code at shell start.
Most tools can emit a PowerShell completer. Redirect that to a file, then register it:
# Examples of generators (the tool's, not Pathman's):
someprogram --completions powershell > .\someprogram.ps1
gh completion powershell > .\gh.ps1
rustup completions powershell > .\rustup.ps1
pathman completions register-file .\someprogram.ps1
pathman completions register-file .\gh.ps1 --name gh
. $PROFILEregister-file copies the .ps1 to %LOCALAPPDATA%\PathManager\completions\<name>.ps1. The command name defaults to the file name without extension. Use --name to override. Use --force to overwrite an existing completer.
If that name is already in the catalog (pathman link), Pathman stores completer: completions/<name>.ps1 on the catalog row. The hook still loads every *.ps1 in the folder, catalog or not.
You can also drop a file in by hand:
Copy-Item .\someprogram.ps1 $env:LOCALAPPDATA\PathManager\completions\Same result, one step. Pathman runs the command in pwsh, captures stdout, and writes the folder file:
pathman completions register-command "someprogram --completions powershell"
pathman completions register-command "gh completion powershell" --name gh
pathman completions register-command rustup completions powershell --name rustupThe command name defaults to the first token (basename without .exe). Non-zero exit or empty stdout fails with a named error and a pathman doctor hint.
This runs whatever you pass. Only use generators you trust — the captured script is executed at every future shell start.
When a tool has no completer generator, Pathman can scrape flags (and a Commands: section) from --help, falling back to -h:
pathman completions from-help git
pathman completions from-help "docker compose" --name dockerThis is a heuristic. It will miss nested flags, value completions, and unusual help layouts. Prefer register-file / register-command when the tool can emit a real script.
- New pwsh windows load the folder automatically.
- This session:
. $PROFILE - Commands still run if the hook is missing; Tab does not.
pathman doctorsays so.
| Command | Description | Notable Flags |
|---|---|---|
pathman |
Shows quick status summary and usage help | --json, --help |
pathman link <file> [name] |
Links a file as a runnable command | --force, --host <exe>, --i-trust-this, --json |
pathman unlink <name> |
Unlinks a command and deletes its shim | --json |
pathman list |
Lists all linked commands and their targets | --json |
pathman why <name> |
Traces command resolution and PATH shadowing | --json |
pathman doctor |
Inspects PATH limits, dead folders, duplicates, and catalog drift | --repair, --json |
pathman path |
Displays User and Machine PATH entries | --json |
pathman path add <dir> |
Safely adds a directory to User PATH | --prepend, --json |
pathman path remove <dir> |
Safely removes a directory from User PATH | --force, --json |
pathman undo |
Restores the previous snapshot of catalog and User PATH | --json |
pathman completions install |
Installs the $PROFILE hook (load folder + pathman Tab) |
--windows-powershell, --json |
pathman completions register-file <file.ps1> |
Copies a completer .ps1 into the completions folder |
--name, --force, --json |
pathman completions register-command <cmd> |
Runs a generator command and stores its stdout as the completer | --name, --force, --json |
pathman completions from-help <cmd> |
Best-effort native completer from --help / -h |
--name, --force, --json |
pathman uninstall |
Uninstalls PathManager and cleans User PATH | --keep-shims, --json |
%LOCALAPPDATA%\PathManager\
state.json # Catalog database (source of truth)
shims\ # The single directory added to User PATH
pathman.exe # CLI tool
shim.exe # Template native runner
<name>.exe # Native shim for linked command
<name>.exe.meta # Sidecar metadata (recovery backup)
completions\ # Organized PowerShell completion scripts
<name>.ps1
snapshots\ # Automated undo backups
<timestamp>\
state.json
UserPath.txt
audit.jsonl # Append-only audit log
Run the xUnit test suite (completely isolated from the host machine's real PATH):
dotnet testEvery push and pull request runs restore → Release build → dotnet test → publish (.github/workflows/ci.yml).
CD (.github/workflows/release.yml) then ships a self-contained pathman-win-x64.zip:
- Push to
master/mainupdates the nightly pre-release - A version tag publishes a stable GitHub Release
git tag v1.0.0
git push origin v1.0.0Install from the stable release with irm …/releases/latest/download/install.ps1 | iex. The zip is also attached to the Actions run.