# Use the Lit language server

> Completion, hover and type checks for your Lit components in VS Code and Zed: templates, HTML files and css templates, in one package or a whole monorepo, with or without Vite.

The Lit language server makes your editor understand your components: it completes their tags, attributes, properties and events in `html` templates, shows their docs on hover, types your event handlers, and reports a handler that doesn’t fit its event. It reads your sources as you type, so a component’s docs are current before you save, and it works in a project without Vite. [Language server](/reference/language-server/) lists everything it does.

Not published yet

`@oddsquad/lit-language-server` and the editor extensions aren’t on npm or in the editors’ marketplaces yet. Until they are, build them from a checkout of this repository, as below.

## Set it up in VS Code

1. Build the extension in a checkout of the repository:

   ```sh
   pnpm install
   cd packages/vscode
   pnpm run build && pnpm run package
   ```

   This writes `lit-devtools-<platform>.vsix` for your machine, with the server bundled in.

2. In VS Code, run **Extensions: Install from VSIX…** from the command palette and pick that file.

3. Open a project and hover a component’s tag in an `html` template.

The extension runs the project’s own `@oddsquad/lit-language-server` when the project installs it, directly or through `@oddsquad/lit-devtools`, so the version matches the project, and the bundled copy otherwise. To run a different build, point the `lit.server.path` setting at its `dist/bin.mjs`. **Lit: Restart Language Server** picks the server again, and the **Lit Language Server** output channel says which one started.

The type hints on event handlers are inlay hints, which VS Code shows unless `editor.inlayHints.enabled` is off.

## Set it up in Zed

1. Build the server in a checkout of the repository:

   ```sh
   pnpm install
   cd packages/lit-language-server && pnpm run build
   ```

2. In Zed, run **zed: install dev extension** from the command palette and pick `packages/zed`. Zed compiles it, which needs Rust from [rustup](https://rustup.rs).

3. Point Zed at the server you built, in its settings:

   ```json
   {
     "lsp": {
       "lit-language-server": {
         "binary": {
           "path": "/path/to/lit-devtools/packages/lit-language-server/dist/bin.mjs"
         }
       }
     }
   }
   ```

   Inside the repository itself the extension finds the server without this.

4. Open a project and hover a component’s tag in an `html` template.

Once the package is published, a project that installs it as a dev dependency is found without the setting, and the extension otherwise installs the latest release itself.

The type hints on event handlers are inlay hints, which Zed shows when `"inlay_hints": {"enabled": true}` is set.

## Configure it

The server needs no settings. To change what it reads or how loud a problem is, set `languageServer` in your Vite config:

```ts
import {defineConfig} from 'vite';
import {litPlugin} from '@oddsquad/lit-devtools/vite';

export default defineConfig({
  plugins: [
    litPlugin({
      languageServer: {
        diagnostics: {css: 'off', 'event-type': 'warning'},
      },
    }),
  ],
});
```

In a project without Vite, put the same settings in a `lit-devtools.config.ts` (or `.mts`, `.js`, `.mjs`, `.json`) next to its `package.json`:

```ts
export default {
  languageServer: {
    scan: ['src', 'lib'],
    cssTemplateTags: ['css', 'styles'],
  },
};
```

When a package has both, the Vite config’s `languageServer` wins as a whole, and the config file gets a warning saying it’s ignored: the two are never merged key by key. A `.ts` config file needs Node 22.18 or later; a `.js` or `.json` one works on any. The [settings reference](/reference/language-server/#settings) lists every key.

## Check it in CI with Oxlint

The same problems can fail a lint run. Install `@oddsquad/lit-devtools` next to Oxlint and extend its Oxlint plugin’s recommended config, which turns each rule on at the severity the editor gives it:

```sh
npm install -D oxlint @oddsquad/lit-devtools
```

```ts
import {defineConfig} from 'oxlint';
import litDevtools from '@oddsquad/lit-devtools/oxlint';

export default defineConfig({
  extends: [litDevtools.configs.recommended],
  rules: {'lit-devtools/css': 'off'},
});
```

Rules set next to `extends` win, as `lit-devtools/css` does here. With Vite+, the same object goes under `lint` in `vite.config.ts`. A project that wants only the rules installs `@oddsquad/oxlint-plugin-lit` and imports from it instead. In an `.oxlintrc.json`, list the plugin and its rules yourself:

```json
{
  "jsPlugins": ["@oddsquad/lit-devtools/oxlint"],
  "rules": {"lit-devtools/event-type": "error", "lit-devtools/css": "warn"}
}
```

* Oxlint’s config decides each rule’s severity; the `diagnostics` setting is for the editor only. The other settings, such as `scan`, apply to both.
* Silence one spot with Oxlint’s own comment, `// oxlint-disable-next-line lit-devtools/event-type`.
* Oxlint reads JavaScript and TypeScript files, so problems in HTML, Astro and MDX pages still show only in the editor.
* The first file waits while the plugin reads the workspace, once per run.

## Use it in a monorepo

Open the monorepo at its root. The server finds the workspace from a `pnpm-workspace.yaml` or a `workspaces` field in `package.json`, and reads every package in it:

* Each package is read with its own settings and its own Vite config, so its aliases apply.
* A component can extend a base class from another workspace package; its inherited attributes and properties show up.
* A tag from a published library completes only in the packages that depend on that library.

## When nothing shows up

* Check that the server started: in VS Code, the **Lit Language Server** output channel; in Zed, **dev: open language server logs**.
* After rebuilding the server, restart it: **Lit: Restart Language Server** in VS Code, **editor: restart language server** in Zed.
* Check the settings file for a warning on its first line: a mistake there is reported, not thrown.
* With another Custom Elements Manifest server installed, such as the Web Components Language Server, hovers appear twice; disable one.

## Related

[Language server reference](/reference/language-server/)What it completes, shows and reports, its settings and rules.

[Publish a Custom Elements Manifest](/guides/manifest/)Document your components for other tools and the people who install them.
