Make update reach the desktop app, and make the desktop app render - #9
Merged
Conversation
`diskpush update` re-ran the installer with --cli-only whenever the manifest said desktop:false, so an install made from a tty or over SSH — where has_desktop_session() finds no DISPLAY — could never gain the desktop app, however many times it was updated, and printed nothing to say so. The desktop app looked stale because it had never been installed. A CLI-only install is now left to the installer's own detection, so a machine that has a desktop gets the desktop app on its next update. A desktop install is pinned the other way, to --desktop: updating one from cron or SSH has no DISPLAY to detect, and auto-detect would quietly strip the app out from under a working desktop and orphan its files. --cli-only and --desktop on the update command override both, and a Surfaces: line now says which it chose. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CBc6KV8dL7oLS5okq15B4W
… asset
The window loaded out/index.html with loadFile, so the page origin was file://.
Next emits root-absolute asset URLs (/_next/static/...), which under file://
resolve against the filesystem root — file:///_next/... — so the stylesheet and
all five chunks 404ed. What shipped was the prerendered HTML with zero CSS
rules applied and no React: unstyled Times New Roman, native form controls, and
a permanent "Loading…". It reads as a broken UI rather than a broken path,
which is why it survived a UI pass — the export was verified over http://,
where those same absolute paths resolve fine.
Next cannot emit relative ones: next/font rejects an assetPrefix without a
leading slash, and the CSP here sends base-uri 'none', so a <base> tag is out
too. Instead the bundle gets an origin of its own via a standard scheme, which
also makes the existing default-src 'self' mean the bundle rather than the
whole disk. Files are read with fs, not net.fetch('file://'), so it keeps
working inside the packaged asar.
Verified in headless Chromium against the real export: 6 failed requests and 0
CSS rules before, 0 failed requests and 124 after, with React hydrating and the
dark theme and Geist both applied.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CBc6KV8dL7oLS5okq15B4W
The launch check dies at the display, so it never loads a page — which is why it watched v0.2.0 ship a window where the stylesheet and all five chunks 404ed and reported ok. Two checks that need no display now run first: every root-absolute asset in the export must resolve to a real file through the same function that serves it, and the main process must still register the bundle scheme and must not load the renderer with loadFile. The second is the one with teeth. Assets resolve whatever the window does with them; what broke the app was the page origin, so the mechanism is pinned rather than only the paths. Verified by reintroducing loadFile into the built main and watching the check fail. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CBc6KV8dL7oLS5okq15B4W
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two bugs that combined into "I keep updating and the desktop UI is still garbage".
1.
diskpush updatecould never install the desktop apprunUpdatere-ran the installer with--cli-onlywhenever the manifest saiddesktop: false:install.sh'shas_desktop_session()only checksDISPLAY/WAYLAND_DISPLAY/XDG_CURRENT_DESKTOP, so installing from a tty or over SSH silently produces a CLI-only install — which then stayed CLI-only forever, however many times it was updated, and said nothing about why.--desktop, so updating from cron or SSH cannot quietly downgrade it and orphan its files.--cli-only/--desktopon the update command override both, and aSurfaces:line reports the choice.The same fix applies to the startup auto-update in
self-update.ts, which had an identical copy of the expression.2. The desktop app 404'd every one of its own assets
The window used
loadFile, so the page origin wasfile://. Next emits root-absolute asset URLs (/_next/static/…), which underfile://resolve against the filesystem root (file:///_next/…). The stylesheet and all five chunks 404'd, leaving prerendered HTML with 0 CSS rules and no React — unstyled serif text, native form controls, permanent "Loading…".Next can't emit relative paths (
next/fontrejects anassetPrefixwithout a leading slash) and the CSP sendsbase-uri 'none', so a<base>tag is out. The bundle now gets its own origin via a standard scheme, which also makes the existingdefault-src 'self'mean the bundle rather than the whole disk. Files are read withfsrather thannet.fetch('file://')so it keeps working inside the packaged asar.Before / after, measured against the real export in headless Chromium
rgb(7, 12, 22)This is why the bug survived a UI pass: the export was verified over a static
http://server, where those absolute paths resolve fine. Onlyfile://breaks them.Tests
12 new tests (
installer-flags.test.ts,bundle-path.test.ts) covering the flag matrix, asset path resolution, directory-traversal refusal, and content types. Full suite: 258 passing, typecheck and build clean.🤖 Generated with Claude Code
https://claude.ai/code/session_01CBc6KV8dL7oLS5okq15B4W