Skip to main content

Agent Skills Framework Extension

Binary Distribution Patterns Skill

When to Use This Skill

Use this skill when implementing binary distribution patterns patterns in your codebase.

How to Use This Skill

  1. Review the patterns and examples below
  2. Apply the relevant patterns to your implementation
  3. Follow the best practices outlined in this skill

Cross-platform binary releases, artifact management, and distribution strategies.

Core Capabilities

  1. Cross-Platform Builds - Multi-OS, multi-arch compilation
  2. Release Automation - CI/CD release workflows
  3. Artifact Signing - Code signing and verification
  4. Distribution - CDN, package managers, direct download
  5. Installation - Shell scripts, package managers

Multi-Platform Build Matrix

# .github/workflows/release.yml
name: Release

on:
push:
tags:
- 'v*'

env:
CARGO_TERM_COLOR: always

jobs:
build:
strategy:
matrix:
include:
# Linux
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
artifact: myapp-linux-x64
- os: ubuntu-latest
target: aarch64-unknown-linux-gnu
artifact: myapp-linux-arm64
cross: true

# macOS
- os: macos-latest
target: x86_64-apple-darwin
artifact: myapp-darwin-x64
- os: macos-latest
target: aarch64-apple-darwin
artifact: myapp-darwin-arm64

# Windows
- os: windows-latest
target: x86_64-pc-windows-msvc
artifact: myapp-windows-x64.exe

runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v4

- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}

- name: Install cross-compilation tools
if: matrix.cross
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu
echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV

- name: Build
run: cargo build --release --target ${{ matrix.target }}

- name: Package (Unix)
if: runner.os != 'Windows'
run: |
mkdir -p dist
cp target/${{ matrix.target }}/release/myapp dist/${{ matrix.artifact }}
cd dist
tar -czvf ${{ matrix.artifact }}.tar.gz ${{ matrix.artifact }}
sha256sum ${{ matrix.artifact }}.tar.gz > ${{ matrix.artifact }}.tar.gz.sha256

- name: Package (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
New-Item -ItemType Directory -Force -Path dist
Copy-Item target/${{ matrix.target }}/release/myapp.exe dist/${{ matrix.artifact }}
Compress-Archive -Path dist/${{ matrix.artifact }} -DestinationPath dist/${{ matrix.artifact }}.zip
Get-FileHash dist/${{ matrix.artifact }}.zip -Algorithm SHA256 |
ForEach-Object { $_.Hash.ToLower() + " " + (Split-Path $_.Path -Leaf) } |
Out-File -FilePath dist/${{ matrix.artifact }}.zip.sha256

- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact }}
path: dist/*
retention-days: 1

release:
needs: build
runs-on: ubuntu-latest
permissions:
contents: write

steps:
- uses: actions/checkout@v4

- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts

- name: Prepare release files
run: |
mkdir release
find artifacts -type f -name "*.tar.gz" -o -name "*.zip" -o -name "*.sha256" |
while read f; do cp "$f" release/; done

- name: Generate release notes
run: |
echo "## What's Changed" > RELEASE_NOTES.md
git log $(git describe --tags --abbrev=0 HEAD^)..HEAD --pretty=format:"- %s" >> RELEASE_NOTES.md

- name: Create Release
uses: softprops/action-gh-release@v1
with:
files: release/*
body_path: RELEASE_NOTES.md
draft: false
prerelease: ${{ contains(github.ref, '-') }}

Release Manifest

// scripts/generate-manifest.ts
interface ReleaseAsset {
name: string;
os: 'linux' | 'darwin' | 'windows';
arch: 'x64' | 'arm64';
url: string;
sha256: string;
size: number;
}

interface ReleaseManifest {
version: string;
releaseDate: string;
assets: ReleaseAsset[];
changelog: string;
minVersion?: string;
}

async function generateManifest(version: string): Promise<ReleaseManifest> {
const assets: ReleaseAsset[] = [];
const baseUrl = `https://github.com/org/repo/releases/download/v${version}`;

const platforms = [
{ os: 'linux', arch: 'x64', ext: 'tar.gz' },
{ os: 'linux', arch: 'arm64', ext: 'tar.gz' },
{ os: 'darwin', arch: 'x64', ext: 'tar.gz' },
{ os: 'darwin', arch: 'arm64', ext: 'tar.gz' },
{ os: 'windows', arch: 'x64', ext: 'zip' },
];

for (const platform of platforms) {
const name = `myapp-${platform.os}-${platform.arch}.${platform.ext}`;
const sha256Path = `dist/${name}.sha256`;

if (existsSync(sha256Path)) {
const sha256 = readFileSync(sha256Path, 'utf-8').split(' ')[0].trim();
const size = statSync(`dist/${name}`).size;

assets.push({
name,
os: platform.os as ReleaseAsset['os'],
arch: platform.arch as ReleaseAsset['arch'],
url: `${baseUrl}/${name}`,
sha256,
size,
});
}
}

const changelog = execSync(`git log --pretty=format:"- %s" v${getPreviousVersion()}..HEAD`)
.toString()
.trim();

return {
version,
releaseDate: new Date().toISOString(),
assets,
changelog,
};
}

// Write manifest to file
const manifest = await generateManifest(process.env.VERSION!);
writeFileSync('dist/manifest.json', JSON.stringify(manifest, null, 2));

Install Script

#!/usr/bin/env bash
# install.sh - Universal installer for myapp

set -euo pipefail

# Configuration
REPO="org/myapp"
INSTALL_DIR="${MYAPP_INSTALL_DIR:-$HOME/.myapp/bin}"
VERSION="${MYAPP_VERSION:-latest}"

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1" >&2; }

# Detect platform
detect_platform() {
local os arch

case "$(uname -s)" in
Linux*) os="linux" ;;
Darwin*) os="darwin" ;;
MINGW*|MSYS*|CYGWIN*) os="windows" ;;
*) log_error "Unsupported OS: $(uname -s)"; exit 1 ;;
esac

case "$(uname -m)" in
x86_64|amd64) arch="x64" ;;
arm64|aarch64) arch="arm64" ;;
*) log_error "Unsupported architecture: $(uname -m)"; exit 1 ;;
esac

echo "${os}-${arch}"
}

# Get latest version from GitHub API
get_latest_version() {
local url="https://api.github.com/repos/${REPO}/releases/latest"
curl -fsSL "$url" | grep '"tag_name"' | sed -E 's/.*"v([^"]+)".*/\1/'
}

# Download and verify
download_and_install() {
local platform="$1"
local version="$2"
local ext="tar.gz"

[[ "$platform" == windows-* ]] && ext="zip"

local filename="myapp-${platform}.${ext}"
local url="https://github.com/${REPO}/releases/download/v${version}/${filename}"
local sha_url="${url}.sha256"

log_info "Downloading myapp v${version} for ${platform}..."

local tmpdir
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT

# Download binary and checksum
curl -fsSL -o "${tmpdir}/${filename}" "$url"
curl -fsSL -o "${tmpdir}/${filename}.sha256" "$sha_url"

# Verify checksum
log_info "Verifying checksum..."
cd "$tmpdir"
if command -v sha256sum >/dev/null 2>&1; then
sha256sum -c "${filename}.sha256"
elif command -v shasum >/dev/null 2>&1; then
shasum -a 256 -c "${filename}.sha256"
else
log_warn "No SHA256 tool found, skipping verification"
fi

# Extract and install
log_info "Installing to ${INSTALL_DIR}..."
mkdir -p "$INSTALL_DIR"

if [[ "$ext" == "tar.gz" ]]; then
tar -xzf "$filename" -C "$INSTALL_DIR"
else
unzip -o "$filename" -d "$INSTALL_DIR"
fi

chmod +x "${INSTALL_DIR}/myapp"*
}

# Update shell profile
update_path() {
local shell_profile=""

case "$SHELL" in
*/bash) shell_profile="$HOME/.bashrc" ;;
*/zsh) shell_profile="$HOME/.zshrc" ;;
*/fish) shell_profile="$HOME/.config/fish/config.fish" ;;
esac

if [[ -n "$shell_profile" ]] && ! grep -q "$INSTALL_DIR" "$shell_profile" 2>/dev/null; then
log_info "Adding ${INSTALL_DIR} to PATH in ${shell_profile}"

if [[ "$SHELL" == */fish ]]; then
echo "set -gx PATH \$PATH $INSTALL_DIR" >> "$shell_profile"
else
echo "export PATH=\"\$PATH:$INSTALL_DIR\"" >> "$shell_profile"
fi

log_info "Please restart your shell or run: source $shell_profile"
fi
}

main() {
log_info "Installing myapp..."

local platform
platform=$(detect_platform)
log_info "Detected platform: ${platform}"

if [[ "$VERSION" == "latest" ]]; then
VERSION=$(get_latest_version)
fi
log_info "Version: ${VERSION}"

download_and_install "$platform" "$VERSION"
update_path

log_info "Installation complete!"
log_info "Run 'myapp --version' to verify"
}

main "$@"

npm Binary Package Pattern

// package.json (main package)
{
"name": "myapp",
"version": "1.0.0",
"description": "Cross-platform CLI tool",
"bin": {
"myapp": "bin/myapp"
},
"scripts": {
"postinstall": "node scripts/postinstall.js"
},
"optionalDependencies": {
"@myapp/darwin-x64": "1.0.0",
"@myapp/darwin-arm64": "1.0.0",
"@myapp/linux-x64": "1.0.0",
"@myapp/linux-arm64": "1.0.0",
"@myapp/win32-x64": "1.0.0"
}
}
// scripts/postinstall.js
const { existsSync, mkdirSync, copyFileSync, chmodSync } = require('fs');
const { join } = require('path');

const PLATFORM_PACKAGES = {
'darwin-x64': '@myapp/darwin-x64',
'darwin-arm64': '@myapp/darwin-arm64',
'linux-x64': '@myapp/linux-x64',
'linux-arm64': '@myapp/linux-arm64',
'win32-x64': '@myapp/win32-x64',
};

function getBinaryPath() {
const platformKey = `${process.platform}-${process.arch}`;
const packageName = PLATFORM_PACKAGES[platformKey];

if (!packageName) {
console.error(`Unsupported platform: ${platformKey}`);
process.exit(1);
}

try {
const packagePath = require.resolve(`${packageName}/package.json`);
const packageDir = join(packagePath, '..');
const binaryName = process.platform === 'win32' ? 'myapp.exe' : 'myapp';
return join(packageDir, binaryName);
} catch (e) {
console.error(`Platform package not installed: ${packageName}`);
console.error('Try running: npm install --ignore-scripts && npm run postinstall');
process.exit(1);
}
}

function install() {
const sourcePath = getBinaryPath();
const binDir = join(__dirname, '..', 'bin');
const targetPath = join(binDir, process.platform === 'win32' ? 'myapp.exe' : 'myapp');

if (!existsSync(binDir)) {
mkdirSync(binDir, { recursive: true });
}

copyFileSync(sourcePath, targetPath);
chmodSync(targetPath, 0o755);

console.log(`Installed myapp binary to ${targetPath}`);
}

install();

Usage Examples

Setup Cross-Platform Builds

Apply binary-distribution-patterns skill to configure GitHub Actions for multi-platform Rust binary releases

Create Install Script

Apply binary-distribution-patterns skill to create universal install script with checksum verification

npm Binary Package

Apply binary-distribution-patterns skill to structure npm package with platform-specific optionalDependencies

Integration Points

  • cicd-pipeline-design - CI/CD workflows
  • npm-packaging-patterns - npm distribution
  • code-signing - Binary signing

Success Output

When successful, this skill MUST output:

✅ SKILL COMPLETE: binary-distribution-patterns

Completed:
- [x] Multi-platform build matrix configured (Linux/macOS/Windows)
- [x] Cross-compilation tools setup for ARM64 targets
- [x] SHA256 checksums generated for all artifacts
- [x] Release manifest created with download URLs
- [x] Universal install script tested on all platforms
- [x] GitHub Release created with all artifacts
- [x] npm binary package structure validated

Outputs:
- .github/workflows/release.yml (GitHub Actions workflow)
- dist/myapp-{platform}-{arch}.{tar.gz|zip} (binaries)
- dist/myapp-{platform}-{arch}.{tar.gz|zip}.sha256 (checksums)
- dist/manifest.json (release metadata)
- install.sh (universal installer)
- package.json (npm binary wrapper)
- scripts/postinstall.js (npm platform selection)

Completion Checklist

Before marking this skill as complete, verify:

  • Build matrix produces binaries for all target platforms
  • Cross-compilation succeeds without linker errors
  • SHA256 checksums match actual binary hashes
  • Release manifest includes all platform/arch combinations
  • Install script detects platform correctly on Linux/macOS/Windows
  • Install script verifies checksums before installation
  • GitHub Release contains all artifacts with correct names
  • npm package installs correct binary for host platform
  • Installed binary executes successfully (--version works)
  • All artifact sizes under expected limits (no debug symbols)

Failure Indicators

This skill has FAILED if:

  • ❌ Build fails for any target platform
  • ❌ Cross-compilation produces non-functional binaries
  • ❌ SHA256 checksum verification fails
  • ❌ Release manifest missing any platform
  • ❌ Install script fails platform detection
  • ❌ Install script installs wrong binary for platform
  • ❌ GitHub Release upload incomplete or corrupted
  • ❌ npm package installs but binary not executable
  • ❌ Binary size exceeds 100MB (likely includes debug symbols)
  • ❌ Windows binary not code-signed (triggers SmartScreen)

When NOT to Use

Do NOT use this skill when:

  • Interpreted languages only - No binary compilation needed for Python/Node.js scripts
  • Container-only distribution - Docker images sufficient, no standalone binaries
  • Single-platform applications - If only targeting one OS, simpler build sufficient
  • Library/SDK projects - Distribute source code, not binaries
  • Internal tools only - GitHub releases overkill for team-only tools
  • Frequent iterations - Binary distribution too heavy for rapid prototyping
  • Web-only applications - No client-side installation required

Alternative approaches:

  • Use Docker images for container-based distribution
  • Use language package managers (pip, npm, cargo publish) for libraries
  • Use internal artifact repositories (Artifactory, Nexus) for enterprise tools

Anti-Patterns (Avoid)

Anti-PatternProblemSolution
No checksum verificationCorrupted downloads undetectedAlways generate and verify SHA256
Debug symbols in release10x larger binariesStrip symbols with --release flag
Missing platform detectionWrong binary installedDetect OS and arch in installer
Hardcoded download URLsBreaks when URLs changeUse GitHub API for latest release
No version in filenameCan't tell versions apartInclude version in artifact name
Sequential buildsSlow release processUse matrix strategy for parallel builds
Unsigned Windows binariesSmartScreen warnings, low trustCode sign with certificate
No ARM64 supportExcludes Apple Silicon, ARM serversInclude aarch64 targets
Manual release creationError-prone, slowFully automate with GitHub Actions
Missing install scriptUsers don't know how to installProvide curl | sh one-liner

Principles

This skill embodies these CODITECT principles:

  • #3 Keep It Simple - Universal installer works across all platforms
  • #6 Clear, Understandable, Explainable - Install manifest documents all artifacts
  • #7 Error Handling Excellence - Checksum verification prevents corrupt installs
  • #9 Observability First - Release manifest tracks all versions and platforms
  • #10 Performance Matters - Matrix builds parallelize cross-platform compilation
  • #11 Security by Design - SHA256 verification, code signing for Windows
  • #13 Automate Repetitive Tasks - GitHub Actions eliminates manual releases
  • #14 Cross-Platform by Default - Supports Linux/macOS/Windows from start

Full Principles: CODITECT-STANDARD-AUTOMATION.md