buninu-linux 0.7.5 → 0.8.55

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 (47) hide show
  1. package/Dockerfile +5 -2
  2. package/NOTICE.md +110 -49
  3. package/README.md +439 -144
  4. package/fetch-npm.sh +44 -0
  5. package/fetch-plus-build.sh +1 -0
  6. package/index.js +15 -13
  7. package/initramfs/bin/buninu-browser +24 -0
  8. package/initramfs/bin/jspinyin +12 -0
  9. package/initramfs/bin/jspulse +2 -0
  10. package/initramfs/bin/tar +40 -6
  11. package/initramfs/bin/top +1 -7
  12. package/initramfs/buninu/CHANGELOG.md +4 -0
  13. package/initramfs/buninu/apps/bunmsh/CHANGELOG.md +28 -0
  14. package/initramfs/buninu/apps/bunmsh/package.json +1 -1
  15. package/initramfs/buninu/apps/bunmsh/src/main.js +7 -5
  16. package/initramfs/buninu/apps/bunmsh/src/shell.js +584 -75
  17. package/initramfs/buninu/apps/bunmsh/test/shell1.test.js +64 -0
  18. package/initramfs/buninu/package.json +1 -1
  19. package/initramfs/init.js +5 -0
  20. package/initramfs/lib/browser-resources.js +25 -0
  21. package/initramfs/lib/tar-exclude.js +20 -0
  22. package/initramfs/lib/tar-strip.js +94 -0
  23. package/initramfs/lib/top-memory.js +12 -0
  24. package/initramfs/usr/share/doc/buninu-linux/tar.md +24 -1
  25. package/initramfs/usr/share/doc/buninu-linux/top.md +18 -0
  26. package/package.json +1 -1
  27. package/scripts/arch.js +5 -5
  28. package/scripts/arch.sh +5 -5
  29. package/scripts/fetch-npm.js +51 -0
  30. package/scripts/fetch.js +1 -0
  31. package/scripts/js-tools.js +3 -0
  32. package/scripts/npm-packages.md +18 -0
  33. package/scripts/pack-initramfs.sh +1 -0
  34. package/scripts/pack.js +2 -0
  35. package/scripts/stage-npm.js +57 -0
  36. package/scripts/stage-npm.sh +62 -0
  37. package/test/fetch-npm.test.js +92 -0
  38. package/test/host/Dockerfile +6 -4
  39. package/test/host/boot-test.exp +2 -2
  40. package/test/host/host-test.sh +2 -2
  41. package/test/host/in-container.sh +4 -4
  42. package/test/js-tools-selection.test.js +19 -0
  43. package/test/npm-launchers.test.js +59 -0
  44. package/test/stage-npm.test.js +130 -0
  45. package/test/tar-strip.test.js +218 -0
  46. package/test/top-memory.test.js +23 -0
  47. package/initramfs/buninu/apps/bunmsh/test/shell.test.js +0 -2092
package/README.md CHANGED
@@ -44,10 +44,9 @@
44
44
  + See [Multitasking modes](#multitasking-modes)
45
45
  * The graphical terminal `bunterm` draws on the framebuffer with CJK, colour emoji and kitty images; see [Showing images](#showing-images)
46
46
  + Also has mouse click, wheel, and cursor drawing
47
- + Simplified browser works: @sanohiro/casty in chroot debian
48
- + (Use at your own risk: We haven't fully examined its code)
47
+ + Simplified browser works: buninu-browser natively or casty in chroot debian
49
48
  + Playing YouTube with sound (experimental); see [Playing YouTube with sound](#playing-youtube-with-sound-experimental)
50
- + See [Commands inside `/bin`](#commands-inside-bin) for browser usage instructions
49
+ + See [Buninu Browser](#buninu-browser-early-stage-experimental) for the built-in browser, or [Debian and Chromium with casty](#debian-and-chromium-with-casty) for the optional chroot setup
51
50
 
52
51
  ---
53
52
 
@@ -61,58 +60,40 @@
61
60
  > test either an x86_64 or aarch64 guest with `qemu-system` instead, see
62
61
  > [Build and test with QEMU on macOS or Linux](#build-and-test-with-qemu-on-macos-or-linux).
63
62
 
63
+ You can build the image on an Android phone, but the `--real` image below
64
+ boots an x86-64 UEFI computer. It does not install Buninu Linux onto the phone.
65
+
64
66
  - This guide builds a bootable `buninu-linux-<version>.img`
65
- - The documented build environment is Debian 13 under Termux PRoot
66
- - A regular Debian installation works as well.
67
- * Experimental Alpine support now!
68
- - For a source checkout, clone into the Termux home so native Termux and PRoot
69
- can share it; `~` differs between them, but the absolute path is the same.
67
+ - Fetch and build use JS tools by default and need host Bun, not the native
68
+ build toolchain or Docker. There is no need to enter PRoot just to build.
70
69
 
71
70
  ### Steps
72
71
 
73
- - Before anything, install Bun in Debian/Alpine first:
74
-
75
- ```sh
76
- # Debian/Ubuntu
77
- apt update
78
- apt install curl unzip
79
-
80
- # Alpine
81
- apk update
82
- apk add curl unzip bash libgcc libstdc++
72
+ - Install bun first:
73
+ * Android: run these commands in Termux:
83
74
 
84
- curl -fsSL https://bun.sh/install | bash
85
- ```
75
+ ```sh
76
+ pkg update && pkg upgrade
77
+ pkg i npm
78
+ npm i -g bun
79
+ ```
86
80
 
87
- - Small tip: The below `apt install` command shows in the terminal when you run -b without the needed tools
81
+ * Others: Follow the official guide: <https://bun.com>
82
+ - With Bun installed and on `PATH`, choose either build method below.
83
+ * Check by `bun --version`
84
+ - Leave `BUNINU_JS_TOOLS` unset (or set it to `1`); `0`, `off` or `false`
85
+ selects the [old shell build](#old-build-shell-tools) instead.
88
86
 
89
87
  #### Build directly with bun x
90
88
 
91
- Install the build tools, enter a directory where
92
- you want to keep the finished image, then run the published package:
89
+ Enter a directory where you want to keep the finished image, then run the
90
+ published package directly. No `apt install`/`apk add` build tools are needed:
93
91
 
94
92
  ```sh
95
- # Debian/Ubuntu
96
- apt install binutils-mingw-w64-x86-64 cpio curl dosfstools fakeroot mtools parted unzip
97
-
98
- # Alpine
99
- apk add bash coreutils tar curl unzip parted dosfstools mtools libgcc libstdc++
100
-
101
- mkdir -p /data/data/com.termux/files/home/buninu-build
102
- cd /data/data/com.termux/files/home/buninu-build
103
-
104
- export PATH=$HOME/.bun/bin:$PATH
105
-
93
+ mkdir -p buninu-build
94
+ cd buninu-build
106
95
  bun x buninu-linux --version
107
-
108
- # Debian/Ubuntu
109
96
  bun x buninu-linux -fb --real --export
110
-
111
- # Alpine
112
- export BUNINU_JS_CPIO=1
113
- export BUNINU_JS_UKI=1
114
- bun x buninu-linux -fb --real --export
115
-
116
97
  ```
117
98
 
118
99
  `--export` copies the completed `vda.img` out of bunx's package directory and
@@ -122,35 +103,86 @@ command when writing the USB drive.
122
103
 
123
104
  #### Or build from a source checkout
124
105
 
125
- In native Termux:
126
-
127
- - git clone https://github.com/jjtseng93/buninu-linux.git ~/buninu-linux
106
+ With Git and Bun available:
128
107
 
129
- In Debian 13 under PRoot:
108
+ ```sh
109
+ git clone https://github.com/jjtseng93/buninu-linux.git buninu-linux
110
+ cd buninu-linux
111
+ bun ./index.js -fb --real --export
112
+ ```
130
113
 
131
- - apt install binutils-mingw-w64-x86-64 cpio curl dosfstools fakeroot mtools parted unzip
132
- - cd /data/data/com.termux/files/home/buninu-linux
133
- - bun ./index.js -fb --real --export
134
- * Fetches from Alpine/Bun
135
- * Selects the physical-hardware modules
136
- * Builds `vda.img`
137
- * Exports it to `buninu-linux-<version>.img`
114
+ This fetches the pinned Alpine/Bun/npm inputs, selects the physical-hardware
115
+ modules, builds `vda.img`, and exports `buninu-linux-<version>.img`.
138
116
 
139
117
  #### Write the image to a USB drive
140
118
 
141
- Write the complete exported image (or `vda.img` when not using `--export`), not
142
- the FAT partition inside it, to a USB drive. The source filename below is an
143
- example; replace it with the exact name printed by the build. The destination
144
- is also only an example: identify the correct whole-disk device first, because
145
- this overwrites it completely.
119
+ The recommended method is **Ventoy**: install it on the USB drive once using
120
+ a Windows or Linux computer, then copy image files onto it from Android,
121
+ Linux, macOS or Windows. For later builds, simply copy the new `.img` file
122
+ onto the same drive; there is no need to flash or reformat it each time.
123
+ You can keep multiple images and choose one from Ventoy's boot menu.
124
+
125
+ On Android, first make the exported image accessible to your file manager.
126
+ Run `termux-setup-storage` and accept the storage permission prompt, or allow
127
+ Termux to manage all files in Android's app settings if that option is
128
+ available. From the directory containing the exported image, copy it to
129
+ Download:
130
+
131
+ ```sh
132
+ termux-setup-storage
133
+ cp buninu-linux-*.img /sdcard/Download/
134
+ ```
135
+
136
+ Use the complete exported `.img` (or `vda.img` when not using `--export`),
137
+ not the FAT partition inside it. Replace the example filename below with the
138
+ exact name printed by the build.
139
+
140
+ **Android / Termux: copy to a prepared Ventoy drive.** Ordinary non-root
141
+ Android/Termux cannot directly access a USB block device with `dd`; PRoot
142
+ does not grant that access either. One option is to install
143
+ [Ventoy on the USB drive using a Windows or Linux computer](https://www.ventoy.net/en/doc_start.html)
144
+ first, then connect it to Android via USB OTG and use a file manager to copy
145
+ the `.img` onto Ventoy's data partition. Safely eject it, boot the target PC from the USB
146
+ drive, and select the image in Ventoy's menu. Ventoy supports `.img` files;
147
+ no extraction or renaming to `.iso` is needed.
148
+
149
+ ---
150
+
151
+ Installing Ventoy initially erases the selected USB drive. Later copying an
152
+ image file onto it does not require reformatting. Do not use `dd` or Rufus
153
+ on that drive if you want to preserve its Ventoy installation.
154
+
155
+ Choose either Ventoy or direct image writing, not both. If you used Ventoy,
156
+ skip the Linux/macOS/Windows direct-write methods below and continue to
157
+ [Booting from the USB drive](#booting-from-the-usb-drive).
158
+
159
+ **Linux: write directly with `dd`.** Identify the USB drive with `lsblk` and
160
+ unmount its mounted partitions first. `/dev/sdX` below means the whole disk,
161
+ not a partition such as `/dev/sdX1`. This overwrites the destination disk,
162
+ including its partition table and existing files; check the device carefully.
146
163
 
147
164
  ```sh
148
165
  sudo dd if='buninu-linux-<version>.img' of=/dev/sdX bs=4M conv=fsync status=progress
149
166
  ```
150
167
 
151
- Alternatively, copy the exported `.img` file to a
152
- [Ventoy](https://www.ventoy.net/en/index.html) USB drive and select it from
153
- Ventoy's boot menu.
168
+ **macOS: write directly with `dd`.** Use `diskutil list` to identify the USB
169
+ drive, then substitute its actual disk number for `N` below. The same
170
+ whole-disk overwrite warning applies. Use macOS's `bs=4m` spelling; press
171
+ `Ctrl-T` during the copy to request progress.
172
+
173
+ ```sh
174
+ diskutil list
175
+ diskutil unmountDisk /dev/diskN
176
+ sudo dd if='buninu-linux-<version>.img' of=/dev/rdiskN bs=4m
177
+ sync
178
+ diskutil eject /dev/diskN
179
+ ```
180
+
181
+ **Windows: write with [Rufus](https://rufus.ie/).** Rufus supports raw `.img`
182
+ disk images, not just ISO files (see its [official FAQ](https://github.com/pbatard/rufus/wiki/FAQ#openbsd)).
183
+ Select the correct USB device, select the exported `.img` as the boot image,
184
+ and start writing. Use DD/raw-image mode if prompted. This overwrites the
185
+ selected USB drive; no conversion to `.iso` is needed.
154
186
 
155
187
  #### Booting from the USB drive
156
188
 
@@ -181,6 +213,17 @@ cfg.sound // all packaged ALSA sound modules and detected sound devices
181
213
  start()
182
214
  ```
183
215
 
216
+ Once `start()` opens the Buninu shell, run:
217
+
218
+ ```sh
219
+ bunterm 2
220
+ ```
221
+
222
+ This opens the graphical terminal on virtual console 2 and switches to it.
223
+ It supports Chinese text, emoji and the browser's terminal graphics. Use
224
+ `Ctrl+Alt+F1` to return to the original console and `Ctrl+Alt+F2` to return
225
+ to this terminal.
226
+
184
227
  There is no DHCP client yet; configure a detected wired interface with `ip` as
185
228
  described under [Basic configuration](#basic-configuration). Run `poweroff` for a synced
186
229
  shutdown. After editing the initramfs, `bun ./index.js -b --real --export` rebuilds the
@@ -193,6 +236,11 @@ image; `-h` lists all flags.
193
236
  > an image for real x86-64 UEFI hardware, follow [Quick start](#quick-start)
194
237
  > above and use `-fb --real --export`.
195
238
 
239
+ The commands in this section assume you have cloned the source and changed
240
+ into its directory, as in [Or build from a source checkout](#or-build-from-a-source-checkout).
241
+ You do not need to run that section's `--real` build first. Bun must be on
242
+ `PATH`; install QEMU as shown below.
243
+
196
244
  The same `index.js` builds and boots Buninu Linux in QEMU on a Mac or Linux
197
245
  host. `--arch` picks the guest:
198
246
 
@@ -208,15 +256,15 @@ host. `--arch` picks the guest:
208
256
 
209
257
  #### macOS
210
258
 
211
- This project does not currently support a native macOS build toolchain (GNU
212
- cpio and tar, `fakeroot`, `parted`, PE-aware binutils), so on a Mac `index.js`
213
- always runs the fetch and build stages in a Debian 13 container built from
259
+ The default JS tools build directly on macOS with host Bun, without Docker.
260
+ If you opt out with `BUNINU_JS_TOOLS=0`, `index.js` runs the shell fetch and
261
+ build stages in a Debian-based `oven/bun:1.4.2` container built from
214
262
  [`Dockerfile`](Dockerfile), with the checkout bind-mounted. The image is built
215
263
  on first use and tagged with a hash of the Dockerfile. Only the run stage uses
216
- the Mac itself:
264
+ the Mac itself in that shell-tools mode:
217
265
 
218
266
  ```sh
219
- # Docker Desktop (running) for -f/-b, QEMU and its UEFI firmware for -r
267
+ # Host Bun for -f/-b; QEMU and its UEFI firmware for -r
220
268
  brew install qemu
221
269
 
222
270
  # Apple Silicon: Hypervisor.framework accelerates the aarch64 guest
@@ -234,19 +282,20 @@ To run `bunterm` in a QEMU window on the aarch64 guest, see
234
282
 
235
283
  #### amd64 Linux
236
284
 
237
- On Debian or Ubuntu the build runs on the host exactly as in PRoot, and QEMU
238
- uses KVM for the x86_64 guest when the user can open `/dev/kvm`:
285
+ On Debian or Ubuntu, the default JS build needs host Bun, not the native
286
+ build toolchain. QEMU uses KVM for the x86_64 guest when the user can open
287
+ `/dev/kvm`. Install QEMU and its firmware, then build and boot:
239
288
 
240
289
  ```sh
241
- apt install binutils-mingw-w64-x86-64 cpio curl dosfstools fakeroot mtools parted unzip
242
- apt install qemu-system-x86 ovmf
290
+ sudo apt install qemu-system-x86 ovmf
243
291
  bun ./index.js -fbr
244
292
  ```
245
293
 
246
- Pass `--docker` to build in the same container as macOS instead of installing
247
- the build packages; the aarch64 guest additionally needs
248
- `binutils-aarch64-linux-gnu` for a host build and `qemu-system-arm
249
- qemu-efi-aarch64` to run.
294
+ To run an aarch64 guest, additionally install `qemu-system-arm` and
295
+ `qemu-efi-aarch64`. Cross-binutils are not needed for the default JS build.
296
+ For the optional [old shell build](#old-build-shell-tools), install its native
297
+ toolchain (including `binutils-aarch64-linux-gnu` for aarch64), or set
298
+ `BUNINU_JS_TOOLS=0` and pass `--docker` to use the build container instead.
250
299
 
251
300
  #### What differs on aarch64
252
301
 
@@ -290,9 +339,9 @@ qemu-efi-aarch64` to run.
290
339
  #### Testing on a Linux host in Docker
291
340
 
292
341
  `test/host/host-test.sh` checks the Linux-host path from any machine with
293
- Docker: it starts a fresh Debian 13 container of the chosen CPU with the
342
+ Docker: it starts a fresh `oven/bun:1.4.2` container of the chosen CPU with the
294
343
  build packages above and QEMU, clones the committed `HEAD` of this checkout,
295
- builds both guests with that toolchain (not `--docker`) and boots each one,
344
+ builds both guests with Bun and the default JS tools (not nested `--docker`) and boots each one,
296
345
  driving the serial console through `test/host/boot-test.exp`:
297
346
 
298
347
  ```sh
@@ -546,25 +595,25 @@ For Chinese input, run the pinyin input method
546
595
  that is not inside a chroot, so it uses Buninu's `xclip`:
547
596
 
548
597
  ```sh
549
- bun x @drxiaozhi/jspinyin
598
+ jspinyin
550
599
  ```
551
600
 
552
601
  - jspinyin → casty: press `Ctrl-C` in jspinyin to copy its result box, then
553
- `Ctrl-V` in casty pastes it through OSC 52.
602
+ `Ctrl-V` or `Ctrl-E paste` in casty pastes it through OSC 52.
554
603
  - casty → jsmdcui / jspinyin: `Alt-C` in casty copies the selection through
555
604
  OSC 52, and `Ctrl-V` pastes it in jsmdcui or jspinyin, since jsmdcui reads
556
605
  from `xclip` first by default.
557
606
 
558
607
  ### Playing YouTube with sound (experimental)
559
608
 
560
- [jspulse](https://www.npmjs.com/package/@drxiaozhi/jspulse) is a
609
+ [jspulse](https://github.com/jjtseng93/jspulse), now a built-in, is a
561
610
  PulseAudio-compatible sound server written for Bun. It runs natively in
562
611
  Buninu, outside any chroot, and plays through ALSA. Chromium-based programs
563
612
  such as `casty` inside the Debian chroot connect to it over `127.0.0.1`,
564
613
  because a chroot shares Buninu's network. Several programs can play at once.
565
614
 
566
615
  This assumes the Debian chroot and `casty` from
567
- [Commands inside /bin](#commands-inside-bin) are already set up, with the
616
+ [Debian and Chromium with casty](#debian-and-chromium-with-casty) are already set up, with the
568
617
  chroot shell on tty2. `bun x` needs network access; see
569
618
  [Basic configuration](#basic-configuration).
570
619
 
@@ -593,15 +642,18 @@ chroot shell on tty2. `bun x` needs network access; see
593
642
  the percentage afterwards if it is too quiet or too loud:
594
643
 
595
644
  ```sh
596
- bun x @drxiaozhi/jspulse --volume 50
597
- bun x @drxiaozhi/jspulse --play
645
+ jspulse --volume 50
646
+ jspulse --play
598
647
  ```
599
648
 
600
649
  4. **Start the sound server.** It keeps running in the foreground, so leave
601
650
  this terminal as it is; `Ctrl+C` stops it:
602
651
 
603
652
  ```sh
604
- bun x @drxiaozhi/jspulse --alsa
653
+ jspulse --alsa
654
+
655
+ # or start in the background
656
+ jspulse --alsa &
605
657
  ```
606
658
 
607
659
  5. **Start casty with sound.** Press `Ctrl+Alt+F2` to return to the chroot
@@ -613,6 +665,18 @@ chroot shell on tty2. `bun x` needs network access; see
613
665
  bun casty.js https://www.youtube.com
614
666
  ```
615
667
 
668
+ Alternatively, the built-in `buninu-browser` runs directly in a native
669
+ Buninu `bunterm`, outside the chroot, and uses the same running jspulse
670
+ server. It is still in an early experimental stage, but can play an
671
+ individual video, for example:
672
+
673
+ ```sh
674
+ buninu-browser https://youtu.be/jf-pn0a-Twk
675
+ ```
676
+
677
+ Playback may still fail or be unstable; this does not imply full YouTube
678
+ compatibility.
679
+
616
680
  If there is no sound, check step 4's terminal for errors, and make sure
617
681
  `PULSE_SERVER` was exported in the same shell that started casty.
618
682
 
@@ -621,6 +685,9 @@ If there is no sound, check step 4's terminal for errors, and make sure
621
685
  | command | does | manual |
622
686
  | --- | --- | --- |
623
687
  | `buninu-linux-help` | render this buninu-linux README from `/usr/share/doc/buninu-linux/README.md` | `buninu-linux-help` |
688
+ | `buninu-browser` | early-stage, experimental JavaScript/WASM browser with the bundled casty terminal frontend; not yet a general-purpose browser replacement | `buninu-browser --help` |
689
+ | `jspulse` | PulseAudio-compatible audio server and ALSA mixer controls; use `--alsa` on Buninu Linux | `jspulse --help` |
690
+ | `jspinyin` | Chinese pinyin input panel, opened with the system jsmdcui in TUI mode; not a system-wide input method | — |
624
691
  | `mount` | `mount(2)` with type detection, `-o` parsing, `LABEL=`/`UUID=`, bind/move/remount; loads required filesystem and disk modules | `mount --help` → `/usr/share/doc/buninu-linux/mount.md` |
625
692
  | `umount` | `umount2(2)` with `-l`, `-f`, `-R` | `umount --help` |
626
693
  | `ip` | iproute2 grammar over `SIOC*` ioctls and `/proc/net`: `link`, `addr`, `route`, `neigh` | `ip --help` |
@@ -629,12 +696,46 @@ If there is no sound, check step 4's terminal for errors, and make sure
629
696
  | `poweroff` | sync pending writes and power off through the Linux reboot system call | `poweroff --help` |
630
697
  | `reboot` | sync pending writes and restart through the shared Linux reboot logic | `reboot --help` |
631
698
  | `tar` | create, extract, or list tar archives with gzip and zstd compression through `Bun.Archive` | `tar --help` |
699
+ | `gzip`, `gunzip`, `zcat` | compress or decompress gzip files, including decompression to stdout | `gzip --help` |
700
+ | `unzip` | list or extract ZIP archives, or write a member to stdout with `-p` | `unzip --help` |
701
+ | `truncate` | resize files, including sparse files | `truncate --help` |
702
+ | `dd` | copy blocks between files with offsets, size limits and sparse-output support | `dd --help` |
703
+ | `mkfs.fat` | format a FAT32 filesystem in a disk image | `mkfs.fat --help` |
704
+ | `mmd`, `mcopy`, `mdir` | create directories, copy files and list contents in a FAT image without mounting it; use `-i IMAGE` and `::/path` | — |
705
+ | `parted` | create and inspect GPT partitions in a disk image; script-mode subset | `parted --help` |
632
706
  | `stripansi` | remove ANSI escape sequences from stdin, `-`, or one or more files and concatenate the results | — |
633
707
  | `chroot` | `chroot(2)` into another root directory, mounting `/proc`, `/sys`, `/dev`, `/dev/pts`, `/run`, `/tmp` and `/etc/resolv.conf` for you and unmounting them afterwards | `chroot --help` |
634
708
  | `bunterm` | a graphical terminal on the framebuffer: Skia (CanvasKit) text with CJK, colour emoji, seamless box drawing, kitty graphics images, with the mouse working, wheel scrollback included (`--no-mouse` turns it off); xterm.js's emulator core over Bun's built-in PTY | `bunterm --help` |
635
709
 
636
- Besides `bun` (and `sh`/`node` pointing at it), `/bin` includes twelve commands
637
- implemented as Bun scripts.
710
+ Besides `bun` (and `sh`/`node` pointing at it), `/bin` includes the commands
711
+ above, implemented as Bun scripts or thin launchers for bundled packages.
712
+
713
+ For Debian/Alpine rootfs and Chromium examples, see
714
+ [Optional chroot and native binaries](#optional-chroot-and-native-binaries).
715
+
716
+ ### Buninu Browser (early-stage, experimental)
717
+
718
+ `buninu-browser` is still in an early stage. Websites may render incorrectly
719
+ or fail to load or play media; it is not yet a general-purpose browser
720
+ replacement. Run it inside `bunterm` (or another Kitty-graphics terminal).
721
+ The browser and casty are bundled; these commands do not install them from npm.
722
+
723
+ ```sh
724
+ # Open the Buninu website (requires network access)
725
+ buninu-browser buninu.org
726
+
727
+ # Open the browser's built-in audio test page
728
+ buninu-browser about:audio
729
+ ```
730
+
731
+ For audio output, first load sound drivers with `cfg.sound` at the PID 1
732
+ REPL, then run `jspulse --alsa` in another terminal or use `jspulse --alsa &` to run in the background. In the browser terminal:
733
+
734
+ ```sh
735
+ buninu-browser about:audio
736
+ ```
737
+
738
+ ### Archive tools and other examples
638
739
 
639
740
  The small `tar` reads the archive's own headers for links and listing, so
640
741
  extraction restores directories, hard links and every symbolic link —
@@ -644,7 +745,7 @@ only regular files. Creation still follows the `Bun.Archive` boundary: it
644
745
  stores regular files but not Unix metadata, links, or empty directories. It
645
746
  supports gzip and Bun's built-in zstd, not xz or bzip2.
646
747
 
647
- - `--help` renders each Markdown manual in the terminal.
748
+ - Where provided, `--help` shows the command's help or renders its Markdown manual.
648
749
  - The `bun x` examples below require network access:
649
750
  * `bun x` downloads the requested program from the npm registry and runs it without installing it permanently.
650
751
  * If they fail the 1st time, try `bun pm cache rm`
@@ -668,6 +769,57 @@ bun x bunproot --git --readme | stripansi | jmi
668
769
 
669
770
 
670
771
 
772
+ ip link set eth0 up
773
+ ip addr add 192.168.1.50/24 dev eth0
774
+ ip route add default via 192.168.1.1
775
+
776
+ ip -br addr && ip route
777
+ ip addr replace 192.168.1.50/24 dev eth0
778
+ ip route replace default via 192.168.1.1
779
+
780
+ ps -eo pid,args
781
+ ps -ef
782
+ ps aux
783
+ pspac
784
+ top
785
+ top -b -n 1
786
+
787
+ poweroff
788
+ reboot
789
+
790
+ tar cvf /tmp/buninu.tar README.md package.json
791
+ tar tvf /tmp/buninu.tar
792
+ mkdir -p /tmp/buninu-copy
793
+ tar xvf /tmp/buninu.tar -C /tmp/buninu-copy
794
+
795
+ # Add z to create a gzip-compressed archive
796
+ tar czvf /tmp/buninu.tar.gz README.md package.json
797
+
798
+ # On another virtual console: a graphical terminal with CJK, emoji and images
799
+ bunterm 2
800
+ bunterm /dev/tty3 --font-size 13 -e bun /buninu/apps/jsmdcui/src/index.js --demo
801
+ ```
802
+
803
+ The graphics stack behind `bunterm` — the framebuffer module, CanvasKit,
804
+ the fonts and the terminal — is described in [graphics.md](graphics.md).
805
+
806
+ ## Optional chroot and native binaries
807
+
808
+ These optional examples download and run native Linux binaries, including
809
+ Debian/Alpine utilities and Chromium. They are outside Buninu Linux's
810
+ JS/WASM userspace-tooling approach and are not part of its default bundled
811
+ applications. Skip this section if you want to use only the JS/WASM tools.
812
+ The built-in `chroot` command itself is a Bun script; programs run inside
813
+ the selected root filesystem need not be JavaScript or WebAssembly.
814
+
815
+ A chroot shares the host kernel and is not a security sandbox. Use trusted
816
+ root filesystems and software. Downloads require network access. The
817
+ Debian and Alpine examples below target x86-64; chroot does not emulate
818
+ another CPU architecture.
819
+
820
+ ### Debian and Chromium with casty
821
+
822
+ ```sh
671
823
  # Download and enter an x64 Debian rootfs
672
824
  # Make sure you have run this already:
673
825
  # bunterm 2 --font-size 13
@@ -681,29 +833,25 @@ apt update
681
833
  apt install --no-install-recommends ca-certificates curl unzip chromium-headless-shell fonts-noto-cjk fonts-noto-color-emoji git
682
834
  curl -fsSL https://bun.sh/install | bash
683
835
  bun x bunmsh
684
- # We haven't fully reviewed
685
- # @sanohiro/casty's safety
836
+ # The original casty is
837
+ # @sanohiro/casty
686
838
  # below is a fork of mine
687
- # fixing some issues
688
- # !!!Use at your own risk!!!
689
- # !!!Use at your own risk!!!
690
- # !!!Use at your own risk!!!
691
- # !!!Use at your own risk!!!
692
- # !!!Use at your own risk!!!
693
- # !!!Use at your own risk!!!
694
- # !!!Use at your own risk!!!
695
- # !!!Use at your own risk!!!
696
- # !!!Use at your own risk!!!
697
- # !!!Use at your own risk!!!
839
+ # fixing some issues and adding functions
698
840
  cd
699
841
  git clone https://github.com/jjtseng93/casty
700
842
  cd casty/bin
701
- # When clicking around, don’t release the mouse button immediately after pressing it, to make sure the mouse-down event is triggered
843
+
702
844
  bun casty.js buninu.org
703
845
  # For sound in casty (YouTube), start jspulse first:
704
846
  # see "Playing YouTube with sound (experimental)" under "Using Buninu Linux"
847
+ ```
848
+
849
+ For audio setup, see
850
+ [Playing YouTube with sound (experimental)](#playing-youtube-with-sound-experimental).
705
851
 
852
+ ### Alpine minirootfs
706
853
 
854
+ ```sh
707
855
  # Download and enter an x64 Alpine minirootfs
708
856
  bun x bunproot --download-alpine-x64
709
857
  mkdir alpine
@@ -712,52 +860,24 @@ tar xvf ../alpine-minirootfs-*-x86_64.tar.gz
712
860
  cp $(which bun) bin
713
861
  chroot .
714
862
  apk add libgcc libstdc++
863
+ ```
715
864
 
865
+ ### An existing root filesystem
716
866
 
867
+ ```sh
717
868
  # Enter a root filesystem on a disk. /proc, /sys, /dev, /dev/pts, /run, /tmp
718
869
  # and /etc/resolv.conf are mounted for you and removed again on exit
719
870
  chroot /mnt
720
871
  chroot /mnt /bin/bun --version
721
872
  chroot -n /mnt /bin/sh # traditional: mount nothing
722
-
723
-
724
-
725
- ip link set eth0 up
726
- ip addr add 192.168.1.50/24 dev eth0
727
- ip route add default via 192.168.1.1
728
-
729
- ip -br addr && ip route
730
- ip addr replace 192.168.1.50/24 dev eth0
731
- ip route replace default via 192.168.1.1
732
-
733
- ps -eo pid,args
734
- ps -ef
735
- ps aux
736
- pspac
737
- top
738
- top -b -n 1
739
-
740
- poweroff
741
- reboot
742
-
743
- tar cvf /tmp/buninu.tar README.md package.json
744
- tar tvf /tmp/buninu.tar
745
- mkdir -p /tmp/buninu-copy
746
- tar xvf /tmp/buninu.tar -C /tmp/buninu-copy
747
-
748
- # Add z to create a gzip-compressed archive
749
- tar czvf /tmp/buninu.tar.gz README.md package.json
750
-
751
- # On another virtual console: a graphical terminal with CJK, emoji and images
752
- bunterm 2
753
- bunterm /dev/tty3 --font-size 13 -e bun /buninu/apps/jsmdcui/src/index.js --demo
754
873
  ```
755
874
 
756
- The graphics stack behind `bunterm` — the framebuffer module, CanvasKit,
757
- the fonts and the terminal — is described in [graphics.md](graphics.md).
758
-
759
875
  ## Environment and dependencies
760
876
 
877
+ The default JS build uses host Bun. The native build-tool dependencies below
878
+ apply to the [old shell build](#old-build-shell-tools), the optional Docker
879
+ shell toolchain, and the separate native hello-world example.
880
+
761
881
  ### Build environment
762
882
 
763
883
  The baseline is the stock Debian 13 (trixie) OCI image, which is also what this
@@ -825,6 +945,82 @@ The retired `test/build-init-bootstrap.sh` also needs `clang lld`. It compiles
825
945
  the historical freestanding x86-64 `/init`; the current Buninu Linux path does
826
946
  not use or compile it.
827
947
 
948
+ ## Old build (shell tools)
949
+
950
+ These are the previous native-toolchain build instructions, retained as an
951
+ optional alternative to the default JS tools. Set `BUNINU_JS_TOOLS=0`
952
+ explicitly to use them. The documented environment is Debian 13 under Termux
953
+ PRoot or a regular Debian/Ubuntu installation; the Alpine route is experimental.
954
+ Missing shell build tools are reported before the selected stages run.
955
+
956
+ - For a source checkout, clone into the Termux home so native Termux and PRoot
957
+ can share it; `~` differs between them, but the absolute path is the same.
958
+ - Before anything, install Bun in Debian/Alpine first:
959
+
960
+ ```sh
961
+ # Debian/Ubuntu
962
+ apt update
963
+ apt install curl unzip
964
+
965
+ # Alpine
966
+ apk update
967
+ apk add curl unzip bash libgcc libstdc++
968
+
969
+ curl -fsSL https://bun.sh/install | bash
970
+ ```
971
+
972
+ ### Old build directly with bun x
973
+
974
+ Install the build tools, enter a directory where you want to keep the
975
+ finished image, then run the published package:
976
+
977
+ ```sh
978
+ # Debian/Ubuntu
979
+ apt install binutils-mingw-w64-x86-64 cpio curl dosfstools fakeroot mtools parted unzip
980
+
981
+ # Alpine
982
+ apk add bash coreutils tar curl unzip parted dosfstools mtools libgcc libstdc++
983
+
984
+ mkdir -p /data/data/com.termux/files/home/buninu-build
985
+ cd /data/data/com.termux/files/home/buninu-build
986
+
987
+ export PATH=$HOME/.bun/bin:$PATH
988
+ export BUNINU_JS_TOOLS=0
989
+
990
+ bun x buninu-linux --version
991
+
992
+ # Debian/Ubuntu
993
+ bun x buninu-linux -fb --real --export
994
+
995
+ # Alpine: use JS for cpio and UKI assembly within the shell pipeline
996
+ export BUNINU_JS_CPIO=1
997
+ export BUNINU_JS_UKI=1
998
+ bun x buninu-linux -fb --real --export
999
+ ```
1000
+
1001
+ `--export` copies the completed `vda.img` out of bunx's package directory into
1002
+ the invocation directory as `buninu-linux-<version>.img`.
1003
+
1004
+ ### Old build from a source checkout
1005
+
1006
+ In native Termux:
1007
+
1008
+ ```sh
1009
+ git clone https://github.com/jjtseng93/buninu-linux.git ~/buninu-linux
1010
+ ```
1011
+
1012
+ In Debian 13 under PRoot:
1013
+
1014
+ ```sh
1015
+ apt install binutils-mingw-w64-x86-64 cpio curl dosfstools fakeroot mtools parted unzip
1016
+ cd /data/data/com.termux/files/home/buninu-linux
1017
+ BUNINU_JS_TOOLS=0 bun ./index.js -fb --real --export
1018
+ ```
1019
+
1020
+ This fetches the pinned inputs, selects the physical-hardware modules, builds
1021
+ `vda.img`, and exports `buninu-linux-<version>.img`. Continue with
1022
+ [Write the image to a USB drive](#write-the-image-to-a-usb-drive).
1023
+
828
1024
  ## Implementation details
829
1025
 
830
1026
  ### 1. Hello world
@@ -862,12 +1058,19 @@ it too). Its physical-image stages run as fetch → build:
862
1058
 
863
1059
  #### Build flags
864
1060
 
1061
+ Fetch and build default to JS tools. Host Bun is required for npm extraction.
1062
+ Only `BUNINU_JS_TOOLS=0`, `off` or `false` disables this route (case-insensitive,
1063
+ with surrounding whitespace ignored); unset or empty values keep it enabled.
1064
+ JS tools bypass Docker, even with `--docker`. To use the container toolchain,
1065
+ run `BUNINU_JS_TOOLS=0 bun index.js -fb --docker`. The run stage still uses
1066
+ `run-qemu.sh` and host QEMU.
1067
+
865
1068
  | flag | runs | use it when |
866
1069
  | --- | --- | --- |
867
- | `-f`, `--fetch` | `fetch-alpine.sh`, `fetch-bun.sh` | first clone, or after bumping a pinned version |
868
- | `-b`, `--build` | `build-uki.sh`, `build-image.sh` | after editing `initramfs/init.js` or the kernel command line |
1070
+ | `-f`, `--fetch` | `scripts/fetch.js` by default; shell route: `fetch-alpine.sh`, `fetch-bun.sh`, `fetch-npm.sh` | first clone, or after bumping a pinned version |
1071
+ | `-b`, `--build` | `scripts/build.js` by default; shell route: `build-uki.sh`, `build-image.sh` | after editing `initramfs/init.js` or the kernel command line |
869
1072
  | `--arch ARCH` | explicitly selects `x86_64` (default for fetch/build) or `aarch64`; a bare `-r` detects the last built UKI | building or running a particular guest architecture |
870
- | `--docker` | `-f`/`-b` inside the container from `Dockerfile` (always on macOS) | no Debian toolchain on the host |
1073
+ | `--docker` | with JS tools disabled, `-f`/`-b` inside the container from `Dockerfile` (automatic on macOS in shell mode) | use the shell toolchain without installing it on the host |
871
1074
 
872
1075
  `--export` is a post-build option: after `-b` finishes, it copies `vda.img` to
873
1076
  the directory where the command was invoked as
@@ -892,9 +1095,10 @@ its own.
892
1095
 
893
1096
  ```text
894
1097
  index.js entry point: -f / -b / -r / --arch / --docker / --export / --linux-lts / --real
895
- Dockerfile the Debian 13 build toolchain for --docker (and macOS)
1098
+ Dockerfile Debian-based oven/bun:1.4.2 plus the shell build toolchain
896
1099
  fetch-alpine.sh [fetch] kernel, EFI stub, musl, network/input/display modules
897
1100
  fetch-bun.sh [fetch] Bun, libstdc++, libgcc
1101
+ fetch-npm.sh [fetch] pinned browser, casty, jspulse and jspinyin tarballs (download only)
898
1102
  build-uki.sh [build] UKI; calls scripts/pack-initramfs.sh
899
1103
  build-image.sh [build] GPT disk image; shared with the hello-world EFI
900
1104
  run-qemu.sh [run] QEMU q35 (x86_64) or virt (aarch64), KVM/HVF/TCG
@@ -908,7 +1112,7 @@ initramfs/ init.js, commands, userspace: the same for every archi
908
1112
  native/<arch>/ musl and the GCC runtime (committed); bun and modules (fetched)
909
1113
  ```
910
1114
 
911
- The `--real` inputs are Alpine v3.24 `linux-lts-6.18.54-r0`, musl `1.2.6-r2`,
1115
+ The `--real` inputs are Alpine v3.24 `linux-lts-6.18.55-r0`, musl `1.2.6-r2`,
912
1116
  `systemd-efistub-260.2-r0`, `libstdc++`/`libgcc` `15.2.0-r5`, and Bun 1.4.2
913
1117
  `linux-x64-musl-baseline`. The aarch64 guest uses the same versions from
914
1118
  Alpine's aarch64 repository and Bun's `linux-aarch64-musl`. There is no BusyBox
@@ -922,6 +1126,70 @@ tampered with is fetched again and has to pass the same hash before a script
922
1126
  extracts from it. Bumping a version changes both the file name and the hash, so
923
1127
  it always refetches.
924
1128
 
1129
+ The four application packages are pinned separately in
1130
+ `scripts/npm-packages.md`: `buninu-browser@0.2.2`,
1131
+ `@drxiaozhi/casty@1.3.4`, `@drxiaozhi/jspulse@0.2.1`, and
1132
+ `@drxiaozhi/jspinyin@0.1.1`. These were npm's `latest` versions when checked
1133
+ on 2026-10-11; fetch never resolves `latest` or a version range at runtime.
1134
+ Each registry tarball was checked against its published SHA-512 integrity
1135
+ before its SHA-256 was recorded in the shared pins file.
1136
+
1137
+ The manifest uses fixed YAML-compatible blocks: a double-quoted
1138
+ `"package@version":` header, followed by two ` - ` lines containing the
1139
+ registry URL and `sha256:HEX`. Blank lines and `#` comments are allowed.
1140
+ The `.md` extension lets `bun scripts/npm-packages.md` display the list.
1141
+ Bun parses it with `Bun.YAML.parse`; Node and shell also support the same
1142
+ strict format without installing a YAML parser. Cache filenames are derived
1143
+ from the package name and version, preserving the existing cache names.
1144
+
1145
+ Both fetch routes download them directly from `registry.npmjs.org` into
1146
+ `downloads/npm/`, shared by x86_64 and aarch64, and verify the pinned SHA-256
1147
+ on cache hits as well as downloads. No npm/Bun package installation,
1148
+ lifecycle scripts or dependency resolution runs during fetch.
1149
+
1150
+ At pack time, `scripts/stage-npm.js` (JS tools) or `scripts/stage-npm.sh`
1151
+ (shell tools) rechecks SHA-256 and extracts each archive with one leading
1152
+ component removed into the staging tree's `/usr/lib/node_modules/<package>`.
1153
+ Scoped names retain their `@scope/name` directories. No install scripts or
1154
+ dependency resolution run. JS extraction uses the initramfs JS `tar` and
1155
+ requires a host Bun; shell/Docker extraction uses the host `tar`, without Bun.
1156
+ The source `initramfs/` and project `package.json` are not modified by packing.
1157
+
1158
+ The image gets `/usr/lib/package.json` with the four exact dependencies and
1159
+ standard `node_modules/.bin` links. This reserves a normal package-manager
1160
+ layout for later `cd /usr/lib` and `bun i --backend=copyfile`; no lockfile is
1161
+ fabricated. `bun i` alone retains the pinned versions, not newer releases.
1162
+ Persistence across boots and a package-update command are not implemented here.
1163
+
1164
+ Only `buninu-browser` excludes `package/usr/lib/canvaskit` and
1165
+ `package/usr/share/fonts` when unpacked; `usr/README.md` and other contents
1166
+ are retained. The distribution's
1167
+ `/bin/buninu-browser` launcher creates missing resource directories and relative
1168
+ links on startup: package `usr/lib/canvaskit` points to `/lib/canvaskit`, and
1169
+ package `usr/share/fonts` points to `/usr/share/fonts`. Existing resources are
1170
+ left untouched, including resources restored by a later npm installation.
1171
+ The launcher runs the packaged casty directly, without `bunx`/`npx` downloads;
1172
+ other frontends/options are delegated to the package launcher. Use this
1173
+ distribution command for resource setup; calling the npm entry directly
1174
+ bypasses the hook. The extracted packages are otherwise unmodified, including
1175
+ their license/source files. This step does not start services or integrate
1176
+ jspinyin into the terminal.
1177
+
1178
+ `/bin/jspulse` directly imports its installed package entry from
1179
+ `/usr/lib/node_modules`. `/bin/jspinyin` instead starts the system jsmdcui
1180
+ at `/buninu/apps/jsmdcui/src/index.js` with `--tui`, passing the user's arguments followed
1181
+ by `/usr/lib/node_modules/@drxiaozhi/jspinyin/im.md`. It bypasses the upstream
1182
+ `bun x jsmdcui` launcher, so launching this command does not download jsmdcui.
1183
+ Both are small, executable JavaScript files, with no shell wrapper.
1184
+ Run `jspulse --alsa` or `jspinyin` from the terminal.
1185
+
1186
+ To fetch only these application archives:
1187
+
1188
+ ```sh
1189
+ bun scripts/fetch-npm.js # built-in fetch; also works with Node.js
1190
+ ./fetch-npm.sh # curl + sha256sum, including inside Docker
1191
+ ```
1192
+
925
1193
  #### Build pipeline
926
1194
 
927
1195
  The primary `bun ./index.js -fb --real` pipeline runs the steps below in order;
@@ -934,6 +1202,7 @@ and copies the final `vda.img` to the invocation directory.
934
1202
  | --- | --- | --- |
935
1203
  | `fetch-alpine.sh` | Alpine CDN | `kernel/<arch>/vmlinuz-<flavor>`, `kernel/<arch>/linuxx64.efi.stub` (`linuxaa64.efi.stub`), `native/<arch>/lib/ld-musl-<arch>.so.1`, and the selected network, storage, input, power and filesystem modules under `native/<arch>/lib/modules/` with trimmed module indexes |
936
1204
  | `fetch-bun.sh` | GitHub, Alpine CDN | `native/<arch>/bin/bun`, `native/<arch>/lib/{libc.musl-<arch>.so.1,libstdc++.so.6,libgcc_s.so.1}` |
1205
+ | `fetch-npm.sh` / `scripts/fetch-npm.js` | npm registry, fixed URLs and SHA-256 in `scripts/npm-packages.md` | `downloads/npm/*.tgz`; pack later extracts into `/usr/lib/node_modules` |
937
1206
  | `scripts/pack-initramfs.sh` | `initramfs/`, then `native/<arch>/` over it | `build/initramfs.cpio.gz` |
938
1207
  | `build-uki.sh` | that archive, kernel, stub | `build/cmdline`, `build/os-release`, `vda/EFI/BOOT/BOOTX64.EFI` (`BOOTAA64.EFI`) |
939
1208
  | `build-image.sh` | `vda/EFI/BOOT/BOOTX64.EFI` (`BOOTAA64.EFI`) | `vda.img` |
@@ -1005,7 +1274,7 @@ The physical boot chain is firmware → the UKI stub → its embedded
1005
1274
  and, with the currently pinned kernel, embeds this complete command line:
1006
1275
 
1007
1276
  ```text
1008
- console=ttyS0,115200 console=tty0 REAL_MACHINE=1 panic=0 PATH=/bin KERNEL_RELEASE=6.18.54-0-lts rdinit=/bin/bun -- -e import('/init.js')
1277
+ console=ttyS0,115200 console=tty0 REAL_MACHINE=1 panic=0 PATH=/bin KERNEL_RELEASE=6.18.55-0-lts rdinit=/bin/bun -- -e import('/init.js')
1009
1278
  ```
1010
1279
 
1011
1280
  Serial kernel logging is retained, while the final console makes
@@ -1029,7 +1298,7 @@ the same way). Build without `--real`; this selects Alpine `linux-virt`, omits t
1029
1298
  module set, and puts `ttyS0` last so serial stdio owns `/dev/console`:
1030
1299
 
1031
1300
  ```text
1032
- console=tty0 console=ttyS0,115200 panic=0 PATH=/bin KERNEL_RELEASE=6.18.54-0-virt rdinit=/bin/bun -- -e import('/init.js')
1301
+ console=tty0 console=ttyS0,115200 panic=0 PATH=/bin KERNEL_RELEASE=6.18.55-0-virt rdinit=/bin/bun -- -e import('/init.js')
1033
1302
  ```
1034
1303
 
1035
1304
  Build and boot it with:
@@ -1146,7 +1415,7 @@ The default `--real` image embeds this kernel command line (shown for the
1146
1415
  currently pinned LTS release):
1147
1416
 
1148
1417
  ```text
1149
- console=ttyS0,115200 console=tty0 REAL_MACHINE=1 panic=0 PATH=/bin KERNEL_RELEASE=6.18.54-0-lts rdinit=/bin/bun -- -e import('/init.js')
1418
+ console=ttyS0,115200 console=tty0 REAL_MACHINE=1 panic=0 PATH=/bin KERNEL_RELEASE=6.18.55-0-lts rdinit=/bin/bun -- -e import('/init.js')
1150
1419
  ```
1151
1420
 
1152
1421
  The physical display (`tty0`) is the final console and therefore owns PID 1's
@@ -1282,11 +1551,20 @@ for the userspace session.
1282
1551
  * [Clipboard](#clipboard)
1283
1552
  * [Playing YouTube with sound (experimental)](#playing-youtube-with-sound-experimental)
1284
1553
  - [Commands inside /bin](#commands-inside-bin)
1554
+ * [Buninu Browser (early-stage, experimental)](#buninu-browser-early-stage-experimental)
1555
+ * [Archive tools and other examples](#archive-tools-and-other-examples)
1556
+ - [Optional chroot and native binaries](#optional-chroot-and-native-binaries)
1557
+ * [Debian and Chromium with casty](#debian-and-chromium-with-casty)
1558
+ * [Alpine minirootfs](#alpine-minirootfs)
1559
+ * [An existing root filesystem](#an-existing-root-filesystem)
1285
1560
  - [Environment and dependencies](#environment-and-dependencies)
1286
1561
  * [Build environment](#build-environment)
1287
1562
  * [Buninu Linux (Section 2)](#buninu-linux-section-2)
1288
1563
  * [Hello world (Section 1)](#hello-world-section-1)
1289
1564
  * [Retired native bootstrap](#retired-native-bootstrap)
1565
+ - [Old build (shell tools)](#old-build-shell-tools)
1566
+ * [Old build directly with bun x](#old-build-directly-with-bun-x)
1567
+ * [Old build from a source checkout](#old-build-from-a-source-checkout)
1290
1568
  - [Implementation details](#implementation-details)
1291
1569
  * [1. Hello world](#1-hello-world)
1292
1570
  * [2. Buninu Linux – Bun as PID 1](#2-buninu-linux-bun-as-pid-1)
@@ -1325,7 +1603,19 @@ own third-party notices, listed at the end of [NOTICE.md](NOTICE.md).
1325
1603
  The repository also commits four third-party platform binaries per guest
1326
1604
  architecture under `native/<arch>/lib/`, and the built image redistributes
1327
1605
  several more. Each stays
1328
- under its own terms, with the full texts in [`LICENSES/`](LICENSES/):
1606
+ under its own terms, with platform license texts in [`LICENSES/`](LICENSES/).
1607
+
1608
+ The build also fetches four SHA-256-pinned npm releases and redistributes
1609
+ them under `/usr/lib/node_modules`: `buninu-browser`, `@drxiaozhi/casty`,
1610
+ `@drxiaozhi/jspulse` and `@drxiaozhi/jspinyin`. Their license and notice files
1611
+ remain inside their package directories. Exact download URLs and hashes are
1612
+ in [`scripts/npm-packages.md`](scripts/npm-packages.md); versions, upstream
1613
+ sources and installed notice/source locations are recorded in
1614
+ [NOTICE.md](NOTICE.md#npm-applications-fetched-and-redistributed-in-the-image).
1615
+ The project's MIT license does not replace those packages' licenses.
1616
+ In particular, jspulse and the browser's bundled wasmpeg/FFmpeg code carry
1617
+ LGPL obligations; retain their licenses and supplied source/rebuild material
1618
+ when redistributing the image.
1329
1619
 
1330
1620
  ### Bundled component licenses
1331
1621
 
@@ -1336,6 +1626,11 @@ under its own terms, with the full texts in [`LICENSES/`](LICENSES/):
1336
1626
  | Linux kernels and networking, storage, xHCI, USB and HID modules | GPL-2.0-only with the Linux syscall note | image only |
1337
1627
  | systemd EFI stub | LGPL-2.1-or-later | image only |
1338
1628
  | Bun | MIT, plus the licenses of what it statically links | image only |
1629
+ | buninu-browser 0.2.2 | MIT for its own code; bundled components have their own licenses | npm download → image |
1630
+ | wasmpeg / FFmpeg (`@wasmpeg/cpu` 1.0.1, bundled in buninu-browser) | LGPL-2.1-or-later, plus component notices; source archive and rebuild documentation retained | browser package → image |
1631
+ | `@drxiaozhi/casty` 1.3.4 | MIT | npm download → image |
1632
+ | `@drxiaozhi/jspulse` 0.2.1 | LGPL-2.1-or-later, plus component notices | npm download → image |
1633
+ | `@drxiaozhi/jspinyin` 0.1.1 | MIT; hanzipinyin material under the Unlicense | npm download → image |
1339
1634
  | CanvasKit 0.41.1 (`initramfs/lib/canvaskit/`, Skia compiled to WebAssembly) | BSD-3-Clause (`LICENSES/BSD-3-Clause-Skia.txt`) | committed |
1340
1635
  | xterm.js 6.0.0 headless core and unicode-graphemes addon (`initramfs/lib/xterm/`); box-drawing shape tables in `initramfs/lib/bunterm/glyphs.js` | MIT (`LICENSES/MIT-xterm.js.txt`) | committed |
1341
1636
  | DejaVu Sans Mono (`initramfs/usr/share/fonts/DejaVuSansMono*.ttf`) | Bitstream Vera (`LICENSES/Bitstream-Vera.txt`) | committed |