Help us improve
Share bugs, ideas, or general feedback.
From ai-kit
Audits and updates Go module dependencies using go toolchain and govulncheck, with semver-aware patching and vulnerability checks.
npx claudepluginhub ivklgn/ai-kitHow this skill is triggered — by the user, by Claude, or both
Slash command
/ai-kit:update-golang-depssonnetThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Audit and update Go module dependencies safely, one semver tier at a time. Use the native `go` toolchain plus `govulncheck` — no third-party wrappers.
Manages Go module dependencies: go.mod editing, Minimal Version Selection, vulnerability scanning (govulncheck), Dependabot/Renovate setup, and go.work workspaces.
Manages Go modules and dependencies: initializes projects, edits go.mod/go.sum, handles versioning/conflicts, sets up workspaces, troubleshoots errors.
Share bugs, ideas, or general feedback.
Audit and update Go module dependencies safely, one semver tier at a time. Use the native go toolchain plus govulncheck — no third-party wrappers.
go version
Locate go.mod:
find . -name go.mod -not -path '*/vendor/*' -not -path '*/.git/*' -not -path '*/node_modules/*'
If multiple go.mod files are found (nested modules), ask the user which module to target, or whether to iterate all.
Check for go.work:
test -f go.work && cat go.work
If a workspace exists, ask whether to target a single module or iterate across the workspace.
command -v govulncheck
If missing, inform the user and ask for approval to install:
go install golang.org/x/vuln/cmd/govulncheck@latest
If declined, proceed without the vuln scan — note it in the final report.
go list -u -m -json all
This streams one JSON object per module (not a single array). Parse by splitting on }\n{ or using a JSON stream parser. Relevant fields:
{
"Path": "github.com/stretchr/testify",
"Version": "v1.8.0",
"Update": { "Path": "github.com/stretchr/testify", "Version": "v1.9.0" },
"Main": false,
"Indirect": false,
"Replace": null
}
Default to direct dependencies only (Indirect: false, Main: false). go mod tidy drags indirects along automatically after direct bumps. Only include indirects if the user explicitly asks.
Skip modules with a non-nil Replace — they point to a local path or forked repo and must be updated manually. Report them separately.
govulncheck ./... -format json
Parse the stream. Each finding event with osv populated is an advisory. Record:
{ module, vulnerable_ranges, fixed_in, severity, summary }
Map fixed_in to the outdated list so you know which advisories each tier's updates would resolve.
For each module with an Update, classify the jump from Version to Update.Version:
v1.2.3 → v1.2.5v1.2.3 → v1.3.0v1.2.3 → v2.0.0Additional Go-specific rules:
+incompatible suffix (e.g., v2.3.0+incompatible): legacy pre-modules v2+. Treat as major and flag — these modules never adopted Go modules properly.github.com/foo/bar with latest = v2.x.x requires the import path to change to github.com/foo/bar/v2 (Go modules convention SIV — semantic import versioning). Detect by comparing latest major ≥ 2 and current path has no /vN suffix. Handle in the major tier with special rewriting flow.v0.2.3 → v0.2.9 = patch; v0.2.3 → v0.3.0 = major (not minor). Go pre-1.0 libraries make breaking changes between v0.y bumps.gopkg.in modules: versioning lives in the import path (gopkg.in/yaml.v2 vs gopkg.in/yaml.v3). A jump from v2 to v3 requires a manual import path change, not a go get.Skip patches. For each minor and major update:
gh for GitHub-hosted modules (most common):
gh release view v<X.Y.Z> -R <owner>/<repo>
The module path github.com/<owner>/<repo> maps directly to the GitHub repo. For modules in subdirectories (e.g., github.com/foo/bar/subpkg), the release is on the repo root, sometimes tagged subpkg/v<X.Y.Z>.
Context7 MCP for well-known libraries (less coverage than npm, but fast when present):
mcp__context7__resolve-library-id with the module pathmcp__context7__query-docs with query="changelog" or query="migration"WebFetch fallback:
https://pkg.go.dev/<module>?tab=versions — shows version listhttps://pkg.go.dev/<module> — may link to changelogSummarize each into one line with breaking changes flagged.
Apply in strict order: patch → minor → major. Run verification (Step 8) after each tier and after each individual major. On failure, offer rollback and stop.
For each patch in the batch:
go get <module>@<patch-version>
Then tidy once:
go mod tidy
If a vendor/ directory with modules.txt exists, also run:
go mod vendor
Report count after.
Present the full minor batch as a table (Module | Current → Latest | Fixes advisory? | Release notes). Ask the user: approve the batch, deselect specific modules, or skip tier. Apply each approved module with go get, then go mod tidy once at the end.
Iterate majors one at a time. For each, first classify:
Case A — same module path (module already at /vN or major is still v0/v1):
go get <module>@v<N>.0.0, then go mod tidy, then verify.Case B — v2+ path change required (current path has no /vN, new major ≥ 2):
github.com/foo/bar to github.com/foo/bar/v2. Every import statement referencing this module in your code must be rewritten."grep -rl "\"<current-module-path>\"" --include='*.go' .
go get) / skip / defer.go.mod: go get <new-module-path>@v<N>.0.0 (this adds the /vN path as a new dependency).gofmt -r for mechanical rewrites:
gofmt -w -r '"<old-path>" -> "<new-path>"' .
(Note: gofmt -r operates on expressions, not strings. For import-path rewrites specifically, a sed-based approach is more reliable — or use goimports after manual sed:)
grep -rl "\"<old-path>\"" --include='*.go' . | xargs sed -i.bak "s|\"<old-path>\"|\"<new-path>\"|g"
find . -name '*.bak' -delete
go mod tidy — this should drop the old path from go.mod.gopkg.in special case: path changes like gopkg.in/yaml.v2 → gopkg.in/yaml.v3 follow the same rewrite flow — the "major" is encoded in the path segment.After each tier (and after each individual major):
go build ./...
go vet ./...
Offer (don't force — can be slow):
go test ./...
On failure:
git checkout -- go.mod go.sum and any source files changed for import rewrites. Then go mod tidy to re-sync.# Go Dependencies Update Report
**Module:** github.com/example/app
**Go version:** go1.24
## Applied
- patch: 8 modules (1 fixed advisory)
- minor: 3 modules
- major: 1 module (github.com/foo/bar → /v2, 14 imports rewritten)
## Skipped / deferred
- `github.com/old/lib` — has `replace` directive, manual update needed
- `github.com/big/lib` → v3 — deferred, requires app-wide migration
## Vulnerabilities (govulncheck)
- Resolved: 2 (GO-2024-XXXX critical, GO-2024-YYYY high)
- Remaining: 0
## Verification
- go build ./...: ok
- go vet ./...: ok
- go test ./...: not run (user declined)
go.sum by hand. Use go get / go mod tidy exclusively.replace directives — flag them in the report; user handles manually.toolchain directive in go.mod: if an update requires a newer Go toolchain than the project's toolchain line, flag and skip.vendor/ mode: if vendor/modules.txt exists, run go mod vendor after go mod tidy so the vendor tree stays in sync.GOFLAGS=-mod=vendor: detect via go env GOFLAGS; updates still work but the user must re-vendor.go list -u and go get respect those env vars — no action needed, just noted.