---
title: New linters
weight: 4
aliases:
  - /contributing/new-linters/
---

## How to write a linter

Use `go/analysis` and take a look at [this tutorial](https://web.archive.org/web/20250527152107/https://disaev.me/p/writing-useful-go-analysis-linter/):
it shows how to write `go/analysis` linter from scratch and integrate it into `golangci-lint`.

## How to add a public linter to `golangci-lint`

You need to implement a new linter using `go/analysis` API.

We don't accept non `go/analysis` linters.

After that:

1. Implement functional tests for the linter:
    - Add one file into directory `pkg/golinters/{yourlintername}/testdata/`.
2. Add a new file `pkg/golinters/{yourlintername}/{yourlintername}.go`.
   Other linters implementation can help you.
3. Add the new struct for the linter (which you've implemented in `pkg/golinters/{yourlintername}/{yourlintername}.go`) to the
   list of all supported linters in [`pkg/lint/lintersdb/builder_linter.go`](https://github.com/golangci/golangci-lint/blob/HEAD/pkg/lint/lintersdb/builder_linter.go)
   to the method `LinterBuilder.Build`.
    - Add `WithSince("next_version")`, where `next_version` must be replaced by the next minor version. (ex: v1.2.0 if the current version is v1.1.0)
4. Find out what options do you need to configure for the linter.
   For example, `nakedret` has only 1 option: [`max-func-lines`](https://github.com/golangci/golangci-lint/blob/HEAD/.golangci.reference.yml).
   Choose default values to not being annoying for users of golangci-lint. Add configuration options to:
    - [.golangci.next.reference.yml](https://github.com/golangci/golangci-lint/blob/HEAD/.golangci.next.reference.yml): the example of a configuration file.
      You can also add them to [.golangci.yml](https://github.com/golangci/golangci-lint/blob/HEAD/.golangci.yml)
      if you think that this project needs not default values.
    - [config struct](https://github.com/golangci/golangci-lint/blob/HEAD/pkg/config/config.go):
      don't forget about `mapstructure` tags for proper configuration files parsing.
5. Take a look at the example of [pull requests with new linter support](https://github.com/golangci/golangci-lint/pulls?q=is%3Apr+is%3Amerged+label%3A%22linter%3A+new%22).
6. Run the tests:
    ```bash
    go run ./cmd/golangci-lint/ run --no-config --default=none --enable={yourlintername} ./pkg/golinters/{yourlintername}/testdata/{yourlintername}.go
    ```

## How to add a private linter to `golangci-lint`

Some people and organizations may choose to have custom-made linters run as a part of `golangci-lint`.  
Typically, these linters can't be open-sourced or too specific.

Such linters can be added through 2 plugin systems:

{{< cards cols=2 >}}
  {{< card link="/docs/plugins/module-plugins" title="Module Plugin System" icon="puzzle" tag="Recommended" >}}
  {{< card link="/docs/plugins/go-plugins" title="Go Plugin System" icon="puzzle" >}}
{{< /cards >}}
