A Makefile for Go projects.

$ go install lesiw.io/gorc/go@latest
$ go test ./...
go.rc: go tool gotestsum -- ./... -shuffle=on -timeout=30s -count=10
store (159ms)
httpapi (265ms)
. (387ms)
DONE 30 tests in 0.387s
$ go vet ./...
go.rc: golangci-lint run ./...
0 issues.
$ go build .
go.rc: CGO_ENABLED=0 go build -trimpath -ldflags "-s -w" .
$

Recipes

Go standardized the verbs.
go.rc makes them yours.

Syntax

Simple by design.

go.rc works by the same rules as //go:generate: no shell, no globs, no syntax. Just environment variables and a cross-platform statement.

Need more? Break into go tool and write your own tooling with command buffers.

go.rc
release go tool example.com/app/internal/release $GOARGS $GOFLAGS

Adoption

Extension, not invention.

go build, go test, and go vet are what people, editors, pipelines, and coding agents already reach for. Quit adding commands into AGENTS and README files. Inject them into the verbs everyone already knows.

  • Developers README.md
  • Agents AGENTS.md
  • Editors settings.json
  • Pipelines .github/workflows
  • Everyone go.rc

Formatting

Go fmt your way.

Does your project opt into more formatting rules or sorted imports, but your editors and agents just don't care? Chain formatters together in a go.fmt file and let the shim expose them through the ordinary gofmt interface, so -l, -w, and -d behave exactly as they always have.

go.fmt
gofmt -s
go tool goimports
$ gofmt -l .
go.fmt: gofmt -s | go tool goimports
store/store.go
$ gofmt -w .
go.fmt: gofmt -s | go tool goimports
$ gofmt -l .
go.fmt: gofmt -s | go tool goimports
$

Install

Try it now

shell
go install lesiw.io/gorc/go@latest
go install lesiw.io/gorc/gofmt@latest

export PATH="$(go env GOPATH)/bin:$PATH"

Use go run in CI.

.github/workflows/check.yml
steps:
  - uses: actions/checkout@v7
  - uses: actions/setup-go@v7
    with:
      go-version: stable
  - run: go run lesiw.io/gorc/gofmt@latest -l .
  - run: go run lesiw.io/gorc/go@latest test ./...