Tips & Tricks

ESLint Configuration with Claude Code

Learn about ESLint configuration using Claude Code. Practical tips and code examples included.

Automate Code Quality With ESLint

ESLint is a static analysis tool for JavaScript/TypeScript that automatically checks code quality and style. Starting with ESLint v9, the Flat Config format makes setup much simpler. Claude Code provides solid support from designing the Flat Config to writing custom rules.

Basic Flat Config

Ask Claude Code for an optimal ESLint configuration.

> Create an ESLint Flat Config for a Next.js + TypeScript project.
> Include strict type checking, import ordering, and accessibility checks.
// eslint.config.mjs
import eslint from "@eslint/js";
import tseslint from "typescript-eslint";
import reactPlugin from "eslint-plugin-react";
import reactHooksPlugin from "eslint-plugin-react-hooks";
import jsxA11yPlugin from "eslint-plugin-jsx-a11y";
import importPlugin from "eslint-plugin-import";

export default tseslint.config(
  // Base configuration
  eslint.configs.recommended,
  ...tseslint.configs.strictTypeChecked,
  ...tseslint.configs.stylisticTypeChecked,

  // Global ignore patterns
  {
    ignores: [
      "node_modules/",
      ".next/",
      "out/",
      "dist/",
      "coverage/",
      "*.config.{js,mjs}",
    ],
  },

  // TypeScript configuration
  {
    languageOptions: {
      parserOptions: {
        project: true,
        tsconfigRootDir: import.meta.dirname,
      },
    },
  },

  // React configuration
  {
    plugins: {
      react: reactPlugin,
      "react-hooks": reactHooksPlugin,
      "jsx-a11y": jsxA11yPlugin,
    },
    rules: {
      ...reactPlugin.configs.recommended.rules,
      ...reactHooksPlugin.configs.recommended.rules,
      ...jsxA11yPlugin.configs.recommended.rules,
      "react/react-in-jsx-scope": "off",
      "react/prop-types": "off",
      "react/jsx-no-target-blank": "error",
    },
    settings: {
      react: { version: "detect" },
    },
  },

  // Import ordering
  {
    plugins: { import: importPlugin },
    rules: {
      "import/order": [
        "error",
        {
          groups: [
            "builtin",
            "external",
            "internal",
            "parent",
            "sibling",
            "index",
          ],
          "newlines-between": "always",
          alphabetize: { order: "asc", caseInsensitive: true },
        },
      ],
      "import/no-duplicates": "error",
    },
  },

  // Project-specific rules
  {
    rules: {
      "@typescript-eslint/no-unused-vars": [
        "error",
        { argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
      ],
      "@typescript-eslint/consistent-type-imports": [
        "error",
        { prefer: "type-imports" },
      ],
      "@typescript-eslint/no-misused-promises": [
        "error",
        { checksVoidReturn: { attributes: false } },
      ],
      "no-console": ["warn", { allow: ["warn", "error"] }],
    },
  }
);

Separating Configs by File Type

A pattern for applying different rules to test files or script files.

// eslint.config.mjs (continued)
export default tseslint.config(
  // ...the earlier configuration

  // Relaxed rules for test files
  {
    files: ["**/*.test.{ts,tsx}", "**/*.spec.{ts,tsx}"],
    rules: {
      "@typescript-eslint/no-unsafe-assignment": "off",
      "@typescript-eslint/no-unsafe-member-access": "off",
      "@typescript-eslint/no-explicit-any": "off",
      "no-console": "off",
    },
  },

  // Configuration files
  {
    files: ["*.config.ts", "*.config.mts"],
    rules: {
      "import/no-default-export": "off",
    },
  },

  // Page components (Next.js)
  {
    files: ["src/app/**/page.tsx", "src/app/**/layout.tsx"],
    rules: {
      "import/no-default-export": "off",
    },
  }
);

Creating Custom Rules

Ask Claude Code to create project-specific rules.

// eslint-rules/no-hardcoded-strings.ts
import { ESLintUtils } from "@typescript-eslint/utils";

const createRule = ESLintUtils.RuleCreator(
  (name) => `https://example.com/rules/${name}`
);

export const noHardcodedStrings = createRule({
  name: "no-hardcoded-strings",
  meta: {
    type: "suggestion",
    docs: {
      description: "Disallow hardcoded strings in JSX and encourage i18n usage",
    },
    messages: {
      noHardcodedString:
        "Do not use hardcoded strings directly. Use the t() function.",
    },
    schema: [],
  },
  defaultOptions: [],
  create(context) {
    return {
      JSXText(node) {
        const text = node.value.trim();
        if (text.length > 0 && !/^[\s\d\W]+$/.test(text)) {
          context.report({ node, messageId: "noHardcodedString" });
        }
      },
    };
  },
});

VS Code Integration

Settings to run ESLint automatically in VS Code.

// .vscode/settings.json
{
  "eslint.useFlatConfig": true,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit"
  },
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact"
  ],
  "eslint.rules.customizations": [
    { "rule": "no-console", "severity": "warn" },
    { "rule": "import/order", "severity": "warn" }
  ]
}

Integration With lint-staged

Only lint changed files on commit.

// package.json
{
  "lint-staged": {
    "*.{ts,tsx}": ["eslint --fix", "prettier --write"],
    "*.{json,md,yml}": ["prettier --write"]
  }
}

Summary

ESLint’s Flat Config dramatically improves config clarity. With Claude Code, you can efficiently build everything from project-optimized rule selection, to TypeScript integration, to custom rule authoring.

For code formatter configuration, see the Prettier config customization guide, and for automatic commit-time execution, see the Husky + lint-staged setup guide. Also check the official ESLint documentation.

#Claude Code #ESLint #code quality #TypeScript #development environment

Level up your Claude Code workflow

50 battle-tested prompt templates you can copy-paste into Claude Code right now.

Free

Free PDF: Claude Code Cheatsheet in 5 Minutes

Key commands, shortcuts, and prompt examples on a single printable page.

Download PDF
M

About the Author

Masa

Engineer obsessed with Claude Code. Runs claudecode-lab.com, a 10-language tech media with 2,000+ pages.