# How to Configure Monorepo Linting in TSSLint with Multiple tsconfig.json Files

> Configure monorepo linting with TSSLint and multiple tsconfigjson files. Learn how TSSLint uses glob patterns and parallel workers for efficient code inspection across your projects.

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

---

**TSSLint treats each [`tsconfig.json`](https://github.com/johnsoncodehk/tsslint/blob/main/tsconfig.json) as an independent linting unit, allowing you to lint an entire monorepo by passing multiple `--project` flags with glob patterns that the CLI expands into parallel worker processes.**

In a monorepo environment, managing linting across multiple packages with different TypeScript configurations can be complex. TSSLint simplifies this by treating every TypeScript project—defined by a [`tsconfig.json`](https://github.com/johnsoncodehk/tsslint/blob/main/tsconfig.json) file—as a first-class linting boundary. This architecture allows the CLI to orchestrate multiple projects simultaneously while respecting per-project rule sets and language plugins.

## Understanding TSSLint's Project-Based Architecture

TSSLint's CLI, located in [`packages/cli/index.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/cli/index.ts), is designed around the concept that each [`tsconfig.json`](https://github.com/johnsoncodehk/tsslint/blob/main/tsconfig.json) represents a distinct linting context. This design enables fine-grained control over how different parts of a monorepo are analyzed.

### The tsconfig.json as a Linting Boundary

When you invoke the TSSLint CLI, it constructs a map called `tsconfigAndLanguages` (lines 57-71 in [`packages/cli/index.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/cli/index.ts)). This map associates each discovered [`tsconfig.json`](https://github.com/johnsoncodehk/tsslint/blob/main/tsconfig.json) path with a list of language identifiers. The CLI then instantiates a `Project` class (lines 40-63) for each entry, which loads the companion [`tsslint.config.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/tsslint.config.ts) file using `ts.findConfigFile` (line 65).

### Language Plugin Resolution

For projects using frameworks like Vue, MDX, or Astro, TSSLint dynamically loads language plugins through [`packages/cli/lib/languagePlugins.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/cli/lib/languagePlugins.ts). The `load` function (lines 13-34) adds the appropriate language support based on the identifiers attached to each project during the initial flag parsing phase.

## Configuring Multiple Projects in the CLI

The TSSLint CLI accepts multiple project paths through various flags, expanding glob patterns to discover configurations across your monorepo structure.

### Using Glob Patterns with --project Flags

The CLI scans command-line arguments for project-related flags—including `--project`, `--vue-project`, `--vue-vine-project`, `--mdx-project`, `--astro-project`, and `--ts-macro-project`. For each flag, it glob-expands the following arguments using `fs.globSync`, allowing patterns like `packages/*/tsconfig.json` to resolve to multiple configuration files:

```bash

# Lint every package in a monorepo with a single command

npx tsslint --project packages/*/tsconfig.json

```

### Framework-Specific Project Flags

When a flag includes a framework name, TSSLint automatically attaches the corresponding language identifier to that project. This ensures the correct parser is used without manual configuration:

```bash

# Lint TypeScript packages alongside a Vue application

npx tsslint \
  --project packages/*/tsconfig.json \
  --vue-project apps/web/tsconfig.json

```

You can also use brace expansion to combine multiple patterns in one argument:

```bash
npx tsslint \
  --project {tsconfig.json,packages/*/tsconfig.json,extensions/*/tsconfig.json}

```

## Per-Project Configuration with tsslint.config.ts

Each [`tsconfig.json`](https://github.com/johnsoncodehk/tsslint/blob/main/tsconfig.json) can have its own [`tsslint.config.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/tsslint.config.ts) file located in the same directory. When the `Project` class initializes, it resolves this configuration file using TypeScript's `ts.findConfigFile` utility (line 65 in [`packages/cli/index.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/cli/index.ts)).

Here is an example of a project-specific configuration:

```typescript
// packages/foo/tsslint.config.ts
import { defineConfig } from '@tsslint/config';
import { fromTSLRules } from '@tsslint/config';
import { core } from 'tsl';

export default defineConfig({
  rules: fromTSLRules(core.all()), // project-specific rule set
});

```

This architecture allows different packages in your monorepo to enforce different rule sets, severity levels, or plugin configurations while still being linted in a single coordinated run.

## Parallel Execution and Worker Architecture

After constructing the `Project` instances, TSSLint spawns lint workers to process files in parallel. The `startWorker` function (starting at line 27 in [`packages/cli/index.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/cli/index.ts)) creates worker threads that lint each file in every project while maintaining per-project caches.

This parallelization ensures that linting a monorepo with dozens of packages scales efficiently, as each project runs independently while the CLI aggregates diagnostics into a unified console report.

## Summary

- TSSLint treats each [`tsconfig.json`](https://github.com/johnsoncodehk/tsslint/blob/main/tsconfig.json) as an independent linting unit, creating a `Project` instance for every configuration found.
- The CLI accepts multiple `--project` flags with glob patterns (e.g., `packages/*/tsconfig.json`), expanding them using `fs.globSync` to discover all projects in a monorepo.
- Framework-specific flags (`--vue-project`, `--mdx-project`, etc.) automatically attach the correct language identifiers and load appropriate plugins from [`packages/cli/lib/languagePlugins.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/cli/lib/languagePlugins.ts).
- Each project resolves its own [`tsslint.config.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/tsslint.config.ts) via `ts.findConfigFile`, allowing per-package rule customization.
- Lint workers run in parallel via `startWorker`, aggregating results across all projects into a single report.

## Frequently Asked Questions

### How does TSSLint handle multiple tsconfig.json files in a single command?

TSSLint scans CLI arguments for `--project` and framework-specific flags, then uses `fs.globSync` to expand glob patterns like `packages/*/tsconfig.json` into individual project paths. It creates a `Project` instance for each discovered [`tsconfig.json`](https://github.com/johnsoncodehk/tsslint/blob/main/tsconfig.json), allowing you to lint an entire monorepo with one command.

### Can different packages in a monorepo have different linting rules?

Yes. Each [`tsconfig.json`](https://github.com/johnsoncodehk/tsslint/blob/main/tsconfig.json) directory can contain its own [`tsslint.config.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/tsslint.config.ts) file. When the CLI initializes a `Project` instance, it calls `ts.findConfigFile` (line 65 in [`packages/cli/index.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/cli/index.ts)) to locate and load the project-specific configuration, enabling different rules, severities, or plugins per package.

### What is the difference between --project and --vue-project flags?

The `--project` flag treats the specified [`tsconfig.json`](https://github.com/johnsoncodehk/tsslint/blob/main/tsconfig.json) as a standard TypeScript project, while `--vue-project` (and similar framework flags like `--mdx-project`, `--astro-project`) attaches a language identifier to the project. This identifier triggers the loading of framework-specific language plugins via [`packages/cli/lib/languagePlugins.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/cli/lib/languagePlugins.ts), ensuring proper parsing of Vue SFCs or MDX files.

### How does TSSLint optimize performance when linting large monorepos?

TSSLint uses a worker-based architecture where `startWorker` (starting at line 27 in [`packages/cli/index.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/cli/index.ts)) spawns parallel lint workers for each project. These workers process files concurrently while maintaining per-project caches, and the CLI aggregates diagnostics into a unified report. This parallelization ensures that adding more packages to a monorepo does not linearly increase linting time.