Minimum Required Functions for a TheFuck Rule: Match and Get_new_command Explained

Every thefuck rule must expose exactly two functions—match(command) to determine applicability and get_new_command(command) to generate the correction—or the engine will ignore the module.

The nvbn/thefuck repository is a popular Python command-line tool that corrects errors in previous console commands. To extend its functionality with custom behaviors, developers create Python modules under thefuck/rules/ that conform to a strict two-function contract recognized by the core engine.

The Two Required Functions

The core engine in thefuck/main.py dynamically imports every module in thefuck/rules/ and inspects it for two specific callables. If either is missing, the rule is silently skipped.

The match Function

The match(command) function receives a thefuck.main.Command object and returns a truthy value when the rule can fix the given error.

def match(command):
    """Return True when this rule applies."""
    return 'error' in command.output.lower()

This function acts as the gatekeeper. According to the source code, the engine calls match() first; only if it returns True does it proceed to generate corrections.

The get_new_command Function

The get_new_command(command) function generates one or more corrected command strings that thefuck suggests to the user.

def get_new_command(command):
    """Return the corrected command."""
    return 'corrected-command'

This function can return a single string or a list of strings when multiple alternatives exist. The engine invokes this only after match() returns a truthy value.

Optional Components

While only match and get_new_command are strictly required, rules often include additional attributes to modify behavior.

  • priority: An integer that determines execution order. Higher values run first. For example, thefuck/rules/no_command.py sets priority = 3000.
  • side_effect: A function side_effect(old_cmd, command) that executes after the user accepts a suggestion, used by rules like dirty_unzip to modify files.
  • Decorators: Wrappers like @sudo_support or @git_support restrict rules to run only when underlying tools are available, as seen in thefuck/rules/git_push.py.
  • Helper functions: Private functions like _get_used_executables that assist the main logic but are ignored by the engine.

Minimal Viable Rule Skeleton

The smallest possible valid rule requires only the two mandatory functions:


# thefuck/rules/example.py

def match(command):
    """Return True when this rule applies."""
    return command.script == 'foo'

def get_new_command(command):
    """Return the corrected command."""
    return 'bar'

This skeleton satisfies the engine's requirements and will be loaded and executed if match() returns True.

Real-World Examples from the Source Code

Examining the actual nvbn/thefuck source code reveals how required and optional components interact.

The no_command Rule

Located in thefuck/rules/no_command.py, this rule suggests valid commands when you mistype an executable name:


# thefuck/rules/no_command.py

@sudo_support
def match(command):
    return (not which(command.script_parts[0]) and
            ('not found' in command.output or
             'is not recognized as' in command.output) and
            bool(get_close_matches(command.script_parts[0],
                                   get_all_executables())))

def get_new_command(command):
    old = command.script_parts[0]
    candidates = get_close_matches(old, get_all_executables())
    return [command.script.replace(old, c, 1) for c in candidates]

priority = 3000

This example demonstrates both required functions plus the optional priority attribute and @sudo_support decorator.

The unsudo Rule

The thefuck/rules/unsudo.py module provides a minimal implementation without optional components:


# thefuck/rules/unsudo.py

patterns = ['you cannot perform this operation as root']

def match(command):
    if command.script_parts and command.script_parts[0] != 'sudo':
        return False
    return any(p in command.output.lower() for p in patterns)

def get_new_command(command):
    return ' '.join(command.script_parts[1:])

Here, priority defaults to 0 and no decorators are used, proving that only the two core functions are essential.

The git_push Rule

Found in thefuck/rules/git_push.py, this rule uses the optional @git_support decorator to ensure it only runs for git-related errors:


# thefuck/rules/git_push.py

@git_support
def match(command):
    return ('push' in command.script_parts and
            'git push --set-upstream' in command.output)

def get_new_command(command):
    # Returns corrected git command

    pass

This illustrates how optional decorators complement the required function pair without replacing them.

How the Engine Loads Rules

The rule discovery mechanism lives in thefuck/main.py. During initialization, the engine iterates through all Python files in thefuck/rules/ and inspects each module for the match and get_new_command symbols. If both exist, the rule is registered; otherwise, the module is ignored. This strict contract ensures that every loaded rule can both detect its applicable scenario and provide a meaningful correction.

Summary

  • Two functions are mandatory: match(command) and get_new_command(command).
  • Both receive a thefuck.main.Command object containing the script and output.
  • Optional enhancements include priority, side_effect, and decorators like @git_support.
  • File location: Rules reside in thefuck/rules/ as standard Python modules.
  • Engine behavior: thefuck/main.py loads only modules exposing both required functions.

Frequently Asked Questions

What happens if a rule is missing the match function?

The engine in thefuck/main.py checks for both match and get_new_command when loading modules from thefuck/rules/. If either function is missing, the module is silently ignored and will not participate in error correction.

Can a rule suggest multiple corrections?

Yes. While get_new_command can return a single string, returning a list of strings causes thefuck to present multiple suggestions. The no_command rule in thefuck/rules/no_command.py uses this technique to suggest several close executable matches.

Is the priority attribute required?

No. The priority attribute is optional and defaults to 0 when omitted. Rules with higher priority values execute before those with lower values, allowing fine-grained control over suggestion ordering.

Can I use decorators like @sudo_support on any function?

Decorators like @sudo_support and @git_support are optional utilities found in the thefuck source code. They wrap the match function to check for tool availability before execution, but they are not required for a rule to function.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →