Skip to Content
DocumentationDistribute CLI

Distribute a CLI

The CLI target generates everything needed for cross-platform binary distribution: a GoReleaser configuration, a GitHub Actions release workflow, and install scripts for Linux, macOS, and Windows.

Distribution methods

Method
GoReleaser + GitHub Releases
Description
Automated cross-platform binary builds triggered by git tags. Produces archives with checksums.
Best for
Production releases
Install scripts
Description
Generated
(bash) and
(PowerShell) scripts that download the latest release from GitHub.
Best for
End-user installation
Description
Install directly from the Go module. Requires Go toolchain on the user's machine.
Best for
Go developers

GoReleaser

The CLI target generates a .goreleaser.yaml that builds binaries for all major platforms:

Operating System
Linux
Architectures
amd64, arm64
macOS (Darwin)
Architectures
amd64, arm64
Windows
Architectures
amd64, arm64

Generated GoReleaser configuration

The id, main, and binary fields are derived from the cliName configuration value. For example, with cliName: "petstore":

# .goreleaser.yaml (generated) version: 2 builds: - id: petstore main: ./cmd/petstore binary: petstore env: - CGO_ENABLED=0 goos: [linux, windows, darwin] goarch: [amd64, arm64] ldflags: - -s -w - -X main.version={{.Version}} - -X main.buildTime={{.Date}} archives: - id: petstore formats: [tar.gz] format_overrides: - goos: windows formats: [zip] files: - README.md - LICENSE* release: draft: false prerelease: auto mode: append checksum: name_template: "checksums.txt"

Creating a release

The generated GitHub Actions workflow automates releases when a version tag is pushed:

git tag v0.1.0 git push origin v0.1.0

This triggers the workflow, which runs GoReleaser to build binaries, create a GitHub Release, and upload the archives with checksums.

Prerequisites

  • GitHub Actions permissions: The release workflow requires contents: write permission to create releases and upload assets.
  • Repository access: For public repositories, release assets are accessible to anyone. For private repositories, users need repository access to download binaries.

Install scripts

The CLI target generates platform-specific install scripts that download the latest (or a pinned) release from GitHub.

Linux and macOS

curl -fsSL https://raw.githubusercontent.com/{org}/{repo}/main/scripts/install.sh | bash

Configure the installation using environment variables derived from your envVarPrefix configuration. For example, with envVarPrefix: "PETSTORE":

# Custom install directory PETSTORE_INSTALL_DIR=/opt/bin curl -fsSL .../install.sh | bash # Specific version PETSTORE_VERSION=v0.2.0 curl -fsSL .../install.sh | bash

The environment variable names follow the pattern <envVarPrefix>_INSTALL_DIR and <envVarPrefix>_VERSION. The script installs to /usr/local/bin by default, falling back to ~/.local/bin if the user doesn’t have write access to /usr/local/bin.

Windows (PowerShell)

irm https://raw.githubusercontent.com/{org}/{repo}/main/scripts/install.ps1 | iex

go install

Users with the Go toolchain can install directly from the module:

go install {packageName}/cmd/{cliName}@latest

For example:

go install github.com/acme/petstore-cli/cmd/petstore@latest

The exact command depends on the packageName and cliName values in your gen.yaml.

Disabling release generation

If you manage releases through your own tooling, disable the generated release artifacts:

cli: generateRelease: false

This prevents generation of .goreleaser.yaml, the GitHub Actions workflow, and install scripts.

Common pitfalls

Issue
GoReleaser fails with permission errors
Solution
Ensure the GitHub Actions workflow has
permission. Check that the
has sufficient scope.
Install script fails on private repos
Solution
The install scripts use unauthenticated GitHub API calls by default. For private repos, users need to set a
environment variable or download binaries manually.
Checksums don't match
Solution
Always use the official release workflow. Manual builds may produce different binaries due to environment differences. GoReleaser builds are deterministic with
.
builds without version info
Solution
doesn't inject ldflags. The version will show as
. Use GoReleaser for versioned builds.

Last updated on