leobrival

linter-setup

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.

leobrival 0 Updated 3mo ago

Resources

1
GitHub

Install

npx skillscat add leobrival/topographic-plugins-official/linter-setup

Install via the SkillsCat registry.

SKILL.md

Linter Setup Guide

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.

Quick Start

# 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/**'

Common Workflows

Workflow 1: New Project Setup (Biome + markdownlint)

# 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/**'"
  }
}

Workflow 2: Migrate from ESLint and Prettier

# 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

Workflow 3: CI/CD Integration

# 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"

Workflow 4: Git Hooks with lint-staged

# 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

Workflow 5: Monorepo Setup

# 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"]
  }
}

Decision Tree

When to use which tool:

  • To lint TS/JS/JSX/TSX/CSS/JSON/GraphQL: Use biome check
  • To format TS/JS/JSX/TSX/CSS/JSON: Use biome format
  • To lint Markdown (.md) files: Use markdownlint-cli2
  • To auto-fix code issues: Use biome check --write
  • To auto-fix Markdown: Use markdownlint-cli2 --fix
  • To run in CI (read-only): Use biome ci
  • To migrate from ESLint: Use biome migrate eslint --write
  • To migrate from Prettier: Use biome migrate prettier --write
  • To lint only staged files: Use biome check --staged
  • To lint changes since branch: Use biome check --changed
  • For detailed Biome config: See Commands Reference
  • For config recipes: See Common Patterns
  • For troubleshooting: See Troubleshooting Guide

Common Patterns

Biome Rule Configuration

{
  "linter": {
    "rules": {
      "recommended": true,
      "style": {
        "noNonNullAssertion": "warn",
        "useConst": "error",
        "useTemplate": "error"
      },
      "suspicious": {
        "noExplicitAny": "warn",
        "noDebugger": "error"
      },
      "complexity": {
        "noForEach": "off"
      }
    },
    "domains": {
      "react": "recommended",
      "test": "recommended"
    }
  }
}

Biome File Overrides

{
  "overrides": [
    {
      "includes": ["**/*.test.ts", "**/*.spec.ts"],
      "linter": {
        "rules": {
          "suspicious": {
            "noExplicitAny": "off"
          }
        }
      }
    },
    {
      "includes": ["scripts/**"],
      "formatter": {
        "lineWidth": 120
      }
    }
  ]
}

Suppress and Ignore

// 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 Configuration (VS Code)

{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "biomejs.biome",
  "editor.codeActionsOnSave": {
    "source.fixAll.biome": "explicit",
    "source.organizeImports.biome": "explicit"
  },
  "[markdown]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  }
}

Troubleshooting

Common Issues:

  1. Biome not found after install

    • Solution: Use bunx --bun biome or npx @biomejs/biome instead of bare biome
    • See: Installation Issues
  2. Config not picked up

  3. ESLint migration misses rules

    • Quick fix: Add --include-inspired --include-nursery flags
    • See: Migration Issues
  4. markdownlint too strict

    • Quick fix: Disable MD013 (line length) in .markdownlint.json
    • See: Markdown Issues
  5. Conflicts between Prettier and Biome

For detailed troubleshooting steps, see the Troubleshooting Guide.

Reference Files

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:

  • Use Commands Reference when you need exact syntax, config schema, or the full list of Biome/markdownlint rules
  • Use Common Patterns for project setup recipes, migration guides, or CI/CD pipeline configuration
  • Use Troubleshooting when tools won't install, configs aren't detected, or rules behave unexpectedly

Resources