Skip to content

How to Configure Ruff Formatter: quote-style, indent-style, and line-length Settings

I recently switched from Black to Ruff for formatting my Python code. While Ruff’s defaults match Black almost perfectly, I needed to understand how to customize the formatter settings to fit different project requirements.

The Problem: Understanding Ruff’s Format Configuration

When I first started using Ruff, I assumed it was just a linter. Then I discovered Ruff also includes a formatter that can replace Black entirely. But I was confused about where to configure formatting options like quote style and indentation.

The answer is simple: Ruff format settings go in pyproject.toml under the [tool.ruff.format] section. Let me show you how this works.

Ruff Format Default Settings

Ruff intentionally mirrors Black’s defaults, which makes migration painless:

Ruff Format Defaults
line-length: 88 # Same as Black
indent-width: 4 spaces # Standard Python indentation
quote-style: "double" # Black uses double quotes

These defaults mean most projects can switch from Black to Ruff with zero configuration. I tried it on several projects and the formatted output was identical.

Basic Format Configuration

The minimal configuration for Ruff format lives in pyproject.toml:

pyproject.toml
[tool.ruff]
line-length = 88
indent-width = 4
[tool.ruff.format]
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "auto"

The [tool.ruff] section controls the top-level settings that apply to both linting and formatting. The [tool.ruff.format] section contains formatter-specific options.

Understanding Each Format Setting

quote-style

This setting determines which quotes Ruff uses for strings:

pyproject.toml - Double quotes (default)
[tool.ruff.format]
quote-style = "double" # Uses " for strings
pyproject.toml - Single quotes
[tool.ruff.format]
quote-style = "single" # Uses ' for strings

I prefer single quotes for strings (a habit from JavaScript), so I set quote-style = "single" in my projects. Ruff automatically handles quotes inside strings, escaping them when necessary.

indent-style

Controls whether Ruff uses spaces or tabs for indentation:

pyproject.toml - Space indentation (default)
[tool.ruff.format]
indent-style = "space"
pyproject.toml - Tab indentation
[tool.ruff.format]
indent-style = "tab"

Stick with spaces unless your team specifically requires tabs. Python’s PEP 8 recommends spaces, and most formatters use them by default.

skip-magic-trailing-comma

Black introduced the “magic trailing comma” concept. When you put a trailing comma after the last item in a list, dictionary, or function call, Black keeps those items on separate lines:

example.py
# With trailing comma - Black preserves multi-line format
items = [
"first",
"second",
"third", # <- This comma is magic
]
# Without trailing comma - Black may collapse to single line
items = ["first", "second", "third"]

By default, Ruff respects this behavior:

pyproject.toml
[tool.ruff.format]
skip-magic-trailing-comma = false # Respects trailing commas (default)

Set skip-magic-trailing-comma = true to ignore trailing commas and let Ruff decide the formatting purely based on line length.

line-ending

Controls line endings (LF vs CRLF):

pyproject.toml
[tool.ruff.format]
line-ending = "auto" # Detects from file (default)
# Or explicitly:
# line-ending = "lf" # Unix/Linux/macOS
# line-ending = "crlf" # Windows

Use "auto" unless you have specific requirements. Git can handle line ending normalization via .gitattributes.

Advanced Format Settings

docstring-code-format

This is my favorite Ruff formatter feature. It formats code inside docstrings:

pyproject.toml
[tool.ruff.format]
docstring-code-format = true
docstring-code-line-length = "dynamic"

When enabled, Ruff formats code examples in docstrings:

example.py
def calculate_sum(numbers):
"""
Calculate the sum of a list of numbers.
Example:
>>> numbers = [1, 2, 3, 4, 5]
>>> result = calculate_sum(numbers)
>>> print(result)
15
Args:
numbers: A list of numbers to sum.
Returns:
The sum of all numbers.
"""
return sum(numbers)

The docstring-code-line-length option can be:

  • "dynamic": Use the docstring’s indentation as the line length limit
  • A specific number like 60: Use that as the line length limit

exclude Files from Formatting

You can exclude specific files or patterns from formatting:

pyproject.toml
[tool.ruff.format]
exclude = [
"migrations/*",
"generated/*",
"legacy_code.py",
]

This is useful for generated code or files from legacy systems that you don’t want to reformat.

A Complete Example Configuration

Here’s a configuration I use for new projects:

pyproject.toml
[tool.ruff]
target-version = "py311"
line-length = 100
indent-width = 4
[tool.ruff.lint]
select = ["E", "F", "I", "N", "W", "D"]
ignore = ["D100", "D104"]
[tool.ruff.format]
quote-style = "single"
indent-style = "space"
docstring-code-format = true
docstring-code-line-length = "dynamic"
[tool.ruff.lint.pydocstyle]
convention = "google"

This configuration uses:

  • 100 character line length (slightly longer than default)
  • Single quotes for strings
  • Google-style docstrings
  • Automatic docstring code formatting

Common Mistakes to Avoid

Mismatch Between Format and Lint Settings

If you change line-length in [tool.ruff], both the formatter and linter use it. But if you only change it in the formatter, the linter still uses 88:

pyproject.toml - WRONG
[tool.ruff]
# line-length not set, defaults to 88
[tool.ruff.format]
# This only affects formatting, not linting!
# E501 (line too long) will still use 88
line-length = 100 # This won't work!
pyproject.toml - CORRECT
[tool.ruff]
line-length = 100 # This applies to both linter and formatter
[tool.ruff.format]
# No need to set line-length here

Enabling docstring-code-line-length Without docstring-code-format

pyproject.toml - WRONG
[tool.ruff.format]
# docstring-code-format is false by default!
docstring-code-line-length = "dynamic" # This has no effect
pyproject.toml - CORRECT
[tool.ruff.format]
docstring-code-format = true
docstring-code-line-length = "dynamic" # Now this works

Excluding Files from Formatting But Not Linting

If you exclude a file from formatting, it still gets linted:

pyproject.toml
[tool.ruff.format]
exclude = ["generated/*"] # Not formatted
[tool.ruff.lint]
# generated/* is still linted! Add exclude here too if needed
exclude = ["generated/*"]

Ruff’s formatter is designed to be a drop-in replacement for Black. The key differences are:

  1. Speed: Ruff is written in Rust and can be 100x faster than Black
  2. Integration: Ruff combines linting and formatting in one tool
  3. Configuration: Ruff uses pyproject.toml exclusively; Black supports multiple config files

The formatting output should be nearly identical to Black for most code. There are minor edge cases where they differ, but Ruff documents these clearly in their compatibility guide.

Running Ruff Format

After configuring your settings, run the formatter:

Terminal
# Check formatting without changing files
ruff format --check .
# Format files in place
ruff format .
# Format specific files
ruff format src/

I recommend running ruff format --check in your CI pipeline to catch formatting issues before they reach the main branch.

In this post, I explained how to configure Ruff’s formatter settings including quote-style, indent-style, and line-length. I covered the default settings that match Black, explained each format option with examples, and highlighted common configuration mistakes. I also shared a complete example configuration and showed how to run the formatter from the command line.

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