Skip to content

Monorepo Support

claudelint provides full support for monorepo projects with workspace detection and configuration inheritance.

File Discovery

claudelint recursively discovers Claude Code configuration files throughout your project tree. CLAUDE.md files in subdirectories (e.g., packages/api/CLAUDE.md, src/CLAUDE.md) are automatically found and validated. Skills in nested .claude/skills/ directories are also discovered, matching Claude Code's on-demand subdirectory skill loading.

For the complete file discovery table and glob patterns, see File Discovery.

Quick Start

1. Config Inheritance

Share configuration across packages using the extends field:

json
{
  "extends": "./base-config.json",
  "rules": {
    "claude-md-size": "warn"
  }
}

2. Workspace Validation

Validate specific packages or all packages in your monorepo:

bash
claudelint check-all --workspace my-package

claudelint check-all --workspaces

Configuration Inheritance

Basic Usage

Create a base configuration that child packages can extend:

json
{
  "extends": "../.claudelintrc.json",
  "rules": {
    "skill-missing-version": "error"
  }
}

Supported Formats

Relative paths:

json
{
  "extends": "../../.claudelintrc.json"
}

Node modules packages:

json
{
  "extends": "claudelint-config-standard"
}
json
{
  "extends": "@company/claudelint-config"
}

Multiple extends:

json
{
  "extends": ["./base.json", "./strict.json"]
}

Merge Behavior

When extending configs, claudelint merges configurations in this order:

  1. Base config (first in extends array)
  2. Additional extended configs (in order)
  3. Current config (overrides everything)

Each field type merges differently:

FieldStrategy
rulesDeep merged (child can override specific rules)
overridesArrays concatenated (all overrides apply)
ignorePatternsArrays concatenated and deduplicated
outputChild completely replaces parent
ScalarsChild value wins

Example Monorepo Structure

text
monorepo/
├── CLAUDE.md                   # Root project context
├── .claudelintrc.json          # Root config
├── pnpm-workspace.yaml
├── packages/
│   ├── app-1/
│   │   ├── CLAUDE.md           # Package-specific context
│   │   └── .claudelintrc.json  # Extends root
│   └── app-2/
│       ├── CLAUDE.md           # Package-specific context
│       └── .claudelintrc.json  # Extends root
└── libs/
    └── shared/
        ├── CLAUDE.md           # Package-specific context
        └── .claudelintrc.json  # Extends root
json
{
  "rules": {
    "claude-md-size": "warn",
    "skill-missing-version": "error"
  },
  "ignorePatterns": [
    "node_modules/**",
    "dist/**"
  ]
}
json
{
  "extends": "../../.claudelintrc.json"
}
json
{
  "extends": "../../.claudelintrc.json",
  "rules": {
    "claude-md-size": "warn"
  }
}

Workspace Detection

claudelint automatically detects monorepo workspaces from:

  • pnpm-workspace.yaml (pnpm)
  • package.json workspaces field (npm/Yarn)

Supported Package Managers

yaml
packages:
  - 'packages/*'
  - 'apps/*'
json
{
  "workspaces": [
    "packages/*",
    "apps/*"
  ]
}
json
{
  "workspaces": {
    "packages": [
      "packages/*",
      "apps/*"
    ]
  }
}

CLI Flags

Validate specific package:

bash
claudelint check-all --workspace my-package

This finds the workspace package with directory name my-package and runs validation only for that package.

Validate all packages:

bash
claudelint check-all --workspaces

This runs validation for every package in the workspace and aggregates results.

Troubleshooting

No workspace detected

Problem: claudelint can't find a workspace configuration in the current directory.

Workspace detection looks for pnpm-workspace.yaml or a workspaces field in package.json.

Solution: Run the command from your monorepo root where the workspace config file exists.

Package not found

Problem: --workspace flag references a package name that doesn't match any workspace.

The error output lists available packages for reference.

Solution: Use the exact directory name of the package (shown in the "Available packages" list in the error output).

Extended config not found

Problem: A .claudelintrc.json uses extends to reference a config file that doesn't exist.

Solution: Check that the relative path is correct and the target file exists on disk.

Circular dependency

Problem: Config extends chain creates a cycle (A extends B, B extends A).

Solution: Remove the circular reference so the extends chain forms a tree.

Migration Guide

Upgrading existing monorepos:

text
packages/
├── app-1/.claudelintrc.json  (full config)
├── app-2/.claudelintrc.json  (full config)
└── shared/.claudelintrc.json (full config)
text
.claudelintrc.json              (shared rules)
packages/
├── app-1/.claudelintrc.json  (extends root)
├── app-2/.claudelintrc.json  (extends root)
└── shared/.claudelintrc.json (extends root)

Steps:

  1. Create root .claudelintrc.json with common rules

  2. Update package configs to extend root:

    json
    {
      "extends": "../../.claudelintrc.json"
    }
  3. Keep only package-specific overrides in child configs

  4. Test with claudelint check-all --workspaces

Backward compatibility: All existing configs continue to work without changes. The extends field is optional, workspaces are auto-detected, and there are no breaking changes to existing functionality.

Best Practices

  1. Keep root config minimal - only shared rules
  2. Use extends for consistency - avoid duplicating rules
  3. Override sparingly - only when packages truly differ
  4. Test with --workspaces - catch issues across all packages
  5. Version shared configs - treat them like dependencies
  6. Document overrides - explain why packages differ

FAQ