Ugrás a fő tartalomra
50% kedvezmény minden csomagra, korlátozott ideig. Már $2.48/mo
14 min left
Fejlesztői eszközök és DevOps

Hogyan állítsunk be lintert az AI által generált kódhoz

S By Sherwin 14 min read
ESLint output showing AI-specific lint violations in a TypeScript file

Az AI-ügynökök képesek olyan kódot generálni, amely lefordul.

Ez azonban még mindig nem az a mérce, amit szeretnél. A mérce az olyan kód, amely nem importál olyasmit, amit soha nem használ, nem any-cast-olja ki magát a típusrendszerből, nem hagyja figyelmen kívül a hibavisszatérési értékeket, és nem éget bele olyan hitelesítő adatokat, amelyeket a gosecnek el kellene kapnia az átnézés előtt.

Az AI-modellek régi Stack Overflow-válaszokon tanulnak, és az ott megismert mintákat szállítják, beleértve az elavult API-kat, a hiányzó típusannotációkat és azokat a függvényeket, amelyek technikailag helyesek, de túl nagyok ahhoz, hogy biztonságosan át lehessen nézni őket. Szükséged van egy linterre a folyamatban. Nem javaslatként, hanem kapuként.

Ez az útmutató három ökoszisztéma konfigurációját fedi le (Python a Ruff-fal, TypeScript/JavaScript az ESLint v10 flat configgal, és Go a golangci-linttel), kifejezetten azokra a hibamintákra hangolt szabályokkal, amelyeket az AI bevezet. Ezután bemutatja, hogyan tehető a kapu sokkal nehezebben megkerülhetővé, hogy az ügynök ne tudja egyszerűen a --no-verify kapcsolóval átugrani a helyi hookokat anélkül, hogy egy másik réteg elkapná.

A beállítás rétegzett: az IDE-szintű lintelés soron belül kapja el a problémákat, ahogy az ügynök ír, a pre-commit hookok elkapnak mindent, ami eljut egy commit-kísérletig, a CI pedig elkap mindent, ami helyileg átmegy. Minden réteg független, és kiválaszthatod a stackedre vonatkozó nyelvi szakaszokat. A betartató réteg ugyanúgy működik, függetlenül attól, melyik nyelvet linteled.

Röviden

  • A Ruff (Python), az ESLint v10 (TS/JS) és a golangci-lint (Go) mindegyikének vannak olyan szabályai, amelyek elkapják az AI leggyakoribb hibáit
  • Az alábbi konfigurációk kommentálva vannak; minden szabálynak megvan az oka
  • A Lefthook kezeli a pre-commit kaput; a Cursor afterFileEdit hookja soron belül futtatja a lintet
  • Négy betartató réteg sokkal nehezebbé teszi, hogy az AI-ügynökök a --no-verify kapcsolóval megkerüljék a kaput
  • A CI a végső védőháló: az ügynökök nem tudnak --no-verify kapcsolót átadni a GitHub Actionsnek

Hogyan konfiguráljuk a Ruffot Python AI-kódhoz

Terminal output from Ruff flagging unused imports and a missing return type annotation in AI-generated Python code

A Ruff a megfelelő Python-linter az AI-asszisztált kódbázisokhoz. Elég gyors ahhoz, hogy minden fájlmentéskor lefuthasson anélkül, hogy bármit blokkolna, lefedi mind a stílust, mind a valódi logikai hibákat, és ugyanabban a binárisban formázó viselkedést is szállít (a Black helyettesítésére). Az alábbi szabályok azokat a konkrét hibamintákat célozzák, amelyeket az AI-modellek a leggyakrabban vezetnek be Pythonban.

A Ruff telepítése

pip install ruff

# or via uv (faster for new projects):
uv add --dev ruff

Ennyi. Nincs plugin-ökoszisztéma, nincs peer-függőségi egyeztetés.

A pyproject.toml konfiguráció

[tool.ruff]
line-length = 88
target-version = "py311"

[tool.ruff.lint]
select = [
  "E",   # pycodestyle — style consistency
  "F",   # pyflakes — catches unused imports (the most common AI artifact)
  "I",   # isort — import ordering (AI frequently reorders imports incorrectly)
  "N",   # pep8-naming — naming conventions
  "UP",  # pyupgrade — flags deprecated APIs (AI trains on old Stack Overflow answers)
  "S",   # flake8-bandit — security rules: subprocess.shell=True, eval(), hardcoded creds
  "ANN", # type annotation enforcement (AI frequently omits return type annotations)
]
ignore = []  # intentional: do not add sweeping ignores in AI-assisted codebases

[tool.ruff.lint.per-file-ignores]
"tests/**" = ["S101"]  # allow assert in tests

Az F szabályok azonnal megtérülnek. Az AI-kód olyan csomagokhoz generál import utasításokat, amelyeket végül nem használ, és az F401 (nem használt import) mindegyiket elkapja. Az UP szabályok elkapják a 3.10 előtti Python-válaszokból tanult elavult API-mintákra irányuló hívásokat; az UP006 és az UP007 önmagában is tucatnyi szükségtelen típusellenőrzési mintát jelez. Az S (Bandit) szabályok elkapják a biztonsági hibákat: a hitelesítő adatoknak tűnő, beégetett szövegeket (S105/S106), a subprocess(shell=True) általi shell-injekciót (S603/S607), a gyenge kriptográfiai választásokat (S324).

Az ignore = [] szándékos. Minden kivétel, amit ehhez a listához adsz, egy olyan AI-hibaosztály, amelynek az engedélyezése mellett döntöttél.

A Ruff futtatása

ruff check .           # lint only — see what's wrong
ruff check --fix .     # auto-fix safe violations (imports, formatting)
ruff format .          # format the codebase (replaces Black)

A --fix alapértelmezetten alkalmazza a Ruff biztonságos javításait, például a nem használt importok eltávolítását vagy az egyértelmű formázási és lintelési korrekciók elvégzését. A Ruffnak vannak nem biztonságos javításai is, de ezekhez kifejezett beleegyezés szükséges, és gondosabban át kell nézni őket. Nézz át kézzel mindent, amit a Ruff nem tud biztonságosan megjavítani.

Hogyan konfiguráljuk az ESLint v10-et TypeScript és JavaScript AI-kódhoz

ESLint v10 flat config reporting no-explicit-any and max-lines-per-function violations in an AI-generated TypeScript file

Az ESLint v10 elhagyta a régi .eslintrc.* konfigurációs formátumot. Minden mostantól flat config az eslint.config.mjs fájlban. Ha olyan oktatóanyagot találsz, amely .eslintrc.json vagy .eslintrc.js fájlt használ, az az ESLint v8-at vagy v9-et célozza, ahol a szintaxis más. Használd az alábbit.

Az ebben a konfigurációban szereplő @typescript-eslint szabályok azokat a konkrét hibamódokat célozzák, amelyek ismételten felbukkannak az AI által generált TypeScriptben: az any kibúvót, a monolitikus függvényeket, amelyeket nehéz átnézni, és a beégetett értékeket, amelyeknek konstansoknak kellene lenniük.

Az ESLint v10 telepítése TypeScript-támogatással

npm install --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin

# or with pnpm:
pnpm add -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin

Az ESLint v10.5.0 az aktuális verzió 2026 júniusában. A @typescript-eslint csomagoknak illeszkedniük kell a TypeScript-verziódhoz; a kompatibilitási mátrixért nézd meg a README-t.

Az eslint.config.mjs konfiguráció

import tseslint from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';

export default [
  {
    files: ['**/*.ts', '**/*.tsx'],
    languageOptions: {
      parser: tsParser,
      parserOptions: { project: './tsconfig.json' },
    },
    plugins: { '@typescript-eslint': tseslint },
    rules: {
      // AI defaults to `any` to bypass the type system — this blocks it
      '@typescript-eslint/no-explicit-any': 'error',

      // AI generates variables it declares but never uses
      '@typescript-eslint/no-unused-vars': 'error',

      // AI writes functions that work but are too long to review safely
      'max-lines-per-function': ['error', { max: 50 }],

      // AI overloads function signatures; this forces decomposition
      'max-params': ['error', 2],

      // AI hardcodes values that should be named constants
      'no-magic-numbers': ['error', { ignore: [0, 1, -1] }],

      // AI writes files that are too large to reason about in a single review
      'max-lines': ['error', { max: 250 }],

      // AI leaves console.log debugging in production code
      'no-console': 'warn',
    },
  },
];

A max-lines-per-function: 50 szabály a legagresszívebb dolog ebben a konfigurációban. Egy AI-asszisztált kódbázisban az első futtatáskor folyamatosan bele fogsz ütközni. Ez a lényeg. Bele kell ütköznöd. Az 50 sort meghaladó függvények az elsők, amelyek lehetetlenné válnak az értelmezésre, amikor nagy mennyiségben nézel át AI-kimenetet.

A max-params: 2 szabály kikényszeríti a dekompozíciót. Az AI-modellek olyan kódbázisokon tanulnak, ahol az ötargumentumú függvények normálisak; a szabály ellenáll ennek azzal, hogy megköveteli az ügynöktől egy options objektum használatát, ami jobb tervezés és könnyebben olvasható.

Az ESLint futtatása

npx eslint .                       # lint
npx eslint . --fix                 # auto-fix safe issues
npx eslint . --max-warnings 0      # CI mode — treats warnings as errors

Használd a --max-warnings 0 kapcsolót a CI-lépésedben. Ez a no-console figyelmeztetéseket „technikailag feljegyezve" állapotból „valóban blokkoló" állapotba lépteti elő.

Opcionális: szigorúbb szabályok az AI által generált fájlokhoz

Ha a csapatod fájlelnevezési konvenciót használ az AI által generált kód jelölésére (*.ai.ts, *-generated.ts vagy hasonló), kifejezetten ezekre a fájlokra alkalmazhatsz szigorúbb szabályokat:

// Add to eslint.config.mjs after the main config object
{
  files: ['**/*.ai.ts', '**/*.ai.tsx', '**/*-generated.ts'],
  rules: {
    'max-lines': ['error', { max: 100 }],  // tighter file ceiling
    'complexity': ['error', 5],             // McCabe complexity limit
  },
}

Hogyan konfiguráljuk a golangci-lintet Go AI-kódhoz

A golangci-lint a szabványos multi-linter-futtató Go-hoz. A gosec, errcheck, staticcheck és 40+ további linter mellett érkezik, amelyek egyetlen YAML-fájlból konfigurálhatók. Az AI által generált Go-kódhoz a kritikus szabályok a hibavisszatérési értékek ellenőrzése és a biztonsági minták felismerése: ez az a két hibakategória, amelyet az AI-modellek a legkövetkezetesebben elmulasztanak Go-ban.

A golangci-lint telepítése

# Official binary installer:
curl -sSfL https://golangci-lint.run/install.sh | sh -s -- -b "$(go env GOPATH)/bin" v2.12.2

# or via Homebrew:
brew install golangci-lint

A .golangci.yml konfiguráció

version: "2"

linters:
  enable:
    - gosec        # security: flags hardcoded creds (G101), file path injection (G304), weak crypto (G401)
    - unused       # flags unused vars and functions — a common AI artifact in Go
    - errcheck     # AI frequently ignores error returns — this blocks it
    - govet        # catches subtle correctness bugs AI introduces
    - staticcheck  # comprehensive static analysis
    - revive       # style: catches non-idiomatic Go patterns AI writes
    - misspell     # AI occasionally misspells in comments and string literals

  settings:
    gosec:
      severity: medium
      confidence: medium
    errcheck:
      check-type-assertions: true  # check `val, ok := x.(Type)` patterns
      check-blank: true            # catch `_ = someErr` error suppression

run:
  timeout: 3m
  issues-exit-code: 1

A Go hibakezelési mintája tervezésénél fogva explicit: minden függvény, amely meghibásodhat, egy error értéket ad vissza. Az AI-modellek értik ezt, de alulsúlyozzák; kihagyják a hibaellenőrzéseket a nem kritikus kódutakon. Az errcheck ezt a kihagyást lintelési hibává teszi.

A gosec a biztonsági linter. Az AI-kódnál elkapja azokat a mintákat, amelyeket az AI a 2020 előtti Go-oktatóanyagokból szedett fel: a nem biztonságos véletlenszám-generálást (G404), a nem biztonságos hash-függvényeket (G401), a fájljogosultsági problémákat (G306). Ezek azok a hibák, amelyeket nem kapsz el a kódátnézés során, mert szintaktikailag normálisnak tűnnek.

A golangci-lint futtatása

golangci-lint run ./...            # lint all packages
golangci-lint run --fix ./...      # auto-fix where possible

Hogyan kössük be a lintert a pre-commit hookokba

Egy pre-commit hook minden git commit előtt lefuttatja a lintet, és blokkolja a commitot, ha a lint elbukik. Ez azt jelenti, hogy az AI-ügynök nem tud olyan kódot commitolni, amely megbukik a beállított szabályaidon. Először ki kell javítania a szabálysértéseket.

A Lefthook az ajánlott opció. Platformfüggetlen, gyors, és olyan konfigurációs mintája van, amely kifejezetten az AI-ügynökök betartatásával működik (a következő szakaszban tárgyaljuk).

Lefthook

npm install --save-dev lefthook
npx lefthook install

lefthook.yml:

pre-commit:
  parallel: true
  commands:
    lint-python:
      glob: "*.py"
      run: ruff check {staged_files} --fix
    lint-js-ts:
      glob: "*.{js,ts,tsx}"
      run: npx eslint {staged_files} --fix
    lint-go:
      glob: "*.go"
      run: golangci-lint run {staged_files}
  fail_text: |
    Lint failed. For AI Agents: fix all lint violations before committing.
    Do not use --no-verify to bypass this gate.

A fail_text üzenetet az AI-ügynökök olvassák, amikor egy commit elbukik. A mintát dokumentálja Liam Bigelow írása a Lefthook lintbetartatásáról Claude Code-hoz. Ez önmagában nem állít meg egy elszánt ügynököt, de megadja neki a helyes következő utasítást („javítsd ki a lintszabálysértéseket"), ahelyett, hogy rábíznánk egy megkerülő megoldás kitalálását.

Alternatíva: pre-commit (csak Python beállításokhoz)

Ha csak Python-stacken vagy, és a pre-commit keretrendszert részesíted előnyben:

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.15.17
    hooks:
      - id: ruff-check
        args: [--fix]
      - id: ruff-format

Cursor: soron belüli lintelés az afterFileEdit hookon keresztül

Ha Cursort használsz, azonnal kiválthatod a lintet, amikor az AI módosít egy fájlt, még mielőtt egyáltalán megkísérelne egy commitot. Hozd létre a .cursor/hooks.json fájlt a projekted gyökerében:

{
  "hooks": {
    "afterFileEdit": [
      {
        "match": "*.py",
        "run": "ruff check {file} --fix"
      },
      {
        "match": "*.{ts,tsx,js}",
        "run": "npx eslint {file} --fix"
      },
      {
        "match": "*.go",
        "run": "golangci-lint run {file}"
      }
    ]
  }
}

Ez minden alkalommal elindul, amikor a Cursor AI-ja módosít egy fájlt. Az ügynök soron belül kap lint-visszajelzést, mielőtt befejezettnek tekintené a feladatot, így a legtöbb szabálysértés kijavul, mielőtt elérné a pre-commit kaput.

Hogyan tegyük a kaput nehezebben megkerülhetővé az AI-ügynökök számára

Diagram of four enforcement layers (CLAUDE.md policy, Claude Code deny rule, PreToolUse hook, and CI backstop) blocking an AI agent from skipping the lint gate with --no-verify

Négy betartató réteg sokkal nehezebbé teszi, hogy egy AI-ügynök a --no-verify kapcsolóval átugorja a pre-commit kaput. Mindegyik más támadási felületet céloz: a CLAUDE.md-ben lévő irányelvet, egy Claude Code deny szabályt, egy PreToolUse hookot és egy CI-védőhálót. Kezeld ezeket rétegzett beállításként, ne négy független garanciaként.

Az AI-ügynökök néha átadják a --no-verify kapcsolót a git commitnak, hogy átugorják a pre-commit hookokat, amikor a lint elbukik, és az ügynök úgy döntött, hogy a hibák „nem kapcsolódnak a változtatásaihoz". A döntés nem mindig téves, de nem szabad hagynod, hogy az ügynök egyoldalúan hozza meg. A lintkapu lényege éppen az, hogy egy ember állította be az irányelvet; az ügynök dolga az, hogy teljesítse, ne pedig kikerülje.

Íme az egyes rétegek és a támadási felület, amelyet lefednek.

1. réteg: dokumentáld az irányelvet a CLAUDE.md-ben

## Linting Policy

NEVER use `git commit --no-verify`. All commits must pass pre-commit hooks.
Pre-commit hooks run lint. Fix lint violations before committing. Do not treat
lint failures as unrelated to your changes — they may not be, and you don't get
to decide that.

A Claude Code a munkamenet indításakor olvassa a CLAUDE.md-t. Ez nem betartatás; az ügynök még mindig megkísérelheti a megkerülést. De megszünteti a „nem tudtam róla" lehetőséget, és világos irányelvet állít fel, amelyet az ügynöknek aktívan kell megsértenie, ami kevésbé valószínű, mint hogy egy megkerülő megoldást találjon ki a hallgatásból.

2. réteg: Claude Code deny szabály

Add hozzá a .claude/settings.json-höz:

{
  "permissions": {
    "deny": [
      "Bash(git commit --no-verify*)"
    ]
  }
}

Ez blokkolja az explicit hívást. Egy korlátozás: a deny szabály prefixillesztést használ, így csak a commit közvetlenül utáni --no-verify-et kapja el. Egy kellően kreatív ügynök másképp strukturálhatná a hívást. Ne hagyatkozz erre egyedül.

3. réteg: PreToolUse hook

Telepítsd a block-no-verify csomagot:

npm install --save-dev block-no-verify

Majd konfiguráld PreToolUse hookként a Claude Code beállításaiban. Ez minden eszközhívás előtt elindul, és megvizsgálja az argumentumokat a --no-verify után hat git alparancson keresztül, nem csak a commitnál. Nem nullával lép ki, hogy blokkolja a hívást, mielőtt az lefutna.

A kézikönyv itt: pydevtools.com nyíltan fogalmaz erről: „a hookréteg az egyetlen, amely megbízhatóan kikényszeríti a szabályt." Használd ezt a többi réteggel együtt; ne kezelj egyetlen helyi hookot sem teljes garanciaként.

4. réteg: CI-védőháló

A CI a szerveren fut, ahol az ügynöknek nincs shellje, amelybe kapcsolókat adhatna át:

# .github/workflows/lint.yml
name: Lint
on: [push, pull_request]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Lint Python
        run: |
          pip install ruff
          ruff check . --output-format github

      - name: Lint JS/TS
        run: npx eslint . --max-warnings 0

      - name: Lint Go
        uses: golangci/golangci-lint-action@v9
        with:
          version: v2.12.2

Az AI-ügynökök nem tudnak --no-verify kapcsolót átadni a CI-nek. A GitHub Actions attól függetlenül fut, amit az ügynök helyileg tett. Ha egy commit valahogy mégis átment elbukott linttel, a CI elkapja, mielőtt összeolvadna.

Ez a végső védőháló.

Bónusz: ESLint MCP szerver

Ha Claude Code-ot használsz, van egy proaktív réteg, amely csökkenti, hogy egyáltalán milyen gyakran ütközöl bele a kapuba.

Az ESLint MCP szerver (@eslint/mcp) közvetlenül az ügynök eszközhurkába integrálja az ESLintet. Az ügynök a feladat során, még a commit megkísérlése előtt lekérdezheti az ESLintet. Telepítsd globálisan:

npm install -g @eslint/mcp@latest

Add hozzá a .claude/settings.json-höz:

{
  "mcpServers": {
    "eslint": {
      "command": "npx",
      "args": ["@eslint/mcp@latest"]
    }
  }
}

Ezzel a beállítással az ügynök a feladat során lekérdezheti az ESLintet. Az ügynök soron belül kap lint-visszajelzést, és néhány szabálysértés kijavítható, mielőtt elérnék a hookot. Ez nem helyettesíti a kaput, hanem csökkenti a kapun a zajt.

Gyakran ismételt kérdések

Mind a három lintert konfigurálnom kell, ha csak egy nyelven dolgozom?

Nem. Állítsd be a lintert az elsődleges nyelvedhez és a betartató réteget. Ha a stacked csak TypeScript, konfiguráld az ESLintet, és hagyd ki a Ruffot és a golangci-lintet. Az ügynök-megkerülés megelőzéséről szóló szakasz attól függetlenül érvényes, hogy melyik nyelvet linteled.

Tönkreteszik ezek a konfigurációk a meglévő kódbázisomat az első futtatáskor?

Szinte biztosan, és szándékosan. Futtasd a ruff check --fix . vagy az npx eslint . --fix parancsot, hogy először automatikusan kijavítsd a biztonságos szabálysértéseket. Ami az automatikus javítás után marad, az a kézi átnézési lista: a no-explicit-any cast-ok, az 50 sort meghaladó függvények, a hiányzó hibakezelés. Dolgozd át ezeket fokozatosan. Ne adj hozzá ignore szabályokat, hogy elkerüld a velük való foglalkozást.

A Biome jelenleg az ESLint helyettesítője?

A Biome v2.5.0 (2026 júniusában jelent meg) versenyképes a formázás és az alapvető lintszabályok terén. Gyorsabb az ESLintnél, és nulla konfigurációs ráfordítással jár, ha a bun x ultracite@latest init paranccsal telepíted. Az olyan csapatok számára, amelyek egyetlen eszközt szeretnének, és nincs szükségük a teljes @typescript-eslint szabálymélységre, a Biome ésszerű választás. Az ebben az útmutatóban szereplő AI-specifikus szabályokhoz (max-params, no-magic-numbers, max-lines-per-function AI-célzott küszöbértékekkel) az ESLint a @typescript-eslinttel még mindig nagyobb lefedettséggel rendelkezik. Mindkettőt futtathatod: a Biome-ot a formázáshoz és az alapvető linteléshez, az ESLintet az AI-specifikus szabályokhoz.

Mi van, ha az AI-ügynököm folyamatosan újragenerálja ugyanazokat a lintszabálysértéseket?

Az ügynök megkerüli a szabályt ahelyett, hogy kijavítaná a mögöttes problémát. A no-explicit-any esetén ez azt jelenti, hogy egy típusállítást ad hozzá ahelyett, hogy meghatározná a tényleges típust. A max-lines-per-function esetén azt jelenti, hogy kiemel egy segédfüggvényt, amely semmi hasznosat nem csinál, de a sorszámot a küszöb alá viszi. Egyik megoldás sem megy át a kódátnézésen. A lintszabály elkapta a tünetet; a gyökérok az ügynök promptja. Finomítsd a promptot, hogy meghatározza a típuskorlátozást vagy az elvárt dekompozíciót; az ügynök megbízhatóbban követi az explicit struktúrairányítást, mint az implicit szabályokat. Ha bonyolultabb ügynökbeállítást futtatsz, a munka egy dedikált al-ügynökre szűkítése, amelynek az utasításaiba bele van sütve a korlátozás, általában jobban tart, mint egyetlen széles prompt.

Az ESLint MCP szerver helyettesíti a pre-commit kaput?

Nem. Csökkenti, hogy milyen gyakran generál az ügynök olyan kódot, amely megbukik a kapun. A kapu továbbra is minden commitnál lefut. Az MCP szerver soron belüli ellenőrzése és a pre-commit hook betartatása egymást kiegészítik, ezért egyiket se távolítsd el.

Share

Több a blogról

Folytassa az olvasást.

Készen áll a telepítésre? Már 2,48 $/hó-tól.

Független felhő 2008 óta. AMD EPYC, NVMe, 40 Gbps. 14 napos pénzvisszafizetési garancia.