From dev
Linting and formatting setup expert using Biome and markdownlint-cli2. Use when users need to set up linters, configure Biome for TypeScript/JavaScript/CSS/JSON, configure markdownlint for Markdown files, migrate from ESLint/Prettier, or add code quality tooling to a project.
How this skill is triggered — by the user, by Claude, or both
Slash command
/dev:linter-setupThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Biome is a fast all-in-one linter, formatter, and import organizer for JavaScript, TypeScript, JSX, CSS, JSON, GraphQL, and HTML. markdownlint-cli2 is the standard linter for Markdown files. This guide provides workflows for setting up both tools in any project.
Biome is a fast all-in-one linter, formatter, and import organizer for JavaScript, TypeScript, JSX, CSS, JSON, GraphQL, and HTML. markdownlint-cli2 is the standard linter for Markdown files. This guide provides workflows for setting up both tools in any project.
# Install Biome (pin exact version)
bun add -D -E @biomejs/biome
# Initialize Biome config
bunx --bun biome init
# Check code (lint + format + imports)
bunx --bun biome check .
# Auto-fix all issues
bunx --bun biome check --write .
# Install markdownlint-cli2
bun add -D markdownlint-cli2
# Lint Markdown files
bunx markdownlint-cli2 '**/*.md' '!node_modules/**'
# Fix Markdown issues
bunx markdownlint-cli2 --fix '**/*.md' '!node_modules/**'
# Install both tools
bun add -D -E @biomejs/biome markdownlint-cli2
# Initialize Biome
bunx --bun biome init
Create biome.json:
{
"$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"formatter": {
"indentStyle": "tab",
"lineWidth": 80
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"javascript": {
"formatter": {
"quoteStyle": "double",
"semicolons": "always",
"trailingCommas": "all"
}
},
"json": {
"formatter": {
"trailingCommas": "none"
}
}
}
Create .markdownlint.json:
{
"default": true,
"MD013": false,
"MD029": false,
"MD033": {
"allowed_elements": ["br", "details", "summary", "img"]
},
"MD060": false
}
Add npm scripts to package.json:
{
"scripts": {
"lint": "biome check .",
"lint:fix": "biome check --write .",
"format": "biome format --write .",
"lint:md": "markdownlint-cli2 '**/*.md' '!node_modules/**'",
"fix:md": "markdownlint-cli2 --fix '**/*.md' '!node_modules/**'"
}
}
# Migrate ESLint rules to Biome
bunx --bun biome migrate eslint --write
# Include inspired rules (slightly different behavior)
bunx --bun biome migrate eslint --write --include-inspired
# Migrate Prettier options to Biome
bunx --bun biome migrate prettier --write
# Suppress existing violations (clean migration)
bunx --bun biome lint --write --unsafe --suppress="migration from ESLint"
# Verify migration
bunx --bun biome check .
# Remove ESLint and Prettier when satisfied
bun remove eslint prettier @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-config-prettier eslint-plugin-react
rm .eslintrc* .prettierrc* .eslintignore .prettierignore
# CI mode: read-only check, exits non-zero on errors
bunx --bun biome ci .
# With GitHub reporter for annotations
bunx --bun biome ci --reporter=github .
# With JUnit for CI dashboards
bunx --bun biome ci --reporter=junit . > biome-report.xml
# Markdown lint in CI
bunx markdownlint-cli2 '**/*.md' '!node_modules/**'
GitHub Actions example:
# .github/workflows/lint.yml
name: Lint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- run: bun install
- run: bunx --bun biome ci --reporter=github .
- uses: DavidAnson/markdownlint-cli2-action@main
with:
globs: "**/*.md"
# Install lint-staged and lefthook (or husky)
bun add -D lint-staged lefthook
Configure package.json:
{
"lint-staged": {
"*.{js,ts,jsx,tsx,css,json}": ["biome check --write --no-errors-on-unmatched"],
"*.md": ["markdownlint-cli2 --fix"]
}
}
Or use Biome's built-in git integration:
# Lint only staged files
bunx --bun biome check --staged --write
# Lint changes since default branch
bunx --bun biome check --changed --write
# Lint changes since specific ref
bunx --bun biome check --since=main --write
# Root biome.json (shared config)
# Each package can have its own biome.json that inherits
Root biome.json:
{
"$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
"formatter": {
"indentStyle": "tab"
},
"linter": {
"rules": {
"recommended": true
}
}
}
Package packages/frontend/biome.json:
{
"$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
"extends": ["../../biome.json"],
"linter": {
"domains": {
"react": "recommended"
}
}
}
Package packages/backend/biome.json:
{
"$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
"extends": ["../../biome.json"],
"javascript": {
"globals": ["Bun"]
}
}
When to use which tool:
biome checkbiome formatmarkdownlint-cli2biome check --writemarkdownlint-cli2 --fixbiome cibiome migrate eslint --writebiome migrate prettier --writebiome check --stagedbiome check --changed{
"linter": {
"rules": {
"recommended": true,
"style": {
"noNonNullAssertion": "warn",
"useConst": "error",
"useTemplate": "error"
},
"suspicious": {
"noExplicitAny": "warn",
"noDebugger": "error"
},
"complexity": {
"noForEach": "off"
}
},
"domains": {
"react": "recommended",
"test": "recommended"
}
}
}
{
"overrides": [
{
"includes": ["**/*.test.ts", "**/*.spec.ts"],
"linter": {
"rules": {
"suspicious": {
"noExplicitAny": "off"
}
}
}
},
{
"includes": ["scripts/**"],
"formatter": {
"lineWidth": 120
}
}
]
}
// Biome: suppress a specific rule
// biome-ignore lint/suspicious/noDebugger: needed for development
debugger;
// Biome: suppress formatting
// biome-ignore format: keep manual alignment
const matrix = [
[1, 0, 0],
[0, 1, 0],
[0, 0, 1],
];
<!-- markdownlint-disable MD013 -->
Long line that should not be flagged.
<!-- markdownlint-enable MD013 -->
<!-- markdownlint-disable-next-line MD041 -->
Not a heading on the first line.
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "biomejs.biome",
"editor.codeActionsOnSave": {
"source.fixAll.biome": "explicit",
"source.organizeImports.biome": "explicit"
},
"[markdown]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
Common Issues:
Biome not found after install
bunx --bun biome or npx @biomejs/biome instead of bare biomeConfig not picked up
biome.json is in project root with biome rageESLint migration misses rules
--include-inspired --include-nursery flagsmarkdownlint too strict
MD013 (line length) in .markdownlint.jsonConflicts between Prettier and Biome
For detailed troubleshooting steps, see the Troubleshooting Guide.
Load as needed for detailed information:
Commands Reference - Complete CLI documentation for Biome and markdownlint-cli2 with all flags, configuration schema, and rule groups. Use when you need exact syntax or config options.
Common Patterns - Real-world patterns for project setup, migration recipes, monorepo configs, CI/CD integration, editor setup, and advanced rule configuration. Use for implementing specific setups.
Troubleshooting Guide - Detailed error messages, diagnosis steps, and resolution strategies for installation, configuration, migration, and runtime issues. Use when encountering errors or unexpected behavior.
When to use each reference:
npx claudepluginhub leobrival/livenexx-plugin --plugin devGuides markdown linting with markdownlint-cli2: run checks, fix MD0XX errors, configure .markdownlint-cli2.jsonc rules/ignores, set up VS Code extension and GitHub Actions. Supports GFM/CommonMark for validation and workflows.
Provides Biome commands for formatting, linting, and organizing imports in JavaScript, TypeScript, JSX/TSX, JSON, CSS projects. Use for zero-config setup, fast CI checks, or ESLint/Prettier migration.
Applies Biome linting for accessibility, complexity, correctness rules and code quality enforcement in JavaScript/TypeScript projects via check commands and config.