---
title: New linters
---

## How to write a linter

Use `go/analysis` and take a look at [this tutorial](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 [`test/testdata`](https://github.com/golangci/golangci-lint/tree/master/test/testdata).
    - Run the test to ensure that test fails:
      ```bash
      T=yourlintername.go make test_linters
      ```
    - Run:
      ```bash
      go run ./cmd/golangci-lint/ run --no-config --disable-all --enable=yourlintername ./test/testdata/yourlintername.go
      ```
2. Add a new file `pkg/golinters/{yourlintername}.go`.
   Look at other linters in this directory.
   Implement linter integration and check that test passes.
3. Add the new struct for the linter (which you've implemented in `pkg/golinters/{yourlintername}.go`) to the
   list of all supported linters in [`pkg/lint/lintersdb/builder_linter.go`](https://github.com/golangci/golangci-lint/blob/master/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/master/.golangci.reference.yml).
   Choose default values to not being annoying for users of golangci-lint. Add configuration options to:
    - [.golangci.reference.yml](https://github.com/golangci/golangci-lint/blob/master/.golangci.reference.yml) - the example of a configuration file.
      You can also add them to [.golangci.yml](https://github.com/golangci/golangci-lint/blob/master/.golangci.yml)
      if you think that this project needs not default values.
    - [config struct](https://github.com/golangci/golangci-lint/blob/master/pkg/config/config.go) -
      don't forget about `mapstructure` tag for proper configuration files parsing by [pflag](https://github.com/spf13/pflag).
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).

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

1. [Go Plugin System](/plugins/module-plugins)
2. [Module Plugin System](/plugins/go-plugins)
