Skip to content

feat(kits): add experimental vscode mixin using --display - #215

Draft
djs55 wants to merge 3 commits into
docker:mainfrom
djs55:feat/vscode-mixin
Draft

djs55 wants to merge 3 commits into
docker:mainfrom
djs55:feat/vscode-mixin

Conversation

@djs55

@djs55 djs55 commented Aug 19, 2026 •

Copy link
Copy Markdown

Have you ever worried about running complex GUI applications on your host, especially apps which have sophisticated extension systems with correspondingly sophisticated supply chains? It's rational to worry; even the most vigilant users have been hacked via poisoned VS Code extensions.

Instead of running VS Code natively on your app, run it safely inside your Docker Sandbox instead.

image

The Linux version of VS Code runs in the microVM sandbox with all the governance applied, while the windows are transparently forwarded to the host. The green border is a reminder that the window is from inside the sandbox, a homage to Qubes OS

Spec choices worth flagging for review

My first kit, so it's hard to tell!

Origin

It's a simple wrapper of Linux VS Code. Previously VS Code always ran on the host and could connect into the sandbox. This kit colocates VS Code in the sandbox.

Test plan

For manual testing with sbx 0.39+:

sbx settings set platform.allowExperimentalFeatures true
sbx settings set feature.sandbox-display true
sbx settings set kit.allowedSources '["docker.io/","github.com/djs55/"]'

sbx run claude \
    --display \
    --kit "git+https://github.com/djs55/sbx-kits-contrib.git#ref=92469534d88a9bf55b55da93bc8e8bed2dd5cebd&dir=vscode" \
    ~/my-project

CI runs kit validate and the TCK on every PR. CI does not run e2e on
fork PRs (Docker Hub secrets aren't exposed there), so the e2e step below is
required from your side before requesting review.

  • sbx kit validate ./<kit>/ passes
  • ./scripts/test-kit.sh <kit> passes (the TCK)
  • ./scripts/test-kit-e2e.sh <kit> passes. The script applies the same
    deny-all baseline CI uses and scopes everything to its own daemon
    (--app-name sbx-kits-contrib-tck), so my main sbx state is untouched.
    Every entry I added to network.allowedDomains came from
    sbx --app-name sbx-kits-contrib-tck policy log <tck-e2e-…>, not a guess.
  • Manual smoke: sbx run --kit ./<kit>/ <agent> and verified the kit's
    binary / files / env are inside the running container.

All three re-verified at 94e2af7, after the apt fix in that commit — the
earlier e2e tick predated it and had gone stale. test-kit-e2e.sh vscode
passes under deny-all (real sbx create on claude-code-docker, install
hook OK in 38.1s, files / tmpfs / agentContext subtests PASS), and the manual
smoke confirmed code 1.138.0 installed, dbus-run-session present,
/run/display/wayland-0 live, and VS Code running with a GPU process on
--ozone-platform=wayland with the workspace open.

One-time setup if you haven't run e2e on this machine before:
sbx --app-name sbx-kits-contrib-tck login.

See CONTRIBUTING.md → Verifying locally
and README → Declare every domain your kit needs
for the cross-arch domain gotchas (archive.ubuntu.com,
security.ubuntu.com, ports.ubuntu.com) and the package-manager refresh trap.

@djs55
djs55 force-pushed the feat/vscode-mixin branch from 2eb6671 to 72a784e Compare August 19, 2026 13:35
djs55 and others added 3 commits September 24, 2026 11:05
Installs VS Code from Microsoft's apt repo and starts it as a Wayland
client on the host compositor, opening the sandbox workspace. Requires
--display (behind feature.sandbox-display). Includes a README with
prerequisites and agentInstructions so the running agent knows the
editor is open.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: David Scott <dave@recoil.org>
Signed-off-by: David Scott <dave@recoil.org>
setup.install redirected Dir::State::Lists to /dev/shm/apt-lists, which is
a 64 MiB tmpfs. The base template's sources (main/universe/restricted/
multiverse across resolute, -updates, -backports and -security) measure
41 MiB of index at rest and peak at 59.3 MiB during the fetch, because apt
recompresses each Packages file to .lz4 while the next ones are still
downloading into partial/. That left ~4.7 MiB of headroom, and Ubuntu's
metadata has since grown past it.

Once the tmpfs fills, apt's LZ4 writer fails with ENOSPC, apt retries each
failed index with a different compression variant, and the last fallback is
the plain uncompressed Packages path — which Ubuntu does not publish. The
resulting 404 made apt-get update exit 100, failing the kit install and
sandbox creation:

  Err:19 ports.ubuntu.com resolute-security/multiverse arm64 Packages
    Error writing to file - write (28: No space left on device)
    404  Not Found

The redirect was justified by a comment claiming apt's InRelease
verification needs O_TMPFILE, which the virtiofs overlay does not support.
That is not the case: O_TMPFILE succeeds on /var/lib/apt/lists, /tmp,
/dev/shm and /var/cache/apt inside a claude-code-docker sandbox, / is a
20 GiB overlay on the microVM's own block device with 19 GiB free, and
plain apt-get update there exits 0. The other apt-using kits in this repo
(crush, playwright, codex-app-server, packages-through-sfw) all run apt
against its defaults without trouble.

Drop the override, the TMPDIR=/dev/shm export and the /dev/shm cleanup.
DPkg::Lock::Timeout stays: the base template registers its own apt-get
update startup hook, which can hold the lock when this install hook runs.

Verified by sbx create on claude-code-docker — failed with exit 100 before,
installs in 33s after, with code 1.138.0 running on the Wayland surface and
the workspace open. scripts/test-kit.sh vscode passes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: David Scott <dave@recoil.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant