Skip to content

feat: add esbuild single-file bundle as lightweight distribution#1581

Merged
Mossaka merged 2 commits intomainfrom
feat/esbuild-bundle
Apr 1, 2026
Merged

feat: add esbuild single-file bundle as lightweight distribution#1581
Mossaka merged 2 commits intomainfrom
feat/esbuild-bundle

Conversation

@Mossaka
Copy link
Copy Markdown
Collaborator

@Mossaka Mossaka commented Apr 1, 2026

Summary

  • Adds a ~350KB esbuild single-file bundle (release/awf-bundle.js) as a lightweight alternative to the ~50MB pkg binaries which bundle the entire Node.js 18 runtime (EOL since April 2025)
  • The install script (install.sh) now auto-detects Node.js >= 20 and downloads the bundle instead of the pkg binary (opt out with AWF_FORCE_BINARY=1)
  • The seccomp profile is inlined at build time via esbuild define, so the bundle works without the containers/ directory tree

Changes

File What
scripts/build-bundle.mjs New esbuild config: bundles dist/cli.js into single CJS file with inlined seccomp profile
src/docker-manager.ts Support embedded __AWF_SECCOMP_PROFILE__ constant; guard --build-local when running from bundle
package.json Add esbuild devDep and build:bundle script
.github/workflows/release.yml Build, smoke-test, and publish the bundle alongside existing pkg binaries
install.sh Auto-detect Node.js >= 20 and prefer lightweight bundle over pkg binary
.gitignore Ignore release/ directory

Test plan

  • npm run build succeeds
  • npm test passes (1264 tests)
  • npm run lint passes (warnings only, no errors)
  • node scripts/build-bundle.mjs produces a working bundle
  • node release/awf-bundle.js --version prints correct version
  • node release/awf-bundle.js --help shows CLI help
  • Verify install.sh bundle path works in CI (will be validated by release workflow)

Closes #1577

🤖 Generated with Claude Code

Add a ~350KB esbuild bundle (release/awf-bundle.js) as an alternative to
the ~50MB pkg binary. GitHub hosted runners already have Node.js 22,
making the bundled Node.js 18 runtime in pkg redundant.

Changes:
- Add scripts/build-bundle.mjs: esbuild config that bundles dist/cli.js
  into a single CJS file with the seccomp profile inlined via `define`
- Modify src/docker-manager.ts: support embedded seccomp profile
  (__AWF_SECCOMP_PROFILE__) and guard --build-local for bundle users
- Add esbuild to devDependencies and build:bundle script
- Update release.yml to build, smoke-test, and publish the bundle
- Update install.sh to prefer the bundle when Node.js >= 20 is available
  (opt out with AWF_FORCE_BINARY=1)
- Add release/ to .gitignore

Closes #1577

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 1, 2026 21:39
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

✅ Coverage Check Passed

Overall Coverage

Metric Base PR Delta
Lines 85.80% 85.83% 📈 +0.03%
Statements 85.68% 85.71% 📈 +0.03%
Functions 86.66% 86.66% ➡️ +0.00%
Branches 78.47% 78.48% 📈 +0.01%
📁 Per-file Coverage Changes (1 files)
File Lines (Before → After) Statements (Before → After)
src/docker-manager.ts 85.8% → 86.0% (+0.13%) 85.3% → 85.5% (+0.13%)

Coverage comparison generated by scripts/ci/compare-coverage.ts

Copy link
Copy Markdown
Collaborator Author

@Mossaka Mossaka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review: esbuild single-file bundle distribution

I reviewed this PR against the security posture documented in CLAUDE.md and AGENTS.md. Overall the approach is sound, but there are several findings worth addressing.


a. Seccomp Profile Integrity — LOW RISK, one concern

Mechanism: The build script reads containers/agent/seccomp-profile.json at build time and passes it to esbuild via define: { __AWF_SECCOMP_PROFILE__: JSON.stringify(seccompContent) }. At runtime, docker-manager.ts checks typeof __AWF_SECCOMP_PROFILE__ !== 'undefined' and writes it to ${workDir}/seccomp-profile.json.

The good: JSON.stringify(seccompContent) produces a valid JS string literal containing the full JSON. esbuild's define does a textual substitution, so the content will be faithfully embedded. The double-stringify (JSON inside a JS string) is correct — esbuild define expects a JS expression, and JSON.stringify(string) produces a quoted JS string literal. At runtime, __AWF_SECCOMP_PROFILE__ will be a string containing the raw JSON, which is then written to disk. This is functionally equivalent to fs.copyFileSync.

Concern — profile drift: There is no build-time or CI validation that the embedded profile matches the source file. If someone edits seccomp-profile.json but forgets to rebuild the bundle, or if the build pipeline caches a stale dist/ directory, the released bundle could ship an outdated seccomp profile. Recommendation: Add a CI step or test that compares the embedded profile against the source file, e.g., node -e "const b = require('./release/awf-bundle.js'); ..." or a checksum comparison in the release workflow after the bundle is built.

Concern — no JSON parse validation at build time: The build script reads the file as a raw string and inlines it. If the JSON file is malformed (e.g., trailing comma added during editing), this would only be caught at runtime when Docker tries to apply the seccomp profile, not at build time. Recommendation: Add JSON.parse(seccompContent) in build-bundle.mjs to fail fast on malformed JSON.


b. Install Script Security — ACCEPTABLE

SHA256 checksums are preserved: The bundle path still downloads checksums.txt and calls verify_checksum, which performs SHA256 verification. This is the same integrity guarantee as the binary path.

Format validation is weaker but adequate: The binary path validates ELF/Mach-O format via file command. The bundle path validates #!/usr/bin/env node shebang in the first 20 bytes. This is a weaker check (a shebang is trivial to forge), but the SHA256 checksum is the real integrity gate — the format check is defense-in-depth only. The checksums.txt is downloaded over HTTPS from GitHub Releases, which is sufficient.

AWF_FORCE_BINARY=1 escape hatch: Good — allows users to opt out of the bundle path if needed.


c. Supply Chain — LOW RISK

esbuild (v0.25.12) is a well-maintained, widely-used bundler by Evan Wallace (co-founder of Figma). It has 38k+ GitHub stars, is a devDependency only (not shipped to users), and is used in production by Vite, SvelteKit, and many other major projects. The package uses platform-specific optional native binaries which are all published under the @esbuild/ scope by the same author. The package-lock.json includes integrity hashes for all platform binaries.

No known vulnerabilities in esbuild 0.25.x as of my knowledge cutoff.


d. Bundle Content — LOW RISK

esbuild bundles from dist/cli.js (the tsc output), not from source. It bundles all require() dependencies (commander, chalk, execa, js-yaml, etc.) into one file with minify: true. This is standard for Node.js single-file distributions.

Minification does not affect security logic: The security-critical paths (iptables rules, DNS config, domain filtering) are all string constants and function calls that survive minification unchanged. The seccomp profile is a separate JSON string, not affected by minification. Squid config generation (squid-config.ts) produces string output that is passed to Docker as an env var — also unaffected.

No risk of bundling sensitive files: esbuild only follows require() chains from the entry point. It cannot accidentally include files that are not require()d. The containers/ directory contains shell scripts and Dockerfiles which are never require()d — they are referenced only by path in Docker Compose config.


e. --build-local Guard — ADEQUATE

The guard in generateDockerCompose() checks fs.existsSync(path.join(projectRoot, 'containers')). When running from the bundle, __dirname resolves to a temp/release directory where containers/ does not exist, so the check correctly throws. The error message is clear and actionable.

Note: projectRoot is path.join(__dirname, '..'). In the bundle, __dirname is the directory containing the bundle file. Since the bundle is a single .js file (not inside a dist/ subdirectory), projectRoot will be the parent of wherever the bundle lives. This is correct — there is no containers/ directory adjacent to the bundle.


f. Runtime Equivalence — ACCEPTABLE with caveat

All security-critical paths are preserved:

  • Seccomp profile: embedded verbatim, written to disk, applied via security_opt
  • iptables rules: defined in setup-iptables.sh (container script, not bundled)
  • DNS config: generated in docker-manager.ts, survives bundling
  • Domain filtering: squid-config.ts and domain-patterns.ts, all pure JS
  • Capability dropping: entrypoint.sh (container script, not bundled)
  • No-new-privileges: string constant in docker-manager.ts

Caveat — __dirname semantics change: In the tsc build, __dirname is <repo>/dist/. In the bundle, __dirname is the directory containing the bundle file. The code uses path.join(__dirname, '..') as projectRoot in multiple places. In tsc mode this resolves to the repo root; in bundle mode it resolves to the parent of the bundle's directory. This is fine for the seccomp profile (handled by __AWF_SECCOMP_PROFILE__) and for --build-local (guarded). But other projectRoot-relative paths may break silently if not guarded. Recommendation: Audit all uses of projectRoot / path.join(__dirname, '..') in docker-manager.ts to ensure they are either (a) guarded by --build-local check, (b) handled by embedded data, or (c) irrelevant to the bundle path.


Summary

Concern Severity Status
Seccomp profile integrity Low Embedded correctly; recommend build-time JSON validation
Profile drift risk Medium No CI check that bundle matches source; recommend adding one
Install script integrity Low SHA256 checksums preserved; shebang check is adequate
Supply chain (esbuild) Low Well-maintained, devDep only
Bundle content safety Low Only require() chain bundled
--build-local guard Low Correctly prevents misuse
__dirname semantics Medium Seccomp and build-local handled; audit other projectRoot uses

No blocking security issues found. The two medium items (profile drift detection and __dirname audit) are worth addressing but are not exploitable vulnerabilities — they are robustness concerns for a security-critical tool.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a lightweight esbuild-based single-file JavaScript bundle distribution for the AWF CLI and updates release/install flows to prefer it when a suitable system Node.js is available.

Changes:

  • Introduces scripts/build-bundle.mjs to produce release/awf-bundle.js with an inlined seccomp profile.
  • Updates src/docker-manager.ts to support an embedded seccomp profile and to block --build-local when running outside a full repo checkout (e.g., bundle install).
  • Updates release workflow and install.sh to build/publish and preferentially install the bundle on Node.js >= 20.

Reviewed changes

Copilot reviewed 5 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/docker-manager.ts Adds embedded seccomp profile support and guards --build-local for bundled installs.
scripts/build-bundle.mjs New esbuild bundling script that inlines the seccomp profile and emits release/awf-bundle.js.
package.json Adds esbuild devDependency and build:bundle script.
package-lock.json Locks esbuild and its platform-specific optional dependencies.
install.sh Detects Node.js to prefer installing the bundle (with an escape hatch).
.github/workflows/release.yml Builds and smoke-tests the bundle, and publishes it with other release artifacts.
.gitignore Ignores release/ build artifacts.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

install.sh Outdated
Comment on lines +146 to +162
# Check for Node.js >= 20 to decide between bundle and pkg binary
check_node() {
if [ "${AWF_FORCE_BINARY:-}" = "1" ]; then
info "AWF_FORCE_BINARY=1 set, using standalone binary"
USE_BUNDLE=false
return
fi
if command -v node &> /dev/null; then
NODE_VERSION=$(node -v | sed 's/^v//')
NODE_MAJOR=$(echo "$NODE_VERSION" | cut -d. -f1)
if [ "$NODE_MAJOR" -ge 20 ]; then
info "Node.js v${NODE_VERSION} detected (>= 20), using lightweight bundle"
USE_BUNDLE=true
return
fi
warn "Node.js v${NODE_VERSION} detected but < 20, using standalone binary"
fi
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check_node treats any Node.js 20.x as eligible for the bundle, but package.json declares engines.node >=20.12.0. This can select the bundle on Node 20.0–20.11 where runtime behavior may be unsupported. Consider parsing the full semver (major/minor/patch) and requiring >=20.12.0 to match the engine constraint (or update the stated requirement if >=20.0.0 is truly sufficient).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in d1d4c65. The version check now requires >=20.12.0 (matching engines.node in package.json) by parsing both major and minor version components.


- name: Create esbuild bundle
run: |
npm install esbuild
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This step runs npm install esbuild even though npm ci already installed devDependencies (including esbuild from package.json). This adds extra time and can introduce version drift from the lockfile. Prefer removing the install and just running the build script (e.g., npm run build:bundle or node scripts/build-bundle.mjs).

Suggested change
npm install esbuild

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in d1d4c65. Removed the redundant npm install esbuild since it's already a devDependency installed by npm ci.

Comment on lines +47 to +52
// Prepend shebang so the file is directly executable
const outPath = join(projectRoot, 'release', 'awf-bundle.js');
const bundleContent = readFileSync(outPath, 'utf-8');
if (!bundleContent.startsWith('#!')) {
writeFileSync(outPath, '#!/usr/bin/env node\n' + bundleContent);
}
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The script prepends a shebang and states the output is "directly executable", but it never sets the executable bit on release/awf-bundle.js. Consider chmoding the output (e.g., 0o755) so ./release/awf-bundle.js works immediately after building, matching the comment and typical CLI bundle expectations.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in d1d4c65. Added chmodSync(outPath, 0o755) after writing the bundle so ./release/awf-bundle.js is directly executable.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Smoke Test Results

GitHub MCP — Last 2 merged PRs: #1557 feat: add daily token usage analyzer workflow, #1555 fix: copy AWF CA cert to chroot-accessible path for ssl-bump
Playwright — github.com title contains "GitHub"
File Writesmoke-test-claude-23872168536.txt created
Bash — File verified via cat

Overall: PASS

💥 [THE END] — Illustrated by Smoke Claude for issue #1581

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Smoke Test Results@Mossaka

Test Result
GitHub MCP (last 2 merged PRs) #1557 "feat: add daily token usage analyzer workflow", #1555 "fix: copy AWF CA cert to chroot-accessible path for ssl-bump"
Playwright (github.com title contains "GitHub")
File write + bash verify

Overall: PASS

📰 BREAKING: Report filed by Smoke Copilot for issue #1581

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Chroot Version Comparison Results

Runtime Host Version Chroot Version Match?
Python Python 3.12.13 Python 3.12.3 ❌ NO
Node.js v24.14.0 v20.20.1 ❌ NO
Go go1.22.12 go1.22.12 ✅ YES

Result: FAILED — Python and Node.js versions differ between host and chroot environments.

Tested by Smoke Chroot for issue #1581

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

This was referenced Apr 1, 2026
- Tighten Node.js version check in install.sh to >=20.12.0 (matches
  engines.node in package.json) instead of just >=20
- Remove redundant `npm install esbuild` in release workflow since
  esbuild is already installed via `npm ci` from devDependencies
- Add build-time JSON.parse validation for seccomp profile to fail
  fast on malformed JSON
- Set executable bit (chmod 755) on bundle output file

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Mossaka
Copy link
Copy Markdown
Collaborator Author

Mossaka commented Apr 1, 2026

Thanks for the thorough security review! Addressed the following in d1d4c65:

Seccomp profile JSON validation (build-time): Added JSON.parse(seccompContent) in build-bundle.mjs so malformed JSON fails the build immediately rather than at runtime.

Also addressed Copilot review feedback in the same commit:

  • Tightened Node.js version check to >=20.12.0 (matching engines.node)
  • Removed redundant npm install esbuild in release workflow
  • Added chmod 755 on bundle output

Regarding profile drift and __dirname audit: These are good recommendations for follow-up. The profile drift concern could be addressed by a CI step comparing the embedded content against the source file. The __dirname paths are currently safe since all projectRoot-relative accesses in the non---build-local path are either guarded or handled by the embedded constant, but an explicit audit would be worthwhile.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Smoke Test Results

  • ✅ GitHub MCP: Last merged PR — "feat: add daily token usage analyzer workflow" (feat: add daily token usage analyzer workflow #1557)
  • ✅ Playwright: github.com title contains "GitHub"
  • ✅ File write: /tmp/gh-aw/agent/smoke-test-claude-23873101575.txt created
  • ✅ Bash verify: File contents confirmed

Overall: PASS

💥 [THE END] — Illustrated by Smoke Claude for issue #1581

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Smoke Test Results

Test Status
GitHub MCP (last 2 merged PRs) #1557 "feat: add daily token usage analyzer workflow", #1555 "fix: copy AWF CA cert to chroot-accessible path for ssl-bump"
Playwright (github.com title check)
File write /tmp/gh-aw/agent/smoke-test-copilot-23873101538.txt
Bash verification (cat)

Overall: PASS

PR by @Mossaka, no assignees.

📰 BREAKING: Report filed by Smoke Copilot for issue #1581

@github-actions

This comment has been minimized.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Chroot Version Comparison Results

Runtime Host Version Chroot Version Match?
Python Python 3.12.13 Python 3.12.3 ❌ NO
Node.js v24.14.0 v20.20.1 ❌ NO
Go go1.22.12 go1.22.12 ✅ YES

Overall: ❌ Not all tests passed — Python and Node.js versions differ between host and chroot environments.

Tested by Smoke Chroot for issue #1581

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Smoke Test: GitHub Actions Services Connectivity ✅

Check Result
Redis PING (host.docker.internal:6379) PONG
PostgreSQL pg_isready (host.docker.internal:5432) accepting connections
PostgreSQL SELECT 1 (db: smoketest, user: postgres) ✅ returned 1

All checks passed. (redis-cli was unavailable so Redis was tested via raw RESP protocol with nc.)

🔌 Service connectivity validated by Smoke Services

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 7 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +6 to +7
* This produces release/awf-bundle.js (~2 MB) which requires only a
* system Node.js >= 20 to run — no node_modules needed.
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The header comment says the bundle requires Node.js ">= 20" and is "~2 MB", but the repo’s engines.node is ">=20.12.0" and the PR description cites a much smaller artifact. To avoid misleading users, update this comment to match the actual runtime requirement (>=20.12.0) and either use the current measured size or remove the hard-coded size estimate.

Suggested change
* This produces release/awf-bundle.js (~2 MB) which requires only a
* system Node.js >= 20 to run no node_modules needed.
* This produces release/awf-bundle.js which requires only a
* system Node.js >= 20.12.0 to run no node_modules needed.

Copilot uses AI. Check for mistakes.
Comment on lines +154 to +163
if command -v node &> /dev/null; then
NODE_VERSION=$(node -v | sed 's/^v//')
NODE_MAJOR=$(echo "$NODE_VERSION" | cut -d. -f1)
NODE_MINOR=$(echo "$NODE_VERSION" | cut -d. -f2)
if [ "$NODE_MAJOR" -gt 20 ] || { [ "$NODE_MAJOR" -eq 20 ] && [ "$NODE_MINOR" -ge 12 ]; }; then
info "Node.js v${NODE_VERSION} detected (>= 20.12.0), using lightweight bundle"
USE_BUNDLE=true
return
fi
warn "Node.js v${NODE_VERSION} detected but < 20.12.0, using standalone binary"
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check_node runs under sudo/root (the script exits if not root). On environments where sudo resets PATH (common in CI and when Node is installed via nvm/asdf or GitHub Actions toolcache), command -v node may fail even though Node is available to the invoking user, causing the installer to incorrectly pick the pkg binary. Consider detecting Node using the original user context (e.g., if $SUDO_USER is set, probe via sudo -u "$SUDO_USER" -H command -v node / node -v), or restructure so Node detection happens before privilege escalation.

Copilot uses AI. Check for mistakes.
ls -lh release/awf-bundle.js
echo "=== Bundle smoke test ==="
node release/awf-bundle.js --version
node release/awf-bundle.js --help | head -5
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Piping --help output into head -5 can intermittently fail the step due to EPIPE (the consumer exits early while Node is still writing). To keep the smoke test reliable, redirect help output to a file (or /dev/null) and then head the file, or otherwise avoid truncating via a pipe that closes early.

Suggested change
node release/awf-bundle.js --help | head -5
node release/awf-bundle.js --help > awf-help.txt
head -5 awf-help.txt

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator

@lpcox lpcox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review — LGTM ✅

Reviewed all 7 changed files with focus on security implications for this firewall project.

What I verified:

Seccomp profile inlining — JSON validated at build time, JSON.stringify() properly escapes content, embedded as compile-time constant (not runtime injection). Fallback chain (embedded → repo path → alt path) is correct.

install.sh — Node.js version comparison logic handles edge cases correctly (20.11.9, 21.0.0, 19.9.0). Checksum verification works for both bundle and binary paths. Shebang validation prevents wrong file downloads. AWF_FORCE_BINARY=1 escape hatch is a good addition.

esbuild config — Platform/target/format are appropriate (node, node20, cjs). __dirname preserved correctly. Shebang written after build to avoid duplication bug.

docker-manager.ts--build-local guard correctly checks for containers/ directory existence (won't exist in bundle deployment). typeof __AWF_SECCOMP_PROFILE__ !== 'undefined' is the safe way to check for the embedded constant.

Release workflow — Bundle built before checksums, included in sha256sum *, smoke-tested (--version, --help) before publish.

Clean implementation — no security concerns, no bugs found.

@Mossaka Mossaka merged commit 59da663 into main Apr 1, 2026
68 of 69 checks passed
@Mossaka Mossaka deleted the feat/esbuild-bundle branch April 1, 2026 23:55
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 2, 2026

Smoke test report (run 23878316602)
PR titles: feat: add esbuild single-file bundle as lightweight distribution; fix: recompile token-usage-analyzer lock file
GitHub MCP last 2 merged PRs: ✅
safeinputs-gh PR query: ❌
Playwright title contains GitHub: ❌
Tavily search: ❌
File write + bash cat: ✅
Build (npm ci && npm run build): ✅
Overall status: FAIL

🔮 The oracle has spoken through Smoke Codex

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: add esbuild single-file bundle as lightweight distribution

3 participants