Skip to main content

Binary distribution for omnidist

Project description

omnidist

Go Report Card lint test codecov version npm PyPI license

Run your Go CLI everywhere with npx and uvx, without requiring Go on end-user machines.

omnidist turns one Go project into cross-platform npm and uv distributions with prebuilt binaries, then stages, verifies, and publishes them in a deterministic release flow.

Release flow: build -> stage -> verify -> publish so users can run your tool from JavaScript and Python ecosystems out of the box.

For project background, packaging model details, migration notes, and contributor-oriented repo layout, see CONTRIBUTING.md.

Requirements

  • Go 1.25+
  • Node.js + npm (for npm distribution commands)
  • uv (for uv distribution commands)
  • git (when version.source: git-tag)
  • NPM_PUBLISH_TOKEN for npm publish when distributions.npm.publish-auth: token (default) and not --dry-run
  • UV_PUBLISH_TOKEN (or --token) for uv publish (unless --dry-run)

Installation

Run without installation first:

npx @omnidist/omnidist --help
uvx omnidist --help

Install globally with npm:

npm i -g @omnidist/omnidist
omnidist --help

Install with Go toolchain:

go install github.com/metalagman/omnidist/cmd/omnidist@latest
omnidist --help

Build locally from source:

go build -o ./bin/omnidist ./cmd/omnidist
./bin/omnidist --help

Or run directly:

go run ./cmd/omnidist --help

Quick Start

  1. Print repo-tailored onboarding/release commands:
omnidist quickstart
  1. Initialize config and distribution folder structure:
omnidist init

This creates:

  • .omnidist/omnidist.yaml
  • .omnidist/ workspace directories

omnidist init writes profiles-mode config with a default profile. It also derives default distributions.npm.package / distributions.uv.package from the current directory name (slugified).

  1. Edit config and set environment variables (optional):
$EDITOR .omnidist/omnidist.yaml

omnidist loads .env automatically when present, so you can keep values like OMNIDIST_VERSION, NPM_PUBLISH_TOKEN, and UV_PUBLISH_TOKEN there.

  1. Build binaries for configured targets:
omnidist build

This also writes the resolved build version to .omnidist/<profile>/dist/VERSION (.omnidist/default/dist/VERSION with init defaults).

  1. Stage and verify artifacts:
omnidist stage
omnidist verify

omnidist uv stage converts the resolved version to PEP 440 and writes .omnidist/<profile>/uv/pyproject.toml with that version. It also recreates .omnidist/<profile>/uv/dist to prevent stale wheel artifacts from previous runs. On first stage run, omnidist creates .omnidist/.gitignore (if missing).

  1. Publish when verification passes:
omnidist publish
  1. Generate tag-triggered release workflow:
omnidist ci

The generated workflow publishes npm and uv artifacts and also creates a GitHub release with the built cross-platform binaries plus checksums.txt.

Common Commands

# Build binaries for configured targets and persist build version
omnidist build

# Print a quickstart command sequence for this repo
omnidist quickstart

# Show runtime version/build metadata
omnidist version

# Stage and verify both distributions (npm -> uv)
omnidist stage
omnidist verify

# Stage dev/pre-release artifacts
omnidist stage --dev

# Publish both distributions (fail-fast, npm -> uv)
omnidist publish

# Generate GitHub Actions workflow for tagged releases
omnidist ci

# Limit orchestration to one distribution
omnidist stage --only npm
omnidist verify --only uv

# Distribution-specific publishing options
omnidist npm publish --tag next --otp <6-digit-code>
omnidist uv publish --publish-url https://test.pypi.org/legacy/ --token <pypi-token>

Environment Variables and .env

omnidist loads .env automatically at startup (via godotenv) if present.

Supported variables:

  • OMNIDIST_VERSION: used only when version.source: env; also expanded in build.ldflags templates (for example ${OMNIDIST_VERSION}). VERSION is not used.
  • OMNIDIST_CONFIG: optional global config file path (same as --config).
  • OMNIDIST_PROFILE: optional config profile name (same as --profile).
  • OMNIDIST_OMNIDIST_ROOT: optional project root directory (same as --omnidist-root).
  • OMNIDIST_GIT_COMMIT: optional ldflags template variable for build metadata; populated automatically by omnidist build when git metadata is available.
  • OMNIDIST_BUILD_DATE: optional ldflags template variable for build metadata; populated automatically by omnidist build as UTC RFC3339.
  • NPM_PUBLISH_TOKEN: required for npm publish commands in token auth mode when not using --dry-run
  • distributions.npm.publish-auth: npm publish auth mode; token uses NPM_PUBLISH_TOKEN, trusted uses ambient trusted publishing/OIDC
  • distributions.npm.repository-url: repository URL written to staged package.json repository.url; required for trusted npm publishing
  • UV_PUBLISH_TOKEN: used by uv publish when --token is not provided

Example .env:

OMNIDIST_VERSION=1.2.3
OMNIDIST_PROFILE=release
NPM_PUBLISH_TOKEN=npm_xxx
UV_PUBLISH_TOKEN=pypi-xxx

Configuration

.omnidist/omnidist.yaml:

omnidist init now generates the profiles-mode shape (profiles.default) by default. Legacy top-level format remains supported when loading config files.

tool:
  name: omnidist
  main: ./cmd/omnidist

version:
  source: git-tag # git-tag | file | env | fixed
  file: VERSION # optional; used when source is file (default VERSION)
  fixed: 1.2.3 # required when source is fixed

readme-path: docs/README.md # optional shared README source for staging

targets:
  - os: darwin
    arch: amd64
  - os: darwin
    arch: arm64
  - os: linux
    arch: amd64
  - os: linux
    arch: arm64
  - os: windows
    arch: amd64

build:
  ldflags: -s -w
  tags: []
  cgo: false

distributions:
  npm:
    package: "@omnidist/omnidist"
    registry: https://registry.npmjs.org
    access: public # public | restricted
    publish-auth: token # token | trusted
    repository-url: git+https://github.com/your-org/your-repo.git # required for trusted publish
    license: MIT # optional override for package.json license; omit to use SEE LICENSE IN <file>
    keywords: [cli, ai, llm] # optional npm meta-package keywords
    readme-path: docs/npm-readme.md # optional npm-specific README source
    include-readme: true # include project README.md in staged packages when present

  uv:
    package: omnidist
    index-url: https://upload.pypi.org/legacy/
    linux-tag: manylinux2014 # manylinux2014 | musllinux_1_2
    readme-path: docs/uv-readme.md # optional uv-specific README source
    include-readme: true # include project README.md in staged wheels when present

Profiles mode:

profiles:
  default:
    tool:
      name: omnidist
      main: ./cmd/omnidist
    version:
      source: env
    readme-path: docs/README.md
    targets:
      - os: linux
        arch: amd64
    build:
      ldflags: -s -w
      tags: []
      cgo: false
    distributions:
      npm:
        package: "@scope/mytool"
        keywords: [cli, ai, llm]
        readme-path: docs/npm-readme.md
      uv:
        package: mytool
        readme-path: docs/uv-readme.md

  release:
    tool:
      name: omnidist
      main: ./cmd/omnidist
    version:
      source: fixed
      fixed: 1.0.0
    targets:
      - os: linux
        arch: amd64
    build:
      ldflags: -s -w
      tags: []
      cgo: false

Select a profile with --profile <name> or OMNIDIST_PROFILE. If profiles is present and no profile is provided, default is used. Mixing top-level runtime fields and profiles in the same file is not supported.

targets use Go values (GOOS/GOARCH). Distribution workflows map them as needed (for example windows/amd64 -> npm win32/x64).

README source precedence during staging: distributions.<name>.readme-path -> readme-path -> README.md. If a configured readme-path is set and cannot be read, staging fails.

When distributions.npm.keywords is set, omnidist writes those values to the staged npm meta package package.json.

For appkit version injection, configure build.ldflags in your project config:

build:
  ldflags: -s -w -X github.com/metalagman/appkit/version.version=${OMNIDIST_VERSION} -X github.com/metalagman/appkit/version.gitCommit=${OMNIDIST_GIT_COMMIT} -X github.com/metalagman/appkit/version.buildDate=${OMNIDIST_BUILD_DATE}

build.ldflags values are expanded with os.ExpandEnv during omnidist build. Both ${VAR} and $VAR are supported; unset vars expand to empty strings.

With version.source: git-tag, release workflows require HEAD to be on an exact SemVer tag (vX.Y.Z or X.Y.Z).

With version.source: file, omnidist reads ./VERSION from the repository root.

With version.source: file, you can override the path via version.file (for example versions/release.txt).

With version.source: fixed, set version.fixed to an exact value in config (for example 1.2.3).

With version.source: env, set OMNIDIST_VERSION (for example in .env) before build/stage/publish.

Use global --omnidist-root <path> to set the project root for a command. Omnidist resolves it to an absolute path at startup and changes working directory to it before loading .env and config.

Workspace behavior:

  • Legacy config writes artifacts to .omnidist/*.
  • Profiles config writes artifacts to .omnidist/<profile>/*.
  • Isolation is by profile name. If different config files use the same profile name in the same repo, they share the same .omnidist/<profile> workspace.

Command Reference

Top-level:

  • omnidist init
  • omnidist build
  • omnidist quickstart
  • omnidist version
  • omnidist ci [--force]
  • omnidist stage [--dev] [--only npm|uv|npm,uv]
  • omnidist verify [--only npm|uv|npm,uv]
  • omnidist publish [--dry-run] [--only npm|uv|npm,uv]
  • omnidist npm
  • omnidist uv

Global flags:

  • --config <path>
  • --profile <name>
  • --omnidist-root <path>

NPM subcommands:

  • omnidist npm stage [--dev]
  • omnidist npm verify
  • omnidist npm publish [--dry-run] [--tag <tag>] [--registry <url>] [--otp <code>]

UV subcommands:

  • omnidist uv stage [--dev]
  • omnidist uv verify
  • omnidist uv publish [--dry-run] [--publish-url <url>] [--token <pypi-token>]

Usage Patterns

Local development loop

Use this when iterating on the CLI binary and validating artifact generation locally:

omnidist build
omnidist stage
omnidist verify

Dev pre-release artifacts

Generate prerelease versions from git describe data:

omnidist stage --dev

Unified multi-distribution orchestration

Top-level stage, verify, and publish run distributions in deterministic order: npm first, then uv, and stop on first failure.

Select a subset with --only:

omnidist stage --only uv
omnidist verify --only npm
omnidist publish --dry-run --only npm,uv

CI bootstrap for tag releases

Generate .github/workflows/omnidist-release.yml:

omnidist ci

The generated workflow triggers on v* tag pushes and runs: build -> stage -> verify -> publish, then publishes the built binaries and checksums to the GitHub release.

If workflow already exists:

omnidist ci --force

npm publishing flow with custom options

omnidist npm publish --dry-run --tag next --registry https://registry.npmjs.org

Before npm commands run, omnidist writes .omnidist/.npmrc from distributions.npm.registry using: //<registry>/:_authToken=${NPM_PUBLISH_TOKEN}. If staged package version contains a -dev prerelease and --tag is not provided, omnidist auto-publishes with --tag dev.

To publish through npm trusted publishing, set:

distributions:
  npm:
    publish-auth: trusted
    repository-url: git+https://github.com/your-org/your-repo.git

In trusted mode, omnidist skips token-only auth preflight and does not force a workspace .npmrc; npm publish uses the ambient CI credentials instead. For GitHub Actions, that means:

  • the workflow must grant id-token: write
  • the job must use a supported Node/npm toolchain for OIDC
  • each published npm package must have its own trusted publisher configured on npm
  • each staged package must include a repository.url that exactly matches the GitHub repository

omnidist ci emits the required GitHub Actions OIDC permissions and Node setup when publish-auth: trusted is configured.

If your npm account requires 2FA for publish operations:

omnidist npm publish --otp <6-digit-code>

uv publishing flow with custom index/auth

omnidist uv publish --publish-url https://upload.pypi.org/legacy/ --token <pypi-token>

omnidist uv publish uses token authentication.
Provide token via --token or UV_PUBLISH_TOKEN (required for non-dry-run). omnidist uv verify and omnidist uv publish use the staged version from .omnidist/uv/pyproject.toml when present. For PyPI/TestPyPI, omnidist uv verify fails if the staged version contains local metadata (+...), since those indexes reject local versions.

TestPyPI dry-run style validation:

omnidist uv publish --dry-run --publish-url https://test.pypi.org/legacy/

Usage Examples

npm release path

git tag v1.2.0
omnidist build
omnidist npm stage
omnidist npm verify
omnidist npm publish

uv release path

git tag v1.2.0
omnidist build
omnidist uv stage
omnidist uv verify
omnidist uv publish --publish-url https://upload.pypi.org/legacy/

uv dry-run publish

omnidist uv publish --dry-run --publish-url https://test.pypi.org/legacy/

version from environment

version:
  source: env
export OMNIDIST_VERSION=2.0.0
omnidist npm stage
omnidist uv stage

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

omnidist-0.1.28-py3-none-win_amd64.whl (6.0 MB view details)

Uploaded Python 3Windows x86-64

omnidist-0.1.28-py3-none-manylinux2014_x86_64.whl (5.6 MB view details)

Uploaded Python 3

omnidist-0.1.28-py3-none-manylinux2014_aarch64.whl (5.3 MB view details)

Uploaded Python 3

omnidist-0.1.28-py3-none-macosx_11_0_arm64.whl (5.5 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

omnidist-0.1.28-py3-none-macosx_10_13_x86_64.whl (5.8 MB view details)

Uploaded Python 3macOS 10.13+ x86-64

File details

Details for the file omnidist-0.1.28-py3-none-win_amd64.whl.

File metadata

  • Download URL: omnidist-0.1.28-py3-none-win_amd64.whl
  • Upload date:
  • Size: 6.0 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for omnidist-0.1.28-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 837851e05d9ae821efeb4de9db0a4e5d284c8284e9d72e04bd5299d5f0b29894
MD5 f39c8994068e1382462d298178a3410a
BLAKE2b-256 7b43e6d8aee8012041489de58f628d1a97643601b2d58a1240f0cafb66b704a7

See more details on using hashes here.

File details

Details for the file omnidist-0.1.28-py3-none-manylinux2014_x86_64.whl.

File metadata

  • Download URL: omnidist-0.1.28-py3-none-manylinux2014_x86_64.whl
  • Upload date:
  • Size: 5.6 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for omnidist-0.1.28-py3-none-manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e11581cce58463c9f3cc6ed4fef175e797e2291708e1984818d3a2e8b9d2b3d4
MD5 ec346742bdbbbb913278fd28e67039d4
BLAKE2b-256 3a2d0575f0b0575e670405eed74c219e01868dbc5dedd017c5575f57a21f95d7

See more details on using hashes here.

File details

Details for the file omnidist-0.1.28-py3-none-manylinux2014_aarch64.whl.

File metadata

  • Download URL: omnidist-0.1.28-py3-none-manylinux2014_aarch64.whl
  • Upload date:
  • Size: 5.3 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for omnidist-0.1.28-py3-none-manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 b8c7b810bbb72d24f5d2ef66ec94e5bb948e01c3fced23bafeff231978d40e59
MD5 5e3331bfeea448a225b06dc63a46f168
BLAKE2b-256 a088440273f568ec9ee1818c69c947831d53074659b7554a129a830bc8e56de4

See more details on using hashes here.

File details

Details for the file omnidist-0.1.28-py3-none-macosx_11_0_arm64.whl.

File metadata

  • Download URL: omnidist-0.1.28-py3-none-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 5.5 MB
  • Tags: Python 3, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for omnidist-0.1.28-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ccd5d887e88e3c5afddaeb43a98fdecde190fd9d9f142ccd4c83f950547786a5
MD5 ead955b6e8cbaafa5f57eea1e57ba090
BLAKE2b-256 8c55866c37bc7cdf077188d9c0e7961f3888f0d1c56aadbd6761adcd3709cd01

See more details on using hashes here.

File details

Details for the file omnidist-0.1.28-py3-none-macosx_10_13_x86_64.whl.

File metadata

  • Download URL: omnidist-0.1.28-py3-none-macosx_10_13_x86_64.whl
  • Upload date:
  • Size: 5.8 MB
  • Tags: Python 3, macOS 10.13+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for omnidist-0.1.28-py3-none-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 0c971f2ad47e450ccde9f4cdaf25c57255c7b740b00aae8a6b93f1ddd2321ca6
MD5 3da3895e481aa65eb0b7bec9f1db50b7
BLAKE2b-256 06f830009a09145ddc5374234f8fb92147feb783894c1f208b24ada8f54243fc

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page