AI slop a kód: Proč linter a formatter potřebujete víc než kdy dřív
Pokud vám nevadí platit vývojáře za čekání na terminál, platit CI minuty za pipeline, která běží o půl hodiny déle, než musí, a platit tokeny za to, že AI agent opravuje stejné chyby potřetí, tak tenhle článek nečtěte. Nic vám v něm nechybí. Peníze a čas jsou vám očividně šumák.
Všichni ostatní, pokračujte.
AI vám dnes napíše komponentu za minutu. Třeba i dvacet komponent za pět minut. Funguje to, testy projdou, všichni jsou spokojení. Pak otevřete pull request a vidíte, že jedna komponenta používá interface, druhá type, třetí má console.log zapomenutý uprostřed a čtvrtá importuje stejnou knihovnu třemi různými způsoby.
Žádná z těch věcí není chyba. Kód běží. Jenže codebase, ve které každý soubor vypadá, jako by ho psal někdo jiný, se špatně čte, špatně reviewuje a špatně udržuje. Té záplavě „nějak to funguje, ale nikdo to nesjednotil" se dnes říká AI slop. A každá hodina, kterou strávíte jeho úklidem, je hodina, kterou platíte.
Dobrá zpráva: dá se tomu předejít skoro zadarmo. Špatná zpráva: pokud to děláte pomalými nástroji, předejdete tomu jen napůl, protože je budete obcházet.
A důležitá věc na úvod: není to problém jen AI.
Není to jen o AI, jenom je to vidět víc
Už v článku o pravidlu Interface vs. Type jsem psal o tom, co se stane, když se tým rozroste. Deset vývojářů, deset trochu jiných zvyklostí. Někdo je zvyklý na interface z Javy, někdo míchá oba přístupy a code review se promění v diskusi o mezerách místo o architektuře.
AI agent je v podstatě dalších deset vývojářů, kteří se nikdy nepotkali. Nezná vaše „nepsané pravidlo". Každá session začíná od nuly, model má naučené tisíce různých stylů a vybere si ten, který se mu zrovna hodí. A navíc píše rychleji než kdokoli z nás, takže nekonzistence rostou rychleji, než je stihne kdokoli zachytit.
Odpověď je stejná jako dřív, jen s vyšší naléhavostí: pravidla musí hlídat stroj, ne lidská paměť.
Pravidlo v promptu je prosba, pravidlo v linteru je zákon
Dá se samozřejmě napsat do AGENTS.md nebo do systémového promptu: „Používej type místo interface, nepoužívej any, nenechávej console.log." Často to funguje. Ale je to jen prosba. Model na ni zapomene, jakmile se kontext zaplní, nebo si ji vyloží po svém.
Lint pravidlo funguje jinak. Buď projde, nebo neprojde. Nediskutuje se.
Moderní AI agenti navíc pracují ve smyčce:
- napíšou kód,
- spustí kontroly (testy, typy, lint),
- přečtou chyby,
- opraví je a jedou znovu.
Linter a formatter jsou přesně ta zpětná vazba, kterou tahle smyčka potřebuje. Agent se nemusí domýšlet, co máte rádi. Spustí jeden příkaz a dostane konkrétní odpověď: tady řádek 42, tohle pravidlo, tohle se nesmí.
Formatter navíc eliminuje celou kategorii šumu. Agent (ani člověk) nemusí řešit uvozovky, odsazení nebo čárky. Diff v pull requestu obsahuje jen skutečné změny a reviewer se soustředí na to, co dělá kód, ne na to, jak vypadá.
Krátká historie: ESLint a Prettier
ESLint vznikl v roce 2013 a Prettier v roce 2017. Změnily JavaScript svět. ESLint hlídal kvalitu kódu (nepoužité proměnné, nebezpečné konstrukce, vlastní týmová pravidla), Prettier odstranil věčné spory o formátování tím, že rozhodl za všechny.
Dvojice ESLint + Prettier se stala standardem a po deset let fungovala skvěle. Mělo to ale jednu vlastnost, se kterou jsme se naučili žít: oba nástroje jsou napsané v JavaScriptu a běží v Node.js. Na malém projektu to nikdo nevnímá. Na velké codebase s TypeScriptem a type-aware pravidly se z lintu stane něco, co pouštíte „až na konec", protože trvá minuty.
Rust změnil pravidla hry
Pak přišel projekt Oxc a s ním Oxlint (2023) a později Oxfmt. Obojí je napsané v Rustu, běží nativně a využívá všechna jádra procesoru.
Rozdíl v rychlosti není kosmetický. Jeden vývojář na Redditu popsal migraci svého firemního projektu (M3 MacBook Pro, medián ze tří běhů, přes 6 000 souborů):
- ESLint (single-thread, type-aware pravidla): ~2 min 27 s
- Oxlint (5 360 souborů, 134 pravidel, 11 vláken): ~1,3 s
- Prettier: ~13,9 s
- Oxfmt: ~2,1 s
Pozor, je to jeden konkrétní projekt s jednou konkrétní konfigurací a váš výsledek se bude lišit. Oficiální čísla z dokumentace Oxc jsou střízlivější: Oxfmt je zhruba 30× rychlejší než Prettier. Ale řád je všude stejný. Mluvíme o desítkách a stovkách násobků, ne o desítkách procent.
A tady je důležité, co se za poslední rok změnilo:
- Oxfmt je od února 2026 v betě a prochází 100 % konformitních testů Prettieru pro JavaScript a TypeScript. Zbylé rozdíly jsou známé chyby samotného Prettieru. Výstup se tedy neliší, jen je rychlejší.
- Type-aware linting je od července 2026 stabilní. Dělá ho
tsgolintpostavený na nativním TypeScriptu 7 a pokrývá 59 z 61 type-aware pravidel z typescript-eslint. To byla dlouho největší výmluva, proč zůstat u ESLintu. - Oxlint dnes podporuje přes 800 pravidel z ESLint core a populárních pluginů (React, jsx-a11y, import, unicorn...) a umí spouštět i JS pluginy.
Rychlost jsou peníze
Říkám to vždycky, i když to zní trochu suše: rychlost nástrojů je business argument.
Spočítejme si to na jednoduchém, ilustračním příkladu. Tým deseti vývojářů, každý spustí kontroly desetkrát denně (před commitem, před pushem, při opravách po CI). Při dvou a půl minutě čekání na jeden běh to dělá 10 × 10 × 2,5 min, tedy zhruba 4 hodiny denně a asi 80 hodin měsíčně strávených pohledem na terminál. S Oxlintem (1,3 s na běh) je to dohromady necelé dvě minuty denně.
A to jsme nezapočítali:
- CI/CD pipeline. Každá minuta v pipeline se platí (runnery) i čeká (vývojář). Rychlejší lint znamená rychlejší zpětnou vazbu na pull requestu a rychlejší release.
- Pre-commit hooky. Hook, který trvá 40 sekund, lidé začnou obcházet přes
--no-verify. Hook, který trvá sekundu, nikdo nevypíná. - Doručování. Rychlejší cyklus znamená, že klientům dříve doručíme featuru i opravu chyby. To je to, na co se zákazník ptá.
Kde do toho zapadá AI
Tady se ta rychlost násobí. Vývojář spustí lint párkrát za den. AI agent ho pouští po každé iteraci, tedy klidně dvacetkrát za jeden úkol.
Pokud každý běh trvá dvě minuty, agent buď čeká (a vy čekáte s ním, případně platíte minuty běhu cloudového agenta), nebo, a to je horší, kontrolu začne přeskakovat. Pomalá zpětná vazba vede k tomu, že agent udělá víc práce naslepo a pak opravuje víc věcí najednou.
Co se týče tokenů, buďme přesní: samotné čekání tokeny nepálí. Pálí je počet iterací a velikost kontextu. Když agent dostane rychlou a přesnou zpětnou vazbu hned po každé změně, opraví chybu, dokud je malá. Když ji dostane až na konci, musí znovu číst větší kus kódu, rozplétat souvislosti a opravovat i věci, které mezitím postavil na špatném základu. Podle toho, jaký model používáte, to může být znát i na faktuře.
Výsledek: rychlý linter je pro AI agenta to, co rychlé testy pro člověka. Dokud trvají vteřiny, používá se. Jakmile trvají minuty, začne se kolem nich chodit.
Jak to máme nastavené my
Nezůstaňme jen u teorie. Tenhle web běží na Oxlintu a Oxfmt. Konfigurace linteru vypadá takhle:
import { defineConfig } from 'oxlint';
export default defineConfig({
plugins: ['import', 'unicorn', 'react', 'typescript', 'jsx-a11y'],
categories: {
correctness: 'warn',
},
rules: {
'eslint/no-console': ['error', { allow: ['warn', 'error'] }],
'@typescript-eslint/consistent-type-definitions': ['error', 'type'],
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-unused-vars': 'error',
},
});
Všimněte si prostředního řádku. Pravidlo consistent-type-definitions, kvůli kterému jsem kdysi psal vlastní ESLint plugin, je dnes jeden řádek konfigurace a běží v Oxlintu nativně. Stejně tak pravidla pro přístupnost (jsx-a11y), která si AI ráda vynechá.
A abychom nemuseli myslet na tři příkazy, máme jeden v package.json:
{
"scripts": {
"lint": "oxlint",
"fmt": "oxfmt",
"cq": "oxlint && oxfmt --check && tsc --noEmit"
}
}
cq (code quality) pouští lint, kontrolu formátu a typy. Stejný příkaz běží v CI. Stejný příkaz říkáme agentovi. Do instrukcí pro agenty (AGENTS.md, CLAUDE.md, rules) stačí jedna věta:
Než práci označíš za hotovou, spusť `pnpm run cq` a oprav všechna zjištění.
Tím se z „doporučení" stává brána, kterou kód musí projít, ať ho psal člověk, nebo model.
Není to ještě 100 % (a stejně bych nesáhl po ničem jiném)
Nechci tu psát reklamu, takže na rovinu: Oxlint a Oxfmt ještě nejsou 100% náhrada za ESLint a Prettier. Pár věcí, na které narazíte:
- Ne každé pravidlo existuje. Oxlint pokrývá přes 800 pravidel, ale nějaké speciální pravidlo z ESLint pluginu, na kterém závisíte, může chybět.
- Vlastní ESLint pluginy. Lokální pluginy se nemigrují automaticky, ale dají se ručně přidat do konfigurace přes
jsPlugins. Oxlint umí většinu ESLint v9 API, ne úplně všechno. - Prettier pluginy a méně obvyklé formáty. Oxfmt je v betě a podpora Prettier pluginů se teprve dotahuje. Pokud závisíte na přesném chování konkrétního pluginu, ověřte si to předem.
- Type-aware linting vyžaduje TypeScript 7. Na starší verzi je to jeden krok navíc.
Co s tím? Můj postoj je jednoduchý: dokud nepřijde něco lepšího, nesáhl bych po ničem jiném než po Oxlintu a Oxfmt. Ne proto, že jsou dokonalé, ale proto, že rozdíl v rychlosti je tak velký, že pár chybějících pravidel nebo drobných odchylek jde vyřešit, kdežto pomalý nástroj v pipeline nevyřešíte nikdy. Vývoj jde navíc rychle dopředu: Oxfmt prošel za pár měsíců od alfy k betě s plnou kompatibilitou na JS a TS a type-aware linting je stabilní.
Pokud vám opravdu nějaké pravidlo chybí, jde to přemostit tím, že Oxlint pustíte první a ESLint necháte jen pro to, co zbývá (oxlint && eslint, plugin eslint-plugin-oxlint vypne duplicity). Berte to ale jako dočasnou lávku, ne jako cílový stav.
Jak začít (za odpoledne)
Migrace je dnes překvapivě bezbolestná.
Linter:
pnpm add -D oxlint
npx @oxlint/migrate
Formatter:
pnpm add -D oxfmt@latest
pnpm oxfmt --migrate=prettier
pnpm oxfmt
Hromadné přeformátování nechte jako samostatný commit a přidejte jeho hash do .git-blame-ignore-revs, aby git blame nepoukazoval na „kdo přeformátoval celý projekt". Potom aktualizujte CI a pre-commit hooky a nakonec napište příkaz do instrukcí pro AI agenty.
Závěr
Ve světě, kde kód z velké části píše model, není konzistence luxus. Je to jediná věc, která udrží codebase čitelnou pro lidi i pro další AI agenty, kteří po vás přijdou.
Pravidla musí být automatická (nechceme na ně pořád myslet), vynucená (žádné „příště si dám pozor") a rychlá (jinak se jim všichni vyhnou). ESLint a Prettier nás tomu naučili. Oxlint a Oxfmt to dotáhly do stavu, kdy kontrola trvá vteřinu, ne minuty. A to se vyplatí, ať už platíte za čas vývojářů, za CI minuty, nebo za tokeny.
Pokud je váš lint dnes ten krok, který pouštíte „až na konec", zkuste ho přepnout. Stačí odpoledne. A pak se mi ozvěte, kolik sekund vám zbylo.