A command-line utility that automatically fixes common shell command errors, inspired
by thefuck. When you type a command incorrectly, just run shit and it will suggest
the correct command.
- Installation
- Usage
- Supported Shells
- Built-in Rules
- Custom Rules
- Configuration
- Tricks and Tips
- Contributing
- Bug Reports
- License
cargo install theshitgit clone https://github.com/AsfhtgkDavid/theshit.git
cd theshit
cargo build --release --no-default-featuresThe binary will be available at target/release/theshit. You can install it to your system with
cargo install --path . or copy it to a directory in your $PATH.
First, set up the alias in your shell:
# This will add the necessary alias to your shell configuration and create the base rules
theshit setupOr specify a custom alias name:
theshit setup myfixAfter setup, restart your shell or source your configuration file.
When a command fails, just type theshit (or your custom alias):
$ sl
bash: sl: command not found
$ shit
ls [enter/↑/↓/Ctrl+C]The tool will suggest corrections. Use:
- Enter to execute the selected command
- ↑/↓ to navigate between suggestions
- Ctrl+C to cancel
- Bash
- Zsh
- Fish
| Rule | Description | Example |
|---|---|---|
sudo |
Adds sudo to commands that failed with permission errors |
mkdir /etc/config → sudo mkdir /etc/config |
to_cd |
Fixes typos in the cd command |
cs /home → cd /home |
unsudo |
Removes sudo from commands that shouldn't be run as root |
sudo npm install → npm install |
mkdir_p |
Adds -p flag to mkdir when parent directories don't exist |
mkdir a/b/c → mkdir -p a/b/c |
cargo_no_command |
Fixes cargo subcommand typos | cargo biuld → cargo build |
The sudo rule recognizes these error patterns:
- "permission denied"
- "eacces"
- "operation not permitted"
- "must be run as root"
- "authentication is required"
- And many more...
Create a Python file in ~/.config/theshit/fix_rules/active/ with the following structure:
def match(command: str, stdout: str, stderr: str) -> bool:
"""
Determine if this rule should be applied to the failed command.
Args:
command: The original command that failed
stdout: Standard output from the failed command
stderr: Standard error from the failed command
Returns:
True if this rule should fix the command, False otherwise
"""
return "your condition here"
def fix(command: str, stdout: str, stderr: str) -> str:
"""
Generate the corrected command.
Args:
command: The original command that failed
stdout: Standard output from the failed command
stderr: Standard error from the failed command
Returns:
The corrected command string
"""
return "your fixed command here"# ~/.config/theshit/fix_rules/active/git_branch_typo.py
import re
def match(command: str, stdout: str, stderr: str) -> bool:
return (command.startswith("git") and
"did you mean" in stderr and
"branch" in command)
def fix(command: str, stdout: str, stderr: str) -> str:
# Extract suggested branch name from git error message
match = re.search(r"did you mean '([^']+)'", stderr)
if match:
suggested_branch = match.group(1)
return re.sub(r"branch \S+", f"branch {suggested_branch}", command)
return commandTo disable a rule temporarily, add .bak to its filename:
# Disable the sudo rule
mv ~/.config/theshit/fix_rules/active/sudo.native ~/.config/theshit/fix_rules/active/sudo.native.bak
# Disable a Python rule
mv ~/.config/theshit/fix_rules/active/my_rule.py ~/.config/theshit/fix_rules/active/my_rule.py.bakTo permanently disable a rule, move it to the additional rules directory:
mv ~/.config/theshit/fix_rules/active/sudo.native ~/.config/theshit/fix_rules/additional/Configuration files are stored in ~/.config/theshit/:
~/.config/theshit/
├── fix_rules/
│ ├── active/ # Rules that are currently enabled
│ │ ├── sudo.native
│ │ ├── to_cd.native
│ │ └── custom_rule.py
│ └── additional/ # Disabled rules
│ └── disabled_rule.py
For the best experience, add this to your shell configuration:
Bash (~/.bashrc):
# Run theshit on double ESC
bind '"\e\e": "theshit\n"'Zsh (~/.zshrc):
# Run theshit on double ESC
bindkey -s '\e\e' 'theshit\n'The tool automatically expands aliases before processing, so if you have:
alias ll='ls -la'And you run ll /nonexistent, the tool will process ls -la /nonexistent.
You can use any alias name:
theshit setup fix
theshit setup oops
theshit setup dammitThe tool sets these environment variables during execution:
SH_SHELL: Current shell (bash/zsh)SH_PREV_CMD: The previous command that failedSH_SHELL_ALIASES: Available shell aliases
Please see CONTRIBUTING.md for details on how to contribute to this project.
For a quick overview of the project architecture, you can use Code2tutorial.
If you encounter a bug or have a feature request, please open an issue with:
-
Environment information:
- OS and version
- Shell and version
- Rust version (if building from source)
-
Steps to reproduce:
- The original command that failed
- The error message
- Expected vs actual behavior
-
Relevant logs:
- Include any error messages from
theshit - Shell configuration if relevant
- Include any error messages from
-
For rule-related issues:
- Output of the failing command
- Contents of
~/.config/theshit/fix_rules/active/if using custom rules
Issue: Custom Python rules not working
- Check that the rule file has both
match()andfix()functions - Ensure the file is in the
activedirectory - Verify Python syntax with
python -m py_compile your_rule.py
Issue: Alias not found after setup
- Restart your shell or run
source ~/.bashrc/source ~/.zshrc - Check that the alias was added to the correct configuration file
This project is licensed under the MIT License - see the LICENSE file for details.
