{"id":"6cbbbcb7-03d6-45f8-9c33-d78a15d52ee1","entityType":"agent","slug":"clawhub-samber-golang-lint","name":"golang-lint","canonicalUrl":"https://www.xpersona.co/agent/clawhub-samber-golang-lint","canonicalPath":"/agent/clawhub-samber-golang-lint","generatedAt":"2026-10-11T03:56:36.078Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-11T01:49:39.382Z","emptyReason":null},"description":"Linting best practices and golangci-lint configuration for Golang projects — running linters, configuring .golangci.yml, suppressing warnings with nolint directives, interpreting lint output, and selecting linters. Use when configuring golangci-lint, asking about lint warnings or nolint suppressions, setting up code quality tooling, or choosing linters. Also use when the user mentions golangci-lint, go vet, staticcheck, or revive. Skill: golang-lint Owner: samber Summary: Linting best practices and golangci-lint configuration for Golang projects — running linters, configuring .golangci.yml, suppressing warnings with nolint directives, interpreting lint output, and selecting linters. Use when configuring golangci-lint, asking about lint warnings or nolint suppressions, setting up code quality tooling, or choosing linters. Also use when the user","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.2K downloads reported by the source. Last updated 10/11/2026.","installCommand":"clawhub skill install s173arkhs3131fq5jf769qq75583hdgt:golang-lint","sourceUrl":"https://clawhub.ai/samber/golang-lint","homepage":"https://clawhub.ai/samber/skills/golang-lint","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/samber/golang-lint","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/samber/skills/golang-lint","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":62,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Linting best practices and golangci-lint configuration for Golang projects — running linters, configuring .golangci.yml, suppressing warnings with nolint direct"},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-11T01:49:39.382Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T01:49:39.382Z","emptyReason":null},"stars":null,"forks":null,"downloads":1200,"packageName":null,"latestVersion":"1.4.0","tractionLabel":"1.2K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T01:49:39.314Z","emptyReason":null},"lastUpdatedAt":"2026-10-11T01:49:39.382Z","lastCrawledAt":"2026-10-11T01:49:39.314Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-12T01:49:39.314Z","lastVerifiedAt":null,"highlights":[{"version":"1.4.0","createdAt":"2026-08-21T16:21:58.465Z","changelog":"- Added explicit support for multi-agent orchestration and ultracode, enabling fan-out for parallel legacy codebase cleanup. - Clarified compatibility section for Claude Code and Codex. - Introduced a new \"paths\" field to specify lint-relevant files. - Updated metadata version to 1.4.0. - Removed obsolete skill-card.md.","fileCount":6,"zipByteSize":14823},{"version":"1.2.2","createdAt":"2026-06-10T22:22:09.695Z","changelog":"- Bumped version to 1.2.2. - Added explicit dependency installation instructions for golangci-lint using `go install`. - Removed the file `skill-card.md`. - No changes to core functionality or major documentation structure.","fileCount":6,"zipByteSize":14733},{"version":"1.2.1","createdAt":"2026-05-22T18:58:23.723Z","changelog":"- Updated recommended default to \"48 linters enabled\" in overview and clarified linter numbers in configuration sections. - Improved description for clarity and simplified scope. - Revised security linter suppression rule to include \"gosec\" as unsuppressable without strong reason. - Clarified that in golangci-lint v2, the default `run.timeout` is `0` (no timeout). - Updated advice for excluding paths in large repos to use `linters.exclusions.paths` and `formatters.exclusions.paths`.","fileCount":6,"zipByteSize":14701},{"version":"1.1.2","createdAt":"2026-04-30T13:05:13.202Z","changelog":"- Expanded and clarified documentation in SKILL.md, providing detailed best practices for using golangci-lint on Go projects. - Added mode descriptions for setup, coding, and interpreting/fixing lint issues, including guidance on running in parallel using sub-agents. - Included quick references for running, fixing, formatting, and configuring golangci-lint, as well as Makefile targets for common tasks. - Outlined strict rules for suppressing lint warnings and how to justify and enforce them. - Provided workflow recommendations, troubleshooting tips for common linter issues, and cross-references to related skills. - No changes to functionality; this update focuses on comprehensive documentation improvements.","fileCount":5,"zipByteSize":12543}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s173arkhs3131fq5jf769qq75583hdgt:golang-lint","setupComplexity":"medium","setupSteps":["Setup complexity is MEDIUM. Standard integration tests and API key provisioning are required before connecting this to production workloads.","Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-lint/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-lint/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-lint/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-lint/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-lint/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-lint/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-11T03:56:36.071Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-lint/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-lint/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-lint/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-lint/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"high","updatedAt":"2026-10-11T01:49:39.382Z","emptyReason":null},"readme":"Skill: golang-lint\n\nOwner: samber\n\nSummary: Linting best practices and golangci-lint configuration for Golang projects — running linters, configuring .golangci.yml, suppressing warnings with nolint directives, interpreting lint output, and selecting linters. Use when configuring golangci-lint, asking about lint warnings or nolint suppressions, setting up code quality tooling, or choosing linters. Also use when the user mentions golangci-lint, go vet, staticcheck, or revive.\n\nTags: latest:1.4.0\n\nVersion history:\n\nv1.4.0 | 2026-08-21T16:21:58.465Z | auto\n\n- Added explicit support for multi-agent orchestration and ultracode, enabling fan-out for parallel legacy codebase cleanup.\n- Clarified compatibility section for Claude Code and Codex.\n- Introduced a new \"paths\" field to specify lint-relevant files.\n- Updated metadata version to 1.4.0.\n- Removed obsolete skill-card.md.\n\nv1.2.2 | 2026-06-10T22:22:09.695Z | auto\n\n- Bumped version to 1.2.2.\n- Added explicit dependency installation instructions for golangci-lint using `go install`.\n- Removed the file `skill-card.md`.\n- No changes to core functionality or major documentation structure.\n\nv1.2.1 | 2026-05-22T18:58:23.723Z | auto\n\n- Updated recommended default to \"48 linters enabled\" in overview and clarified linter numbers in configuration sections.\n- Improved description for clarity and simplified scope.\n- Revised security linter suppression rule to include \"gosec\" as unsuppressable without strong reason.\n- Clarified that in golangci-lint v2, the default `run.timeout` is `0` (no timeout).\n- Updated advice for excluding paths in large repos to use `linters.exclusions.paths` and `formatters.exclusions.paths`.\n\nv1.1.2 | 2026-04-30T13:05:13.202Z | auto\n\n- Expanded and clarified documentation in SKILL.md, providing detailed best practices for using golangci-lint on Go projects.\n- Added mode descriptions for setup, coding, and interpreting/fixing lint issues, including guidance on running in parallel using sub-agents.\n- Included quick references for running, fixing, formatting, and configuring golangci-lint, as well as Makefile targets for common tasks.\n- Outlined strict rules for suppressing lint warnings and how to justify and enforce them.\n- Provided workflow recommendations, troubleshooting tips for common linter issues, and cross-references to related skills.\n- No changes to functionality; this update focuses on comprehensive documentation improvements.\n\nArchive index:\n\nArchive v1.4.0: 6 files, 14823 bytes\n\nFiles: evals/evals.json (16136b), references/linter-reference.md (7930b), references/nolint-directives.md (2531b), skill-card.md (2108b), SKILL.md (7355b), _meta.json (130b)\n\nFile v1.4.0:SKILL.md\n\n---\nname: golang-lint\ndescription: \"Linting best practices and golangci-lint configuration for Golang projects — running linters, configuring .golangci.yml, suppressing warnings with nolint directives, interpreting lint output, and selecting linters. Use when configuring golangci-lint, asking about lint warnings or nolint suppressions, setting up code quality tooling, or choosing linters. Also use when the user mentions golangci-lint, go vet, staticcheck, or revive.\"\nuser-invocable: true\nlicense: MIT\ncompatibility: Designed for Claude Code, Codex or similar harness, and for projects using Golang.\nmetadata:\n  author: samber\n  version: \"1.4.0\"\n  openclaw:\n    emoji: \"🧹\"\n    homepage: https://github.com/samber/cc-skills-golang\n    requires:\n      bins:\n        - go\n        - golangci-lint\n    install:\n      - kind: brew\n        formula: golangci-lint\n        bins: [golangci-lint]\nallowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent\npaths:\n  - \"**/*.go\"\n  - \".golangci.yml\"\n---\n\n**Persona:** You are a Go code quality engineer. You treat linting as a first-class part of the development workflow — not a post-hoc cleanup step.\n\n**Orchestration mode:** Fan out the five sub-agents described in the \"Parallelizing Legacy Codebase Cleanup\" section (auto-fix, security linters, error handling, style/formatting, code quality) when adopting linting on a legacy codebase, so independent linter categories are fixed concurrently. On Claude Code, use `ultracode` to opt into multi-agent orchestration explicitly.\n\n**Modes:**\n\n- **Setup mode** — configuring `.golangci.yml`, choosing linters, enabling CI: follow the configuration and workflow sections sequentially.\n- **Coding mode** — writing new Go code: launch a background agent running `golangci-lint run --fix` on the modified files only while the main agent continues implementing the feature; surface results when it completes.\n- **Interpret/fix mode** — reading lint output, suppressing warnings, fixing issues on existing code: start from \"Interpreting Output\" and \"Suppressing Lint Warnings\"; use parallel sub-agents for large-scale legacy cleanup.\n\n**Dependencies:**\n\n- golangci-lint: `go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest`\n\n# Go Linting\n\n## Overview\n\n`golangci-lint` is the standard Go linting tool. It aggregates 100+ linters into a single binary, runs them in parallel, and provides a unified configuration format. Run it frequently during development and always in CI.\n\nEvery Go project MUST have a `.golangci.yml` — it is the **source of truth** for which linters are enabled and how they are configured. See the [recommended configuration](./assets/.golangci.yml) for a production-ready setup with 48 linters enabled.\n\n## Quick Reference\n\n```bash\n# Run all configured linters\ngolangci-lint run ./...\n\n# Auto-fix issues where possible\ngolangci-lint run --fix ./...\n\n# Format code (golangci-lint v2+)\ngolangci-lint fmt ./...\n\n# Run a single linter only\ngolangci-lint run --enable-only govet ./...\n\n# List all available linters\ngolangci-lint linters\n\n# Verbose output with timing info\ngolangci-lint run --verbose ./...\n```\n\n## Configuration\n\nThe [recommended .golangci.yml](./assets/.golangci.yml) provides a production-ready setup with 33 linters. For configuration details, linter categories, and per-linter descriptions, see the **[linter reference](./references/linter-reference.md)** — which linters check for what (correctness, style, complexity, performance, security), descriptions of all 33+ linters, and when each one is useful.\n\n## Suppressing Lint Warnings\n\nUse `//nolint` directives sparingly — fix the root cause first.\n\n```go\n// Good: specific linter + justification\n//nolint:errcheck // fire-and-forget logging, error is not actionable\n_ = logger.Sync()\n\n// Bad: blanket suppression without reason\n//nolint\n_ = logger.Sync()\n```\n\nRules:\n\n1. **//nolint directives MUST specify the linter name**: `//nolint:errcheck` not `//nolint`\n2. **//nolint directives MUST include a justification comment**: `//nolint:errcheck // reason`\n3. **The `nolintlint` linter enforces both rules above** — it flags bare `//nolint` and missing reasons\n4. **NEVER suppress security linters** (gosec, bodyclose, sqlclosecheck) without a very strong reason\n\nFor comprehensive patterns and examples, see **[nolint directives](./references/nolint-directives.md)** — when to suppress, how to write justifications, patterns for per-line vs per-function suppression, and anti-patterns.\n\n## Development Workflow\n\n1. **Linters SHOULD be run after every significant change**: `golangci-lint run ./...`\n2. **Auto-fix what you can**: `golangci-lint run --fix ./...`\n3. **Format before committing**: `golangci-lint fmt ./...`\n4. **Incremental adoption on legacy code**: set `issues.new-from-rev` in `.golangci.yml` to only lint new/changed code, then gradually clean up old code\n\nMakefile targets (recommended):\n\n```makefile\nlint:\n\tgolangci-lint run ./...\n\nlint-fix:\n\tgolangci-lint run --fix ./...\n\nfmt:\n\tgolangci-lint fmt ./...\n```\n\nFor CI pipeline setup (GitHub Actions with `golangci-lint-action`), see the `samber/cc-skills-golang@golang-continuous-integration` skill.\n\n## Interpreting Output\n\nEach issue follows this format:\n\n```\npath/to/file.go:42:10: message describing the issue (linter-name)\n```\n\nThe linter name in parentheses tells you which linter flagged it. Use this to:\n\n- Look up the linter in the [reference](./references/linter-reference.md) to understand what it checks\n- Suppress with `//nolint:linter-name // reason` if it's a false positive\n- Use `golangci-lint run --verbose` for additional context and timing\n\n## Common Issues\n\n| Problem | Solution |\n| --- | --- |\n| \"deadline exceeded\" | Set or increase `run.timeout` in `.golangci.yml`; golangci-lint v2 defaults to no timeout (`0`) |\n| Too many issues on legacy code | Set `issues.new-from-rev: HEAD~1` to lint only new code |\n| Linter not found | Check `golangci-lint linters` — linter may need a newer version |\n| Conflicts between linters | Disable the less useful one with a comment explaining why |\n| v1 config errors after upgrade | Run `golangci-lint migrate` to convert config format |\n| Slow on large repos | Reduce `run.concurrency` or exclude paths with `linters.exclusions.paths` / `formatters.exclusions.paths` |\n\n## Parallelizing Legacy Codebase Cleanup\n\nWhen adopting linting on a legacy codebase, use up to 5 parallel sub-agents to fix independent linter categories simultaneously:\n\n- Sub-agent 1: Run `golangci-lint run --fix ./...` for auto-fixable issues\n- Sub-agent 2: Fix security linter findings (bodyclose, sqlclosecheck, gosec)\n- Sub-agent 3: Fix error handling issues (errcheck, nilerr, wrapcheck)\n- Sub-agent 4: Fix style and formatting (gofumpt, goimports, revive)\n- Sub-agent 5: Fix code quality (gocritic, unused, ineffassign)\n\n## Cross-References\n\n- → See `samber/cc-skills-golang@golang-continuous-integration` skill for CI pipeline with golangci-lint-action\n- → See `samber/cc-skills-golang@golang-code-style` skill for style rules that linters enforce\n- → See `samber/cc-skills-golang@golang-security` skill for SAST tools beyond linting (gosec, govulncheck)\n- → See `samber/cc-skills-golang@golang-continuous-integration` skill for automated AI-driven code review in CI using these guidelines\n\nFile v1.4.0:_meta.json\n\n{\n  \"ownerId\": \"kn72rhnkwjfeex9wr1n7y24qa983cjn3\",\n  \"slug\": \"golang-lint\",\n  \"version\": \"1.4.0\",\n  \"publishedAt\": 1787329318465\n}\n\nFile v1.4.0:references/linter-reference.md\n\n# Linter Reference\n\ngolangci-lint v2 uses a `.golangci.yml` with `version: \"2\"` at the project root.\n\nKey sections of `.golangci.yml`:\n\n- **`run`** — concurrency, timeout, test inclusion, directory exclusions\n- **`linters.enable`** / **`linters.disable`** — which linters are active\n- **`linters.settings`** — per-linter thresholds and options\n- **`formatters`** — code formatters (gofmt, gofumpt)\n- **`issues`** — output limits, exclusion rules\n\nTo add a linter: add it to `linters.enable` and optionally configure it in `linters.settings`.\n\nTo disable a linter: move it to `linters.disable` with a comment explaining why.\n\n## Linter Categories\n\nThe recommended configuration enables linters across these domains:\n\n| Domain | Linters | Catches |\n| --- | --- | --- |\n| Correctness | govet, staticcheck, unused, errcheck, errorlint, nilerr, forcetypeassert, copyloopvar, durationcheck, reassign | Bugs, unchecked errors, stdlib misuse |\n| Style | gocritic, revive, wsl_v5, whitespace, godot, misspell, dupword, predeclared, errname, asciicheck | Readability, naming, consistency |\n| Complexity | gocyclo, nestif, funlen, dupl | Overly complex or duplicated code |\n| Performance | perfsprint, unconvert, ineffassign, goconst | Conversions, string ops, dead assigns |\n| Security | gosec, bidichk, bodyclose, noctx, containedctx, fatcontext, sqlclosecheck, rowserrcheck | Security issues, resource leaks (HTTP, SQL) |\n| Logging | sloglint, loggercheck | Structured log consistency |\n| Testing | thelper, paralleltest, testifylint, usetesting | Test hygiene and best practices |\n| Modernization | modernize, exptostd, intrange, usestdlibvars, exhaustive, nolintlint | Modern Go idioms, lint hygiene |\n| Formatting | gofmt, gofumpt | Code formatting |\n\nAll linters are enabled in the [recommended .golangci.yml](../assets/.golangci.yml), organized by domain.\n\n### Correctness & Safety\n\n- **govet** — Go's built-in checker: copylocks, printf format mismatches, struct tag validation, context stored in structs, unreachable code, nil dereferences\n- **staticcheck** — Extensive static analysis: deprecated APIs, common mistakes, unnecessary code, simplifications, misuse of standard library\n- **unused** — Detects unused variables, functions, types, and struct fields\n- **errcheck** — Ensures all error returns are checked, including type assertions (configured with `check-type-assertions: true`)\n- **nilerr** — Detects returning nil error when `err` is non-nil (common source of silent failures)\n- **forcetypeassert** — Flags type assertions without the comma-ok check (`v := x.(T)` instead of `v, ok := x.(T)`)\n- **copyloopvar** — Detects loop variable copy issues (Go 1.22+)\n- **errorlint** — Enforces correct use of `errors.Is`/`errors.As` and `%w` wrapping (Go 1.13+ error wrapping)\n- **durationcheck** — Detects `time.Duration * time.Duration` multiplication bugs (e.g., `2 * time.Second * time.Minute` produces nanoseconds squared, not seconds)\n- **reassign** — Detects reassignment of package-level variables outside `init()`, which hides state mutations\n\n### Style & Readability\n\n- **gocritic** — Opinionated style checks: unnecessary conversions, range copies, append-assign patterns, redundant code\n- **revive** — Naming conventions for exported types, unexported returns, receiver naming, error naming, stuttered package names\n- **wsl_v5** — Whitespace and blank line rules for visual grouping and readability\n- **whitespace** — Detects trailing whitespace and unnecessary blank lines in function bodies\n- **godot** — Ensures exported-symbol comments end with a period\n- **misspell** — Catches common English misspellings in identifiers and comments\n- **predeclared** — Flags shadowing of Go built-in identifiers (e.g., naming a variable `len`, `cap`, `error`)\n- **errname** — Enforces error naming conventions: error types suffixed with `Error` (e.g., `DecodeError`), error variables prefixed with `Err` (e.g., `ErrNotFound`)\n- **dupword** — Detects duplicate words in comments and strings (e.g., \"the the\", \"is is\") — often copy-paste artifacts\n- **asciicheck** — Flags non-ASCII identifiers that enable homoglyph/trojan source attacks (visually identical but different Unicode codepoints)\n\n### Complexity\n\n- **gocyclo** — Cyclomatic complexity threshold (configured: 13). Functions exceeding this should be split\n- **nestif** — Detects deeply nested if/else chains that harm readability\n- **funlen** — Function length limits (configured: 120 lines, 80 statements)\n- **dupl** — Code duplication detection (configured: 100 token threshold)\n\n### Performance\n\n- **perfsprint** — Suggests faster alternatives to `fmt.Sprintf` (e.g., `strconv.Itoa` instead of `fmt.Sprintf(\"%d\", n)`)\n- **unconvert** — Detects unnecessary type conversions (e.g., `int(x)` when `x` is already `int`)\n- **ineffassign** — Detects assignments to variables that are never subsequently read\n- **goconst** — Detects repeated string/number literals that should be extracted to constants (configured: min 3 chars, min 4 occurrences)\n\n### Security & Resources\n\n- **gosec** — Security scanner: SQL injection, hardcoded credentials, weak crypto, path traversal, unsafe usage, and 50+ other rules. The primary SAST tool in the config — never suppress without strong justification.\n- **bidichk** — Detects dangerous bidirectional Unicode sequences (CVE-2021-42574 trojan source attack — code that looks safe but executes differently)\n- **noctx** — Detects HTTP requests sent without `context.Context` (prevents proper timeouts and cancellation)\n- **containedctx** — Flags `context.Context` stored in struct fields instead of passed as a parameter (anti-pattern per Go docs)\n- **fatcontext** — Detects `context.WithValue`/`WithCancel` in loops, creating unbounded context chains that grow each iteration and cause memory leaks\n- **bodyclose** — Ensures HTTP response bodies are closed (unclosed bodies leak connections)\n- **sqlclosecheck** — Ensures `sql.Rows` and `sql.Stmt` are closed after use\n- **rowserrcheck** — Ensures `sql.Rows.Err()` is checked after iteration\n\n### Logging\n\n- **sloglint** — Enforces consistent `log/slog` code style: proper key-value pairing, message formatting, and level usage\n- **loggercheck** — Validates key-value pair formatting for structured loggers (zap, slog, logr) — detects odd numbers of args, missing keys\n\n### Testing\n\n- **thelper** — Ensures test helpers call `t.Helper()` so failures report the correct call site\n- **paralleltest** — Detects tests and subtests missing `t.Parallel()` calls\n- **testifylint** — Enforces testify best practices (e.g., `assert.Equal(t, expected, actual)` over `assert.True(t, expected == actual)`)\n- **usetesting** — Suggests `t.Setenv`/`t.TempDir` instead of `os.Setenv`/`os.MkdirTemp` in tests (automatic cleanup, proper isolation)\n\n### Modernization & Meta\n\n- **modernize** — Detects code that can be rewritten using newer Go features (requires golangci-lint v2.6.0+)\n- **exptostd** — Detects `golang.org/x/exp/` functions that now have stdlib equivalents (e.g., `slices`, `maps`, `cmp` packages added in Go 1.21)\n- **intrange** — Suggests `range N` over C-style `for i := 0; i < N; i++` loops (Go 1.22+)\n- **usestdlibvars** — Replaces hardcoded strings/numbers with stdlib constants (e.g., `http.MethodGet` instead of `\"GET\"`)\n- **exhaustive** — Ensures switch statements on enum types cover all possible values\n- **nolintlint** — Enforces proper `//nolint` directive usage: requires linter name and justification comment (configured with `require-explanation` and `require-specific`)\n\n### Formatting\n\nFormatters run via `golangci-lint fmt ./...`:\n\n- **gofmt** — Standard Go formatter (canonical formatting)\n- **gofumpt** — Stricter formatter with extra rules (configured with `extra-rules: true`): consistent empty lines, grouped imports, simplified code patterns\n\nFile v1.4.0:references/nolint-directives.md\n\n# Nolint Directives\n\n## Syntax\n\n```go\n//nolint:lintername // justification explaining why this suppression is needed\n```\n\nPlace the directive on the same line as the flagged code, or on the line immediately above it.\n\n## Rules\n\n1. **MUST specify the linter name** — bare `//nolint` suppresses all linters on that line and makes it impossible to track what is being suppressed\n2. **MUST add a justification comment** — future readers (and your future self) need to understand why\n3. **The `nolintlint` linter enforces both rules** — it will flag bare `//nolint` and missing reasons\n4. **MUST fix the root cause before suppressing** — only suppress after confirming the issue is a false positive or an intentional pattern\n\n## Examples\n\n```go\n// Specific linter with reason\n//nolint:errcheck // fire-and-forget logging, error not actionable\n_ = logger.Sync()\n\n// Type assertion is safe because preceding type switch guarantees the type\nv := x.(MyType) //nolint:forcetypeassert // guaranteed by type switch on line 42\n\n// Orchestration function has inherent complexity\n//nolint:gocyclo // orchestration function coordinating 8 subsystems\nfunc orchestrate() error {\n\n// Table-driven test with many cases\n//nolint:funlen // table-driven test, length is proportional to case count\nfunc TestParser(t *testing.T) {\n\n// Intentional parallel structure is clearer than abstracting\n//nolint:dupl // intentional parallel structure for readability\n```\n\n## Multiple Linters\n\nSuppress multiple linters on one line with comma separation:\n\n```go\n//nolint:errcheck,gosec // fire-and-forget in test helper\n```\n\n## When to Suppress vs. When to Fix\n\n**Fix** (almost always):\n\n- `errcheck` — check the error, even if just logging it\n- `govet` — these are usually real bugs\n- `staticcheck` — deprecated API usage, logic errors\n- `bodyclose`, `sqlclosecheck` — resource leaks are real issues\n\n**Suppress** (with justification):\n\n- `funlen` — table-driven tests with many cases\n- `gocyclo` — orchestration functions where splitting would obscure the flow\n- `dupl` — intentional parallel structure that is clearer than an abstraction\n- `exhaustive` — when a default case intentionally handles remaining values\n- `goconst` — when extracting to a constant would reduce clarity (e.g., test assertions)\n\n**Never suppress without strong justification**:\n\n- Security linters (`bodyclose`, `sqlclosecheck`, `rowserrcheck`) — these catch real resource leaks\n- `errcheck` on production code paths — unchecked errors cause silent failures\n\nFile v1.4.0:skill-card.md\n\n## Description:\n\nLinting best practices and golangci-lint configuration for Go projects, including running linters, configuring .golangci.yml, suppressing warnings with nolint directives, interpreting lint output, and selecting linters.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[samber](https://clawhub.ai/user/samber)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and engineers use this skill to set up golangci-lint, interpret and fix lint findings, write disciplined nolint suppressions, and adopt linting workflows in Go codebases.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Installing golangci-lint with an unpinned latest version can change lint behavior over time.\n\nMitigation: Pin and review the golangci-lint version used by local setup and CI.\n\nRisk: Auto-fix commands can modify Go code in ways that still need developer review.\n\nMitigation: Review diffs and run the relevant test suite before accepting --fix output.\n\nRisk: Using the skill outside Go linting work may produce irrelevant guidance.\n\nMitigation: Invoke it for Go linting, golangci-lint configuration, lint-output interpretation, or nolint guidance.\n\n## Reference(s):\n\n- [Project homepage](https://github.com/samber/cc-skills-golang)\n- [Linter Reference](references/linter-reference.md)\n- [Nolint Directives](references/nolint-directives.md)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, Code, Shell commands, Configuration, Guidance]\n\n**Output Format:** [Markdown with inline Go, YAML, Makefile, and shell snippets]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May propose golangci-lint commands, .golangci.yml changes, nolint directives, and cleanup plans for Go files.]\n\n## Skill Version(s):\n\n1.4.0 (source: release evidence and frontmatter)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v1.4.0:evals/evals.json\n\n[\n  {\n    \"id\": 1,\n    \"name\": \"nolint-directive-specificity\",\n    \"description\": \"Tests that nolint directives specify the linter name and include a justification — never bare //nolint\",\n    \"prompt\": \"I have a Go function that triggers several lint warnings. I want to suppress them. Write the nolint directives for these cases:\\n\\n1. A logger.Sync() call where the error is intentionally ignored\\n2. A type assertion that is guaranteed safe by a preceding type switch\\n3. A function with cyclomatic complexity of 15 that orchestrates 6 subsystems\\n4. A table-driven test function that is 200 lines long\\n5. A deprecated API call that we can't migrate yet\\n\\nShow the code with proper suppression directives.\",\n    \"trap\": \"Model uses bare //nolint without specifying the linter name, or omits the justification comment. May also use //nolint at the file level instead of per-line.\",\n    \"assertions\": [\n      {\n        \"id\": \"1.1\",\n        \"text\": \"Every //nolint directive specifies the linter name (e.g., //nolint:errcheck, //nolint:gocyclo) — NO bare //nolint without a linter name\"\n      },\n      {\n        \"id\": \"1.2\",\n        \"text\": \"Every //nolint directive includes a justification comment after // (e.g., //nolint:errcheck // fire-and-forget logging)\"\n      },\n      {\n        \"id\": \"1.3\",\n        \"text\": \"The type assertion uses //nolint:forcetypeassert with an explanation referencing why the assertion is safe\"\n      },\n      {\n        \"id\": \"1.4\",\n        \"text\": \"The long test function uses //nolint:funlen with a justification like 'table-driven test, length proportional to case count'\"\n      },\n      {\n        \"id\": \"1.5\",\n        \"text\": \"The cyclomatic complexity suppression uses //nolint:gocyclo with a justification about orchestration\"\n      }\n    ]\n  },\n  {\n    \"id\": 2,\n    \"name\": \"nolint-fix-vs-suppress-judgment\",\n    \"description\": \"Tests judgment about when to fix vs when to suppress — security and correctness linters should almost never be suppressed\",\n    \"prompt\": \"My Go codebase has these lint warnings. For each one, should I fix the code or suppress the warning? Explain.\\n\\n1. `bodyclose: response body not closed` on an HTTP client call\\n2. `funlen: function too long (150 lines)` on a table-driven test\\n3. `errcheck: error return not checked` on a database query in a request handler\\n4. `dupl: duplicate code block` on two similar but intentionally parallel handler functions\\n5. `sqlclosecheck: rows not closed` on a database query\\n6. `goconst: string 'application/json' repeated 4 times` in test assertions\",\n    \"trap\": \"Model suppresses bodyclose, errcheck on production DB code, or sqlclosecheck — these are real bugs, not style issues. Should only suppress funlen, dupl, and goconst with justifications.\",\n    \"assertions\": [\n      {\n        \"id\": \"2.1\",\n        \"text\": \"Recommends FIXING bodyclose — unclosed HTTP response bodies leak connections, this is a real resource leak\"\n      },\n      {\n        \"id\": \"2.2\",\n        \"text\": \"Recommends SUPPRESSING funlen on the table-driven test — length is proportional to test case count, splitting would be worse\"\n      },\n      {\n        \"id\": \"2.3\",\n        \"text\": \"Recommends FIXING errcheck on the database query — unchecked errors in production request handlers cause silent failures\"\n      },\n      {\n        \"id\": \"2.4\",\n        \"text\": \"Recommends SUPPRESSING dupl on intentional parallel structure — with a justification that the parallel pattern is clearer than abstracting\"\n      },\n      {\n        \"id\": \"2.5\",\n        \"text\": \"Recommends FIXING sqlclosecheck — unclosed sql.Rows leak database connections\"\n      },\n      {\n        \"id\": \"2.6\",\n        \"text\": \"Recommends SUPPRESSING goconst in tests — extracting 'application/json' to a constant in tests would reduce clarity\"\n      }\n    ]\n  },\n  {\n    \"id\": 3,\n    \"name\": \"golangci-yml-version-2-structure\",\n    \"description\": \"Tests knowledge of golangci-lint v2 config structure: version field, linters.enable/disable, formatters section\",\n    \"prompt\": \"Create a .golangci.yml configuration file for a Go project. Enable at least govet, staticcheck, errcheck, and gofumpt. Set the timeout to 5 minutes and configure errcheck to also check type assertions.\",\n    \"trap\": \"Model uses golangci-lint v1 config format (missing version: \\\"2\\\", using enable-all/disable-all, missing formatters section, putting gofumpt in linters instead of formatters).\",\n    \"assertions\": [\n      {\n        \"id\": \"3.1\",\n        \"text\": \"Config file has version: \\\"2\\\" at the top — golangci-lint v2 requires this field\"\n      },\n      {\n        \"id\": \"3.2\",\n        \"text\": \"Linters are listed under linters.enable (not enable-all with exclusions) — explicit listing is the recommended approach\"\n      },\n      {\n        \"id\": \"3.3\",\n        \"text\": \"gofumpt is configured under formatters.enable, NOT under linters.enable — formatters are a separate section in v2\"\n      },\n      {\n        \"id\": \"3.4\",\n        \"text\": \"errcheck has check-type-assertions: true in linters.settings.errcheck\"\n      },\n      {\n        \"id\": \"3.5\",\n        \"text\": \"Timeout is set under run.timeout: 5m\"\n      }\n    ]\n  },\n  {\n    \"id\": 4,\n    \"name\": \"linter-categories-correctness-vs-style\",\n    \"description\": \"Tests understanding of linter domains — which linters catch bugs vs which catch style issues\",\n    \"prompt\": \"I'm setting up golangci-lint for a new Go project and can only enable 10 linters due to team constraints. Which 10 should I prioritize and why? Categorize them.\",\n    \"trap\": \"Model prioritizes style linters (revive, godot, misspell) over correctness linters (govet, staticcheck, errcheck, nilerr). May also include deprecated or redundant linters.\",\n    \"assertions\": [\n      {\n        \"id\": \"4.1\",\n        \"text\": \"Includes govet and staticcheck — these are the highest-value correctness linters that catch real bugs\"\n      },\n      {\n        \"id\": \"4.2\",\n        \"text\": \"Includes errcheck — unchecked errors are the most common source of silent failures in Go\"\n      },\n      {\n        \"id\": \"4.3\",\n        \"text\": \"Prioritizes correctness/safety linters over style linters — bug-finding tools provide more value than formatting preferences\"\n      },\n      {\n        \"id\": \"4.4\",\n        \"text\": \"Includes at least one security linter (bodyclose, gosec, or sqlclosecheck) for resource leak prevention\"\n      },\n      {\n        \"id\": \"4.5\",\n        \"text\": \"Does NOT include both gocyclo and cyclop (redundant) or both gocognit and gocyclo (overlapping complexity checkers)\"\n      }\n    ]\n  },\n  {\n    \"id\": 5,\n    \"name\": \"legacy-codebase-incremental-adoption\",\n    \"description\": \"Tests the new-from-rev strategy for adopting linters on legacy code without drowning in warnings\",\n    \"prompt\": \"We have a large legacy Go codebase with 2000+ lint warnings. We want to adopt golangci-lint but can't fix everything at once. How should we approach this?\",\n    \"trap\": \"Model suggests suppressing all existing warnings with //nolint directives, or disabling linters until the code is clean. Doesn't know about new-from-rev for incremental adoption.\",\n    \"assertions\": [\n      {\n        \"id\": \"5.1\",\n        \"text\": \"Recommends setting issues.new-from-rev (e.g., HEAD~1 or main) in .golangci.yml to only lint new/changed code\"\n      },\n      {\n        \"id\": \"5.2\",\n        \"text\": \"Does NOT suggest adding //nolint directives to all 2000+ existing warnings — that's unmaintainable\"\n      },\n      {\n        \"id\": \"5.3\",\n        \"text\": \"Suggests gradually cleaning up old code over time while enforcing quality on new code\"\n      },\n      {\n        \"id\": \"5.4\",\n        \"text\": \"Suggests running golangci-lint run --fix for auto-fixable issues as a quick first pass\"\n      },\n      {\n        \"id\": \"5.5\",\n        \"text\": \"Mentions using parallel sub-agents or batching fixes by linter category (security, error handling, style) to tackle cleanup efficiently\"\n      }\n    ]\n  },\n  {\n    \"id\": 6,\n    \"name\": \"interpreting-lint-output-format\",\n    \"description\": \"Tests ability to read lint output format and use the linter name for targeted investigation or suppression\",\n    \"prompt\": \"I ran golangci-lint and got this output:\\n\\n```\\nserver/handler.go:42:10: Error return value of `(*DB).Close` is not checked (errcheck)\\nserver/handler.go:55:2: response body must be closed (bodyclose)\\nserver/auth.go:12:6: func `validateToken` is unused (unused)\\nserver/auth.go:30:1: cyclomatic complexity 17 of func `processAuth` is high (> 13) (gocyclo)\\nserver/model.go:5:2: exported type `Model` should have comment or be unexported (revive)\\n```\\n\\nFor each warning, explain what it means and whether I should fix or suppress it.\",\n    \"trap\": \"Model doesn't use the linter name in parentheses to guide its response. May treat all warnings equally instead of recognizing that errcheck and bodyclose are critical while revive is style.\",\n    \"assertions\": [\n      {\n        \"id\": \"6.1\",\n        \"text\": \"Identifies errcheck on DB.Close as a real issue to fix — unchecked database close errors can mask connection problems\"\n      },\n      {\n        \"id\": \"6.2\",\n        \"text\": \"Identifies bodyclose as a critical resource leak to fix — not suppress\"\n      },\n      {\n        \"id\": \"6.3\",\n        \"text\": \"Identifies unused validateToken as dead code to either remove or fix — not suppress\"\n      },\n      {\n        \"id\": \"6.4\",\n        \"text\": \"For gocyclo, evaluates whether processAuth should be refactored or suppressed based on its nature (orchestration function vs genuinely complex logic)\"\n      },\n      {\n        \"id\": \"6.5\",\n        \"text\": \"For revive comment warning, correctly identifies it as a style issue that's lower priority than the correctness issues above\"\n      }\n    ]\n  },\n  {\n    \"id\": 7,\n    \"name\": \"disabled-linters-with-rationale\",\n    \"description\": \"Tests understanding of which linters should be disabled and why — the recommended config explicitly disables several with reasons\",\n    \"prompt\": \"A colleague wants to enable these linters in our .golangci.yml: exhaustruct, gochecknoglobals, wrapcheck, mnd (magic number detector), and varnamelen. Should we? Explain your reasoning for each.\",\n    \"trap\": \"Model enables all of them without considering that they are intentionally excluded from the recommended config due to being too noisy, too opinionated, or breaking idiomatic Go patterns.\",\n    \"assertions\": [\n      {\n        \"id\": \"7.1\",\n        \"text\": \"Recommends AGAINST exhaustruct — it requires all struct fields to be set, which breaks Go's zero-value idiom and is extremely noisy\"\n      },\n      {\n        \"id\": \"7.2\",\n        \"text\": \"Recommends AGAINST gochecknoglobals — there are many valid uses for global variables in Go (loggers, registries, etc.) and a blanket ban is too strict\"\n      },\n      {\n        \"id\": \"7.3\",\n        \"text\": \"Recommends AGAINST wrapcheck as a default — it forces wrapping all external errors, which is too noisy and not always appropriate\"\n      },\n      {\n        \"id\": \"7.4\",\n        \"text\": \"Recommends AGAINST mnd — magic number detection is extremely noisy, flagging obvious constants like HTTP status codes\"\n      },\n      {\n        \"id\": \"7.5\",\n        \"text\": \"Recommends AGAINST varnamelen — Go idiomatically favors short variable names, and this linter conflicts with that philosophy\"\n      }\n    ]\n  },\n  {\n    \"id\": 8,\n    \"name\": \"nolintlint-meta-linter\",\n    \"description\": \"Tests knowledge that nolintlint enforces proper nolint directive usage and should be enabled\",\n    \"prompt\": \"I see //nolint directives scattered throughout our Go codebase. Many are bare '//nolint' without specifying which linter or why. How can I enforce proper nolint hygiene automatically?\",\n    \"trap\": \"Model suggests a manual code review process or a custom script instead of enabling the nolintlint linter with require-explanation and require-specific settings.\",\n    \"assertions\": [\n      {\n        \"id\": \"8.1\",\n        \"text\": \"Recommends enabling the nolintlint linter — it automatically enforces nolint directive quality\"\n      },\n      {\n        \"id\": \"8.2\",\n        \"text\": \"Configures nolintlint with require-specific: true to require linter names (not bare //nolint)\"\n      },\n      {\n        \"id\": \"8.3\",\n        \"text\": \"Configures nolintlint with require-explanation: true to require justification comments\"\n      },\n      {\n        \"id\": \"8.4\",\n        \"text\": \"Shows the correct config location: linters.settings.nolintlint in .golangci.yml\"\n      }\n    ]\n  },\n  {\n    \"id\": 9,\n    \"name\": \"multiple-nolint-comma-syntax\",\n    \"description\": \"Tests proper syntax for suppressing multiple linters on one line\",\n    \"prompt\": \"I have a line of Go code that triggers both errcheck and gosec warnings. I've confirmed both are false positives in this specific case. How do I suppress both on the same line?\",\n    \"trap\": \"Model uses two separate //nolint directives on the same line, or uses //nolint without comma separation, or stacks directives on consecutive lines for the same code line.\",\n    \"assertions\": [\n      {\n        \"id\": \"9.1\",\n        \"text\": \"Uses comma-separated linter names in a single directive: //nolint:errcheck,gosec — not two separate //nolint directives\"\n      },\n      {\n        \"id\": \"9.2\",\n        \"text\": \"Includes a justification comment after the directive explaining why both are false positives\"\n      },\n      {\n        \"id\": \"9.3\",\n        \"text\": \"The directive is placed on the same line as the flagged code or the line immediately above it\"\n      }\n    ]\n  },\n  {\n    \"id\": 10,\n    \"name\": \"common-config-issues\",\n    \"description\": \"Tests troubleshooting knowledge for golangci-lint: timeout, v1-to-v2 migration, linter-not-found\",\n    \"prompt\": \"I'm getting these errors with golangci-lint:\\n1. 'deadline exceeded' when running on our large monorepo\\n2. After upgrading to golangci-lint v2, my .golangci.yml throws config errors\\n3. 'linter modernize not found' even though I listed it in enable\\n\\nHow do I fix each?\",\n    \"trap\": \"Model doesn't know about the v2 config migration tool, suggests reinstalling for the linter-not-found issue instead of checking the golangci-lint version, or increases concurrency instead of timeout.\",\n    \"assertions\": [\n      {\n        \"id\": \"10.1\",\n        \"text\": \"For deadline exceeded: recommends increasing run.timeout in .golangci.yml (default is 5m, may need 10m+ for large repos)\"\n      },\n      {\n        \"id\": \"10.2\",\n        \"text\": \"For v1 config errors: recommends running golangci-lint migrate to convert the config format to v2\"\n      },\n      {\n        \"id\": \"10.3\",\n        \"text\": \"For linter not found: recommends checking the golangci-lint version — modernize requires v2.6.0+ or similar newer version\"\n      },\n      {\n        \"id\": \"10.4\",\n        \"text\": \"Mentions golangci-lint linters command to check available linters in the installed version\"\n      }\n    ]\n  },\n  {\n    \"id\": 11,\n    \"name\": \"formatter-vs-linter-distinction\",\n    \"description\": \"Tests that formatters (gofumpt, gofmt) are configured in the formatters section, not the linters section, and use the fmt subcommand\",\n    \"prompt\": \"I want to enforce consistent code formatting in my Go project using golangci-lint. I want gofumpt with extra rules. How do I set it up?\",\n    \"trap\": \"Model puts gofumpt in the linters.enable section instead of formatters.enable (v2 distinction), or doesn't mention the golangci-lint fmt subcommand for formatting.\",\n    \"assertions\": [\n      {\n        \"id\": \"11.1\",\n        \"text\": \"Configures gofumpt under formatters.enable, NOT linters.enable — formatters are a separate section in golangci-lint v2\"\n      },\n      {\n        \"id\": \"11.2\",\n        \"text\": \"Sets gofumpt extra-rules: true under formatters.settings.gofumpt\"\n      },\n      {\n        \"id\": \"11.3\",\n        \"text\": \"Mentions the golangci-lint fmt ./... command for running formatters — separate from golangci-lint run\"\n      },\n      {\n        \"id\": \"11.4\",\n        \"text\": \"Notes that gci and goimports are redundant with gofumpt and can be disabled\"\n      }\n    ]\n  }\n]\n\nArchive v1.2.2: 6 files, 14733 bytes\n\nFiles: evals/evals.json (16136b), references/linter-reference.md (7930b), references/nolint-directives.md (2531b), skill-card.md (2355b), SKILL.md (6959b), _meta.json (130b)\n\nFile v1.2.2:SKILL.md\n\n---\nname: golang-lint\ndescription: \"Linting best practices and golangci-lint configuration for Golang projects — running linters, configuring .golangci.yml, suppressing warnings with nolint directives, interpreting lint output, and selecting linters. Use when configuring golangci-lint, asking about lint warnings or nolint suppressions, setting up code quality tooling, or choosing linters. Also use when the user mentions golangci-lint, go vet, staticcheck, or revive.\"\nuser-invocable: true\nlicense: MIT\ncompatibility: Designed for Claude Code or similar AI coding agents, and for projects using Golang.\nmetadata:\n  author: samber\n  version: \"1.2.2\"\n  openclaw:\n    emoji: \"🧹\"\n    homepage: https://github.com/samber/cc-skills-golang\n    requires:\n      bins:\n        - go\n        - golangci-lint\n    install:\n      - kind: brew\n        formula: golangci-lint\n        bins: [golangci-lint]\nallowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent\n---\n\n**Persona:** You are a Go code quality engineer. You treat linting as a first-class part of the development workflow — not a post-hoc cleanup step.\n\n**Modes:**\n\n- **Setup mode** — configuring `.golangci.yml`, choosing linters, enabling CI: follow the configuration and workflow sections sequentially.\n- **Coding mode** — writing new Go code: launch a background agent running `golangci-lint run --fix` on the modified files only while the main agent continues implementing the feature; surface results when it completes.\n- **Interpret/fix mode** — reading lint output, suppressing warnings, fixing issues on existing code: start from \"Interpreting Output\" and \"Suppressing Lint Warnings\"; use parallel sub-agents for large-scale legacy cleanup.\n\n**Dependencies:**\n\n- golangci-lint: `go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest`\n\n# Go Linting\n\n## Overview\n\n`golangci-lint` is the standard Go linting tool. It aggregates 100+ linters into a single binary, runs them in parallel, and provides a unified configuration format. Run it frequently during development and always in CI.\n\nEvery Go project MUST have a `.golangci.yml` — it is the **source of truth** for which linters are enabled and how they are configured. See the [recommended configuration](./assets/.golangci.yml) for a production-ready setup with 48 linters enabled.\n\n## Quick Reference\n\n```bash\n# Run all configured linters\ngolangci-lint run ./...\n\n# Auto-fix issues where possible\ngolangci-lint run --fix ./...\n\n# Format code (golangci-lint v2+)\ngolangci-lint fmt ./...\n\n# Run a single linter only\ngolangci-lint run --enable-only govet ./...\n\n# List all available linters\ngolangci-lint linters\n\n# Verbose output with timing info\ngolangci-lint run --verbose ./...\n```\n\n## Configuration\n\nThe [recommended .golangci.yml](./assets/.golangci.yml) provides a production-ready setup with 33 linters. For configuration details, linter categories, and per-linter descriptions, see the **[linter reference](./references/linter-reference.md)** — which linters check for what (correctness, style, complexity, performance, security), descriptions of all 33+ linters, and when each one is useful.\n\n## Suppressing Lint Warnings\n\nUse `//nolint` directives sparingly — fix the root cause first.\n\n```go\n// Good: specific linter + justification\n//nolint:errcheck // fire-and-forget logging, error is not actionable\n_ = logger.Sync()\n\n// Bad: blanket suppression without reason\n//nolint\n_ = logger.Sync()\n```\n\nRules:\n\n1. **//nolint directives MUST specify the linter name**: `//nolint:errcheck` not `//nolint`\n2. **//nolint directives MUST include a justification comment**: `//nolint:errcheck // reason`\n3. **The `nolintlint` linter enforces both rules above** — it flags bare `//nolint` and missing reasons\n4. **NEVER suppress security linters** (gosec, bodyclose, sqlclosecheck) without a very strong reason\n\nFor comprehensive patterns and examples, see **[nolint directives](./references/nolint-directives.md)** — when to suppress, how to write justifications, patterns for per-line vs per-function suppression, and anti-patterns.\n\n## Development Workflow\n\n1. **Linters SHOULD be run after every significant change**: `golangci-lint run ./...`\n2. **Auto-fix what you can**: `golangci-lint run --fix ./...`\n3. **Format before committing**: `golangci-lint fmt ./...`\n4. **Incremental adoption on legacy code**: set `issues.new-from-rev` in `.golangci.yml` to only lint new/changed code, then gradually clean up old code\n\nMakefile targets (recommended):\n\n```makefile\nlint:\n\tgolangci-lint run ./...\n\nlint-fix:\n\tgolangci-lint run --fix ./...\n\nfmt:\n\tgolangci-lint fmt ./...\n```\n\nFor CI pipeline setup (GitHub Actions with `golangci-lint-action`), see the `samber/cc-skills-golang@golang-continuous-integration` skill.\n\n## Interpreting Output\n\nEach issue follows this format:\n\n```\npath/to/file.go:42:10: message describing the issue (linter-name)\n```\n\nThe linter name in parentheses tells you which linter flagged it. Use this to:\n\n- Look up the linter in the [reference](./references/linter-reference.md) to understand what it checks\n- Suppress with `//nolint:linter-name // reason` if it's a false positive\n- Use `golangci-lint run --verbose` for additional context and timing\n\n## Common Issues\n\n| Problem | Solution |\n| --- | --- |\n| \"deadline exceeded\" | Set or increase `run.timeout` in `.golangci.yml`; golangci-lint v2 defaults to no timeout (`0`) |\n| Too many issues on legacy code | Set `issues.new-from-rev: HEAD~1` to lint only new code |\n| Linter not found | Check `golangci-lint linters` — linter may need a newer version |\n| Conflicts between linters | Disable the less useful one with a comment explaining why |\n| v1 config errors after upgrade | Run `golangci-lint migrate` to convert config format |\n| Slow on large repos | Reduce `run.concurrency` or exclude paths with `linters.exclusions.paths` / `formatters.exclusions.paths` |\n\n## Parallelizing Legacy Codebase Cleanup\n\nWhen adopting linting on a legacy codebase, use up to 5 parallel sub-agents (via the Agent tool) to fix independent linter categories simultaneously:\n\n- Sub-agent 1: Run `golangci-lint run --fix ./...` for auto-fixable issues\n- Sub-agent 2: Fix security linter findings (bodyclose, sqlclosecheck, gosec)\n- Sub-agent 3: Fix error handling issues (errcheck, nilerr, wrapcheck)\n- Sub-agent 4: Fix style and formatting (gofumpt, goimports, revive)\n- Sub-agent 5: Fix code quality (gocritic, unused, ineffassign)\n\n## Cross-References\n\n- → See `samber/cc-skills-golang@golang-continuous-integration` skill for CI pipeline with golangci-lint-action\n- → See `samber/cc-skills-golang@golang-code-style` skill for style rules that linters enforce\n- → See `samber/cc-skills-golang@golang-security` skill for SAST tools beyond linting (gosec, govulncheck)\n- → See `samber/cc-skills-golang@golang-continuous-integration` skill for automated AI-driven code review in CI using these guidelines\n\nFile v1.2.2:_meta.json\n\n{\n  \"ownerId\": \"kn72rhnkwjfeex9wr1n7y24qa983cjn3\",\n  \"slug\": \"golang-lint\",\n  \"version\": \"1.2.2\",\n  \"publishedAt\": 1781130129695\n}\n\nFile v1.2.2:references/linter-reference.md\n\n# Linter Reference\n\ngolangci-lint v2 uses a `.golangci.yml` with `version: \"2\"` at the project root.\n\nKey sections of `.golangci.yml`:\n\n- **`run`** — concurrency, timeout, test inclusion, directory exclusions\n- **`linters.enable`** / **`linters.disable`** — which linters are active\n- **`linters.settings`** — per-linter thresholds and options\n- **`formatters`** — code formatters (gofmt, gofumpt)\n- **`issues`** — output limits, exclusion rules\n\nTo add a linter: add it to `linters.enable` and optionally configure it in `linters.settings`.\n\nTo disable a linter: move it to `linters.disable` with a comment explaining why.\n\n## Linter Categories\n\nThe recommended configuration enables linters across these domains:\n\n| Domain | Linters | Catches |\n| --- | --- | --- |\n| Correctness | govet, staticcheck, unused, errcheck, errorlint, nilerr, forcetypeassert, copyloopvar, durationcheck, reassign | Bugs, unchecked errors, stdlib misuse |\n| Style | gocritic, revive, wsl_v5, whitespace, godot, misspell, dupword, predeclared, errname, asciicheck | Readability, naming, consistency |\n| Complexity | gocyclo, nestif, funlen, dupl | Overly complex or duplicated code |\n| Performance | perfsprint, unconvert, ineffassign, goconst | Conversions, string ops, dead assigns |\n| Security | gosec, bidichk, bodyclose, noctx, containedctx, fatcontext, sqlclosecheck, rowserrcheck | Security issues, resource leaks (HTTP, SQL) |\n| Logging | sloglint, loggercheck | Structured log consistency |\n| Testing | thelper, paralleltest, testifylint, usetesting | Test hygiene and best practices |\n| Modernization | modernize, exptostd, intrange, usestdlibvars, exhaustive, nolintlint | Modern Go idioms, lint hygiene |\n| Formatting | gofmt, gofumpt | Code formatting |\n\nAll linters are enabled in the [recommended .golangci.yml](../assets/.golangci.yml), organized by domain.\n\n### Correctness & Safety\n\n- **govet** — Go's built-in checker: copylocks, printf format mismatches, struct tag validation, context stored in structs, unreachable code, nil dereferences\n- **staticcheck** — Extensive static analysis: deprecated APIs, common mistakes, unnecessary code, simplifications, misuse of standard library\n- **unused** — Detects unused variables, functions, types, and struct fields\n- **errcheck** — Ensures all error returns are checked, including type assertions (configured with `check-type-assertions: true`)\n- **nilerr** — Detects returning nil error when `err` is non-nil (common source of silent failures)\n- **forcetypeassert** — Flags type assertions without the comma-ok check (`v := x.(T)` instead of `v, ok := x.(T)`)\n- **copyloopvar** — Detects loop variable copy issues (Go 1.22+)\n- **errorlint** — Enforces correct use of `errors.Is`/`errors.As` and `%w` wrapping (Go 1.13+ error wrapping)\n- **durationcheck** — Detects `time.Duration * time.Duration` multiplication bugs (e.g., `2 * time.Second * time.Minute` produces nanoseconds squared, not seconds)\n- **reassign** — Detects reassignment of package-level variables outside `init()`, which hides state mutations\n\n### Style & Readability\n\n- **gocritic** — Opinionated style checks: unnecessary conversions, range copies, append-assign patterns, redundant code\n- **revive** — Naming conventions for exported types, unexported returns, receiver naming, error naming, stuttered package names\n- **wsl_v5** — Whitespace and blank line rules for visual grouping and readability\n- **whitespace** — Detects trailing whitespace and unnecessary blank lines in function bodies\n- **godot** — Ensures exported-symbol comments end with a period\n- **misspell** — Catches common English misspellings in identifiers and comments\n- **predeclared** — Flags shadowing of Go built-in identifiers (e.g., naming a variable `len`, `cap`, `error`)\n- **errname** — Enforces error naming conventions: error types suffixed with `Error` (e.g., `DecodeError`), error variables prefixed with `Err` (e.g., `ErrNotFound`)\n- **dupword** — Detects duplicate words in comments and strings (e.g., \"the the\", \"is is\") — often copy-paste artifacts\n- **asciicheck** — Flags non-ASCII identifiers that enable homoglyph/trojan source attacks (visually identical but different Unicode codepoints)\n\n### Complexity\n\n- **gocyclo** — Cyclomatic complexity threshold (configured: 13). Functions exceeding this should be split\n- **nestif** — Detects deeply nested if/else chains that harm readability\n- **funlen** — Function length limits (configured: 120 lines, 80 statements)\n- **dupl** — Code duplication detection (configured: 100 token threshold)\n\n### Performance\n\n- **perfsprint** — Suggests faster alternatives to `fmt.Sprintf` (e.g., `strconv.Itoa` instead of `fmt.Sprintf(\"%d\", n)`)\n- **unconvert** — Detects unnecessary type conversions (e.g., `int(x)` when `x` is already `int`)\n- **ineffassign** — Detects assignments to variables that are never subsequently read\n- **goconst** — Detects repeated string/number literals that should be extracted to constants (configured: min 3 chars, min 4 occurrences)\n\n### Security & Resources\n\n- **gosec** — Security scanner: SQL injection, hardcoded credentials, weak crypto, path traversal, unsafe usage, and 50+ other rules. The primary SAST tool in the config — never suppress without strong justification.\n- **bidichk** — Detects dangerous bidirectional Unicode sequences (CVE-2021-42574 trojan source attack — code that looks safe but executes differently)\n- **noctx** — Detects HTTP requests sent without `context.Context` (prevents proper timeouts and cancellation)\n- **containedctx** — Flags `context.Context` stored in struct fields instead of passed as a parameter (anti-pattern per Go docs)\n- **fatcontext** — Detects `context.WithValue`/`WithCancel` in loops, creating unbounded context chains that grow each iteration and cause memory leaks\n- **bodyclose** — Ensures HTTP response bodies are closed (unclosed bodies leak connections)\n- **sqlclosecheck** — Ensures `sql.Rows` and `sql.Stmt` are closed after use\n- **rowserrcheck** — Ensures `sql.Rows.Err()` is checked after iteration\n\n### Logging\n\n- **sloglint** — Enforces consistent `log/slog` code style: proper key-value pairing, message formatting, and level usage\n- **loggercheck** — Validates key-value pair formatting for structured loggers (zap, slog, logr) — detects odd numbers of args, missing keys\n\n### Testing\n\n- **thelper** — Ensures test helpers call `t.Helper()` so failures report the correct call site\n- **paralleltest** — Detects tests and subtests missing `t.Parallel()` calls\n- **testifylint** — Enforces testify best practices (e.g., `assert.Equal(t, expected, actual)` over `assert.True(t, expected == actual)`)\n- **usetesting** — Suggests `t.Setenv`/`t.TempDir` instead of `os.Setenv`/`os.MkdirTemp` in tests (automatic cleanup, proper isolation)\n\n### Modernization & Meta\n\n- **modernize** — Detects code that can be rewritten using newer Go features (requires golangci-lint v2.6.0+)\n- **exptostd** — Detects `golang.org/x/exp/` functions that now have stdlib equivalents (e.g., `slices`, `maps`, `cmp` packages added in Go 1.21)\n- **intrange** — Suggests `range N` over C-style `for i := 0; i < N; i++` loops (Go 1.22+)\n- **usestdlibvars** — Replaces hardcoded strings/numbers with stdlib constants (e.g., `http.MethodGet` instead of `\"GET\"`)\n- **exhaustive** — Ensures switch statements on enum types cover all possible values\n- **nolintlint** — Enforces proper `//nolint` directive usage: requires linter name and justification comment (configured with `require-explanation` and `require-specific`)\n\n### Formatting\n\nFormatters run via `golangci-lint fmt ./...`:\n\n- **gofmt** — Standard Go formatter (canonical formatting)\n- **gofumpt** — Stricter formatter with extra rules (configured with `extra-rules: true`): consistent empty lines, grouped imports, simplified code patterns\n\nFile v1.2.2:references/nolint-directives.md\n\n# Nolint Directives\n\n## Syntax\n\n```go\n//nolint:lintername // justification explaining why this suppression is needed\n```\n\nPlace the directive on the same line as the flagged code, or on the line immediately above it.\n\n## Rules\n\n1. **MUST specify the linter name** — bare `//nolint` suppresses all linters on that line and makes it impossible to track what is being suppressed\n2. **MUST add a justification comment** — future readers (and your future self) need to understand why\n3. **The `nolintlint` linter enforces both rules** — it will flag bare `//nolint` and missing reasons\n4. **MUST fix the root cause before suppressing** — only suppress after confirming the issue is a false positive or an intentional pattern\n\n## Examples\n\n```go\n// Specific linter with reason\n//nolint:errcheck // fire-and-forget logging, error not actionable\n_ = logger.Sync()\n\n// Type assertion is safe because preceding type switch guarantees the type\nv := x.(MyType) //nolint:forcetypeassert // guaranteed by type switch on line 42\n\n// Orchestration function has inherent complexity\n//nolint:gocyclo // orchestration function coordinating 8 subsystems\nfunc orchestrate() error {\n\n// Table-driven test with many cases\n//nolint:funlen // table-driven test, length is proportional to case count\nfunc TestParser(t *testing.T) {\n\n// Intentional parallel structure is clearer than abstracting\n//nolint:dupl // intentional parallel structure for readability\n```\n\n## Multiple Linters\n\nSuppress multiple linters on one line with comma separation:\n\n```go\n//nolint:errcheck,gosec // fire-and-forget in test helper\n```\n\n## When to Suppress vs. When to Fix\n\n**Fix** (almost always):\n\n- `errcheck` — check the error, even if just logging it\n- `govet` — these are usually real bugs\n- `staticcheck` — deprecated API usage, logic errors\n- `bodyclose`, `sqlclosecheck` — resource leaks are real issues\n\n**Suppress** (with justification):\n\n- `funlen` — table-driven tests with many cases\n- `gocyclo` — orchestration functions where splitting would obscure the flow\n- `dupl` — intentional parallel structure that is clearer than an abstraction\n- `exhaustive` — when a default case intentionally handles remaining values\n- `goconst` — when extracting to a constant would reduce clarity (e.g., test assertions)\n\n**Never suppress without strong justification**:\n\n- Security linters (`bodyclose`, `sqlclosecheck`, `rowserrcheck`) — these catch real resource leaks\n- `errcheck` on production code paths — unchecked errors cause silent failures\n\nFile v1.2.2:skill-card.md\n\n## Description: <br>\nLinting best practices and golangci-lint configuration for Golang projects, including running linters, configuring .golangci.yml, suppressing warnings with nolint directives, interpreting lint output, and selecting linters. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[samber](https://clawhub.ai/user/samber) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nDevelopers and engineering teams use this skill to configure golangci-lint, interpret Go lint findings, apply safe fixes, and decide when lint warnings should be fixed or narrowly suppressed. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: Autofix and legacy cleanup workflows may modify many Go files or configuration files. <br>\nMitigation: Review generated diffs before committing, and prefer scoped lint runs or batched cleanup for large repositories. <br>\nRisk: Incorrect suppression guidance can hide real correctness, security, or resource-leak findings. <br>\nMitigation: Require specific nolint directives with justifications, and fix security and correctness findings unless there is a documented false positive. <br>\n\n\n## Reference(s): <br>\n- [Golang Lint ClawHub page](https://clawhub.ai/samber/golang-lint) <br>\n- [Publisher profile](https://clawhub.ai/user/samber) <br>\n- [Project homepage](https://github.com/samber/cc-skills-golang) <br>\n- [Linter Reference](references/linter-reference.md) <br>\n- [Nolint Directives](references/nolint-directives.md) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance] <br>\n**Output Format:** [Markdown guidance with inline Go, YAML, Makefile, and shell command examples] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [May propose file edits and golangci-lint commands; users should review generated code and configuration changes before committing.] <br>\n\n## Skill Version(s): <br>\n1.2.2 (source: server release metadata and frontmatter) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v1.2.2:evals/evals.json\n\n[\n  {\n    \"id\": 1,\n    \"name\": \"nolint-directive-specificity\",\n    \"description\": \"Tests that nolint directives specify the linter name and include a justification — never bare //nolint\",\n    \"prompt\": \"I have a Go function that triggers several lint warnings. I want to suppress them. Write the nolint directives for these cases:\\n\\n1. A logger.Sync() call where the error is intentionally ignored\\n2. A type assertion that is guaranteed safe by a preceding type switch\\n3. A function with cyclomatic complexity of 15 that orchestrates 6 subsystems\\n4. A table-driven test function that is 200 lines long\\n5. A deprecated API call that we can't migrate yet\\n\\nShow the code with proper suppression directives.\",\n    \"trap\": \"Model uses bare //nolint without specifying the linter name, or omits the justification comment. May also use //nolint at the file level instead of per-line.\",\n    \"assertions\": [\n      {\n        \"id\": \"1.1\",\n        \"text\": \"Every //nolint directive specifies the linter name (e.g., //nolint:errcheck, //nolint:gocyclo) — NO bare //nolint without a linter name\"\n      },\n      {\n        \"id\": \"1.2\",\n        \"text\": \"Every //nolint directive includes a justification comment after // (e.g., //nolint:errcheck // fire-and-forget logging)\"\n      },\n      {\n        \"id\": \"1.3\",\n        \"text\": \"The type assertion uses //nolint:forcetypeassert with an explanation referencing why the assertion is safe\"\n      },\n      {\n        \"id\": \"1.4\",\n        \"text\": \"The long test function uses //nolint:funlen with a justification like 'table-driven test, length proportional to case count'\"\n      },\n      {\n        \"id\": \"1.5\",\n        \"text\": \"The cyclomatic complexity suppression uses //nolint:gocyclo with a justification about orchestration\"\n      }\n    ]\n  },\n  {\n    \"id\": 2,\n    \"name\": \"nolint-fix-vs-suppress-judgment\",\n    \"description\": \"Tests judgment about when to fix vs when to suppress — security and correctness linters should almost never be suppressed\",\n    \"prompt\": \"My Go codebase has these lint warnings. For each one, should I fix the code or suppress the warning? Explain.\\n\\n1. `bodyclose: response body not closed` on an HTTP client call\\n2. `funlen: function too long (150 lines)` on a table-driven test\\n3. `errcheck: error return not checked` on a database query in a request handler\\n4. `dupl: duplicate code block` on two similar but intentionally parallel handler functions\\n5. `sqlclosecheck: rows not closed` on a database query\\n6. `goconst: string 'application/json' repeated 4 times` in test assertions\",\n    \"trap\": \"Model suppresses bodyclose, errcheck on production DB code, or sqlclosecheck — these are real bugs, not style issues. Should only suppress funlen, dupl, and goconst with justifications.\",\n    \"assertions\": [\n      {\n        \"id\": \"2.1\",\n        \"text\": \"Recommends FIXING bodyclose — unclosed HTTP response bodies leak connections, this is a real resource leak\"\n      },\n      {\n        \"id\": \"2.2\",\n        \"text\": \"Recommends SUPPRESSING funlen on the table-driven test — length is proportional to test case count, splitting would be worse\"\n      },\n      {\n        \"id\": \"2.3\",\n        \"text\": \"Recommends FIXING errcheck on the database query — unchecked errors in production request handlers cause silent failures\"\n      },\n      {\n        \"id\": \"2.4\",\n        \"text\": \"Recommends SUPPRESSING dupl on intentional parallel structure — with a justification that the parallel pattern is clearer than abstracting\"\n      },\n      {\n        \"id\": \"2.5\",\n        \"text\": \"Recommends FIXING sqlclosecheck — unclosed sql.Rows leak database connections\"\n      },\n      {\n        \"id\": \"2.6\",\n        \"text\": \"Recommends SUPPRESSING goconst in tests — extracting 'application/json' to a constant in tests would reduce clarity\"\n      }\n    ]\n  },\n  {\n    \"id\": 3,\n    \"name\": \"golangci-yml-version-2-structure\",\n    \"description\": \"Tests knowledge of golangci-lint v2 config structure: version field, linters.enable/disable, formatters section\",\n    \"prompt\": \"Create a .golangci.yml configuration file for a Go project. Enable at least govet, staticcheck, errcheck, and gofumpt. Set the timeout to 5 minutes and configure errcheck to also check type assertions.\",\n    \"trap\": \"Model uses golangci-lint v1 config format (missing version: \\\"2\\\", using enable-all/disable-all, missing formatters section, putting gofumpt in linters instead of formatters).\",\n    \"assertions\": [\n      {\n        \"id\": \"3.1\",\n        \"text\": \"Config file has version: \\\"2\\\" at the top — golangci-lint v2 requires this field\"\n      },\n      {\n        \"id\": \"3.2\",\n        \"text\": \"Linters are listed under linters.enable (not enable-all with exclusions) — explicit listing is the recommended approach\"\n      },\n      {\n        \"id\": \"3.3\",\n        \"text\": \"gofumpt is configured under formatters.enable, NOT under linters.enable — formatters are a separate section in v2\"\n      },\n      {\n        \"id\": \"3.4\",\n        \"text\": \"errcheck has check-type-assertions: true in linters.settings.errcheck\"\n      },\n      {\n        \"id\": \"3.5\",\n        \"text\": \"Timeout is set under run.timeout: 5m\"\n      }\n    ]\n  },\n  {\n    \"id\": 4,\n    \"name\": \"linter-categories-correctness-vs-style\",\n    \"description\": \"Tests understanding of linter domains — which linters catch bugs vs which catch style issues\",\n    \"prompt\": \"I'm setting up golangci-lint for a new Go project and can only enable 10 linters due to team constraints. Which 10 should I prioritize and why? Categorize them.\",\n    \"trap\": \"Model prioritizes style linters (revive, godot, misspell) over correctness linters (govet, staticcheck, errcheck, nilerr). May also include deprecated or redundant linters.\",\n    \"assertions\": [\n      {\n        \"id\": \"4.1\",\n        \"text\": \"Includes govet and staticcheck — these are the highest-value correctness linters that catch real bugs\"\n      },\n      {\n        \"id\": \"4.2\",\n        \"text\": \"Includes errcheck — unchecked errors are the most common source of silent failures in Go\"\n      },\n      {\n        \"id\": \"4.3\",\n        \"text\": \"Prioritizes correctness/safety linters over style linters — bug-finding tools provide more value than formatting preferences\"\n      },\n      {\n        \"id\": \"4.4\",\n        \"text\": \"Includes at least one security linter (bodyclose, gosec, or sqlclosecheck) for resource leak prevention\"\n      },\n      {\n        \"id\": \"4.5\",\n        \"text\": \"Does NOT include both gocyclo and cyclop (redundant) or both gocognit and gocyclo (overlapping complexity checkers)\"\n      }\n    ]\n  },\n  {\n    \"id\": 5,\n    \"name\": \"legacy-codebase-incremental-adoption\",\n    \"description\": \"Tests the new-from-rev strategy for adopting linters on legacy code without drowning in warnings\",\n    \"prompt\": \"We have a large legacy Go codebase with 2000+ lint warnings. We want to adopt golangci-lint but can't fix everything at once. How should we approach this?\",\n    \"trap\": \"Model suggests suppressing all existing warnings with //nolint directives, or disabling linters until the code is clean. Doesn't know about new-from-rev for incremental adoption.\",\n    \"assertions\": [\n      {\n        \"id\": \"5.1\",\n        \"text\": \"Recommends setting issues.new-from-rev (e.g., HEAD~1 or main) in .golangci.yml to only lint new/changed code\"\n      },\n      {\n        \"id\": \"5.2\",\n        \"text\": \"Does NOT suggest adding //nolint directives to all 2000+ existing warnings — that's unmaintainable\"\n      },\n      {\n        \"id\": \"5.3\",\n        \"text\": \"Suggests gradually cleaning up old code over time while enforcing quality on new code\"\n      },\n      {\n        \"id\": \"5.4\",\n        \"text\": \"Suggests running golangci-lint run --fix for auto-fixable issues as a quick first pass\"\n      },\n      {\n        \"id\": \"5.5\",\n        \"text\": \"Mentions using parallel sub-agents or batching fixes by linter category (security, error handling, style) to tackle cleanup efficiently\"\n      }\n    ]\n  },\n  {\n    \"id\": 6,\n    \"name\": \"interpreting-lint-output-format\",\n    \"description\": \"Tests ability to read lint output format and use the linter name for targeted investigation or suppression\",\n    \"prompt\": \"I ran golangci-lint and got this output:\\n\\n```\\nserver/handler.go:42:10: Error return value of `(*DB).Close` is not checked (errcheck)\\nserver/handler.go:55:2: response body must be closed (bodyclose)\\nserver/auth.go:12:6: func `validateToken` is unused (unused)\\nserver/auth.go:30:1: cyclomatic complexity 17 of func `processAuth` is high (> 13) (gocyclo)\\nserver/model.go:5:2: exported type `Model` should have comment or be unexported (revive)\\n```\\n\\nFor each warning, explain what it means and whether I should fix or suppress it.\",\n    \"trap\": \"Model doesn't use the linter name in parentheses to guide its response. May treat all warnings equally instead of recognizing that errcheck and bodyclose are critical while revive is style.\",\n    \"assertions\": [\n      {\n        \"id\": \"6.1\",\n        \"text\": \"Identifies errcheck on DB.Close as a real issue to fix — unchecked database close errors can mask connection problems\"\n      },\n      {\n        \"id\": \"6.2\",\n        \"text\": \"Identifies bodyclose as a critical resource leak to fix — not suppress\"\n      },\n      {\n        \"id\": \"6.3\",\n        \"text\": \"Identifies unused validateToken as dead code to either remove or fix — not suppress\"\n      },\n      {\n        \"id\": \"6.4\",\n        \"text\": \"For gocyclo, evaluates whether processAuth should be refactored or suppressed based on its nature (orchestration function vs genuinely complex logic)\"\n      },\n      {\n        \"id\": \"6.5\",\n        \"text\": \"For revive comment warning, correctly identifies it as a style issue that's lower priority than the correctness issues above\"\n      }\n    ]\n  },\n  {\n    \"id\": 7,\n    \"name\": \"disabled-linters-with-rationale\",\n    \"description\": \"Tests understanding of which linters should be disabled and why — the recommended config explicitly disables several with reasons\",\n    \"prompt\": \"A colleague wants to enable these linters in our .golangci.yml: exhaustruct, gochecknoglobals, wrapcheck, mnd (magic number detector), and varnamelen. Should we? Explain your reasoning for each.\",\n    \"trap\": \"Model enables all of them without considering that they are intentionally excluded from the recommended config due to being too noisy, too opinionated, or breaking idiomatic Go patterns.\",\n    \"assertions\": [\n      {\n        \"id\": \"7.1\",\n        \"text\": \"Recommends AGAINST exhaustruct — it requires all struct fields to be set, which breaks Go's zero-value idiom and is extremely noisy\"\n      },\n      {\n        \"id\": \"7.2\",\n        \"text\": \"Recommends AGAINST gochecknoglobals — there are many valid uses for global variables in Go (loggers, registries, etc.) and a blanket ban is too strict\"\n      },\n      {\n        \"id\": \"7.3\",\n        \"text\": \"Recommends AGAINST wrapcheck as a default — it forces wrapping all external errors, which is too noisy and not always appropriate\"\n      },\n      {\n        \"id\": \"7.4\",\n        \"text\": \"Recommends AGAINST mnd — magic number detection is extremely noisy, flagging obvious constants like HTTP status codes\"\n      },\n      {\n        \"id\": \"7.5\",\n        \"text\": \"Recommends AGAINST varnamelen — Go idiomatically favors short variable names, and this linter conflicts with that philosophy\"\n      }\n    ]\n  },\n  {\n    \"id\": 8,\n    \"name\": \"nolintlint-meta-linter\",\n    \"description\": \"Tests knowledge that nolintlint enforces proper nolint directive usage and should be enabled\",\n    \"prompt\": \"I see //nolint directives scattered throughout our Go codebase. Many are bare '//nolint' without specifying which linter or why. How can I enforce proper nolint hygiene automatically?\",\n    \"trap\": \"Model suggests a manual code review process or a custom script instead of enabling the nolintlint linter with require-explanation and require-specific settings.\",\n    \"assertions\": [\n      {\n        \"id\": \"8.1\",\n        \"text\": \"Recommends enabling the nolintlint linter — it automatically enforces nolint directive quality\"\n      },\n      {\n        \"id\": \"8.2\",\n        \"text\": \"Configures nolintlint with require-specific: true to require linter names (not bare //nolint)\"\n      },\n      {\n        \"id\": \"8.3\",\n        \"text\": \"Configures nolintlint with require-explanation: true to require justification comments\"\n      },\n      {\n        \"id\": \"8.4\",\n        \"text\": \"Shows the correct config location: linters.settings.nolintlint in .golangci.yml\"\n      }\n    ]\n  },\n  {\n    \"id\": 9,\n    \"name\": \"multiple-nolint-comma-syntax\",\n    \"description\": \"Tests proper syntax for suppressing multiple linters on one line\",\n    \"prompt\": \"I have a line of Go code that triggers both errcheck and gosec warnings. I've confirmed both are false positives in this specific case. How do I suppress both on the same line?\",\n    \"trap\": \"Model uses two separate //nolint directives on the same line, or uses //nolint without comma separation, or stacks directives on consecutive lines for the same code line.\",\n    \"assertions\": [\n      {\n        \"id\": \"9.1\",\n        \"text\": \"Uses comma-separated linter names in a single directive: //nolint:errcheck,gosec — not two separate //nolint directives\"\n      },\n      {\n        \"id\": \"9.2\",\n        \"text\": \"Includes a justification comment after the directive explaining why both are false positives\"\n      },\n      {\n        \"id\": \"9.3\",\n        \"text\": \"The directive is placed on the same line as the flagged code or the line immediately above it\"\n      }\n    ]\n  },\n  {\n    \"id\": 10,\n    \"name\": \"common-config-issues\",\n    \"description\": \"Tests troubleshooting knowledge for golangci-lint: timeout, v1-to-v2 migration, linter-not-found\",\n    \"prompt\": \"I'm getting these errors with golangci-lint:\\n1. 'deadline exceeded' when running on our large monorepo\\n2. After upgrading to golangci-lint v2, my .golangci.yml throws config errors\\n3. 'linter modernize not found' even though I listed it in enable\\n\\nHow do I fix each?\",\n    \"trap\": \"Model doesn't know about the v2 config migration tool, suggests reinstalling for the linter-not-found issue instead of checking the golangci-lint version, or increases concurrency instead of timeout.\",\n    \"assertions\": [\n      {\n        \"id\": \"10.1\",\n        \"text\": \"For deadline exceeded: recommends increasing run.timeout in .golangci.yml (default is 5m, may need 10m+ for large repos)\"\n      },\n      {\n        \"id\": \"10.2\",\n        \"text\": \"For v1 config errors: recommends running golangci-lint migrate to convert the config format to v2\"\n      },\n      {\n        \"id\": \"10.3\",\n        \"text\": \"For linter not found: recommends checking the golangci-lint version — modernize requires v2.6.0+ or similar newer version\"\n      },\n      {\n        \"id\": \"10.4\",\n        \"text\": \"Mentions golangci-lint linters command to check available linters in the installed version\"\n      }\n    ]\n  },\n  {\n    \"id\": 11,\n    \"name\": \"formatter-vs-linter-distinction\",\n    \"description\": \"Tests that formatters (gofumpt, gofmt) are configured in the formatters section, not the linters section, and use the fmt subcommand\",\n    \"prompt\": \"I want to enforce consistent code formatting in my Go project using golangci-lint. I want gofumpt with extra rules. How do I set it up?\",\n    \"trap\": \"Model puts gofumpt in the linters.enable section instead of formatters.enable (v2 distinction), or doesn't mention the golangci-lint fmt subcommand for formatting.\",\n    \"assertions\": [\n      {\n        \"id\": \"11.1\",\n        \"text\": \"Configures gofumpt under formatters.enable, NOT linters.enable — formatters are a separate section in golangci-lint v2\"\n      },\n      {\n        \"id\": \"11.2\",\n        \"text\": \"Sets gofumpt extra-rules: true under formatters.settings.gofumpt\"\n      },\n      {\n        \"id\": \"11.3\",\n        \"text\": \"Mentions the golangci-lint fmt ./... command for running formatters — separate from golangci-lint run\"\n      },\n      {\n        \"id\": \"11.4\",\n        \"text\": \"Notes that gci and goimports are redundant with gofumpt and can be disabled\"\n      }\n    ]\n  }\n]\n\nArchive v1.2.1: 6 files, 14701 bytes\n\nFiles: evals/evals.json (16136b), references/linter-reference.md (7930b), references/nolint-directives.md (2531b), skill-card.md (2306b), SKILL.md (6850b), _meta.json (130b)\n\nFile v1.2.1:SKILL.md\n\n---\nname: golang-lint\ndescription: \"Linting best practices and golangci-lint configuration for Golang projects — running linters, configuring .golangci.yml, suppressing warnings with nolint directives, interpreting lint output, and selecting linters. Use when configuring golangci-lint, asking about lint warnings or nolint suppressions, setting up code quality tooling, or choosing linters. Also use when the user mentions golangci-lint, go vet, staticcheck, or revive.\"\nuser-invocable: true\nlicense: MIT\ncompatibility: Designed for Claude Code or similar AI coding agents, and for projects using Golang.\nmetadata:\n  author: samber\n  version: \"1.2.1\"\n  openclaw:\n    emoji: \"🧹\"\n    homepage: https://github.com/samber/cc-skills-golang\n    requires:\n      bins:\n        - go\n        - golangci-lint\n    install:\n      - kind: brew\n        formula: golangci-lint\n        bins: [golangci-lint]\nallowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent\n---\n\n**Persona:** You are a Go code quality engineer. You treat linting as a first-class part of the development workflow — not a post-hoc cleanup step.\n\n**Modes:**\n\n- **Setup mode** — configuring `.golangci.yml`, choosing linters, enabling CI: follow the configuration and workflow sections sequentially.\n- **Coding mode** — writing new Go code: launch a background agent running `golangci-lint run --fix` on the modified files only while the main agent continues implementing the feature; surface results when it completes.\n- **Interpret/fix mode** — reading lint output, suppressing warnings, fixing issues on existing code: start from \"Interpreting Output\" and \"Suppressing Lint Warnings\"; use parallel sub-agents for large-scale legacy cleanup.\n\n# Go Linting\n\n## Overview\n\n`golangci-lint` is the standard Go linting tool. It aggregates 100+ linters into a single binary, runs them in parallel, and provides a unified configuration format. Run it frequently during development and always in CI.\n\nEvery Go project MUST have a `.golangci.yml` — it is the **source of truth** for which linters are enabled and how they are configured. See the [recommended configuration](./assets/.golangci.yml) for a production-ready setup with 48 linters enabled.\n\n## Quick Reference\n\n```bash\n# Run all configured linters\ngolangci-lint run ./...\n\n# Auto-fix issues where possible\ngolangci-lint run --fix ./...\n\n# Format code (golangci-lint v2+)\ngolangci-lint fmt ./...\n\n# Run a single linter only\ngolangci-lint run --enable-only govet ./...\n\n# List all available linters\ngolangci-lint linters\n\n# Verbose output with timing info\ngolangci-lint run --verbose ./...\n```\n\n## Configuration\n\nThe [recommended .golangci.yml](./assets/.golangci.yml) provides a production-ready setup with 33 linters. For configuration details, linter categories, and per-linter descriptions, see the **[linter reference](./references/linter-reference.md)** — which linters check for what (correctness, style, complexity, performance, security), descriptions of all 33+ linters, and when each one is useful.\n\n## Suppressing Lint Warnings\n\nUse `//nolint` directives sparingly — fix the root cause first.\n\n```go\n// Good: specific linter + justification\n//nolint:errcheck // fire-and-forget logging, error is not actionable\n_ = logger.Sync()\n\n// Bad: blanket suppression without reason\n//nolint\n_ = logger.Sync()\n```\n\nRules:\n\n1. **//nolint directives MUST specify the linter name**: `//nolint:errcheck` not `//nolint`\n2. **//nolint directives MUST include a justification comment**: `//nolint:errcheck // reason`\n3. **The `nolintlint` linter enforces both rules above** — it flags bare `//nolint` and missing reasons\n4. **NEVER suppress security linters** (gosec, bodyclose, sqlclosecheck) without a very strong reason\n\nFor comprehensive patterns and examples, see **[nolint directives](./references/nolint-directives.md)** — when to suppress, how to write justifications, patterns for per-line vs per-function suppression, and anti-patterns.\n\n## Development Workflow\n\n1. **Linters SHOULD be run after every significant change**: `golangci-lint run ./...`\n2. **Auto-fix what you can**: `golangci-lint run --fix ./...`\n3. **Format before committing**: `golangci-lint fmt ./...`\n4. **Incremental adoption on legacy code**: set `issues.new-from-rev` in `.golangci.yml` to only lint new/changed code, then gradually clean up old code\n\nMakefile targets (recommended):\n\n```makefile\nlint:\n\tgolangci-lint run ./...\n\nlint-fix:\n\tgolangci-lint run --fix ./...\n\nfmt:\n\tgolangci-lint fmt ./...\n```\n\nFor CI pipeline setup (GitHub Actions with `golangci-lint-action`), see the `samber/cc-skills-golang@golang-continuous-integration` skill.\n\n## Interpreting Output\n\nEach issue follows this format:\n\n```\npath/to/file.go:42:10: message describing the issue (linter-name)\n```\n\nThe linter name in parentheses tells you which linter flagged it. Use this to:\n\n- Look up the linter in the [reference](./references/linter-reference.md) to understand what it checks\n- Suppress with `//nolint:linter-name // reason` if it's a false positive\n- Use `golangci-lint run --verbose` for additional context and timing\n\n## Common Issues\n\n| Problem | Solution |\n| --- | --- |\n| \"deadline exceeded\" | Set or increase `run.timeout` in `.golangci.yml`; golangci-lint v2 defaults to no timeout (`0`) |\n| Too many issues on legacy code | Set `issues.new-from-rev: HEAD~1` to lint only new code |\n| Linter not found | Check `golangci-lint linters` — linter may need a newer version |\n| Conflicts between linters | Disable the less useful one with a comment explaining why |\n| v1 config errors after upgrade | Run `golangci-lint migrate` to convert config format |\n| Slow on large repos | Reduce `run.concurrency` or exclude paths with `linters.exclusions.paths` / `formatters.exclusions.paths` |\n\n## Parallelizing Legacy Codebase Cleanup\n\nWhen adopting linting on a legacy codebase, use up to 5 parallel sub-agents (via the Agent tool) to fix independent linter categories simultaneously:\n\n- Sub-agent 1: Run `golangci-lint run --fix ./...` for auto-fixable issues\n- Sub-agent 2: Fix security linter findings (bodyclose, sqlclosecheck, gosec)\n- Sub-agent 3: Fix error handling issues (errcheck, nilerr, wrapcheck)\n- Sub-agent 4: Fix style and formatting (gofumpt, goimports, revive)\n- Sub-agent 5: Fix code quality (gocritic, unused, ineffassign)\n\n## Cross-References\n\n- → See `samber/cc-skills-golang@golang-continuous-integration` skill for CI pipeline with golangci-lint-action\n- → See `samber/cc-skills-golang@golang-code-style` skill for style rules that linters enforce\n- → See `samber/cc-skills-golang@golang-security` skill for SAST tools beyond linting (gosec, govulncheck)\n- → See `samber/cc-skills-golang@golang-continuous-integration` skill for automated AI-driven code review in CI using these guidelines\n\nFile v1.2.1:_meta.json\n\n{\n  \"ownerId\": \"kn72rhnkwjfeex9wr1n7y24qa983cjn3\",\n  \"slug\": \"golang-lint\",\n  \"version\": \"1.2.1\",\n  \"publishedAt\": 1779476303723\n}\n\nFile v1.2.1:references/linter-reference.md\n\n# Linter Reference\n\ngolangci-lint v2 uses a `.golangci.yml` with `version: \"2\"` at the project root.\n\nKey sections of `.golangci.yml`:\n\n- **`run`** — concurrency, timeout, test inclusion, directory exclusions\n- **`linters.enable`** / **`linters.disable`** — which linters are active\n- **`linters.settings`** — per-linter thresholds and options\n- **`formatters`** — code formatters (gofmt, gofumpt)\n- **`issues`** — output limits, exclusion rules\n\nTo add a linter: add it to `linters.enable` and optionally configure it in `linters.settings`.\n\nTo disable a linter: move it to `linters.disable` with a comment explaining why.\n\n## Linter Categories\n\nThe recommended configuration enables linters across these domains:\n\n| Domain | Linters | Catches |\n| --- | --- | --- |\n| Correctness | govet, staticcheck, unused, errcheck, errorlint, nilerr, forcetypeassert, copyloopvar, durationcheck, reassign | Bugs, unchecked errors, stdlib misuse |\n| Style | gocritic, revive, wsl_v5, whitespace, godot, misspell, dupword, predeclared, errname, asciicheck | Readability, naming, consistency |\n| Complexity | gocyclo, nestif, funlen, dupl | Overly complex or duplicated code |\n| Performance | perfsprint, unconvert, ineffassign, goconst | Conversions, string ops, dead assigns |\n| Security | gosec, bidichk, bodyclose, noctx, containedctx, fatcontext, sqlclosecheck, rowserrcheck | Security issues, resource leaks (HTTP, SQL) |\n| Logging | sloglint, loggercheck | Structured log consistency |\n| Testing | thelper, paralleltest, testifylint, usetesting | Test hygiene and best practices |\n| Modernization | modernize, exptostd, intrange, usestdlibvars, exhaustive, nolintlint | Modern Go idioms, lint hygiene |\n| Formatting | gofmt, gofumpt | Code formatting |\n\nAll linters are enabled in the [recommended .golangci.yml](../assets/.golangci.yml), organized by domain.\n\n### Correctness & Safety\n\n- **govet** — Go's built-in checker: copylocks, printf format mismatches, struct tag validation, context stored in structs, unreachable code, nil dereferences\n- **staticcheck** — Extensive static analysis: deprecated APIs, common mistakes, unnecessary code, simplifications, misuse of standard library\n- **unused** — Detects unused variables, functions, types, and struct fields\n- **errcheck** — Ensures all error returns are checked, including type assertions (configured with `check-type-assertions: true`)\n- **nilerr** — Detects returning nil error when `err` is non-nil (common source of silent failures)\n- **forcetypeassert** — Flags type assertions without the comma-ok check (`v := x.(T)` instead of `v, ok := x.(T)`)\n- **copyloopvar** — Detects loop variable copy issues (Go 1.22+)\n- **errorlint** — Enforces correct use of `errors.Is`/`errors.As` and `%w` wrapping (Go 1.13+ error wrapping)\n- **durationcheck** — Detects `time.Duration * time.Duration` multiplication bugs (e.g., `2 * time.Second * time.Minute` produces nanoseconds squared, not seconds)\n- **reassign** — Detects reassignment of package-level variables outside `init()`, which hides state mutations\n\n### Style & Readability\n\n- **gocritic** — Opinionated style checks: unnecessary conversions, range copies, append-assign patterns, redundant code\n- **revive** — Naming conventions for exported types, unexported returns, receiver naming, error naming, stuttered package names\n- **wsl_v5** — Whitespace and blank line rules for visual grouping and readability\n- **whitespace** — Detects trailing whitespace and unnecessary blank lines in function bodies\n- **godot** — Ensures exported-symbol comments end with a period\n- **misspell** — Catches common English misspellings in identifiers and comments\n- **predeclared** — Flags shadowing of Go built-in identifiers (e.g., naming a variable `len`, `cap`, `error`)\n- **errname** — Enforces error naming conventions: error types suffixed with `Error` (e.g., `DecodeError`), error variables prefixed with `Err` (e.g., `ErrNotFound`)\n- **dupword** — Detects duplicate words in comments and strings (e.g., \"the the\", \"is is\") — often copy-paste artifacts\n- **asciicheck** — Flags non-ASCII identifiers that enable homoglyph/trojan source attacks (visually identical but different Unicode codepoints)\n\n### Complexity\n\n- **gocyclo** — Cyclomatic complexity threshold (configured: 13). Functions exceeding this should be split\n- **nestif** — Detects deeply nested if/else chains that harm readability\n- **funlen** — Function length limits (configured: 120 lines, 80 statements)\n- **dupl** — Code duplication detection (configured: 100 token threshold)\n\n### Performance\n\n- **perfsprint** — Suggests faster alternatives to `fmt.Sprintf` (e.g., `strconv.Itoa` instead of `fmt.Sprintf(\"%d\", n)`)\n- **unconvert** — Detects unnecessary type conversions (e.g., `int(x)` when `x` is already `int`)\n- **ineffassign** — Detects assignments to variables that are never subsequently read\n- **goconst** — Detects repeated string/number literals that should be extracted to constants (configured: min 3 chars, min 4 occurrences)\n\n### Security & Resources\n\n- **gosec** — Security scanner: SQL injection, hardcoded credentials, weak crypto, path traversal, unsafe usage, and 50+ other rules. The primary SAST tool in the config — never suppress without strong justification.\n- **bidichk** — Detects dangerous bidirectional Unicode sequences (CVE-2021-42574 trojan source attack — code that looks safe but executes differently)\n- **noctx** — Detects HTTP requests sent without `context.Context` (prevents proper timeouts and cancellation)\n- **containedctx** — Flags `context.Context` stored in struct fields instead of passed as a parameter (anti-pattern per Go docs)\n- **fatcontext** — Detects `context.WithValue`/`WithCancel` in loops, creating unbounded context chains that grow each iteration and cause memory leaks\n- **bodyclose** — Ensures HTTP response bodies are closed (unclosed bodies leak connections)\n- **sqlclosecheck** — Ensures `sql.Rows` and `sql.Stmt` are closed after use\n- **rowserrcheck** — Ensures `sql.Rows.Err()` is checked after iteration\n\n### Logging\n\n- **sloglint** — Enforces consistent `log/slog` code style: proper key-value pairing, message formatting, and level usage\n- **loggercheck** — Validates key-value pair formatting for structured loggers (zap, slog, logr) — detects odd numbers of args, missing keys\n\n### Testing\n\n- **thelper** — Ensures test helpers call `t.Helper()` so failures report the correct call site\n- **paralleltest** — Detects tests and subtests missing `t.Parallel()` calls\n- **testifylint** — Enforces testify best practices (e.g., `assert.Equal(t, expected, actual)` over `assert.True(t, expected == actual)`)\n- **usetesting** — Suggests `t.Setenv`/`t.TempDir` instead of `os.Setenv`/`os.MkdirTemp` in tests (automatic cleanup, proper isolation)\n\n### Modernization & Meta\n\n- **modernize** — Detects code that can be rewritten using newer Go features (requires golangci-lint v2.6.0+)\n- **exptostd** — Detects `golang.org/x/exp/` functions that now have stdlib equivalents (e.g., `slices`, `maps`, `cmp` packages added in Go 1.21)\n- **intrange** — Suggests `range N` over C-style `for i := 0; i < N; i++` loops (Go 1.22+)\n- **usestdlibvars** — Replaces hardcoded strings/numbers with stdlib constants (e.g., `http.MethodGet` instead of `\"GET\"`)\n- **exhaustive** — Ensures switch statements on enum types cover all possible values\n- **nolintlint** — Enforces proper `//nolint` directive usage: requires linter name and justification comment (configured with `require-explanation` and `require-specific`)\n\n### Formatting\n\nFormatters run via `golangci-lint fmt ./...`:\n\n- **gofmt** — Standard Go formatter (canonical formatting)\n- **gofumpt** — Stricter formatter with extra rules (configured with `extra-rules: true`): consistent empty lines, grouped imports, simplified code patterns\n\nFile v1.2.1:references/nolint-directives.md\n\n# Nolint Directives\n\n## Syntax\n\n```go\n//nolint:lintername // justification explaining why this suppression is needed\n```\n\nPlace the directive on the same line as the flagged code, or on the line immediately above it.\n\n## Rules\n\n1. **MUST specify the linter name** — bare `//nolint` suppresses all linters on that line and makes it impossible to track what is being suppressed\n2. **MUST add a justification comment** — future readers (and your future self) need to understand why\n3. **The `nolintlint` linter enforces both rules** — it will flag bare `//nolint` and missing reasons\n4. **MUST fix the root cause before suppressing** — only suppress after confirming the issue is a false positive or an intentional pattern\n\n## Examples\n\n```go\n// Specific linter with reason\n//nolint:errcheck // fire-and-forget logging, error not actionable\n_ = logger.Sync()\n\n// Type assertion is safe because preceding type switch guarantees the type\nv := x.(MyType) //nolint:forcetypeassert // guaranteed by type switch on line 42\n\n// Orchestration function has inherent complexity\n//nolint:gocyclo // orchestration function coordinating 8 subsystems\nfunc orchestrate() error {\n\n// Table-driven test with many cases\n//nolint:funlen // table-driven test, length is proportional to case count\nfunc TestParser(t *testing.T) {\n\n// Intentional parallel structure is clearer than abstracting\n//nolint:dupl // intentional parallel structure for readability\n```\n\n## Multiple Linters\n\nSuppress multiple linters on one line with comma separation:\n\n```go\n//nolint:errcheck,gosec // fire-and-forget in test helper\n```\n\n## When to Suppress vs. When to Fix\n\n**Fix** (almost always):\n\n- `errcheck` — check the error, even if just logging it\n- `govet` — these are usually real bugs\n- `staticcheck` — deprecated API usage, logic errors\n- `bodyclose`, `sqlclosecheck` — resource leaks are real issues\n\n**Suppress** (with justification):\n\n- `funlen` — table-driven tests with many cases\n- `gocyclo` — orchestration functions where splitting would obscure the flow\n- `dupl` — intentional parallel structure that is clearer than an abstraction\n- `exhaustive` — when a default case intentionally handles remaining values\n- `goconst` — when extracting to a constant would reduce clarity (e.g., test assertions)\n\n**Never suppress without strong justification**:\n\n- Security linters (`bodyclose`, `sqlclosecheck`, `rowserrcheck`) — these catch real resource leaks\n- `errcheck` on production code paths — unchecked errors cause silent failures\n\nFile v1.2.1:skill-card.md\n\n## Description: <br>\nLinting best practices and golangci-lint configuration for Go projects, including running linters, configuring .golangci.yml, suppressing warnings with nolint directives, interpreting lint output, and selecting linters. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[samber](https://clawhub.ai/user/samber) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nDevelopers and engineering teams use this skill to configure and operate golangci-lint for Go projects, interpret lint findings, apply safe fixes, and write disciplined nolint suppressions when needed. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: Auto-fix, formatting, or parallel cleanup can legitimately modify Go source files and configuration. <br>\nMitigation: Confirm the target scope before execution and review the resulting git diff before accepting changes. <br>\nRisk: Incorrect nolint guidance could hide real security, resource leak, or error-handling defects. <br>\nMitigation: Require linter-specific nolint directives with justifications and avoid suppressing security or correctness findings without a strong documented reason. <br>\n\n\n## Reference(s): <br>\n- [Linter Reference](references/linter-reference.md) <br>\n- [Nolint Directives](references/nolint-directives.md) <br>\n- [Source Homepage](https://github.com/samber/cc-skills-golang) <br>\n- [ClawHub Skill Page](https://clawhub.ai/samber/golang-lint) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance] <br>\n**Output Format:** [Markdown with inline Go, YAML, Makefile, and shell command examples] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [May propose source edits, formatter runs, golangci-lint commands, .golangci.yml settings, and review guidance for lint findings.] <br>\n\n## Skill Version(s): <br>\n1.2.1 (source: server release metadata and artifact frontmatter) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v1.2.1:evals/evals.json\n\n[\n  {\n    \"id\": 1,\n    \"name\": \"nolint-directive-specificity\",\n    \"description\": \"Tests that nolint directives specify the linter name and include a justification — never bare //nolint\",\n    \"prompt\": \"I have a Go function that triggers several lint warnings. I want to suppress them. Write the nolint directives for these cases:\\n\\n1. A logger.Sync() call where the error is intentionally ignored\\n2. A type assertion that is guaranteed safe by a preceding type switch\\n3. A function with cyclomatic complexity of 15 that orchestrates 6 subsystems\\n4. A table-driven test function that is 200 lines long\\n5. A deprecated API call that we can't migrate yet\\n\\nShow the code with proper suppression directives.\",\n    \"trap\": \"Model uses bare //nolint without specifying the linter name, or omits the justification comment. May also use //nolint at the file level instead of per-line.\",\n    \"assertions\": [\n      {\n        \"id\": \"1.1\",\n        \"text\": \"Every //nolint directive specifies the linter name (e.g., //nolint:errcheck, //nolint:gocyclo) — NO bare //nolint without a linter name\"\n      },\n      {\n        \"id\": \"1.2\",\n        \"text\": \"Every //nolint directive includes a justification comment after // (e.g., //nolint:errcheck // fire-and-forget logging)\"\n      },\n      {\n        \"id\": \"1.3\",\n        \"text\": \"The type assertion uses //nolint:forcetypeassert with an explanation referencing why the assertion is safe\"\n      },\n      {\n        \"id\": \"1.4\",\n        \"text\": \"The long test function uses //nolint:funlen with a justification like 'table-driven test, length proportional to case count'\"\n      },\n      {\n        \"id\": \"1.5\",\n        \"text\": \"The cyclomatic complexity suppression uses //nolint:gocyclo with a justification about orchestration\"\n      }\n    ]\n  },\n  {\n    \"id\": 2,\n    \"name\": \"nolint-fix-vs-suppress-judgment\",\n    \"description\": \"Tests judgment about when to fix vs when to suppress — security and correctness linters should almost never be suppressed\",\n    \"prompt\": \"My Go codebase has these lint warnings. For each one, should I fix the code or suppress the warning? Explain.\\n\\n1. `bodyclose: response body not closed` on an HTTP client call\\n2. `funlen: function too long (150 lines)` on a table-driven test\\n3. `errcheck: error return not checked` on a database query in a request handler\\n4. `dupl: duplicate code block` on two similar but intentionally parallel handler functions\\n5. `sqlclosecheck: rows not closed` on a database query\\n6. `goconst: string 'application/json' repeated 4 times` in test assertions\",\n    \"trap\": \"Model suppresses bodyclose, errcheck on production DB code, or sqlclosecheck — these are real bugs, not style issues. Should only suppress funlen, dupl, and goconst with justifications.\",\n    \"assertions\": [\n      {\n        \"id\": \"2.1\",\n        \"text\": \"Recommends FIXING bodyclose — unclosed HTTP response bodies leak connections, this is a real resource leak\"\n      },\n      {\n        \"id\": \"2.2\",\n        \"text\": \"Recommends SUPPRESSING funlen on the table-driven test — length is proportional to test case count, splitting would be worse\"\n      },\n      {\n        \"id\": \"2.3\",\n        \"text\": \"Recommends FIXING errcheck on the database query — unchecked errors in production request handlers cause silent failures\"\n      },\n      {\n        \"id\": \"2.4\",\n        \"text\": \"Recommends SUPPRESSING dupl on intentional parallel structure — with a justification that the parallel pattern is clearer than abstracting\"\n      },\n      {\n        \"id\": \"2.5\",\n        \"text\": \"Recommends FIXING sqlclosecheck — unclosed sql.Rows leak database connections\"\n      },\n      {\n        \"id\": \"2.6\",\n        \"text\": \"Recommends SUPPRESSING goconst in tests — extracting 'application/json' to a constant in tests would reduce clarity\"\n      }\n    ]\n  },\n  {\n    \"id\": 3,\n    \"name\": \"golangci-yml-version-2-structure\",\n    \"description\": \"Tests knowledge of golangci-lint v2 config structure: version field, linters.enable/disable, formatters section\",\n    \"prompt\": \"Create a .golangci.yml configuration file for a Go project. Enable at least govet, staticcheck, errcheck, and gofumpt. Set the timeout to 5 minutes and configure errcheck to also check type assertions.\",\n    \"trap\": \"Model uses golangci-lint v1 config format (missing version: \\\"2\\\", using enable-all/disable-all, missing formatters section, putting gofumpt in linters instead of formatters).\",\n    \"assertions\": [\n      {\n        \"id\": \"3.1\",\n        \"text\": \"Config file has version: \\\"2\\\" at the top — golangci-lint v2 requires this field\"\n      },\n      {\n        \"id\": \"3.2\",\n        \"text\": \"Linters are listed under linters.enable (not enable-all with exclusions) — explicit listing is the recommended approach\"\n      },\n      {\n        \"id\": \"3.3\",\n        \"text\": \"gofumpt is configured under formatters.enable, NOT under linters.enable — formatters are a separate section in v2\"\n      },\n      {\n        \"id\": \"3.4\",\n        \"text\": \"errcheck has check-type-assertions: true in linters.settings.errcheck\"\n      },\n      {\n        \"id\": \"3.5\",\n        \"text\": \"Timeout is set under run.timeout: 5m\"\n      }\n    ]\n  },\n  {\n    \"id\": 4,\n    \"name\": \"linter-categories-correctness-vs-style\",\n    \"description\": \"Tests understanding of linter domains — which linters catch bugs vs which catch style issues\",\n    \"prompt\": \"I'm setting up golangci-lint for a new Go project and can only enable 10 linters due to team constraints. Which 10 should I prioritize and why? Categorize them.\",\n    \"trap\": \"Model prioritizes style linters (revive, godot, misspell) over correctness linters (govet, staticcheck, errcheck, nilerr). May also include deprecated or redundant linters.\",\n    \"assertions\": [\n      {\n        \"id\": \"4.1\",\n        \"text\": \"Includes govet and staticcheck — these are the highest-value correctness linters that catch real bugs\"\n      },\n      {\n        \"id\": \"4.2\",\n        \"text\": \"Includes errcheck — unchecked errors are the most common source of silent failures in Go\"\n      },\n      {\n        \"id\": \"4.3\",\n        \"text\": \"Prioritizes correctness/safety linters over style linters — bug-finding tools provide more value than formatting preferences\"\n      },\n      {\n        \"id\": \"4.4\",\n        \"text\": \"Includes at least one security linter (bodyclose, gosec, or sqlclosecheck) for resource leak prevention\"\n      },\n      {\n        \"id\": \"4.5\",\n        \"text\": \"Does NOT include both gocyclo and cyclop (redundant) or both gocognit and gocyclo (overlapping complexity checkers)\"\n      }\n    ]\n  },\n  {\n    \"id\": 5,\n    \"name\": \"legacy-codebase-incremental-adoption\",\n    \"description\": \"Tests the new-from-rev strategy for adopting linters on legacy code without drowning in warnings\",\n    \"prompt\": \"We have a large legacy Go codebase with 2000+ lint warnings. We want to adopt golangci-lint but can't fix everything at once. How should we approach this?\",\n    \"trap\": \"Model suggests suppressing all existing warnings with //nolint directives, or disabling linters until the code is clean. Doesn't know about new-from-rev for incremental adoption.\",\n    \"assertions\": [\n      {\n        \"id\": \"5.1\",\n        \"text\": \"Recommends setting issues.new-from-rev (e.g., HEAD~1 or main) in .golangci.yml to only lint new/changed code\"\n      },\n      {\n        \"id\": \"5.2\",\n        \"text\": \"Does NOT suggest adding //nolint directives to all 2000+ existing warnings — that's unmaintainable\"\n      },\n      {\n        \"id\": \"5.3\",\n        \"text\": \"Suggests gradually cleaning up old code over time while enforcing quality on new code\"\n      },\n      {\n        \"id\": \"5.4\",\n        \"text\": \"Suggests running golangci-lint run --fix for auto-fixable issues as a quick first pass\"\n      },\n      {\n        \"id\": \"5.5\",\n        \"text\": \"Mentions using parallel sub-agents or batching fixes by linter category (security, error handling, style) to tackle cleanup efficiently\"\n      }\n    ]\n  },\n  {\n    \"id\": 6,\n    \"name\": \"interpreting-lint-output-format\",\n    \"description\": \"Tests ability to read lint output format and use the linter name for targeted investigation or suppression\",\n    \"prompt\": \"I ran golangci-lint and got this output:\\n\\n```\\nserver/handler.go:42:10: Error return value of `(*DB).Close` is not checked (errcheck)\\nserver/handler.go:55:2: response body must be closed (bodyclose)\\nserver/auth.go:12:6: func `validateToken` is unused (unused)\\nserver/auth.go:30:1: cyclomatic complexity 17 of func `processAuth` is high (> 13) (gocyclo)\\nserver/model.go:5:2: exported type `Model` should have comment or be unexported (revive)\\n```\\n\\nFor each warning, explain what it means and whether I should fix or suppress it.\",\n    \"trap\": \"Model doesn't use the linter name in parentheses to guide its response. May treat all warnings equally instead of recognizing that errcheck and bodyclose are critical while revive is style.\",\n    \"assertions\": [\n      {\n        \"id\": \"6.1\",\n        \"text\": \"Identifies errcheck on DB.Close as a real issue to fix — unchecked database close errors can mask connection problems\"\n      },\n      {\n        \"id\": \"6.2\",\n        \"text\": \"Identifies bodyclose as a critical resource leak to fix — not suppress\"\n      },\n      {\n        \"id\": \"6.3\",\n        \"text\": \"Identifies unused validateToken as dead code to either remove or fix — not suppress\"\n      },\n      {\n        \"id\": \"6.4\",\n        \"text\": \"For gocyclo, evaluates whether processAuth should be refactored or suppressed based on its nature (orchestration function vs genuinely complex logic)\"\n      },\n      {\n        \"id\": \"6.5\",\n        \"text\": \"For revive comment warning, correctly identifies it as a style issue that's lower priority than the correctness issues above\"\n      }\n    ]\n  },\n  {\n    \"id\": 7,\n    \"name\": \"disabled-linters-with-rationale\",\n    \"description\": \"Tests understanding of which linters should be disabled and why — the recommended config explicitly disables several with reasons\",\n    \"prompt\": \"A colleague wants to enable these linters in our .golangci.yml: exhaustruct, gochecknoglobals, wrapcheck, mnd (magic number detector), and varnamelen. Should we? Explain your reasoning for each.\",\n    \"trap\": \"Model enables all of them without considering that they are intentionally excluded from the recommended config due to being too noisy, too opinionated, or breaking idiomatic Go patterns.\",\n    \"assertions\": [\n      {\n        \"id\": \"7.1\",\n        \"text\": \"Recommends AGAINST exhaustruct — it requires all struct fields to be set, which breaks Go's zero-value idiom and is extremely noisy\"\n      },\n      {\n        \"id\": \"7.2\",\n        \"text\": \"Recommends AGAINST gochecknoglobals — there are many valid uses for global variables in Go (loggers, registries, etc.) and a blanket ban is too strict\"\n      },\n      {\n        \"id\": \"7.3\",\n        \"text\": \"Recommends AGAINST wrapcheck as a default — it forces wrapping all external errors, which is too noisy and not always appropriate\"\n      },\n      {\n        \"id\": \"7.4\",\n        \"text\": \"Recommends AGAINST mnd — magic number detection is extremely noisy, flagging obvious constants like HTTP status codes\"\n      },\n      {\n        \"id\": \"7.5\",\n        \"text\": \"Recommends AGAINST varnamelen — Go idiomatically favors short variable names, and this linter conflicts with that philosophy\"\n      }\n    ]\n  },\n  {\n    \"id\": 8,\n    \"name\": \"nolintlint-meta-linter\",\n    \"description\": \"Tests knowledge that nolintlint enforces proper nolint directive usage and should be enabled\",\n    \"prompt\": \"I see //nolint directives scattered throughout our Go codebase. Many are bare '//nolint' without specifying which linter or why. How can I enforce proper nolint hygiene automatically?\",\n    \"trap\": \"Model suggests a manual code review process or a custom script instead of enabling the nolintlint linter with require-explanation and require-specific settings.\",\n    \"assertions\": [\n      {\n        \"id\": \"8.1\",\n        \"text\": \"Recommends enabling the nolintlint linter — it automatically enforces nolint directive quality\"\n      },\n      {\n        \"id\": \"8.2\",\n        \"text\": \"Configures nolintlint with require-specific: true to require linter names (not bare //nolint)\"\n      },\n      {\n        \"id\": \"8.3\",\n        \"text\": \"Configures nolintlint with require-explanation: true to require justification comments\"\n      },\n      {\n        \"id\": \"8.4\",\n        \"text\": \"Shows the correct config location: linters.settings.nolintlint in .golangci.yml\"\n      }\n    ]\n  },\n  {\n    \"id\": 9,\n    \"name\": \"multiple-nolint-comma-syntax\",\n    \"description\": \"Tests proper syntax for suppressing multiple linters on one line\",\n    \"prompt\": \"I have a line of Go code that triggers both errcheck and gosec warnings. I've confirmed both are false positives in this specific case. How do I suppress both on the same line?\",\n    \"trap\": \"Model uses two separate //nolint directives on the same line, or uses //nolint without comma separation, or stacks directives on consecutive lines for the same code line.\",\n    \"assertions\": [\n      {\n        \"id\": \"9.1\",\n        \"text\": \"Uses comma-separated linter names in a single directive: //nolint:errcheck,gosec — not two separate //nolint directives\"\n      },\n      {\n        \"id\": \"9.2\",\n        \"text\": \"Includes a justification comment after the directive explaining why both are false positives\"\n      },\n      {\n        \"id\": \"9.3\",\n        \"text\": \"The directive is placed on the same line as the flagged code or the line immediately above it\"\n      }\n    ]\n  },\n  {\n    \"id\": 10,\n    \"name\": \"common-config-issues\",\n    \"description\": \"Tests troubleshooting knowledge for golangci-lint: timeout, v1-to-v2 migration, linter-not-found\",\n    \"prompt\": \"I'm getting these errors with golangci-lint:\\n1. 'deadline exceeded' when running on our large monorepo\\n2. After upgrading to golangci-lint v2, my .golangci.yml throws config errors\\n3. 'linter modernize not found' even though I listed it in enable\\n\\nHow do I fix each?\",\n    \"trap\": \"Model doesn't know about the v2 config migration tool, suggests reinstalling for the linter-not-found issue instead of checking the golangci-lint version, or increases concurrency instead of timeout.\",\n    \"assertions\": [\n      {\n        \"id\": \"10.1\",\n        \"text\": \"For deadline exceeded: recommends increasing run.timeout in .golangci.yml (default is 5m, may need 10m+ for large repos)\"\n      },\n      {\n        \"id\": \"10.2\",\n        \"text\": \"For v1 config errors: recommends running golangci-lint migrate to convert the config format to v2\"\n      },\n      {\n        \"id\": \"10.3\",\n        \"text\": \"For linter not found: recommends checking the golangci-lint version — modernize requires v2.6.0+ or similar newer version\"\n      },\n      {\n        \"id\": \"10.4\",\n        \"text\": \"Mentions golangci-lint linters command to check available linters in the installed version\"\n      }\n    ]\n  },\n  {\n    \"id\": 11,\n    \"name\": \"formatter-vs-linter-distinction\",\n    \"description\": \"Tests that formatters (gofumpt, gofmt) are configured in the formatters section, not the linters section, and use the fmt subcommand\",\n    \"prompt\": \"I want to enforce consistent code formatting in my Go project using golangci-lint. I want gofumpt with extra rules. How do I set it up?\",\n    \"trap\": \"Model puts gofumpt in the linters.enable section instead of formatters.enable (v2 distinction), or doesn't mention the golangci-lint fmt subcommand for formatting.\",\n    \"assertions\": [\n      {\n        \"id\": \"11.1\",\n        \"text\": \"Configures gofumpt under formatters.enable, NOT linters.enable — formatters are a separate section in golangci-lint v2\"\n      },\n      {\n        \"id\": \"11.2\",\n        \"text\": \"Sets gofumpt extra-rules: true under formatters.settings.gofumpt\"\n      },\n      {\n        \"id\": \"11.3\",\n        \"text\": \"Mentions the golangci-lint fmt ./... command for running formatters — separate from golangci-lint run\"\n      },\n      {\n        \"id\": \"11.4\",\n        \"text\": \"Notes that gci and goimports are redundant with gofumpt and can be disabled\"\n      }\n    ]\n  }\n]\n\nArchive v1.1.2: 5 files, 12543 bytes\n\nFiles: evals/evals.json (16136b), references/linter-reference.md (5705b), references/nolint-directives.md (2531b), SKILL.md (6855b), _meta.json (130b)\n\nFile v1.1.2:SKILL.md\n\n---\nname: golang-lint\ndescription: \"Provides linting best practices and golangci-lint configuration for Go projects. Covers running linters, configuring .golangci.yml, suppressing warnings with nolint directives, interpreting lint output, and managing linter settings. Use this skill whenever the user runs linters, configures golangci-lint, asks about lint warnings or suppressions, sets up code quality tooling, or asks which linters to enable for a Go project. Also use when the user mentions golangci-lint, go vet, staticcheck, revive, or any Go linting tool.\"\nuser-invocable: true\nlicense: MIT\ncompatibility: Designed for Claude Code or similar AI coding agents, and for projects using Golang.\nmetadata:\n  author: samber\n  version: \"1.1.2\"\n  openclaw:\n    emoji: \"🧹\"\n    homepage: https://github.com/samber/cc-skills-golang\n    requires:\n      bins:\n        - go\n        - golangci-lint\n    install:\n      - kind: brew\n        formula: golangci-lint\n        bins: [golangci-lint]\nallowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent\n---\n\n**Persona:** You are a Go code quality engineer. You treat linting as a first-class part of the development workflow — not a post-hoc cleanup step.\n\n**Modes:**\n\n- **Setup mode** — configuring `.golangci.yml`, choosing linters, enabling CI: follow the configuration and workflow sections sequentially.\n- **Coding mode** — writing new Go code: launch a background agent running `golangci-lint run --fix` on the modified files only while the main agent continues implementing the feature; surface results when it completes.\n- **Interpret/fix mode** — reading lint output, suppressing warnings, fixing issues on existing code: start from \"Interpreting Output\" and \"Suppressing Lint Warnings\"; use parallel sub-agents for large-scale legacy cleanup.\n\n# Go Linting\n\n## Overview\n\n`golangci-lint` is the standard Go linting tool. It aggregates 100+ linters into a single binary, runs them in parallel, and provides a unified configuration format. Run it frequently during development and always in CI.\n\nEvery Go project MUST have a `.golangci.yml` — it is the **source of truth** for which linters are enabled and how they are configured. See the [recommended configuration](./assets/.golangci.yml) for a production-ready setup with 33 linters enabled.\n\n## Quick Reference\n\n```bash\n# Run all configured linters\ngolangci-lint run ./...\n\n# Auto-fix issues where possible\ngolangci-lint run --fix ./...\n\n# Format code (golangci-lint v2+)\ngolangci-lint fmt ./...\n\n# Run a single linter only\ngolangci-lint run --enable-only govet ./...\n\n# List all available linters\ngolangci-lint linters\n\n# Verbose output with timing info\ngolangci-lint run --verbose ./...\n```\n\n## Configuration\n\nThe [recommended .golangci.yml](./assets/.golangci.yml) provides a production-ready setup with 33 linters. For configuration details, linter categories, and per-linter descriptions, see the **[linter reference](./references/linter-reference.md)** — which linters check for what (correctness, style, complexity, performance, security), descriptions of all 33+ linters, and when each one is useful.\n\n## Suppressing Lint Warnings\n\nUse `//nolint` directives sparingly — fix the root cause first.\n\n```go\n// Good: specific linter + justification\n//nolint:errcheck // fire-and-forget logging, error is not actionable\n_ = logger.Sync()\n\n// Bad: blanket suppression without reason\n//nolint\n_ = logger.Sync()\n```\n\nRules:\n\n1. **//nolint directives MUST specify the linter name**: `//nolint:errcheck` not `//nolint`\n2. **//nolint directives MUST include a justification comment**: `//nolint:errcheck // reason`\n3. **The `nolintlint` linter enforces both rules above** — it flags bare `//nolint` and missing reasons\n4. **NEVER suppress security linters** (bodyclose, sqlclosecheck) without a very strong reason\n\nFor comprehensive patterns and examples, see **[nolint directives](./references/nolint-directives.md)** — when to suppress, how to write justifications, patterns for per-line vs per-function suppression, and anti-patterns.\n\n## Development Workflow\n\n1. **Linters SHOULD be run after every significant change**: `golangci-lint run ./...`\n2. **Auto-fix what you can**: `golangci-lint run --fix ./...`\n3. **Format before committing**: `golangci-lint fmt ./...`\n4. **Incremental adoption on legacy code**: set `issues.new-from-rev` in `.golangci.yml` to only lint new/changed code, then gradually clean up old code\n\nMakefile targets (recommended):\n\n```makefile\nlint:\n\tgolangci-lint run ./...\n\nlint-fix:\n\tgolangci-lint run --fix ./...\n\nfmt:\n\tgolangci-lint fmt ./...\n```\n\nFor CI pipeline setup (GitHub Actions with `golangci-lint-action`), see the `samber/cc-skills-golang@golang-continuous-integration` skill.\n\n## Interpreting Output\n\nEach issue follows this format:\n\n```\npath/to/file.go:42:10: message describing the issue (linter-name)\n```\n\nThe linter name in parentheses tells you which linter flagged it. Use this to:\n\n- Look up the linter in the [reference](./references/linter-reference.md) to understand what it checks\n- Suppress with `//nolint:linter-name // reason` if it's a false positive\n- Use `golangci-lint run --verbose` for additional context and timing\n\n## Common Issues\n\n| Problem | Solution |\n| --- | --- |\n| \"deadline exceeded\" | Increase `run.timeout` in `.golangci.yml` (default: 5m) |\n| Too many issues on legacy code | Set `issues.new-from-rev: HEAD~1` to lint only new code |\n| Linter not found | Check `golangci-lint linters` — linter may need a newer version |\n| Conflicts between linters | Disable the less useful one with a comment explaining why |\n| v1 config errors after upgrade | Run `golangci-lint migrate` to convert config format |\n| Slow on large repos | Reduce `run.concurrency` or exclude directories in `run.skip-dirs` |\n\n## Parallelizing Legacy Codebase Cleanup\n\nWhen adopting linting on a legacy codebase, use up to 5 parallel sub-agents (via the Agent tool) to fix independent linter categories simultaneously:\n\n- Sub-agent 1: Run `golangci-lint run --fix ./...` for auto-fixable issues\n- Sub-agent 2: Fix security linter findings (bodyclose, sqlclosecheck, gosec)\n- Sub-agent 3: Fix error handling issues (errcheck, nilerr, wrapcheck)\n- Sub-agent 4: Fix style and formatting (gofumpt, goimports, revive)\n- Sub-agent 5: Fix code quality (gocritic, unused, ineffassign)\n\n## Cross-References\n\n- → See `samber/cc-skills-golang@golang-continuous-integration` skill for CI pipeline with golangci-lint-action\n- → See `samber/cc-skills-golang@golang-code-style` skill for style rules that linters enforce\n- → See `samber/cc-skills-golang@golang-security` skill for SAST tools beyond linting (gosec, govulncheck)\n- → See `samber/cc-skills-golang@golang-continuous-integration` skill for automated AI-driven code review in CI using these guidelines\n\nFile v1.1.2:_meta.json\n\n{\n  \"ownerId\": \"kn72rhnkwjfeex9wr1n7y24qa983cjn3\",\n  \"slug\": \"golang-lint\",\n  \"version\": \"1.1.2\",\n  \"publishedAt\": 1777554313202\n}\n\nFile v1.1.2:references/linter-reference.md\n\n# Linter Reference\n\ngolangci-lint v2 uses a `.golangci.yml` with `version: \"2\"` at the project root.\n\nKey sections of `.golangci.yml`:\n\n- **`run`** — concurrency, timeout, test inclusion, directory exclusions\n- **`linters.enable`** / **`linters.disable`** — which linters are active\n- **`linters.settings`** — per-linter thresholds and options\n- **`formatters`** — code formatters (gofmt, gofumpt)\n- **`issues`** — output limits, exclusion rules\n\nTo add a linter: add it to `linters.enable` and optionally configure it in `linters.settings`.\n\nTo disable a linter: move it to `linters.disable` with a comment explaining why.\n\n## Linter Categories\n\nThe recommended configuration enables linters across these domains:\n\n| Domain | Linters | Catches |\n| --- | --- | --- |\n| Correctness | govet, staticcheck, unused, errcheck, nilerr, forcetypeassert, copyloopvar | Bugs, unchecked errors, stdlib misuse |\n| Style | gocritic, revive, wsl_v5, whitespace, godot, misspell, predeclared, errname | Readability, naming, consistency |\n| Complexity | gocyclo, nestif, funlen, dupl | Overly complex or duplicated code |\n| Performance | perfsprint, unconvert, ineffassign, goconst | Conversions, string ops, dead assigns |\n| Security | bodyclose, sqlclosecheck, rowserrcheck | Resource leaks (HTTP, SQL) |\n| Testing | thelper, paralleltest, testifylint | Test hygiene and best practices |\n| Modernization | modernize, intrange, usestdlibvars, exhaustive, nolintlint | Modern Go idioms, lint hygiene |\n| Formatting | gofmt, gofumpt | Code formatting |\n\nAll linters are enabled in the [recommended .golangci.yml](./.golangci.yml), organized by domain.\n\n### Correctness & Safety\n\n- **govet** — Go's built-in checker: copylocks, printf format mismatches, struct tag validation, context stored in structs, unreachable code, nil dereferences\n- **staticcheck** — Extensive static analysis: deprecated APIs, common mistakes, unnecessary code, simplifications, misuse of standard library\n- **unused** — Detects unused variables, functions, types, and struct fields\n- **errcheck** — Ensures all error returns are checked, including type assertions (configured with `check-type-assertions: true`)\n- **nilerr** — Detects returning nil error when `err` is non-nil (common source of silent failures)\n- **forcetypeassert** — Flags type assertions without the comma-ok check (`v := x.(T)` instead of `v, ok := x.(T)`)\n- **copyloopvar** — Detects loop variable copy issues (Go 1.22+)\n\n### Style & Readability\n\n- **gocritic** — Opinionated style checks: unnecessary conversions, range copies, append-assign patterns, redundant code\n- **revive** — Naming conventions for exported types, unexported returns, receiver naming, error naming, stuttered package names\n- **wsl_v5** — Whitespace and blank line rules for visual grouping and readability\n- **whitespace** — Detects trailing whitespace and unnecessary blank lines in function bodies\n- **godot** — Ensures exported-symbol comments end with a period\n- **misspell** — Catches common English misspellings in identifiers and comments\n- **predeclared** — Flags shadowing of Go built-in identifiers (e.g., naming a variable `len`, `cap`, `error`)\n- **errname** — Enforces error naming conventions: error types suffixed with `Error` (e.g., `DecodeError`), error variables prefixed with `Err` (e.g., `ErrNotFound`)\n\n### Complexity\n\n- **gocyclo** — Cyclomatic complexity threshold (configured: 13). Functions exceeding this should be split\n- **nestif** — Detects deeply nested if/else chains that harm readability\n- **funlen** — Function length limits (configured: 120 lines, 80 statements)\n- **dupl** — Code duplication detection (configured: 20 token threshold)\n\n### Performance\n\n- **perfsprint** — Suggests faster alternatives to `fmt.Sprintf` (e.g., `strconv.Itoa` instead of `fmt.Sprintf(\"%d\", n)`)\n- **unconvert** — Detects unnecessary type conversions (e.g., `int(x)` when `x` is already `int`)\n- **ineffassign** — Detects assignments to variables that are never subsequently read\n- **goconst** — Detects repeated string/number literals that should be extracted to constants (configured: min 2 chars, min 3 occurrences)\n\n### Security & Resources\n\n- **bodyclose** — Ensures HTTP response bodies are closed (unclosed bodies leak connections)\n- **sqlclosecheck** — Ensures `sql.Rows` and `sql.Stmt` are closed after use\n- **rowserrcheck** — Ensures `sql.Rows.Err()` is checked after iteration\n\n### Testing\n\n- **thelper** — Ensures test helpers call `t.Helper()` so failures report the correct call site\n- **paralleltest** — Detects tests and subtests missing `t.Parallel()` calls\n- **testifylint** — Enforces testify best practices (e.g., `assert.Equal(t, expected, actual)` over `assert.True(t, expected == actual)`)\n\n### Modernization & Meta\n\n- **modernize** — Detects code that can be rewritten using newer Go features (requires golangci-lint v2.6.0+)\n- **intrange** — Suggests `range N` over C-style `for i := 0; i < N; i++` loops (Go 1.22+)\n- **usestdlibvars** — Replaces hardcoded strings/numbers with stdlib constants (e.g., `http.MethodGet` instead of `\"GET\"`)\n- **exhaustive** — Ensures switch statements on enum types cover all possible values\n- **nolintlint** — Enforces proper `//nolint` directive usage: requires linter name and justification comment (configured with `require-explanation` and `require-specific`)\n\n### Formatting\n\nFormatters run via `golangci-lint fmt ./...`:\n\n- **gofmt** — Standard Go formatter (canonical formatting)\n- **gofumpt** — Stricter formatter with extra rules (configured with `extra-rules: true`): consistent empty lines, grouped imports, simplified code patterns\n\nFile v1.1.2:references/nolint-directives.md\n\n# Nolint Directives\n\n## Syntax\n\n```go\n//nolint:lintername // justification explaining why this suppression is needed\n```\n\nPlace the directive on the same line as the flagged code, or on the line immediately above it.\n\n## Rules\n\n1. **MUST specify the linter name** — bare `//nolint` suppresses all linters on that line and makes it impossible to track what is being suppressed\n2. **MUST add a justification comment** — future readers (and your future self) need to understand why\n3. **The `nolintlint` linter enforces both rules** — it will flag bare `//nolint` and missing reasons\n4. **MUST fix the root cause before suppressing** — only suppress after confirming the issue is a false positive or an intentional pattern\n\n## Examples\n\n```go\n// Specific linter with reason\n//nolint:errcheck // fire-and-forget logging, error not actionable\n_ = logger.Sync()\n\n// Type assertion is safe because preceding type switch guarantees the type\nv := x.(MyType) //nolint:forcetypeassert // guaranteed by type switch on line 42\n\n// Orchestration function has inherent complexity\n//nolint:gocyclo // orchestration function coordinating 8 subsystems\nfunc orchestrate() error {\n\n// Table-driven test with many cases\n//nolint:funlen // table-driven test, length is proportional to case count\nfunc TestParser(t *testing.T) {\n\n// Intentional parallel structure is clearer than abstracting\n//nolint:dupl // intentional parallel structure for readability\n```\n\n## Multiple Linters\n\nSuppress multiple linters on one line with comma separation:\n\n```go\n//nolint:errcheck,gosec // fire-and-forget in test helper\n```\n\n## When to Suppress vs. When to Fix\n\n**Fix** (almost always):\n\n- `errcheck` — check the error, even if just logging it\n- `govet` — these are usually real bugs\n- `staticcheck` — deprecated API usage, logic errors\n- `bodyclose`, `sqlclosecheck` — resource leaks are real issues\n\n**Suppress** (with justification):\n\n- `funlen` — table-driven tests with many cases\n- `gocyclo` — orchestration functions where splitting would obscure the flow\n- `dupl` — intentional parallel structure that is clearer than an abstraction\n- `exhaustive` — when a default case intentionally handles remaining values\n- `goconst` — when extracting to a constant would reduce clarity (e.g., test assertions)\n\n**Never suppress without strong justification**:\n\n- Security linters (`bodyclose`, `sqlclosecheck`, `rowserrcheck`) — these catch real resource leaks\n- `errcheck` on production code paths — unchecked errors cause silent failures\n\nFile v1.1.2:evals/evals.json\n\n[\n  {\n    \"id\": 1,\n    \"name\": \"nolint-directive-specificity\",\n    \"description\": \"Tests that nolint directives specify the linter name and include a justification — never bare //nolint\",\n    \"prompt\": \"I have a Go function that triggers several lint warnings. I want to suppress them. Write the nolint directives for these cases:\\n\\n1. A logger.Sync() call where the error is intentionally ignored\\n2. A type assertion that is guaranteed safe by a preceding type switch\\n3. A function with cyclomatic complexity of 15 that orchestrates 6 subsystems\\n4. A table-driven test function that is 200 lines long\\n5. A deprecated API call that we can't migrate yet\\n\\nShow the code with proper suppression directives.\",\n    \"trap\": \"Model uses bare //nolint without specifying the linter name, or omits the justification comment. May also use //nolint at the file level instead of per-line.\",\n    \"assertions\": [\n      {\n        \"id\": \"1.1\",\n        \"text\": \"Every //nolint directive specifies the linter name (e.g., //nolint:errcheck, //nolint:gocyclo) — NO bare //nolint without a linter name\"\n      },\n      {\n        \"id\": \"1.2\",\n        \"text\": \"Every //nolint directive includes a justification comment after // (e.g., //nolint:errcheck // fire-and-forget logging)\"\n      },\n      {\n        \"id\": \"1.3\",\n        \"text\": \"The type assertion uses //nolint:forcetypeassert with an explanation referencing why the assertion is safe\"\n      },\n      {\n        \"id\": \"1.4\",\n        \"text\": \"The long test function uses //nolint:funlen with a justification like 'table-driven test, length proportional to case count'\"\n      },\n      {\n        \"id\": \"1.5\",\n        \"text\": \"The cyclomatic complexity suppression uses //nolint:gocyclo with a justification about orchestration\"\n      }\n    ]\n  },\n  {\n    \"id\": 2,\n    \"name\": \"nolint-fix-vs-suppress-judgment\",\n    \"description\": \"Tests judgment about when to fix vs when to suppress — security and correctness linters should almost never be suppressed\",\n    \"prompt\": \"My Go codebase has these lint warnings. For each one, should I fix the code or suppress the warning? Explain.\\n\\n1. `bodyclose: response body not closed` on an HTTP client call\\n2. `funlen: function too long (150 lines)` on a table-driven test\\n3. `errcheck: error return not checked` on a database query in a request handler\\n4. `dupl: duplicate code block` on two similar but intentionally parallel handler functions\\n5. `sqlclosecheck: rows not closed` on a database query\\n6. `goconst: string 'application/json' repeated 4 times` in test assertions\",\n    \"trap\": \"Model suppresses bodyclose, errcheck on production DB code, or sqlclosecheck — these are real bugs, not style issues. Should only suppress funlen, dupl, and goconst with justifications.\",\n    \"assertions\": [\n      {\n        \"id\": \"2.1\",\n        \"text\": \"Recommends FIXING bodyclose — unclosed HTTP response bodies leak connections, this is a real resource leak\"\n      },\n      {\n        \"id\": \"2.2\",\n        \"text\": \"Recommends SUPPRESSING funlen on the table-driven test — length is proportional to test case count, splitting would be worse\"\n      },\n      {\n        \"id\": \"2.3\",\n        \"text\": \"Recommends FIXING errcheck on the database query — unchecked errors in production request handlers cause silent failures\"\n      },\n      {\n        \"id\": \"2.4\",\n        \"text\": \"Recommends SUPPRESSING dupl on intentional parallel structure — with a justification that the parallel pattern is clearer than abstracting\"\n      },\n      {\n        \"id\": \"2.5\",\n        \"text\": \"Recommends FIXING sqlclosecheck — unclosed sql.Rows leak database connections\"\n      },\n      {\n        \"id\": \"2.6\",\n        \"text\": \"Recommends SUPPRESSING goconst in tests — extracting 'application/json' to a constant in tests would reduce clarity\"\n      }\n    ]\n  },\n  {\n    \"id\": 3,\n    \"name\": \"golangci-yml-version-2-structure\",\n    \"description\": \"Tests knowledge of golangci-lint v2 config structure: version field, linters.enable/disable, formatters section\",\n    \"prompt\": \"Create a .golangci.yml configuration file for a Go project. Enable at least govet, staticcheck, errcheck, and gofumpt. Set the timeout to 5 minutes and configure errcheck to also check type assertions.\",\n    \"trap\": \"Model uses golangci-lint v1 config format (missing version: \\\"2\\\", using enable-all/disable-all, missing formatters section, putting gofumpt in linters instead of formatters).\",\n    \"assertions\": [\n      {\n        \"id\": \"3.1\",\n        \"text\": \"Config file has version: \\\"2\\\" at the top — golangci-lint v2 requires this field\"\n      },\n      {\n        \"id\": \"3.2\",\n        \"text\": \"Linters are listed under linters.enable (not enable-all with exclusions) — explicit listing is the recommended approach\"\n      },\n      {\n        \"id\": \"3.3\",\n        \"text\": \"gofumpt is configured under formatters.enable, NOT under linters.enable — formatters are a separate section in v2\"\n      },\n      {\n        \"id\": \"3.4\",\n        \"text\": \"errcheck has check-type-assertions: true in linters.settings.errcheck\"\n      },\n      {\n        \"id\": \"3.5\",\n        \"text\": \"Timeout is set under run.timeout: 5m\"\n      }\n    ]\n  },\n  {\n    \"id\": 4,\n    \"name\": \"linter-categories-correctness-vs-style\",\n    \"description\": \"Tests understanding of linter domains — which linters catch bugs vs which catch style issues\",\n    \"prompt\": \"I'm setting up golangci-lint for a new Go project and can only enable 10 linters due to team constraints. Which 10 should I prioritize and why? Categorize them.\",\n    \"trap\": \"Model prioritizes style linters (revive, godot, misspell) over correctness linters (govet, staticcheck, errcheck, nilerr). May also include deprecated or redundant linters.\",\n    \"assertions\": [\n      {\n        \"id\": \"4.1\",\n        \"text\": \"Includes govet and staticcheck — these are the highest-value correctness linters that catch real bugs\"\n      },\n      {\n        \"id\": \"4.2\",\n        \"text\": \"Includes errcheck — unchecked errors are the most common source of silent failures in Go\"\n      },\n      {\n        \"id\": \"4.3\",\n        \"text\": \"Prioritizes correctness/safety linters over style linters — bug-finding tools provide more value than formatting preferences\"\n      },\n      {\n        \"id\": \"4.4\",\n        \"text\": \"Includes at least one security linter (bodyclose, gosec, or sqlclosecheck) for resource leak prevention\"\n      },\n      {\n        \"id\": \"4.5\",\n        \"text\": \"Does NOT include both gocyclo and cyclop (redundant) or both gocognit and gocyclo (overlapping complexity checkers)\"\n      }\n    ]\n  },\n  {\n    \"id\": 5,\n    \"name\": \"legacy-codebase-incremental-adoption\",\n    \"description\": \"Tests the new-from-rev strategy for adopting linters on legacy code without drowning in warnings\",\n    \"prompt\": \"We have a large legacy Go codebase with 2000+ lint warnings. We want to adopt golangci-lint but can't fix everything at once. How should we approach this?\",\n    \"trap\": \"Model suggests suppressing all existing warnings with //nolint directives, or disabling linters until the code is clean. Doesn't know about new-from-rev for incremental adoption.\",\n    \"assertions\": [\n      {\n        \"id\": \"5.1\",\n        \"text\": \"Recommends setting issues.new-from-rev (e.g., HEAD~1 or main) in .golangci.yml to only lint new/changed code\"\n      },\n      {\n        \"id\": \"5.2\",\n        \"text\": \"Does NOT suggest adding //nolint directives to all 2000+ existing warnings — that's unmaintainable\"\n      },\n      {\n        \"id\": \"5.3\",\n        \"text\": \"Suggests gradually cleaning up old code over time while enforcing quality on new code\"\n      },\n      {\n        \"id\": \"5.4\",\n        \"text\": \"Suggests running golangci-lint run --fix for auto-fixable issues as a quick first pass\"\n      },\n      {\n        \"id\": \"5.5\",\n        \"text\": \"Mentions using parallel sub-agents or batching fixes by linter category (security, error handling, style) to tackle cleanup efficiently\"\n      }\n    ]\n  },\n  {\n    \"id\": 6,\n    \"name\": \"interpreting-lint-output-format\",\n    \"description\": \"Tests ability to read lint output format and use the linter name for targeted investigation or suppression\",\n    \"prompt\": \"I ran golangci-lint and got this output:\\n\\n```\\nserver/handler.go:42:10: Error return value of `(*DB).Close` is not checked (errcheck)\\nserver/handler.go:55:2: response body must be closed (bodyclose)\\nserver/auth.go:12:6: func `validateToken` is unused (unused)\\nserver/auth.go:30:1: cyclomatic complexity 17 of func `processAuth` is high (> 13) (gocyclo)\\nserver/model.go:5:2: exported type `Model` should have comment or be unexported (revive)\\n```\\n\\nFor each warning, explain what it means and whether I should fix or suppress it.\",\n    \"trap\": \"Model doesn't use the linter name in parentheses to guide its response. May treat all warnings equally instead of recognizing that errcheck and bodyclose are critical while revive is style.\",\n    \"assertions\": [\n      {\n        \"id\": \"6.1\",\n        \"text\": \"Identifies errcheck on DB.Close as a real issue to fix — unchecked database close errors can mask connection problems\"\n      },\n      {\n        \"id\": \"6.2\",\n        \"text\": \"Identifies bodyclose as a critical resource leak to fix — not suppress\"\n      },\n      {\n        \"id\": \"6.3\",\n        \"text\": \"Identifies unused validateToken as dead code to either remove or fix — not suppress\"\n      },\n      {\n        \"id\": \"6.4\",\n        \"text\": \"For gocyclo, evaluates whether processAuth should be refactored or suppressed based on its nature (orchestration function vs genuinely complex logic)\"\n      },\n      {\n        \"id\": \"6.5\",\n        \"text\": \"For revive comment warning, correctly identifies it as a style issue that's lower priority than the correctness issues above\"\n      }\n    ]\n  },\n  {\n    \"id\": 7,\n    \"name\": \"disabled-linters-with-rationale\",\n    \"description\": \"Tests understanding of which linters should be disabled and why — the recommended config explicitly disables several with reasons\",\n    \"prompt\": \"A colleague wants to enable these linters in our .golangci.yml: exhaustruct, gochecknoglobals, wrapcheck, mnd (magic number detector), and varnamelen. Should we? Explain your reasoning for each.\",\n    \"trap\": \"Model enables all of them without considering that they are intentionally excluded from the recommended config due to being too noisy, too opinionated, or breaking idiomatic Go patterns.\",\n    \"assertions\": [\n      {\n        \"id\": \"7.1\",\n        \"text\": \"Recommends AGAINST exhaustruct — it requires all struct fields to be set, which breaks Go's zero-value idiom and is extremely noisy\"\n      },\n      {\n        \"id\": \"7.2\",\n        \"text\": \"Recommends AGAINST gochecknoglobals — there are many valid uses for global variables in Go (loggers, registries, etc.) and a blanket ban is too strict\"\n      },\n      {\n        \"id\": \"7.3\",\n        \"text\": \"Recommends AGAINST wrapcheck as a default — it forces wrapping all external errors, which is too noisy and not always appropriate\"\n      },\n      {\n        \"id\": \"7.4\",\n        \"text\": \"Recommends AGAINST mnd — magic number detection is extremely noisy, flagging obvious constants like HTTP status codes\"\n      },\n      {\n        \"id\": \"7.5\",\n        \"text\": \"Recommends AGAINST varnamelen — Go idiomatically favors short variable names, and this linter conflicts with that philosophy\"\n      }\n    ]\n  },\n  {\n    \"id\": 8,\n    \"name\": \"nolintlint-meta-linter\",\n    \"description\": \"Tests knowledge that nolintlint enforces proper nolint directive usage and should be enabled\",\n    \"prompt\": \"I see //nolint directives scattered throughout our Go codebase. Many are bare '//nolint' without specifying which linter or why. How can I enforce proper nolint hygiene automatically?\",\n    \"trap\": \"Model suggests a manual code review process or a custom script instead of enabling the nolintlint linter with require-explanation and require-specific settings.\",\n    \"assertions\": [\n      {\n        \"id\": \"8.1\",\n        \"text\": \"Recommends enabling the nolintlint linter — it automatically enforces nolint directive quality\"\n      },\n      {\n        \"id\": \"8.2\",\n        \"text\": \"Configures nolintlint with require-specific: true to require linter names (not bare //nolint)\"\n      },\n      {\n        \"id\": \"8.3\",\n        \"text\": \"Configures nolintlint with require-explanation: true to require justification comments\"\n      },\n      {\n        \"id\": \"8.4\",\n        \"text\": \"Shows the correct config location: linters.settings.nolintlint in .golangci.yml\"\n      }\n    ]\n  },\n  {\n    \"id\": 9,\n    \"name\": \"multiple-nolint-comma-syntax\",\n    \"description\": \"Tests proper syntax for suppressing multiple linters on one line\",\n    \"prompt\": \"I have a line of Go code that triggers both errcheck and gosec warnings. I've confirmed both are false positives in this specific case. How do I suppress both on the same line?\",\n    \"trap\": \"Model uses two separate //nolint directives on the same line, or uses //nolint without comma separation, or stacks directives on consecutive lines for the same code line.\",\n    \"assertions\": [\n      {\n        \"id\": \"9.1\",\n        \"text\": \"Uses comma-separated linter names in a single directive: //nolint:errcheck,gosec — not two separate //nolint directives\"\n      },\n      {\n        \"id\": \"9.2\",\n        \"text\": \"Includes a justification comment after the directive explaining why both are false positives\"\n      },\n      {\n        \"id\": \"9.3\",\n        \"text\": \"The directive is placed on the same line as the flagged code or the line immediately above it\"\n      }\n    ]\n  },\n  {\n    \"id\": 10,\n    \"name\": \"common-config-issues\",\n    \"description\": \"Tests troubleshooting knowledge for golangci-lint: timeout, v1-to-v2 migration, linter-not-found\",\n    \"prompt\": \"I'm getting these errors with golangci-lint:\\n1. 'deadline exceeded' when running on our large monorepo\\n2. After upgrading to golangci-lint v2, my .golangci.yml throws config errors\\n3. 'linter modernize not found' even though I listed it in enable\\n\\nHow do I fix each?\",\n    \"trap\": \"Model doesn't know about the v2 config migration tool, suggests reinstalling for the linter-not-found issue instead of checking the golangci-lint version, or increases concurrency instead of timeout.\",\n    \"assertions\": [\n      {\n        \"id\": \"10.1\",\n        \"text\": \"For deadline exceeded: recommends increasing run.timeout in .golangci.yml (default is 5m, may need 10m+ for large repos)\"\n      },\n      {\n        \"id\": \"10.2\",\n        \"text\": \"For v1 config errors: recommends running golangci-lint migrate to convert the config format to v2\"\n      },\n      {\n        \"id\": \"10.3\",\n        \"text\": \"For linter not found: recommends checking the golangci-lint version — modernize requires v2.6.0+ or similar newer version\"\n      },\n      {\n        \"id\": \"10.4\",\n        \"text\": \"Mentions golangci-lint linters command to check available linters in the installed version\"\n      }\n    ]\n  },\n  {\n    \"id\": 11,\n    \"name\": \"formatter-vs-linter-distinction\",\n    \"description\": \"Tests that formatters (gofumpt, gofmt) are configured in the formatters section, not the linters section, and use the fmt subcommand\",\n    \"prompt\": \"I want to enforce consistent code formatting in my Go project using golangci-lint. I want gofumpt with extra rules. How do I set it up?\",\n    \"trap\": \"Model puts gofumpt in the linters.enable section instead of formatters.enable (v2 distinction), or doesn't mention the golangci-lint fmt subcommand for formatting.\",\n    \"assertions\": [\n      {\n        \"id\": \"11.1\",\n        \"text\": \"Configures gofumpt under formatters.enable, NOT linters.enable — formatters are a separate section in golangci-lint v2\"\n      },\n      {\n        \"id\": \"11.2\",\n        \"text\": \"Sets gofumpt extra-rules: true under formatters.settings.gofumpt\"\n      },\n      {\n        \"id\": \"11.3\",\n        \"text\": \"Mentions the golangci-lint fmt ./... command for running formatters — separate from golangci-lint run\"\n      },\n      {\n        \"id\": \"11.4\",\n        \"text\": \"Notes that gci and goimports are redundant with gofumpt and can be disabled\"\n      }\n    ]\n  }\n]","readmeExcerpt":"Skill: golang-lint Owner: samber Summary: Linting best practices and golangci-lint configuration for Golang projects — running linters, configuring .golangci.yml, suppressing warnings with nolint directives, interpreting lint output, and selecting linters. Use when configuring golangci-lint, asking about lint warnings or nolint suppressions, setting up code quality tooling, or choosing linters. Also use when the user","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"# Run all configured linters\ngolangci-lint run ./...\n\n# Auto-fix issues where possible\ngolangci-lint run --fix ./...\n\n# Format code (golangci-lint v2+)\ngolangci-lint fmt ./...\n\n# Run a single linter only\ngolangci-lint run --enable-only govet ./...\n\n# List all available linters\ngolangci-lint linters\n\n# Verbose output with timing info\ngolangci-lint run --verbose ./..."},{"language":"go","snippet":"// Good: specific linter + justification\n//nolint:errcheck // fire-and-forget logging, error is not actionable\n_ = logger.Sync()\n\n// Bad: blanket suppression without reason\n//nolint\n_ = logger.Sync()"},{"language":"makefile","snippet":"lint:\n\tgolangci-lint run ./...\n\nlint-fix:\n\tgolangci-lint run --fix ./...\n\nfmt:\n\tgolangci-lint fmt ./..."},{"language":"text","snippet":"path/to/file.go:42:10: message describing the issue (linter-name)"},{"language":"go","snippet":"//nolint:lintername // justification explaining why this suppression is needed"},{"language":"go","snippet":"// Specific linter with reason\n//nolint:errcheck // fire-and-forget logging, error not actionable\n_ = logger.Sync()\n\n// Type assertion is safe because preceding type switch guarantees the type\nv := x.(MyType) //nolint:forcetypeassert // guaranteed by type switch on line 42\n\n// Orchestration function has inherent complexity\n//nolint:gocyclo // orchestration function coordinating 8 subsystems\nfunc orchestrate() error {\n\n// Table-driven test with many cases\n//nolint:funlen // table-driven test, length is proportional to case count\nfunc TestParser(t *testing.T) {\n\n// Intentional parallel structure is clearer than abstracting\n//nolint:dupl // intentional parallel structure for readability"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: golang-lint\ndescription: \"Linting best practices and golangci-lint configuration for Golang projects — running linters, configuring .golangci.yml, suppressing warnings with nolint directives, interpreting lint output, and selecting linters. Use when configuring golangci-lint, asking about lint warnings or nolint suppressions, setting up code quality tooling, or choosing linters. Also use when the user mentions golangci-lint, go vet, staticcheck, or revive.\"\nuser-invocable: true\nlicense: MIT\ncompatibility: Designed for Claude Code, Codex or similar harness, and for projects using Golang.\nmetadata:\n  author: samber\n  version: \"1.4.0\"\n  openclaw:\n    emoji: \"🧹\"\n    homepage: https://github.com/samber/cc-skills-golang\n    requires:\n      bins:\n        - go\n        - golangci-lint\n    install:\n      - kind: brew\n        formula: golangci-lint\n        bins: [golangci-lint]\nallowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent\npaths:\n  - \"**/*.go\"\n  - \".golangci.yml\"\n---\n\n**Persona:** You are a Go code quality engineer. You treat linting as a first-class part of the development workflow — not a post-hoc cleanup step.\n\n**Orchestration mode:** Fan out the five sub-agents described in the \"Parallelizing Legacy Codebase Cleanup\" section (auto-fix, security linters, error handling, style/formatting, code quality) when adopting linting on a legacy codebase, so independent linter categories are fixed concurrently. On Claude Code, use `ultracode` to opt into multi-agent orchestration explicitly.\n\n**Modes:**\n\n- **Setup mode** — configuring `.golangci.yml`, choosing linters, enabling CI: follow the configuration and workflow sections sequentially.\n- **Coding mode** — writing new Go code: launch a background agent running `golangci-lint run --fix` on the modified files only while the main agent continues implementing the feature; surface results when it completes.\n- **Interpret/fix mode** — reading lint output, suppressing warnings, fixing issues on existing code: start from \"Interpreting Output\" and \"Suppressing Lint Warnings\"; use parallel sub-agents for large-scale legacy cleanup.\n\n**Dependencies:**\n\n- golangci-lint: `go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest`\n\n# Go Linting\n\n## Overview\n\n`golangci-lint` is the standard Go linting tool. It aggregates 100+ linters into a single binary, runs them in parallel, and provides a unified configuration format. Run it frequently during development and always in CI.\n\nEvery Go project MUST have a `.golangci.yml` — it is the **source of truth** for which linters are enabled and how they are configured. See the [recommended configuration](./assets/.golangci.yml) for a production-ready setup with 48 linters enabled.\n\n## Quick Reference\n\n```bash\n# Run all configured linters\ngolangci-lint run ./...\n\n# Auto-fix issues where possible\ngolangci-lint run --fix ./...\n\n# Format code (golangci-lint v2+)\ngolangci-lint fmt ./...\n\n# Run a single linter only\ngolang"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn72rhnkwjfeex9wr1n7y24qa983cjn3\",\n  \"slug\": \"golang-lint\",\n  \"version\": \"1.4.0\",\n  \"publishedAt\": 1787329318465\n}"},{"path":"references/linter-reference.md","content":"# Linter Reference\n\ngolangci-lint v2 uses a `.golangci.yml` with `version: \"2\"` at the project root.\n\nKey sections of `.golangci.yml`:\n\n- **`run`** — concurrency, timeout, test inclusion, directory exclusions\n- **`linters.enable`** / **`linters.disable`** — which linters are active\n- **`linters.settings`** — per-linter thresholds and options\n- **`formatters`** — code formatters (gofmt, gofumpt)\n- **`issues`** — output limits, exclusion rules\n\nTo add a linter: add it to `linters.enable` and optionally configure it in `linters.settings`.\n\nTo disable a linter: move it to `linters.disable` with a comment explaining why.\n\n## Linter Categories\n\nThe recommended configuration enables linters across these domains:\n\n| Domain | Linters | Catches |\n| --- | --- | --- |\n| Correctness | govet, staticcheck, unused, errcheck, errorlint, nilerr, forcetypeassert, copyloopvar, durationcheck, reassign | Bugs, unchecked errors, stdlib misuse |\n| Style | gocritic, revive, wsl_v5, whitespace, godot, misspell, dupword, predeclared, errname, asciicheck | Readability, naming, consistency |\n| Complexity | gocyclo, nestif, funlen, dupl | Overly complex or duplicated code |\n| Performance | perfsprint, unconvert, ineffassign, goconst | Conversions, string ops, dead assigns |\n| Security | gosec, bidichk, bodyclose, noctx, containedctx, fatcontext, sqlclosecheck, rowserrcheck | Security issues, resource leaks (HTTP, SQL) |\n| Logging | sloglint, loggercheck | Structured log consistency |\n| Testing | thelper, paralleltest, testifylint, usetesting | Test hygiene and best practices |\n| Modernization | modernize, exptostd, intrange, usestdlibvars, exhaustive, nolintlint | Modern Go idioms, lint hygiene |\n| Formatting | gofmt, gofumpt | Code formatting |\n\nAll linters are enabled in the [recommended .golangci.yml](../assets/.golangci.yml), organized by domain.\n\n### Correctness & Safety\n\n- **govet** — Go's built-in checker: copylocks, printf format mismatches, struct tag validation, context stored in structs, unreachable code, nil dereferences\n- **staticcheck** — Extensive static analysis: deprecated APIs, common mistakes, unnecessary code, simplifications, misuse of standard library\n- **unused** — Detects unused variables, functions, types, and struct fields\n- **errcheck** — Ensures all error returns are checked, including type assertions (configured with `check-type-assertions: true`)\n- **nilerr** — Detects returning nil error when `err` is non-nil (common source of silent failures)\n- **forcetypeassert** — Flags type assertions without the comma-ok check (`v := x.(T)` instead of `v, ok := x.(T)`)\n- **copyloopvar** — Detects loop variable copy issues (Go 1.22+)\n- **errorlint** — Enforces correct use of `errors.Is`/`errors.As` and `%w` wrapping (Go 1.13+ error wrapping)\n- **durationcheck** — Detects `time.Duration * time.Duration` multiplication bugs (e.g., `2 * time.Second * time.Minute` produces nanoseconds squared, not seconds)\n- **reassign** — Detects reassignment of package-level v"},{"path":"references/nolint-directives.md","content":"# Nolint Directives\n\n## Syntax\n\n```go\n//nolint:lintername // justification explaining why this suppression is needed\n```\n\nPlace the directive on the same line as the flagged code, or on the line immediately above it.\n\n## Rules\n\n1. **MUST specify the linter name** — bare `//nolint` suppresses all linters on that line and makes it impossible to track what is being suppressed\n2. **MUST add a justification comment** — future readers (and your future self) need to understand why\n3. **The `nolintlint` linter enforces both rules** — it will flag bare `//nolint` and missing reasons\n4. **MUST fix the root cause before suppressing** — only suppress after confirming the issue is a false positive or an intentional pattern\n\n## Examples\n\n```go\n// Specific linter with reason\n//nolint:errcheck // fire-and-forget logging, error not actionable\n_ = logger.Sync()\n\n// Type assertion is safe because preceding type switch guarantees the type\nv := x.(MyType) //nolint:forcetypeassert // guaranteed by type switch on line 42\n\n// Orchestration function has inherent complexity\n//nolint:gocyclo // orchestration function coordinating 8 subsystems\nfunc orchestrate() error {\n\n// Table-driven test with many cases\n//nolint:funlen // table-driven test, length is proportional to case count\nfunc TestParser(t *testing.T) {\n\n// Intentional parallel structure is clearer than abstracting\n//nolint:dupl // intentional parallel structure for readability\n```\n\n## Multiple Linters\n\nSuppress multiple linters on one line with comma separation:\n\n```go\n//nolint:errcheck,gosec // fire-and-forget in test helper\n```\n\n## When to Suppress vs. When to Fix\n\n**Fix** (almost always):\n\n- `errcheck` — check the error, even if just logging it\n- `govet` — these are usually real bugs\n- `staticcheck` — deprecated API usage, logic errors\n- `bodyclose`, `sqlclosecheck` — resource leaks are real issues\n\n**Suppress** (with justification):\n\n- `funlen` — table-driven tests with many cases\n- `gocyclo` — orchestration functions where splitting would obscure the flow\n- `dupl` — intentional parallel structure that is clearer than an abstraction\n- `exhaustive` — when a default case intentionally handles remaining values\n- `goconst` — when extracting to a constant would reduce clarity (e.g., test assertions)\n\n**Never suppress without strong justification**:\n\n- Security linters (`bodyclose`, `sqlclosecheck`, `rowserrcheck`) — these catch real resource leaks\n- `errcheck` on production code paths — unchecked errors cause silent failures"},{"path":"skill-card.md","content":"## Description:\n\nLinting best practices and golangci-lint configuration for Go projects, including running linters, configuring .golangci.yml, suppressing warnings with nolint directives, interpreting lint output, and selecting linters.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[samber](https://clawhub.ai/user/samber)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and engineers use this skill to set up golangci-lint, interpret and fix lint findings, write disciplined nolint suppressions, and adopt linting workflows in Go codebases.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Installing golangci-lint with an unpinned latest version can change lint behavior over time.\n\nMitigation: Pin and review the golangci-lint version used by local setup and CI.\n\nRisk: Auto-fix commands can modify Go code in ways that still need developer review.\n\nMitigation: Review diffs and run the relevant test suite before accepting --fix output.\n\nRisk: Using the skill outside Go linting work may produce irrelevant guidance.\n\nMitigation: Invoke it for Go linting, golangci-lint configuration, lint-output interpretation, or nolint guidance.\n\n## Reference(s):\n\n- [Project homepage](https://github.com/samber/cc-skills-golang)\n- [Linter Reference](references/linter-reference.md)\n- [Nolint Directives](references/nolint-directives.md)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, Code, Shell commands, Configuration, Guidance]\n\n**Output Format:** [Markdown with inline Go, YAML, Makefile, and shell snippets]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May propose golangci-lint commands, .golangci.yml changes, nolint directives, and cleanup plans for Go files.]\n\n## Skill Version(s):\n\n1.4.0 (source: release evidence and frontmatter)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"Linting best practices and golangci-lint configuration for Golang projects — running linters, configuring .golangci.yml, suppressing warnings with nolint directives, interpreting lint output, and selecting linters. Use when configuring golangci-lint, asking about lint warnings or nolint suppressions, setting up code quality tooling, or choosing linters. Also use when the user mentions golangci-lint, go vet, staticcheck, or revive. Skill: golang-lint Owner: samber Summary: Linting best practices and golangci-lint configuration for Golang projects — running linters, configuring .golangci.yml, suppressing warnings with nolint directives, interpreting lint output, and selecting linters. Use when configuring golangci-lint, asking about lint warnings or nolint suppressions, setting up code quality tooling, or choosing linters. Also use when the user","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":1501,"uniquenessScore":47,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-11T01:49:39.382Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-11T01:49:39.382Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-11T03:56:36.078Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}