---
description: Learn how to configure Knip to work with TailwindCSS v4's new
  @plugin and @import directives using custom compilers. Eliminate false
  positives and keep your dependency reports clean.
keywords:
  - knip
  - tailwindcss
  - regex
  - typescript
  - custom compilers
  - false positives
  - css analysis
  - build tools
  - dead code elimination
  - unused dependencies
publishDate: 2025-07-08
tags:
  - Tailwind
  - Tooling
title: Fix Knip False Positives with Tailwind v4
---

> [!WARNING]
> This is no longer needed after `knip` [version 5.67.0](https://github.com/webpro-nl/knip/releases/tag/5.67.0), which added an official Tailwind CSS v4 compiler.

## What is Knip?

[Knip](https://knip.dev) helps declutter JavaScript and TypeScript projects by detecting dead exports, unused files, and dependencies. It does this intelligently using a plugin system modeled after real-world tooling and frameworks. This fine-grained approach results in an accurate representation of dead code.

To [get started with Knip](https://knip.dev/overview/getting-started), run:

```bash
pnpm create @knip/config
```

Add a script to your `package.json`:

```json title="package.json"
{
  "scripts": {
    "knip": "knip"
  }
}
```

Or just run it directly:

```bash
pnpx knip
```

Out of the box, Knip technically works with Tailwind CSS v4, but not perfectly. Its lack of support for Tailwind's new **@plugin** and **@import** directives can cause false positives.

## What changed in Tailwind CSS v4?

Tailwind CSS v4 introduced a new configuration approach that is [CSS-first](http://tailwindcss.com/blog/tailwindcss-v4#css-first-configuration), which allows for imports and plugins. However, Knip doesn't scan these directives by default, which leads to false positives. For example, if you have a Tailwind CSS file like this:

```css
@import "tailwindcss";

@plugin "@tailwindcss/typography";

@plugin "daisyui";

@plugin "@iconify/tailwind4";
```

When you run `knip`, you might see output like this:

```bash
Unused devDependencies (4)
@iconify/tailwind4       package.json:29:6
@tailwindcss/typography  package.json:32:6
daisyui                  package.json:36:6
tailwindcss              package.json:45:6
error: script "knip" exited with code 1
```

One quick fix is to ignore these dependencies in your [Knip configuration file](https://knip.dev/overview/configuration):

```ts title="knip.config.ts"
import type { KnipConfig } from "knip";

export default {
  ignoreDependencies: [
    "@iconify/tailwind4",
    "@tailwindcss/typography",
    "daisyui",
    "tailwindcss",
  ],
} satisfies KnipConfig;
```

_We use `satisfies KnipConfig` to ensure our config matches the expected structure. It's a [TypeScript safety check](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html#the-satisfies-operator), not required for runtime._

Knip supports a [custom compilers configuration option](https://knip.dev/features/compilers#custom-compilers), and with a bit of regex magic, we can teach it to understand Tailwind's directives like **@import** and **@plugin**.

## How to configure Knip for Tailwind CSS v4?

```ts title="knip.config.ts"
import type { KnipConfig } from "knip";

export default {
  compilers: {
    css: (text: string) => {
      // Converts @import and @plugin directives into JS-style imports
      return [...text.matchAll(/@(?:import|plugin)\s+["']([^"']+)["']/g)]
        .map(([_, dep]) => `import "${dep}";`)
        .join("\n");
    },
  },
} satisfies KnipConfig;
```

And if you've modified `knip`'s `project` field, be sure to include `.css` files as well:

```ts title="knip.config.ts"
import type { KnipConfig } from "knip";

export default {
  project: "**/*.{ts,tsx,css}",
} satisfies KnipConfig;
```

This prevents false positives, keeps your reports clean, and avoids accidentally removing real dependencies.

## How does this work?

This configuration defines a custom compiler for CSS files. It looks for **@import** and **@plugin** directives using a regular expression and transforms them into JavaScript-style import statements that Knip can understand and analyze like regular module imports.

_This borrows from [Knip's own css compiler example](https://knip.dev/features/compilers#css)._

[matchAll](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/matchAll) is used to find all matches of a regular expression in a string.

The regex pattern `@(?:import|plugin)\s+["']([^"']+)["']` breaks down as:

- `@(?:import|plugin)` - Matches either @import or @plugin
- `\s+` - Matches one or more whitespace characters
- `["']([^"']+)["']` - Captures the dependency name inside quotes

In the earlier example, it would return:

```ts
[
  ['@import "tailwindcss"', "tailwindcss"],
  ['@plugin "@tailwindcss/typography"', "@tailwindcss/typography"],
  ['@plugin "daisyui"', "daisyui"],
  ['@plugin "@iconify/tailwind4"', "@iconify/tailwind4"],
];
```

_You can further learn about regex at [regex101](https://regex101.com/r/aoOabK/1)._

Then `map` transforms each match into an import statement using the captured dependency name, and the `join("\n")` combines them into a single string to make it look like valid JavaScript/TypeScript code.

Once that's in place, running `knip` will no longer flag these dependencies:

```bash
✂️  Excellent, Knip found no issues.
```

Tailwind's new config is great, but Knip doesn't know what to do with **@plugin** or **@import** by default. This setup bridges that gap and keeps your reports clean.