
Go Linting
- 969 installs
- 137 repo stars
- Updated June 20, 2026
- cxuu/golang-skills
go-linting is a Go skill that generates a production-grade .golangci.yml and runs a comprehensive golangci-lint suite with one bash command for developers who need standardized static analysis on Go modules.
About
go-linting is a cxuu Go skill (script v1.0.0) that generates a production-grade .golangci.yml and runs an initial comprehensive lint pass in one command. The bundled config enables 10 linters—errcheck, goimports, revive, govet, staticcheck, gosec, ineffassign, misspell, gocyclo, and bodyclose—with a 5-minute timeout, zero max-issues-per-linter, and revive exported-rule settings. Developers reach for go-linting when bootstrapping Go repos, standardizing CI lint gates, or replacing ad-hoc golangci-lint setups with an opinionated baseline that enforces security (gosec) and complexity (gocyclo min-complexity 15) checks.
- Generates .golangci.yml with 5 minimum recommended linters (errcheck, goimports, revive, govet, staticcheck) plus 5 addi
- Configures revive exported rule, gocyclo minimum complexity of 15, and goimports local-prefix handling
- Supports --force, --dry-run, --json, and --limit options for flexible CI and local workflows
- Exits with standard codes (0 clean, 1 issues found, 2 error) for easy scripting
- Runs with a 5-minute timeout and strict issue reporting (max-issues-per-linter: 0)
Go Linting by the numbers
- 969 all-time installs (skills.sh)
- +39 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #139 of 1,352 Code Review & Quality skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/cxuu/golang-skills --skill go-lintingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 969 |
|---|---|
| repo stars | ★ 137 |
| Security audit | 3 / 3 scanners passed |
| Last updated | June 20, 2026 |
| Repository | cxuu/golang-skills ↗ |
How do you bootstrap golangci-lint for a Go project?
Automatically generate a production-grade.golangci.yml configuration and run a comprehensive Go linter suite with one command.
Who is it for?
Go backend developers setting up or hardening static analysis on new or existing modules before CI merge.
Skip if: Teams already running a customized golangci-lint config they do not want overwritten by a generated baseline.
When should I use this skill?
User asks to lint Go code, create .golangci.yml, or run golangci-lint with security and style checks.
What you get
.golangci.yml config file and initial golangci-lint report across enabled linters.
- .golangci.yml configuration
- Initial golangci-lint report
By the numbers
- Enables 10 linters including errcheck, staticcheck, gosec, and revive
- Bundled bash script version 1.0.0 with 5-minute lint timeout
Files
Go Linting
Core Principle
More important than any "blessed" set of linters: lint consistently across a codebase.
Consistent linting helps catch common issues and establishes a high bar for code quality without being unnecessarily prescriptive.
Resource Routing
scripts/setup-lint.sh- Run when generating a.golangci.yml, validating the first lint pass, or producing JSON metadata.assets/golangci.yml- Use as the v2 golangci-lint baseline for established projects.
Setup Procedure
1. Create .golangci.yml with scripts/setup-lint.sh or copy assets/golangci.yml 2. Run golangci-lint run ./... 3. If errors appear, fix them category by category (formatting first, then vet, then style) 4. Re-run until clean
After generating .golangci.yml, run golangci-lint config verify --config .golangci.yml to verify the configuration schema before relying on lint results.
---
Minimum Recommended Linters
These linters catch the most common issues while maintaining a high quality bar:
| Linter | Purpose |
|---|---|
| errcheck | Ensure errors are handled |
| goimports | Format code and manage imports |
| revive | Common style mistakes (modern replacement for golint) |
| govet | Analyze code for common mistakes |
| staticcheck | Various static analysis checks |
Note:reviveis the modern, faster successor to the now-deprecatedgolint.
---
Lint Runner: golangci-lint
Use golangci-lint as your lint runner. See the example .golangci.yml from uber-go/guide.
---
Example Configuration
Use assets/golangci.yml as the maintained example. It targets golangci-lint v2 (verified with 2.10.1 on 2026-06-19), keeps goimports under formatters, and enables the core linters plus common production additions.
Running
# Install the version this skill's config is verified against
go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.10.1
# Run all linters
golangci-lint run
# Run on specific paths
golangci-lint run ./pkg/...---
Additional Recommended Linters
Beyond the minimum set, consider these for production projects:
| Linter | Purpose | When to enable |
|---|---|---|
| gosec | Security vulnerability detection | Always for services handling user input |
| ineffassign | Detect ineffectual assignments | Always — catches dead code |
| misspell | Correct common misspellings in comments/strings | Always |
| gocyclo | Cyclomatic complexity threshold | When functions exceed ~15 complexity |
| exhaustive | Ensure switch covers all enum values | When using iota enums |
| bodyclose | Detect unclosed HTTP response bodies | Always for HTTP client code |
---
Nolint Directives
When suppressing a lint finding, always explain why:
//nolint:errcheck // fire-and-forget logging; error is not actionable
_ = logger.Sync()Rules:
- Use
//nolint:lintername— never bare//nolint - Place the comment on the same line as the finding
- Include a justification after
//
---
CI/CD Integration
Run golangci-lint run ./... in CI after tests. Pin the golangci-lint version used by CI so local and release behavior do not drift.
Pre-commit Hook
#!/bin/sh
# .git/hooks/pre-commit
golangci-lint run --new-from-rev=HEAD~1Use --new-from-rev to lint only changed code, keeping the feedback loop fast.
---
Quick Reference
| Task | Command/Action |
|---|---|
| Install golangci-lint | go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.10.1 |
| Run linters | golangci-lint run |
| Run on path | golangci-lint run ./pkg/... |
| Config file | .golangci.yml in project root |
| CI integration | Run golangci-lint run in pipeline |
| Nolint directives | //nolint:name // reason — never bare //nolint |
| CI integration | Use golangci/golangci-lint-action for GitHub Actions |
| Pre-commit | golangci-lint run --new-from-rev=HEAD~1 |
Linter Selection Guidelines
| When you need... | Use |
|---|---|
| Error handling coverage | errcheck |
| Import formatting | goimports |
| Style consistency | revive |
| Bug detection | govet, staticcheck |
| All of the above | golangci-lint with config |
---
Related Skills
- Style foundations: See go-style-core when resolving style questions that linters enforce (formatting, nesting, naming)
- Code review: See go-code-review when combining linter output with a manual review checklist
- Error handling: See go-error-handling when errcheck flags unhandled errors and you need to decide how to handle them
- Testing: See go-testing when running linters alongside tests in CI pipelines
version: "2"
linters:
enable:
# Minimum recommended
- errcheck
- govet
- revive
- staticcheck
# Additional recommended
- bodyclose
- gocyclo
- gosec
- ineffassign
- misspell
settings:
revive:
rules:
- name: exported
gocyclo:
min-complexity: 15
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
issues:
max-issues-per-linter: 0
max-same-issues: 0
formatters:
enable:
- goimports
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
#!/usr/bin/env bash
set -euo pipefail
VERSION="1.0.0"
SCRIPT_NAME="$(basename "$0")"
usage() {
cat <<EOF
$SCRIPT_NAME v$VERSION — Generate .golangci.yml and run initial lint
USAGE
bash $SCRIPT_NAME [options] [local-prefix]
DESCRIPTION
Creates a .golangci.yml with a curated set of linters (errcheck,
goimports, revive, govet, staticcheck) and runs golangci-lint.
If local-prefix is provided, configures goimports to group local
imports separately.
Exits 0 if lint passes, 1 if lint issues found, 2 on error.
OPTIONS
-h, --help Show this help message
-v, --version Show version
--json Output results as JSON
--force Overwrite existing .golangci.yml
--dry-run Print generated config to stdout without writing
--limit N Max lint issue lines in JSON output (default: 50, 0 = unlimited)
ARGUMENTS
local-prefix Module path prefix for goimports grouping
(e.g., github.com/myorg/myrepo)
EXAMPLES
bash $SCRIPT_NAME
bash $SCRIPT_NAME github.com/myorg/myrepo
bash $SCRIPT_NAME --force github.com/myorg/myrepo
bash $SCRIPT_NAME --dry-run github.com/myorg/myrepo
bash $SCRIPT_NAME --json
bash $SCRIPT_NAME --json --limit 20
EOF
}
json_escape() {
local s="$1"
s="${s//\\/\\\\}"
s="${s//\"/\\\"}"
s="${s//$'\t'/\\t}"
s="${s//$'\r'/}"
s="${s//$'\n'/\\n}"
printf '%s' "$s"
}
JSON_OUTPUT=false
FORCE=false
DRY_RUN=false
LIMIT=50
LOCAL_PREFIX=""
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help) usage; exit 0 ;;
-v|--version) echo "$SCRIPT_NAME v$VERSION"; exit 0 ;;
--json) JSON_OUTPUT=true; shift ;;
--force) FORCE=true; shift ;;
--dry-run) DRY_RUN=true; shift ;;
--limit)
if [[ $# -lt 2 ]]; then
echo "error: --limit requires a number" >&2
exit 2
fi
LIMIT="$2"
shift 2
;;
-*) echo "error: unknown option: $1" >&2; usage >&2; exit 2 ;;
*) LOCAL_PREFIX="$1"; shift ;;
esac
done
if ! [[ "$LIMIT" =~ ^[0-9]+$ ]]; then
echo "error: --limit must be a non-negative integer, got: $LIMIT" >&2
exit 2
fi
generate_config() {
cat <<'YAML'
version: "2"
linters:
enable:
# Minimum recommended
- errcheck
- govet
- revive
- staticcheck
# Additional recommended
- bodyclose
- gocyclo
- gosec
- ineffassign
- misspell
settings:
revive:
rules:
- name: exported
gocyclo:
min-complexity: 15
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
issues:
max-issues-per-linter: 0
max-same-issues: 0
formatters:
enable:
- goimports
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
YAML
if [[ -n "$LOCAL_PREFIX" ]]; then
cat <<YAML
settings:
goimports:
local-prefixes:
- ${LOCAL_PREFIX}
YAML
fi
}
if $DRY_RUN; then
generate_config
exit 0
fi
CONFIG_PATH=".golangci.yml"
if [[ -f "$CONFIG_PATH" ]] && ! $FORCE; then
echo "error: $CONFIG_PATH already exists (use --force to overwrite)" >&2
exit 2
fi
generate_config > "$CONFIG_PATH"
LINT_OUTPUT=""
LINT_EXIT=0
if ! command -v golangci-lint &>/dev/null; then
echo "error: golangci-lint is not installed" >&2
exit 2
fi
LINT_OUTPUT=$(golangci-lint run ./... 2>&1) || LINT_EXIT=$?
if $JSON_OUTPUT; then
LINT_TRUNCATED=false
LINT_DISPLAY="$LINT_OUTPUT"
if [[ $LIMIT -gt 0 && -n "$LINT_OUTPUT" ]]; then
LINT_ARR=()
while IFS= read -r line; do
LINT_ARR+=("$line")
done <<< "$LINT_OUTPUT"
if [[ ${#LINT_ARR[@]} -gt $LIMIT ]]; then
LINT_DISPLAY=""
for (( i=0; i<LIMIT; i++ )); do
[[ -n "$LINT_DISPLAY" ]] && LINT_DISPLAY+=$'\n'
LINT_DISPLAY+="${LINT_ARR[$i]}"
done
LINT_TRUNCATED=true
fi
fi
LINT_ESC="$(json_escape "$LINT_DISPLAY")"
CONFIG_ESC="$(json_escape "$CONFIG_PATH")"
PREFIX_ESC="$(json_escape "$LOCAL_PREFIX")"
CREATED=true
HAS_ISSUES=$( [[ $LINT_EXIT -ne 0 ]] && echo true || echo false )
TRUNC_FIELD=""
$LINT_TRUNCATED && TRUNC_FIELD=',"truncated":true'
cat <<EOF
{"config_path":"$CONFIG_ESC","local_prefix":"$PREFIX_ESC","created":$CREATED,"lint_issues":$HAS_ISSUES,"lint_output":"$LINT_ESC"$TRUNC_FIELD}
EOF
else
echo "Created $CONFIG_PATH"
if [[ $LINT_EXIT -ne 0 ]]; then
echo ""
echo "$LINT_OUTPUT"
echo ""
echo "Lint issues found — fix them category by category (formatting first, then vet, then style)."
else
echo "golangci-lint: all clean."
fi
fi
if [[ $LINT_EXIT -ne 0 ]]; then
exit 1
fi
exit 0
Related skills
How it compares
Pick go-linting over manual golangci-lint docs when you need an opinionated .golangci.yml and first lint run in a single step.
FAQ
Which linters does go-linting enable by default?
go-linting enables 10 linters: errcheck, goimports, revive, govet, staticcheck, gosec, ineffassign, misspell, gocyclo, and bodyclose. The generated .golangci.yml sets a 5-minute timeout and zero max-issues-per-linter.
How do you run the go-linting skill?
go-linting ships a bash script (v1.0.0) that generates .golangci.yml and runs an initial golangci-lint pass. Execute it from the Go module root to bootstrap lint configuration and surface findings.
Is Go Linting safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.