Scopes guide
Scopes enable path-based rule application for monorepos. Apply different rules to frontend vs backend, new code vs legacy, or team-specific directories while maintaining a shared base.
See it in action: Check out the monorepo scopes example for a working demonstration.
Quick example
Monorepo structure:
my-monorepo/
├── apps/
│ ├── web/ # Next.js app
│ └── mobile/ # React Native app
├── packages/
│ └── api/ # Node.js API
└── services/
└── worker/ # Python workerScope configuration:
scopes:
- path: "apps/web"
include: ["**/*.ts", "**/*.tsx"]
rulesets: ["base-rules", "nextjs-rules"]
- path: "packages/api"
include: ["**/*.ts"]
rulesets: ["base-rules", "node-rules"]
- path: "services/worker"
include: ["**/*.py"]
rulesets: ["base-rules", "python-rules"]Result: Each directory gets appropriate stack-specific rules.
When to use scopes
Good use cases
- Monorepos - Different tech stacks per directory
- Team boundaries - Team A owns
apps/web, Team B ownspackages/api - Progressive adoption - Strict rules in new code, lenient in legacy
- Multi-stack projects - Frontend + backend + services with different requirements
Not suitable for
- Single-stack projects - Use base rules without scopes
- Rule customization - Use overlays to adjust severity/inputs
- Stack-specific values - Use plugs for test commands, paths, etc.
Scope anatomy
Basic scope
scopes:
- path: "apps/web"
include: ["**/*.ts", "**/*.tsx"]
rulesets: ["base-rules", "nextjs-rules"]Advanced scope with exclusions
scopes:
- path: "packages/api"
include: ["**/*.ts"]
exclude: ["**/*.test.ts", "**/__tests__/**"]
rulesets: ["base-rules", "node-rules", "api-rules"]Default scope (workspace root)
scopes:
- path: "." # Workspace root
include: ["**/*.ts"]
rulesets: ["base-rules"]Scope properties
path (required)
Relative path from workspace root.
Rules:
- Must be relative (no leading
/) - No parent directory traversal (
..not allowed) - Use forward slashes (POSIX-style)
- Use
.for workspace root
Examples:
# Valid
path: "apps/web"
path: "packages/api"
path: "." # Workspace root
# Invalid
path: "/apps/web" # Absolute path
path: "../other" # Parent traversal
path: "apps\\web" # Backslashes (use forward slashes)include (optional)
Glob patterns to include files.
Rules:
- Standard glob syntax (micromatch)
- Relative to scope path
- Multiple patterns allowed
- Defaults to all files if omitted
Examples:
# TypeScript only
include: ["**/*.ts", "**/*.tsx"]
# JavaScript and TypeScript
include: ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
# Specific directories
include: ["src/**/*.ts", "lib/**/*.ts"]
# All files (default)
include: ["**/*"]exclude (optional)
Glob patterns to exclude files.
Rules:
- Standard glob syntax (micromatch)
- Relative to scope path
- Applied after include patterns
- Defaults to empty if omitted
Examples:
# Exclude tests
exclude: ["**/*.test.ts", "**/__tests__/**"]
# Exclude generated files
exclude: ["**/*.generated.ts", "**/dist/**", "**/build/**"]
# Exclude multiple patterns
exclude:
- "**/*.test.ts"
- "**/__tests__/**"
- "**/node_modules/**"
- "**/dist/**"rulesets (optional)
List of rule pack IDs to apply to this scope.
Rules:
- Rule pack IDs from sources
- Applied in order (later packs override earlier)
- Defaults to all rules if omitted
Examples:
# Base + stack-specific
rulesets: ["base-rules", "nextjs-rules"]
# Multiple stack packs
rulesets: ["base-rules", "typescript-rules", "react-rules", "nextjs-rules"]
# Single ruleset
rulesets: ["python-rules"]
# All rules (default)
rulesets: []Merge order and precedence
Scopes support hierarchical rule merging with configurable order.
Default merge order
merge:
strategy: "deep"
order: ["root", "path", "local"]Merge order:
- root - Rules from workspace root config
- path - Rules from scope-specific configs
- local - Rules from nested/local configs
Last writer wins: Later sources override earlier ones.
Merge strategies
deep (default):
- Merges rule properties recursively
- Preserves non-conflicting properties
- Last writer wins for conflicts
Example:
# Root config
rules:
- id: test-rule
severity: "warn"
applies_to: ["**/*.ts"]
# Scope config
rules:
- id: test-rule
severity: "error" # Overrides root
# Result: severity="error", applies_to=["**/*.ts"]Custom merge order
scopes:
- path: "apps/web"
rulesets: ["nextjs-rules"]
merge:
strategy: "deep"
order: ["path", "root", "local"] # Path rules take precedence over rootScenario-based examples
More examples: See STRUCTURE.md in the monorepo scopes example for detailed architecture explanation.
Scenario 1: Solo developer - Next.js + Node.js monorepo
Goal: Different rules for frontend and backend.
Structure:
my-app/
├── apps/
│ └── web/ # Next.js frontend
└── packages/
└── api/ # Node.js backendConfiguration:
sources:
- git: https://github.com/org/base-rules
ref: v1.0.0
- git: https://github.com/org/nextjs-rules
ref: v1.0.0
- git: https://github.com/org/node-rules
ref: v1.0.0
scopes:
- path: "apps/web"
include: ["**/*.ts", "**/*.tsx"]
exclude: ["**/*.test.ts"]
rulesets: ["base-rules", "nextjs-rules"]
- path: "packages/api"
include: ["**/*.ts"]
exclude: ["**/*.test.ts"]
rulesets: ["base-rules", "node-rules"]Result:
apps/web/uses Next.js rulespackages/api/uses Node.js rules- Both share base rules
Scenario 2: Team monorepo with multiple teams
Goal: Team boundaries with shared base rules.
Structure:
company-monorepo/
├── apps/
│ ├── web/ # Team A: Frontend
│ └── mobile/ # Team B: Mobile
├── packages/
│ ├── api/ # Team C: Backend
│ └── shared/ # Shared utilities
└── services/
└── worker/ # Team D: WorkersConfiguration:
sources:
- git: https://github.com/company/base-standards
ref: v2.0.0
- git: https://github.com/company/frontend-standards
ref: v1.0.0
- git: https://github.com/company/backend-standards
ref: v1.0.0
scopes:
# Team A: Frontend
- path: "apps/web"
include: ["**/*.ts", "**/*.tsx"]
rulesets: ["base-standards", "frontend-standards"]
# Team B: Mobile
- path: "apps/mobile"
include: ["**/*.ts", "**/*.tsx"]
rulesets: ["base-standards", "frontend-standards"]
# Team C: Backend
- path: "packages/api"
include: ["**/*.ts"]
rulesets: ["base-standards", "backend-standards"]
# Shared: Base only
- path: "packages/shared"
include: ["**/*.ts"]
rulesets: ["base-standards"]
# Team D: Workers
- path: "services/worker"
include: ["**/*.ts"]
rulesets: ["base-standards", "backend-standards"]Result: Each team gets appropriate rules while sharing base standards.
Scenario 3: Progressive adoption (strict in new, lenient in legacy)
Goal: Enforce strict rules in new code, lenient in legacy during migration.
Structure:
app/
├── src/
│ ├── new/ # New code (strict)
│ └── legacy/ # Legacy code (lenient)
└── tests/Configuration:
sources:
- git: https://github.com/org/typescript-standards
ref: v1.0.0
scopes:
# Strict rules for new code
- path: "src/new"
include: ["**/*.ts"]
rulesets: ["typescript-standards"]
# Lenient rules for legacy (use overlays to downgrade)
- path: "src/legacy"
include: ["**/*.ts"]
rulesets: ["typescript-standards"]
overlays:
overrides:
# Downgrade strict rules for legacy code
- selector: "rule[id=strict-null-checks]"
set:
severity: "warn" # Error in new, warn in legacyAlternative with separate rule packs:
sources:
- git: https://github.com/org/typescript-strict
ref: v1.0.0
- git: https://github.com/org/typescript-lenient
ref: v1.0.0
scopes:
- path: "src/new"
rulesets: ["typescript-strict"]
- path: "src/legacy"
rulesets: ["typescript-lenient"]Scenario 4: Multi-stack monorepo (Next.js + Node.js + Python)
Goal: Different tech stacks with appropriate rules per stack.
Structure:
multi-stack/
├── apps/
│ └── web/ # Next.js (TypeScript)
├── services/
│ ├── api/ # Node.js (TypeScript)
│ └── worker/ # Python
└── packages/
└── shared/ # Shared TypeScript utilitiesConfiguration:
sources:
- git: https://github.com/org/base-rules
ref: v1.0.0
- git: https://github.com/org/nextjs-rules
ref: v1.0.0
- git: https://github.com/org/node-rules
ref: v1.0.0
- git: https://github.com/org/python-rules
ref: v1.0.0
scopes:
# Next.js app
- path: "apps/web"
include: ["**/*.ts", "**/*.tsx"]
exclude: ["**/*.test.ts", "**/*.test.tsx"]
rulesets: ["base-rules", "nextjs-rules"]
# Node.js API
- path: "services/api"
include: ["**/*.ts"]
exclude: ["**/*.test.ts"]
rulesets: ["base-rules", "node-rules"]
# Python worker
- path: "services/worker"
include: ["**/*.py"]
exclude: ["**/*_test.py", "**/tests/**"]
rulesets: ["base-rules", "python-rules"]
# Shared TypeScript utilities
- path: "packages/shared"
include: ["**/*.ts"]
exclude: ["**/*.test.ts"]
rulesets: ["base-rules"]Result: Each stack gets appropriate rules, shared utilities use base only.
Scenario 5: Combining scopes with plugs and overlays
Goal: Use all three customization features together.
Configuration:
sources:
- git: https://github.com/org/base-rules
ref: v1.0.0
- git: https://github.com/org/nextjs-rules
ref: v1.0.0
- git: https://github.com/org/node-rules
ref: v1.0.0
# 1. Scopes: Apply different rules per path
scopes:
- path: "apps/web"
rulesets: ["base-rules", "nextjs-rules"]
- path: "packages/api"
rulesets: ["base-rules", "node-rules"]
# 2. Plugs: Fill stack-specific values
plugs:
fills:
test.cmd: "pnpm test"
docs.url: "https://docs.example.com"
# 3. Overlays: Adjust severity for team
overlays:
overrides:
- selector: "rule[id=no-console-log]"
set:
severity: "error" # Upgrade from warningApplication order:
- Scopes filter rules by path
- Plugs resolve template slots
- Overlays apply property overrides
CLI commands
List configured scopes
aligntrue scopesExample output:
Configured scopes (3):
apps/web
Include: **/*.ts, **/*.tsx
Exclude: **/*.test.ts
Rulesets: base-rules, nextjs-rules
packages/api
Include: **/*.ts
Exclude: **/*.test.ts
Rulesets: base-rules, node-rules
services/worker
Include: **/*.py
Rulesets: base-rules, python-rules
Merge order: root → path → localValidate scope configuration
aligntrue checkValidates:
- Path safety (no
..or absolute paths) - Glob pattern syntax
- Merge order values
- Ruleset references
See CLI Reference for complete command documentation.
Path validation
Safety rules
AlignTrue validates scope paths to prevent security issues:
Blocked:
- Absolute paths:
/apps/web - Parent traversal:
../other - Backslashes:
apps\web(use forward slashes)
Allowed:
- Relative paths:
apps/web - Nested paths:
apps/web/src - Workspace root:
.
Glob pattern validation
Glob patterns are validated for syntax errors:
# Valid
include: ["**/*.ts", "src/**/*.tsx"]
# Invalid (syntax error)
include: ["**/*[.ts"] # Unclosed bracketMerge order validation
Merge order must contain only valid values:
# Valid
merge:
order: ["root", "path", "local"]
# Invalid
merge:
order: ["root", "invalid", "local"] # Unknown value
order: ["root", "path", "path"] # DuplicateBest practices
For solo developers
- Start simple - Use scopes only when you have multiple stacks
- Shared base - Use base rules across all scopes
- Stack-specific - Add stack packs per scope
- Document structure - Add comments explaining scope boundaries
Example:
scopes:
# Frontend: Next.js app
- path: "apps/web"
rulesets: ["base-rules", "nextjs-rules"]
# Backend: Node.js API
- path: "packages/api"
rulesets: ["base-rules", "node-rules"]For teams
- Team boundaries - Map scopes to team ownership
- Shared standards - Use base rules across all teams
- Team-specific - Allow team-specific overrides via overlays
- Document ownership - Add comments with team names
- Review changes - PR review for scope configuration changes
Example:
scopes:
# Team A: Frontend
# Owner: @frontend-team
- path: "apps/web"
rulesets: ["base-standards", "frontend-standards"]
# Team B: Backend
# Owner: @backend-team
- path: "packages/api"
rulesets: ["base-standards", "backend-standards"]General best practices
- Minimal scopes - Only create scopes when rules differ
- Clear boundaries - Use directory structure that maps to scopes
- Shared base - Maximize shared rules, minimize scope-specific
- Exclude tests - Use exclude patterns for test files if rules differ
- Validate early - Run
aligntrue checkafter scope changes
Troubleshooting
Scope path validation errors
Problem: Invalid scope path: absolute paths not allowed
Solution: Use relative paths from workspace root:
# Bad
scopes:
- path: "/apps/web" # Absolute path
# Good
scopes:
- path: "apps/web" # Relative pathProblem: Invalid scope path: parent directory traversal (..) not allowed
Solution: Remove .. segments:
# Bad
scopes:
- path: "../other" # Parent traversal
# Good
scopes:
- path: "other" # Relative to workspace rootGlob pattern errors
Problem: Invalid glob pattern: unclosed bracket
Solution: Fix glob syntax:
# Bad
include: ["**/*[.ts"] # Unclosed bracket
# Good
include: ["**/*.ts"] # Valid globMerge order errors
Problem: Invalid merge order value: must be one of root, path, local
Solution: Use only valid values:
# Bad
merge:
order: ["root", "invalid", "local"]
# Good
merge:
order: ["root", "path", "local"]Problem: Duplicate merge order value
Solution: Remove duplicates:
# Bad
merge:
order: ["root", "path", "path"]
# Good
merge:
order: ["root", "path", "local"]Rules not applying to scope
Problem: Rules defined but not applying to files in scope.
Diagnosis:
# Check scope configuration
aligntrue scopes
# Validate configuration
aligntrue checkCommon causes:
- Include pattern doesn’t match files
- Exclude pattern blocks files
- Ruleset ID doesn’t match source pack
Solution: Adjust include/exclude patterns or ruleset IDs.
Scope conflicts
Problem: Multiple scopes match the same path.
Behavior: Last matching scope wins (scopes apply in definition order).
Solution: Reorder scopes or make paths more specific:
# Ambiguous (both match apps/web/src/file.ts)
scopes:
- path: "apps"
rulesets: ["base-rules"]
- path: "apps/web"
rulesets: ["nextjs-rules"]
# Clear (more specific path wins)
scopes:
- path: "apps/web"
rulesets: ["nextjs-rules"]
- path: "apps"
rulesets: ["base-rules"]Related documentation
- Customization Overview - When to use scopes vs plugs vs overlays
- Plugs Guide - Stack-specific values
- Overlays Guide - Rule property overrides
- Team Mode Guide - Team collaboration with scopes
- CLI Reference - Complete command docs
- Solo Developer Guide - Solo workflow with scopes
- Team Guide - Team collaboration with scopes
Summary
Scopes enable path-based rule application:
- Monorepo support - Different rules per directory
- Team boundaries - Map scopes to team ownership
- Progressive adoption - Strict in new, lenient in legacy
- Multi-stack - Different tech stacks per scope
- Hierarchical merge - Root → path → local precedence
When to use:
- Use scopes for path-based rule application (monorepo)
- Use plugs for stack-specific values (test commands, paths)
- Use overlays for rule property overrides (severity, inputs)
Start with simple scopes, add complexity only when needed.