Go Developer Tools
osdk installs Go command packages through the go: namespace. The namespace is separate from the bare go runtime: go@1.24.6 selects a compiler toolchain, while go:golang.org/x/tools/gopls@0.20.0 builds and installs a command with that exact managed toolchain.
Install and select a tool
Select a managed Go line, then add the command package:
osdk use go@1.24
osdk use go:golang.org/x/tools/gopls@0.20.0
eval "$(osdk activate bash)"
gopls versionThe requests can also be used without changing project configuration:
osdk install go@1.24.6 go:golang.org/x/tools/gopls@0.20.0
osdk exec --tool go@1.24.6 \
--tool go:golang.org/x/tools/gopls@0.20.0 -- gopls versionEvery go: tool requires exactly one managed Go request. An explicit request wins; otherwise osdk injects the active project/configured go selection, installs that runtime first, and binds the resolved exact version to the tool. The ambient go on PATH is never used as the provider.
For a user-wide selection, configure both entries globally:
osdk use --global go@1.24
osdk use --global go:golang.org/x/tools/gopls@0.20.0The tool still lives in an osdk-owned fingerprinted install root; global means that its selection is written to user configuration and the user lock rather than to the current project.
Paths and selectors
The subject is a canonical module or nested command-package path:
go:<module-or-command-path>[@SELECTOR]The module host must be lowercase DNS text, while path case is preserved. Empty components, ./.., hidden components, whitespace, URL syntax, and a leading v in versions are rejected. Supported selectors are exact semantic versions (including canonical prereleases), canonical pseudo-versions, latest, and numeric prefixes:
| Request | Selection |
|---|---|
go:golang.org/x/tools/gopls or @latest | Proxy @latest result |
go:golang.org/x/tools/gopls@0 | Highest stable 0.x version in the proxy list |
go:golang.org/x/tools/gopls@0.20 | Highest stable 0.20.x version |
go:golang.org/x/tools/gopls@0.20.0 | Exact semantic version |
go:example.com/acme/tool@0.0.0-20240801123456-0123456789ab | Exact canonical Go pseudo-version |
For a nested command path, osdk checks longest module candidates first. It records the first module root proven by proxy metadata and passes the complete command path to go install. The provider remains the final authority that the selected module actually contains that command package.
Build options
Both public options contribute to installation identity:
| Option | Behavior |
|---|---|
tags | Comma-separated Go build tags; normalized, sorted, and deduplicated |
env | Semicolon-separated allowlisted build assignments |
The build-environment allowlist is CGO_ENABLED=0, GOAMD64, GO386, GOARM, GOMIPS, GOMIPS64, and bounded GOEXPERIMENT values. CGO_ENABLED=1 is rejected because osdk does not yet select and bind a C compiler/linker identity. Credentials and network/cache overrides such as GOPROXY, GONOSUMDB, GOMODCACHE, GOCACHE, GOBIN, and PATH cannot be supplied through this option.
osdk use 'go:example.com/acme/tool[tags=netgo,env=CGO_ENABLED=0]@1.2.3'Proxy selection
The built-in candidates are https://proxy.golang.org and https://goproxy.cn. The normal auto, ordered, and pinned source policies apply; auto mode probes candidates and caches the ranking before metadata resolution. Exact versions are still verified with the chosen proxy's .info endpoint.
Custom Go proxies must be canonical HTTPS origins or paths without credentials, query strings, fragments, or trailing slashes. When custom sources are present without a pin, only those candidates are used, preventing private module paths from being probed against public defaults. Custom source headers are rejected because the later native go install process cannot preserve osdk's per-request credential-forwarding boundary. A fresh resolution places the selected proxy first, then joins the remaining ranked candidates with | into one GOPROXY. Go can therefore change proxy after any download error without osdk rerunning a possibly side-effecting install command. Lock replay still uses only its recorded proxy, rather than pretending an unrecorded source graph is reproducible input.
All of the above concerns the go:<module> package install path. Running a managed go directly (go build / go test) fetches dependencies over a different channel: [sources.go] only selects where the Go toolchain archive is downloaded from, while module downloads are driven by the go command through GOPROXY, so mirroring the archive does not mirror the modules.
A managed go's xec_env injects a ranked GOPROXY. The candidate set is configured under its own go-modules name (proxy.golang.org, goproxy.cn and mirrors.aliyun.com/goproxy by default, with direct appended). Ranking here is configuration-level only, with no network probe: this code runs in the shim on every command invocation, where a probe round-trip would be charged to interactive latency. Live probing stays in the install path.
Entries are joined with | rather than ,. The separator is the fallback policy: after a comma the go command only advances on 404/410 and treats a connection timeout as terminal, so a comma-joined list dies on the first unreachable proxy and never reaches the mirrors behind it -- exactly the case mirrors exist for. The gatekeeper semantics a comma buys (a private proxy answering 403 stops the lookup instead of leaking the module path onward) do not apply, because every candidate here is a public mirror of the same public module set. A GOPROXY the user set themselves -- including off and direct -- is never overridden.
go-modules is not a backend and so cannot be reached through the registry, but like self (osdk's own release download) it carries per-tool source configuration, so canonical_source_tool admits it explicitly and osdk source list/test/add/remove/pin/unpin all work. source test probes <proxy>/golang.org/x/text/@v/list: a small, long-lived, universally mirrored module on a well-known public path -- probing whatever the user actually depends on would leak that dependency to every candidate. direct is not a mirror and has no endpoint to measure, so it stays unranked and only appears as the final GOPROXY fallback.
Pins need explicit handling here. The generic path applies a pin after probing, but this list is consumed directly in the shim with no probe, so module_proxy_sources moves the pinned source to the front itself; otherwise the pin would be written, reported as set, and then silently ignored. It moves to the front rather than displacing the rest because GOPROXY is a fallback list: a pin says "try this first", and dropping the others would turn one unreachable host into a hard build failure.
Isolation and activation
osdk runs one shell-free go install <command>@v<version> in a cleared environment. It forces the selected managed GOROOT, a staged GOBIN, private home/GOPATH/temp directories, shared osdk-controlled module and build caches, GOENV=off, and GOTOOLCHAIN=local. GOSUMDB=off prevents an unrelated checksum-service request; source trust therefore follows the selected proxy.
Only regular executable files from staged bin are published. Their names, sizes, and SHA-256 values are recorded, and activation/shims expose only those validated commands. Different versions, tags, build environments, proxies, module roots, managed Go versions, or managed runtime contents produce distinct installation identities.
Lock and offline behavior
osdk.lock schema 4 stores compact native metadata: the exact Go runtime version, version-only replay class, selected proxy, and discovered module root. It also keeps the public tags and env options and a matching exact go entry in the same platform table. It does not copy go.sum or the complete transitive module graph into osdk.lock.
Consequently, a complete installation with the exact matching identity can be validated and reused offline. A cold offline build or repair is unsupported, even when the shared Go caches happen to contain some dependencies.
Lifecycle commands
osdk current go:golang.org/x/tools/gopls
osdk list go:golang.org/x/tools/gopls
osdk list-remote go:golang.org/x/tools/gopls
osdk where go:golang.org/x/tools/gopls@0.20.0
osdk outdated go:golang.org/x/tools/gopls
osdk upgrade go:golang.org/x/tools/gopls
osdk --yes uninstall go:golang.org/x/tools/gopls@0.20.0
osdk reshimChanging or removing the selected Go runtime invalidates dependent Go-tool reuse. If several otherwise matching source/runtime identities exist, select the exact one through osdk.lock instead of allowing an ambiguous activation. --global currently changes selection/lock scope only: where --global and uninstall --global remain npm-only CLI operations. Use the ordinary exact where/uninstall forms for a Go tool selected in the current environment.
For runtime identity, staging, provider, and lock-schema details, see Go developer tool implementation.