# Black User Guide

**Black** is the uncompromising Python code formatter. You give it your source files; it rewrites them into a single, deterministic style so you never argue about formatting again. By using Black, you cede control over the minutiae of hand-formatting — and in return you get speed, determinism, and freedom from formatting nags. Blackened code looks the same regardless of the project you are reading, which makes diffs smaller and code review faster.

This guide covers everything you need to install Black, format your code, configure it for your project, and integrate it into your editor and CI. Every command, option, and default below is taken directly from Black's source.

> [!NOTE]
> Black requires **Python 3.10 or newer** to run. It can format code targeting much older Python versions (back to 3.3), but the Black process itself needs 3.10+.

---

## 1. Quick Start

Install Black and format a file or directory in three steps.

```bash
# 1. Install
pip install black

# 2. Format a single file (rewrites it in place)
black your_script.py

# 3. Or format an entire project
black .
```

When Black finishes, it prints a short summary:

```text
reformatted your_script.py

All done! ✨ 🍰 ✨
1 file reformatted.
```

If your code was already perfectly formatted, you'll see:

```text
All done! ✨ 🍰 ✨
1 file left unchanged.
```

> [!TIP]
> Before letting Black rewrite a whole project, run it in preview mode first to see what *would* change without touching any files:
> ```bash
> black --check --diff .
> ```
> `--check` tells you whether anything would change (via the exit code), and `--diff` prints the exact changes as a unified diff.

That's the whole product. Black is deliberately about **sensible defaults** — if you are asking yourself "do I need to configure anything?", the answer is almost always "no".

---

## 2. Installation

Black is distributed on PyPI as the `black` package. It ships several optional "extras" that pull in additional dependencies for specific features.

=== "Base install"

    ```bash
    pip install black
    ```

    Gives you the `black` and `python -m black` commands. This is all most users ever need.

=== "Jupyter Notebooks"

    ```bash
    pip install "black[jupyter]"
    ```

    Adds support for formatting `.ipynb` notebook files. Pulls in `ipython` and `tokenize-rt`.

=== "Colored output on Windows"

    ```bash
    pip install "black[colorama]"
    ```

    Adds `colorama` so that `--color` diffs render correctly in the Windows terminal.

=== "Faster startup (uvloop)"

    ```bash
    pip install "black[uvloop]"
    ```

    Installs `uvloop` (Linux/macOS) or `winloop` (Windows) for a faster event loop when formatting many files in parallel.

=== "Format server (blackd)"

    ```bash
    pip install "black[d]"
    ```

    Installs `aiohttp` and enables the `blackd` HTTP formatting server (see [Section 8](#8-the-blackd-format-server)).

You can combine extras: `pip install "black[jupyter,colorama]"`.

### Verify the installation

```bash
black --version
```

```text
black, 25.x.x (compiled: yes)
Python (CPython) 3.12.6
```

The `compiled: yes/no` field tells you whether you installed a **mypyc-compiled** build. Compiled builds run significantly faster; the pure-Python build behaves identically but is slower.

> [!NOTE]
> If running `black` as a script doesn't work (for example, the entry point isn't on your `PATH`), you can always invoke it as a module:
> ```bash
> python -m black your_script.py
> ```

### Run Black without installing it

If you just want to format something once, [`pipx`](https://pipx.pypa.io/) and [`uvx`](https://docs.astral.sh/uv/) let you run Black in a throwaway environment:

```bash
pipx run black .
# or
uvx black .
```

---

## 3. Everyday Usage

Black's core job is simple: point it at code, and it reformats that code.

### Format files and directories

You can pass any mix of files and directories. Black walks directories recursively, finding every `.py`, `.pyi`, and `.ipynb` file.

```bash
black src/ tests/ setup.py
```

```text
reformatted src/app/models.py
reformatted tests/test_models.py

All done! ✨ 🍰 ✨
2 files reformatted, 14 files left unchanged.
```

> [!TIP]
> Black is safe to run repeatedly. It is **idempotent**: running it on already-formatted code changes nothing. There's no harm in formatting your whole project on every commit.

### Format code from a string

Use `-c` / `--code` to format a snippet directly, printing the result to stdout. This never touches any file.

```bash
black -c "def f(x:int=1)->None: print( x )"
```

```text
def f(x: int = 1) -> None:
    print(x)
```

### Format from standard input

Pass `-` as the source to read from stdin and write the formatted result to stdout. This is how most editor plugins talk to Black.

```bash
cat your_script.py | black -
```

> [!IMPORTANT]
> When reading from stdin, Black can't see the filename, so it can't honor `--force-exclude` or pick the right mode for `.pyi`/`.ipynb` files. Use `--stdin-filename` to tell Black what the file is really called:
> ```bash
> cat stub.pyi | black --stdin-filename=stub.pyi -
> ```

### Preview changes without writing them

| You want to… | Command | Effect |
|---|---|---|
| See if anything would change | `black --check .` | Writes nothing. Exit code `0` = no changes needed, `1` = changes needed. |
| See exactly what would change | `black --diff .` | Prints a unified diff to stdout. Writes nothing. |
| Both, with color | `black --check --diff --color .` | Colored diff + status exit code. |

```bash
black --check --diff src/app/models.py
```

```text
--- src/app/models.py	2026-06-05 12:00:00.000000+00:00
+++ src/app/models.py	2026-06-05 12:00:01.000000+00:00
@@ -1,3 +1,3 @@
-def f(x:int=1)->None:
-    print( x )
+def f(x: int = 1) -> None:
+    print(x)
would reformat src/app/models.py

Oh no! 💥 💔 💥
1 file would be reformatted.
```

> [!TIP]
> `--check` is the option you want in continuous integration. It fails the build (exit code 1) when someone forgot to run Black, without modifying any files. See [Section 7](#7-continuous-integration).

### Control the output volume

| Option | Behavior |
|---|---|
| `-v` / `--verbose` | Report files that were left unchanged or skipped, and which config file is in use. |
| `-q` / `--quiet` | Suppress all non-critical output. Error messages still appear (silence them with `2>/dev/null`). |

---

## 4. Common Tasks (Recipes)

### Format only specific line ranges

When you only want to format the lines you actually touched — useful for gradually adopting Black on a large legacy file — use `--line-ranges`. Ranges are **1-based and inclusive** on both ends, given as `START-END`. Repeat the option to format multiple ranges.

```bash
black --line-ranges=10-20 --line-ranges=45-50 legacy_module.py
```

> [!WARNING]
> `--line-ranges` only works on a **single file at a time** and is incompatible with Jupyter notebooks (`--ipynb`). Black will exit with an error if you combine it with multiple files.

### Skip formatting a region of code

Black reads special comment directives in your source. These let you opt specific code out of formatting:

| Directive | Effect |
|---|---|
| `# fmt: off` | Stop formatting from this line onward. |
| `# fmt: on` | Resume formatting (pairs with a preceding `# fmt: off`). |
| `# fmt: skip` | Leave **this one line/statement** exactly as written. |

```python
# fmt: off
custom_matrix = [
    1, 0, 0,
    0, 1, 0,
    0, 0, 1,
]
# fmt: on

WIDE_TABLE = {'a': 1,  'b': 2,   'c': 3}  # fmt: skip
```

> [!NOTE]
> For compatibility, Black also recognizes [YAPF](https://github.com/google/yapf)'s `# yapf: disable` and `# yapf: enable` as aliases for `# fmt: off` and `# fmt: on`. Both spellings with and without a space after the colon work (`# fmt:off` and `# fmt: off`).

### Keep a collection exploded with the magic trailing comma

If you add a trailing comma to a bracketed collection, Black treats that as a signal that you *want* it expanded one-item-per-line, and it won't collapse it back:

```python
# You write this (note the trailing comma after "three"):
COLORS = ["one", "two", "three",]

# Black keeps it exploded:
COLORS = [
    "one",
    "two",
    "three",
]
```

Remove the trailing comma and Black will collapse short collections back onto one line. To disable this behavior entirely, pass `-C` / `--skip-magic-trailing-comma`.

### Format Jupyter notebooks

With the `jupyter` extra installed, Black formats the Python code cells inside `.ipynb` files, automatically masking IPython magics (`%timeit`, `!ls`, etc.) so they don't break parsing.

```bash
black notebooks/analysis.ipynb
```

To treat input piped on stdin as a notebook regardless of its extension, add `--ipynb`. To teach Black that a custom cell magic contains Python (so it formats the cell body), use `--python-cell-magics`:

```bash
black --python-cell-magics=my_magic --python-cell-magics=custom notebook.ipynb
```

### Format typing stub (`.pyi`) files

Black automatically formats `.pyi` files using stub-specific rules (e.g. different blank-line conventions). To force stub formatting on stdin or non-`.pyi` files, pass `--pyi`.

### Require everyone to use the same Black version

Different Black releases can format code slightly differently. To guarantee everyone on a team uses the same version, set `--required-version`. Black exits with an error if the running version doesn't match:

```bash
black --required-version=25.1.0 .
```

This is best set in your `pyproject.toml` (see [Section 5](#5-configuration)) so it applies everywhere automatically.

### Go faster on large codebases

| Option | Effect |
|---|---|
| `-W` / `--workers N` | Use `N` parallel worker processes (default: number of CPUs). |
| `--fast` | Skip the post-format AST safety check (faster, slightly riskier). |
| `--no-cache` | Ignore the cache and reformat every file (mostly for debugging). |

```bash
black --workers=8 .
```

> [!TIP]
> Black caches formatting results, so the second run over an unchanged project is nearly instant. You rarely need `--no-cache`.

---

## 5. Configuration

Black is "all about sensible defaults", but you can override them per-project. Black reads its default option values from a `pyproject.toml` file, so you set them once and every team member and CI run picks them up automatically.

### The `[tool.black]` section

Put a `[tool.black]` table in your `pyproject.toml`. **The keys are the long names of the command-line options**, with dashes replaced by underscores (or kept as dashes — both are accepted).

```toml
[tool.black]
line-length = 100
target-version = ["py310", "py311", "py312"]
skip-string-normalization = false
extend-exclude = '''
/(
    migrations
    | build
)/
'''
```

The table below maps every configurable CLI option to its `pyproject.toml` key and default.

| CLI option | `pyproject.toml` key | Default | Meaning |
|---|---|---|---|
| `--line-length` | `line-length` | `88` | Maximum characters per line. |
| `--target-version` | `target-version` | *auto-detected* | Python versions your output must support (a **list**). |
| `--skip-string-normalization` | `skip-string-normalization` | `false` | Keep your original quote style instead of preferring double quotes. |
| `--skip-magic-trailing-comma` | `skip-magic-trailing-comma` | `false` | Ignore trailing commas as a split signal. |
| `--skip-source-first-line` | `skip-source-first-line` | `false` | Leave the first line of each file untouched. |
| `--preview` | `preview` | `false` | Opt into upcoming stable-style changes. |
| `--unstable` | `unstable` | `false` | Opt into preview **plus** known-buggy experimental changes. |
| `--include` | `include` | `(\.pyi?\|\.ipynb)$` | Regex of filenames to include in recursive search. |
| `--exclude` | `exclude` | *(see below)* | Regex of paths to exclude (overrides the defaults). |
| `--extend-exclude` | `extend-exclude` | — | Regex of paths to exclude **in addition** to the defaults. |
| `--force-exclude` | `force-exclude` | — | Like exclude, but also applies to paths passed explicitly. |
| `--required-version` | `required-version` | — | Fail unless this Black version is running. |
| `--workers` | `workers` | *CPU count* | Number of parallel worker processes. |

> [!IMPORTANT]
> In TOML, regular expressions must use **single-quoted** strings (the equivalent of Python raw strings), and multi-line strings are treated as **verbose** regexes (whitespace and `#` comments are ignored). This is why the `extend-exclude` example above is formatted across several lines.

> [!WARNING]
> `--line-ranges` **cannot** be set in `pyproject.toml` — it only makes sense per-invocation. Black raises an error if it finds a `line_ranges` key in your config file.

### How Black finds your configuration

Black locates the project root by walking up from the files you passed, looking for the first directory that contains any of:

1. A `.git` directory
2. A `.hg` directory
3. A `pyproject.toml` file **that contains a `[tool.black]` section**

It then reads `pyproject.toml` from that root. Run with `-v` to see which root and config file Black chose:

```bash
black -v .
```

```text
Identified `/home/you/project` as project root containing a pyproject.toml.
Using configuration from project root.
```

You can point at a specific config file with `--config`:

```bash
black --config=/path/to/black.toml src/
```

If no project-level config is found, Black falls back to a **user-level** config file:

- **Windows:** `~\.black`
- **macOS / Linux:** `~/.config/black` (or `$XDG_CONFIG_HOME/black` if set)

### Target version auto-detection

If you don't set `target-version`, Black tries to figure out which Python versions your output must support:

1. First, it reads `requires-python` from the `[project]` table of your `pyproject.toml` (the PEP 621 metadata).
2. If that's inconclusive, it auto-detects per file based on the syntax features each file actually uses.

So in a well-formed modern project, you usually don't need to set `target-version` at all.

> [!TIP]
> Setting `target-version` explicitly is still worthwhile when you want Black to use newer formatting (like trailing commas after `*args`) that's only safe on certain Python versions. List **every** version your code supports, e.g. `["py310", "py311"]`.

### Invalid config keys

If you misspell a key in `[tool.black]`, Black warns you but continues:

```text
Invalid config keys detected: 'line_lenght' (in /home/you/project/pyproject.toml)
```

---

## 6. Editor & Version Control Integration

### pre-commit

Black ships [pre-commit](https://pre-commit.com/) hooks. Add this to your `.pre-commit-config.yaml`:

```yaml
repos:
  - repo: https://github.com/psf/black-pre-commit-mirror
    rev: 25.1.0   # use the version you pin
    hooks:
      - id: black
        # For Jupyter notebooks, use this hook instead:
        # - id: black-jupyter
```

> [!TIP]
> Black recommends the dedicated **`psf/black-pre-commit-mirror`** repository rather than hooking `psf/black` directly. The mirror runs about **2× faster** because it doesn't have to build Black from source.

The two available hook IDs are:

| Hook ID | Formats |
|---|---|
| `black` | `.py` and `.pyi` files |
| `black-jupyter` | `.py`, `.pyi`, **and** `.ipynb` files (installs the `jupyter` extra automatically) |

### Editors

Most editors integrate by piping the buffer through `black -` (with `--stdin-filename` set so excludes are respected). Black is also commonly driven through the [Language Server Protocol](https://black.readthedocs.io/) via companion projects. Consult your editor's Python tooling docs; the underlying command is always the same `black -` stdin invocation shown in [Section 3](#format-from-standard-input).

### Show your style

Let people know your project uses Black with the badge:

```md
[Code style: black](https://github.com/psf/black)
```

---

## 7. Continuous Integration

### The official GitHub Action

Black publishes a GitHub Action. In a workflow:

```yaml
- uses: psf/black@stable
  with:
    options: "--check --diff"
    src: "./src"
```

The Action accepts these inputs:

| Input | Default | Description |
|---|---|---|
| `options` | `"--check --diff"` | Options passed to Black. |
| `src` | `"."` | Paths to format. |
| `jupyter` | `false` | Set `true` to also format Jupyter notebooks. |
| `version` | *(latest)* | A PEP 440 version specifier, e.g. `"25.1.0"`. |
| `use_pyproject` | `false` | Read the Black version from your `pyproject.toml` instead. |
| `summary` | `true` | Add Black's output to the GitHub job summary. |
| `output-file` | — | Also write Black's output to a file (keeps logs clean when using `--diff`). |
| ~~`black_args`~~ | — | **Deprecated.** Use `options` + `src` instead. |

> [!IMPORTANT]
> `version` and `use_pyproject` are **mutually exclusive** — set one or the other, not both. The Action will fail if you provide both.

### Exit codes

Black's exit code is what makes CI work. Use it directly in any CI system:

| Exit code | Meaning |
|---|---|
| `0` | Success. With `--check`: nothing would be reformatted. |
| `1` | With `--check`: one or more files **would** be reformatted. |
| `123` | An internal error occurred while processing a file. |

```bash
# Typical CI step
black --check --diff . || exit 1
```

---

## 8. The `blackd` Format Server

`blackd` is a small HTTP server that formats code on demand. It's intended for editor and tooling integrations that want to avoid paying Black's startup cost on every keystroke. It requires the `d` extra (`pip install "black[d]"`).

### Start the server

```bash
blackd --bind-host=localhost --bind-port=45484
```

```text
blackd version 25.x.x listening on localhost port 45484
```

| Option | Default | Description |
|---|---|---|
| `--bind-host` | `localhost` | Address to bind to. |
| `--bind-port` | `45484` | Port to listen on. |
| `--cors-allow-origin` | — | An origin allowed to access blackd via CORS. Repeat for multiple origins. |
| `--max-body-size` | `5242880` (5 MiB) | Maximum request body size in bytes. |

### Make a request

Send the unformatted code as the raw `POST /` body. Formatting options are passed as `X-*` request headers.

```bash
curl -s -XPOST "http://localhost:45484" \
  -H "X-Line-Length: 100" \
  -H "X-Skip-String-Normalization: yes" \
  --data-binary @your_script.py
```

The response carries the formatted code, plus an `X-Black-Version` header.

**Request headers** (all optional):

| Header | Corresponds to |
|---|---|
| `X-Protocol-Version` | Must be `1` (the only supported version). |
| `X-Line-Length` | `--line-length` |
| `X-Python-Variant` | `--target-version` (e.g. `py3.10,py3.11`), or `pyi`. |
| `X-Skip-Source-First-Line` | `--skip-source-first-line` |
| `X-Skip-String-Normalization` | `--skip-string-normalization` |
| `X-Skip-Magic-Trailing-Comma` | `--skip-magic-trailing-comma` |
| `X-Preview` | `--preview` |
| `X-Unstable` | `--unstable` |
| `X-Enable-Unstable-Feature` | `--enable-unstable-feature` (comma-separated). |
| `X-Fast-Or-Safe` | `fast` to skip the safety check. |
| `X-Diff` | Return a unified diff instead of the formatted code. |

**Response status codes:**

| Status | Meaning |
|---|---|
| `200` | Code was reformatted; body is the result. |
| `204` | Input was already well-formatted; nothing returned. |
| `400` | Input had a syntax error, or a header was invalid. |
| `500` | An unexpected error occurred while formatting. |
| `501` | Requested protocol version is not supported. |

> [!CAUTION]
> `blackd` performs no authentication. Bind it to `localhost` (the default) and never expose it directly to an untrusted network. Use `--cors-allow-origin` only for the specific browser origins you trust.

---

## 9. The Black Code Style (What to Expect)

Black is a PEP 8–compliant, opinionated formatter. It reformats entire files in place and deliberately offers **very few** style knobs. A few highlights of what it does:

- **Line length** defaults to 88 characters — a deliberate ~10% increase over PEP 8's 79, found to reduce total lines without hurting readability.
- **Strings** are normalized to double quotes (`"like this"`), unless that would require more escaping. Disable with `-S`.
- **Magic trailing comma**: a trailing comma forces a collection to stay expanded (see [Section 4](#keep-a-collection-exploded-with-the-magic-trailing-comma)).
- **Smallest diffs**: Black aims to produce the minimal change, so code review focuses on content, not formatting.

> [!NOTE]
> Black is intentionally stable. Now that it has reached maturity, you should not expect large formatting changes between releases — stylistic changes are mostly responses to bug reports and support for new Python syntax. New ideas land behind `--preview` first.

### Preview and unstable styles

Black gates experimental formatting behind two flags so it can gather feedback before making changes permanent:

| Flag | What it enables |
|---|---|
| `--preview` | Potentially disruptive changes likely to become part of the next stable release. |
| `--unstable` | Everything in `--preview`, **plus** changes with known bugs. Implies `--preview`. |
| `--enable-unstable-feature NAME` | Turn on one specific experimental feature. Requires `--preview`. |

> [!WARNING]
> No compatibility guarantees are made for `--unstable` or individually enabled unstable features — their behavior and even their existence can change between releases. Don't depend on them in shared configuration unless you accept churn.

### The safety check

By default (`--safe`), after formatting a file Black re-parses both the original and the result and confirms they produce an equivalent abstract syntax tree, and that a second formatting pass wouldn't change anything. If either check fails, Black aborts with an internal-error message and a link to file a bug — it will **never** knowingly write code that means something different from your original. Pass `--fast` to skip these checks when you value speed over the extra guarantee.

---

## 10. Complete CLI Reference

Every option of the `black` command, taken directly from the source.

| Option | Argument | Description |
|---|---|---|
| `SRC ...` | paths | Files/directories to format. Use `-` for stdin. |
| `-c`, `--code` | TEXT | Format the code passed as a string and print the result. |
| `-l`, `--line-length` | INT | Characters per line allowed. Default `88`. |
| `-t`, `--target-version` | py33…py315 | Python version(s) the output must support. Repeatable. |
| `--pyi` | flag | Format input as typing stubs regardless of extension. |
| `--ipynb` | flag | Format input as Jupyter notebooks regardless of extension. |
| `--python-cell-magics` | TEXT | Treat this notebook cell magic as containing Python. Repeatable. |
| `-x`, `--skip-source-first-line` | flag | Don't format the first line of the file. |
| `-S`, `--skip-string-normalization` | flag | Don't normalize string quotes or prefixes. |
| `-C`, `--skip-magic-trailing-comma` | flag | Don't use trailing commas as a reason to split lines. |
| `--preview` | flag | Enable upcoming stable-style changes. |
| `--unstable` | flag | Enable preview + known-buggy changes. Implies `--preview`. |
| `--enable-unstable-feature` | NAME | Enable one specific unstable feature. Requires `--preview`. Repeatable. |
| `--check` | flag | Don't write; exit `0`/`1` based on whether changes are needed. |
| `--diff` | flag | Don't write; print a unified diff to stdout. |
| `--color` / `--no-color` | flag | Show (or hide) colored diff. Only applies with `--diff`. |
| `--line-ranges` | START-END | Format only these 1-based inclusive line ranges. Repeatable. Single file only. |
| `--fast` / `--safe` | flag | Skip (or run) the post-format AST safety check. Default `--safe`. |
| `--required-version` | TEXT | Fail unless this exact Black version is running. |
| `--exclude` | REGEX | Paths to exclude on recursive search (overrides defaults). |
| `--extend-exclude` | REGEX | Paths to exclude in addition to the defaults. |
| `--force-exclude` | REGEX | Like `--exclude`, but also applies to explicitly-passed paths. |
| `--stdin-filename` | TEXT | The filename to assume for stdin input. |
| `--include` | REGEX | Paths to include on recursive search. Default `(\.pyi?\|\.ipynb)$`. |
| `-W`, `--workers` | INT | Number of parallel worker processes. Default: CPU count. |
| `--config` | PATH | Read options from this configuration file. |
| `--no-cache` | flag | Skip reading/writing the cache; reformat everything. |
| `-q`, `--quiet` | flag | Suppress non-critical output. |
| `-v`, `--verbose` | flag | Report unchanged/skipped files and the config in use. |
| `--version` | flag | Show version (and whether it's compiled) and exit. |
| `-h`, `--help` | flag | Show help and exit. |

### Environment variables

| Variable | Effect |
|---|---|
| `BLACK_CACHE_DIR` | Override where Black stores its formatting cache. |
| `BLACK_NUM_WORKERS` | Set the default number of parallel workers (same as `--workers`). |
| `XDG_CONFIG_HOME` | On Unix, where Black looks for the user-level config (`$XDG_CONFIG_HOME/black`). |

---

## 11. Troubleshooting

### Error: `One of 'SRC' or 'code' is required.`

**Cause:** You ran `black` with no files and no `-c`.
**Solution:** Pass a path (`black .`), a file, `-` for stdin, or `-c "code"`.
**Prevention:** In scripts and CI, always pass an explicit path.

### Error: `'SRC' and 'code' cannot be passed simultaneously.`

**Cause:** You combined a path argument with `-c/--code`.
**Solution:** Use one or the other — format files *or* a string, not both at once.

### Message: `No Python files are present to be formatted. Nothing to do 😴`

**Cause:** Every file under the given path was excluded — by `.gitignore`, the default excludes, your `--exclude`/`--extend-exclude` patterns, or because none matched `--include`.
**Solution:** Run with `-v` to see exactly which paths were skipped and why. Check your `exclude` regex and whether the directory is in `.gitignore`.
**Prevention:** Remember Black ignores `.gitignore`d paths and a built-in list of virtualenv/build directories by default.

### Error: `Cannot pass both 'pyi' and 'ipynb' flags!`

**Cause:** `--pyi` and `--ipynb` are mutually exclusive.
**Solution:** Pick the one that matches your input.

### Error: `'--enable-unstable-feature' requires '--preview'.`

**Cause:** You enabled an unstable feature without `--preview` (or `--unstable`).
**Solution:** Add `--preview` (or use `--unstable`, which implies it).

### Error: `The required version ... does not match the running version ...!`

**Cause:** `--required-version` (or the `required-version` config key) doesn't match the installed Black.
**Solution:** Install the required version, e.g. `pip install black==25.1.0`, or update the requirement.

### Warning about Python 3.12.5

**Cause:** Python 3.12.5 has a memory-safety bug that can break Black's AST safety check.
**Solution:** Upgrade to Python 3.12.6 or downgrade to 3.12.4. Black exits rather than risk an unsafe check.

### Error: `cannot use --safe with this file; failed to parse source file AST`

**Cause:** Your source uses syntax that the Python running Black can't parse (often because you're running Black on an older Python than your code targets).
**Solution:** Run Black on a newer Python, set `--target-version` to match, or use `--fast` to skip the equivalence check.

### `INTERNAL ERROR: Black produced code that is not equivalent...` / `...different code on the second pass...`

**Cause:** A genuine bug in Black — the safety check caught it before any bad output was written.
**Solution:** This is rare. The message includes a path to a dump file and a link to file a bug. Please [report it](https://github.com/psf/black/issues) with the diff. Your original file is left untouched.

### Error: `File '...' cannot be parsed as valid Jupyter notebook.`

**Cause:** A `.ipynb` file is malformed or isn't actually JSON.
**Solution:** Open it in Jupyter to repair it, or exclude it.

### `blackd`: `400 Invalid line length header value`

**Cause:** `X-Line-Length` wasn't an integer.
**Solution:** Send a numeric value, e.g. `X-Line-Length: 88`.

### `blackd`: `400` with `3.x is not supported` / `major version must be 2 or 3`

**Cause:** The `X-Python-Variant` header named an unsupported version (Black supports Python 3 only).
**Solution:** Use values like `py3.10`, `3.11`, or `pyi`.

---

## 12. FAQ

**Q: Do I need to configure anything to get started?**
No. Black is designed around sensible defaults. Just run `black .`. Reach for `pyproject.toml` only when you have a genuine reason, like a non-standard line length.

**Q: Will Black ever change what my code does?**
No. By default Black runs an AST-equivalence check after formatting and refuses to write output that isn't semantically identical to your input. The only way to skip that check is to explicitly pass `--fast`.

**Q: Why is the default line length 88 and not 79?**
It's a deliberate ~10% bump over PEP 8's 79, which the maintainers found reduces total line count meaningfully without hurting readability. You can change it with `--line-length`.

**Q: Can I make Black leave my single quotes alone?**
Yes — pass `-S` / `--skip-string-normalization` (or set `skip-string-normalization = true`). Otherwise Black prefers double quotes.

**Q: How do I stop Black from touching one specific block?**
Wrap it in `# fmt: off` … `# fmt: on`, or put `# fmt: skip` at the end of a single line.

**Q: How do I exclude a directory?**
Black already skips `.gitignore`d paths and common virtualenv/build folders. For anything else, use `--extend-exclude` (to add to the defaults) or `--exclude` (to replace them). Remember these are regexes.

**Q: Does Black format my whole repo even files I didn't change?**
If you point it at `.`, yes — it formats every discovered Python file. To format just changed lines, use `--line-ranges`; to format just changed files, pass those files explicitly (often combined with `--force-exclude` in pre-commit hooks).

**Q: Why is Black skipping my `.ipynb` files?**
You need the Jupyter extra: `pip install "black[jupyter]"`. Without it, notebooks are silently skipped (run with `-v` to see the notice).

**Q: My CI passes locally but fails in the pipeline. Why?**
Different Black versions format slightly differently. Pin the version everywhere (in `pyproject.toml`, pre-commit `rev`, and the GitHub Action `version`/`use_pyproject`), or set `--required-version`.

**Q: Is there a way to run Black faster?**
Use more workers (`-W`), install the `uvloop` extra, and rely on the cache (don't pass `--no-cache`). For editor integrations, run the `blackd` server to avoid repeated startup cost.

**Q: What do the exit codes mean?**
`0` = all good, `1` = files would be reformatted (under `--check`), `123` = an internal error occurred.

**Q: What Python versions can Black format?**
Black itself needs Python 3.10+ to run, but it can target output for Python 3.3 through 3.15 via `--target-version`.

**Q: What does `compiled: yes` in `--version` mean?**
You installed a mypyc-compiled build, which runs faster. Pure-Python builds (`compiled: no`) behave identically, just slower.

---

_Generated June 2026 from psf/black at ce1897a. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
