LogoLogo
SlackLogin
  • Overview
    • Welcome
  • Setup & Configuration
    • Connecting to Trunk
    • Managing Your Organization
      • GitHub App Permissions
  • Integration with Slack
  • Flaky Tests (Beta)
    • Overview
    • Get Started
      • Test Frameworks
        • Android
        • Bazel
        • Behave
        • cargo-nextest
        • Cypress
        • Dart Test
        • Go
        • GoogleTest
        • Gradle
        • Jasmine
        • Jest
        • Karma
        • Maven
        • minitest
        • Mocha
        • Nightwatch
        • NUnit
        • Pest
        • PHPUnit
        • Playwright
        • Pytest
        • Robot Framework
        • RSpec
        • Swift Testing
        • Vitest
        • XCTest
        • Other Test Frameworks
      • CI Providers
        • Azure DevOps Pipelines
        • BitBucket Pipelines
        • Buildkite
        • CircleCI
        • Drone CI
        • GitHub Actions
        • GitLab
        • Jenkins
        • Semaphore CI
        • TeamCity
        • Travis CI
        • Other CI Providers
    • Dashboard
    • Flaky Test Detection
    • Quarantining
    • PR Comments
    • Ticketing Integrations
      • Jira Integration
      • Linear Integration
      • Other Ticketing Platforms
    • Webhooks
      • Slack Integration
      • Microsoft Teams Integration
      • GitHub Issues Integration
      • Linear Integration
    • Uploader CLI Reference
  • Merge Queue
    • Overview
    • How does it work?
    • Setup
      • Quick Start
      • Settings
      • Integration for Slack
    • Concepts and Optimizations
      • Predictive Testing
      • Optimistic Merging
      • Pending Failure Depth
      • Anti-Flake Protection
      • Batching
      • Parallel Queues
        • Bazel
        • Nx
        • API
      • FAQ
    • Priority
    • Managing Merge Queue
      • Using the Merge UI
      • Metrics
      • Command Line
    • Webhooks
    • Reference
  • Code Quality
    • Overview
    • Why Metalinters?
      • How does it work?
      • Why Code Quality?
    • Setup & Installation
      • Initialize Trunk
      • Local Linting
      • Linting in CI
      • Nightly Report (Deprecated)
    • IDE Integration
      • VSCode
      • Neovim
      • GitHub Codespaces
    • Linters
      • Supported Linters
        • Actionlint
        • Ansible-lint
        • Autopep8
        • Bandit
        • Biome
        • Black
        • Brakeman
        • buf
        • Buildifier
        • cfnlint
        • Checkov
        • circleci
        • ClangFormat
        • clang-tidy
        • Clippy
        • cmake-format
        • codespell
        • cspell
        • cue-fmt
        • dart
        • deno
        • Detekt
        • djlint
        • dotenv-linter
        • dotnet-format
        • dustilock
        • ESLint
        • Flake8
        • git-diff-check
        • Gitleaks
        • Gofmt
        • gofumpt
        • goimports
        • gokart
        • golangci-lint
        • golines
        • google-java-format
        • graphql-schema-linter
        • hadolint
        • haml-lint
        • isort
        • iwyu
        • ktlint
        • kube-linter
        • markdown-link-check
        • markdown-table-prettify
        • Markdownlint
        • markdownlint-cli2
        • mypy
        • nancy
        • nixpkgs-fmt
        • opa
        • OSV-Scanner
        • Oxipng
        • perlcritic
        • perltidy
        • php-cs-fixer
        • phpstan
        • pmd
        • pragma-once
        • pre-commit-hooks
        • Prettier
        • prisma
        • psscriptanalyzer
        • Pylint
        • pyright
        • regal
        • remark-lint
        • renovate
        • rome
        • rubocop
        • Ruff
        • rufo
        • rustfmt
        • scalafmt
        • semgrep
        • ShellCheck
        • shfmt
        • sort-package-json
        • sourcery
        • sql-formatter
        • SQLFluff
        • sqlfmt
        • squawk
        • standardrb
        • stringslint
        • stylelint
        • stylua
        • SVGO
        • swiftformat
        • swiftlint
        • taplo
        • Terraform
        • terragrunt
        • terrascan
        • TFLint
        • tfsec
        • tofu
        • Trivy
        • Trufflehog
        • txtpbfmt
        • vale
        • Yamllint
        • yapf
      • Run Linters
      • Manage Linters
      • Configure Linters
      • Ignoring Issues and Files
      • Custom Linters
      • Shared Configs
      • Upgrades
    • Debugging
    • Licensing
  • CLI & API References
    • CLI Reference
      • Install
      • Getting Started
        • Code Quality
        • Merge Queue
        • Flaky Tests
        • Tools
        • Actions
          • Git Hooks
        • Announce
      • Compatibility
      • Caching
      • Commands Reference
        • Code Quality
        • Actions
        • Merge
      • Configuration
        • Plugins
          • Share Config Between Codebases
          • Exporting Linter Configs
        • Runtimes
        • Tools
        • Lint
          • Definitions
          • Commands
          • Output
          • Output Parsing
          • Files and Caching
          • Dependencies
          • Auto-Enable
        • Actions
          • Notifications
          • Logging and Troubleshooting
        • Merge
        • Telemetry
        • Per User Overrides
    • API Reference
      • Flaky Tests
      • Merge Queue
      • Webhooks Reference
  • Pricing & Security
    • Security
  • Billing
  • Community & Support
  • Links
    • Open App
    • Slack Community
    • Changelog
    • Feature Requests
On this page
  • Why you need to lint everything
  • Why it's hard to lint everything
  • Why it's hard to lint giant code bases
  • Why not just write a script?
  • Who uses Trunk Code Quality?
Edit on GitHub
  1. Code Quality
  2. Why Metalinters?

Why Code Quality?

Last updated 8 months ago

Why you need to lint everything

Most projects will run linters and formatters for their primary language but neglect to run any static analysis on the build scripts, IaC (infrastructure-as-code), CI (continuous integration) config, and docs files. These are the "hard to clean corners" of your code base, where coding standards fall apart and vulnerabilities accumulate unnoticed.

These bits of unlinted code accumulate unused dependencies, deprecated method calls, poorly formatted code, and known antipatterns, which will spread as your project ages from copy-pasting. They become bits of code that no one wants to touch or own.

Worse is the accumulation of . A 2017 study by Northeastern University aptly named : Analysing the Use of Outdated JavaScript Libraries on the Web revealed that 37% of 133,000 websites used a JavaScript library with known vulnerabilities. More recently, , 84% of 1,703 reviewed codebases had at least one such vulnerability.

Now factor in your IaC files, CI config, and build scripts; these are the places that you should lint regularly because of the likelihood of newly discovered vulnerabilities in your dependency chain. This is why you need a metalinter that can lint all of your files.

Why it's hard to lint everything

Having good linter coverage in any modern project is difficult because there isn't just one language and technology. There are tons of scripts, images, config files, docs, and IaC files to lint.

The tools required to lint everything install, run, output, upgrade, and configure differently. Now consider the tools that require dependencies and runtimes, such as and that depend on Go, or and that depend on Python. You have to maintain version pinned tools and their runtimes.

These tools are also prone to tool-rot, where dependencies become old, deprecated, or known vulnerabilities are discovered. In fact, . Keeping these tools up to date is a Sisyphean task. It's better to have a metalinter handle all of it.

Why it's hard to lint giant code bases

Giant code bases are hard to lint without good tooling. Imagine introducing a new Python linter to lint over 1 million lines of code. No one will wait tens of minutes or hours for linters to run. Now, considering a polyglot mono repo with millions of lines of code and many languages, the problem only grows.

Trunk Code Quality solves this by being and linting only the lines and files that have changed in your repo on commit or PR.

Why not just write a script?

adopted Trunk Code Quality to replace their because it's difficult to maintain. Writing a script that can do everything a metalinter does is not trivial. You need to handle per-line and file ignores properly, adapt to the many config and output formats of different tools, support different OS and architectures, lint in a way that's so it can run on large code bases quickly, and adapt to breaking changes or newly added linters.

That code is outside of a project's core goals and is bound to become debt. Code Quality is free to run locally and in CI, and reporting to the is free for open-source teams.

Who uses Trunk Code Quality?

Trunk Code Quality lets them easily manage consistent config and tooling for their repo and achieve full linter coverage.

Popular open-source repos like and use Trunk Code Quality to lint their source code. They use Trunk Code Quality as their metalinter because it's difficult to maintain and run the many linters they run, especially when open-source maintainers need to run and install them individually.

.

ESLint
Realm.js
Learn more about how ESLint leverages Code Quality in their repos
unnoticed security vulnerabilities
Thou Shalt Not Depend on Me
in a study by Synopsys
nancy
actionlint
Bandit
sqlfmt
82% of open-source projects suffer from tool-rot
ESLint
linter script
Web App
Git aware
git-aware