Cursor plugin for modern Go (1.22, 1.23, 1.24). Teaches the AI to write idiomatic Go that uses log/slog, errors.Is/As with %w wrapping, context-first APIs, the 1.22+ http.ServeMux method routing, and 1.23 range-over-func iterators. Catches io/ioutil, interface{}, panic(err), time.After leaks in select loops, and the other regressions LLMs trained on pre-1.18 code still ship.
LLMs trained on Go code from the 1.16-2023 era default to outdated patterns. They:
- Import
io/ioutil(deprecated since 1.16) - Write
interface{}instead ofany - Compare errors with
==instead oferrors.Is, lose chains with%v panic(err)on normal I/O failures- Use
time.Afterinsidefor/selectloops (timer leak) - Pass
sync.WaitGroupby value (silently does nothing) - Stick
defer f.Close()inside aforloop (resources accumulate until function return) - Reach for
gorilla/muxandchiwhen stdlibhttp.ServeMux(1.22+) has method routing - Use
log.Println/log.Fatalinstead oflog/slog - Call
http.Get/http.Postwithout a context - Run a goroutine with no exit condition
- Add the unnecessary
v := vshadow inside goroutines (fixed at language level in 1.22) - Stuff
context.Contextinto a struct field - Use
func init()to open DB connections and register globals - Generate fresh
*time.Timerallocations from everytime.Aftercall
Clone into your Cursor plugins directory:
git clone https://github.com/RoninForge/roninforge-go.git ~/.cursor/plugins/local/roninforge-goOr copy into your project:
git clone https://github.com/RoninForge/roninforge-go.git
cp -r roninforge-go/rules/* your-project/.cursor/rules/
cp -r roninforge-go/skills/* your-project/.cursor/skills/
cp -r roninforge-go/agents/* your-project/.cursor/agents/| Rule | Scope | What it does |
|---|---|---|
go-core |
Always active | Loop-var rules, async iterators, any, context-first, error wrapping, slog, http.ServeMux 1.22+, graceful shutdown, sql.DB pool |
go-anti-patterns |
Always active | 20 LLM mistakes: io/ioutil, interface{}, panic(err), time.After leaks, defer-in-loop, WG-by-value, log.Println, http.Get without context, body-not-closed, %v on err, init() side effects |
go-errors |
**/*.go |
Wrap-and-check, sentinels, typed error structs, errors.Join, when to panic, common stdlib sentinels |
go-concurrency |
**/*.go |
Goroutine lifecycle, context propagation, errgroup over hand-rolled WG, channels, sync.Once, race detector, atomic counters |
go-testing |
Agent-requested | Table tests, t.Cleanup, testing.TB, httptest, fuzz, benchmarks, testing/synctest (1.24 experimental, stable 1.25+) |
| Skill | Command | What it does |
|---|---|---|
| New service | /go-new-service |
Scaffold HTTP service with graceful shutdown, slog setup, 1.22+ mux, ReadHeaderTimeout |
| Error wrap | /go-error-wrap |
Convert %v to %w, == to errors.Is, type assertions to errors.As, define sentinels |
| Validate | /go-validate |
Scan a codebase for the 20 anti-patterns, report by severity |
| Modernize | /go-modernize |
Migrate older code: ioutil to io/os, log to slog, interface{} to any, hand-rolled router to ServeMux 1.22+ |
| Agent | What it does |
|---|---|
go-reviewer |
Reviews Go code by severity: critical (crashes, leaks), warnings (regressions vs modern Go), suggestions (style) |
Existing Go cursor rules cover style-only items (gofmt, naming) or are pinned to Go 1.18 patterns. None of them:
- Cover the 1.22 / 1.23 / 1.24 language deltas (range-over-func iterators,
math/rand/v2,crypto/rand.Text,b.Loop()in benchmarks, thetooldirective) - Catch
time.Afterleaks inselect, the single most common production bug LLMs ship - Force context-first signatures with grep-able patterns
- Teach
log/slogmigration fromlog.Println(still the dominant generated output) - Bundle a reviewer agent that grades by severity
The plugin treats the LLM as a junior writing in 2026, not as a senior writing in 2018.
tests/fixtures/anti-pattern-sample/ is a deliberate worst-case service (compiles on Go 1.20 to demonstrate ioutil). tests/fixtures/correct-sample/ is the modernised version - compiles, vets clean, and go test -race ./... passes.
MIT - see LICENSE