The Fuck

repository·master·Indexed 13 days ago

https://github.com/nvbn/thefuck

A command-line tool that corrects errors in previous console commands, such as typos or missing permissions, by suggesting and executing a corrected version. It uses a system of default, platform-specific, and custom rules to match failed commands and provide fixes. Requires Python 3.5+.

Tokens
9.3K
Snippets
10
Records
14
Agent score
50%

What's inside The Fuck

  1. How The Fuck works

    master

    The Fuck operates by attempting to match your previous failed command against a set of predefined rules. If a match is found, it generates a corrected version of that command and offers to execute it.

    Rules are categorized into three types:

    1. Enabled by default: A wide variety of rules for common tools like git, docker, npm, python, cd, sudo, etc.
    2. Platform-specific: Rules that are only enabled on specific operating systems (e.g., apt-get rules for Debian/Ubuntu, brew rules for macOS, pacman rules for Arch Linux).
    3. Bundled but disabled: Rules that are included in the package but are not active by default for safety or conflict reasons (e.g., git_push_force or rm_root).
  2. Install The Fuck

    master

    Install The Fuck using the package manager appropriate for your operating system. After installation, you must add an alias to your shell configuration file (e.g., .bashrc, .zshrc, .fish) to enable the command.

    Installation Commands

    macOS (Homebrew):

    brew install thefuck

    Ubuntu / Mint:

    sudo apt update
    sudo apt install python3-dev python3-pip python3-setuptools
    pip3 install thefuck --user

    FreeBSD:

    pkg install thefuck

    ChromeOS (chromebrew):

    crew install thefuck

    Arch Linux:

    sudo pacman -S thefuck

    Generic (pip):

    pip install thefuck

    Shell Configuration (Required)

    To use the command, add the following line to your shell startup script (.bash_profile, .bashrc, .zshrc, etc.):

    eval $(thefuck --alias)

    You can customize the alias name (e.g., FUCK):

    eval $(thefuck --alias FUCK)

    Note: Changes require a new shell session or running source <your_config_file> to take effect immediately.

    eval $(thefuck --alias)
  3. Create your own custom rules

    master

    To add a custom rule, create a Python file named your-rule-name.py in ~/.config/thefuck/rules.

    Each rule must implement two mandatory functions:

    • match(command: Command) -> bool: Returns True if the rule should apply to the given command.
    • get_new_command(command: Command) -> str | list[str]: Returns the corrected command or a list of possible corrections.

    Optional components:

    • side_effect(old_command: Command, fixed_command: str) -> None: Performs an action (like changing permissions) when a rule is applied.
    • enabled_by_default: Boolean variable.
    • requires_output: Boolean variable (set to True if the rule needs to inspect command output).
    • priority: Integer variable (lower values are matched first; default is 1000).

    The Command object provides script, output, and script_parts attributes. Note: Rules must not modify the Command object.

    To access global settings within a rule, use: from thefuck.conf import settings

    def match(command):
        return ('permission denied' in command.output.lower() 
                or 'EACCES' in command.output)
    
    
    def get_new_command(command):
        return 'sudo {}'.format(command.script)
    
    # Optional:
    enabled_by_default = True
    
    def side_effect(command, fixed_command):
        import subprocess
        subprocess.call('chmod 777 .', shell=True)
    
    priority = 1000
    requires_output = True
  4. Uninstall The Fuck

    master

    To completely remove The Fuck:

    1. Erase or comment out the thefuck alias line from your shell configuration file (Bash, Zsh, Fish, Powershell, tcsh, etc.).
    2. Use your system's package manager (brew, pip3, pkg, crew, pip) to uninstall the binaries.
  5. Create a third-party rules package

    master

    To distribute a non-public set of rules as a package, name it thefuck_contrib_<name>. The package must follow this structure so The Fuck can locate the rules in the rules module:

    thefuck_contrib_foo
      thefuck_contrib_foo
        rules
          __init__.py
          *third-party rules*
        __init__.py
        *third-party-utils*
      setup.py
  6. Enable experimental instant mode

    master

    Instant mode improves performance by logging output with script and reading the log instead of re-running commands.

    Requirements:

    • Python 3
    • bash or zsh (if using zsh, you must disable its autocorrect function).

    To enable it, add the --enable-experimental-instant-mode flag to your alias initialization in .bashrc, .bash_profile, or .zshrc.

    eval $(thefuck --alias --enable-experimental-instant-mode)
  7. Configure settings via settings.py or environment variables

    master

    You can configure The Fuck using a Python file at $XDG_CONFIG_HOME/thefuck/settings.py (defaults to ~/.config/thefuck/settings.py) or via environment variables.

    Configuration Options

    OptionDescription
    rulesList of enabled rules (default: thefuck.const.DEFAULT_RULES)
    exclude_rulesList of disabled rules (default: [])
    require_confirmationRequires confirmation before running new command (default: True)
    wait_commandMax seconds to wait for previous command output
    no_colorsDisable colored output
    priorityDict of rule priorities; lower priority matches first
    debugEnables debug output (default: False)
    history_limitNumber of history commands to scan (e.g., 2000)
    alter_historyPush fixed command to history (default: True)
    wait_slow_commandMax seconds to wait for output if command is in slow_commands
    slow_commandsList of commands considered slow
    num_close_matchesMax number of close matches to suggest (default: 3)
    excluded_search_path_prefixesPath prefixes to ignore when searching (default: [])
    # Example settings.py
    rules = ['sudo', 'no_command']
    exclude_rules = ['git_push']
    require_confirmation = True
    wait_command = 10
    no_colors = False
    priority = {'sudo': 100, 'no_command': 9999}
    debug = False
    history_limit = 9999
    wait_slow_command = 20
    slow_commands = ['react-native', 'gradle']
    num_close_matches = 5
  8. Reference of default rules

    master

    The following rules are enabled by default across most platforms. They cover common mistakes such as typos, missing arguments, or incorrect command usage.

    Common categories include:

    • Navigation: cd_correction, cd_mkdir, cd_parent.
    • Git: git_add, git_commit_amend, git_push, git_rebase_no_changes, git_pull_uncommitted_changes, etc.
    • Package Managers: npm_wrong_command, pip_install, yarn_command_not_found.
    • System/Shell: sudo, rm_dir, mkdir_p, ls_lah.
    • Language Specific: go_run, python_execute, javac, cargo_no_command.
    ### Default Rules (Selection)
    * `adb_unknown_command` – fixes misspelled commands like `adb logcta`;
    * `ag_literal` – adds `-Q` to `ag` when suggested;
    * `aws_cli` – fixes misspelled commands like `aws dynamdb scan`;
    * `az_cli` – fixes misspelled commands like `az providers`;
    * `cargo` – runs `cargo build` instead of `cargo`;
    * `cargo_no_command` – fixes wrong commands like `cargo buid`;
    * `cat_dir` – replaces `cat` with `ls` when you try to `cat` a directory;
    * `cd_correction` – spellchecks and corrects failed cd commands;
    * `cd_cs` – changes `cs` to `cd`;
    * `cd_mkdir` – creates directories before cd'ing into them;
    * `cd_parent` – changes `cd..` to `cd ..`;
    * `chmod_x` – adds execution bit;
    * `choco_install` – appends common suffixes for chocolatey packages;
    * `composer_not_command` – fixes composer command name;
    * `conda_mistype` – fixes conda commands;
    * `cp_create_destination` – creates a new directory when you attempt to `cp` or `mv` to a non-existent one;
    * `cp_omitting_directory` – adds `-a` when you `cp` directory;
    * `cpp11` – adds missing `-std=c++11` to `g++` or `clang++`;
    * `dirty_untar` – fixes `tar x` command that untarred in the current directory;
    * `dirty_unzip` – fixes `unzip` command that unzipped in the current directory;
    * `django_south_ghost` – adds `--delete-ghost-migrations` to failed because ghosts django south migration;
    * `django_south_merge` – adds `--merge` to inconsistent django south migration;
    * `docker_login` – executes a `docker login` and repeats the previous command;
    * `docker_not_command` – fixes wrong docker commands like `docker tags`;
    * `docker_image_being_used_by_container` – removes the container that is using the image before removing the image;
    * `dry` – fixes repetitions like `git git push`;
    * `fab_command_not_found` – fixes misspelled fabric commands;
    * `fix_alt_space` – replaces Alt+Space with Space character;
    * `fix_file` – opens a file with an error in your `$EDITOR`;
    * `gem_unknown_command` – fixes wrong `gem` commands;
    * `git_add` – fixes "*pathspec 'foo' did not match any file(s) known to git.";
    * `git_add_force` – adds `--force` to `git add <pathspec>...` when paths are .gitignore'd;
    * `git_bisect_usage` – fixes `git bisect strt`, `git bisect goood`, `git bisect rset`, etc. when bisecting;
    * `git_branch_delete` – changes `git branch -d` to `git branch -D`;
    * `git_branch_delete_checked_out` – changes `git branch -d` to `git checkout master && git branch -D` when trying to delete a checked out branch;
    * `git_branch_exists` – offers `git branch -d foo`, `git branch -D foo` or `git checkout foo` when creating a branch that already exists;
    * `git_branch_list` – catches `git branch list` in place of `git branch` and removes created branch;
    * `git_branch_0flag` – fixes commands such as `git branch 0v` and `git branch 0r` removing the created branch;
    * `git_checkout` – fixes branch name or creates new branch;
    * `git_clone_git_clone` – replaces `git clone git clone ...` with `git clone ...`;
    * `git_clone_missing` – adds `git clone` to URLs that appear to link to a git repository;
    * `git_commit_add` – offers `git commit -a ...` or `git commit -p ...` after previous commit if it failed because nothing was staged;
    * `git_commit_amend` – offers `git commit --amend` after previous commit;
    * `git_commit_reset` – offers `git reset HEAD~` after previous commit;
    * `git_diff_no_index` – adds `--no-index` to previous `git diff` on untracked files;
    * `git_diff_staged` – adds `--staged` to previous `git diff` with unexpected output;
    * `git_fix_stash` – fixes `git stash` commands (misspelled subcommand and missing `save`);
    * `git_flag_after_filename` – fixes `fatal: bad flag '...' after filename`;
    * `git_help_aliased` – fixes `git help <alias>` commands replacing <alias> with the aliased command;
    * `git_hook_bypass` – adds `--no-verify` flag previous to `git am`, `git commit`, or `git push` command;
    * `git_lfs_mistype` – fixes mistyped `git lfs <command>` commands;
    * `git_main_master` – fixes incorrect branch name between `main` and `master`;
    * `git_merge` – adds remote to branch names;
    * `git_merge_unrelated` – adds `--allow-unrelated-histories` when required;
    * `git_not_command` – fixes wrong git commands like `git brnch`;
    * `git_pull` – sets upstream before executing previous `git pull`;
    * `git_pull_clone` – clones instead of pulling when the repo does not exist;
    * `git_pull_uncommitted_changes` – stashes changes before pulling and pops them afterwards;
    * `git_push` – adds `--set-upstream origin $branch` to previous failed `git push`;
    * `git_push_different_branch_names` – fixes pushes when local branch name does not match remote branch name;
    * `git_push_pull` – runs `git pull` when `push` was rejected;
    * `git_push_without_commits` – creates an initial commit if you forget and only `git add .`, when setting up a new project;
    * `git_rebase_no_changes` – runs `git rebase --skip` instead of `git rebase --continue` when there are no changes;
    * `git_remote_delete` – replaces `git remote delete remote_name` with `git remote remove remote_name`;
    * `git_rm_local_modifications` – adds `-f` or `--cached` when you try to `rm` a locally modified file;
    * `git_rm_recursive` – adds `-r` when you try to `rm` a directory;
    * `git_rm_staged` – adds `-f` or `--cached` when you try to `rm` a file with staged changes;
    * `git_rebase_merge_dir` – offers `git rebase (--continue | --abort | --skip)` or removing the `.git/rebase-merge` dir when a rebase is in progress;
    * `git_remote_seturl_add` – runs `git remote add` when `git remote set_url` on nonexistent remote;
    * `git_stash` – stashes your local modifications before rebasing or switching branch;
    * `git_stash_pop` – adds your local modifications before popping stash, then resets;
    * `git_tag_force` – adds `--force` to `git tag <tagname>` when the tag already exists;
    * `git_two_dashes` – adds a missing dash to commands like `git commit -amend` or `git rebase -continue`;
    * `go_run` – appends `.go` extension when compiling/running Go programs;
    * `go_unknown_command` – fixes wrong `go` commands, for example `go bulid`;
    * `gradle_no_task` – fixes not found or ambiguous `gradle` task;
    * `gradle_wrapper` – replaces `gradle` with `./gradlew`;
    * `grep_arguments_order` – fixes `grep` arguments order for situations like `grep -lir . test`;
    * `grep_recursive` – adds `-r` when you try to `grep` directory;
    * `grunt_task_not_found` – fixes misspelled `grunt` commands;
    * `gulp_not_task` – fixes misspelled `gulp` tasks;
    * `has_exists_script` – prepends `./` when script/binary exists;
    * `heroku_multiple_apps` – adds `--app <app>` to `heroku` commands like `heroku pg`;
    * `heroku_not_command` – fixes wrong `heroku` commands like `heroku log`;
    * `history` – tries to replace command with the most similar command from history;
    * `hostscli` – tries to fix `hostscli` usage;
    * `ifconfig_device_not_found` – fixes wrong device names like `wlan0` to `wlp2s0`;
    * `java` – removes `.java` extension when running Java programs;
    * `javac` – appends missing `.java` when compiling Java files;
    * `lein_not_task` – fixes wrong `lein` tasks like `lein rpl`;
    * `long_form_help` – changes `-h` to `--help` when the short form version is not supported;
    * `ln_no_hard_link` – catches hard link creation on directories, suggest symbolic link;
    * `ln_s_order` – fixes `ln -s` arguments order;
    * `ls_all` – adds `-A` to `ls` when output is empty;
    * `ls_lah` – adds `-lah` to `ls`;
    * `man` – changes manual section;
    * `man_no_space` – fixes man commands without spaces, for example `mandiff`;
    * `mercurial` – fixes wrong `hg` commands;
    * `missing_space_before_subcommand` – fixes command with missing space like `npminstall`;
    * `mkdir_p` – adds `-p` when you try to create a directory without a parent;
    * `mvn_no_command` – adds `clean package` to `mvn`;
    * `mvn_unknown_lifecycle_phase` – fixes misspelled life cycle phases with `mvn`;
    * `npm_missing_script` – fixes `npm` custom script name in `npm run-script <script>`;
    * `npm_run_script` – adds missing `run-script` for custom `npm` scripts;
    * `npm_wrong_command` – fixes wrong npm commands like `npm urgrade`;
    * `no_command` – fixes wrong console commands, for example `vom/vim`;
    * `no_such_file` – creates missing directories with `mv` and `cp` commands;
    * `omnienv_no_such_command` – fixes wrong commands for `goenv`, `nodenv`, `pyenv` and `rbenv` (eg.: `pyenv isntall` or `goenv list`);
    * `open` – either prepends `http://` to address passed to `open` or creates a new file or directory and passes it to `open`;
    * `pip_install` – fixes permission issues with `pip install` commands by adding `--user` or prepending `sudo` if necessary;
    * `pip_unknown_command` – fixes wrong `pip` commands, for example `pip instatl/pip install`;
    * `php_s` – replaces `-s` by `-S` when trying to run a local php server;
    * `port_already_in_use` – kills process that bound port;
    * `prove_recursively` – adds `-r` when called with directory;
    * `python_command` – prepends `python` when you try to run non-executable/without `./` python script;
    * `python_execute` – appends missing `.py` when executing Python files;
    * `python_module_error` – fixes ModuleNotFoundError by trying to `pip install` that module;
    * `quotation_marks` – fixes uneven usage of `'` and `"` when containing args';
    * `path_from_history` – replaces not found path with a similar absolute path from history;
    * `rails_migrations_pending` – runs pending migrations;
    * `react_native_command_unrecognized` – fixes unrecognized `react-native` commands;
    * `remove_shell_prompt_literal` – removes leading shell prompt symbol `$`, common when copying commands from documentations;
    * `remove_trailing_cedilla` – removes trailing cedillas `ç`, a common typo for European keyboard layouts;
    * `rm_dir` – adds `-rf` when you try to remove a directory;
    * `scm_correction` – corrects wrong scm like `hg log` to `git log`;
    * `sed_unterminated_s` – adds missing '/' to `sed`'s `s` commands;
    * `sl_ls` – changes `sl` to `ls`;
    * `ssh_known_hosts` – removes host from `known_hosts` on warning;
    * `sudo` – prepends `sudo` to the previous command if it failed because of permissions;
    * `sudo_command_from_user_path` – runs commands from users `$PATH` with `sudo`;
    * `switch_lang` – switches command from your local layout to en;
    * `systemctl` – correctly orders parameters of confusing `systemctl`;
    * `terraform_init.py` – runs `terraform init` before plan or apply;
    * `terraform_no_command.py` – fixes unrecognized `terraform` commands;
    * `test.py` – runs `pytest` instead of `test.py`;
    * `touch` – creates missing directories before "touching";
    * `tsuru_login` – runs `tsuru login` if not authenticated or session expired;
    * `tsuru_not_command` – fixes wrong `tsuru` commands like `tsuru shell`;
    * `tmux` – fixes `tmux` commands;
    * `unknown_command` – fixes hadoop hdfs-style "unknown command", for example adds missing '-' to the command on `hdfs dfs ls`;
    * `unsudo` – removes `sudo` from previous command if a process refuses to run on superuser privilege;
    * `vagrant_up` – starts up the vagrant instance;
    * `whois` – fixes `whois` command;
    * `workon_doesnt_exists` – fixes `virtualenvwrapper` env name os suggests to create new;
    * `wrong_hyphen_before_subcommand` – removes an improperly placed hyphen (`apt-install` -> `apt install`, `git-log` -> `git log`, etc.);
    * `yarn_alias` – fixes aliased `yarn` commands like `yarn ls`;
    * `yarn_command_not_found` – fixes misspelled `yarn` commands;
    * `yarn_command_replaced` – fixes replaced `yarn` commands;
    * `yarn_help` – makes it easier to open `yarn` documentation.
  9. Reference of bundled (disabled) rules

    master

    The following rules are included in The Fuck but are not enabled by default. These are typically high-risk commands or commands that might conflict with other rules.

    • git_push_force: Adds --force-with-lease to a git push (may conflict with git_push_pull).
    • rm_root: Adds --no-preserve-root to rm -rf / command.
    ### Bundled (but not enabled by default) commands
    * `git_push_force` – adds `--force-with-lease` to a `git push` (may conflict with `git_push_pull`);
    * `rm_root` – adds `--no-preserve-root` to `rm -rf /` command.
  10. Reference of platform-specific rules

    master

    The following rules are enabled only on specific platforms to provide better integration with system package managers and tools.

    Linux (apt/dnf/yum/pacman/nixos):

    • apt_get, apt_get_search, apt_invalid_operation, apt_list_upgradable, apt_upgrade.
    • dnf_no_such_command.
    • yum_invalid_operation.
    • pacman, pacman_invalid_option, pacman_not_found.
    • nixos_cmd_not_found.

    macOS (brew):

    • brew_cask_dependency, brew_install, brew_reinstall, brew_link, brew_uninstall, brew_unknown_command, brew_update_formula.

    Other:

    • brew_cask_dependency (macOS).
    • pacman (Arch Linux).
    • yum (RHEL/CentOS).
    ### Platform-specific Rules
    * `apt_get` – installs app from apt if it not installed (requires `python-commandnotfound` / `python3-commandnotfound`);
    * `apt_get_search` – changes trying to search using `apt-get` with searching using `apt-cache`;
    * `apt_invalid_operation` – fixes invalid `apt` and `apt-get` calls, like `apt-get isntall vim`;
    * `apt_list_upgradable` – helps you run `apt list --upgradable` after `apt update`;
    * `apt_upgrade` – helps you run `apt upgrade` after `apt list --upgradable`;
    * `brew_cask_dependency` – installs cask dependencies;
    * `brew_install` – fixes formula name for `brew install`;
    * `brew_reinstall` – turns `brew install <formula>` into `brew reinstall <formula>`;
    * `brew_link` – adds `--overwrite --dry-run` if linking fails;
    * `brew_uninstall` – adds `--force` to `brew uninstall if multiple versions were installed;
    * `brew_unknown_command` – fixes wrong brew commands, for example `brew docto/brew doctor`;
    * `brew_update_formula` – turns `brew update <formula>` into `brew upgrade <formula>`;
    * `dnf_no_such_command` – fixes mistyped DNF commands;
    * `nixos_cmd_not_found` – installs apps on NixOS;
    * `pacman` – installs app with `pacman` if it is not installed (uses `yay`, `pikaur` or `yaourt` if available);
    * `pacman_invalid_option` – replaces lowercase `pacman` options with uppercase;
    * `pacman_not_found` – fixes package name with `pacman`, `yay`, `pikaur` or `yaourt`;
    * `yum_invalid_operation` – fixes invalid `yum` calls, like `yum isntall vim`.
  11. Reference: Environment variables for configuration

    master

    Use these environment variables to override settings. For lists, use colon-separated values (e.g., rule1:rule2).

    export THEFUCK_RULES='sudo:no_command'
    export THEFUCK_EXCLUDE_RULES='git_pull:git_push'
    export THEFUCK_REQUIRE_CONFIRMATION='true'
    export THEFUCK_WAIT_COMMAND=10
    export THEFUCK_NO_COLORS='false'
    export THEFUCK_PRIORITY='no_command=9999:apt_get=100'
    export THEFUCK_HISTORY_LIMIT='2000'
    export THEFUCK_NUM_CLOSE_MATCHES='5'