/go-dev
Connection string used by the Justfile migration recipes (golang-migrate)
Claude Code
$ npx -y skills add tenequm/skills --skill go-dev --agent claude-code
Codex
$ npx skills add tenequm/skills --skill go-dev -a codex -y
Cursor
$ npx skills add tenequm/skills --skill go-dev -a cursor -y
Gemini CLI
$ npx skills add tenequm/skills --skill go-dev -a gemini-cli -y
GitHub Copilot
$ npx skills add tenequm/skills --skill go-dev -a github-copilot -y
OpenCode
$ npx skills add tenequm/skills --skill go-dev -a opencode -y
Windsurf
$ npx skills add tenequm/skills --skill go-dev -a windsurf -y
SKILL.md
go-dev.SKILL.mdname: go-dev
description: Opinionated Go setup with golangci-lint v2, gofumpt, gotestsum, golang-migrate, and just. Use when starting a Go project, configuring lint, format, test, coverage or CI, writing a Justfile, wiring migrations, or leaving a Makefile workflow.
metadata:
version: "0.7.0"
categories: "development"
topics: "go, golangci-lint, gofumpt, testing, just"
upstream: "go@1.27.3, golangci-lint@v2.15.0, gofumpt@v0.12.0, gotestsum@v1.13.0, golang-migrate@v4.20.1, just@1.59.0, lefthook@v2.2.2"
openclaw:
homepage: https://github.com/tenequm/skills/tree/main/skills/go-dev
emoji: "🐹"
envVars:
- name: DATABASE_URL
required: false
description: Connection string used by the Justfile migration recipes (golang-migrate)Go Development Stack
Opinionated, modern Go development setup. One tool per concern, zero overlap.
When to Use
- Starting a new Go project from scratch
- Adding linting, formatting, or testing infrastructure
- Setting up CI/CD for a Go service or library
- Creating a Justfile to replace a Makefile
- Adding database migration tooling
- Migrating from scattered gofmt/govet/staticcheck invocations to a unified setup
Not for a fork that regularly merges from upstream: replacing its Makefile and reformatting the tree with gofumpt conflicts on every merge and buries real changes in a reformat diff. Keep upstream's gofmt and build tooling there, and only add checks.
The Stack
| Tool | Version | Role | Replaces | |------|---------|------|----------| | **Go** | 1.27+ | Language, toolchain, `go mod`, `go fix` | - | | **golangci-lint** | v2.15+ | Meta-linter (100+ linters + formatters + `fmt` command) | gofmt, govet, staticcheck, errcheck run separately | | **gofumpt** | v0.12+ | Strict formatter (superset of gofmt, 19 default rules) | gofmt | | **gotestsum** | v1.13+ | Test runner with readable output, watch mode, JUnit XML | Raw `go test` | | **just** | 1.59+ | Task runner | Makefile | | **golang-migrate** | v4.20+ | DB migrations (CLI + library + `embed.FS`) | Manual SQL scripts | | **lefthook** | v2.2+ | Git hooks (single binary, parallel) | pre-commit (Python) |
**Version floors are load-bearing.** golangci-lint "supports Go versions lower or equal to the Go version used to compile it" - a pin older than your Go toolchain fails outright. Go 1.27 support landed in golangci-lint v2.13.0, but a patch release can move the floor: v2.13.2 loads packages built by go1.27.1 and go1.27.2, yet fails on go1.27.3 with `export data version 5 is greater than maximum supported version 4` reported as a `typecheck` issue on every stdlib import. v2.14.0 and v2.15.0 pass on all three, so `v2.14` is the floor for a current Go 1.27 toolchain; this skill pins v2.15.0. Two more floors moved recently: gofumpt v0.12.0 "is based on Go 1.27's gofmt, and requires Go 1.26 or later", and lefthook v2.2's `go install` path needs Go 1.27 - "The minimum Go version required is 1.27" - and tracking it with `go get -tool` raises your own module's `go` line to `1.27.0`.
Quick Start: New Project
# 1. Create module
mkdir myapp && cd myapp
go mod init github.com/yourorg/myapp
# 2. Scaffold directories
mkdir -p cmd/myapp internal migrations
# 3. Install golangci-lint as a binary, not as a module tool (see note below)
curl -sSfL https://golangci-lint.run/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.15.0
# 4. Track the rest in go.mod (Go 1.24+ tool directive). Pin versions - never @latest,
# which recompiles the tool on every CI run and drifts between machines.
go get -tool mvdan.cc/gofumpt@v0.12.0
go get -tool gotest.tools/gotestsum@v1.13.0
# golang-migrate needs a build tag, so install it directly
go install -tags 'postgres' github.com/golang-migrate/migrate/v4/cmd/migrate@v4.20.1
# 5. Create config files (templates below)
# 6. Run: just check
**Do not install golangci-lint through the tools pattern.** Upstream is explicit: "Using `go install`/`go get`, \"tools pattern\", and `tool` command/directives installations aren't guaranteed to work. We recommend using binary installation." The reason that matters in a shared repo is dependency bleed - "the dependencies of a tool can modify the dependencies of another tool or your project". If you must have it in `go.mod`, isolate it behind its own `-modfile` - see the [golangci-lint Reference](references/golangci-lint-reference.md). The bleed is not specific to golangci-lint: "Tools are built using the same module graph as the module itself", so every `go get -tool` (gofumpt, gotestsum, lefthook, a secret scanner) can upgrade your project's dependencies or fail on a conflict with them. Keep the tool set small, and give a heavy tool its own `-modfile`.
**`go get -tool` tracks; `go tool` runs.** The tool directive records the dependency in `go.mod` but puts nothing on your PATH. Either invoke through the toolchain - `go tool gofumpt -l .`, `go tool gotestsum --format testname` - or `go install tool` once to populate `$(go env GOPATH)/bin`. The Justfile below calls the bare binaries, so it assumes the `go install tool` route (or a system install via Homebrew - but "Homebrew can use an unexpected version of Go to build the binary" for golangci-lint, and it cannot pin a version). Note that `go tool` resolves against the module in the current directory - "additional tools may be defined in the go.mod of the current module" - so in a monorepo of independent modules it fails with `go: no such tool "..."` unless the recipe sets `[working-directory(...)]`. A `go.work` workspace lifts this - "In workspace mode, you can use `go tool` to run a tool declared in any workspace module" - see the [Go Toolchain Reference](references/go-toolchain-reference.md).
Two Go-command behaviours worth knowing before the first commit:
- `go mod init` under a 1.N toolchain writes `go 1.(N-1).0`, not `1.N` - "Running `go mod init` using a toolchain of version `1.N.X` will create a `go.mod` file specifying the
Read more
name: go-dev
description: Opinionated Go setup with golangci-lint v2, gofumpt, gotestsum, golang-migrate, and just. Use when starting a Go project, configuring lint, format, test, coverage or CI, writing a Justfile, wiring migrations, or leaving a Makefile workflow.
metadata:
version: "0.7.0"
categories: "development"
topics: "go, golangci-lint, gofumpt, testing, just"
upstream: "go@1.27.3, golangci-lint@v2.15.0, gofumpt@v0.12.0, gotestsum@v1.13.0, golang-migrate@v4.20.1, just@1.59.0, lefthook@v2.2.2"
openclaw:
homepage: https://github.com/tenequm/skills/tree/main/skills/go-dev
emoji: "🐹"
envVars:
- name: DATABASE_URL
required: false
description: Connection string used by the Justfile migration recipes (golang-migrate)Go Development Stack
Opinionated, modern Go development setup. One tool per concern, zero overlap.
When to Use
- Starting a new Go project from scratch
- Adding linting, formatting, or testing infrastructure
- Setting up CI/CD for a Go service or library
- Creating a Justfile to replace a Makefile
- Adding database migration tooling
- Migrating from scattered gofmt/govet/staticcheck invocations to a unified setup
Not for a fork that regularly merges from upstream: replacing its Makefile and reformatting the tree with gofumpt conflicts on every merge and buries real changes in a reformat diff. Keep upstream's gofmt and build tooling there, and only add checks.
The Stack
| Tool | Version | Role | Replaces | |------|---------|------|----------| | **Go** | 1.27+ | Language, toolchain, `go mod`, `go fix` | - | | **golangci-lint** | v2.15+ | Meta-linter (100+ linters + formatters + `fmt` command) | gofmt, govet, staticcheck, errcheck run separately | | **gofumpt** | v0.12+ | Strict formatter (superset of gofmt, 19 default rules) | gofmt | | **gotestsum** | v1.13+ | Test runner with readable output, watch mode, JUnit XML | Raw `go test` | | **just** | 1.59+ | Task runner | Makefile | | **golang-migrate** | v4.20+ | DB migrations (CLI + library + `embed.FS`) | Manual SQL scripts | | **lefthook** | v2.2+ | Git hooks (single binary, parallel) | pre-commit (Python) |
**Version floors are load-bearing.** golangci-lint "supports Go versions lower or equal to the Go version used to compile it" - a pin older than your Go toolchain fails outright. Go 1.27 support landed in golangci-lint v2.13.0, but a patch release can move the floor: v2.13.2 loads packages built by go1.27.1 and go1.27.2, yet fails on go1.27.3 with `export data version 5 is greater than maximum supported version 4` reported as a `typecheck` issue on every stdlib import. v2.14.0 and v2.15.0 pass on all three, so `v2.14` is the floor for a current Go 1.27 toolchain; this skill pins v2.15.0. Two more floors moved recently: gofumpt v0.12.0 "is based on Go 1.27's gofmt, and requires Go 1.26 or later", and lefthook v2.2's `go install` path needs Go 1.27 - "The minimum Go version required is 1.27" - and tracking it with `go get -tool` raises your own module's `go` line to `1.27.0`.
Quick Start: New Project
# 1. Create module mkdir myapp && cd myapp go mod init github.com/yourorg/myapp # 2. Scaffold directories mkdir -p cmd/myapp internal migrations # 3. Install golangci-lint as a binary, not as a module tool (see note below) curl -sSfL https://golangci-lint.run/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.15.0 # 4. Track the rest in go.mod (Go 1.24+ tool directive). Pin versions - never @latest, # which recompiles the tool on every CI run and drifts between machines. go get -tool mvdan.cc/gofumpt@v0.12.0 go get -tool gotest.tools/gotestsum@v1.13.0 # golang-migrate needs a build tag, so install it directly go install -tags 'postgres' github.com/golang-migrate/migrate/v4/cmd/migrate@v4.20.1 # 5. Create config files (templates below) # 6. Run: just check
**Do not install golangci-lint through the tools pattern.** Upstream is explicit: "Using `go install`/`go get`, \"tools pattern\", and `tool` command/directives installations aren't guaranteed to work. We recommend using binary installation." The reason that matters in a shared repo is dependency bleed - "the dependencies of a tool can modify the dependencies of another tool or your project". If you must have it in `go.mod`, isolate it behind its own `-modfile` - see the [golangci-lint Reference](references/golangci-lint-reference.md). The bleed is not specific to golangci-lint: "Tools are built using the same module graph as the module itself", so every `go get -tool` (gofumpt, gotestsum, lefthook, a secret scanner) can upgrade your project's dependencies or fail on a conflict with them. Keep the tool set small, and give a heavy tool its own `-modfile`.
**`go get -tool` tracks; `go tool` runs.** The tool directive records the dependency in `go.mod` but puts nothing on your PATH. Either invoke through the toolchain - `go tool gofumpt -l .`, `go tool gotestsum --format testname` - or `go install tool` once to populate `$(go env GOPATH)/bin`. The Justfile below calls the bare binaries, so it assumes the `go install tool` route (or a system install via Homebrew - but "Homebrew can use an unexpected version of Go to build the binary" for golangci-lint, and it cannot pin a version). Note that `go tool` resolves against the module in the current directory - "additional tools may be defined in the go.mod of the current module" - so in a monorepo of independent modules it fails with `go: no such tool "..."` unless the recipe sets `[working-directory(...)]`. A `go.work` workspace lifts this - "In workspace mode, you can use `go tool` to run a tool declared in any workspace module" - see the [Go Toolchain Reference](references/go-toolchain-reference.md).
Two Go-command behaviours worth knowing before the first commit:
- `go mod init` under a 1.N toolchain writes `go 1.(N-1).0`, not `1.N` - "Running `go mod init` using a toolchain of version `1.N.X` will create a `go.mod` file specifying the
Claude Code skills for founders, developers, and web3 builders. This repository publishes reusable skill folders under skills//, ships stable bundle downloads through GitHub Releases, and publishes changed skills to ClawHub.
Other skills on skills.
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
Questions about go-dev.
- Which coding agents can use go-dev?
- go-dev installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

