Publish binaries to npm, pypi, and github releases.
Project description
Bin Upload
Easily distribute binaries via npm, pypi, and GitHub releases.
Overview
bin-upload is a CLI tool built with Bun that packages and publishes pre-built binaries to multiple registries and platforms. It supports:
- npm — Publishes a main package that depend on platform-specific binary packages using optionalDependencies. When the main package is installed, the corresponding platform-specific package containing the actual binary is also installed. This allows for downloading and installing only the necessary binary without relying on post-install scripts, which some package managers do not run for dependencies.
- PyPI — Builds wheel (
.whl) packages for each platform-specific tag. Tools such aspipanduvautomatically install the correct wheel for the machine installing the package. - GitHub Releases — Creates releases and uploads archive assets (
.tar.gzor.zip).
Installation
From npm
# Globally
npm install -g @d-dev/bin-upload
# or as a package dep
npm install -D @d-dev/bin-upload
# or run with npx
npx @d-dev/bin-upload <command>
From PyPI
pip install bin-upload
# or with UV
uv tool install bin-upload
# or run with uvx
uvx bin-upload <command>
From GitHub Releases
Download the appropriate binary for your platform from the releases page.
Quick Start
-
Initialize a configuration file:
bin-upload initThis will walk you through an interactive prompt and generate a
bin-upload.config.yamlfile. -
Pack binaries into publishable artifacts:
bin-upload packThis will generate artifacts that can be published to npm (tarballs), pypi (wheel), and GitHub (tarballs and zips).
-
Publish the artifacts:
bin-upload publishThis publishes the artifacts generatd by the
packcommand.
Commands
init
Initialize a bin-upload configuration file via interactive prompts.
bin-upload init [options]
| Option | Description |
|---|---|
--help, -h |
Show help. |
--config, -c |
Path to output configuration file. |
--force, -f |
Overwrite existing configuration file. |
pack
Build publishable artifacts (npm tarballs, PyPI wheels, GitHub archives) from your binaries.
bin-upload pack [options]
| Option | Description |
|---|---|
--help, -h |
Show help. |
--config, -c |
Path to YAML configuration file. Default: bin-upload.config.yaml. |
--set, -s |
Set configuration values, e.g., --set npm.packageJson.version=1.0.0. |
--source |
Sources to pack: all, npm, pypi, github. Default: all. |
--verbose |
Enable verbose logging. |
publish
Publish the packed artifacts to their respective registries.
bin-upload publish [options]
| Option | Description |
|---|---|
--help, -h |
Show help. |
--config, -c |
Path to YAML configuration file. Default: bin-upload.config.yaml. |
--set, -s |
Set configuration values, e.g., --set pypi.publish.token=some-token. |
--source |
Sources to publish: all, npm, pypi, github. Default: all. |
--verbose |
Enable verbose logging. |
Configuration
The configuration file is a YAML file (default: bin-upload.config.yaml) that supports Eta templating with access to environment variables and built-in variables.
Template Variables
env— Access environment variables, e.g.,<%= env.NPM_TOKEN %>.vars.gitTag— The latest semver git tag (without thevprefix), extracted from tags matchingv*.*.*.
Configuration Structure
binaries:
# binaryId -> path to binary file
linux-x64: "./bin/linux-x64/my-binary"
darwin-arm64: "./bin/darwin-arm64/my-binary"
win-x64: "./bin/win-x64/my-binary.exe"
pack:
prePackCommand: "bun run build" # Optional command to run before packing
dir: "./dist" # Output directory for packed artifacts
npm:
readmeFile: "README.md"
licenseFile: "LICENSE"
packageJson:
name: "@scope/my-package"
version: <%= vars.gitTag %>
description: "My binary package"
license: "MIT"
binaryPackages:
# binaryId -> { name, os, arch } using Node.js process.platform/process.arch values
linux-x64:
name: "@scope/my-package-linux-x64"
os: "linux"
arch: "x64"
darwin-arm64:
name: "@scope/my-package-darwin-arm64"
os: "darwin"
arch: "arm64"
win-x64:
name: "@scope/my-package-win-x64"
os: "win32"
arch: "x64"
binNames:
- "my-binary" # Optional custom bin entry point names
publish:
access: "public"
tag: "latest"
# For publishing from local machine
# Should omit if publishing from GitHub actions
# using trusted publisher with npm
"registry=https://registry.npmjs.org/": true
"//registry.npmjs.org/:_authToken=<%= env.NPM_TOKEN %>": true
pypi:
readmeFile: "README.md"
platformTags:
# binaryId -> wheel platform tag
linux-x64: "manylinux_2_17_x86_64"
darwin-arm64: "macosx_11_0_arm64"
win-x64: "win_amd64"
metadata:
Name: "my-package"
Version: <%= vars.gitTag %>
Summary: "My binary package"
Requires-Python: ">=3.11"
entryPointNames:
- "my-binary" # Optional custom console_scripts entry points
publish:
# For publishing from local machine
# should omit if publishing from GitHub actions
# using trusted publisher with pypi
token: "<%= env.PYPI_TOKEN %>"
github:
owner: "my-org"
repo: "my-repo"
# Token should have the following repository level permissions
# Metadata read
# Contents read and write
token: "<%= env.GITHUB_TOKEN %>"
release:
tag_name: "v<%= vars.gitTag %>"
archives:
# Simple: binaryId -> format
linux-x64: "tar.gz"
win-x64: "zip"
# Advanced: custom archive with file globs
# source:
# format: "tar.gz"
# files:
# - cwd: "src"
# pattern: "**/*"
# - "README.md"
Setting Config Values via CLI
Use --set (-s) to override configuration values using dot notation:
bin-upload pack -s npm.packageJson.version=1.0.0 -s pypi.metadata.Version=1.0.0
bin-upload publish -s "pypi.publish.token=some-token"
This will create the following values in the yaml configuration.
npm
packageJson
version: 1.0.0
pypi
metadata
Version: 1.0.0
Escape dots and equals signs with backslashes when they are part of the key:
bin-upload publish -s "npm.publish.registry\=https://registry\.npmjs\.org/=true"
This will create the following values in the yaml configuration.
npm
publish
"registry=https://registry.npmjs.org/": true
How it Works
npm
The pack command generates:
- A main package that detects the user's platform (
process.platform+process.arch) and delegates to the appropriate binary package. - Platform-specific packages listed as
optionalDependenciesin the main package, each containing the binary for that platform.
Note: musl Linux binaries cannot be distinguished from glibc Linux binaries via
process.platform/process.arch, so they cannot be published to npm.
PyPI
The pack command builds platform-specific .whl (wheel) files. Each wheel contains:
- A Python wrapper module that locates and executes the bundled binary.
- Console script entry points for CLI usage.
GitHub Releases
The pack command creates .tar.gz or .zip archives. The publish command creates a GitHub release (if one doesn't exist for the tag) and uploads the archives as release assets.
Environment Variables
| Variable | Used By |
|---|---|
NPM_TOKEN |
npm publish authentication |
PYPI_TOKEN |
PyPI publish authentication |
GITHUB_TOKEN |
GitHub API authentication |
These can be set in a .env file or your CI environment. When using trusted publishers (e.g., GitHub Actions OIDC), tokens may not be required.
Publishing
One of the variables available for reference in the configuration file is gitTag, a reference to the latest git tag on the current git branch that matches v\d+\.\d+\.\d+ (the variable is without the leading v). Referencing this variable in the configuration allows for git-based release process and bypasses the need to manually update version numbers when releasing.
Local git-based Release Flow
git add .
git commit -m "..."
git tag -a v1.0.0 -m "Release v1.0.0"
# The tag needs to exist in the remote
# in order for bin-upload to create a release
# for the tag and upload assets
git push --follow-tags
bin-upload pack
bin-upload publish
Publishing with GitHub actions
The following GitHub action will publish the binary artifacts whenever a version tag is pushed to the repo. You will need to establish trusted publishing between the GitHub repo and npm and/or pypi if publishing to those locations.
# .github/workflows/relesae.yml
name: Release
on:
push:
tags:
- "v*"
permissions:
contents: write
id-token: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Build binaries
run: COMMAND TO BUILD YOUR BINARIES
- name: Pack
run: uvx bin-upload pack
- name: Publish
run: uvx bin-upload publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
With the above GitHub action, you no longer need to set auth or tokens in the npm.publish and pypi.publish sections. You still need to reference the GITHUB_TOKEN in the github portion of the config.
From here, the release process is similar to releasing from local machine
git add .
git commit -m "..."
git tag -a v1.0.0 -m "Release v1.0.0"
git push --follow-tags
Development
This project uses Bun as its runtime and build tool.
# Install dependencies
bun install
# Build binaries for all platforms
bun run build
# Build for a specific target
bun run ./scripts/build.ts bun-darwin-arm64
# Lint and format
bun run check
bun run fix
License
MIT — Copyright (c) Derek Worthen
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bin_upload-0.0.7-py3-none-win_amd64.whl.
File metadata
- Download URL: bin_upload-0.0.7-py3-none-win_amd64.whl
- Upload date:
- Size: 42.4 MB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ef28136e1947645ff7f9e79e0c04abdb460bf560d6adc9601f7bd94687c4d636
|
|
| MD5 |
8a0b5dfaa9f65bef511b0c52384ed935
|
|
| BLAKE2b-256 |
bbcd4d87a93ef73086ff88320654efb311c10e6bb7854d1323e7b66acad1b0d5
|
File details
Details for the file bin_upload-0.0.7-py3-none-musllinux_1_2_x86_64.whl.
File metadata
- Download URL: bin_upload-0.0.7-py3-none-musllinux_1_2_x86_64.whl
- Upload date:
- Size: 37.6 MB
- Tags: Python 3, musllinux: musl 1.2+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ae19bcc3c30cdee8417e9818be1db2e1efc7f1f87e15cdb50d0b244f922e76ef
|
|
| MD5 |
bb743dde698ea70bd339c4ac0d3c0a0c
|
|
| BLAKE2b-256 |
89dae3c2dc06a8582817ffde50617f11e064ab051f598b9b4d5e05edce3c3caf
|
File details
Details for the file bin_upload-0.0.7-py3-none-musllinux_1_2_aarch64.whl.
File metadata
- Download URL: bin_upload-0.0.7-py3-none-musllinux_1_2_aarch64.whl
- Upload date:
- Size: 37.6 MB
- Tags: Python 3, musllinux: musl 1.2+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
19b119089ee3f1cba79805260b9196bf0850ce7b5af837e3f430b8366d380cae
|
|
| MD5 |
156618e70defb0bce8b40f0da5359a95
|
|
| BLAKE2b-256 |
d705094f44b09d88d9651d80b12801db7e66c180139eab2ab2014c112043b5ae
|
File details
Details for the file bin_upload-0.0.7-py3-none-manylinux_2_17_x86_64.whl.
File metadata
- Download URL: bin_upload-0.0.7-py3-none-manylinux_2_17_x86_64.whl
- Upload date:
- Size: 40.0 MB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
29c167914be66149ffa163d28cc7210e574b809fa06c1c09c86ade0ff6614c07
|
|
| MD5 |
5aa8f5a0775b0a85a2fa0359ef648e4f
|
|
| BLAKE2b-256 |
d730485932524a34a4d2d4845209021b4138c66a5b19ad04e3b3c4cbe8b9b26f
|
File details
Details for the file bin_upload-0.0.7-py3-none-manylinux_2_17_aarch64.whl.
File metadata
- Download URL: bin_upload-0.0.7-py3-none-manylinux_2_17_aarch64.whl
- Upload date:
- Size: 39.9 MB
- Tags: Python 3, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
219a629a8177912cc767ff0fff43e87c4441cd1fe9244b61ddebf3c0ce405b29
|
|
| MD5 |
6cddfb959a2ccbb28e6932d43f58bdf8
|
|
| BLAKE2b-256 |
a31f203e9c1e8747a7c5a1c63578abf1bec8cc010150f054a318f0d55f744a5a
|
File details
Details for the file bin_upload-0.0.7-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: bin_upload-0.0.7-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 23.0 MB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a031b7aa51c89a0d3430c78ef1cbee690fcf46742c88fa980f2dd8550a21c95d
|
|
| MD5 |
ab97206e86cdbbf7ecc313f6b88ec432
|
|
| BLAKE2b-256 |
184c5d5ff3d346c9417579de48e372e2fa10a7d95d17891d35f4280faab8aa55
|
File details
Details for the file bin_upload-0.0.7-py3-none-macosx_10_9_x86_64.whl.
File metadata
- Download URL: bin_upload-0.0.7-py3-none-macosx_10_9_x86_64.whl
- Upload date:
- Size: 24.9 MB
- Tags: Python 3, macOS 10.9+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f77d99f2ace1586d9e559ce1c4d37cfaeffedae1c80b4991f8d7860702cbd0ce
|
|
| MD5 |
dc0bdac076d703ba36d0f143c815effd
|
|
| BLAKE2b-256 |
7b7ca5b9a636c06bd31f0cb4d3f4ccc56d778f07b265e078cd68c45b120a91c0
|