eglot-python-preset and eglot-typescript-preset: Now on MELPA

Published:
Keywords: emacs

Contents

Introduction

A quick follow-up to my earlier posts on eglot-python-preset and the beta multi-LSP release: both packages are now available on MELPA with full rassumfrassum (rass) support included.

When I wrote the beta post in March, eglot-typescript-preset wasn’t on MELPA at all, and eglot-python-preset’s MELPA version didn’t include rass support. That’s no longer the case. You can install both with a standard use-package :ensure t and get multi-LSP out of the box.

What Changed

The main thing that landed since the beta: MELPA now ships the rass backend for both packages. This means the rass LSP server option and all the preset generation machinery are available without cloning repos or managing load paths manually.

Both packages also now set up Eglot integration automatically when Eglot loads, so you no longer need an explicit (eglot-python-preset-setup) or (eglot-typescript-preset-setup) call in your config. Just install and go.

Installation

Python

(use-package eglot-python-preset
  :ensure t
  :custom
  (eglot-python-preset-lsp-server 'ty)) ; or 'basedpyright or 'rass

With the default ty backend, this gives you type checking for standard Python projects and PEP-723 scripts with no further configuration. Switch to rass to run ty and Ruff simultaneously:

(use-package eglot-python-preset
  :ensure t
  :custom
  (eglot-python-preset-lsp-server 'rass)
  (eglot-python-preset-rass-tools '(ty ruff)))

TypeScript

(use-package eglot-typescript-preset
  :ensure t)

That’s it. The defaults configure typescript-language-server for TS/JS files and use rass to combine language servers with Tailwind CSS support for CSS, Astro, Vue, and Svelte buffers. If your project uses any of those frameworks, the corresponding language server starts automatically when you open a file in that mode.

To add linting alongside the TypeScript language server, switch the TS/JS backend to rass:

(use-package eglot-typescript-preset
  :ensure t
  :custom
  (eglot-typescript-preset-lsp-server 'rass)
  (eglot-typescript-preset-rass-tools
   '(typescript-language-server eslint)))

Out-of-the-Box Multi-LSP

The part I’m most pleased with is how much works without any rass-specific configuration on the TypeScript side. The default settings for CSS, Astro, Vue, and Svelte all use rass, combining each framework’s language server with Tailwind CSS support automatically.

For Astro, this means astro-ls runs alongside ESLint and tailwindcss-language-server in a single Eglot session. Vue gets hybrid mode where vue-language-server handles template features and typescript-language-server with @vue/typescript-plugin provides type checking, plus Tailwind. Svelte works similarly.

On the Python side, the rass backend lets you run ty for type checking and Ruff for linting in the same buffer. PEP-723 scripts work too: the generated rass preset includes the script’s cached uv environment so both tools resolve imports.

All of this resolves executables from project-local directories first (node_modules/.bin for JS/TS, .venv for Python), falling back to your PATH.

Per-Project Configuration

Both packages support per-project overrides via .dir-locals.el or dir-locals-set-directory-class. The preset variables are declared as safe local variables, so Emacs applies them without prompting. For example, if one project uses Biome instead of ESLint:

;;; .dir-locals.el
((typescript-ts-mode
  . ((eglot-typescript-preset-lsp-server . rass)
     (eglot-typescript-preset-rass-tools
      . (typescript-language-server biome)))))