agent-dev-env 0.1.0-canary.2.fbbd044

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +106 -0
  3. package/dist/assets/bridge/bridge.js +202 -0
  4. package/dist/assets/guest/guest-agent-mac.js +586 -0
  5. package/dist/assets/guest/guest-agent-ubuntu.js +481 -0
  6. package/dist/assets/guest/guest-agent-windows.js +466 -0
  7. package/dist/assets/images/mac/CHANGELOG.md +265 -0
  8. package/dist/assets/images/mac/README.md +63 -0
  9. package/dist/assets/images/mac/sandbox.pkr.hcl +468 -0
  10. package/dist/assets/images/mac/vars/sandbox-macos-tahoe.pkrvars.hcl +39 -0
  11. package/dist/assets/images/ubuntu-arm64-vmware/CHANGELOG.md +239 -0
  12. package/dist/assets/images/ubuntu-arm64-vmware/README.md +177 -0
  13. package/dist/assets/images/ubuntu-arm64-vmware/autoinstall/meta-data +2 -0
  14. package/dist/assets/images/ubuntu-arm64-vmware/autoinstall/user-data +34 -0
  15. package/dist/assets/images/ubuntu-arm64-vmware/sandbox.pkr.hcl +776 -0
  16. package/dist/assets/images/ubuntu-arm64-vmware/vars/sandbox-ubuntu-24-04-arm64-vmware.pkrvars.hcl +71 -0
  17. package/dist/assets/images/windows-arm64-qemu/CHANGELOG.md +209 -0
  18. package/dist/assets/images/windows-arm64-qemu/README.md +142 -0
  19. package/dist/assets/images/windows-arm64-qemu/autounattend.xml +325 -0
  20. package/dist/assets/images/windows-arm64-qemu/qemu-with-tpm.sh +170 -0
  21. package/dist/assets/images/windows-arm64-qemu/sandbox.pkr.hcl +1012 -0
  22. package/dist/assets/images/windows-arm64-qemu/vars/sandbox-windows-11-arm64-qemu.pkrvars.hcl +83 -0
  23. package/dist/assets/images/windows-arm64-vmware/CHANGELOG.md +270 -0
  24. package/dist/assets/images/windows-arm64-vmware/README.md +171 -0
  25. package/dist/assets/images/windows-arm64-vmware/autounattend.xml +311 -0
  26. package/dist/assets/images/windows-arm64-vmware/sandbox.pkr.hcl +1036 -0
  27. package/dist/assets/images/windows-arm64-vmware/vars/sandbox-windows-11-arm64-vmware.pkrvars.hcl +83 -0
  28. package/dist/assets/rules/agent-rules-linux.md +68 -0
  29. package/dist/assets/rules/agent-rules.md +71 -0
  30. package/dist/assets/watchdog/watch-build-ocr.swift +40 -0
  31. package/dist/assets/watchdog/watch-build.py +275 -0
  32. package/dist/cli.js +52 -0
  33. package/dist/commands/delete.js +179 -0
  34. package/dist/commands/doctor.js +165 -0
  35. package/dist/commands/list.js +38 -0
  36. package/dist/commands/not-yet.js +15 -0
  37. package/dist/commands/register.js +150 -0
  38. package/dist/commands/run.js +65 -0
  39. package/dist/commands/status.js +142 -0
  40. package/dist/commands/stop.js +186 -0
  41. package/dist/commands/sync.js +98 -0
  42. package/dist/lib/exec.js +250 -0
  43. package/dist/lib/ghcr.js +82 -0
  44. package/dist/lib/git.js +100 -0
  45. package/dist/lib/logger.js +87 -0
  46. package/dist/lib/network.js +63 -0
  47. package/dist/lib/paths.js +116 -0
  48. package/dist/lib/platform.js +87 -0
  49. package/dist/lib/prompt.js +66 -0
  50. package/dist/lib/qemu.js +373 -0
  51. package/dist/lib/regex.js +9 -0
  52. package/dist/lib/ssh.js +230 -0
  53. package/dist/lib/tart.js +210 -0
  54. package/dist/lib/template.js +35 -0
  55. package/dist/lib/vars.js +99 -0
  56. package/dist/lib/vmrun.js +334 -0
  57. package/dist/lifecycle/build-macos.js +23 -0
  58. package/dist/lifecycle/build-qemu.js +204 -0
  59. package/dist/lifecycle/build-shared.js +355 -0
  60. package/dist/lifecycle/build-ubuntu.js +184 -0
  61. package/dist/lifecycle/build-watchdog.js +146 -0
  62. package/dist/lifecycle/build-windows-vmware.js +112 -0
  63. package/dist/lifecycle/build.js +55 -0
  64. package/dist/lifecycle/catalog.js +165 -0
  65. package/dist/lifecycle/deploy.js +161 -0
  66. package/dist/lifecycle/tag.js +77 -0
  67. package/dist/lifecycle/watch-build.js +64 -0
  68. package/dist/runners/bridges.js +156 -0
  69. package/dist/runners/framework.js +66 -0
  70. package/dist/runners/macos-bridges.js +143 -0
  71. package/dist/runners/macos-guest.js +76 -0
  72. package/dist/runners/macos-rules.js +77 -0
  73. package/dist/runners/macos-summary.js +145 -0
  74. package/dist/runners/macos.js +258 -0
  75. package/dist/runners/openchamber.js +60 -0
  76. package/dist/runners/options.js +56 -0
  77. package/dist/runners/qemu-image.js +183 -0
  78. package/dist/runners/rules.js +49 -0
  79. package/dist/runners/ubuntu-bridges.js +154 -0
  80. package/dist/runners/ubuntu-guest.js +136 -0
  81. package/dist/runners/ubuntu-image.js +26 -0
  82. package/dist/runners/ubuntu-rules.js +86 -0
  83. package/dist/runners/ubuntu-shared.js +65 -0
  84. package/dist/runners/ubuntu-summary.js +141 -0
  85. package/dist/runners/ubuntu.js +117 -0
  86. package/dist/runners/vmware-common.js +158 -0
  87. package/dist/runners/vmware-image.js +242 -0
  88. package/dist/runners/windows-autologon.js +119 -0
  89. package/dist/runners/windows-bridges.js +136 -0
  90. package/dist/runners/windows-guest.js +213 -0
  91. package/dist/runners/windows-image.js +23 -0
  92. package/dist/runners/windows-qemu-summary.js +85 -0
  93. package/dist/runners/windows-qemu.js +189 -0
  94. package/dist/runners/windows-shared.js +68 -0
  95. package/dist/runners/windows-summary.js +104 -0
  96. package/dist/runners/windows.js +96 -0
  97. package/dist/settings/common.js +107 -0
  98. package/dist/settings/macos-copy.js +223 -0
  99. package/dist/settings/macos.js +41 -0
  100. package/dist/settings/ubuntu-copy.js +223 -0
  101. package/dist/settings/ubuntu.js +68 -0
  102. package/package.json +52 -0
@@ -0,0 +1,83 @@
1
+ # Windows 11 (ARM64) sandbox image.
2
+ #
3
+ # Built with the Packer qemu plugin on Apple Silicon (HVF accelerator):
4
+ # Windows 11 ARM64 ISO + virtio-win drivers + swtpm (TPM 2.0). See
5
+ # images/windows-arm64-qemu/README.md for the full build flow — the Windows ISO is
6
+ # bring-your-own (Microsoft does not permit redistribution), so it is not
7
+ # part of this repo.
8
+
9
+ windows_version = "11"
10
+
11
+ # SHA256 of the Windows 11 ARM64 ISO. Microsoft publishes the hash on the
12
+ # download page (https://www.microsoft.com/software-download/windows11arm64);
13
+ # paste it here to enable integrity verification. Set WINDOWS_ISO_PATH to
14
+ # the local ISO path when building. Empty = skip verification.
15
+ iso_sha256 = "638AA2C88E94385B00F4F178D071E3DF0B7D9E335577A83BD533B7F2EB65ADF0"
16
+
17
+ # virtio-win ISO with ARM64 drivers (release 0.1.240+). Downloaded by
18
+ # the agent-dev-env CLI build flow into build/windows-arm64-qemu/
19
+ # packer_cache/ when VIRTIO_WIN_ISO_PATH is unset; paste the published
20
+ # SHA256 to verify (empty = skip).
21
+ virtio_win_url = "https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso"
22
+ virtio_win_sha256 = ""
23
+
24
+ # Toolchain versions installed via Chocolatey (choco package versions —
25
+ # must exist in the community repository).
26
+ nodejs_version = "26.8.1"
27
+ python_version = "3.13.15"
28
+ github_cli_version = "2.97.0"
29
+ ripgrep_version = "15.2.0"
30
+ git_version = "2.55.0.4"
31
+ jq_version = "1.8.1"
32
+ open_code_review_version = "1.9.5"
33
+
34
+ # C/C++ + cross-language toolchains (brought over from AdGuard's
35
+ # build-agent-images windows2022-vs2022 / windows2022-go images).
36
+ # VS2022 Build Tools (choco package version; the finalizer adds the .NET
37
+ # SDKs + VC++ workload + Win11 SDK) and Rust (via rustup, not choco) are
38
+ # installed by dedicated provisioners.
39
+ go_version = "1.27.0"
40
+ rust_version = "1.95"
41
+ wixtoolset_version = "3.14.1.20250415"
42
+ protoc_version = "36.0.0"
43
+ nasm_version = "3.2.0"
44
+ llvm_version = "22.1.7"
45
+ vim_version = "9.2.995"
46
+ nuget_version = "7.9.0"
47
+ mingw_version = "16.1.0"
48
+ make_version = "4.4.1"
49
+ vs_buildtools_version = "117.14.37"
50
+
51
+ # Google Chrome: installed from the Chrome for Testing (CfT) snapshot
52
+ # archive instead of choco — choco's googlechrome package always downloads
53
+ # the live dl.google.com MSI whose hash rotates on every Chrome release,
54
+ # so the pinned package hash breaks between releases. CfT serves versioned
55
+ # zips at storage.googleapis.com/chrome-for-testing-public/<version>/,
56
+ # which stay downloadable and hash-stable. The x64 build runs under Windows
57
+ # on ARM emulation, like the choco MSI did.
58
+ chrome_version = "152.0.7977.54"
59
+ chrome_sha256 = "91850065e6b80bba0c752e17a150fe1b9e39bba51ed705640c1273f565950dda"
60
+
61
+ # VM resources
62
+ disk_size = 100
63
+ cpu_count = 4
64
+ memory_gb = 8
65
+
66
+ # WinRM credentials used for provisioning. They are baked into
67
+ # images/windows-arm64-qemu/autounattend.xml (Administrator password) and become the
68
+ # sandbox's login (SSH/RDP) — keep the two files in sync.
69
+ winrm_username = "Administrator"
70
+ winrm_password = "sandbox1"
71
+
72
+ # OpenChamber web UI password + port. The runner forwards guest 4000 to
73
+ # host 127.0.0.1:4000, so the UI is reachable at http://127.0.0.1:4000
74
+ # (password "sandbox" by default). OpenChamber refuses to serve on the
75
+ # network without a password.
76
+ openchamber_ui_password = "sandbox"
77
+ openchamber_port = 4000
78
+
79
+ # Semantic version this image is published under (also the GHCR push tag,
80
+ # besides :latest). For every release: bump it, add a CHANGELOG.md entry,
81
+ # and create the windows-arm64-qemu-v<version> git tag
82
+ # (npx agent-dev-env tag <image>).
83
+ image_version = "1.1.0"
@@ -0,0 +1,270 @@
1
+ # Changelog
2
+
3
+ All notable changes to the Windows sandbox images (VMware).
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ The image version lives in the image's vars file (`image_version`); every
9
+ release bumps it, adds an entry below, and tags the release commit
10
+ `<platform>-v<version>` (e.g. `windows-arm64-vmware-v1.0.0`). The
11
+ `[Unreleased]` section on top is never removed — changes land there until
12
+ the next release.
13
+
14
+ ## [Unreleased]
15
+
16
+ ### Added
17
+
18
+ - `agent-dev-env stop` (windows-vmware) — stops the sandbox:
19
+ `vmrun -T fusion stop` on the working VM (graceful via VMware Tools with
20
+ a hard power-off fallback), plus the host SSH agent / Docker bridge
21
+ listeners the runner leaves up. Honors the runner's
22
+ `SANDBOX_AGENT_PORT` / `SANDBOX_DOCKER_PORT` overrides.
23
+ - `agent-dev-env delete` (windows-vmware) — deletes the sandbox: stops
24
+ it first (delegating to the stop step), then removes the state dir
25
+ (extracted pristine base + working clone + pulled image cache). Asks
26
+ before deleting unless `--yes`.
27
+ - The toolchain and VS provisioners re-read PATH from the registry at
28
+ the start of their scripts: after the tools reboot a fresh WinRM
29
+ process can inherit a stale PATH (observed once: 'choco' not
30
+ recognized), and the choco bootstrapper's PATH update must be picked
31
+ up explicitly.
32
+ - The final verification checks the new toolchains with a check-and-warn
33
+ loop instead of hard version dumps: a missing helper (e.g.
34
+ `llvm-config`, not shipped by every LLVM Windows build) no longer
35
+ fails the build.
36
+ - The build reboots the guest once after the VMware Tools install (new
37
+ `windows-restart` provisioner): the tools installer leaves a pending
38
+ reboot, which makes `choco install` return 3010 (observed on python)
39
+ and makes the .NET Framework 4.8 Developer Pack installer fail with
40
+ exit code 1 (it refuses to run while a reboot is pending). Choco
41
+ exit-code checks in the VS phase accept 3010 (success, reboot
42
+ required).
43
+ - Toolchains from AdGuard's `build-agent-images` Windows image
44
+ (`windows2022-vs2022` / `windows2022-go`) that were missing: Go, Rust
45
+ (via rustup — arm64 host toolchain + MSVC targets for
46
+ x86_64/i686/aarch64), Visual Studio 2022 Build Tools (choco package +
47
+ `setup.exe` finalizer: .NET 4.8/.NET Core SDKs, VC++ workload
48
+ x86/x64/ARM/ARM64, CMake, Windows 11 SDK 22621), WiX Toolset, protoc,
49
+ NASM, LLVM, Vim, NuGet CLI, MinGW-w64 and GNU make. All versions are
50
+ pinned in the vars file (`go_version`, `rust_version`,
51
+ `vs_buildtools_version`, `wixtoolset_version`, `protoc_version`,
52
+ `nasm_version`, `llvm_version`, `vim_version`, `nuget_version`,
53
+ `mingw_version`, `make_version`); the toolchain provisioner and the
54
+ final verification dump their versions.
55
+
56
+ ### Changed
57
+
58
+ - Node.js is bumped from 22 to 26 (`nodejs_version = "26.8.1"` in the
59
+ vars file, choco package `nodejs`).
60
+ - The image was renamed from `sandbox-windows-11-vmware` to
61
+ `sandbox-windows-11-arm64-vmware` (vars file, template `vm_name` —
62
+ `sandbox-windows-<windows_version>-arm64-vmware` — the GHCR package
63
+ name, the runner's `image_name` and the working VM's display name):
64
+ the platform is now part of the image name, matching the state-dir
65
+ naming (`~/Library/Application Support/agent-dev-env/windows-vmware/`).
66
+ Older releases stay published under the old name.
67
+ - Build artifacts moved out of the image directory into a top-level
68
+ `build/windows-arm64-<platform>/` directory: `output/` for
69
+ the built vmx + vmdk + nvram, `packer_cache/` for watchdog scratch and
70
+ `drivers/staging/` for the unattend CD vmxnet3 driver. The template's
71
+ `output_directory` (and the `cd_files` staging path) are now variables
72
+ set by the CLI build flow; the macOS/tart images build no
73
+ files and have no such directory. Guest content is unchanged (no
74
+ `image_version` bump).
75
+ - The build output is upgraded post-build with `vmrun upgradevm`
76
+ (the CLI build flow): the vmware-iso builder writes
77
+ the VM at hardware version 20, and a newer Fusion first starts such a VM
78
+ with a one-time "Upgrade this virtual machine?" prompt (the headless
79
+ build never sees it; the first GUI start does). The published artifact
80
+ now carries the hardware version the building Fusion supports (22 on
81
+ Fusion 26). The shared helper lives in `lib/vmrun.ts`.
82
+ - `agent-dev-env run` (windows-vmware) upgrades its working clone the
83
+ same way (once per clone, recorded next to the vmx in
84
+ `working/.hw-version`), so artifacts built by older Fusion versions also
85
+ start without the prompt.
86
+ - The guest-side bridge scripts (the Node relay, the idempotent
87
+ `bridges.ps1`, the `start-relays.cmd` bootstrap and the
88
+ `guest-setup.ps1` installer) moved out of the runner's heredocs into
89
+ the bundled `packages/guest-agent-windows` agent: the agent
90
+ renders them for the run's bridge ports + host alias and writes each
91
+ one into the guest with its own small SSH exec (one combined payload
92
+ overran the Windows OpenSSH exec-request command line); the guest only
93
+ rewrites a file when its content changed.
94
+ - `agent-dev-env run` (windows-vmware) — the default working-VM state
95
+ dir now lives under the CLI's data root
96
+ (`~/Library/Application Support/agent-dev-env/windows-vmware/<image>/`):
97
+ the platform and image are part of the path, so state from different
98
+ platforms and images never collides. Override the data root with
99
+ `AGENT_DEV_ENV_DATA_HOME` (or `XDG_DATA_HOME`) as before.
100
+ - `agent-dev-env run` (windows-vmware) — the working clone now gets a
101
+ distinct display name, `agent-dev-env-windows-11-arm64-vmware` (set in
102
+ the cloned vmx before the first start), instead of inheriting the
103
+ pristine image's `sandbox-windows-11-arm64-vmware`: `vmrun clone`
104
+ copies the source vmx's `displayName`, so before this the working VM
105
+ was indistinguishable from the base in Fusion's VM library.
106
+ - `agent-dev-env run` (windows-vmware) — the summary's stop hints now
107
+ point at `agent-dev-env stop` instead of a bare
108
+ `vmrun stop` and a hand-written `lsof | xargs kill` for the bridge
109
+ listeners.
110
+ - HGFS shared folders are not supported for Windows 11 ARM guests on
111
+ Apple silicon (VMware Tools for Windows Arm ships no HGFS kernel
112
+ driver, so the guest can never mount `\\vmware-host\Shared Folders`
113
+ even though the host publishes the share). The runner now detects the
114
+ unsupported combo from the vmx `guestos` string and skips the share
115
+ with a warning instead of registering it and claiming success; the
116
+ summary reports `Shared: not supported (...)`.
117
+ `SANDBOX_WORK_DIR` / `--work-dir` stay accepted but are a no-op with a
118
+ warning. `docs/windows-vmware.md` and the image README now state the
119
+ limitation and the working alternatives (SMB share from the Mac,
120
+ SSH/SCP, RDP clipboard, git, OpenChamber UI).
121
+
122
+ ### Fixed
123
+
124
+ - The runner's guest bridge setup no longer takes ~5 min per SSH command
125
+ on a guest whose bridges are already installed: the sshd channel does
126
+ not close when a PowerShell payload finishes (the guest-side relays
127
+ hold the console handles and keep trickling output, which resets
128
+ expect's idle timeout), so every `guest_ps` call used to end only at
129
+ the 5-min alarm. Each remote command now ends with a unique sentinel
130
+ echoed by the guest's shell after the payload exits, and expect kills
131
+ the ssh client on it — step 5 finishes in seconds.
132
+ - The shared host directory no longer fails right after the auto-logon
133
+ reboot — the runner (`agent-dev-env run`, windows-vmware) called
134
+ `vmrun addSharedFolder`
135
+ as soon as sshd answered, but VMware Tools can still be starting then:
136
+ `getGuestIPAddress`/sshd were already up while the tools state vmrun
137
+ needs for the HGFS registration was not, so the runner logged `Error:
138
+ The VMware Tools are not running in the virtual machine` and the share
139
+ never appeared in the guest at
140
+ `\\vmware-host\Shared Folders\work`. The runner now waits for
141
+ `vmrun checkToolsState` to report `running` (up to 5 min) and
142
+ retries `addSharedFolder` a few times, then warns only if it still
143
+ failed. A share persisted by a previous run (`Error: Already exists`)
144
+ is treated as success.
145
+ - The image no longer depends on the Chocolatey bootstrapper persisting
146
+ the machine PATH: the Chocolatey provisioner adds
147
+ `C:\ProgramData\chocolatey\bin` to the Machine PATH itself and the
148
+ toolchain + VS provisioners call `choco.exe` by its full path — the
149
+ bootstrapper's compiled `Install-ChocolateyPath` can silently fail to
150
+ persist in the elevated WinRM context, so after the reboot the
151
+ re-read PATH still lacked the choco bin dir ('choco' not recognized).
152
+ The toolchain retry loop also stops redirecting native stderr with
153
+ `2>&1`: under `$ErrorActionPreference='Stop'` in Windows PowerShell
154
+ 5.1 that turns the not-found message into an immediate terminating
155
+ error before the retry logic could run. The loop still goes through
156
+ `cmd /c` so the package name and its `--version` stay separate
157
+ arguments (a direct `& $choco install $installArgs` passed
158
+ 'nodejs --version=…' as one argument, which choco treated as a package
159
+ name). `choco cleanup` in the final verification now redirects inside
160
+ `cmd` for the same stderr reason.
161
+ - The RemoteSigned bake-in no longer aborts the build (observed at the
162
+ OpenChamber provisioner): the build passes `-ExecutionPolicy Bypass`
163
+ at Process scope, so `Set-ExecutionPolicy -Scope LocalMachine`
164
+ emitted its "overridden by a more specific scope" notice, which
165
+ Windows PowerShell 5.1 under WinRM turned into a terminating error
166
+ even though the machine policy was updated. The provisioner now sets
167
+ the Process scope first (no override, no notice) and tolerates a
168
+ failed machine-policy set.
169
+ - The image now bakes in machine-wide PowerShell `RemoteSigned` instead
170
+ of shipping Windows' default `Restricted` policy: `opencode` (an npm
171
+ shim — `opencode.ps1` in `%APPDATA%\npm`) refused to start in a
172
+ PowerShell session with "running scripts is disabled on this system".
173
+ The runners' runtime `Set-ExecutionPolicy` stays as a fallback for
174
+ images built before this change.
175
+ - VMware Tools are now actually working in the image — the runnable
176
+ regression the sandbox runner was hitting: the ARM64 tools package
177
+ (Fusion's `windows.iso`) ships no VMCI driver (only `vmxnet3` +
178
+ `vm3d` + `vmusbmouse`), so the tools installer skips its own service
179
+ registration and the image landed with `vmtoolsd.exe` present but no
180
+ 'VMware Tools' service. The runner then hung for 15 min at "Waiting
181
+ for the guest IP (VMware Tools; up to 15 min)" — vmrun
182
+ `getGuestIPAddress` answered "The VMware Tools are not running in the
183
+ virtual machine", and the runner (correctly) refused to treat that as
184
+ an IP. The final verification now registers the 'VMware Tools'
185
+ service itself (auto-start, if absent) and starts it, and fails the
186
+ build when the service is still not running — instead of checking
187
+ only for `vmtoolsd.exe` with `Test-Path` (which passed for the broken
188
+ install).
189
+ - The VMware Tools service registration lives in a provisioner, not in
190
+ `autounattend.xml`'s FirstLogonCommands: the first attempt (baking
191
+ the `New-Service` + `Start-Service` block into the tools-install
192
+ CommandLine, ~1 KB of extra text) broke Windows Setup at the first
193
+ boot — the guest showed "Windows could not complete the installation.
194
+ To install Windows on this computer, restart the installation." and
195
+ Packer spun on "Waiting for WinRM" until the 90 m timeout. The setup
196
+ logs (C:\Windows\Panther) show the failure at the Pre-OOBE phase
197
+ (windeploy 0x80220005 → rollback; also a BFSVC EFI boot-file
198
+ `BfspCopyFile` 0x3 storm) — the oobeSystem pass never finished, so
199
+ neither the OOBE nor FirstLogonCommands (network driver, tools,
200
+ WinRM) ever ran. The tools CommandLine is back to the proven shorter
201
+ form; the service registration moved to the final-verification
202
+ provisioner.
203
+ - The final verification's fail-hard `throw` message is ASCII-only:
204
+ the original em-dash (`—`) inside the inline PowerShell string was
205
+ mangled in the Packer WinRM transfer (it came back as a smart-quote
206
+ byte, which closed the string literal early and made the parser fail
207
+ with "Unexpected token 'vmtoolsd.exe'" plus a misleading "Missing
208
+ closing '}'"/"Try statement is missing its Catch or Finally block" —
209
+ the build aborted at 47 min in the last provisioner). Non-ASCII in
210
+ inline PowerShell string literals is now documented as a gotcha in
211
+ `AGENTS.md`; comments are unaffected.
212
+
213
+ ## [windows-arm64-vmware-v1.0.0] - 2026-08-23
214
+
215
+ ### Added
216
+
217
+ - Windows 11 (ARM64) VMware sandbox image (`sandbox-windows-11-vmware`),
218
+ built with the Packer vmware-iso plugin on Apple Silicon (VMware Fusion
219
+ hosts the installer — the most proven Windows-ARM path; Fusion provides
220
+ the ARM64 vmxnet3 NIC driver, the ARM64 VMware Tools and NVMe storage
221
+ with the in-box driver). Windows 11 Pro ARM64 from the official
222
+ Microsoft ISO (bring-your-own; the same 25H2 ISO checksum the QEMU
223
+ image pins), installed unattended via `autounattend.xml` with the
224
+ Windows-11 hardware-check bypasses (BypassCPUCheck is mandatory —
225
+ Apple Silicon) and OOBE bypasses. The build stages the vmxnet3 driver
226
+ from Fusion's `Contents/Library/isoimages/arm64/drivers-arm64.zip` into
227
+ the unattend CD (no in-box VMware NIC driver: it must land before any
228
+ network use) and installs Fusion's ARM64 tools ISO (attached by the
229
+ builder, `tools_mode "attach"`; installed by `autounattend.xml` at
230
+ first logon, before WinRM — the tools installer rebinds the NIC and
231
+ kills any live WinRM session (a provisioner-based install timed out).
232
+ - The image ships the same toolchain as the QEMU image: Chocolatey +
233
+ toolchain (Node.js, Python, Git, GitHub CLI, ripgrep, jq, curl —
234
+ versions pinned in the vars file), Visual Studio Code (native arm64),
235
+ Chrome (Chrome for Testing snapshot, hash-pinned), Firefox, OpenCode,
236
+ OpenCodeReview (`ocr`), the OpenChamber web UI as a native service on
237
+ port 4000, VMware Tools, OpenSSH Server + RDP, a Docker CLI client
238
+ (remote engine via the host bridge), and the bridge tooling
239
+ (`socat` + `npiperelay`) as utilities.
240
+ - `images/windows-arm64-vmware/build.sh` — platform build wrapper:
241
+ verifies the host + Fusion install + ISO sha256, stages the vmxnet3
242
+ driver, starts the VNC build watchdog (shared `scripts/watch-build.sh`),
243
+ and runs `packer init` + `packer build`.
244
+ - `images/windows-arm64-vmware/deploy.sh` — platform deploy wrapper that
245
+ packs the output directory (vmx + vmdk + nvram) into a tar.gz and
246
+ pushes it to GHCR as an OCI artifact with `oras`
247
+ (`ghcr.io/<owner>/sandbox-windows-11-vmware:<version>` + `:latest`);
248
+ `scripts/deploy.sh` delegates to it like it does for the QEMU image.
249
+ - `scripts/run-windows-vmware-sandbox.sh` — the user-facing VMware sandbox
250
+ runner, landing together with the user guide `docs/windows-vmware.md`:
251
+ extracts the archive into the state dir and clones a working VM with
252
+ `vmrun -T fusion clone ... full` (base never written to) under
253
+ `~/Library/Application Support/agent-dev-env/windows-11-vmware`, boots
254
+ it with `vmrun start`, discovers the guest IP via `vmrun
255
+ getGuestIPAddress` (VMware Tools are in the image — no port
256
+ forwarding, the host is the NAT router for the vmnet8 subnet),
257
+ re-enables Windows auto-logon (the image's `LogonCount=1` disables it
258
+ after the OOBE boot) so the OpenChamber task fires at boot, bridges the
259
+ host's SSH agent and Docker engine into the guest (host-side socat on
260
+ TCP 4200/4201 bound to the vmnet8 address + guest-side Node relays
261
+ serving the `\\.\pipe\openssh-ssh-agent` and `\\.\pipe\docker_engine`
262
+ named pipes, started detached via a SYSTEM scheduled task), optionally
263
+ shares a host directory (HGFS, `--work-dir`), and verifies OpenChamber.
264
+ - Known limitations at this stage: Windows runs unactivated with a
265
+ watermark; the sandbox agent rules (`scripts/agent-rules.md`) are
266
+ macOS-flavored and not installed into Windows guests yet; the shared
267
+ folder is best-effort (HGFS must be enabled by VMware Tools).
268
+
269
+ [unreleased]: https://github.com/ameshkov/agent-dev-env/compare/windows-arm64-vmware-v1.0.0...HEAD
270
+ [windows-arm64-vmware-v1.0.0]: https://github.com/ameshkov/agent-dev-env/releases/tag/windows-arm64-vmware-v1.0.0
@@ -0,0 +1,171 @@
1
+ # Windows Sandbox Images — VMware
2
+
3
+ Windows 11 (ARM64) sandbox VM images built with [Packer](https://www.packer.io/)
4
+ and the [VMware plugin](https://github.com/vmware/packer-plugin-vmware)
5
+ (`vmware-iso` builder) on an Apple Silicon Mac. The output is a runnable
6
+ vmx + vmdk VM (built at the vmware-iso hardware level, upgraded post-build
7
+ to the host Fusion's current hardware version — see
8
+ [How to Build](#how-to-build)), packed into a tar.gz for publishing; the
9
+ macOS host runs it under Fusion's `vmrun` CLI. Fusion
10
+ virtualizes ARM64 guests natively and is the most proven Windows-ARM path —
11
+ it also ships the ARM64 boot drivers and the ARM64 VMware Tools (guest IP
12
+ discovery works, but HGFS shared folders are not supported for Windows 11
13
+ ARM guests on Apple silicon — see
14
+ [docs/windows-vmware.md](../../docs/windows-vmware.md)).
15
+
16
+ This is the VMware sibling of the
17
+ [QEMU-based image](../windows-arm64-qemu/README.md): same Windows 11 Pro
18
+ ARM64 guest, same toolchain, same credentials. See
19
+ [docs/windows-vmware.md](../../docs/windows-vmware.md) for the user guide
20
+ (boot it with `npx agent-dev-env run windows-vmware`) and
21
+ [docs/windows-qemu.md](../../docs/windows-qemu.md) for the QEMU variant.
22
+
23
+ ## Prerequisites
24
+
25
+ - Apple Silicon Mac (M-series). Fusion cannot virtualize ARM64 guests on
26
+ Intel, so this image is ARM64-only.
27
+ - [VMware Fusion](https://www.vmware.com/products/desktop-hypervisor/workstation-and-fusion)
28
+ (free for personal use; the Packer plugin requires Fusion 13.6+).
29
+ - [Packer](https://www.packer.io/): `brew install hashicorp/tap/packer`
30
+ (the VMware plugin is installed automatically by `packer init`).
31
+ - The **Windows 11 ARM64 ISO** — bring your own, Microsoft does not permit
32
+ redistribution:
33
+
34
+ 1. Visit [Download Windows 11 (ARM64)](https://www.microsoft.com/software-download/windows11arm64)
35
+ and generate a download link (no Insider login required).
36
+ 2. Download the ISO (e.g. `Win11_25H2_English_Arm64_v2.iso`, ~7.5 GB) and
37
+ copy the SHA256 shown on the page into `iso_sha256` in the vars file.
38
+ 3. Set `WINDOWS_ISO_PATH` to its absolute path when building.
39
+
40
+ No driver or tool disk is needed beyond Fusion itself: the ARM64 vmxnet3
41
+ NIC driver comes from Fusion's
42
+ `Contents/Library/isoimages/arm64/drivers-arm64.zip` and the ARM64 VMware
43
+ Tools ISO from `Contents/Library/isoimages/arm64/windows.iso` (same app
44
+ bundle; `FUSION_APP_PATH` overrides a non-standard install).
45
+
46
+ ## How to Build
47
+
48
+ ```bash
49
+ # From the repository root
50
+ WINDOWS_ISO_PATH=/path/to/Win11_25H2_English_Arm64_v2.iso \
51
+ npx agent-dev-env build sandbox-windows-11-arm64-vmware
52
+ ```
53
+
54
+ `agent-dev-env` is the CLI shipped by this repo (see
55
+ [docs/cli.md](../../docs/cli.md)). The windows-vmware build flow:
56
+
57
+ 1. Verifies the host (Apple Silicon), the tools, the Fusion install (must
58
+ ship the ARM64 drivers zip and tools ISO), and the Windows ISO (SHA256
59
+ against `iso_sha256` from the vars file).
60
+ 2. Stages the ARM64 `vmxnet3` driver (inf/sys/cat) into
61
+ `drivers/staging/` at the root of the unattend CD — Windows 11 ARM64
62
+ has no in-box VMware NIC driver, and it must land before any network
63
+ use (WinRM from the host).
64
+ 3. Runs `packer init` + `packer build` with the vars file; the template
65
+ attaches Fusion's ARM64 tools ISO (`tools_mode "attach"`) and
66
+ `autounattend.xml` installs it at first logon (before WinRM comes up —
67
+ the tools installer rebinds the NIC and would kill a live WinRM
68
+ session).
69
+ 4. Runs the VNC **build watchdog** (bundled `assets/watchdog/`) alongside
70
+ `packer build` (pinned VNC port 5901) to auto-dismiss Windows Setup
71
+ dialogs and rescue a boot that lands in the UEFI shell. Needs
72
+ `pip3 install vncdotool` + Xcode command line tools; skipped with a
73
+ warning when missing.
74
+ 5. Upgrades the output VM with `vmrun upgradevm` to the hardware version
75
+ the installed Fusion writes for a new VM (hardware version 20 → 22 on
76
+ Fusion 26). The headless build never shows Fusion's one-time
77
+ "Upgrade this virtual machine?" prompt, but a first GUI start of a
78
+ version-20 VM would; the upgrade also rewrites the vmdk descriptor.
79
+ The runner upgrades its working clone the same way for artifacts built
80
+ by older Fusion versions (see
81
+ [docs/windows-vmware.md](../../docs/windows-vmware.md)).
82
+
83
+ A build takes roughly 30 minutes on an M-series Mac (Windows Setup
84
+ dominates; Fusion runs the guest near-native). Everything per image lives
85
+ under the CLI's data root:
86
+ `~/Library/Application Support/agent-dev-env/build/windows-vmware/output/`
87
+ (the vmx + vmdk + nvram), plus `packer_cache/` and `drivers/staging/`.
88
+ The macOS/tart images build no files and have no such directory.
89
+
90
+ ## What's in the image
91
+
92
+ | Component | Detail |
93
+ | --- | --- |
94
+ | Windows 11 Pro (ARM64) | Unactivated (watermark); generic Pro key used for Setup |
95
+ | VMware Tools | ARM64 tools from the Fusion install (attached by the builder, installed at first logon); enables `vmrun getGuestIPAddress` (no HGFS shared folders for Win11 ARM guests) |
96
+ | VMware drivers | vmxnet3 ARM64 NIC driver (staged into the unattend CD); NVMe disk uses the in-box driver |
97
+ | Chocolatey | Community package manager (versions pinned in the vars file) |
98
+ | Node.js, Python, Git, gh, ripgrep, jq, curl | Choco packages (versions from the vars file) |
99
+ | Go, Vim, NuGet, make, MinGW-w64 | Choco packages (versions from the vars file) |
100
+ | Rust | Via rustup (arm64 host toolchain + MSVC targets for x86_64/i686/aarch64), `rust`/`cargo` on PATH |
101
+ | VS2022 Build Tools | Choco + `setup.exe` finalizer: .NET 4.8/.NET Core SDKs, VC++ workload (x86/x64/ARM/ARM64), CMake, Windows 11 SDK |
102
+ | WiX, protoc, NASM, LLVM | Choco packages (versions from the vars file) |
103
+ | Visual Studio Code | Native arm64 build, latest stable, direct download; `code` on PATH |
104
+ | Google Chrome | Chrome for Testing snapshot, hash-pinned (see the vars file); x64, runs under Prism emulation |
105
+ | Firefox | Choco package (x64, runs under Prism emulation) |
106
+ | OpenCode (`opencode-ai`) | npm global |
107
+ | OpenCodeReview (`ocr`) | npm global (`@alibaba-group/open-code-review`) |
108
+ | OpenChamber web UI | npm global (`@openchamber/web`), native service on `0.0.0.0:4000` |
109
+ | OpenSSH Server + RDP | Enabled; Administrator/sandbox1 (see the vars file) |
110
+ | Docker CLI | Client only (`docker` + `docker compose`), remote engine via the host bridge |
111
+ | Bridge tooling | Node relays (in-image `node.exe`, written by the bundled guest agent) for the SSH-agent/Docker bridges — the host side is the CLI's own forwarder (no socat) |
112
+
113
+ ## Versioning
114
+
115
+ Same convention as the other images: the image version lives in
116
+ `image_version` in the vars file; every release bumps it, adds a
117
+ `CHANGELOG.md` entry, and creates a `windows-arm64-vmware-v<version>` git
118
+ tag via `npx agent-dev-env tag <image>`.
119
+
120
+ ## Running and publishing
121
+
122
+ - Run the sandbox: `npx agent-dev-env run windows-vmware` — extracts
123
+ the archive, clones a working VM with `vmrun`, discovers the guest IP
124
+ via VMware Tools, and bridges the host's Docker engine and SSH agent
125
+ into the guest (see [docs/windows-vmware.md](../../docs/windows-vmware.md)).
126
+ - Publish: `npx agent-dev-env deploy sandbox-windows-11-arm64-vmware` packs
127
+ the output directory into `${image_name}.tar.gz` and pushes it to
128
+ `ghcr.io/<owner>/sandbox-windows-11-arm64-vmware:<version>` + `:latest` as
129
+ an OCI artifact via `oras` (the CLI packs and pushes directly — no
130
+ platform wrapper — because `tart push` only works for Tart VMs). Needs
131
+ `brew install oras` and a GHCR token with `write:packages`
132
+ (`oras login ghcr.io`).
133
+
134
+ ## Gotchas
135
+
136
+ - **The Windows ISO is not in the repo.** The build fails fast without
137
+ `WINDOWS_ISO_PATH`; the sha256 in the vars file protects against a
138
+ corrupt download.
139
+ - **ARM64 only.** Fusion on Intel can only run x86_64 guests, so this
140
+ image requires Apple Silicon.
141
+ - **Fusion 13.6+ and the VMware plugin v2+.** The template uses
142
+ `github.com/vmware/vmware` (Broadcom's maintained fork); the older
143
+ `github.com/hashicorp/vmware` plugin has different options.
144
+ - **vmxnet3 driver must be installed before any network use.**
145
+ FirstLogonCommands order 1 scans the unattend CD (drive letters D:..H:)
146
+ for the driver; if the CD is relocated the scan fails loudly in the
147
+ guest and WinRM never comes up — check the build log before blaming the
148
+ template.
149
+ - **The build uses the *host's* Fusion tools ISO.** The image's VMware
150
+ Tools version tracks the Fusion that built it; running the VM under a
151
+ much older Fusion can complain about unstable tools. Rebuild after a
152
+ Fusion update, or update tools in the running guest from the new
153
+ Fusion's ISO.
154
+ - **Tools install must not reboot the guest.** The installer passes
155
+ `REBOOT=R` (autounattend order 2): without it the tools MSI initiates a
156
+ reboot mid-FirstLogonCommands, orders 3-6 (network + WinRM) never run,
157
+ and the build spins on "Waiting for WinRM" forever at the login screen.
158
+ - **No snapshot in the published image.** `snapshot_name` is deliberately
159
+ unset: the sandbox runner makes a *full* clone as its working VM, and a
160
+ snapshot inside the published archive would only complicate disk
161
+ compaction and re-cloning.
162
+ - **Unactivated Windows.** The image runs indefinitely with a desktop
163
+ watermark; personalization (wallpaper) is locked.
164
+ - **Computer name ≤ 15 chars.** `win11-sandbox` fits; longer names fail
165
+ the specialize pass even though `xmllint`/`packer validate` pass.
166
+
167
+ ## Migration notes
168
+
169
+ The v1.0.0 image reuses the exact Windows 11 25H2 ISO that
170
+ `images/windows-arm64-qemu` pins (same sha256), so the same downloaded
171
+ ISO serves both platforms.