pyproject.toml vs ruff.toml: Which Ruff Config File Should You Use?
I recently started using Ruff to lint and format my Python code, but I got confused by the configuration options. Should I use pyproject.toml or ruff.toml? Which one is better? Let me share what I learned.
The Problem
I installed Ruff in my Python project and wanted to configure it to match my coding style. I noticed that Ruff supports multiple configuration files, but I wasn’t sure which one to choose. The documentation mentioned pyproject.toml, ruff.toml, and even .ruff.toml. What’s the difference?
The Direct Answer
Ruff supports three configuration files:
- pyproject.toml - Requires a
[tool.ruff]section header - ruff.toml - Omits the
[tool.ruff]header andtool.ruffprefix - .ruff.toml - Same syntax as ruff.toml, but with higher precedence
All three files implement the same schema. The only difference is the syntax. If multiple config files exist in the same directory, Ruff follows this precedence order:
.ruff.toml > ruff.toml > pyproject.tomlThis means .ruff.toml takes the highest priority, followed by ruff.toml, and finally pyproject.toml.
Code Examples
Let me show you how each file looks.
pyproject.toml
When using pyproject.toml, you must include the [tool.ruff] section header. Ruff ignores pyproject.toml files that lack this section.
[tool.ruff]line-length = 88target-version = "py39"
[tool.ruff.lint]select = ["E4", "E7", "E9", "F"]ignore = ["E501"]
[tool.ruff.format]quote-style = "double"indent-style = "space"Notice how every Ruff setting starts with [tool.ruff] or [tool.ruff.lint] or [tool.ruff.format].
ruff.toml
The ruff.toml file uses a simpler syntax. You can omit the [tool.ruff] header and the tool.ruff prefix.
line-length = 88target-version = "py39"
[lint]select = ["E4", "E7", "E9", "F"]ignore = ["E501"]
[format]quote-style = "double"indent-style = "space"Compare this to pyproject.toml. The [tool.ruff.lint] becomes just [lint], and [tool.ruff.format] becomes [format].
.ruff.toml
The .ruff.toml file uses the same syntax as ruff.toml. The only difference is the filename and precedence.
line-length = 100target-version = "py39"
[lint]select = ["E4", "E7", "E9", "F"]ignore = ["E501"]
[format]quote-style = "single"Since .ruff.toml has the highest precedence, it will override settings from ruff.toml and pyproject.toml if they exist in the same directory.
Why Would You Choose One Over Another?
Now you might wonder: which one should I use?
Choose pyproject.toml if:
- You already have a pyproject.toml in your project (for packaging, dependencies, etc.)
- You want all tool configurations in one place (Black, MyPy, Pytest, etc. all support pyproject.toml)
- You prefer the standard Python project layout
This is my preferred approach because I can keep all my tool configurations in one file. For example:
[project]name = "my-project"version = "0.1.0"
[tool.ruff]line-length = 88
[tool.black]line-length = 88
[tool.mypy]python_version = "3.9"warn_return_any = trueChoose ruff.toml or .ruff.toml if:
- You don’t have a pyproject.toml (maybe a simple script project)
- You want Ruff-specific settings in a separate file
- You need to override project-level settings locally (use .ruff.toml for this)
The ruff.toml file is cleaner because you don’t need to type [tool.ruff] everywhere.
Common Mistakes to Avoid
I made these mistakes when I started, so let me share them to save you time.
Mistake 1: Missing the [tool.ruff] Header in pyproject.toml
This is the most common mistake. If you add Ruff settings to pyproject.toml without the [tool.ruff] header, Ruff will ignore them completely.
line-length = 88
[lint]select = ["E4", "E7", "E9", "F"][tool.ruff]line-length = 88
[tool.ruff.lint]select = ["E4", "E7", "E9", "F"]Mistake 2: Using Wrong Section Prefix in ruff.toml
In ruff.toml, you should NOT use the [tool.ruff.lint] format. It should be just [lint].
[tool.ruff]line-length = 88
[tool.ruff.lint]select = ["E4", "E7", "E9", "F"]line-length = 88
[lint]select = ["E4", "E7", "E9", "F"]Mistake 3: Creating Multiple Config Files Without Understanding Precedence
If you have both pyproject.toml and ruff.toml in the same directory, ruff.toml takes precedence. This can be confusing when you change settings in pyproject.toml but nothing happens.
Project structure with multiple config files:├── pyproject.toml (line-length = 88)├── ruff.toml (line-length = 100) # This wins!└── src/ └── main.pyIn this case, Ruff will use line-length = 100 from ruff.toml.
Related Knowledge
What is pyproject.toml?
pyproject.toml is the standard configuration file for Python projects, introduced in PEP 518. It specifies build system requirements and can contain configuration for various tools. Many tools support it: Black, MyPy, Pytest, Coverage.py, and of course, Ruff.
What is Ruff?
Ruff is an extremely fast Python linter and formatter written in Rust. It can replace multiple tools: Flake8, isort, pydocstyle, pyupgrade, and Black. It’s 10-100x faster than traditional Python linters.
How Does Ruff Find Config Files?
Ruff searches for configuration files in the following order:
- Explicitly specified via
--configflag orRUFF_CONFIGenvironment variable .ruff.tomlin the current directoryruff.tomlin the current directorypyproject.tomlin the current directory- Parent directories (up to the project root)
Combining Multiple Configurations
Ruff supports extending configurations from other files using the extend option:
extend = "../base-ruff.toml"
[lint]select = ["E4", "E7", "E9", "F", "I"] # Added "I" for import sortingThis is useful for sharing common settings across multiple projects.
Summary
In this post, I explained the three configuration files that Ruff supports: pyproject.toml, ruff.toml, and .ruff.toml. All three implement the same schema, but with slightly different syntax. pyproject.toml requires the [tool.ruff] header, while ruff.toml and .ruff.toml use a cleaner syntax without the prefix. The precedence order is .ruff.toml > ruff.toml > pyproject.toml. I recommend using pyproject.toml if you already have one in your project, as it keeps all tool configurations in one place.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments