# How to Create Category Plugins in TSSLint to Group and Organize Rules

> Learn to create TSSLint category plugins to group and organize related rules. Dynamically remap rule severities across your linting pipeline with createCategoryPlugin.

- Repository: [Johnson Chu/tsslint](https://github.com/johnsoncodehk/tsslint)
- Tags: how-to-guide
- Published: 2026-03-04

---

**Create category plugins in TSSLint by importing `createCategoryPlugin` from `@tsslint/config`, defining a mapping of minimatch patterns to `ts.DiagnosticCategory` values, and including the plugin in your [`tsslint.config.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/tsslint.config.ts) to dynamically remap rule severities across your entire linting pipeline.**

TSSLint, maintained in the `johnsoncodehk/tsslint` repository, provides a lightweight but powerful plugin system that lets you transform diagnostics after they are generated. When you create category plugins, you can batch-categorize related rules—such as treating all stylistic checks as suggestions or security issues as errors—without touching individual rule source code.

## What Are Category Plugins?

A **category plugin** is a specialized TSSLint plugin that implements the `Plugin` interface defined in [`packages/types/index.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/types/index.ts) (lines 24-33). Unlike rule plugins that generate diagnostics, category plugins consume diagnostics through the `resolveDiagnostics` hook and remap their `category` property to `Error`, `Warning`, `Suggestion`, or `Message`. This post-processing step allows you to organize rules into logical groups based on severity, making CLI output cleaner and filtering more predictable.

## How Category Plugins Work

### The Factory Function and Configuration

The core implementation lives in [`packages/config/lib/plugins/category.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/config/lib/plugins/category.ts) (lines 6-34). The exported `create` function (re-exported as `createCategoryPlugin` in [`packages/config/index.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/config/index.ts), lines 1-4) accepts a configuration object where:

- **Keys** are `minimatch` glob patterns matching rule IDs or diagnostic codes (e.g., `no-*`, `react/*`).
- **Values** are `ts.DiagnosticCategory` enum values (e.g., `ts.DiagnosticCategory.Warning`).
- An optional `source` parameter defaults to `"tsslint"` and filters which diagnostics to process.

### Pattern Matching and Caching

For each diagnostic whose `source` matches the configured value, the plugin stringifies the diagnostic `code` and tests it against the pattern map using the `minimatch` library. To optimize performance, the implementation maintains a `matchCache` that stores lookup results, avoiding redundant glob evaluations for repeated diagnostic codes.

### Category Assignment

When a pattern matches, the plugin overwrites the diagnostic's `category` property with the user-specified value. The modified diagnostics array then flows back to the CLI or other downstream plugins, which render the updated severity levels.

## Step-by-Step Guide to Creating Category Plugins

### 1. Import the Factory

Import the helper from the public API. This resolves to the re-export in [`packages/config/index.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/config/index.ts).

```typescript
import { createCategoryPlugin } from '@tsslint/config';
import * as ts from 'typescript';

```

### 2. Define Your Category Mapping

Create an object that maps glob patterns to TypeScript diagnostic categories. Use standard `minimatch` syntax for flexible rule grouping.

```typescript
const categoryMap = {
  // All console-related rules become warnings
  'no-console*': ts.DiagnosticCategory.Warning,
  // Any rule prefixed with "react/" is treated as an error
  'react/*': ts.DiagnosticCategory.Error,
  // Stylistic prefer-* rules appear as suggestions
  'prefer-*': ts.DiagnosticCategory.Suggestion,
  // Catch-all for info-level messages
  'tslint/*': ts.DiagnosticCategory.Message,
};

```

### 3. Instantiate the Plugin

Call `createCategoryPlugin` with your mapping. You can optionally pass a custom `source` string as the second argument if you need to process diagnostics from specific tools.

```typescript
const myCategoryPlugin = createCategoryPlugin(categoryMap, 'tsslint');

```

### 4. Add to Your TSSLint Configuration

Include the plugin in your [`tsslint.config.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/tsslint.config.ts) file within the `plugins` array of `defineConfig`.

```typescript
import { defineConfig, createCategoryPlugin } from '@tsslint/config';
import * as ts from 'typescript';
import NoConsoleRule from './rules/noConsoleRule';
import NoEvalRule from './rules/noEvalRule';

export default defineConfig({
  plugins: [
    // Category plugin remaps severities dynamically
    createCategoryPlugin({
      'no-console*': ts.DiagnosticCategory.Warning,
      'no-eval': ts.DiagnosticCategory.Error,
      'prefer-*': ts.DiagnosticCategory.Suggestion,
    }),
    // Add other plugins (ignore, custom formatters, etc.)
  ],
  rules: {
    'no-console': NoConsoleRule,
    'no-eval': NoEvalRule,
    // Additional rule definitions...
  },
});

```

### 5. Run TSSLint

Execute the CLI. Diagnostics emitted by matched rules now appear with your assigned categories, and the CLI respects these severities when filtering output.

```bash
npx tsslint src/**/*.ts

```

## Advanced Pattern Matching Techniques

Because the category plugin uses `minimatch` under the hood, you can leverage full glob syntax in your patterns:

- **`no-*`** matches `no-console`, `no-debugger`, `no-eval`.
- **`react/*`** matches any rule in the `react` namespace.
- **`**/security/*`** matches rules nested in any security subdirectory.
- **`?`** matches single characters, useful for versioned rule sets.

Patterns are evaluated in the order they are defined in your configuration object, and the first match wins. Place more specific patterns before generic wildcards to ensure correct categorization.

## Summary

- **Category plugins** intercept diagnostics after rule execution via the `resolveDiagnostics` hook defined in [`packages/types/index.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/types/index.ts).
- The `createCategoryPlugin` factory, located in [`packages/config/lib/plugins/category.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/config/lib/plugins/category.ts), accepts minimatch patterns and `ts.DiagnosticCategory` values to remap severities.
- A built-in `matchCache` optimizes performance by avoiding redundant pattern matching for repeated diagnostic codes.
- You import the helper from `@tsslint/config`, define your pattern-to-category map, and include the plugin in [`tsslint.config.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/tsslint.config.ts) to organize rules dynamically.

## Frequently Asked Questions

### What glob patterns are supported when I create category plugins?

TSSLint uses the `minimatch` library for pattern matching, supporting standard glob syntax including `*` (wildcards), `?` (single character), `**/` (any directory depth), and braces for expansion. This allows flexible groupings like `no-*` for all "no-" prefixed rules or `react/*` for entire rule namespaces.

### Can I limit category plugins to diagnostics from specific sources?

Yes. The `createCategoryPlugin` factory accepts an optional second `source` parameter that defaults to `"tsslint"`. By passing a different string (e.g., `"eslint"`), you can restrict the plugin to only remapping diagnostics that originated from that specific tool, leaving others unchanged.

### How does the category plugin handle performance for large codebases?

The implementation in [`packages/config/lib/plugins/category.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/config/lib/plugins/category.ts) maintains a `matchCache` object that stores the result of pattern lookups keyed by diagnostic code. When the same rule fires multiple times, the plugin retrieves the cached category assignment instead of re-running `minimatch` comparisons, significantly reducing overhead in large projects.

### Where is the category plugin defined in the TSSLint source code?

The primary logic resides in [`packages/config/lib/plugins/category.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/config/lib/plugins/category.ts) (lines 6-34), which exports the `create` function. This is re-exported as `createCategoryPlugin` in [`packages/config/index.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/config/index.ts) (lines 1-4) for public consumption. The plugin implements the `Plugin` interface contract defined in [`packages/types/index.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/types/index.ts) (lines 24-33).