mbflash 0.0.0-stage → 1.2.1

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 (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +264 -2
  3. package/mbflash.mjs +1451 -0
  4. package/package.json +42 -4
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Taisuke Yamada
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,265 @@
1
- # Temporary Holding Version
1
+ # mbflash
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [![CI](https://github.com/tai/mbflash/actions/workflows/ci.yml/badge.svg)](https://github.com/tai/mbflash/actions/workflows/ci.yml)
4
+ [![npm](https://img.shields.io/npm/v/mbflash.svg)](https://www.npmjs.com/package/mbflash)
5
+
6
+ A dependency-free CLI for driving the micro:bit MakeCode editor over CDP:
7
+ load TypeScript, commit it to Blocks, compile/download the `.hex`, and flash it
8
+ by writing to the `MICROBIT` volume (no WebUSB pairing needed).
9
+
10
+ ```sh
11
+ mbflash main.ts
12
+ ```
13
+
14
+ That one command:
15
+
16
+ 1. attaches to the MakeCode tab in a CDP-enabled Chromium,
17
+ 2. loads `main.ts` into the editor and rebuilds the Blocks view,
18
+ 3. compiles and downloads the `.hex`,
19
+ 4. copies it to the micro:bit's DAPLink volume and waits for the remount.
20
+
21
+ ## Requirements
22
+
23
+ - Node.js **22.4+** (uses the built-in `WebSocket` and `fetch`).
24
+ - A headed Chromium/Chrome launched with a debugging port:
25
+
26
+ ```sh
27
+ chromium --user-data-dir="$HOME/.config/chromium-agent" \
28
+ --remote-debugging-port=9222 \
29
+ --remote-debugging-address=127.0.0.1 \
30
+ "https://makecode.microbit.org/#editor"
31
+ ```
32
+
33
+ - One or more MakeCode tabs. Select the intended one with `--project`,
34
+ `--target`, or `--index`; ambiguous matches are refused.
35
+ - The micro:bit mounted as `MICROBIT` (normally `/run/media/$USER/MICROBIT`).
36
+
37
+ ## Install
38
+
39
+ From npm:
40
+
41
+ ```sh
42
+ npm install -g mbflash
43
+ ```
44
+
45
+ From this GitHub repository:
46
+
47
+ ```sh
48
+ npm install -g github:tai/mbflash
49
+ # or: npm install -g git+https://github.com/tai/mbflash.git
50
+ ```
51
+
52
+ For development from a checkout:
53
+
54
+ ```sh
55
+ npm link # puts `mbflash` on PATH, pointing at ./mbflash.mjs
56
+ # or run directly:
57
+ node mbflash.mjs --help
58
+ ```
59
+
60
+ The package has no runtime dependencies and requires Node.js **22.4+**.
61
+
62
+ ## Modes
63
+
64
+ | Command | What it does |
65
+ | --- | --- |
66
+ | `mbflash main.ts` | load → Blocks → build → flash |
67
+ | `mbflash --load-only main.ts` | load → Blocks (no build/flash) |
68
+ | `mbflash --hex-only main.ts` | load → Blocks → build/download (no flash) |
69
+ | `mbflash --hex-only` | build/download the code already in the editor |
70
+ | `mbflash --flash-only` | build/flash the code already in the editor |
71
+ | `mbflash --flash-hex demo.hex` | flash an existing `.hex` (no CDP) |
72
+ | `mbflash --project Test1 --switch` | focus the Test1 project (no build) |
73
+
74
+ `--hex-only` with no file is useful when a human has edited Blocks and you just
75
+ want a `.hex`. `--flash-only` skips loading but still builds. `--switch` is the
76
+ tab manager: select by **project name** or target and bring it to the front.
77
+
78
+ If `--project` does not match an existing tab, `mbflash` creates a new project
79
+ with that name by driving the home page’s **New Project** dialog (open the home
80
+ tab, fill `#projectNameInput`, click **Create**, wait for the editor). Use
81
+ `--no-create` to make a missing project an error instead. Creation adds about
82
+ 2–3 s.
83
+
84
+ ## Multiple tabs / projects
85
+
86
+ All MakeCode tabs have the same URL and title. `mbflash` identifies them by
87
+ **CDP target id** and the **MakeCode project name** — the project header /
88
+ `pxt.json` name, read from the editor’s project-name field. No sidecar metadata
89
+ is written, and the tab title is not used for matching.
90
+
91
+ ```sh
92
+ mbflash --list # ids, project names, URLs
93
+ mbflash --project Test1 --switch # focus Test1, no build
94
+ mbflash --project Test1 main.ts # load/build/flash Test1 only
95
+ mbflash --project Test2 --hex-only # build Test2's current code
96
+ mbflash --project Test3 main.ts # create Test3 if missing
97
+ mbflash --project Test3 --switch # create + focus an empty Test3
98
+ mbflash --label Test1 --switch # deprecated alias for --project
99
+ ```
100
+
101
+ Project names are what MakeCode stores (`pxt.json` `"name"`, and the workspace
102
+ header / `headers.name` in IndexedDB when persistent). In this session-only
103
+ profile the header lives in renderer memory, so `mbflash` reads the editor’s
104
+ project-name field. The tab title is cosmetic; add `--retitle` if you also want
105
+ the visible title changed to `MakeCode — <project>`.
106
+
107
+ If `--project` is missing, `mbflash` creates the project through the home page’s
108
+ New Project dialog (same tab, then `#editor`) and the new project is named after
109
+ `--project`. `--no-create` turns a missing project into an error.
110
+
111
+ Duplicate project names: select a specific tab with `--target <id>` or
112
+ `--index <n>`.
113
+
114
+ Practical notes for multiple projects:
115
+
116
+ - Work one at a time. `mbflash` brings the selected tab to the front by default
117
+ (hidden tabs are throttled by Chromium); `--no-focus` skips that.
118
+ - A shared `--download-dir` is fine: MakeCode names the `.hex` after the project
119
+ (`microbit-Test1.hex`, `microbit-Test2.hex`), so sequential builds keep
120
+ distinct files.
121
+ - On this profile the MakeCode workspace is **session-only**: each tab's project
122
+ lives in renderer memory and is lost on reload. Keep `main.ts` on disk.
123
+ - The tabs share origin storage (`localStorage`), but their in-memory projects
124
+ are independent. If you sign in or enable persistent workspaces, keep to one
125
+ tab per project and verify that the IDB workspace is not being shared.
126
+ - Only one board mount is used by default. For multiple boards, pass a different
127
+ `--device` per project.
128
+
129
+ ## Options
130
+
131
+ ### Target
132
+
133
+ ```sh
134
+ mbflash --cdp 9222 main.ts # default 127.0.0.1:9222
135
+ mbflash --cdp 192.168.1.50:9222 main.ts # remote Chromium
136
+ mbflash --list # show page targets
137
+ mbflash --target ABCD1234 main.ts # exact page id
138
+ mbflash --index 2 main.ts # second match
139
+ mbflash --url makecode main.ts # URL substring or /regex/
140
+ mbflash --title "MakeCode" main.ts # title substring
141
+ mbflash --host makecode.microbit.org main.ts
142
+ mbflash --label Test1 --switch # deprecated alias for --project
143
+ mbflash --project Test1 --switch # focus a project tab
144
+ mbflash --project Test1 --switch --retitle # focus + set the visible title
145
+ mbflash --project Test3 main.ts # create Test3 if missing
146
+ mbflash --label NoSuch --switch --no-create # error instead of creating
147
+ ```
148
+
149
+ The default tab match is the exact hostname `makecode.microbit.org`. If more
150
+ than one tab matches (or two tabs have the same project name), the command
151
+ fails and lists them; pick one with `--target` or `--index`.
152
+
153
+ ### Output / device
154
+
155
+ ```sh
156
+ mbflash --download-dir ./build main.ts # where Chromium writes the .hex
157
+ mbflash --hex-out ./demo.hex main.ts # copy the built hex here
158
+ mbflash --device /run/media/$USER/MICROBIT main.ts
159
+ mbflash --wait 90 main.ts # flash timeout (s)
160
+ mbflash --timeout 180 main.ts # build/download timeout (s)
161
+ ```
162
+
163
+ `--download-dir` defaults to `$XDG_CACHE_HOME/mbflash/hex` (usually
164
+ `~/.cache/mbflash/hex`). The new `.hex` is detected without deleting anything
165
+ already in that folder. `--hex-out` can be a file or an existing directory.
166
+
167
+ ### Loading
168
+
169
+ ```sh
170
+ mbflash --no-blocks main.ts # load TS only, do not rebuild Blocks
171
+ mbflash --roundtrip main.ts # JS -> Blocks -> JS sanity check
172
+ ```
173
+
174
+ `--roundtrip` catches icon/enum loss from the TS → Blocks conversion; a
175
+ textual difference is reported as a warning (harmless reformatting is common).
176
+
177
+ ### Automation
178
+
179
+ ```sh
180
+ mbflash --json --hex-only main.ts
181
+ mbflash --quiet main.ts # print only the hex path (or "ok")
182
+ ```
183
+
184
+ `--json` prints a single object on stdout with `ok`, `mode`, `hex`, `device`,
185
+ `markers`, `blocks`, `roundtrip`, `warnings`, and `timings`. On failure it
186
+ prints `{ "ok": false, "error": "...", "timings": ... }` and exits non-zero.
187
+
188
+ ## Examples
189
+
190
+ ```sh
191
+ # Normal development loop
192
+ mbflash main.ts
193
+
194
+ # Only check that the Blocks conversion works
195
+ mbflash --load-only main.ts
196
+
197
+ # Build a hex for someone else, no board attached
198
+ mbflash --hex-only --hex-out ./release.hex main.ts
199
+
200
+ # Reflash whatever the human has open in Blocks
201
+ mbflash --flash-only
202
+
203
+ # Flash a prebuilt artifact on a machine without a browser
204
+ mbflash --flash-hex ./release.hex --device /run/media/$USER/MICROBIT
205
+
206
+ # A second Chromium on another port
207
+ mbflash --cdp 127.0.0.1:9333 --target <id> main.ts
208
+ ```
209
+
210
+ ## Notes
211
+
212
+ - **Multiple tabs.** Tabs share an origin and can share persistent storage. On
213
+ a session-only workspace each tab has its own in-memory project, and
214
+ `mbflash` can address them with `--project`/`--target`. With persistent
215
+ workspaces, avoid opening the same project in two tabs; edit one project per
216
+ tab.
217
+ - **Session-only projects.** Some profiles keep the project only in page
218
+ memory. The CLI still works, but the project is lost on reload; keep the
219
+ `main.ts` and `.hex` on disk.
220
+ - **V1 vs V2.** The CLI flashes what you give it. V2-only APIs (logo touch,
221
+ `input.soundLevel`, audio) compile for a V1 board and then panic with code
222
+ **927** at boot. Check the board version before using those APIs.
223
+ - **Narrow windows.** MakeCode hides the Download control in its mobile
224
+ layout. The CLI temporarily emulates a 1400×900 viewport to reach the menu,
225
+ then clears the override.
226
+ - **Flashing** copies the `.hex` to the DAPLink volume and treats “volume
227
+ remounted, hex gone, no `FAIL.TXT`” as success. The copy of the ~1.3 MB
228
+ universal hex is usually the slowest part (~9 s); the flash itself is a few
229
+ seconds.
230
+ - **Typical full run** on a demo-sized project: ~2 s load + Blocks, ~4 s build,
231
+ ~15 s flash command (copy + flash), ~21 s total.
232
+ - The downloaded filename follows the MakeCode project name; use `--hex-out`
233
+ to give it the name you want.
234
+ - **Not a simulator driver.** Like the skill, this tool does not verify
235
+ behaviour in the simulator; the human watches the board.
236
+
237
+ ## Development
238
+
239
+ ```sh
240
+ npm test # CLI tests; no browser or board required
241
+ npm run lint # node --check
242
+ npm pack --dry-run # inspect the npm package contents
243
+ ```
244
+
245
+ The test suite covers argument parsing, project/title semantics, and hex
246
+ validation. Browser/CDP loading and flashing require a real MakeCode tab and a
247
+ mounted micro:bit.
248
+
249
+ ## Publishing
250
+
251
+ This repository is <https://github.com/tai/mbflash>.
252
+
253
+ ```sh
254
+ npm test
255
+ npm publish
256
+ git tag v1.2.1 # use the new version
257
+ git push origin main --tags
258
+ ```
259
+
260
+ The `Publish npm` workflow runs on a published GitHub release (or manually). It
261
+ skips publishing when the version already exists on npm; otherwise it publishes
262
+ with the OIDC trusted publisher configured for this repository on npmjs.com, so
263
+ no npm secret is stored in GitHub. Keep the repository public for npm
264
+ provenance. `npm pack --dry-run` shows exactly what would be published:
265
+ `mbflash.mjs`, `README.md`, `LICENSE`, and `package.json`.