Summary
On Windows, miniapp-cli dev never respawns the background JSContext. Every edit under
src/background/ broadcasts reload (WebView only) instead of respawn-bg, so the phone keeps
running the previously installed bundle while the terminal reports activity and dist/ is correctly
rebuilt.
The failure is silent and looks like a working dev loop. It cost us about an hour of debugging a
stale bundle before we noticed the terminal line was reload src\background rather than
respawn-bg src/background/index.ts.
Cause
src/dev-server.ts decides which layer changed with forward-slash string tests:
const touchedBackground =
filename.startsWith("src/background/") || filename.includes("/src/background/")
Windows fs.watch reports src\background\index.ts, so touchedBackground is always false and
nextType is always "reload".
The same assumption breaks the watcher's skip list:
const isUnder = (filename: string, name: string): boolean =>
filename === name || filename.startsWith(`${name}/`) || filename.includes(`/${name}/`)
so isUnder(filename, "dist") never matches either, and build output is not filtered out of the
watcher on Windows.
Reproduction
- On Windows,
bunx @mentra/miniapp-cli dev in a two-layer project.
- Install on a phone by scanning the QR.
- Edit anything under
src/background/, e.g. add a console.log at the top of the handler.
- Observe the terminal prints
reload src\background (note the backslash).
- The new log line never appears in the forwarded
[MentraJS] output — the phone is still running
the old bundle, even though dist/background/index.js has a fresh mtime and contains the change.
Suggested fix
Normalise the separator once at the watcher boundary, before any path test:
const norm = (p: string): string => p.replace(/\\/g, "/")
const isUnder = (filename: string, name: string): boolean => {
const f = norm(filename)
return f === name || f.startsWith(`${name}/`) || f.includes(`/${name}/`)
}
const watcher = watch(options.watchDir, {recursive: true}, (_event, rawFilename) => {
const filename = rawFilename === null ? null : norm(rawFilename)
if (!filename) return
// ...unchanged
})
Verified against a local copy of @mentra/miniapp-cli@0.1.0-dev.0: after this change a background
edit prints respawn-bg src/background/index.ts and the phone picks up the new bundle without a
reinstall.
Environment
@mentra/miniapp-cli 0.1.0-dev.0, @mentra/miniapp 3.1.0-dev.27
- Host: Windows 11, Bun 1.x
- Device: Mentra Live, MentraOS app
staging.20260808.*
Note
The project README we inherited advised "delete the entry in Miniapp Developer Settings and rescan to
pick up background changes". That workaround is a correct observation of this bug, and it may be
worth checking whether the docs recommend it anywhere — on macOS/Linux respawn-bg works and the
advice is unnecessary.
Summary
On Windows,
miniapp-cli devnever respawns the background JSContext. Every edit undersrc/background/broadcastsreload(WebView only) instead ofrespawn-bg, so the phone keepsrunning the previously installed bundle while the terminal reports activity and
dist/is correctlyrebuilt.
The failure is silent and looks like a working dev loop. It cost us about an hour of debugging a
stale bundle before we noticed the terminal line was
reload src\backgroundrather thanrespawn-bg src/background/index.ts.Cause
src/dev-server.tsdecides which layer changed with forward-slash string tests:Windows
fs.watchreportssrc\background\index.ts, sotouchedBackgroundis always false andnextTypeis always"reload".The same assumption breaks the watcher's skip list:
so
isUnder(filename, "dist")never matches either, and build output is not filtered out of thewatcher on Windows.
Reproduction
bunx @mentra/miniapp-cli devin a two-layer project.src/background/, e.g. add aconsole.logat the top of the handler.reload src\background(note the backslash).[MentraJS]output — the phone is still runningthe old bundle, even though
dist/background/index.jshas a fresh mtime and contains the change.Suggested fix
Normalise the separator once at the watcher boundary, before any path test:
Verified against a local copy of
@mentra/miniapp-cli@0.1.0-dev.0: after this change a backgroundedit prints
respawn-bg src/background/index.tsand the phone picks up the new bundle without areinstall.
Environment
@mentra/miniapp-cli0.1.0-dev.0,@mentra/miniapp3.1.0-dev.27staging.20260808.*Note
The project README we inherited advised "delete the entry in Miniapp Developer Settings and rescan to
pick up background changes". That workaround is a correct observation of this bug, and it may be
worth checking whether the docs recommend it anywhere — on macOS/Linux
respawn-bgworks and theadvice is unnecessary.