skills/setup-golangci-lint/SKILL.md
Quickly set up golangci-lint environment for Go projects. Auto-detect version, create config, integrate CI, generate smart ignore rules, ensure existing code passes safely.
npx skillsauth add alingse/golangci-lint-skills setup-golangci-lintInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Quickly set up a complete golangci-lint environment for Go projects.
Core Principle: Make existing code pass lint by adjusting configuration, do not modify existing code. Only affects new code.
# Check Go version in go.mod (priority)
cat go.mod | grep "^go "
# Check system Go version (reference)
go version
# Check for existing configuration (supports 4 formats)
ls .golangci.* 2>/dev/null || echo "No config"
# Check CI configuration
ls .gitlab-ci.yml .github/workflows/*.yml .circleci/config.yml 2>/dev/null
# Check for Makefile
ls Makefile 2>/dev/null && echo "Has Makefile" || echo "No Makefile"
Select based on Go version in go.mod:
| go.mod Version | golangci-lint Version | |----------------|----------------------| | < 1.20 | v1.x | | >= 1.20 | v2.x (recommended) |
Method 1: Using install script (cross-platform, recommended)
# v2 (recommended)
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin latest
# v1
# curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.59.1
# Verify
$(go env GOPATH)/bin/golangci-lint --version
Method 2: Using go install (requires Go 1.20+)
# v2 (recommended for Go >= 1.20)
go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest
# v1 (for Go < 1.20 or legacy projects)
# go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
# Verify
golangci-lint --version
If the project already has .golangci.yml in v1 format, use the auto-migration tool:
# Automatically migrate v1 config to v2 format
$(go env GOPATH)/bin/golangci-lint migrate --skip-validation
# Notes:
# --skip-validation: Skip validation, convert directly (recommended)
# migrate command will automatically:
# - Add version: 2
# - Convert enable-all/disable-all to linters.default
# - Change linters-settings to linters.settings
# - Change issues.exclude-rules to linters.exclusions.rules
After migration, manually check the configuration to ensure:
linters.default value meets expectations (standard/all/none/fast)# TODO fix later by human comments# TODO reduce thisSkip this step if .golangci.yml already exists.
📌 AI Operation Requirements:
Must first visit official documentation to confirm latest format: https://golangci-lint.run/docs/configuration/file/
Core Principle: Do not modify existing code, only make code pass by adjusting configuration (settings/disable/exclusions)
Formatters Handling:
- First run
gofmt -l .andgoimports -l .to check code format- If both have no output → enable formatters (uncomment)
- If has output → keep commented, add
# TODO format code and enable - X files currently non-compliantaboveWorkflow: Create minimal config → Run lint → Categorize and handle → Add standardized TODO comments
Universal Classification Logic (based on keywords in linter description):
Step 1: Get linter description
$(go env GOPATH)/bin/golangci-lint help <linter-name>Step 2: Categorize based on keywords in description
| Category | Keywords in Description | Action | Example Linters & Descriptions | |----------|------------------------|--------|-------------------------------| | a. Configurable | complexity, long, deeply, count, length, size, max, min, limit | Adjust settings | funlen: "Checks for long functions"<br>gocyclo: "Checks cyclomatic complexity"<br>nestif: "Reports deeply nested if"<br>dogsled: "Checks too many blank identifiers" | | b. Code Style-Manual Confirm | style, format, naming, whitespace, align, order, declaration | disable + TODO | godot: "Check if comments end in period"<br>tagalign: "Check struct tags well aligned"<br>misspell: "Finds commonly misspelled"<br>varnamelen: "Checks variable name length" | | c. Critical Bugs-Suggest Fix | bug, security, error, check, nil, unsafe, detect, inspects | disable + TODO | errcheck: "Checking for unchecked errors"<br>gosec: "Inspects source code for security"<br>staticcheck: "set of rules from staticcheck"<br>nilerr: "returns nil even if error is not nil" | | d. Cannot Modify | (check specific error message, usually involves external constraints) | exclusions | canonicalheader: HTTP header spec (3rd-party APIs)<br>asciicheck: Non-ASCII symbols (Chinese function names) | | e. Can Fix Small | (determined by actual issue count, < 5) | exclude-rules | Any linter with few issues | | f. New Features-Defer | modern, new, latest, replace, simplification, feature | disable + TODO | modernize: "suggest simplifications using modern language"<br>exptostd: "replaced by std functions"<br>usestdlibvars: "use variables from standard library" |
Step 3: Complete Decision Tree
1. Issue count < 5? ├── Yes → Category e (can fix small): exclude-rules └── No → Continue 2. Description has complexity/long/deeply/max/min/limit/length? ├── Yes → Category a (configurable): Prioritize adjusting settings └── No → Continue 3. Specific error caused by external constraints (3rd-party APIs/generated code/Chinese naming)? ├── Yes → Category d (cannot modify): exclusions path exclusion └── No → Continue 4. Description has modern/new/latest/replace/std/simplification? ├── Yes → Category f (new features-defer): disable + TODO └── No → Continue 5. Description has bug/security/error/check/nil/unsafe/detect/inspects? ├── Yes → Category c (critical bugs-suggest fix): disable + TODO └── No → Category b (code style-manual confirm): disable + TODOExample Demonstrations:
| Linter | Description | Keywords | Category | |--------|-------------|----------|----------| | cyclop | "Checks function complexity" | complexity | a | | gocritic | "checks for bugs, performance and style" | bugs (priority) | c | | revive | "replacement of golint" | (no clear keywords) | b | | bodyclose | "Checks whether response body is closed successfully" | error/check | c | | goconst | "Finds repeated strings that could be replaced by a constant" | (style) | b | | fatcontext | "Detects nested contexts" | nested → complexity | a |
Configuration Priority:
- 1st Priority: Adjust
settingsthresholds (e.g., funlen.lines, gocyclo.min-complexity)- 2nd Priority: Use
linters.exclusionspath exclusion (code that cannot be modified)- 3rd Priority: Use
issues.exclude-rulesrule-based exclusion (specific few issues)- Last Resort: Completely
disable(many issues and cannot be resolved via config)Avoid Duplicates: Each linter appears only once, check for duplicates
v2 Minimal Configuration Template (.golangci.yml)
version: "2"
run:
concurrency: 4
timeout: 5m
skip-dirs: [vendor, third_party, testdata, examples, gen-go]
tests: true
output:
format: colored-line-number
print-linter-name: true
linters:
default: all
formatters:
enable:
# TODO format code and enable - 17 files currently non-compliant with goimports
# - gofmt
# - goimports
Formatters Handling: First run
gofmt -l .andgoimports -l .to check, uncomment to enable if both have no output.
Notes:
- Start with minimal configuration, no preset disable
- After running, gradually add
disableandexclusionsbased on errors- Common linters that need adjustment (add as needed):
mnd(magic numbers) → style issues, can be permanently ignoredwsl(whitespace) → style issues, can be permanently ignoredlll(line length) → style issues, can be permanently ignorederr113→ error handling, temporarily ignore and mark TODO
v1 Configuration Template (.golangci.yml)
Note: v1 does not require
versionfield. v2 is recommended.
run:
concurrency: 4
timeout: 5m
skip-dirs: [vendor, testdata]
linters:
enable-all: true
After running, add
disableandexclude-rulesbased on errors.
GitLab CI
lint:
stage: test
image: golang:1.23-alpine
script:
- curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin latest
- $(go env GOPATH)/bin/golangci-lint run --timeout=5m ./...
GitHub Actions
- name: golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: latest
lint: ## Run lint check
golangci-lint run --timeout=5m ./...
lint-fix: ## Auto-fix issues
golangci-lint run --fix --timeout=5m ./...
# Run lint
$(go env GOPATH)/bin/golangci-lint run --timeout=5m ./...
Important: Resolve issues by adjusting configuration, do not modify existing code.
Analyze Based on Error Output:
Linter Name Errors (e.g., unknown linters):
# View supported linters
$(go env GOPATH)/bin/golangci-lint help linters
gomnd → mndgoerr113 → err113execinquery → removedConfiguration Format Errors:
output.formats needs map format, not listoutput.formatAdjust Configuration Based on Actual Errors:
Configuration Priority (try in order):
| Priority | Action | Use Case |
|----------|--------|----------|
| 1️⃣ Highest | Adjust settings thresholds | Linters with config options for complexity/length |
| 2️⃣ Second | linters.exclusions path exclusion | Code that cannot be modified (generated/3rd-party) |
| 3️⃣ Then | issues.exclude-rules rule exclusion | Specific few issues |
| 4️⃣ Last | disable completely | Many issues and no config options |
Category a: Configurable (Prioritize adjusting settings)
linters:
settings:
# Complexity linters: Prioritize adjusting thresholds rather than completely disabling
funlen:
lines: 100 # Default 60, raised to accommodate existing code
statements: 60 # Default 40
gocyclo:
min-complexity: 25 # Default 15
gocognit:
min-complexity: 30 # Default 15
nestif:
min-complexity: 8 # Default 5
# If still have issues after adjusting thresholds, then consider disable
Category b: Code Style-Manual Confirm
linters:
disable:
# TODO code style-confirm whether to disable: Does not affect functionality, requires manual confirmation
- mnd # 47 issues: magic numbers, style issues
- wsl # 39 issues: whitespace, deprecated, replaced by wsl_v5
- wsl_v5 # 50 issues: whitespace v5, code style
- lll # 46 issues: line length limit, style issues
- godot # 3 issues: comment period
- tagalign # 12 issues: struct tag alignment
- tagliatelle # 50 issues: struct tag naming convention
- whitespace # 3 issues: whitespace issues
- goconst # 7 issues: constant extraction suggestion
- prealloc # 2 issues: pre-allocate slice suggestion
- nakedret # 1 issue: naked return
- nlreturn # 9 issues: blank line before return
- inamedparam # 1 issue: named parameter
- varnamelen # 23 issues: variable name length
- nonamedreturns # 2 issues: named return values
- paralleltest # 47 issues: parallel test suggestion
- testpackage # 3 issues: test package naming
- testifylint # 3 issues: testify usage convention
- ireturn # 4 issues: interface return
- intrange # 3 issues: int range loop
- nilnil # 3 issues: nil interface
- nilnesserr # 3 issues: nil error check
- noinlineerr # 3 issues: inline error
- gosmopolitan # 3 issues: internationalization
- usestdlibvars # 1 issue: standard library constants
- unparam # 1 issue: unused parameter
- perfsprint # 9 issues: performance print suggestion
Category c: Critical Bugs-Suggest Fix
linters:
disable:
# TODO critical bugs-suggest fix: Security and error handling issues, recommend gradual fixes
- errcheck # 13 issues: unchecked errors
- gosec # 10 issues: security checks
- staticcheck # 8 issues: static analysis
- rowserrcheck # 3 issues: database rows.Err check
- errchkjson # 4 issues: JSON error check
- errorlint # 1 issue: error handling convention
- errname # 2 issues: error variable naming
- wrapcheck # 44 issues: error wrapping
- noctx # 3 issues: context parameter check
- forcetypeassert # 2 issues: force type assertion
- contextcheck # 4 issues: context passing check
- nilerr # nil error check
- govet # 1 issue: vet check
- unused # 16 issues: unused variables/packages
- err113 # 21 issues: dynamic error definition
- ineffassign # 1 issue: ineffective assignment
- sqlclosecheck # 3 issues: SQL not closed check
- wastedassign # 2 issues: wasted assignment
Category d: Cannot Modify (Path Exclusion)
linters:
exclusions:
rules:
# Generated code (cannot modify)
- path: \.pb\.go|\.gen\.go|\.gen-\w+\.go|\.mock\.go
linters: [all]
# Third-party dependencies (cannot modify)
- path: vendor/|third_party/
linters: [all]
# Example code (optionally modifiable)
- path: examples/
linters: [all]
issues:
exclude-rules:
# Third-party APIs (cannot modify)
- text: "non-canonical header"
linters: [canonicalheader]
# Chinese function names (business requirement, cannot modify)
- text: "ID.*must match"
linters: [asciicheck]
# Internal project using internal packages (business requirement)
- text: "import of package"
linters: [depguard]
Category e: Can Fix Small (Few Specific Issues)
issues:
exclude-rules:
# Specific business scenarios (cannot modify)
- text: "G101: potential hardcoded credential"
path: config/.*\.go
linters: [gosec]
# Relax for test files
- path: _test\.go
linters: [errcheck, gosec, contextcheck]
# Relax for main function
- path: cmd/
linters: [gocyclo, funlen, errcheck]
Category f: New Features-Defer
linters:
disable:
# TODO new features-defer: Does not affect current code, can be selectively enabled later
- modernize # 12 issues: modern Go syntax suggestions
- revive # 48 issues: revive ruleset
- gocritic # 10 issues: code style suggestions
- godoclint # 3 issues: godoc format
- gomoddirectives # module directive check
- dogsled # blank identifier count
- embeddedstructfieldcheck # 2 issues: embedded field blank lines
- exhaustruct # 49 issues: struct field completeness
- forbidigo # 6 issues: forbid specific functions
- gochecknoglobals # 15 issues: global variable check
- gochecknoinits # 2 issues: init function check
- godox # 2 issues: TODO/FIXME markers
- nolintlint # 1 issue: nolint comment check
Goal: Existing code passes lint, do not modify existing code, new code must follow rules.
# Run again to ensure pass
$(go env GOPATH)/bin/golangci-lint run --timeout=5m ./...
# Or use make
make lint
# golangci-lint Configuration Complete
## Environment Information
- Go Version (go.mod): go 1.23
- golangci-lint Version: v2.8.0
## Configuration
- Created: .golangci.yml (version: 2)
- Initial Config: linters.default: all (minimal config)
## Issue Handling
### Handling Priority
| Priority | Method | Linters |
|----------|--------|---------|
| 1️⃣ Adjust settings | Threshold tuning | funlen, gocyclo, gocognit, nestif |
| 2️⃣ exclusions | Path exclusion | Generated code, 3rd-party dependencies, specific APIs |
| 3️⃣ exclude-rules | Rule exclusion | Test files, specific business scenarios |
| 4️⃣ disable | Completely disable | Linters with many issues |
### Linter Category Statistics
| Category | Count | Description |
|----------|-------|-------------|
| a. Configurable | 4 | Prioritize adjusting settings thresholds |
| b. Code Style-Manual Confirm | 26 | Style issues, need confirmation whether to disable |
| c. Critical Bugs-Suggest Fix | 18 | Security/error handling, recommend fixing |
| d. Cannot Modify | - | Path exclusion (external constraints) |
| e. Can Fix Small | - | Issues exclusion (few issues) |
| f. New Features-Defer | 13 | New features, consider later |
### Settings Threshold Adjustments
```yaml
linters:
settings:
funlen:
lines: 100 # Default 60
statements: 60 # Default 40
gocyclo:
min-complexity: 25 # Default 15
gocognit:
min-complexity: 30 # Default 15
nestif:
min-complexity: 8 # Default 5
.pb.go, .gen.go, .mock.govendor/, third_party/examples/non-canonical header (canonicalheader)ID.*must match (asciicheck)make lint checks
## Notes
1. **Core Principle**: **Do not modify existing code**, only adjust configuration to make code pass lint
2. **v2 Configuration Format**: Must add `version: 2`, use `linters.default` instead of `enable-all`
3. **Do Not Modify Existing Configuration**
4. **Style Issues Can Be Permanently Ignored**: Function length, cyclomatic complexity, etc. do not affect functionality
5. **Critical Issues Need Fix Reminders**: errcheck, gosec, staticcheck, etc. (exclude via config, do not fix directly)
6. **New Code Must Not Bypass Checks**
7. **CI Needs Sufficient Resources**: Recommend at least 2GB memory
## Related Resources
- [Official Documentation](https://golangci-lint.run/)
- [Supported Linters](https://golangci-lint.run/usage/linters/)
development
--- name: upgrade-golangci-lint description: Upgrade golangci-lint to the latest version, automatically migrate config (v1→v2), run lint and supplement config to make code pass. Core principle: only adjust config, do not modify code. --- # golangci-lint Version Upgrade Upgrade golangci-lint to the latest version, handle configuration migration, and adjust configuration to make existing code pass lint checks. > **Core Principle**: Make existing code pass lint by adjusting configuration, **do n
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.
development
Maintainer workflow for OpenClaw releases, prereleases, changelog release notes, and publish validation. Use when Codex needs to prepare or verify stable or beta release steps, align version naming, assemble release notes, check release auth requirements, or validate publish-time commands and artifacts.
development
Run, watch, debug, and extend OpenClaw QA testing with qa-lab and qa-channel. Use when Codex needs to execute the repo-backed QA suite, inspect live QA artifacts, debug failing scenarios, add new QA scenarios, or explain the OpenClaw QA workflow. Prefer the live OpenAI lane with regular openai/gpt-5.4 in fast mode; do not use gpt-5.4-pro or gpt-5.4-mini unless the user explicitly overrides that policy.