boo-flash 0.1.1 → 0.1.2
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.
- package/README.md +17 -289
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,302 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://os.boo">
|
|
3
|
+
<picture>
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://os.boo/boo-logo-dark.svg">
|
|
5
|
+
<img src="https://os.boo/boo-logo-light.svg" width="184" height="96" alt="Boo">
|
|
6
|
+
</picture>
|
|
7
|
+
</a>
|
|
8
|
+
</p>
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
# Boo Flash
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
independent of Boo image release versions such as `0.1.0+151`. Run it without a
|
|
13
|
-
global install using either supported runtime:
|
|
12
|
+
Flash [Boo](https://os.boo) to a USB drive from macOS or Linux.
|
|
14
13
|
|
|
15
14
|
```sh
|
|
16
|
-
npx boo-flash
|
|
17
|
-
bunx boo-flash # Bun 1.4 or later
|
|
15
|
+
npx boo-flash
|
|
18
16
|
```
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
launcher selects a compatible Node installation first and supplies Node's required
|
|
22
|
-
`--experimental-ffi`; otherwise it uses Bun. The npm artifact carries one
|
|
23
|
-
runtime-neutral Solid bundle plus the matching package-installed OpenTUI native
|
|
24
|
-
library. On Linux the launcher detects musl before OpenTUI loads
|
|
25
|
-
and selects its musl artifact; an explicit valid `OPENTUI_LIBC` remains authoritative.
|
|
26
|
-
|
|
27
|
-
Production flashing needs `curl` and `zstd`; Candidates add
|
|
28
|
-
`gh` (GitHub CLI) and `unzip`. macOS can offer to install missing content tools
|
|
29
|
-
through Homebrew. Existing commands on PATH or in `/opt/homebrew/bin` and
|
|
30
|
-
`/usr/local/bin` are used directly, without changing shell configuration. If
|
|
31
|
-
Homebrew is missing, follow [brew.sh](https://brew.sh), then press R to refresh.
|
|
32
|
-
Linux never chooses a distribution or changes system packages: install reported
|
|
33
|
-
missing commands with the distribution's package manager, then refresh. On Linux,
|
|
34
|
-
every command is resolved to a root-owned executable beneath root-owned,
|
|
35
|
-
non-writable directories; user-writable PATH shims are rejected.
|
|
36
|
-
Only the Candidates screen requires your ordinary `gh auth login` with access
|
|
37
|
-
to `anomalyco/boo`; Boo Flash does not manage authentication. Historical
|
|
38
|
-
candidate artifacts carrying the repository's former name remain valid.
|
|
39
|
-
macOS additionally uses `diskutil`, `plutil`, `ioreg`, `stat`, `sudo`, `dd`, and
|
|
40
|
-
`sync`. Linux additionally uses `lsblk`, `findmnt`, `udevadm`, `sudo`, `umount`,
|
|
41
|
-
`dd`, `sync`, and `udisksctl` from UDisks2. Run from a trusted checkout as your
|
|
42
|
-
ordinary user, not root.
|
|
43
|
-
|
|
44
|
-
For development from a checkout, use pinned Bun **1.4.0**:
|
|
18
|
+
or
|
|
45
19
|
|
|
46
20
|
```sh
|
|
47
|
-
|
|
48
|
-
bun install --frozen-lockfile
|
|
49
|
-
bun start
|
|
21
|
+
bunx boo-flash
|
|
50
22
|
```
|
|
51
23
|
|
|
52
|
-
|
|
53
|
-
sudo, and hands the terminal to Homebrew for output and any prerequisite
|
|
54
|
-
guidance. Ctrl-C cancels and quits, including when Homebrew handles the interrupt
|
|
55
|
-
through its own terminal and reports exit 130 or SIGINT. Boo Flash waits for its
|
|
56
|
-
owned brew process to close before exiting; Homebrew manages its own children
|
|
57
|
-
and cleanup, not a guarantee that every descendant has exited. SIGINT/SIGTERM
|
|
58
|
-
sent only to Boo Flash request quit but do not actively cancel brew: Boo Flash
|
|
59
|
-
still waits for it to finish, with no forced deadline. During that handoff,
|
|
60
|
-
Q/Escape are not TUI controls.
|
|
61
|
-
It does not bootstrap Homebrew, upgrade existing tools, or change shell files.
|
|
62
|
-
Homebrew may install/update dependencies needed by the requested formulae.
|
|
63
|
-
On failure, quit to read Homebrew's terminal output, resolve its reported issue
|
|
64
|
-
(such as Xcode Command Line Tools), then retry. Partial installs are not undone.
|
|
65
|
-
|
|
66
|
-
Select the **target GPU**, not the Mac's CPU. All three profiles are x86_64 UEFI
|
|
67
|
-
images, not ARM images. Arrow keys choose, Enter continues, Escape goes back
|
|
68
|
-
or cancels work, R refreshes, Q stops and quits. No USB is initially selected.
|
|
69
|
-
The erase screen defaults to **Go back**. There is no typed phrase or countdown.
|
|
70
|
-
|
|
71
|
-
The three GPU choices use the release identified by
|
|
72
|
-
`https://images.os.boo/channels/main.json` and show its Boo version. **Candidates** is
|
|
73
|
-
an additional choice: it checks the latest ten successful completed
|
|
74
|
-
`candidate.yml` runs and lists up to ten unexpired image artifacts, each with
|
|
75
|
-
its actual GPU profile, built-source SHA, run number/date and run title.
|
|
76
|
-
Choose one to continue directly to USB selection; candidates need not provide
|
|
77
|
-
all three profiles. They are **build-only, not boot/install/hardware qualified**.
|
|
78
|
-
If none are available, **Go back** returns to the main choices; R refreshes the
|
|
79
|
-
candidate list. Authentication/network errors are reported, not shown as empty.
|
|
80
|
-
|
|
81
|
-
After confirmation, only the selected production `.raw.zst` is downloaded from
|
|
82
|
-
its immutable release path (or reused from the verified cache). Candidates keep
|
|
83
|
-
their authenticated GitHub artifact ZIP flow. Candidate flashing needs space for
|
|
84
|
-
both the ZIP and compressed image; the raw image is always streamed, not staged.
|
|
85
|
-
After verification, the UI releases the terminal for an ordinary `sudo -v`
|
|
86
|
-
prompt. No password or GitHub token is read by the application. macOS runs only
|
|
87
|
-
`dd` as root. Linux runs checked non-forced unmounts, `dd`, and UDisks safe
|
|
88
|
-
power-off through `sudo -n`. No privileged app process, custom daemon, shell, or
|
|
89
|
-
shell command string is used.
|
|
90
|
-
|
|
91
|
-
Read-only live production metadata discovery (with no image download or software
|
|
92
|
-
installation):
|
|
93
|
-
|
|
94
|
-
```sh
|
|
95
|
-
bun start --list-images
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
## Download Cache
|
|
99
|
-
|
|
100
|
-
Verified production images and GitHub candidate ZIPs are kept across flashes
|
|
101
|
-
and app restarts in
|
|
102
|
-
`os.tmpdir()/boo-flash-cache-<UID>/`, privately owned by your normal user.
|
|
103
|
-
The temporary parent is resolved normally, including platform symlinks. Each entry
|
|
104
|
-
is `<build-or-artifact-ID>-<SHA256>.{raw.zst|zip}`, not a profile or `latest`
|
|
105
|
-
alias. There is
|
|
106
|
-
no automatic expiry or eviction, but the OS may purge temporary storage: this
|
|
107
|
-
is not permanent storage or an offline image library. Discovery still needs
|
|
108
|
-
the public Boo channel for production or GitHub authentication and a usable,
|
|
109
|
-
unexpired artifact for candidates. Candidate source checks remain unchanged. No
|
|
110
|
-
tokens, signed URLs, or release catalogs are cached.
|
|
111
|
-
|
|
112
|
-
Only a download with matching expected size and SHA-256 is published, with an
|
|
113
|
-
atomic exclusive hardlink. Existing completed bytes are never overwritten.
|
|
114
|
-
A hit is privately hardlinked into operation staging and its owner, regular-file
|
|
115
|
-
type, size and SHA-256 are checked again before the usual image validation.
|
|
116
|
-
The UI says **Using cached image**, not downloading. Unsafe paths or corrupt payloads
|
|
117
|
-
fail before disk writes, without silently deleting or redownloading them. Clear
|
|
118
|
-
a corrupt payload and retry; unsafe ownership/permissions/symlinks require manual
|
|
119
|
-
correction. If the temporary filesystem cannot hardlink safely, the operation
|
|
120
|
-
reports an error before writing rather than pretending it retained the download.
|
|
121
|
-
If publication fails, the verified payload stays in its private operation folder
|
|
122
|
-
as `image.raw.zst` or `image.zip`; the error reports that path for manual
|
|
123
|
-
recovery. It is not a cache hit location and is not automatically reused or
|
|
124
|
-
removed by Clear. No authorization or disk write begins on publication failure.
|
|
125
|
-
|
|
126
|
-
**Clear cached images** in the main menu defaults to **Go back**. It removes
|
|
127
|
-
downloaded payloads only, never USB contents or active operation staging. Clear
|
|
128
|
-
does not interrupt a pinned active flash; a pending download can publish afterward.
|
|
129
|
-
For clearing without GitHub, authentication, dependency setup or UI discovery:
|
|
130
|
-
|
|
131
|
-
```sh
|
|
132
|
-
bun start --clear-cache
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
This explicit CLI action needs no confirmation. It reports the cache path and
|
|
136
|
-
number removed. Demo mode never clears the real cache. Operation scratch and
|
|
137
|
-
partial/unverified downloads are still cleaned when the operation finishes;
|
|
138
|
-
verified cached payloads
|
|
139
|
-
are retained even when subsequent validation/flashing fails or is cancelled.
|
|
140
|
-
|
|
141
|
-
## Image Contract
|
|
142
|
-
|
|
143
|
-
- Fetch `https://images.os.boo/channels/main.json` without caching, require its
|
|
144
|
-
exact version/revision/prefix contract, then fetch and cross-check the immutable
|
|
145
|
-
`releases/VERSION/release.json`. Require exactly Intel, AMD and NVIDIA metadata
|
|
146
|
-
with release filenames, compressed/raw sizes and SHA-256 digests.
|
|
147
|
-
- Candidates instead require exact `boo-{intel|amd|nvidia}-candidate-{full_sha}`
|
|
148
|
-
image artifacts, never producer artifacts. The artifact SHA is the built
|
|
149
|
-
source, not the workflow's orchestration `head_sha`. The selected artifact
|
|
150
|
-
ID, name, run, expiry, size and ZIP digest are rechecked before download/reuse;
|
|
151
|
-
`build-info.json` must agree on revision, profile and candidate source identity.
|
|
152
|
-
Listing downloads no image payloads and does not browse older pages.
|
|
153
|
-
- Stream only the selected production image from `images.os.boo`, measuring its
|
|
154
|
-
exact bytes and validating its release-manifest SHA-256. Candidates stream only
|
|
155
|
-
the chosen ZIP through authenticated `gh api` and validate the API size/digest.
|
|
156
|
-
- For candidates, extract only exact, unique root basenames: the chosen `.raw.zst`,
|
|
157
|
-
`build-info.json`, `SHA256SUMS` and `SHA256SUMS.raw`. Stream file content into
|
|
158
|
-
newly created private files; never unpack arbitrary archive paths or symlinks.
|
|
159
|
-
- Require schema 1, semantic version, build number, combined version, revision,
|
|
160
|
-
profile, exact `boo-VERSION-x86_64-PROFILE.raw.zst` release basename,
|
|
161
|
-
compressed byte count/hash and positive raw size/hash. Candidate `build-info`
|
|
162
|
-
additionally requires repository, clean source and checksum agreement;
|
|
163
|
-
candidates retain their existing basename and carry no release build number,
|
|
164
|
-
while candidates predating this metadata remain valid.
|
|
165
|
-
- Check capacity against `raw_apparent_bytes`. Decompress with `zstd`, bound,
|
|
166
|
-
count and hash the raw stream, and await both decompressor and writer status.
|
|
167
|
-
Raw-stream verification finishes **after writing**, not before erasure, and
|
|
168
|
-
is **not device read-back verification**. A failure cannot restore old data.
|
|
169
|
-
|
|
170
|
-
The progress bar is per-stage real byte progress, not an overall ETA or a timed
|
|
171
|
-
fill. Write progress means backpressured bytes delivered to `dd`, not durable
|
|
172
|
-
device bytes. A separate spinner covers activity; closing the writer, `sync`,
|
|
173
|
-
and the platform safe-removal operation must all succeed before the real success
|
|
174
|
-
screen says the USB is removable.
|
|
175
|
-
|
|
176
|
-
## Disk Safety
|
|
177
|
-
|
|
178
|
-
### macOS
|
|
179
|
-
|
|
180
|
-
Selection requires structured `diskutil -plist` data converted with `plutil`,
|
|
181
|
-
a physical whole disk, explicit external (`Internal=false`) USB transport,
|
|
182
|
-
writable media with 512-byte logical sectors, and a unique current IOMedia
|
|
183
|
-
`IORegistryEntryID` from `ioreg`. Current Boo images use a 512-byte-sector GPT:
|
|
184
|
-
512e disks remain eligible, but 4096-byte logical-sector (4Kn) disks do not.
|
|
185
|
-
Root, APFS System/Data, original user's home, working directory, app source,
|
|
186
|
-
Bun executable, resolved runtime packages/native assets, `gh`/`zstd` binaries
|
|
187
|
-
and image staging storage are protected.
|
|
188
|
-
Real paths and macOS `stat -f %Sd` map files/firmlinks to their devices; APFS
|
|
189
|
-
containers are followed to **all** physical stores, then whole physical disks.
|
|
190
|
-
Unresolved protected mappings fail closed, including unsupported virtual/RAID
|
|
191
|
-
storage. It never assumes that `disk0` is the system disk. External USB root
|
|
192
|
-
storage is excluded too. System/Data installations and multi-store APFS
|
|
193
|
-
containers are conservatively excluded even when not the running system.
|
|
194
|
-
|
|
195
|
-
Attachment ID, size, device-tree path and media name are compared after the
|
|
196
|
-
password prompt and again after checked, non-forced `unmountDisk` (which covers
|
|
197
|
-
APFS virtual volumes too). Mounted target partitions/APFS volumes are rejected
|
|
198
|
-
before writing. Paths are derived only from validated `diskN` identifiers;
|
|
199
|
-
the UI cannot supply arbitrary device paths. Attachment is rechecked before
|
|
200
|
-
eject. These are repeated checks, **not an atomic Disk Arbitration claim**:
|
|
201
|
-
do not unplug, swap or mount devices while an operation is running.
|
|
202
|
-
|
|
203
|
-
### Linux
|
|
204
|
-
|
|
205
|
-
Selection uses explicit-column `lsblk --json` topology. A target must be a
|
|
206
|
-
parentless whole block device with USB transport, writable media, a positive
|
|
207
|
-
size, and 512-byte logical sectors. The device path must be the direct validated
|
|
208
|
-
`/dev/ID` path. Devices with active swap, device-mapper, RAID, LVM, encrypted,
|
|
209
|
-
multipath, or any other non-partition descendants are excluded rather than
|
|
210
|
-
partially dismantled. Mounted ordinary partitions remain selectable so desktop
|
|
211
|
-
auto-mount does not hide a USB.
|
|
212
|
-
|
|
213
|
-
Root, standard system mount paths, home, working directory, app source, Bun
|
|
214
|
-
executable, resolved runtime packages/native assets, tools, and image staging are resolved to filesystem
|
|
215
|
-
major:minor identities with `findmnt`. `lsblk` parent relationships are followed
|
|
216
|
-
to every physical disk, including multi-parent stacks. Attached block devices
|
|
217
|
-
configured in `/etc/fstab` are also protected; every attached match for duplicated
|
|
218
|
-
`UUID`, `LABEL`, `PARTUUID`, or `PARTLABEL` tags is included. Protected filesystem UUIDs expand
|
|
219
|
-
to every attached member, and every member of an active shared-UUID filesystem
|
|
220
|
-
is excluded even when `lsblk` reports its mountpoint on only one member. Discovery
|
|
221
|
-
uses the util-linux 2.37 `SOURCE` column, not newer `SOURCES`. Unknown backing fails
|
|
222
|
-
closed rather than assuming it cannot be a target. A Linux installation running
|
|
223
|
-
from external USB is therefore excluded without assuming a device name.
|
|
224
|
-
|
|
225
|
-
The selected attachment is identified by major:minor, capacity, udev device path,
|
|
226
|
-
block-node device/inode/change time, a hardware-backed `/dev/disk/by-id` link,
|
|
227
|
-
optional udev path/serial, and model. USBs without a current by-id route
|
|
228
|
-
are not offered. Kernel sysfs resolves each whole block device to its nearest
|
|
229
|
-
physical USB parent; every LUN is excluded when safe power-off would affect a
|
|
230
|
-
sibling block device. Identity and eligibility are rechecked after authorization, after unmount, and
|
|
231
|
-
before safe removal. Linux unmounts every mounted target filesystem with
|
|
232
|
-
`umount --all-targets`, without force or lazy detach, then requires all target
|
|
233
|
-
mounts to be gone. It writes through the revalidated by-id route using
|
|
234
|
-
`dd bs=4M conv=fsync`, runs `sync`, refreshes sudo authorization, removes any
|
|
235
|
-
post-write automounts without force, and requires `udisksctl power-off` to succeed
|
|
236
|
-
before claiming the drive is safely powered off. UDisks2 may reject hardware it
|
|
237
|
-
cannot safely power off; its service and selected block object are checked during
|
|
238
|
-
discovery, and a later power-off rejection is reported as an incomplete outcome
|
|
239
|
-
rather than a false success.
|
|
240
|
-
|
|
241
|
-
These repeated checks are not an atomic kernel claim. Do not unplug, swap, or
|
|
242
|
-
mount devices while an operation is running.
|
|
243
|
-
|
|
244
|
-
Cancellation stops the decompressor/input stream, closes the writer's stdin,
|
|
245
|
-
and **waits for the writer to finish its finite buffered tail** before cleanup
|
|
246
|
-
or exit. It does not kill the sudo supervisor and orphan a root writer. If a
|
|
247
|
-
device/driver stalls, stopping can take time: keep the USB connected and wait.
|
|
248
|
-
No force/lazy unmount, forced exit deadline, or automatic safe removal follows
|
|
249
|
-
failure. Use the host platform's safe-removal control for an incomplete USB.
|
|
250
|
-
SIGKILL, power loss and device removal cannot be made safe by application cleanup.
|
|
251
|
-
|
|
252
|
-
## Preview And Status
|
|
253
|
-
|
|
254
|
-
```sh
|
|
255
|
-
bun demo
|
|
256
|
-
bun start --demo=empty
|
|
257
|
-
bun start --demo=error
|
|
258
|
-
bun start --demo=setup
|
|
259
|
-
bun start --demo=setup-gh
|
|
260
|
-
bun start --demo=setup-zstd
|
|
261
|
-
bun start --demo=setup-error
|
|
262
|
-
bun start --demo=setup-interrupted
|
|
263
|
-
bun start --demo=no-homebrew
|
|
264
|
-
bun run typecheck
|
|
265
|
-
bun run test
|
|
266
|
-
bun run test:package
|
|
267
|
-
```
|
|
24
|
+
Choose the target computer’s GPU and USB drive. Boo Flash downloads and verifies the latest qualified image, then erases and writes the selected drive.
|
|
268
25
|
|
|
269
|
-
|
|
270
|
-
IDs, simulated progress and outcomes. They never run disk commands, sudo, a
|
|
271
|
-
writer, Homebrew, package installation or image downloads. The header always
|
|
272
|
-
says `DEMO - no disks written`. Setup previews also label simulated installation.
|
|
273
|
-
These options are for manual UI review, not a test harness.
|
|
274
|
-
`setup-interrupted` simulates a Homebrew interruption result without signaling
|
|
275
|
-
Boo Flash; after the handoff it should quit, not return to setup or load images.
|
|
276
|
-
The card fills compact terminals and is bounded/centered on large ones; below
|
|
277
|
-
40 columns or 16 rows, choices are hidden and Enter cannot approve erasure.
|
|
26
|
+
Requires Node.js 26.4+ or Bun 1.4+.
|
|
278
27
|
|
|
279
|
-
|
|
280
|
-
protection, mounted USBs, post-unmount checks, multi-parent backing storage,
|
|
281
|
-
complex holders, swap, read-only/4Kn/non-USB disks, malformed inventory, unknown
|
|
282
|
-
backing devices, and ambiguous aliases. Typecheck, live production discovery,
|
|
283
|
-
read-only live Linux host inventory, exact npm contents, and clean packed
|
|
284
|
-
`npx`/Node and `bunx`/Bun native-renderer startup/exit are also verified. The
|
|
285
|
-
published runtime dependency tree has zero known npm audit findings. **No macOS or Linux
|
|
286
|
-
hardware flash, real payload write, or physical safe removal has been qualified.**
|
|
287
|
-
Dependency setup and its terminal handoff are likewise only simulated on Linux;
|
|
288
|
-
real Homebrew installation and interruption on macOS remain unqualified.
|
|
289
|
-
Review the source and qualify on an explicitly chosen disposable USB on each host
|
|
290
|
-
platform before relying on it for hardware use.
|
|
28
|
+
## License
|
|
291
29
|
|
|
292
|
-
|
|
293
|
-
[stat manual](https://keith.github.io/xcode-man-pages/stat.1.html),
|
|
294
|
-
[Apple ioreg source](https://github.com/apple-oss-distributions/IOKitTools/blob/main/ioreg.tproj/ioreg.c),
|
|
295
|
-
[Apple registry ID contract](https://github.com/apple-oss-distributions/IOKitUser/blob/main/IOKitLib.h),
|
|
296
|
-
[sudo process/exit contract](https://www.sudo.ws/docs/man/sudo.man/),
|
|
297
|
-
[lsblk manual](https://man7.org/linux/man-pages/man8/lsblk.8.html),
|
|
298
|
-
[findmnt manual](https://man7.org/linux/man-pages/man8/findmnt.8.html),
|
|
299
|
-
[umount manual](https://man7.org/linux/man-pages/man8/umount.8.html), and
|
|
300
|
-
[UDisks documentation](https://storaged.org/doc/udisks2-api/latest/).
|
|
301
|
-
Dependency references: [Homebrew installation](https://docs.brew.sh/Installation),
|
|
302
|
-
[install options/environment](https://docs.brew.sh/Manpage#install-options-formulacask-).
|
|
30
|
+
MIT © 2026 Anomaly
|