# How thefuck Integrates with Third-Party Rule Packages (thefuck_contrib_*)

> Learn how thefuck automatically loads third-party rule packages matching thefuck_contrib_* pattern by scanning sys path and importing rule modules from their rules subdirectories.

- Repository: [Vladimir Iakovlev/thefuck](https://github.com/nvbn/thefuck)
- Tags: internals
- Published: 2026-02-27

---

**The `thefuck` command automatically discovers and loads correction rules from any installed Python package whose name matches the `thefuck_contrib_*` pattern by scanning `sys.path` at startup and importing rule modules found in their `rules/` subdirectories.**

The `nvbn/thefuck` repository provides dozens of built-in rules for correcting mistyped shell commands. However, its architecture treats external packages prefixed with `thefuck_contrib_` as first-class extensions, requiring no manual registration or configuration files to activate them.

## How Third-Party Rule Discovery Works

When `thefuck` initializes, it aggregates rules from three distinct sources:

1. **Bundled rules** – The core package’s `thefuck/rules` directory.
2. **User-defined rules** – Files located in `~/.config/thefuck/rules`.
3. **Third-party rule packages** – Any installed distribution matching the glob pattern `thefuck_contrib_*`.

The discovery of third-party packages happens at runtime in **[`thefuck/corrector.py`](https://github.com/nvbn/thefuck/blob/main/thefuck/corrector.py)**. During initialization, the corrector iterates through every entry in `sys.path` (which includes site-packages directories and virtual environment paths) to locate potential contrib modules.

### Scanning sys.path for Contrib Modules

The specific implementation in [`thefuck/corrector.py`](https://github.com/nvbn/thefuck/blob/main/thefuck/corrector.py) (lines 33-37) uses filesystem globbing to identify candidate packages:

```python
for path in sys.path:
    for contrib_module in Path(path).glob('thefuck_contrib_*'):
        contrib_rules = contrib_module.joinpath('rules')
        if contrib_rules.is_dir():
            yield contrib_rules

```

When you install a package like `pip install thefuck_contrib_foo`, the package directory is automatically added to `sys.path`. The corrector detects the `thefuck_contrib_foo` directory, verifies the existence of a `rules/` subdirectory, and yields that path to the rule loader. This mechanism allows seamless integration without requiring entry points or explicit imports.

## Required Package Structure

According to the **README.md** section "Third-party packages with rules", contrib packages must follow a specific directory layout to ensure automatic discovery:

```

thefuck_contrib_foo/
  thefuck_contrib_foo/
    rules/
      __init__.py
      your_custom_rule.py
    __init__.py
    utils.py
  setup.py

```

Key requirements include:
- The **distribution name** must start with `thefuck_contrib_`.
- The package must contain a `rules/` subdirectory at the top level of the importable package.
- Each rule file must be a valid Python module (`.py` files) containing rule functions that match `thefuck`’s rule API.

## Installing and Using Third-Party Rules

Once installed, contrib rules behave identically to built-in rules. You can verify that your installation worked by inspecting the loaded rules at runtime.

### Installing a Contrib Package

```bash
pip install thefuck_contrib_foo

```

### Verifying Rule Discovery

You can programmatically confirm that rules from a contrib package are available:

```python
from thefuck.corrector import get_rules

# List all rules provided by thefuck_contrib_foo

contrib_rules = [r.name for r in get_rules() if r.name.startswith('foo_')]
print(contrib_rules)  # Output: ['foo_bar', 'foo_baz']

```

### Practical Usage Example

Assume `thefuck_contrib_foo` provides a rule named `foo_sudo` that prepends `sudo` when a command fails with "permission denied":

```bash
$ ls /root
ls: cannot open directory '/root': Permission denied
$ fuck
sudo ls /root [enter/↑/↓/ctrl-c]

```

The rule executes exactly like a native rule because `thefuck` merges contrib rules into the same priority queue used for built-in corrections.

## Configuration and Rule Precedence

While loading is automatic, rule execution is governed by settings in **[`thefuck/conf.py`](https://github.com/nvbn/thefuck/blob/main/thefuck/conf.py)**. The configuration options `rules` (whitelist) and `exclude_rules` (blacklist) apply equally to third-party and built-in rules. If a contrib rule shares a name with an existing rule, the standard precedence rules defined in the corrector determine which suggestion appears first.

## Summary

- **Automatic discovery**: `thefuck` scans `sys.path` for directories matching `thefuck_contrib_*` at startup via [`thefuck/corrector.py`](https://github.com/nvbn/thefuck/blob/main/thefuck/corrector.py).
- **Structure requirement**: Third-party packages must contain a `rules/` subdirectory containing valid rule modules.
- **No registration needed**: Installation via `pip` is sufficient; no configuration changes or explicit imports are required.
- **First-class integration**: Contrib rules are treated identically to built-in rules in terms of execution, configuration, and priority handling.

## Frequently Asked Questions

### How does thefuck discover third-party rule packages?

`thefuck` uses the [`corrector.py`](https://github.com/nvbn/thefuck/blob/main/corrector.py) module to iterate through `sys.path` and glob for directories matching `thefuck_contrib_*`. If a discovered directory contains a `rules/` subdirectory, that path is yielded to the rule loader and included in the global rule set.

### What naming convention must a third-party rule package follow?

The distribution must be named with the prefix `thefuck_contrib_` (e.g., `thefuck_contrib_foo`, `thefuck_contrib_git_extra`). This naming convention triggers the automatic discovery logic in [`thefuck/corrector.py`](https://github.com/nvbn/thefuck/blob/main/thefuck/corrector.py).

### Where should rules be placed within a contrib package?

Rules must reside in a `rules/` subdirectory inside the importable package. For example, `thefuck_contrib_foo/thefuck_contrib_foo/rules/` must exist and contain valid Python rule files. The corrector specifically checks `contrib_module.joinpath('rules').is_dir()` before yielding the path.

### Do third-party rules require manual configuration in thefuck?

No manual configuration is necessary. Once installed via `pip`, the package is automatically detected and loaded on the next invocation of `thefuck`. However, you can use the standard configuration in [`thefuck/conf.py`](https://github.com/nvbn/thefuck/blob/main/thefuck/conf.py) to explicitly enable or disable specific contrib rules using the `rules` or `exclude_rules` settings.