Skip to content

pxgray/oops

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

oops

Fix your last failed shell command.

oops silently watches every command you run. When one fails, type oops and it suggests — or automatically applies — a corrected version. The failed command is never re-executed; oops analyzes the command string, exit code, and context (git state, filesystem, shell history) to produce a fix.

$ gti status
zsh: command not found: gti

$ oops
git status
On branch main...

Installation

From source

go install github.com/pxgray/oops/cmd/oops@latest

Or clone and build:

git clone https://github.com/pxgray/oops
cd oops
go build -o bin/oops ./cmd/oops   # build to ./bin/oops
# or
go install ./cmd/oops             # install to $GOPATH/bin

Requires Go 1.25+. The binary has no runtime dependencies.

Shell integration

After installing the binary, add the hook to your shell's config file. The hook tracks each command passively — it never re-runs anything.

zsh

Add to ~/.zshrc:

eval "$(oops --alias zsh)"

bash

Add to ~/.bashrc:

eval "$(oops --alias bash)"

fish

Add to ~/.config/fish/config.fish:

oops --alias fish | source

Restart your shell (or source the config file) to activate. You can now type oops after any failed command.

Usage

Just type oops after a failed command:

$ cd nonexistent-dir
bash: cd: nonexistent-dir: No such file or directory

$ oops
mkdir -p nonexistent-dir && cd nonexistent-dir

When multiple fixes are possible, an interactive picker appears (requires a TTY). Use arrow keys to select and Enter to confirm. Press q or Ctrl+C to cancel without running anything.

What it fixes

Situation Example Fix
Typo in command name gti status git status
Permission denied cat /etc/shadow sudo cat /etc/shadow
cd to nonexistent dir cd myproject mkdir -p myproject && cd myproject
Wrong git branch name git checkout mian git checkout main
Push without upstream git push (no upstream) git push --set-upstream origin <branch>
Nothing staged to commit git commit -m "..." git commit --amend -m "..."
Python venv not activated python script.py (venv present) source venv/bin/activate && python script.py
Repeated history prefix docker run ... (partial match) best matching prior command

Commands

oops               # print help
oops --alias SHELL # print shell integration hook (bash/zsh/fish)
oops run           # analyze and fix last command (called by the hook)
oops rules         # list all rules and their enabled/disabled status
oops config        # show config file path and current settings

Configuration

Config file: ~/.config/oops/config.toml (created on first use if needed; missing file uses defaults silently).

[core]
timeout     = "5s"    # max time for rule evaluation
cache_max_age = "1h"

[predictor]
history_limit   = 10000  # how many history entries to load
max_suggestions = 5      # max candidates shown in picker

[ui]
interactive = true  # show TUI picker when multiple fixes exist
color       = true

[rules]
disabled = []       # list rule names to disable, e.g. ["history_repeat"]

Disabling rules

[rules]
disabled = ["history_repeat", "python_venv"]

Available rule names: command_not_found, git_branch, git_push_upstream, git_commit_amend, cd_mkdir, python_venv, typo_flag, history_repeat.

Run oops rules to see all rules and their current status.

How it works

oops uses a priority-ordered rule pipeline:

  1. The shell hook captures the command string and exit code after each prompt.
  2. On oops, the hook passes OOPS_CMD, OOPS_EXIT, OOPS_CWD, and OOPS_SHELL to oops run.
  3. Rules are evaluated in priority order; each rule inspects the command and optionally performs secondary checks (git state, filesystem presence, etc.).
  4. Candidates are ranked by confidence. The highest-confidence fix is applied automatically, or presented in the interactive picker.
  5. The chosen command is written to stdout; the shell hook evals it. All UI output goes to /dev/tty.

Command typo correction uses a BK-tree with Damerau-Levenshtein distance (transpositions cost 1) combined with Jaro-Winkler fuzzy scoring, so single-character transpositions like gti → git are reliably caught.

Development

task build    # build to bin/oops
task test     # run all tests
task install  # install to $GOPATH/bin
task clean    # remove bin/

Run a single test:

go test ./internal/rules/ -run TestCdMkdir -v

About

A CLI tool written in Go that hooks into bash, zsh, and fish to detect failed commands and suggest corrections using BK-tree fuzzy matching, radix tree lookups, and shell-specific rules.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages