rust-npm-publish

v2026.09.24

Publish Rust binaries to npm using the optionalDependencies platform package pattern. Covers the full publish pipeline, version sync, workspace:* protocol, and platform package architecture. Use when: (1) publishing Rust binaries to npm, (2) setting up the platform package pattern (main + per-OS packages), (3) debugging publish failures, (4) managing version sync across pnpm + Cargo workspaces, (5) working with workspace:* protocol. Triggers on "publish", "platform packages", "optionalDependencies", "bin.js", "version sync", "workspace protocol", "npm tag", or "prepare-publish".

GitHub
安装命令
npx skhub add onsager-ai/rust-npm-publish
Markdown
SKILL.md

Rust npm Publishing

Distribute Rust binaries to npm using the optionalDependencies platform package pattern.

When to Use This Skill

Activate when any of the following are true:

  • Publishing Rust binaries to npm or debugging publish pipeline failures
  • Setting up publish.config.ts, bin.js, or platform package manifests
  • Managing version sync across workspace packages and Cargo.toml
  • Working with workspace:* protocol or prepare/restore scripts
  • Scripts matching *publish*, *platform*, *version*, or *sync* exist

Decision Tree

What does the user need?

Setting up publishing for the first time?
  → The Pattern section + Configuration + Templates

Running the publish pipeline?
  → Publish Pipeline section
  → Full details: references/publish-pipeline.md

Adding a new platform?
  → Adding a New Platform section
  → Platform reference: references/platform-matrix.md

Version sync / bump?
  → Versioning section
  → Full strategy: references/version-strategy.md
  → workspace:* details: references/workspace-protocol.md

Debugging a failure?
  → references/troubleshooting.md

The Pattern

@scope/my-tool                    ← main package (thin JS wrapper + bin.js)
├── optionalDependencies:
│   ├── @scope/my-tool-darwin-arm64   ← macOS ARM (M-series)
│   ├── @scope/my-tool-darwin-x64     ← macOS Intel
│   ├── @scope/my-tool-linux-x64      ← Linux x86_64
│   └── @scope/my-tool-windows-x64    ← Windows x86_64

Each platform package contains only the pre-compiled binary for that target. npm installs only the one matching the user's OS/CPU at install time.

Same approach used by SWC, Turbopack, esbuild, and similar tools.

Configuration

Each repo provides a publish.config.ts (see examples/):

export default {
  scope: '@myorg',
  binaries: [{ name: 'my-cli', scope: 'cli', cargoPackage: 'my-cli-rs' }],
  platforms: ['darwin-x64', 'darwin-arm64', 'linux-x64', 'windows-x64'],
  mainPackages: [{ path: 'packages/cli', name: 'my-cli' }],
  cargoWorkspace: 'Cargo.toml',
  repositoryUrl: 'https://github.com/myorg/my-project',
};

Publish Pipeline

sync-versions → generate-manifests → add-platform-deps → copy-binaries
→ validate-binaries → prepare-publish → validate-workspace → publish-platforms
→ wait-propagation → publish-main → restore-packages

Critical ordering: Platform packages MUST be published and propagated before main packages, because main packages reference them as optionalDependencies.

See references/publish-pipeline.md for step-by-step details.

Main Package Wrapper (bin.js)

The main npm package is a thin JS wrapper — bin.js resolves the platform binary and spawns it. See templates/wrapper/ for the template.

Key details:

  • process.platform returns win32 (not windows) — map win32-x64 → @scope/cli-windows-x64
  • Use require.resolve('pkg/package.json') to find platform package, then read main for binary name
  • Use execFileSync and forward exit codes from the Rust process
  • Main package has NO os/cpu fields — it installs everywhere. Only platform packages use those.

Platform Package Manifests

Each platform package needs os/cpu fields and a postinstall.js for chmod:

{
  "name": "@scope/cli-darwin-arm64",
  "os": ["darwin"],
  "cpu": ["arm64"],
  "main": "my-cli"
}

Platform Matrix

PlatformRust TargetoscpuBinary Extension
darwin-arm64aarch64-apple-darwindarwinarm64(none)
darwin-x64x86_64-apple-darwindarwinx64(none)
linux-x64x86_64-unknown-linux-gnulinuxx64(none)
windows-x64x86_64-pc-windows-msvcwin32x64.exe

See references/platform-matrix.md for adding new platforms.

Adding a New Platform

  1. Add to platforms array in publish.config.ts
  2. Add Rust target: rustup target add <target-triple>
  3. Add to CI matrix in publish workflow
  4. Regenerate manifests: pnpm tsx scripts/generate-platform-manifests.ts

Versioning

Root package.json is the single source of truth. Never manually edit version elsewhere.

root package.json (version: "0.2.15")
  ├── packages/cli/package.json  → 0.2.15  (via sync-versions.ts)
  ├── Cargo.toml                 → 0.2.15
  └── platform-packages/*/      → 0.2.15  (via generate-manifests)

Version Sync Flow

npm version patch                     # Bump root: 0.2.15 → 0.2.16
pnpm tsx scripts/sync-versions.ts     # Propagate to all packages + Cargo.toml

Dev Builds

CI computes: 0.2.15 → 0.2.16-dev.{github_run_id} Published with --tag dev. Install: npm install my-cli@dev

Cargo.toml stays at base version (0.2.15) for dev builds — Cargo pre-release handling differs from npm.

Version Bump Guide

ChangeCommandExample
Breaking APInpm version major1.0.0 → 2.0.0
New featurenpm version minor0.2.0 → 0.3.0
Bug fixnpm version patch0.2.15 → 0.2.16
CI/testingAutomatic (CI)0.2.15 → 0.2.16-dev.123

workspace:* Protocol

pnpm uses workspace:* for internal deps during development. Replace before publish, restore after:

pnpm tsx scripts/prepare-publish.ts                  # Replace workspace:* → real versions
pnpm tsx scripts/validate-no-workspace-protocol.ts   # Safety gate
npm publish
pnpm tsx scripts/restore-packages.ts                 # Restore workspace:*

See references/workspace-protocol.md for details. See references/version-strategy.md for the full strategy.

Troubleshooting Quick Reference

ProblemLikely CauseFix
Unsupported platformMissing platform in bin.jsAdd platform key mapping
Platform pkg not found on npmRegistry propagation delayWait; check publish logs
workspace:* in published pkgprepare-publish didn't runRun prepare-publish.ts
Binary not executablepostinstall didn't runchmod +x the binary
Version mismatchForgot to syncRun sync-versions.ts

See references/troubleshooting.md for detailed diagnostics.

Templates

DirectoryContents
templates/scripts/All 11 publish pipeline scripts
templates/wrapper/bin.js + main package package.json
examples/Real publish.config.ts from consuming projects

Setup & Activation

npx skills add -g onsager-ai/dev-skills --skill rust-npm-publish -a claude-code -y

Auto-activates when: publish.config.ts present, scripts matching *publish* or *platform* exist, user mentions "publish", "platform packages", or "version sync".

发现
标签

此技能尚未发布标签。

版本
最新版本元数据

版本

v2026.09.24

发布时间

2026年9月24日

分类

未分类

许可证

MIT

源路径

skills/rust-npm-publish

默认分支

main

最新提交

14c732f

Tree SHA

2024cd7