The Craftsman standard for linting and static quality gates — ESLint version policy, resolved-rule extraction, typed TypeScript linting, React/Next/a11y/security rule hardening, zero-warning CI gates, pre-commit alignment, and migration from weak default configs to an enterprise-grade lint setup. Use this WHENEVER the work touches ESLint, lint rules, lint failures, lint config migration, quality scripts, pre-commit linting, or "standardize linting". Scope is **JS/TS ESLint surfaces** — with no ESLint surface (Python/Ruff, Biome-only, Go), mark the domain N-A rather than forcing a migration. Whole-project readiness → craft-audit.
This skill owns linting as a first-class code-quality surface for JS/TS ESLint. Version choice
matters, but the real standard is the resolved rule contract: typed linting, runtime-risk rules as
errors, context-specific React/Next/a11y/security rules, and a zero-warning gate that developers and
CI both run.
Applicability. If discovery finds no JS/TS ESLint surface — e.g. Python-only with Ruff,
Biome-only (no ESLint), Go with golangci-lint, Rust with clippy — mark the domain N-A or
partial with a one-line reason (what linter is present). Do not demand ESLint 10 flat config
on a non-ESLint stack. This skill does not expand into a multi-linter catalog; honest N-A is correct.
Operating principle — discover before you build
Do not judge a lint setup from config prose alone. First confirm ESLint is in scope (see
applicability). Then fetch the resolved ESLint rules for real source files with
eslint --print-config wherever possible, and compare those resolved rules against the standard for
that project's context.
If --print-config fails, record the failure and fall back to direct config-file inspection. A failed
resolved-config extraction is itself a finding: the team cannot reliably reason about what linting is
actually enforcing.
Identify ESLint major/version and plugin versions.
Extract resolved rules
Prefer the helper script in scripts/eslint-rule-audit.mjs.
Run it against the target repo. The plugin is installed outside the project, so always address
the script through ${CLAUDE_PLUGIN_ROOT} rather than a relative or guessed path:
Compare each resolved package to the context-appropriate preset, not a blind universal list.
Separate "not applicable" from "missing." A backend package does not need jsx-a11y; a UI app does.
Recommend or implement
If the user asks for an audit: write findings with evidence, risk, and an ordered migration plan.
If the user asks to fix: implement the smallest config/package/script changes that move the repo
toward the standard without destabilizing unrelated surfaces.
Prefer ESLint 10 flat config for active JS/TS projects. Keep ESLint 8 only as a temporary
exception when a concrete dependency blocker appears. Do not target ESLint 9 as the standard.
Verify
Run eslint --print-config <representative-file> after changes.
Run the repo lint command with --max-warnings 0 where feasible.
Run typecheck if typed linting was added.
Record any blocked verification exactly.
What Good Looks Like
Version & config policy (ESLint 10 flat config, migration sequence, when ESLint 8 is an acceptable exception) → references/standard.md § Version Policy, § Migration Sequence
Context presets — which packages get which rule sets (base, typechecked TS, node, React, Next, a11y, security, tests, architecture) → references/standard.md § Presets
The rule contract — which rules must be errors vs. acceptable warnings, by context (base, TypeScript typechecked, React/Next/UI, security/architecture, tests) → references/standard.md § Required Rule Contract
Known anti-patterns to flag on sight (stale .eslintignore, next lint as the only gate, permanent warnings on risk rules, formatter/linter conflicts) → references/standard.md § Anti-Patterns
Reference index
references/standard.md — version policy, context presets, rule contract, migration sequence.
Audit checklist (for craft-audit)
When craft-audit plans a linting pass for a scope, it turns this checklist into the
plan.md todo list — the checklist is owned by this skill, not improvised by the orchestrator. Tailor
to what discovery found: skip a step that genuinely doesn't apply with a one-line reason; never
silently drop one. Emit findings using craft-audit workspace.md → "Canonical findings.md emission
format" (authority). Heading grammar (variables required — do not hardcode NNN/severity/status):
## <scopeLabel>-LINT-<NNN> · severity <🔴|🟡|🟢> · status <open|fixed|wontfix (reason)|regressed|fixed (merged into <ID>)>
Example only: ## <scopeLabel>-LINT-001 · severity 🔴 · status open
Required fields under each heading, in order, with these exact labels:
**What breaks (plain language):** · **Technical:** · **Fix:** · **Fingerprint:** ·
**Last-checked:** (optional **Confidence:** — verified | inferred | unverified-from-repo, absent
means verified — then optional **Fix-attempt:** only from craft-fix).
Assign sequential NNN per (scope, domain); judge severity with craft-audit prioritization.md.
Forbidden: ### headings; ## ID · 🔴 · open shorthand; severity/status as body bullets.
Applicability first: if no JS/TS ESLint surface (Python/Ruff, Biome-only, Go, etc.), mark
domain N-A or partial with a one-line reason and stop — do not force ESLint 10. → SKILL.md
Applicability
Inventory ESLint/package/plugin versions, config files, lint scripts, formatter config, TS strictness, CI lint gates, and pre-commit/lint-staged setup. → references/standard.md § Version Policy
Run resolved-rule extraction with scripts/eslint-rule-audit.mjs or document why it cannot run. → scripts/eslint-rule-audit.mjs
Flag syntax-only TypeScript linting as insufficient for production TypeScript. → references/standard.md § Required Rule Contract (TypeScript Typechecked)
Flag next lint, missing config, build-skipped linting, warnings-as-steady-state, stale .eslintignore, and unused-disable comments that do not fail. → references/standard.md § Anti-Patterns
Identify rules currently warn/off/missing that should be errors for runtime quality. → references/standard.md § Required Rule Contract
Propose the smallest migration to ESLint 10 flat config, with ESLint 8 exception only for named blockers. → references/standard.md § Migration Sequence
Verify with --print-config, lint, and typecheck where feasible. → scripts/eslint-rule-audit.mjs
1---2name: craft-lint3description: The Craftsman standard for linting and static quality gates — ESLint version policy, resolved-rule extraction, typed TypeScript linting, React/Next/a11y/security rule hardening, zero-warning CI gates, pre-commit alignment, and migration from weak default configs to an enterprise-grade lint setup. Use this WHENEVER the work touches ESLint, lint rules, lint failures, lint config migration, quality scripts, pre-commit linting, or "standardize linting". Scope is **JS/TS ESLint surfaces** — with no ESLint surface (Python/Ruff, Biome-only, Go), mark the domain N-A rather than forcing a migration. Whole-project readiness → craft-audit.4---56# Lint Craft78This skill owns linting as a first-class code-quality surface **for JS/TS ESLint**. Version choice9matters, but the real standard is the resolved rule contract: typed linting, runtime-risk rules as10errors, context-specific React/Next/a11y/security rules, and a zero-warning gate that developers and11CI both run.1213**Applicability.** If discovery finds **no JS/TS ESLint surface** — e.g. Python-only with Ruff,14Biome-only (no ESLint), Go with `golangci-lint`, Rust with clippy — mark the domain **N-A** or15**partial** with a one-line reason (what linter *is* present). Do **not** demand ESLint 10 flat config16on a non-ESLint stack. This skill does not expand into a multi-linter catalog; honest N-A is correct.1718## Operating principle — discover before you build1920Do not judge a lint setup from config prose alone. First confirm ESLint is in scope (see21applicability). Then fetch the **resolved ESLint rules** for real source files with22`eslint --print-config` wherever possible, and compare those resolved rules against the standard for23that project's context.2425If `--print-config` fails, record the failure and fall back to direct config-file inspection. A failed26resolved-config extraction is itself a finding: the team cannot reliably reason about what linting is27actually enforcing.2829## Workflow30311. **Discover**32 - Read package manager files, `package.json`, ESLint configs, TS configs, formatter configs, CI,33 husky/lint-staged, and workspace layout.34 - Identify project contexts: TypeScript library, Node/API/worker, Next app, React UI, JS-only app,35 docs/content-only package.36 - Identify ESLint major/version and plugin versions.37382. **Extract resolved rules**39 - Prefer the helper script in `scripts/eslint-rule-audit.mjs`.40 - Run it against the target repo. The plugin is installed outside the project, so always address41 the script through `${CLAUDE_PLUGIN_ROOT}` rather than a relative or guessed path:4243 ```bash44 node "${CLAUDE_PLUGIN_ROOT}/skills/craft-lint/scripts/eslint-rule-audit.mjs" /absolute/path/to/target-repo45 ```4647 - The script writes evidence under the target repo:48 - `.craftsman/lint-audit/resolved-print-config-results.json`49 - `.craftsman/lint-audit/resolved-print-config-summary.json`50 - `.craftsman/lint-audit/standard-rule-gap-matrix.json`51 - `.craftsman/lint-audit/standard-rule-gap-matrix.md`52 - `.craftsman/lint-audit/top-project-gap-summary.json`53543. **Compare to the standard**55 - Read `references/standard.md`.56 - Compare each resolved package to the context-appropriate preset, not a blind universal list.57 - Separate "not applicable" from "missing." A backend package does not need jsx-a11y; a UI app does.58594. **Recommend or implement**60 - If the user asks for an audit: write findings with evidence, risk, and an ordered migration plan.61 - If the user asks to fix: implement the smallest config/package/script changes that move the repo62 toward the standard without destabilizing unrelated surfaces.63 - Prefer ESLint 10 flat config for active JS/TS projects. Keep ESLint 8 only as a temporary64 exception when a concrete dependency blocker appears. Do not target ESLint 9 as the standard.65665. **Verify**67 - Run `eslint --print-config <representative-file>` after changes.68 - Run the repo lint command with `--max-warnings 0` where feasible.69 - Run typecheck if typed linting was added.70 - Record any blocked verification exactly.7172## What Good Looks Like7374- Version & config policy (ESLint 10 flat config, migration sequence, when ESLint 8 is an acceptable exception) → `references/standard.md` § Version Policy, § Migration Sequence75- Context presets — which packages get which rule sets (base, typechecked TS, node, React, Next, a11y, security, tests, architecture) → `references/standard.md` § Presets76- The rule contract — which rules must be errors vs. acceptable warnings, by context (base, TypeScript typechecked, React/Next/UI, security/architecture, tests) → `references/standard.md` § Required Rule Contract77- Known anti-patterns to flag on sight (stale `.eslintignore`, `next lint` as the only gate, permanent warnings on risk rules, formatter/linter conflicts) → `references/standard.md` § Anti-Patterns7879## Reference index8081- `references/standard.md` — version policy, context presets, rule contract, migration sequence.8283## Audit checklist (for craft-audit)8485When `craft-audit` plans a linting pass for a scope, it turns this checklist into the86`plan.md` todo list — the checklist is owned by this skill, not improvised by the orchestrator. Tailor87to what discovery found: skip a step that genuinely doesn't apply with a one-line reason; never88silently drop one. Emit findings using craft-audit `workspace.md` → "Canonical findings.md emission89format" (authority). Heading grammar (variables required — do not hardcode NNN/severity/status):9091`## <scopeLabel>-LINT-<NNN> · severity <🔴|🟡|🟢> · status <open|fixed|wontfix (reason)|regressed|fixed (merged into <ID>)>`9293Example only: `## <scopeLabel>-LINT-001 · severity 🔴 · status open`9495Required fields under each heading, in order, with these exact labels:96`**What breaks (plain language):**` · `**Technical:**` · `**Fix:**` · `**Fingerprint:**` ·97`**Last-checked:**` (optional `**Confidence:**` — `verified | inferred | unverified-from-repo`, absent98means `verified` — then optional `**Fix-attempt:**` only from craft-fix).99Assign sequential NNN per (scope, domain); judge severity with craft-audit `prioritization.md`.100Forbidden: `###` headings; `## ID · 🔴 · open` shorthand; severity/status as body bullets.101102- [ ] **Applicability first:** if no JS/TS ESLint surface (Python/Ruff, Biome-only, Go, etc.), mark103 domain N-A or partial with a one-line reason and stop — do not force ESLint 10. → SKILL.md104 Applicability105- [ ] Inventory ESLint/package/plugin versions, config files, lint scripts, formatter config, TS strictness, CI lint gates, and pre-commit/lint-staged setup. → `references/standard.md` § Version Policy106- [ ] Run resolved-rule extraction with `scripts/eslint-rule-audit.mjs` or document why it cannot run. → `scripts/eslint-rule-audit.mjs`107- [ ] Compare resolved rules to context presets: base, typechecked TS, node, React, Next, a11y, security, tests, architecture. → `references/standard.md` § Presets108- [ ] Flag syntax-only TypeScript linting as insufficient for production TypeScript. → `references/standard.md` § Required Rule Contract (TypeScript Typechecked)109- [ ] Flag `next lint`, missing config, build-skipped linting, warnings-as-steady-state, stale `.eslintignore`, and unused-disable comments that do not fail. → `references/standard.md` § Anti-Patterns110- [ ] Identify rules currently warn/off/missing that should be errors for runtime quality. → `references/standard.md` § Required Rule Contract111- [ ] Propose the smallest migration to ESLint 10 flat config, with ESLint 8 exception only for named blockers. → `references/standard.md` § Migration Sequence112- [ ] Verify with `--print-config`, lint, and typecheck where feasible. → `scripts/eslint-rule-audit.mjs`113
Run npx skillmds@latest add gul-labs/craft-lint in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
The Craftsman standard for linting and static quality gates — ESLint version policy, resolved-rule extraction, typed TypeScript linting, React/Next/a11y/security rule hardening, zero-warning CI gates, pre-commit alignment, and migration from weak default configs to an enterprise-grade lint setup. Use this WHENEVER the work touches ESLint, lint rules, lint failures, lint config migration, quality scripts, pre-commit linting, or "standardize linting". Scope is **JS/TS ESLint surfaces** — with no ESLint surface (Python/Ruff, Biome-only, Go), mark the domain N-A rather than forcing a migration. Whole-project readiness → craft-audit. It is listed under Web & Frontend on SkillMD.
This skill has not completed SkillMD's automated safety review yet. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
gul-labs (@gul-labs) published this skill. Their other Agent Skills are listed on their SkillMD profile.