Skip to content

Commit b4e550d

Browse files
Rel1cxclaude
andcommitted
docs: enhance CLAUDE.md with comprehensive architecture and workflow guidance
Expand CLAUDE.md to provide detailed guidance for Claude Code including: - Complete development command reference organized by category - Architecture overview with package dependency hierarchy - Core package organization and domain structure - Rule implementation patterns with examples - Testing setup and patterns - Development workflows for common tasks - Important notes on best practices Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 2bd4ddc commit b4e550d

1 file changed

Lines changed: 188 additions & 107 deletions

File tree

CLAUDE.md

Lines changed: 188 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -4,165 +4,246 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
44

55
## Project Overview
66

7-
ESLint React is a high-performance ESLint plugin for React (4-7x faster than alternatives). It provides composable ESLint rules for React and related libraries. It's a monorepo with multiple specialized ESLint plugins that can be used individually or as a unified plugin.
7+
ESLint React is a monorepo containing composable, high-performance ESLint plugins for React and related frameworks. The project provides both a unified plugin (`@eslint-react/eslint-plugin`) and modular plugins for specific concerns (react-x, react-dom, react-web-api, react-hooks-extra, react-naming-convention).
88

9-
## Build System
9+
## Development Commands
1010

11-
- **Package Manager**: pnpm (v10.28.2)
12-
- **Build Tool**: tsdown - TypeScript to JavaScript bundler
13-
- **Formatter**: dprint
14-
- **Test Runner**: vitest
15-
- **TypeScript**: v5.9.3 with strict configuration
16-
17-
## Common Commands
11+
### Building
1812

1913
```bash
20-
# Build all packages (must be run before tests/linting)
14+
# Build all packages (includes update scripts, pkgs, packages, and docs)
2115
pnpm run build
2216

23-
# Run all tests
24-
pnpm run test
17+
# Build internal packages used in the monorepo (.pkgs)
18+
pnpm run build:pkgs
2519

26-
# Run a single test file
27-
pnpm vitest packages/plugins/eslint-plugin-react-x/src/rules/no-missing-key.spec.ts
20+
# Build publishable packages only
21+
pnpm run build:packages
2822

29-
# Run all linting checks
30-
pnpm run lint
31-
32-
# Run specific lint checks
33-
pnpm run lint:es # ESLint
34-
pnpm run lint:ts # TypeScript type checking
35-
pnpm run lint:deps # Dependency analysis with skott
36-
pnpm run lint:publish # Package linting with publint
37-
38-
# Format code
39-
pnpm run format:write
23+
# Build TypeDoc documentation for all packages
24+
pnpm run build:docs
4025

41-
# Update generated files (versions, READMEs, website docs)
42-
pnpm run update:all
26+
# Build the website
27+
pnpm run build:website
4328
```
4429

45-
## Monorepo Structure
30+
### Testing
4631

47-
### Packages (`/packages/`)
32+
```bash
33+
# Run all tests
34+
pnpm test
4835

49-
**Core packages:**
36+
# Run a single test file
37+
pnpm vitest packages/plugins/eslint-plugin-react-x/src/rules/[rule-name].spec.ts
5038

51-
- `@eslint-react/core` - Core ESLint utility module for static analysis of React core APIs
52-
- `@eslint-react/shared` - Shared constants, types, and functions
39+
# Run tests with heap usage logging
40+
pnpm test --logHeapUsage
41+
```
5342

54-
**Plugin packages** (`/packages/plugins/`):
43+
### Linting and Formatting
5544

56-
- `eslint-plugin` - Unified plugin combining all individual plugins
57-
- `eslint-plugin-react-x` - Core React rules (renderer-agnostic)
58-
- `eslint-plugin-react-dom` - DOM-specific rules
59-
- `eslint-plugin-react-web-api` - Web API interaction rules
60-
- `eslint-plugin-react-hooks-extra` - Additional React Hooks rules
61-
- `eslint-plugin-react-naming-convention` - Naming convention rules
62-
- `eslint-plugin-react-debug` - Debug utilities
45+
```bash
46+
# Format code with dprint
47+
pnpm run format:write
6348

64-
**Utility packages** (`/packages/utilities/`):
49+
# Check formatting
50+
pnpm run format:check
6551

66-
- `@eslint-react/ast` - AST manipulation utilities
67-
- `@eslint-react/eff` - Effect/functional programming utilities
68-
- `@eslint-react/var` - Variable analysis utilities
52+
# Run all linting checks (deps, publish, ts, es, examples)
53+
pnpm run lint
6954

70-
### Local Packages (`/.pkgs/`)
55+
# Run ESLint
56+
pnpm run lint:es
7157

72-
Private workspace packages:
58+
# Run TypeScript type checking
59+
pnpm run lint:ts
7360

74-
- `@local/configs` - Shared ESLint and TypeScript configurations
75-
- `@local/function-rules` - Custom function-based lint rules
61+
# Check for circular dependencies
62+
pnpm run lint:deps
7663

77-
### Applications (`/apps/`)
64+
# Verify package.json for publishing
65+
pnpm run lint:publish
66+
```
7867

79-
- `website` - Documentation website built with Next.js and Fumadocs
68+
### Maintenance Scripts
8069

81-
### Examples (`/examples/`)
70+
```bash
71+
# Update version across all packages
72+
pnpm run update:version
8273

83-
Example projects showing integrations with Next.js, React DOM, and various parsers.
74+
# Update README files
75+
pnpm run update:readme
8476

85-
## Rule Structure
77+
# Update website documentation from package sources
78+
pnpm run update:website
8679

87-
Each ESLint rule follows this structure:
80+
# Verify rule metadata consistency
81+
pnpm run verify:rules-metas
8882

89-
```
90-
packages/plugins/[plugin-name]/src/rules/
91-
├── rule-name.ts # Rule implementation
92-
├── rule-name.spec.ts # Test file
93-
└── rule-name.mdx # Documentation
83+
# Sort package.json files
84+
pnpm run sort:package-json
9485
```
9586

87+
## Architecture
88+
89+
### Monorepo Structure
90+
91+
The repository is organized as a pnpm workspace with the following structure:
92+
93+
- **`.pkgs/`** - Internal packages used within the monorepo (configs, function-rules)
94+
- **`packages/`** - Publishable packages organized by type:
95+
- **`packages/utilities/`** - Low-level utilities (ast, eff, var)
96+
- **`packages/shared/`** - Shared constants, types, and utilities
97+
- **`packages/core/`** - Core React analysis utilities (component, hook, jsx detection)
98+
- **`packages/plugins/`** - ESLint plugin packages
99+
- **`test/`** - Shared test utilities and fixtures
100+
- **`scripts/`** - Maintenance and build scripts
101+
- **`apps/`** - Applications (website)
102+
- **`examples/`** - Example projects
103+
104+
### Package Dependencies
105+
106+
The dependency hierarchy flows bottom-up:
107+
108+
1. **`@eslint-react/eff`** - Base JavaScript/TypeScript utilities (no dependencies)
109+
2. **`@eslint-react/ast`** - TSESTree AST utilities (depends on: eff)
110+
3. **`@eslint-react/var`** - Variable and scope analysis (depends on: eff)
111+
4. **`@eslint-react/shared`** - Shared constants, settings, types (depends on: eff)
112+
5. **`@eslint-react/core`** - React-specific analysis (depends on: ast, eff, shared, var)
113+
6. **Plugin packages** - ESLint rules (depend on: core and lower-level packages)
114+
7. **`@eslint-react/eslint-plugin`** - Unified plugin (aggregates all individual plugins)
115+
116+
### Core Package Organization
117+
118+
The `@eslint-react/core` package provides React-specific analysis utilities organized by domain:
119+
120+
- **`api/`** - React API detection and analysis
121+
- **`component/`** - Component detection, collection, and analysis
122+
- Component collectors for both modern and legacy patterns
123+
- Component definition detection
124+
- Component naming and identification
125+
- Semantic node representations
126+
- **`function/`** - Function analysis utilities
127+
- **`hierarchy/`** - Component hierarchy analysis
128+
- **`hook/`** - React Hook detection and analysis
129+
- Hook identification and naming
130+
- Hook collectors for tracking hook usage
131+
- Semantic node representations for hooks
132+
- **`jsx/`** - JSX element and attribute analysis
133+
- JSX detection and configuration
134+
- Attribute value extraction
135+
- Element type analysis
136+
- **`ref/`** - React ref analysis
137+
- **`semantic/`** - Semantic node type definitions
138+
139+
### Plugin Structure
140+
141+
Each plugin package follows a consistent structure:
142+
143+
- **`src/rules/`** - Rule implementations (`.ts`) with co-located tests (`.spec.ts`) and documentation (`.mdx`)
144+
- **`src/configs/`** - Preset configurations
145+
- **`src/utils/`** - Plugin-specific utilities (e.g., `create-rule.ts`)
146+
- **`src/plugin.ts`** - Plugin definition with rule exports
147+
- **`src/index.ts`** - Entry point with flat config adapters
148+
96149
### Rule Implementation Pattern
97150

98-
Rules are created using `createRule` from `@typescript-eslint/utils`:
151+
Rules follow a consistent pattern:
152+
153+
1. Import utilities from `@eslint-react/core`, `@eslint-react/ast`, `@eslint-react/shared`, etc.
154+
2. Define rule metadata: `RULE_NAME`, `RULE_FEATURES`, `MessageID` type
155+
3. Use `createRule` from `../utils` to create the rule with TypeScript types
156+
4. Implement rule logic using collectors (e.g., `useComponentCollector`, `useHookCollector`)
157+
5. Export the rule as default
99158

159+
Example structure:
100160
```typescript
161+
import * as core from "@eslint-react/core";
101162
import { createRule } from "../utils";
102163

103164
export const RULE_NAME = "rule-name";
104165
export const RULE_FEATURES = [] as const satisfies RuleFeature[];
105166
export type MessageID = "messageId";
106167

107168
export default createRule<[], MessageID>({
108-
meta: {
109-
type: "problem",
110-
docs: { description: "..." },
111-
messages: { messageId: "Error message" },
112-
schema: [],
169+
meta: { /* ... */ },
170+
create(context) {
171+
// Rule implementation
113172
},
114-
name: RULE_NAME,
115-
create,
116-
defaultOptions: [],
117173
});
118-
119-
export function create(ctx: RuleContext<MessageID, []>): RuleListener {
120-
return {
121-
// AST visitors
122-
};
123-
}
124174
```
125175

126-
### Testing Pattern
176+
### Testing
127177

128-
Tests use the TypeScript ESLint Rule Tester with vitest:
178+
- Tests use Vitest with `@typescript-eslint/rule-tester`
179+
- Test files are co-located with source files: `rule-name.spec.ts` next to `rule-name.ts`
180+
- Shared test utilities in `test/` directory:
181+
- `test/rule-tester.ts` - Configured rule testers (with/without type checking)
182+
- `test/fixtures/` - TypeScript configuration fixtures for different JSX modes
183+
- `test/helpers.ts` - Test helper functions
184+
- Use `dedent` (imported as `tsx`) for formatting test code
185+
- Two rule testers available:
186+
- `ruleTester` - For rules without type information
187+
- `ruleTesterWithTypes` - For rules requiring TypeScript type information
129188

130-
```typescript
131-
import { ruleTester } from "../../../../../test";
132-
import rule, { RULE_NAME } from "./rule-name";
189+
### Build System
133190

134-
ruleTester.run(RULE_NAME, rule, {
135-
invalid: [{ code: "...", errors: [{ messageId: "..." }] }],
136-
valid: ["..."],
137-
});
138-
```
191+
- Uses `tsdown` for building packages (configured via `tsdown.config.ts`)
192+
- Uses `dprint` for code formatting (configured via `dprint.json`)
193+
- TypeScript configuration extends from `@local/configs/tsconfig.base.json`
194+
- All packages target Node.js 20+ and ESM format
139195

140-
Use `ruleTesterWithTypes` for type-aware rules. Import test helpers from `/test`:
196+
### Settings and Configuration
141197

142-
```typescript
143-
import { allValid, ruleTester, ruleTesterWithTypes } from "../../../../../test";
144-
```
198+
ESLint React supports custom settings via `settings["react-x"]`:
199+
200+
- `importSource` - Custom React import source (default: "react")
201+
- `polymorphicPropName` - Prop name for polymorphic components (e.g., "as")
202+
- `version` - React version (default: "detect")
203+
- `additionalStateHooks` - Regex pattern for custom state hooks
145204

146-
## Key Dependencies
205+
Access settings in rules using `coerceSettings(context.settings)` from `@eslint-react/shared`.
147206

148-
- `@typescript-eslint/*` - TypeScript ESLint integration
149-
- `effect` - Functional programming library used throughout
150-
- `ts-pattern` - Pattern matching library
151-
- `tsdown` - TypeScript bundler for building packages
207+
## Development Workflow
152208

153-
## Adding a New Rule
209+
### Adding a New Rule
154210

155211
1. Create the rule file in the appropriate plugin's `src/rules/` directory
156-
2. Create the corresponding `.spec.ts` test file
157-
3. Export the rule in the plugin's `src/plugin.ts` entry file
158-
4. Add documentation as `.mdx` file with the same name
159-
5. Update preset configurations if the rule should be enabled by default
160-
6. Update the unified plugin to include the new rule
161-
7. Run `pnpm run build` and `pnpm run test`
162-
163-
## Architecture Notes
164-
165-
- Rules use the `@eslint-react/core` package for React-specific analysis (component detection, hook analysis, JSX analysis)
166-
- The `@eslint-react/shared` package provides common types, settings, and reporting utilities
167-
- The `effect` library is used for functional programming patterns
168-
- Each plugin is independently publishable but the unified plugin (`@eslint-react/eslint-plugin`) combines them all
212+
2. Implement the rule following the pattern above
213+
3. Create the test file (`.spec.ts`) with valid and invalid test cases
214+
4. Create documentation file (`.mdx`) describing the rule
215+
5. Export the rule in `src/plugin.ts`
216+
6. Add the rule to appropriate preset configs in `src/configs/`
217+
7. If adding to a modular plugin, update the unified plugin (`packages/plugins/eslint-plugin/`)
218+
8. Run `pnpm run update:website` to sync documentation
219+
9. Run `pnpm run verify:rules-metas` to verify metadata consistency
220+
10. Run tests and build to ensure everything works
221+
222+
### Modifying Core Utilities
223+
224+
When modifying packages in `packages/core/` or `packages/utilities/`:
225+
226+
1. Make changes to the source files
227+
2. Run `pnpm run build:pkgs` if changes affect internal packages
228+
3. Run `pnpm run build:packages` to rebuild dependent packages
229+
4. Run tests to ensure no regressions
230+
5. Update TypeDoc comments if changing public APIs
231+
232+
### Working with the Website
233+
234+
The website is built from rule documentation (`.mdx` files) in plugin packages:
235+
236+
1. Edit `.mdx` files in `packages/plugins/*/src/rules/`
237+
2. Run `pnpm run update:website` to sync changes to the website
238+
3. Run `pnpm run build:website` to build the website
239+
4. Website source is in `apps/website/`
240+
241+
## Important Notes
242+
243+
- **Never use `git add -A` or `git add .`** - Always stage specific files to avoid committing sensitive data
244+
- **Test files are co-located with source files** - Keep `rule-name.spec.ts` next to `rule-name.ts`
245+
- **Use workspace dependencies** - Reference internal packages with `workspace:*` in package.json
246+
- **Follow the existing patterns** - Look at similar rules for guidance on implementation
247+
- **Type safety is critical** - All packages use strict TypeScript settings
248+
- **Performance matters** - This project emphasizes performance; avoid unnecessary AST traversals
249+
- **Use collectors for stateful analysis** - Use `useComponentCollector`, `useHookCollector` from `@eslint-react/core` for tracking components and hooks across the AST

0 commit comments

Comments
 (0)