Skip to content

How to sort Python imports with Ruff

This guide assumes you have uv installed. If not, see How to install uv first.

Ruff sorts imports through its linter, not its formatter, and the import-sorting rule I001 is in Ruff’s default rule set. Sorting a file or directory takes no configuration:

$ uvx ruff check --fix .

Add --select I to narrow a run to import sorting alone, which is what you want when you are not ready to act on Ruff’s other findings:

$ uvx ruff check --select I --fix .

Note

I001 became a default rule in Ruff 0.16. On an earlier Ruff, ruff check --fix . reports All checks passed! on unsorted imports and you need --select I or the extend-select block. Check with uvx ruff --version.

Only a project that narrows the rule set with select has to ask for sorting explicitly, by adding it back under [tool.ruff.lint] in pyproject.toml:

[tool.ruff.lint]
extend-select = ["I"]

The rest of this guide covers each path: the command, project configuration, a pre-commit hook, and organize-on-save in VS Code.

Why ruff format doesn’t sort imports

ruff format and ruff check do different jobs, and only ruff check sorts imports. The formatter rewrites code layout (indentation and line wrapping) to match a consistent style. Import order is a lint rule, I001, so it belongs to the linter.

Running the formatter on unsorted imports leaves them unsorted:

$ cat example.py
import pandas
import numpy as np

$ uvx ruff format example.py
1 file left unchanged
$ cat example.py
import pandas
import numpy as np

Running the linter with the I rule sorts them:

$ uvx ruff check --select I --fix example.py
Found 1 error (1 fixed, 0 remaining).
$ cat example.py
import numpy as np
import pandas

To both reorder imports and format the rest of the file, run the linter and the formatter:

$ uvx ruff check --select I --fix .
$ uvx ruff format .

Sort a single file or directory

To sort the imports in one file, pass its name:

$ uvx ruff check --select I --fix example.py

To sort every Python file in the current directory and its subfolders, pass .:

$ uvx ruff check --select I --fix .

--select I limits the run to import sorting and leaves every other lint rule off, which makes it a direct replacement for an isort invocation. The I prefix covers I001 (unsorted-imports), which reorders and groups imports, and I002 (missing-required-import), which adds any imports the project requires in every file. Drop --select I to run import sorting together with the rest of Ruff’s rules.

Add Ruff to a project for ongoing sorting

For repeated use, add Ruff as a development dependency instead of running it through uvx each time:

$ uv add --dev ruff

Sorting needs no project configuration on a current Ruff. From a project, run:

$ uv run ruff check --fix .

--select I is unnecessary here: ruff check sorts imports as part of its normal run. To customize grouping, add a [tool.ruff.lint.isort] section, for example known-first-party = ["my_package"].

Sort imports on every commit with pre-commit

To sort imports automatically before each commit, add Ruff to pre-commit. Create a .pre-commit-config.yaml with the ruff-check and ruff-format hooks:

repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.16.1
    hooks:
      - id: ruff-check
        args: [--select, I, --fix]
      - id: ruff-format

The ruff-check hook sorts imports (--select I --fix) and the ruff-format hook formats the rest of the file. They run in order, so imports are sorted before formatting. Install the hooks once:

$ uvx pre-commit install

From then on, committing a file with unsorted imports rewrites it and stops the commit so the changes can be staged:

$ git commit -m "Add data loader"
ruff check...............................................................Failed
- hook id: ruff-check
- files were modified by this hook

Found 1 error (1 fixed, 0 remaining).

ruff format..............................................................Passed

Stage the fixed file and commit again. Drop --select, I and use args: [--fix] to let the hook apply every rule Ruff has enabled, sorting included. Run uvx pre-commit autoupdate periodically to bump the rev: to the latest Ruff release.

Sort imports on save in VS Code

The Ruff extension (charliermarsh.ruff) can organize imports every time a Python file is saved. Add this to your settings.json:

{
    "[python]": {
        "editor.codeActionsOnSave": {
            "source.organizeImports.ruff": "explicit"
        }
    }
}

source.organizeImports.ruff runs Ruff’s import sorter on save. The .ruff suffix scopes the action to this extension, so it doesn’t trigger another organize-imports provider you have installed. The extension reads the project’s pyproject.toml, ruff.toml, or .ruff.toml, so the grouping matches what ruff check does on the command line.

To also format the file and apply other autofixes on save, set Ruff as the default formatter and add source.fixAll.ruff. See How to configure VS Code for a uv project for the full editor setup.

Learn More

Last updated on