Add VS Code OS desktop shell extension - #5
Merged
Merged
Conversation
VS Code OS boots straight into VS Code with no desktop environment, which
until now meant there was no way to shut the machine down, see the time,
change the volume, join a network, look at what is running, or open a file
that is not text. Everything had to go through the integrated terminal.
This adds extension/, a TypeScript VS Code extension that supplies the
missing desktop:
* a tray at the right end of the status bar - now playing, battery,
volume, network, clock and date, and the power button in the corner;
* flyouts for power, calendar, quick settings, the volume mixer, the
network picker and the music player;
* a Task Manager in the activity bar, with processes, per-core CPU,
memory, load, uptime and thermals, read from /proc;
* a graphical file explorer;
* an MPRIS music player with launchers for Spotify Web and YouTube Music;
* a browser launcher, and Calculator, Notepad, Paint, Screenshot and
Voice Recorder.
The shell ships as a *built-in* extension rather than a Marketplace one.
Both builds stage it at /usr/share/vscodeos/extensions and
vscodeos-install-extensions copies it into VS Code's own
resources/app/extensions, which is a plain directory scan with no
extensions.json and no engine check - so an editor update can never decide
the desktop is incompatible and disable it. That update does replace the
whole app tree, so vscodeos-update-code re-runs the installer afterwards.
The bundle is architecture-neutral JavaScript, so CI builds it once in a new
`extension` job and hands both image jobs the same artifact through
VSCODEOS_EXTENSION_PREBUILT. The release job now filters its artifact
download to VSCodeOS-*, so the bundle is not published as a release asset.
Packages added to both images: chromium (Edge is AUR-only on Arch and has no
ARM64 Linux build at all, so it could never have shipped on the Pi; the
launcher still prefers microsoft-edge-stable when it is installed), plus
playerctl, scrot, bluez and bluez-utils. Roughly 200 MiB on the ISO against
~400 MiB of headroom under the 2 GiB release-asset limit.
Two grants make the shell work without a polkit agent, which the kiosk
session has nowhere to draw: 49-vscodeos.rules for power and NetworkManager,
and a udev rule making the backlight writable by the `video` group.
The status bar setting is load-bearing: the notifications bell registers at
a priority no extension can outrank, so the skel settings move notifications
to the top right to free the bottom-right corner for the power button.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MQheV7d9dNqz8WSxo43cLk
Running the sys/ layer against this machine's /proc and against nmcli and
wpctl fixtures checked out - RSS and CPU match `ps`, escaped colons in SSIDs
survive, wpctl's box-drawing tree parses. The calculator did not.
Negation was rewritten as "0 − x", which is correct at the start of an
expression and wrong everywhere after it:
5 − −3 -> 5 − 0 − 3 = 2 (should be 8)
2 × −3 -> 2 × 0 − 3 = -3 (should be -6)
and the ± key emitted an ASCII hyphen, which fell through the tokenizer's
prefix handling entirely, so ±5 + 3 was an error rather than -2.
Negation is now a real unary operator carried on the operator stack, and
ASCII hyphens are normalised to the typographic minus the keypad shows.
The failure messages went with it: "Error: undefined" reads like a
JavaScript value, which is the last thing it should read like inside a code
editor. Division by zero and the root or log of a negative now say
"Undefined", overflow says "Overflow", and callers ask isError() instead of
matching on the message text - the check the two call sites were doing by
hand, and would have got wrong.
The evaluator moves to media/src/lib/calc.ts so it can be tested without a
DOM. extension/test/ covers it and the formatters with node:test - 45 cases,
no framework to install - and CI runs typecheck and tests before either
image build starts. Narrow coverage on purpose: everything else here talks
to /proc, nmcli or the VS Code API and is verified by running it. This is
the part where a mistake is invisible.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MQheV7d9dNqz8WSxo43cLk
The workflow only fired on v* tags, so a pull request got no checks at all - the extension's typecheck, its tests and its bundle build first ran when someone cut a release, which is the worst moment to find out any of them broke. Pull requests now run the `extension` job and nothing else. It is a couple of minutes on ubuntu-latest and it is the only part of a build that can fail on a code mistake rather than on a mirror, a runner or a package that moved; the two image jobs are two-hour builds producing gigabyte artifacts, and gating every PR on those would cost a great deal to learn very little. `version` is skipped on pull requests too - nothing a PR runs needs a version, and a check that only echoes one is noise on the PR page. Concurrency now cancels superseded runs on pull requests only. A supplanted PR check is wasted minutes; a release build must never be cancelled out from under a tag. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQheV7d9dNqz8WSxo43cLk
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.
This PR adds VsCodeOsCore, a comprehensive desktop shell extension that transforms VS Code into a complete operating system interface. The extension provides system tray functionality, power management, task monitoring, file exploration, and several mini-applications.
Summary
The extension implements a full desktop shell experience within VS Code, including:
Key Changes
Extension Host (
extension/src/): Core extension logic including:Webview UIs (
extension/media/src/): Browser-based interfaces for:Styling (
extension/media/css/vscodeos.css): Comprehensive theming that respects VS Code's color scheme with custom CSS variablesSystem Integration:
/procand/sysfilesystem reading for process and system statisticsBuild System: esbuild configuration to bundle extension host (Node/CJS) and webview code (browser/IIFE) separately
Package Configuration: Updated both x86_64 and ARM64 package lists to include required dependencies (bluez, chromium, etc.)
Notable Implementation Details
/procdirectly instead of spawningps/topfor each sampleexecFilewithout shell mode to prevent injection attackshttps://claude.ai/code/session_01MQheV7d9dNqz8WSxo43cLk