Since Go 1.24 you can record developer tools such as code generators in go.mod with a tool directive, add one with go get -tool, and run it with go tool. The tool is then versioned and checksummed like any dependency, instead of being installed from @latest on each machine.
Why this matters for supply chain risk
Many projects document a line like go install example.com/tool@latest in a README or Makefile. That fetches whatever is newest on the day, on every laptop and CI job, outside your reviewed dependency list.
The tool directive moves that into go.mod and go.sum, so the version appears in code review and the hash is verified.
Commands
From the Go reference and the managing dependencies guide:
go get -tool golang.org/x/tools/cmd/stringer
go tool stringer
go get tool
go get -tool golang.org/x/tools/cmd/stringer@none
- The first adds a
toolline to go.mod. - The second runs it. If names conflict, use the full package path.
go get toolupgrades all tools.- The
@noneform removes one.
If the tool lives in another module, a require for that module is needed too, which go get -tool handles.
Before and after
| Approach | Version source | Reviewed in PRs |
|---|---|---|
| go install pkg@latest in a script | Whatever is newest today | No |
| go install pkg@v1.2.3 in a script | Script text | Sometimes |
| tool directive | go.mod and go.sum | Yes |
Steps to migrate
- List tools your team runs: linters, generators, mock builders, migration helpers.
- Add each with
go get -tooland commit go.mod and go.sum. - Replace install steps in Makefiles and CI with
go tool name. - Run your vulnerability scan again. Tools are now part of the module graph, so their dependencies appear in results.
- Decide who upgrades them. A scheduled
go get toolpull request works well.
Watch for side effects
Tool dependencies join the graph for version selection, which can raise versions of shared libraries. Review the go.mod diff when you add one. Also note that a tool runs with your developer privileges, so a generator is as trusted as any code you build. Pin it, and review upgrades with the same care as application dependencies.
Where Safeguard fits
Safeguard's SBOM and dependency scanning read go.mod, so pinned tools are inventoried with the rest. You can run a free scan on a repository to see the full list.
Quick check
Which Go version added the tool directive?
The Go reference marks the tool directive as Go 1.24 and later.
How do I remove a pinned tool?
Run go get -tool with the package and @none, which removes the line.
Sources
Last reviewed: 19 October 2026.