wangjohn/levenshtein

A comprehensive batch of lint rules for Go, shared across all your repos.

Go

0

680 commits

updated Oct 2, 2026

See the code

See what people are saying

README

Levenshtein

CI Latest release License: Apache 2.0

A curated set of Go lint rules and verification checks, easy to hook up to any Go repo.

Coding agents are writing more and more of our code, and I want as much of that code as possible to be verifiable. Good lint rules and automated checks give agents feedback they can act on while they work, and give us more than the agent's word that a change is ready.

I built Levenshtein while setting up a bunch of new Go repos. I wanted one place to keep a high-quality set of rules I could rely on for all of my repos, without researching analyzers and copying lint configs every time. Each repo pins a Levenshtein revision and runs ./verify, so that all my repos use the same rules and tool versions (and updates are easy to roll out everywhere).

You can easily add your own lint rules or commands alongside the built-in checks in your repo’s configuration.

What it checks

Levenshtein combines Staticcheck, established Go analyzers, and a few rules of its own. The rules catch bugs and encourage readable code; most naming and comment-style preferences are left out.

Default checks

./verify and pre-merge run these checks. Go vulnerability scanning runs only in main, which also reruns checks without using cached results.

CheckExample finding
StaticcheckClose before error check: deferring f.Close() before checking whether os.Open succeeded
Bug-finding analyzersUnchecked error: calling file.Write(data) without checking whether the write failed
ModernizeManual map copy: copying entries in a loop when maps.Copy does the same job
Levenshtein's rulesUntyped status: comparing a plain string to "done" and "failed" instead of typed constants
go vet (go-vet)Format mismatch: passing "hello" to fmt.Printf("%d", ...), which expects an integer
Module checks (go-mod)Missing dependency: importing a package whose module is missing from go.mod
Go vulnerabilities (go-vuln, main only)Vulnerable function: your code can reach a dependency function with a known security flaw

Optional checks

Add these checks to your repo's configuration.

CheckExample finding
Race detector (go-test)Concurrent writes: two goroutines updating a shared map without synchronization
HTTP resources (go-http)Unclosed response body: returning from an HTTP request without closing resp.Body
SQL resources (go-sql)Unclosed query results: reading database rows without closing them afterward
GitHub Actions lint (workflow-lint)Unknown property: a workflow expression referencing a property that doesn't exist
Workflow security (workflow-security)Shell injection: inserting a PR title directly into a workflow's shell command
ShellCheck (shell-lint)Unchecked directory change: running cd "$dir" without stopping or handling failure
Secret scanning (secrets)Committed API key: a credential left in a tracked configuration file
Other dependency vulnerabilities (deps-vuln)Vulnerable package: a version with a known security flaw pinned in package-lock.json
Import boundaries (go-imports)Forbidden import: a domain package importing a database package against your layering rules
Generated files (go-generate)Stale generated code: a committed file that changes when go generate runs
API compatibility (go-apidiff)Removed exported function: a public API change that breaks existing callers
Mutation testing (go-mutation)Missed boundary bug: changing > to >= without any test failing
Semantic lint (semantic-lint)Vague error message: an added error gives the caller no clue how to fix the problem; advisory review through Jev
Custom commands (command)Failed integration test: your repo's test script exits with an error

self-test tests Levenshtein's own fixtures when developing the shared checks.

The lint and CI/CD rules index links to all the rules, checks, and CI policies, with explanations of why each rule is enabled or left out. To understand a Go lint warning, start with Go lint rules.

Quickstart

To try the Go lint rules, run this from your module's root with Go 1.21 or later:

go run github.com/wangjohn/levenshtein/runner/lint/cmd/levenshtein-lint@latest ./...

For the default checks, use Go and a Docker-compatible runtime on macOS or Linux:

git clone --depth 1 --branch v0.2.0 https://github.com/wangjohn/levenshtein
./levenshtein/verify --source ./myapp --format text

A single Go module needs no config. The first run downloads and builds the tools; verify reports problems without changing your files. See setup for prerequisites and named runs.

Documentation

Setup · Rules index · Configuration · CLI reference · Coding agents · Troubleshooting · All docs

See the changelog and versioning policy before updating the version your repo uses.

If you're happy with a single repo's golangci-lint setup, you may not need this; the FAQ compares the two.

Contributing and security

Maintained by John Wang (@wangjohn). For questions or bugs, open an issue.

See CONTRIBUTING.md. Report vulnerabilities privately as SECURITY.md describes. Released under the Apache License 2.0; see NOTICE.

agentic
agentic-ai
agent-orchestration
ai
ai-agents
ai-coding
ai-tools
cicd
lint

wangjohn/levenshtein

A comprehensive batch of lint rules for Go, shared across all your repos.

Go

0

680 commits

updated Oct 2, 2026

See the code

See what people are saying

README

Levenshtein

CI Latest release License: Apache 2.0

A curated set of Go lint rules and verification checks, easy to hook up to any Go repo.

Coding agents are writing more and more of our code, and I want as much of that code as possible to be verifiable. Good lint rules and automated checks give agents feedback they can act on while they work, and give us more than the agent's word that a change is ready.

I built Levenshtein while setting up a bunch of new Go repos. I wanted one place to keep a high-quality set of rules I could rely on for all of my repos, without researching analyzers and copying lint configs every time. Each repo pins a Levenshtein revision and runs ./verify, so that all my repos use the same rules and tool versions (and updates are easy to roll out everywhere).

You can easily add your own lint rules or commands alongside the built-in checks in your repo’s configuration.

What it checks

Levenshtein combines Staticcheck, established Go analyzers, and a few rules of its own. The rules catch bugs and encourage readable code; most naming and comment-style preferences are left out.

Default checks

./verify and pre-merge run these checks. Go vulnerability scanning runs only in main, which also reruns checks without using cached results.

CheckExample finding
StaticcheckClose before error check: deferring f.Close() before checking whether os.Open succeeded
Bug-finding analyzersUnchecked error: calling file.Write(data) without checking whether the write failed
ModernizeManual map copy: copying entries in a loop when maps.Copy does the same job
Levenshtein's rulesUntyped status: comparing a plain string to "done" and "failed" instead of typed constants
go vet (go-vet)Format mismatch: passing "hello" to fmt.Printf("%d", ...), which expects an integer
Module checks (go-mod)Missing dependency: importing a package whose module is missing from go.mod
Go vulnerabilities (go-vuln, main only)Vulnerable function: your code can reach a dependency function with a known security flaw

Optional checks

Add these checks to your repo's configuration.

CheckExample finding
Race detector (go-test)Concurrent writes: two goroutines updating a shared map without synchronization
HTTP resources (go-http)Unclosed response body: returning from an HTTP request without closing resp.Body
SQL resources (go-sql)Unclosed query results: reading database rows without closing them afterward
GitHub Actions lint (workflow-lint)Unknown property: a workflow expression referencing a property that doesn't exist
Workflow security (workflow-security)Shell injection: inserting a PR title directly into a workflow's shell command
ShellCheck (shell-lint)Unchecked directory change: running cd "$dir" without stopping or handling failure
Secret scanning (secrets)Committed API key: a credential left in a tracked configuration file
Other dependency vulnerabilities (deps-vuln)Vulnerable package: a version with a known security flaw pinned in package-lock.json
Import boundaries (go-imports)Forbidden import: a domain package importing a database package against your layering rules
Generated files (go-generate)Stale generated code: a committed file that changes when go generate runs
API compatibility (go-apidiff)Removed exported function: a public API change that breaks existing callers
Mutation testing (go-mutation)Missed boundary bug: changing > to >= without any test failing
Semantic lint (semantic-lint)Vague error message: an added error gives the caller no clue how to fix the problem; advisory review through Jev
Custom commands (command)Failed integration test: your repo's test script exits with an error

self-test tests Levenshtein's own fixtures when developing the shared checks.

The lint and CI/CD rules index links to all the rules, checks, and CI policies, with explanations of why each rule is enabled or left out. To understand a Go lint warning, start with Go lint rules.

Quickstart

To try the Go lint rules, run this from your module's root with Go 1.21 or later:

go run github.com/wangjohn/levenshtein/runner/lint/cmd/levenshtein-lint@latest ./...

For the default checks, use Go and a Docker-compatible runtime on macOS or Linux:

git clone --depth 1 --branch v0.2.0 https://github.com/wangjohn/levenshtein
./levenshtein/verify --source ./myapp --format text

A single Go module needs no config. The first run downloads and builds the tools; verify reports problems without changing your files. See setup for prerequisites and named runs.

Documentation

Setup · Rules index · Configuration · CLI reference · Coding agents · Troubleshooting · All docs

See the changelog and versioning policy before updating the version your repo uses.

If you're happy with a single repo's golangci-lint setup, you may not need this; the FAQ compares the two.

Contributing and security

Maintained by John Wang (@wangjohn). For questions or bugs, open an issue.

See CONTRIBUTING.md. Report vulnerabilities privately as SECURITY.md describes. Released under the Apache License 2.0; see NOTICE.

agentic
agentic-ai
agent-orchestration
ai
ai-agents
ai-coding
ai-tools
cicd
lint

Languages

Go

94.3%

Shell

4.9%