$ go version
go version go1.26-devel_320df537cc 2025-08-13 20:33:56 -0700 linux/amd64

Using https://github.com/cue-lang/cue as an example, where cmd/cue is a main program which reports the main module's version as the first line of its cue version command, the stamping works fine with go install and go build:

$ go install ./cmd/cue && cue version | sed 1q
cue version v0.15.0-0.dev.0.20250815110336-a2eed3278a6c
$ go build -o cue-build ./cmd/cue && ./cue-build version | sed 1q && rm cue-build
cue version v0.15.0-0.dev.0.20250815110336-a2eed3278a6c

With go run it doesn't work by default, which is surprising and a bit inconsistent. We can however enable it explicitly.

$ go run ./cmd/cue version | sed 1q
cue version (devel)
$ go run -buildvcs=true ./cmd/cue version | sed 1q
cue version v0.15.0-0.dev.0.20250815110336-a2eed3278a6c

With go tool it also doesn't work by default, and on top of that, we can't enable it in any way:

$ go tool cue version | sed 1q
cue version (devel)
$ go tool -buidlvcs=true cue version | sed 1q
flag provided but not defined: -buidlvcs

What's weird is that the "auto" mode (the default) seems to be broken with go run:

$ go run -buildvcs=auto ./cmd/cue version | sed 1q
cue version (devel)

The docs say:

By default ("auto"), version control information is stamped into a binary if the main package, the main module containing it, and the current directory are all in the same repository.

It seems pretty clear to me that I'm meeting those requirements with go run ./cmd/cue, so I don't understand why the auto-stamping is not working.

So it seems to me like go run and go tool should apply the -buildvcs=auto default such that version stamping takes place.

It may also be a good idea for go tool to expose the -buildvcs build flag, so that one can explicitly turn it on or off if needed like with the other commands. But I don't feel strongly about it.

Comment From: gabyhelp

Related Issues

Related Code Changes

(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)

Comment From: seankhliao

This was #52338

Comment From: mvdan

If that is the decision for go run, fair enough, but it should be documented in go help run.

And I feel like go tool needs to be considered separately. The whole point of the command is to run common tools and cache the binaries, so the cost of obtaining the VCS information is amortized. And the command should behave closely to go install or go build within reason.

In fact, go run caches binaries nowadays too, so I'd argue the same argument now applies to both. When https://github.com/golang/go/issues/52338 was closed, there was no caching of binaries, so the cost of fetching VCS information was a latency issue with every single invocation.

Comment From: seankhliao

I don't think much should change for go run: the most common case is probably still interactive usage for running quick tests rather than repeatedly invoking the same program.

I do see the argument for build info for go tool, however, isn't it quite misleading for it to be stamped with the main module version, rather than the version of the tool being executed?

Comment From: mvdan

isn't it quite misleading for it to be stamped with the main module version, rather than the version of the tool being executed?

In my examples above, the main (current) module and the module containing the tool command are the same. This is the case where the main module version stamping does not happen, because it's VCS-derived.

$ go version -m $(go tool -n cue) | grep '^\s*mod'
    mod cuelang.org/go  (devel) 

When running a tool from an external module, i.e. a dependency, then the stamping works fine because no VCS is involved for the main module in the build. The main module is a dependency pulled through GOPROXY.

$ go version -m $(go tool -n stringer) | grep '^\s*mod'
    mod golang.org/x/tools  v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=

I don't think much should change for go run: the most common case is probably still interactive usage for running quick tests rather than repeatedly invoking the same program.

I don't agree with that conclusion. If that were true, then go run would not cache binaries like go tool does. Given that they both cache binaries, and hence the extra time spent on -buildvcs is amortized, I would find it bizarre if one stamps main module versions and the other does not.

Comment From: cagedmantis

@golang/command-line

Comment From: matloob

When running a tool from an external module, i.e. a dependency, then the stamping works fine because no VCS is involved for the main module in the build. The main module is a dependency pulled through GOPROXY.

I'm not sure I understand this. We're talking about a case where the work (what we now call the "main") module example.com/a, which is on vcs on disk declares a tool example.com/b/tool in module example.com/b? And where we run go tool example.com/b/tool from the directory example.com/a is in? In that case, the main/work module is still example.com/a, right, and does involve VCS right?