# Integrations ## VS Code (Official) Download the [Ruff VS Code extension](https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff), which supports fix actions, import sorting, and more. ![Ruff VS Code extension](https://user-images.githubusercontent.com/1309177/205175763-cf34871d-5c05-4abf-9916-440afc82dbf8.gif) ## pre-commit Ruff can be used as a [pre-commit](https://pre-commit.com) hook via [`ruff-pre-commit`](https://github.com/astral-sh/ruff-pre-commit): ```yaml # Run the Ruff formatter. - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. rev: v0.0.291 hooks: - id: ruff-format # Run the Ruff linter. - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. rev: v0.0.291 hooks: - id: ruff ``` To enable fixes, add the `--fix` argument to the linter: ```yaml # Run the Ruff linter. - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. rev: v0.0.291 hooks: - id: ruff args: [ --fix, --exit-non-zero-on-fix ] ``` To run the hooks over Jupyter Notebooks too, add `jupyter` to the list of allowed filetypes: ```yaml # Run the Ruff linter. - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. rev: v0.0.291 hooks: - id: ruff types_or: [python, pyi, jupyter] ``` Ruff's lint hook should be placed after other formatting tools, such as Ruff's format hook, Black, or isort, _unless_ you enable autofix, in which case, Ruff's pre-commit hook should run _before_ Black, isort, and other formatting tools, as Ruff's autofix behavior can output code changes that require reformatting. As long as your Ruff configuration avoids any [linter-formatter incompatibilities](formatter.md#conflicting-lint-rules), `ruff format` should never introduce new lint errors, so it's safe to run Ruff's format hook _after_ `ruff check --fix`. ## Language Server Protocol (Official) Ruff supports the [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) via the [`ruff-lsp`](https://github.com/astral-sh/ruff-lsp) Python package, available on [PyPI](https://pypi.org/project/ruff-lsp/). [`ruff-lsp`](https://github.com/astral-sh/ruff-lsp) enables Ruff to be used with any editor that supports the Language Server Protocol, including [Neovim](https://github.com/astral-sh/ruff-lsp#example-neovim), [Sublime Text](https://github.com/astral-sh/ruff-lsp#example-sublime-text), Emacs, and more. For example, to use `ruff-lsp` with Neovim, install `ruff-lsp` from PyPI along with [`nvim-lspconfig`](https://github.com/neovim/nvim-lspconfig). Then, add something like the following to your `init.lua`: ```lua -- See: https://github.com/neovim/nvim-lspconfig/tree/54eb2a070a4f389b1be0f98070f81d23e2b1a715#suggested-configuration local opts = { noremap=true, silent=true } vim.keymap.set('n', 'e', vim.diagnostic.open_float, opts) vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, opts) vim.keymap.set('n', ']d', vim.diagnostic.goto_next, opts) vim.keymap.set('n', 'q', vim.diagnostic.setloclist, opts) -- Use an on_attach function to only map the following keys -- after the language server attaches to the current buffer local on_attach = function(client, bufnr) -- Enable completion triggered by vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc') -- Mappings. -- See `:help vim.lsp.*` for documentation on any of the below functions local bufopts = { noremap=true, silent=true, buffer=bufnr } vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, bufopts) vim.keymap.set('n', 'gd', vim.lsp.buf.definition, bufopts) vim.keymap.set('n', 'K', vim.lsp.buf.hover, bufopts) vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, bufopts) vim.keymap.set('n', '', vim.lsp.buf.signature_help, bufopts) vim.keymap.set('n', 'wa', vim.lsp.buf.add_workspace_folder, bufopts) vim.keymap.set('n', 'wr', vim.lsp.buf.remove_workspace_folder, bufopts) vim.keymap.set('n', 'wl', function() print(vim.inspect(vim.lsp.buf.list_workspace_folders())) end, bufopts) vim.keymap.set('n', 'D', vim.lsp.buf.type_definition, bufopts) vim.keymap.set('n', 'rn', vim.lsp.buf.rename, bufopts) vim.keymap.set('n', 'ca', vim.lsp.buf.code_action, bufopts) vim.keymap.set('n', 'gr', vim.lsp.buf.references, bufopts) vim.keymap.set('n', 'f', function() vim.lsp.buf.format { async = true } end, bufopts) end -- Configure `ruff-lsp`. local configs = require 'lspconfig.configs' if not configs.ruff_lsp then configs.ruff_lsp = { default_config = { cmd = { 'ruff-lsp' }, filetypes = { 'python' }, root_dir = require('lspconfig').util.find_git_ancestor, init_options = { settings = { args = {} } } } } end require('lspconfig').ruff_lsp.setup { on_attach = on_attach, } ``` Upon successful installation, you should see Ruff's diagnostics surfaced directly in your editor: ![Code Actions available in Neovim](https://user-images.githubusercontent.com/1309177/208278707-25fa37e4-079d-4597-ad35-b95dba066960.png) To use `ruff-lsp` with other editors, including Sublime Text and Helix, see the [`ruff-lsp` documentation](https://github.com/astral-sh/ruff-lsp#installation-and-usage). ## Language Server Protocol (Unofficial) Ruff is also available as the [`python-lsp-ruff`](https://github.com/python-lsp/python-lsp-ruff) plugin for [`python-lsp-server`](https://github.com/python-lsp/python-lsp-ruff), both of which are installable from PyPI: ```shell pip install python-lsp-server python-lsp-ruff ``` The LSP server can then be used with any editor that supports the Language Server Protocol. For example, to use `python-lsp-ruff` with Neovim, add something like the following to your `init.lua`: ```lua require'lspconfig'.pylsp.setup { settings = { pylsp = { plugins = { ruff = { enabled = true }, pycodestyle = { enabled = false }, pyflakes = { enabled = false }, mccabe = { enabled = false } } } }, } ``` ## Vim & Neovim Ruff can be integrated into any editor that supports the Language Server Protocol via [`ruff-lsp`](https://github.com/astral-sh/ruff-lsp) (see: [Language Server Protocol](#language-server-protocol-official)), including Vim and Neovim. It's recommended that you use [`ruff-lsp`](https://github.com/astral-sh/ruff-lsp), the officially supported LSP server for Ruff. To use `ruff-lsp` with Neovim, install `ruff-lsp` from PyPI along with [`nvim-lspconfig`](https://github.com/neovim/nvim-lspconfig). Then, add something like the following to your `init.lua`: ```lua -- See: https://github.com/neovim/nvim-lspconfig/tree/54eb2a070a4f389b1be0f98070f81d23e2b1a715#suggested-configuration local opts = { noremap=true, silent=true } vim.keymap.set('n', 'e', vim.diagnostic.open_float, opts) vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, opts) vim.keymap.set('n', ']d', vim.diagnostic.goto_next, opts) vim.keymap.set('n', 'q', vim.diagnostic.setloclist, opts) -- Use an on_attach function to only map the following keys -- after the language server attaches to the current buffer local on_attach = function(client, bufnr) -- Enable completion triggered by vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc') -- Mappings. -- See `:help vim.lsp.*` for documentation on any of the below functions local bufopts = { noremap=true, silent=true, buffer=bufnr } vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, bufopts) vim.keymap.set('n', 'gd', vim.lsp.buf.definition, bufopts) vim.keymap.set('n', 'K', vim.lsp.buf.hover, bufopts) vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, bufopts) vim.keymap.set('n', '', vim.lsp.buf.signature_help, bufopts) vim.keymap.set('n', 'wa', vim.lsp.buf.add_workspace_folder, bufopts) vim.keymap.set('n', 'wr', vim.lsp.buf.remove_workspace_folder, bufopts) vim.keymap.set('n', 'wl', function() print(vim.inspect(vim.lsp.buf.list_workspace_folders())) end, bufopts) vim.keymap.set('n', 'D', vim.lsp.buf.type_definition, bufopts) vim.keymap.set('n', 'rn', vim.lsp.buf.rename, bufopts) vim.keymap.set('n', 'ca', vim.lsp.buf.code_action, bufopts) vim.keymap.set('n', 'gr', vim.lsp.buf.references, bufopts) vim.keymap.set('n', 'f', function() vim.lsp.buf.format { async = true } end, bufopts) end -- Configure `ruff-lsp`. -- See: https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#ruff_lsp -- For the default config, along with instructions on how to customize the settings require('lspconfig').ruff_lsp.setup { on_attach = on_attach, init_options = { settings = { -- Any extra CLI arguments for `ruff` go here. args = {}, } } } ``` Ruff is also available as part of the [coc-pyright](https://github.com/fannheyward/coc-pyright) extension for `coc.nvim`.
With the ALE plugin for (Neo)Vim. ```vim let g:ale_linters = { "python": ["ruff"] } let g:ale_fixers = { \ "python": ["black", "ruff"], \} ```
Ruff can also be integrated via efm in just a few lines.
```yaml tools: python-ruff: &python-ruff lint-command: "ruff check --config ~/myconfigs/linters/ruff.toml --quiet ${INPUT}" lint-stdin: true lint-formats: - "%f:%l:%c: %m" format-command: "ruff check --stdin-filename ${INPUT} --config ~/myconfigs/linters/ruff.toml --fix --exit-zero --quiet -" format-stdin: true ```
For neovim users using null-ls , Ruff is already integrated.
```lua local null_ls = require("null-ls") null_ls.setup({ sources = { null_ls.builtins.formatting.ruff, null_ls.builtins.diagnostics.ruff, } }) ```
## PyCharm (External Tool) Ruff can be installed as an [External Tool](https://www.jetbrains.com/help/pycharm/configuring-third-party-tools.html) in PyCharm. Open the Preferences pane, then navigate to "Tools", then "External Tools". From there, add a new tool with the following configuration: ![Install Ruff as an External Tool](https://user-images.githubusercontent.com/1309177/193155720-336e43f0-1a8d-46b4-bc12-e60f9ae01f7e.png) Ruff should then appear as a runnable action: ![Ruff as a runnable action](https://user-images.githubusercontent.com/1309177/193156026-732b0aaf-3dd9-4549-9b4d-2de6d2168a33.png) ## PyCharm (Unofficial) Ruff is also available as the [Ruff](https://plugins.jetbrains.com/plugin/20574-ruff) plugin on the IntelliJ Marketplace (maintained by @koxudaxi). ## Emacs (Unofficial) Ruff is available as [`flymake-ruff`](https://melpa.org/#/flymake-ruff) on MELPA: ```elisp (require 'flymake-ruff) (add-hook 'python-mode-hook #'flymake-ruff-load) ``` ## TextMate (Unofficial) Ruff is also available via the [`textmate2-ruff-linter`](https://github.com/vigo/textmate2-ruff-linter) bundle for TextMate. ## GitHub Actions GitHub Actions has everything you need to run Ruff out-of-the-box: ```yaml name: CI on: push jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Install Python uses: actions/setup-python@v4 with: python-version: "3.11" - name: Install dependencies run: | python -m pip install --upgrade pip pip install ruff # Update output format to enable automatic inline annotations. - name: Run Ruff run: ruff check --output-format=github . ``` Ruff can also be used as a GitHub Action via [`ruff-action`](https://github.com/chartboost/ruff-action). By default, `ruff-action` runs as a pass-fail test to ensure that a given repository doesn't contain any lint rule violations as per its [configuration](https://github.com/astral-sh/ruff/blob/main/docs/configuration.md). However, under-the-hood, `ruff-action` installs and runs `ruff` directly, so it can be used to execute any supported `ruff` command (e.g., `ruff check --fix`). `ruff-action` supports all GitHub-hosted runners, and can be used with any published Ruff version (i.e., any version available on [PyPI](https://pypi.org/project/ruff/)). To use `ruff-action`, create a file (e.g., `.github/workflows/ruff.yml`) inside your repository with: ```yaml name: Ruff on: [ push, pull_request ] jobs: ruff: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: chartboost/ruff-action@v1 ``` Alternatively, you can include `ruff-action` as a step in any other workflow file: ```yaml - uses: chartboost/ruff-action@v1 ``` `ruff-action` accepts optional configuration parameters via `with:`, including: - `version`: The Ruff version to install (default: latest). - `options`: The command-line arguments to pass to Ruff (default: `"check"`). - `src`: The source paths to pass to Ruff (default: `"."`). For example, to run `ruff check --select B ./src` using Ruff version `0.0.259`: ```yaml - uses: chartboost/ruff-action@v1 with: src: "./src" version: 0.0.259 args: --select B ```