+---
+name: go-code
+description: Go style rules. Use before you write or review Go code.
+---
+
+# Go code
+
+## Packages and files
+
+- Keep Go code in one root `main` package. Do not add `internal/`,
+ `cmd/`, or one-file packages until the user asks for them.
+- Keep `main.go` limited to the entry point. Name other files for their
+ function. Do not create `main_test.go`.
+- A file carries its own context. Keep each struct and all of its
+ methods in one file. Give a separate responsibility its own type.
+- Put entry points first, then each struct's methods as a group, then
+ standalone utility functions. Do not put a utility function between
+ the methods of one type.
+- In each group, order functions by first use in the file.
+
+## Entry point and context
+
+- `main` calls `run()` and handles its returned error. Do not use
+ `log.Fatal`.
+- `run()` creates the SIGINT/SIGTERM signal context and defers its
+ cancellation. Pass that context through operations and let cleanup
+ finish before `main` exits.
+- Use `ctx` for a context and `cancel` for its cancellation function.
+ Call `defer cancel()` immediately after you create the context.
+- Reuse `ctx` when a child context replaces its parent. Use a different
+ name only when both contexts stay in use. Return `ctx.Err()` directly.
+
+## Errors
+
+- Handle every returned error.
+- Reuse an existing `err` for later operations in the same scope. Use a
+ different variable only to keep or join errors.
+- Use `errors.Is` and `errors.As` to examine errors. Do not compare an
+ error directly with a sentinel, because errors can be wrapped.
+- When a function has more than one error path, wrap each returned error
+ with the context of its operation. A function with one error path can
+ return the error directly.
+- When deferred cleanup can fail, use a named `err` result and join the
+ cleanup error with `errors.Join`.
+
+## Style
+
+- Keep function signatures on one line. Write function bodies on more
+ than one line, also for anonymous functions, deferred cleanup, and
+ test callbacks.
+- Do not use short `if` initializers.
+- Use a one-letter receiver name for each method.
+- Put each field of a keyed struct literal on its own line when you set
+ more than one field.
+- Put an empty line between logical blocks, also after multiline
+ declarations, assignments, literals, and calls. Keep an operation with
+ its immediate error or result check. Keep a short declaration with its
+ immediate use.
+- Use GNU-style command flags: two dashes for long flags, such as
+ `--cwd`, and one dash only for one-letter flags, such as `-h`.
+- Prefer the Go standard library. Prefer Go over cgo.
+- Do not add compile-time interface assertions. Prove compatibility
+ through actual assignments and calls.
+- Use `// nolint: name` for lint directives.
+
+## Dependencies
+
+- After a change to `go.mod` or `go.sum`, update `vendorHash` in
+ `nix/package.nix`. While the module has no dependencies, `vendorHash`
+ is `null`.
+
+## Tests
+
+- Add tests for meaningful behavior. Do not add tests that only repeat
+ implementation details.
+- Use `testify/require` for assertions.
+- Name a table-driven case slice `testCases` and its range variable
+ `tc`. A subtest name describes the behavior, not a generic outcome or
+ input.
+- In a test file, put constants immediately after the imports, then the
+ tests, then supporting types, methods, and helpers.
+- Supply valid required dependencies in tests. Do not make a dependency
+ optional only to make a test simpler.