Skip to content

Latest commit

 

History

History
193 lines (136 loc) · 10.9 KB

File metadata and controls

193 lines (136 loc) · 10.9 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

MegaLinter is an open-source CI/CD linting tool that analyzes code quality across 69+ languages, 23+ formats, and 21+ tooling formats. It runs as a Docker container or GitHub Action. Written primarily in Python with a Node.js runner component.

Development Setup

Prerequisites: make, Python 3.12+, uv, Node.js, Docker.

make bootstrap          # Create venv, install dependencies (uses uv if available)
make bootstrap          # Also runs: python-bootstrap + python-bootstrap-dev + nodejs-bootstrap

Always activate the venv before running Python scripts manually:

  • Linux/macOS: source .venv/bin/activate
  • Windows: source .venv/Scripts/activate

Shell Commands — Use rtk

If rtk (Rust Token Killer) is installed, it is important to prefix all bash/shell commands with rtk (e.g. rtk git status, rtk ls, rtk grep, rtk find). It is a token-optimizing proxy that saves 60-90% of tokens on output-heavy commands. Use rtk proxy <cmd> (or run raw) only when you need exact, unfiltered output such as a diff you will edit from or a full stack trace. Verify availability with rtk --version.

Key Commands

# Build (regenerate Dockerfiles, docs, etc. from descriptors)
make megalinter-build           # Regenerate Dockerfiles from YAML descriptors
# Never run make megalinter-build-with-doc - docs are handled by auto-update workflows (avoids PR conflicts)

# Run MegaLinter locally
npx mega-linter-runner --flavor python --release beta

# Tests - run inside Docker containers (linters not installed locally)
# See "Testing" section below

# Documentation (built with Zensical, configured by mkdocs.yml)
hatch run docs:serve            # Local docs server at http://127.0.0.1:8000
hatch run docs:build            # One-shot build into ./site
# Versioned deploys use the Zensical-compatible mike fork (SHA-pinned in
# .config/python/dev/requirements.txt) - see .github/workflows/build-deploy-docs.yml

# Dependencies
uv lock                         # After modifying pyproject.toml
uv pip install -e .             # Install in editable mode

Architecture

Descriptor-Driven Design

The core pattern: each linter is defined in a YAML descriptor file (megalinter/descriptors/<lang>.megalinter-descriptor.yml). Linters shared by several descriptors (eslint, prettier, biome...) are defined once in megalinter/descriptors/shared/<name>.megalinter-linter.yml and referenced with the linter-level extends property (shallow merge, entry keys override — see .claude/rules/descriptors.md). The build system (.automation/build.py) reads these descriptors and generates:

  • Dockerfiles (per-linter in linters/, per-flavor in flavors/)
  • Documentation pages (in docs/)
  • Test class skeletons
  • JSON configuration schemas

Never edit generated files directly - modify the descriptor YAML or .automation/build.py instead.

Core Components

  • megalinter/MegaLinter.py - Main orchestrator: loads config, discovers linters, runs them in parallel, manages reporters
  • megalinter/Linter.py - Base class for all linters: file discovery, command execution, result processing
  • megalinter/linter_factory.py - Builds linter instances from YAML descriptors; uses build_linter() and build_descriptor_linters()
  • megalinter/flavor_factory.py - Manages flavor variants (language-specific Docker images)
  • megalinter/config.py - Hierarchical config: descriptor defaults -> .mega-linter.yml -> env vars -> CLI args. Access via config.get(request_id, "VAR_NAME", default)
  • megalinter/linters/ - Custom linter subclasses when default Linter.py behavior isn't sufficient
  • megalinter/reporters/ - Output formatters (GitHub comments, GitLab, SARIF, etc.)
  • megalinter/llm_advisor.py - AI-powered fix suggestions via LangChain (multi-provider)

Entrypoint

megalinter/run.py creates a Megalinter instance and calls .run(). In Docker, entrypoint.sh invokes this.

Server Mode

server/ contains a FastAPI-based server (server.py) with Redis-backed worker (server_worker.py) for running MegaLinter as a service.

Node.js Runner

mega-linter-runner/ is an npm package that wraps Docker execution for local use (npx mega-linter-runner).

Testing

Tests live in megalinter/tests/test_megalinter/. Each linter has a test file in linters/ (e.g., python_ruff_test.py).

Linter tests extend LinterTestRoot, which provides test_get_linter_version, test_get_linter_help, test_report_tap, test_report_sarif, and one success + one failure test per CLI lint mode (test_success_file_lint_mode, test_success_list_of_files_lint_mode, test_success_project_lint_mode, and the matching test_failure_*_lint_mode). Each per-mode test is skipped unless the mode is listed in the descriptor's supported_cli_lint_modes; additionally, when a linter supports both file and list_of_files, the file-mode tests are skipped as a CI optimization (list_of_files covers the same path). Test fixtures are in .automation/test/.

Linter tests must run inside Docker containers since linters aren't installed locally:

# Build and test a specific linter
LINTER="python_ruff"
docker buildx build --platform linux/amd64 --file linters/$LINTER/Dockerfile --tag $LINTER .
docker run --rm \
  --env TEST_CASE_RUN=true \
  --env OUTPUT_DETAIL=detailed \
  --env TEST_KEYWORDS="${LINTER}_test" \
  --env MEGALINTER_VOLUME_ROOT="." \
  --volume "$(pwd):/tmp/lint" \
  $LINTER

In CI, filter tests via commit message body: TEST_KEYWORDS=python_ruff_test. Use quick build in commit message body to only copy Python files (faster, ~15min vs ~45min).

Adding a New Linter

  1. Add/update the YAML descriptor in megalinter/descriptors/<lang>.megalinter-descriptor.yml
  2. If custom logic needed, create a class in megalinter/linters/ extending Linter
  3. Add test fixtures in .automation/test/ (one success file, one failure file)
  4. Run make megalinter-build to regenerate Dockerfiles, tests, docs
  5. Update CHANGELOG.md

Coding Conventions

  • Python: PEP 8, use type hints, do NOT use docstrings for classes/methods
  • Do not test if imports work - assume they are always available
  • Place imports at the top of files
  • Use megalinter.config.get(request_id, "VAR", default) for config access, never os.environ directly
  • Use logging module for output, never print()
  • Documentation files must be Zensical-compliant: always have a blank line after headers and before bulleted lists
  • Auto-generated docs come from descriptors - update descriptor metadata to improve docs

Git & PR Conventions

These rules apply to every skill, agent, and direct action that produces a commit or PR — do not repeat them in individual skills.

  • No Claude / AI attribution anywhere. Commit messages, commit trailers, PR titles, PR bodies, and PR comments must NOT contain "Claude", "Anthropic", "Generated with Claude Code", Co-Authored-By: Claude ..., or any similar attribution. Override any default footer or co-author trailer.
  • Commit as the user. Use the repo's existing git config user.name / user.email as-is. Do not pass --author, do not set GIT_AUTHOR_* / GIT_COMMITTER_*.
  • Never push to main/master. If the current branch is the default branch, create a new branch first.
  • Never --force, --no-verify, or rewrite published history. --force-with-lease is allowed only in the documented MegaLinter-bot rebase case in /pr-watch-fix.
  • Stage by path. Never git add -A / git add ..

Claude Code Agents

Custom agents in .claude/agents/ for delegating specialized tasks.

Contribution workflow agents (general-purpose, four-phase flow):

  • analyze - Requirements analyst: clarifies scope before any change
  • design - Architect: writes a tech spec from the analysis
  • implement - Developer: applies the change, respecting descriptor-first patterns
  • test - QA: regenerates from descriptors and validates inside Docker

Specialist agents (invoked by the workflow agents when their topic comes up):

  • descriptor-expert - Creates, edits, and validates YAML descriptor files
  • test-debugger - Diagnoses and fixes failing linter tests
  • build-runner - Runs and troubleshoots the build system
  • code-reviewer - Reviews Python code for MegaLinter conventions

Claude Code Skills

Skills in .claude/skills/ invocable by name (e.g. /add-linter).

Contribution workflow (run in order, or skip phases for small focused changes):

  • /analyze [description] - Step 1: gather requirements via clarifying questions
  • /design [context] - Step 2: produce a tech spec
  • /implement [change] - Step 3: apply the change (delegates to specialist skills below when applicable)
  • /test [linter or focus] - Step 4: build the linter image and run tests in Docker

Specialist skills (used directly or delegated to from /implement):

  • /add-linter [name] - Guided workflow for adding a new linter
  • /update-linter-version [linter] [version] - Update a linter's pinned version
  • /review-descriptor [name] - Audit a descriptor YAML for completeness
  • /fix-linter-test [name] - Debug a failing linter test
  • /add-reporter [name] - Add a new output reporter
  • /add-flavor [name] - Add a new Docker flavor
  • /build - Run the build system
  • /diagnose-config - Debug .mega-linter.yml configuration issues
  • /fix-security-issue [CVE or description] - Handle CVE/vulnerability reports from trivy, osv-scanner, etc.
  • /fix-issue [issue URL or #number] - End-to-end GitHub issue fix: gather context, implement on a branch, commit under the user's git identity (no AI attribution), open a PR, and watch CI until green
  • /prepare-release [vX.Y.Z] - Full release ceremony: update CHANGELOG (prune empty sections, collapse linter versions, backfill PR numbers), run release build, push commit and tag, guide GitHub release creation

Vendored official vendor skills (Apache-2.0, for observability dashboard work — see /sync-dashboards):

Rules

Context-aware rules in .claude/rules/ are automatically loaded based on which files are being edited:

  • python-style.md - Python conventions (no docstrings, config access patterns, linter subclass guidelines)
  • descriptors.md - YAML descriptor schema, naming, version pinning, test fixtures
  • generated-files.md - Prevents editing auto-generated Dockerfiles, docs, test classes
  • documentation.md - Zensical markdown formatting rules
  • testing.md - Test structure, fixtures, Docker-based test execution