Skip to main content

An extremely fast Python linter and code formatter, written in Rust.

Project description

Ruff

Ruff image image image Actions status Discord

Docs | Playground

An extremely fast Python linter and code formatter, written in Rust.

Shows a bar chart with benchmark results.

Linting the CPython codebase from scratch.

  • ⚡️ 10-100x faster than existing linters (like Flake8) and formatters (like Black)
  • 🐍 Installable via pip
  • 🛠️ pyproject.toml support
  • 🤝 Python 3.13 compatibility
  • ⚖️ Drop-in parity with Flake8, isort, and Black
  • 📦 Built-in caching, to avoid re-analyzing unchanged files
  • 🔧 Fix support, for automatic error correction (e.g., automatically remove unused imports)
  • 📏 Over 800 built-in rules, with native re-implementations of popular Flake8 plugins, like flake8-bugbear
  • ⌨️ First-party editor integrations for VS Code and more
  • 🌎 Monorepo-friendly, with hierarchical and cascading configuration

Ruff aims to be orders of magnitude faster than alternative tools while integrating more functionality behind a single, common interface.

Ruff can be used to replace Flake8 (plus dozens of plugins), Black, isort, pydocstyle, pyupgrade, autoflake, and more, all while executing tens or hundreds of times faster than any individual tool.

Ruff is extremely actively developed and used in major open-source projects like:

...and many more.

Ruff is backed by Astral. Read the launch post, or the original project announcement.

Testimonials

Sebastián Ramírez, creator of FastAPI:

Ruff is so fast that sometimes I add an intentional bug in the code just to confirm it's actually running and checking the code.

Nick Schrock, founder of Elementl, co-creator of GraphQL:

Why is Ruff a gamechanger? Primarily because it is nearly 1000x faster. Literally. Not a typo. On our largest module (dagster itself, 250k LOC) pylint takes about 2.5 minutes, parallelized across 4 cores on my M1. Running ruff against our entire codebase takes .4 seconds.

Bryan Van de Ven, co-creator of Bokeh, original author of Conda:

Ruff is ~150-200x faster than flake8 on my machine, scanning the whole repo takes ~0.2s instead of ~20s. This is an enormous quality of life improvement for local dev. It's fast enough that I added it as an actual commit hook, which is terrific.

Timothy Crosley, creator of isort:

Just switched my first project to Ruff. Only one downside so far: it's so fast I couldn't believe it was working till I intentionally introduced some errors.

Tim Abbott, lead developer of Zulip:

This is just ridiculously fast... ruff is amazing.

Table of Contents

For more, see the documentation.

  1. Getting Started
  2. Configuration
  3. Rules
  4. Contributing
  5. Support
  6. Acknowledgements
  7. Who's Using Ruff?
  8. License

Getting Started

For more, see the documentation.

Installation

Ruff is available as ruff on PyPI.

Invoke Ruff directly with uvx:

uvx ruff check   # Lint all files in the current directory.
uvx ruff format  # Format all files in the current directory.

Or install Ruff with uv (recommended), pip, or pipx:

# With uv.
uv tool install ruff@latest  # Install Ruff globally.
uv add --dev ruff            # Or add Ruff to your project.

# With pip.
pip install ruff

# With pipx.
pipx install ruff

Starting with version 0.5.0, Ruff can be installed with our standalone installers:

# On macOS and Linux.
curl -LsSf https://astral.sh/ruff/install.sh | sh

# On Windows.
powershell -c "irm https://astral.sh/ruff/install.ps1 | iex"

# For a specific version.
curl -LsSf https://astral.sh/ruff/0.9.5/install.sh | sh
powershell -c "irm https://astral.sh/ruff/0.9.5/install.ps1 | iex"

You can also install Ruff via Homebrew, Conda, and with a variety of other package managers.

Usage

To run Ruff as a linter, try any of the following:

ruff check                          # Lint all files in the current directory (and any subdirectories).
ruff check path/to/code/            # Lint all files in `/path/to/code` (and any subdirectories).
ruff check path/to/code/*.py        # Lint all `.py` files in `/path/to/code`.
ruff check path/to/code/to/file.py  # Lint `file.py`.
ruff check @arguments.txt           # Lint using an input file, treating its contents as newline-delimited command-line arguments.

Or, to run Ruff as a formatter:

ruff format                          # Format all files in the current directory (and any subdirectories).
ruff format path/to/code/            # Format all files in `/path/to/code` (and any subdirectories).
ruff format path/to/code/*.py        # Format all `.py` files in `/path/to/code`.
ruff format path/to/code/to/file.py  # Format `file.py`.
ruff format @arguments.txt           # Format using an input file, treating its contents as newline-delimited command-line arguments.

Ruff can also be used as a pre-commit hook via ruff-pre-commit:

- repo: https://github.com/astral-sh/ruff-pre-commit
  # Ruff version.
  rev: v0.9.5
  hooks:
    # Run the linter.
    - id: ruff
      args: [ --fix ]
    # Run the formatter.
    - id: ruff-format

Ruff can also be used as a VS Code extension or with various other editors.

Ruff can also be used as a GitHub Action via ruff-action:

name: Ruff
on: [ push, pull_request ]
jobs:
  ruff:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/ruff-action@v3

Configuration

Ruff can be configured through a pyproject.toml, ruff.toml, or .ruff.toml file (see: Configuration, or Settings for a complete list of all configuration options).

If left unspecified, Ruff's default configuration is equivalent to the following ruff.toml file:

# Exclude a variety of commonly ignored directories.
exclude = [
    ".bzr",
    ".direnv",
    ".eggs",
    ".git",
    ".git-rewrite",
    ".hg",
    ".ipynb_checkpoints",
    ".mypy_cache",
    ".nox",
    ".pants.d",
    ".pyenv",
    ".pytest_cache",
    ".pytype",
    ".ruff_cache",
    ".svn",
    ".tox",
    ".venv",
    ".vscode",
    "__pypackages__",
    "_build",
    "buck-out",
    "build",
    "dist",
    "node_modules",
    "site-packages",
    "venv",
]

# Same as Black.
line-length = 88
indent-width = 4

# Assume Python 3.9
target-version = "py39"

[lint]
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`)  codes by default.
select = ["E4", "E7", "E9", "F"]
ignore = []

# Allow fix for all enabled rules (when `--fix`) is provided.
fixable = ["ALL"]
unfixable = []

# Allow unused variables when underscore-prefixed.
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"

[format]
# Like Black, use double quotes for strings.
quote-style = "double"

# Like Black, indent with spaces, rather than tabs.
indent-style = "space"

# Like Black, respect magic trailing commas.
skip-magic-trailing-comma = false

# Like Black, automatically detect the appropriate line ending.
line-ending = "auto"

Note that, in a pyproject.toml, each section header should be prefixed with tool.ruff. For example, [lint] should be replaced with [tool.ruff.lint].

Some configuration options can be provided via dedicated command-line arguments, such as those related to rule enablement and disablement, file discovery, and logging level:

ruff check --select F401 --select F403 --quiet

The remaining configuration options can be provided through a catch-all --config argument:

ruff check --config "lint.per-file-ignores = {'some_file.py' = ['F841']}"

To opt in to the latest lint rules, formatter style changes, interface updates, and more, enable preview mode by setting preview = true in your configuration file or passing --preview on the command line. Preview mode enables a collection of unstable features that may change prior to stabilization.

See ruff help for more on Ruff's top-level commands, or ruff help check and ruff help format for more on the linting and formatting commands, respectively.

Rules

Ruff supports over 800 lint rules, many of which are inspired by popular tools like Flake8, isort, pyupgrade, and others. Regardless of the rule's origin, Ruff re-implements every rule in Rust as a first-party feature.

By default, Ruff enables Flake8's F rules, along with a subset of the E rules, omitting any stylistic rules that overlap with the use of a formatter, like ruff format or Black.

If you're just getting started with Ruff, the default rule set is a great place to start: it catches a wide variety of common errors (like unused imports) with zero configuration.

Beyond the defaults, Ruff re-implements some of the most popular Flake8 plugins and related code quality tools, including:

For a complete enumeration of the supported rules, see Rules.

Contributing

Contributions are welcome and highly appreciated. To get started, check out the contributing guidelines.

You can also join us on Discord.

Support

Having trouble? Check out the existing issues on GitHub, or feel free to open a new one.

You can also ask for help on Discord.

Acknowledgements

Ruff's linter draws on both the APIs and implementation details of many other tools in the Python ecosystem, especially Flake8, Pyflakes, pycodestyle, pydocstyle, pyupgrade, and isort.

In some cases, Ruff includes a "direct" Rust port of the corresponding tool. We're grateful to the maintainers of these tools for their work, and for all the value they've provided to the Python community.

Ruff's formatter is built on a fork of Rome's rome_formatter, and again draws on both API and implementation details from Rome, Prettier, and Black.

Ruff's import resolver is based on the import resolution algorithm from Pyright.

Ruff is also influenced by a number of tools outside the Python ecosystem, like Clippy and ESLint.

Ruff is the beneficiary of a large number of contributors.

Ruff is released under the MIT license.

Who's Using Ruff?

Ruff is used by a number of major open-source projects and companies, including:

Show Your Support

If you're using Ruff, consider adding the Ruff badge to your project's README.md:

[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)

...or README.rst:

.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
    :target: https://github.com/astral-sh/ruff
    :alt: Ruff

...or, as HTML:

<a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff" style="max-width:100%;"></a>

License

This repository is licensed under the MIT License

Project details


Release history Release notifications | RSS feed

This version

0.9.5

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ruff-0.9.5.tar.gz (3.6 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

ruff-0.9.5-py3-none-win_arm64.whl (10.1 MB view details)

Uploaded Python 3Windows ARM64

ruff-0.9.5-py3-none-win_amd64.whl (10.9 MB view details)

Uploaded Python 3Windows x86-64

ruff-0.9.5-py3-none-win32.whl (9.9 MB view details)

Uploaded Python 3Windows x86

ruff-0.9.5-py3-none-musllinux_1_2_x86_64.whl (12.5 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

ruff-0.9.5-py3-none-musllinux_1_2_i686.whl (12.1 MB view details)

Uploaded Python 3musllinux: musl 1.2+ i686

ruff-0.9.5-py3-none-musllinux_1_2_armv7l.whl (11.5 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARMv7l

ruff-0.9.5-py3-none-musllinux_1_2_aarch64.whl (11.9 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

ruff-0.9.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (12.4 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

ruff-0.9.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl (14.4 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ s390x

ruff-0.9.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (12.8 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ppc64le

ruff-0.9.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl (13.3 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ppc64

ruff-0.9.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl (12.6 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ i686

ruff-0.9.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (11.4 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARMv7l

ruff-0.9.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (11.9 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

ruff-0.9.5-py3-none-macosx_11_0_arm64.whl (11.1 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

ruff-0.9.5-py3-none-macosx_10_12_x86_64.whl (11.7 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

ruff-0.9.5-py3-none-linux_armv6l.whl (11.7 MB view details)

Uploaded Python 3

File details

Details for the file ruff-0.9.5.tar.gz.

File metadata

  • Download URL: ruff-0.9.5.tar.gz
  • Upload date:
  • Size: 3.6 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.5.29

File hashes

Hashes for ruff-0.9.5.tar.gz
Algorithm Hash digest
SHA256 11aecd7a633932875ab3cb05a484c99970b9d52606ce9ea912b690b02653d56c
MD5 f6289e6f99478fb02e99eacbc15e268e
BLAKE2b-256 02746c359f6b9ed85b88df6ef31febce18faeb852f6c9855651dfb1184a46845

See more details on using hashes here.

File details

Details for the file ruff-0.9.5-py3-none-win_arm64.whl.

File metadata

  • Download URL: ruff-0.9.5-py3-none-win_arm64.whl
  • Upload date:
  • Size: 10.1 MB
  • Tags: Python 3, Windows ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.5.29

File hashes

Hashes for ruff-0.9.5-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 18a29f1a005bddb229e580795627d297dfa99f16b30c7039e73278cf6b5f9fa9
MD5 acd7168775048d023e7e28d6501acb56
BLAKE2b-256 75d9fde7610abd53c0c76b6af72fc679cb377b27c617ba704e25da834e0a0608

See more details on using hashes here.

File details

Details for the file ruff-0.9.5-py3-none-win_amd64.whl.

File metadata

  • Download URL: ruff-0.9.5-py3-none-win_amd64.whl
  • Upload date:
  • Size: 10.9 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.5.29

File hashes

Hashes for ruff-0.9.5-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 78cc6067f6d80b6745b67498fb84e87d32c6fc34992b52bffefbdae3442967d6
MD5 a2e8283cb09fbf658ccca032531362ea
BLAKE2b-256 b7adc7a900591bd152bb47fc4882a27654ea55c7973e6d5d6396298ad3fd6638

See more details on using hashes here.

File details

Details for the file ruff-0.9.5-py3-none-win32.whl.

File metadata

  • Download URL: ruff-0.9.5-py3-none-win32.whl
  • Upload date:
  • Size: 9.9 MB
  • Tags: Python 3, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.5.29

File hashes

Hashes for ruff-0.9.5-py3-none-win32.whl
Algorithm Hash digest
SHA256 134f958d52aa6fdec3b294b8ebe2320a950d10c041473c4316d2e7d7c2544723
MD5 0195dbdaf68b6ef0b971f21f63af721a
BLAKE2b-256 e0511432afcc3b7aa6586c480142caae5323d59750925c3559688f2a9867343f

See more details on using hashes here.

File details

Details for the file ruff-0.9.5-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for ruff-0.9.5-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 2f71d09aeba026c922aa7aa19a08d7bd27c867aedb2f74285a2639644c1c12f5
MD5 8c1720e2414488755608f6610a81b720
BLAKE2b-256 ecb25ab808833e06c0a1b0d046a51c06ec5687b73c78b116e8d77687dc0cd515

See more details on using hashes here.

File details

Details for the file ruff-0.9.5-py3-none-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for ruff-0.9.5-py3-none-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 2e36c61145e70febcb78483903c43444c6b9d40f6d2f800b5552fec6e4a7bb9a
MD5 5163a05b13295f9a339d1a623acef71d
BLAKE2b-256 0ae43ebfcebca3dff1559a74c6becff76e0b64689cea02b7aab15b8b32ea245d

See more details on using hashes here.

File details

Details for the file ruff-0.9.5-py3-none-musllinux_1_2_armv7l.whl.

File metadata

File hashes

Hashes for ruff-0.9.5-py3-none-musllinux_1_2_armv7l.whl
Algorithm Hash digest
SHA256 5b9d71c3879eb32de700f2f6fac3d46566f644a91d3130119a6378f9312a38e1
MD5 381603d7be9139095daf0371e517bdd0
BLAKE2b-256 a3dbb0183a01a9f25b4efcae919c18fb41d32f985676c917008620ad692b9d5f

See more details on using hashes here.

File details

Details for the file ruff-0.9.5-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for ruff-0.9.5-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 11417521d6f2d121fda376f0d2169fb529976c544d653d1d6044f4c5562516ee
MD5 faec6b41390168df2ea1a50c878c68d3
BLAKE2b-256 554e3abba60a259d79c391713e7a6ccabf7e2c96e5e0a19100bc4204f1a43a51

See more details on using hashes here.

File details

Details for the file ruff-0.9.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for ruff-0.9.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 2c746d7d1df64f31d90503ece5cc34d7007c06751a7a3bbeee10e5f2463d52d2
MD5 7c5153604c5515ff7101627740993654
BLAKE2b-256 0470e59c192a3ad476355e7f45fb3a87326f5219cc7c472e6b040c6c6595c8f0

See more details on using hashes here.

File details

Details for the file ruff-0.9.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl.

File metadata

File hashes

Hashes for ruff-0.9.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl
Algorithm Hash digest
SHA256 3d28532d73b1f3f627ba88e1456f50748b37f3a345d2be76e4c653bec6c3e393
MD5 9148ffe64f97c1f74e512caa752f44a1
BLAKE2b-256 b3d00a3d8f56d1e49af466dc770eeec5c125977ba9479af92e484b5b0251ce9c

See more details on using hashes here.

File details

Details for the file ruff-0.9.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl.

File metadata

File hashes

Hashes for ruff-0.9.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl
Algorithm Hash digest
SHA256 de92170dfa50c32a2b8206a647949590e752aca8100a0f6b8cefa02ae29dce80
MD5 39b6d66697febd139ec2d426382158f1
BLAKE2b-256 8881c639a082ae6d8392bc52256058ec60f493c6a4d06d5505bccface3767e61

See more details on using hashes here.

File details

Details for the file ruff-0.9.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl.

File metadata

File hashes

Hashes for ruff-0.9.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl
Algorithm Hash digest
SHA256 df455000bf59e62b3e8c7ba5ed88a4a2bc64896f900f311dc23ff2dc38156440
MD5 cc29847840f642f53359374053713b74
BLAKE2b-256 d7ceab00bc9d3df35a5f1b64f5117458160a009f93ae5caf65894ebb63a1842d

See more details on using hashes here.

File details

Details for the file ruff-0.9.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for ruff-0.9.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 deb8304636ed394211f3a6d46c0e7d9535b016f53adaa8340139859b2359a070
MD5 244681ac1add274cb3088aefcb95a217
BLAKE2b-256 0927bb8f1b7304e2a9431f631ae7eadc35550fe0cf620a2a6a0fc4aa3d736f94

See more details on using hashes here.

File details

Details for the file ruff-0.9.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for ruff-0.9.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 96d5c76358419bc63a671caac70c18732d4fd0341646ecd01641ddda5c39ca0b
MD5 9e18d9abbb93179bcd9cfdfc9cc8b9b2
BLAKE2b-256 53cf1fffa09fb518d646f560ccfba59f91b23c731e461d6a4dedd21a393a1ff1

See more details on using hashes here.

File details

Details for the file ruff-0.9.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for ruff-0.9.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 4f7cb2a01da08244c50b20ccfaeb5972e4228c3c3a1989d3ece2bc4b1f996001
MD5 2c804212d9c4a9bf999e4d55737118df
BLAKE2b-256 afa742d1832b752fe969ffdbfcb1b4cb477cb271bed5835110fb0a16ef31ab81

See more details on using hashes here.

File details

Details for the file ruff-0.9.5-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for ruff-0.9.5-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d56ba06da53536b575fbd2b56517f6f95774ff7be0f62c80b9e67430391eeb36
MD5 cf8b7e2869af7000b80097f7ea6a93ad
BLAKE2b-256 2a83c6926fa3ccb97cdb3c438bb56a490b395770c750bf59f9bc1fe57ae88264

See more details on using hashes here.

File details

Details for the file ruff-0.9.5-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for ruff-0.9.5-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 38840dbcef63948657fa7605ca363194d2fe8c26ce8f9ae12eee7f098c85ac8a
MD5 141abff5c7991813b395a2f9212b0ae9
BLAKE2b-256 275cf5ae0a9564e04108c132e1139d60491c0abc621397fe79a50b3dc0bd704b

See more details on using hashes here.

File details

Details for the file ruff-0.9.5-py3-none-linux_armv6l.whl.

File metadata

File hashes

Hashes for ruff-0.9.5-py3-none-linux_armv6l.whl
Algorithm Hash digest
SHA256 d466d2abc05f39018d53f681fa1c0ffe9570e6d73cde1b65d23bb557c846f442
MD5 c0d780fc96d6499e089a687f0ee751ae
BLAKE2b-256 174b82b7c9ac874e72b82b19fd7eab57d122e2df44d2478d90825854f9232d02

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page