# Packaging and releases

Packaging is part of the baseline when the project is meant to be installed, not
an afterthought. Choose the artifact based on how people will actually use the
project.

## Choose the artifact

- **Library**: no binary packaging unless examples/tools are part of the repo.
- **Plain CLI or MCP server**: release archives or cross-compiled binaries are
  usually enough.
- **System service**: add service files and consider native packages.
- **Desktop app**: include desktop files, icons, runtime dependencies, and OS
  installer/package constraints from the start.

## Version gating

Package tasks should fail on ambiguous versions. Prefer exact tags for release
packages. For development builds, `VERSION=dev` is fine; for packages, be
stricter.

For Git-tagged releases, a package task can gate on an exact tag:

```sh
version=$(git describe --tags --exact-match 2>/dev/null) || {
  echo "Error: package builds require an exact vMAJOR.MINOR.PATCH tag" >&2
  exit 1
}
version=${version#v}
```

For jj-backed projects, use the project's agreed jj/git-derived release command
instead. Do not infer package versions from language build metadata unless the
project explicitly chose that policy.

## Native Linux packages

Use nFPM when shipping `.deb`, `.rpm`, `.apk`, or Arch-style package artifacts
from a non-distro package pipeline. Keep package metadata boring, explicit, and
consistent with the project's chosen license.

Visible mise tasks should be simple: `pkg`, `pkg:deb`, `pkg:rpm`, `pkg:apk`,
`pkg:arch`. Put version resolution, icon conversion, binary staging, package
builds, and optional compression in hidden/helper tasks when needed.

UPX is optional. Use it only when size matters; do not assume it works well for
every OS or binary format.

Document cross-compilation constraints in task descriptions and preconditions
rather than letting users discover linker or runtime failures.

## Go path

For Go binaries, MCP servers, TUIs, web apps, or Wails releases, read
[golang/index.md](golang/index.md) first and follow its packaging chain. The Go
path covers static builds, CGO exceptions, Wails/Linux constraints, and Go
version-injection policy.
