Skip to content
Back to skills

Lint New

ASecurity

Create a new ESLint rule with tests for eslintPluginScraps. Use when asked to "create a lint rule", "add an eslint rule", "scaffold a rule", "write a new scraps rule", or "new design system lint rule". Covers rule creation, test authoring, registration, and autofix implementation.

  • 44,888 stars
  • 0 votes
  • 0 copies
  • 6 views
  • Added June 12, 2026
devopstypescriptgobashnodeexpressapi

Works with

  • api

Security analysis

A100/100

Pro scans all 4 files and shows the line behind each finding

Scanned September 20, 2026

npx -y skills add getsentry/sentry --skill lint-new --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Lint New?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Lint New
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/getsentry-lint-new/badge)](https://www.skillsdirectory.com/skills/getsentry-lint-new)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: lint-new
description: Create a new ESLint rule with tests for eslintPluginScraps. Use when asked to "create a lint rule", "add an eslint rule", "scaffold a rule", "write a new scraps rule", or "new design system lint rule". Covers rule creation, test authoring, registration, and autofix implementation.
---

Create a new ESLint rule named `$ARGUMENTS` in the eslintPluginScraps plugin.

## Step 1: Choose Your Archetype

Read [references/rule-archetypes.md](references/rule-archetypes.md) and pick the archetype that matches your rule's intent:

| You want to...                              | Archetype              | Reference to load                                                |
| ------------------------------------------- | ---------------------- | ---------------------------------------------------------------- |
| Rewrite import paths                        | Import rewrite         | Inline — simple pattern                                          |
| Validate token/value usage per CSS property | Property validation    | [style-collector-guide.md](references/style-collector-guide.md)  |
| Restrict JSX elements in specific props     | JSX structural         | [rule-archetypes.md](references/rule-archetypes.md) §Archetype 3 |
| Detect patterns in static CSS text          | Template text analysis | [rule-archetypes.md](references/rule-archetypes.md) §Archetype 4 |

Read the relevant reference before writing code. The archetypes document which AST visitors to use, which shared utilities apply, and which patterns are NOT appropriate for each approach.

## Step 2: Check Shared Utilities

Before writing AST traversal logic, check `static/oxlint/eslintPluginScraps/src/ast/` for reusable code:

| Utility                 | Location                                 | Use for                                                             |
| ----------------------- | ---------------------------------------- | ------------------------------------------------------------------- |
| `getStyledCallInfo`     | `src/ast/utils/styled.ts`                | Classifying styled/css calls as element, component, or css          |
| `createQuasiScanner`    | `src/ast/scanner/index.ts`               | Scanning static CSS text in template literals (Archetype 4)         |
| `createImportTracker`   | `src/ast/tracker/imports.ts`             | Resolving where a local name was imported from                      |
| `createStyleCollector`  | `src/ast/extractor/index.ts`             | Collecting CSS-in-JS _dynamic value_ declarations (NOT static text) |
| `shouldAnalyze`         | `src/ast/extractor/index.ts`             | Fast pre-scan to skip files without Emotion usage                   |
| `normalizePropertyName` | `src/ast/utils/normalizePropertyName.ts` | Normalizing CSS property names                                      |
| `decomposeValue`        | `src/ast/extractor/value-decomposer.ts`  | Breaking complex expressions into all possible values               |
| Theme tracker           | `src/ast/tracker/theme.ts`               | Tracking `useTheme()` and callback theme bindings                   |

If another rule already solves a similar problem, extract shared logic into `src/ast/utils/` and reuse it.

## Step 3: Create Files

1. **Rule**: `static/oxlint/eslintPluginScraps/src/rules/$ARGUMENTS.ts`
2. **Test**: `static/oxlint/eslintPluginScraps/src/rules/$ARGUMENTS.spec.ts`

### Rule Template

```typescript
import {ESLintUtils} from '@typescript-eslint/utils';

export const $RULE_NAME = ESLintUtils.RuleCreator.withoutDocs({
  meta: {
    type: 'problem',
    docs: {
      description: '[Rule description]',
    },
    fixable: 'code', // include if rule has autofix — see Autofix Guidance
    schema: [],
    messages: {
      forbidden: 'Error message shown to user',
    },
  },
  create(context) {
    return {
      // AST visitor methods — see your chosen archetype
    };
  },
});
```

If your rule needs configurable options, load [references/schema-patterns.md](references/schema-patterns.md).

### Test Template

```typescript
import {RuleTester} from '@typescript-eslint/rule-tester';

import {$RULE_NAME} from './$ARGUMENTS';

const ruleTester = new RuleTester();

ruleTester.run('$ARGUMENTS', $RULE_NAME, {
  valid: [
    {
      code: '// valid code',
      filename: '/project/src/file.tsx',
    },
  ],
  invalid: [
    {
      code: '// invalid code',
      filename: '/project/src/file.tsx',
      errors: [{messageId: 'forbidden'}],
      output: '// expected output after autofix', // REQUIRED for fixable rules
    },
  ],
});
```

Run tests:

```bash
pnpm test-ci "static/oxlint/eslintPluginScraps/src/rules/$ARGUMENTS.spec.ts"
```

## Autofix Guidance

**Default stance: implement autofix** unless the transformation is ambiguous or could change runtime behavior.

### Safe autofix patterns

- Import path rewrites (see `no-core-import.ts` as canonical example)
- Adding/removing JSX attributes with known values
- Wrapping expressions in a known component
- Identifier renames with no shadowing risk

### Do NOT autofix when

- Multiple valid fixes exist and the right choice requires human judgment
- The fix requires type information not available from the AST alone
- The transformation alters control flow or runtime behavior
- The change spans multiple files

### Fixer API

```typescript
context.report({
  node,
  messageId: 'forbidden',
  fix(fixer) {
    return fixer.replaceText(node, newText);
    // Also: fixer.replaceTextRange([start, end], text)
    //        fixer.insertTextBefore(node, text)
    //        fixer.insertTextAfter(node, text)
    //        fixer.remove(node)
    // Return single fix or array of fixes
  },
});
```

When a rule is fixable, every invalid test case MUST include `output` showing the expected code after the fix.

## Step 4: Register the Rule

### 1. Rule Index

Add to `static/oxlint/eslintPluginScraps/src/rules/index.ts`:

```typescript
import {$RULE_NAME} from './$ARGUMENTS';

export const rules = {
  // existing rules...
  $ARGUMENTS: $RULE_NAME,
};
```

### 2. ESLint Config

Add to `eslint.config.ts` inside the `name: 'plugin/@sentry/scraps'` block:

```typescript
'@sentry/scraps/$ARGUMENTS': 'error',
// or with options:
'@sentry/scraps/$ARGUMENTS': ['error', { /* options */ }],
```

### 3. Verify

```bash
pnpm test-ci "static/oxlint/eslintPluginScraps/src/rules/$ARGUMENTS.spec.ts"
```

## Extending an Existing Rule

If modifying an existing rule rather than creating a new one:

1. Read the existing rule and its config files to understand the architecture
2. For **config-driven rules** (like `use-semantic-token`): changes often only require editing the config file (e.g., `src/config/tokenRules.ts`), not the rule logic
3. Watch for reverse-mapping side effects — adding a new category can change which category is _suggested_ for shared properties (last writer wins in `buildPropertyToRule`)
4. Update existing tests for any changed behavior, then add new test cases

## Naming Convention

- **Rule name** (kebab-case): `my-rule-name` — verb-noun pattern (e.g., `no-token-import`, `use-semantic-token`)
- **Export name** (camelCase): `myRuleName`
- **File name**: matches rule name exactly (`my-rule-name.ts`, `my-rule-name.spec.ts`)

Files in this skill

  • SKILL.md7.1 KB
  • references/rule-archetypes.md7 KB
  • references/schema-patterns.md3.6 KB
  • references/style-collector-guide.md3.6 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.