feat(windows)!: add ARM64 support via x64 emulation with dual-binary distribution#415
feat(windows)!: add ARM64 support via x64 emulation with dual-binary distribution#415
Conversation
…inary support Add build-time feature flag to support dual-binary Windows x64 builds: - build-binary.ts: detect "baseline" in target name and inject __ATOMIC_BASELINE__=true via Bun's define option - download.ts: add declare const + typeof guard so getBinaryFilename() appends "-baseline" suffix when the flag is set at bundle time - Add tests for both baseline detection logic and download filename generation Also fix pre-existing macOS test failures: - agent-commands and skill-commands: resolve symlinked /var vs /private/var temp paths via realpathSync - install-sh-windows-delegation: fix TS2532 null-safety errors Assistant-model: Claude Code
Replace the single Windows baseline-only build with two builds: - Standard x64 (with AVX) for native x64 users - x64-baseline (AVX-free) for ARM64 Prism emulation compatibility Also adds atomic-windows-x64-baseline.exe to the release assets list and removes the separate build-windows job in favor of cross-compilation. Assistant-model: Claude Code
…port The previous commits (285dd70, 03faad7) added tests and CI workflow changes for Windows ARM64 support, but the actual install script changes were left unstaged: - install.ps1: remap ARM64 architecture to windows-x64-baseline.exe (the primary fix for #388 — ARM64 users no longer hit a 404) - install.sh: move Windows delegation from detect_platform() into main() so version/prerelease arguments are properly forwarded to install.ps1 Without these committed, CI tests fail (3 of 11 in install-sh-windows-delegation.test.ts) and ARM64 installs remain broken.
Add research and specification documents for the Windows ARM64 support feature (issues #388, #389): - Initial research on build, install, and runtime gaps - Follow-up research on the dual-binary x64/x64-baseline approach - Execution spec covering CI, installer, and build-flag changes Assistant-model: Claude Code
|
PR Review: Windows ARM64 Support SUMMARY This PR implements Windows ARM64 support using a dual-binary approach that ships both a standard x64 build (with AVX) for native x64 users and an x64-baseline build (without AVX) for ARM64 users running via Prism emulation. This is a well-researched and thoughtfully implemented solution to issues 388 and 389. CODE QUALITY AND BEST PRACTICES Strengths:
Minor suggestions:
POTENTIAL BUGS OR ISSUES
SECURITY CONCERNS - Well Handled
PERFORMANCE CONSIDERATIONS
TEST COVERAGE - Good
OVERALL ASSESSMENT This is a high-quality PR with thorough research and documentation, clean implementation following established patterns, good security practices, comprehensive test coverage, and clear rationale for design decisions. Recommendation: APPROVE after addressing the minor suggestions above (optional). Checklist for author:
|
There was a problem hiding this comment.
Pull request overview
This PR implements Windows ARM64 install/run support by shipping an additional Windows x64 baseline binary (AVX-free for Prism emulation) and ensuring both installers and self-update logic resolve to the correct artifact.
Changes:
- Build and release two Windows artifacts (
atomic-windows-x64.exeandatomic-windows-x64-baseline.exe) and remap ARM64 installs to the baseline artifact. - Inject a build-time discriminator (
__ATOMIC_BASELINE__) for baseline builds and use it ingetBinaryFilename()so baseline binaries self-update to baseline. - Add/adjust tests and docs covering download utilities, build flag derivation, Windows delegation behavior, and macOS temp path normalization.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
.github/workflows/publish.yml |
Cross-compiles and releases both Windows x64 + x64-baseline binaries; removes Windows runner job. |
install.ps1 |
Remaps Windows ARM64 installs to windows-x64-baseline.exe with an info message. |
install.sh |
Moves Windows delegation to main() (pre-subshell), adds semver validation and forwards version/prerelease args. |
src/scripts/build-binary.ts |
Derives isBaseline from --target and injects __ATOMIC_BASELINE__ via define. |
src/services/system/download.ts |
Adds baseline suffix selection in getBinaryFilename() based on __ATOMIC_BASELINE__. |
tests/services/system/download.test.ts |
Adds unit tests for download helpers (filename, checksums parsing, URL builders, config archive name). |
tests/scripts/install-sh-windows-delegation.test.ts |
Adds tests validating the Windows delegation block, argument construction, and semver validation behavior. |
tests/scripts/build-binary-baseline.test.ts |
Tests baseline target detection and define-block construction logic in isolation. |
tests/commands/tui/skill-commands.test.ts |
Normalizes temp root paths via realpathSync() to avoid symlink path mismatches (macOS). |
tests/commands/tui/agent-commands.test.ts |
Same temp path normalization via realpathSync() for agent tests. |
specs/windows-arm64-support.md |
Adds a comprehensive design document for Windows ARM64 support and dual-binary strategy. |
research/docs/2026-03-23-dual-binary-windows-approach.md |
Adds research writeup describing dual-binary mechanics and self-update strategy. |
research/docs/2026-03-20-388-389-windows-arm64-support.md |
Adds detailed research on constraints (TinyCC/FFI, Prism AVX) and viable approach. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
install.sh
Outdated
| if [[ "${ATOMIC_INSTALL_PRERELEASE:-}" == "true" ]]; then | ||
| ps_args="${ps_args} -Prerelease" | ||
| fi | ||
| powershell -c "iex \"& { \$(irm https://raw.githubusercontent.com/${GITHUB_REPO}/main/install.ps1) }${ps_args}\"" |
There was a problem hiding this comment.
The Windows delegation runs powershell -c ..., which typically invokes Windows PowerShell 5.1. Since install.ps1 requires PowerShell 7+, this delegation path will fail for many users even when pwsh is installed. Consider preferring pwsh when available (fallback to powershell if not) so install.sh delegation works with the installer’s PowerShell 7 requirement.
| powershell -c "iex \"& { \$(irm https://raw.githubusercontent.com/${GITHUB_REPO}/main/install.ps1) }${ps_args}\"" | |
| local ps_cmd="powershell" | |
| if command -v pwsh >/dev/null 2>&1; then | |
| ps_cmd="pwsh" | |
| fi | |
| "$ps_cmd" -c "iex \"& { \$(irm https://raw.githubusercontent.com/${GITHUB_REPO}/main/install.ps1) }${ps_args}\"" |
| for (const version of maliciousVersions) { | ||
| const script = ` | ||
| set -euo pipefail | ||
| ATOMIC_INSTALL_VERSION="${version.replace(/"/g, '\\"')}" | ||
| if [[ -n "\${ATOMIC_INSTALL_VERSION:-}" ]]; then | ||
| if [[ ! "\${ATOMIC_INSTALL_VERSION}" =~ ^v?[0-9]+\\.[0-9]+\\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then | ||
| echo "REJECTED" | ||
| exit 0 | ||
| fi | ||
| echo "ACCEPTED" | ||
| fi | ||
| `; | ||
| const result = Bun.spawnSync(["bash", "-c", script]); | ||
| const output = result.stdout.toString().trim(); | ||
| expect(output).toBe("REJECTED"); |
There was a problem hiding this comment.
The malicious-input test embeds ATOMIC_INSTALL_VERSION="${version}" directly into a bash script. For entries like $(whoami), this will execute command substitution during the test, which is undesirable and could become dangerous if the list changes. Prefer passing the version via Bun.spawnSync env vars (or single-quoting/escaping in a way that prevents evaluation) so the test treats the payload as a literal string.
| const baselineSuffix = | ||
| typeof __ATOMIC_BASELINE__ !== "undefined" && __ATOMIC_BASELINE__ | ||
| ? "-baseline" | ||
| : ""; | ||
| return `atomic-${os}-${archStr}${baselineSuffix}${ext}`; |
There was a problem hiding this comment.
The new -baseline behavior is only exercised in the “flag undefined” branch; there’s no test that validates the baseline artifact name when __ATOMIC_BASELINE__ is injected. To prevent regressions, consider adding a test that runs a tiny Bun.build({ define: { __ATOMIC_BASELINE__: "true" } }) snippet and asserts getBinaryFilename() includes -baseline.
| const parserWorker = realpathSync(resolve(projectRoot, "node_modules/@opentui/core/parser.worker.js")); | ||
| const workerRelativePath = relative(projectRoot, parserWorker).replaceAll("\\", "/"); | ||
| const compileTargetOs = inferTargetOs(options.target); | ||
| const isBaseline = options.target?.includes("baseline") ?? false; |
There was a problem hiding this comment.
isBaseline is derived using a case-sensitive includes("baseline"), while inferTargetOs() lowercases the target first. This can silently mis-detect baseline builds if --target ever arrives with different casing. Consider normalizing (options.target?.toLowerCase().includes("baseline")) to match the OS inference logic.
| const isBaseline = options.target?.includes("baseline") ?? false; | |
| const isBaseline = options.target?.toLowerCase().includes("baseline") ?? false; |
…ommand tests These macOS symlink fixes are a pre-existing issue on main and unrelated to the Windows ARM64 feature. Reverting to keep the PR scope focused.
PR Review: feat(windows): add ARM64 support via x64 emulationOverall AssessmentThis is a well-designed PR that solves a real user problem (Windows ARM64 users getting 404 errors) with an elegant dual-binary approach. The code is clean, the documentation is thorough, and the test coverage is comprehensive. Recommendation: ✅ Approve with minor suggestions Code Quality and Best PracticesStrengths:
Minor suggestions:
Potential Bugs or Issues
Performance ConsiderationsPositive:
No concerns - the dual-binary approach has negligible CI impact. Security ConcernsHandled well:
One observation:
Test CoverageExcellent coverage:
Minor suggestion:
CI/CD ChangesThe workflow changes in
DocumentationThe research docs and spec (
This is excellent for future maintainability. Summary
Overall: Well-executed feature PR that follows project conventions and solves a real user pain point. |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
PR Review: feat(windows): add ARM64 support via x64 emulationThis is a well-designed PR that adds Windows ARM64 support by shipping two Windows binaries: a standard x64 build (with AVX) for native x64 users, and an x64-baseline build (AVX-free) for ARM64 users via Prism emulation. Code Quality: Clean Strategy pattern with build-time discriminator. Auto-derivation from --target flag. Proper TypeScript typing with typeof guard. Security: Semver validation in install.sh prevents command injection. Good test coverage for malicious inputs. Performance: Native x64 users retain AVX. ARM64 users get AVX-free baseline. Good trade-off. Consolidating Windows builds to Ubuntu cross-compilation is faster. Minor Issues: (1) install.sh line 108 phrasing may confuse users (2) baselineSuffix applies globally (3) Windows 10 ARM64 warned but not blocked Test Coverage: Good - tests for baseline flag derivation, Windows delegation, and download utilities. Documentation: Excellent spec with problem statement, detailed design, alternatives, and rollback plan. Verdict: Approve with minor comments. Well-architected, documented, and tested. The dual-binary approach is the right solution. |
install.ps1 requires PowerShell 7+, but `powershell` invokes Windows PowerShell 5.1. Use `pwsh` directly and fail fast with a clear error and install link if it is not available. Assistant-model: Claude Code
PR Review: Windows ARM64 Support via x64 EmulationThanks for this well-documented PR! The dual-binary approach with build-time discrimination is a solid solution for supporting Windows ARM64 users without penalizing native x64 users. Strengths:
Suggestions:
Minor nits:
Verdict: Approve with minor suggestions Well-thought-out solution addressing Windows ARM64 404 errors while preserving AVX for x64 majority. Excellent documentation and clean implementation! |
…ows-arm64 # Conflicts: # .github/workflows/publish.yml
|
PR Review: feat(windows): add ARM64 support via x64 emulation Summary: This PR implements Windows ARM64 support using a dual-binary approach (standard x64 with AVX + x64-baseline without AVX). The solution is well-researched and addresses the TinyCC/bun:ffi limitation that blocks native ARM64 binaries. CODE QUALITY - Strengths:
POTENTIAL ISSUES:
PERFORMANCE: Native x64 keeps AVX optimizations. CI adds approx 30s and 80MB. SECURITY: Semver validation prevents injection. Tests cover malicious inputs. TEST COVERAGE: Three new test files cover baseline flag derivation, PS arg construction, and download filename resolution. Gap: Missing test with ATOMIC_BASELINE actually defined. RECOMMENDATION: Approve with minor suggestions - clarify pwsh choice, remove extra blank line, consider baseline integration test. Overall well-researched solution with clean dual-binary architecture. |
Research Bun baseline builds, Prism compatibility (confirmed #21869 fixed), dual-binary CI strategy, and native Windows runner rationale. Update existing ARM64 research doc with resolved open questions. Add technical spec for restoring the two-job CI pattern from main: build on ubuntu-latest (Linux/macOS) and build-windows on windows-latest (standard + baseline binaries). Assistant-model: Claude Code
Restore the two-job CI pattern from main: Linux/macOS binaries cross-compiled on ubuntu-latest, Windows binaries built natively on windows-latest. Fixes orphaned binaries-windows artifact that was built but never consumed by the release job. Changes to publish.yml: - Remove Windows build lines from the build job (ubuntu-latest) - Extend build-windows job to produce both standard (x64, with AVX) and baseline (x64-baseline, AVX-free for ARM64 Prism) binaries - Add prepare:opentui-bindings, tests, and typecheck to build-windows - Add binaries-windows artifact download step to release job Update research doc with resolved open questions: Prism compatibility confirmed (#21869 fixed), Bun version strategy (latest), cross- compilation viability (decided: native), and baseline performance tradeoff (dual-binary). Assistant-model: Claude Code
PR Review: Windows ARM64 Support via x64 EmulationSummaryThis is an excellent, well-researched PR that enables Windows ARM64 users to install and run Atomic CLI by shipping a dual-binary approach: a standard x64 build (with AVX) for native x64 users, and an x64-baseline build (AVX-free) for ARM64 users running via Windows 11's Prism emulation. Code Quality and Best PracticesStrengths:
Code changes reviewed:
Minor suggestion (non-blocking): There's an extra blank line added at Potential Bugs or IssuesNo blocking issues found. The logic appears sound:
One consideration (already acknowledged in docs): Bun issue #21869 remains open. The PR documentation correctly notes this and explains the AVX leak interpretation vs fallback bug interpretation. The static AVX verifier (PR #27801) should address the former, and the UPDATE 3 in the research doc confirms testing passed. Performance ConsiderationsWell addressed:
The research correctly notes that for a CLI/TUI application, the performance difference is negligible since bottlenecks are I/O and terminal rendering, not SIMD operations. Security ConcernsExcellent security handling in if [[ ! "${ATOMIC_INSTALL_VERSION}" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then
error "Invalid version format..."
fi
One security note: The Test CoverageGood coverage added:
Tests are well-structured:
Suggestion (non-blocking): Consider adding an integration test that verifies the CI produces both Windows binaries when run (can be done in a follow-up). Architecture Decision ReviewThe dual-binary approach with build-time discriminator is the correct choice given the constraints:
The Recommendations
VerdictApprove - This PR is well-researched, properly implemented, and addresses a real user pain point (404 on ARM64 install). The code quality is high, security considerations are properly handled, and test coverage is adequate. |
Run Bun.build from /tmp instead of the project directory to avoid fakeowner path resolution failures on DevPod Docker-on-macOS (virtiofs) environments where .bun-build temp files trigger ENOENT. Assistant-model: Claude Code
Bun's coverage reporter can crash with multiple signal types (SIGFPE, SIGSEGV, SIGABRT) due to known JavaScriptCore bugs during report generation. Generalize the retry logic to handle all three signals via a RETRYABLE_SIGNALS set instead of checking only SIGFPE. Assistant-model: Claude Code
Wrap renderOnce() and renderer.destroy() calls in act() across all 13 E2E test files to properly flush React state updates. This prevents "act(...)" warnings and ensures component state is settled before assertions run. Helper functions now await act() internally so individual tests no longer need separate renderOnce() calls. Assistant-model: Claude Code
Add src/services/system/download.ts to coveragePathIgnorePatterns as it is an I/O-heavy system utility that is impractical to unit test without fragile mocks. Assistant-model: Claude Code
PR Review: feat(windows): add ARM64 support via x64 emulationOverall, this is a well-researched and thoughtfully designed PR that solves a real problem (Windows ARM64 users getting 404 errors and crashes). The dual-binary approach with a build-time discriminator is a clean solution to a tricky problem. Code Quality and Best Practices ✅Strengths:
Suggestions:
Potential Issues
|
Additional PR ReviewVerdict: Approve with minor suggestions This is a well-thought-out solution to the Windows ARM64 support problem. The dual-binary approach with build-time discriminator is the right choice given the TinyCC/Prism constraints. Key Strengths:
Minor Suggestions:
Security: No issues - checksum integrity preserved, input validation prevents injection. Performance: Native x64 retains AVX, ARM64 gets AVX-free baseline. Minimal CI overhead. Overall: High-quality PR with solid architecture and good test coverage. |
Resolve modify/delete conflict for src/scripts/test-coverage.ts by accepting main's deletion. Fix type errors from merge: - screenMode → useAlternateScreen (opentui API change) - Remove session_state_changed case (not in SDK type union)
macOS resolves temp directories to /private/var/folders/…, which bypasses the existing **/tmp/** pattern. Add an explicit ignore for **/var/folders/** to prevent temp files from inflating coverage. Assistant-model: Claude Code
|
PR Review: feat(windows) add ARM64 support via x64 emulation Overall: Approve with minor suggestions HIGHLIGHTS:
MINOR ISSUES:
CODE QUALITY:
SECURITY: No concerns. Changes focus on build/install infrastructure. Well-engineered PR with thorough documentation. Minor issues are non-blocking. |
Reverts the act() wrapping of render/destroy calls added in 5e6730b. The underlying Bun coverage crash was resolved separately on main, making these workarounds unnecessary. Aligns E2E tests with main.
PR Review: Windows ARM64 Support via x64 EmulationThis is a well-researched and thoroughly documented PR that adds Windows ARM64 support via a dual-binary distribution strategy. The approach is sound - shipping both a standard x64 binary (with AVX optimizations) and an x64-baseline binary (AVX-free for ARM64 Prism emulation). Summary of Changes
✅ Strengths
|
Restore `screenMode: "alternate-screen"` in place of the removed `useAlternateScreen` property on CliRendererConfig, and re-add the `session_state_changed` case to the exhaustive system subtype switch to fix typecheck failures. Assistant-model: Claude Code
PR Review: Windows ARM64 Support via x64 EmulationSummaryThis PR adds Windows ARM64 support through a dual-binary distribution strategy. ARM64 users get an AVX-free x64-baseline binary that runs via Windows 11 Prism emulation. This is a well-designed solution that addresses the core issues (404 errors and runtime crashes) without sacrificing AVX optimizations for native x64 users. ✅ Code Quality & Best PracticesBuild System (
Download Utility (
Install Scripts
🔒 Security AnalysisStrong Points:
No security concerns identified. 🧪 Test CoverageExcellent coverage for new functionality:
Highlights:
⚡ Performance Considerations
🔧 CI/CD Changes
📝 Minor Suggestions (Non-blocking)
✅ VerdictApprove - This is a well-implemented feature with:
The dual-binary strategy is the right solution - it solves the ARM64 problem without compromising the native x64 experience. Good work! 🎉 |
Enables Windows ARM64 users to install and run Atomic CLI by shipping an AVX-free x64-baseline binary that runs via Windows 11 Prism x64 emulation. Fixes installation failures (404 errors) and runtime crashes for Windows ARM64 users while preserving AVX optimizations for native x64 users.
Problem: Windows ARM64 users faced two blocking issues: (1) install.ps1 requested atomic-windows-arm64.exe which was never built, resulting in 404 errors (2) Native ARM64 binaries would crash because bun:ffi is unavailable on Windows ARM64 due to TinyCC lacking an ARM64 backend. Standard x64 binaries use AVX/AVX2 instructions that Prism emulation cannot translate.
Solution: Dual-binary distribution strategy with atomic-windows-x64.exe (AVX-optimized for native x64) and atomic-windows-x64-baseline.exe (AVX-free for ARM64 via Prism). Build-time discriminator flag ensures correct self-updates.
Key Changes: install.ps1 remaps ARM64 to baseline binary, install.sh fixes version arg passing, publish.yml builds two Windows binaries, build-binary.ts auto-derives baseline flag, download.ts handles self-update correctly. Added comprehensive tests and documentation.
Breaking: ARM64 Windows users require Windows 11 for Prism emulation support.
Closes #388, Closes #389