Problem
The AWF CLI binary is ~50MB because pkg bundles the entire Node.js 18 runtime. GitHub hosted runners (the primary deployment target) already have Node.js 22 in the tool cache, making the bundled runtime redundant.
Additionally, pkg targets Node.js 18 which has been EOL since April 2025, while the project's own engines field requires >=20.12.0 and CI only tests against Node 20/22.
Proposal
Ship an esbuild single-file bundle (awf-bundle.js, ~2MB) alongside the existing pkg binaries. The install script detects Node.js availability and prefers the lightweight bundle.
Changes
-
scripts/build-bundle.mjs — esbuild config bundling dist/cli.js into a single CJS file with platform: 'node', target: 'node20', minify: true, and #!/usr/bin/env node banner.
-
src/docker-manager.ts — Support embedded seccomp profile via esbuild define. The bundled code writes the profile from memory; the existing file-based path remains as fallback for tsc output. Guard --build-local to error clearly when running from the bundle (requires full repo checkout).
-
package.json — Add esbuild devDep, add build:bundle script.
-
.github/workflows/release.yml — Build esbuild bundle alongside pkg binaries, include awf-bundle.js in release artifacts and checksums.
-
install.sh — Add Node.js >= 20 detection. Download bundle when Node available, fall back to pkg binary otherwise. Add AWF_FORCE_BINARY=1 escape hatch.
Technical details
There are only 2 __dirname usage sites in production code (src/docker-manager.ts):
- Line 360:
projectRoot for --build-local Docker context paths — only needed with full repo checkout, not applicable to standalone bundle
- Lines 1681/1688: seccomp profile loading — solved by inlining JSON at build time via esbuild
define
Non-goals
- Do NOT bump pkg targets from node18 to node20/22 (pkg is unmaintained, uncertain support)
- Do NOT remove pkg binaries (handled separately in #NEXT)
Verification
npm run build:bundle produces release/awf-bundle.js < 5MB
node release/awf-bundle.js --version and --help work correctly
sudo node release/awf-bundle.js --allow-domains example.com -- curl https://example.com works end-to-end
install.sh with Node 22 downloads bundle; without Node downloads pkg binary
- Existing pkg binary path continues to work unchanged
Problem
The AWF CLI binary is ~50MB because
pkgbundles the entire Node.js 18 runtime. GitHub hosted runners (the primary deployment target) already have Node.js 22 in the tool cache, making the bundled runtime redundant.Additionally,
pkgtargets Node.js 18 which has been EOL since April 2025, while the project's ownenginesfield requires>=20.12.0and CI only tests against Node 20/22.Proposal
Ship an esbuild single-file bundle (
awf-bundle.js, ~2MB) alongside the existing pkg binaries. The install script detects Node.js availability and prefers the lightweight bundle.Changes
scripts/build-bundle.mjs— esbuild config bundlingdist/cli.jsinto a single CJS file withplatform: 'node',target: 'node20',minify: true, and#!/usr/bin/env nodebanner.src/docker-manager.ts— Support embedded seccomp profile via esbuilddefine. The bundled code writes the profile from memory; the existing file-based path remains as fallback fortscoutput. Guard--build-localto error clearly when running from the bundle (requires full repo checkout).package.json— AddesbuilddevDep, addbuild:bundlescript..github/workflows/release.yml— Build esbuild bundle alongside pkg binaries, includeawf-bundle.jsin release artifacts and checksums.install.sh— Add Node.js >= 20 detection. Download bundle when Node available, fall back to pkg binary otherwise. AddAWF_FORCE_BINARY=1escape hatch.Technical details
There are only 2
__dirnameusage sites in production code (src/docker-manager.ts):projectRootfor--build-localDocker context paths — only needed with full repo checkout, not applicable to standalone bundledefineNon-goals
Verification
npm run build:bundleproducesrelease/awf-bundle.js< 5MBnode release/awf-bundle.js --versionand--helpwork correctlysudo node release/awf-bundle.js --allow-domains example.com -- curl https://example.comworks end-to-endinstall.shwith Node 22 downloads bundle; without Node downloads pkg binary