A lightweight Go binary that catches your common typing mistakes in PowerShell before commands execute.
Type git sattus, press Enter and CommandFixer offers git status; the corrected line runs once you accept it.
Works in both PowerShell 7 (pwsh) and Windows PowerShell 5 (powershell.exe).
Commercial licences available. CommandFixer is free and open source under GPL-3.0. If those terms do not suit what you are building, such as a closed-source product, a commercial licence can be bought from me separately. It covers my own code; the Go standard library it is built with keeps its own licence. See commercial licensing.
It is for someone who lives in PowerShell on Windows and mistypes the same handful of commands often enough to want them corrected in place. Suggestions arrive through a PSReadLine hook and nothing is rewritten behind your back: you confirm before the corrected command runs.
It is not a shell, not a replacement for tab completion and not a command generator. It
matches against a database of common CLI tools using a similarity threshold, so it
corrects spelling rather than intent: it will turn a misspelt command into the one you
meant to type, never a wrong command into the right one. It only looks at lines of two
words or more, so a lone mistyped word such as ipconfg is left as typed. It works by
hooking PowerShell profiles on Windows and has no meaning outside that environment.
- Corrects a mistyped subcommand of a known tool (
git sattustogit status,npm isntalltonpm install), keeping every argument after it. - Corrects a mistyped tool or Windows command name (
dokcer pstodocker ps,ipconfg /alltoipconfig /all) and the habitualgtitogit. - Never renames a first word that already runs as a command on your PATH, so a program the database has never heard of is left alone.
- Asks before anything changes: Y or Enter accepts, any other key keeps the line.
- Holds input that would open PowerShell's
>>continuation prompt (a trailing backtick is stripped; an unclosed quote or a dangling pipe beeps and stays on the line). - Logs each accepted correction to a local file and counts them on request.
| Part | What |
|---|---|
| Language | Go 1.21 or later, standard library only, no cgo |
| Prompt hook | PSReadLine, in PowerShell 7 and Windows PowerShell 5 |
| Install and build | PowerShell scripts: build.ps1, install.ps1, uninstall.ps1 |
| Storage | A JSON settings file and a JSONL log in your home directory |
git clone https://github.com/oernster/commandfixer
cd commandfixer
.\build.ps1 -Test # run tests then buildOr with go directly:
go build -o commandfixer.exe ..\install.ps1The installer:
- Copies
commandfixer.exeto%LOCALAPPDATA%\CommandFixer\ - Adds that directory to your user
PATH - Copies
config.example.jsonto%USERPROFILE%\.typo-fixer\config.jsonwhen you have no config there yet - Hooks into your PowerShell profile for both PS7 and PS5
Everything is per user, so no administrator rights are needed. Then restart PowerShell (both pwsh and powershell.exe will have the hook).
.\uninstall.ps1The uninstaller:
- Removes the hook from both PS7 (
Documents\PowerShell\profile.ps1) and PS5 (Documents\WindowsPowerShell\profile.ps1) - Deletes the
%LOCALAPPDATA%\CommandFixer\folder, binary included - Removes that directory from your user
PATH - Keeps your config and log at
%USERPROFILE%\.typo-fixer\(data is yours)
To also delete config and log:
.\uninstall.ps1 -RemoveConfigThen restart PowerShell to complete removal.
You can also uninstall via the binary directly (if it is on your PATH):
commandfixer uninstall # removes profile hooks only; does not touch binary or PATH
To upgrade to a new build (or reinstall after code changes), rebuild and re-run the installer. install.ps1 is idempotent: it overwrites the existing binary with -Force and leaves your PATH entry and your config/log untouched. It adds the PowerShell profile hook to any profile that lacks it; a profile that already has the hook is left exactly as it is.
.\build.ps1 -Test # rebuild commandfixer.exe (runs tests first)
.\install.ps1 # overwrite the installed binaryNo restart is needed. The hook runs the installed binary by its full path on every Enter, so open shells use the new build straight away.
If a release changes the hook itself, re-running the installer does not update it. Remove the old hook first, then install and restart PowerShell, since a profile registers the hook once at startup:
& "$env:LOCALAPPDATA\CommandFixer\commandfixer.exe" uninstall
.\install.ps1For a clean reinstall that also resets your config and log, uninstall with -RemoveConfig first, then install:
.\uninstall.ps1 -RemoveConfig
.\build.ps1
.\install.ps1There is nothing you have to configure. Corrections come from a database built into the binary, so it is useful the moment it is installed.
If you want to tune it, edit %USERPROFILE%\.typo-fixer\config.json:
{
"settings": {
"log_file": "",
"max_log_lines": 10000,
"similarity_threshold": 0.6
}
}similarity_threshold is how close a typo must be to a known command before it
is offered, in the range (0.0, 1.0]; a value outside it falls back to 0.6.
Lower catches more typos and starts offering corrections you did not want.
log_file empty means the default location below. max_log_lines is read but
nothing acts on it: the log is never trimmed.
Type a mistyped command and press Enter:
PS> git sattus
CommandFixer: did you mean: git status [Y/n]
On branch main ...
CommandFixer hooks into PSReadLine (built into both PowerShell 7 and Windows PowerShell 5) and intercepts the Enter key. When you press Enter:
- PSReadLine captures the current buffer.
- It calls
commandfixer suggest <your-command>. - CommandFixer fuzzy-matches it against a built-in database of CLI tools, their subcommands and the standard Windows commands and prints a suggestion when one is close enough. Nothing is printed when it has nothing to offer.
- If there is a suggestion, PowerShell shows it and waits for you to confirm.
- The corrected command executes only if you accept it.
No system-wide keyboard hooks. No persistent service required. The binary runs once each time you press Enter on a command, then exits. Nothing it does reaches the network.
commandfixer suggest <cmd> Fuzzy-match and print correction (used by hook)
commandfixer correct <cmd> Like suggest but also logs the correction
commandfixer log <from> <to> Record a correction you accepted (used by hook)
commandfixer install [profile] Add PSReadLine hook to your profile(s)
commandfixer uninstall [profile] Remove the hook from your profile(s)
commandfixer stats Show how many corrections have been logged
commandfixer version Print version
commandfixer help Show help
Without a [profile] argument, install and uninstall target both PS7 and PS5 profiles simultaneously.
commandfixer correct "git sattus"
# Prints: git status (and records the correction in the log)| Path | Purpose |
|---|---|
%USERPROFILE%\.typo-fixer\config.json |
Settings: log location and match sensitivity |
%USERPROFILE%\.typo-fixer\corrections.log |
JSONL corrections log |
%LOCALAPPDATA%\CommandFixer\commandfixer.exe |
Installed binary |
Documents\PowerShell\profile.ps1 |
PS7 profile (hook appended here) |
Documents\WindowsPowerShell\profile.ps1 |
PS5 profile (hook appended here) |
Documents is the folder Windows reports as your Documents folder, the same one PowerShell reads its profile from, so a Documents folder moved by OneDrive folder backup is followed rather than ignored.
.\build.ps1 -Coverage # the whole suite, failing below the coverage floor
.\build.ps1 -Lint # gofmt, go vet and staticcheckTESTING.md covers the floor, what each suite proves and how to run part of it.
- DEVELOPMENT.md: build steps, local dev workflow, debugging
- ARCHITECTURE.md: system design, module breakdown, data flow
- TESTING.md: testing strategy, coverage requirements, how to run tests
- TECH_DEBT.md: what is still open, what is deliberately left and what only looks like debt
- DECISIONS-TRADEOFFS.md: the decisions CommandFixer rests on, with what each one gains and what it costs
CommandFixer is free and stays free. There is no paid tier, no licence key and no feature held back behind a donation. If it has saved you time or simply been useful, a donation supports its maintenance and continued development.
CommandFixer is released under the GNU General Public License v3.0; see LICENSE.
A commercial licence is available for uses the GPL does not suit: see commercial licensing.
