x11vnc against display :0 — the session the owner is actually logged into, not a second one Officer installs. sidecar/, api/, web/ and the host setup script, moved out of src/ whole. Dormant when it moved: the websocket was commented out in server.tsx and the router in hono.ts since 2026-08-13, and no officer-vnc process was running on any machine. Nothing regressed and nothing was restored — this took switched-off code out of the platform. The point of the move is what the platform stopped knowing. Its sidecar/protocol.ts carried a VNC section — vnc:start, vnc:ensure-password, vnc:stop, four reply variants, VncStartParams, VncSessionInfo — and sidecar-registry.ts carried startVnc, ensureVncPassword, stopVnc and isVncConnected. That is the platform speaking a plugin's vocabulary, which CLAUDE.md names as a rule and this was the clearest breach of. All of it is in sidecar/protocol.ts here now. The permission made a round trip worth recording. It was kind: 'execution' — "runs as the server owner and cannot be shared" — and a plugin permission has no kind, deliberately, because a permission nobody can delegate is a contradiction. So the property is expressed as ownerOnly: ['/'] instead: every path under this plugin refused to anyone but the owner. Same answer, reached from the paths rather than from a kind, and the first real use of a mechanism that landed the same day. The property is real — there is one physical screen and it is the owner's. Not finished, and BLOCKERS.md says so rather than the commit implying otherwise: the websocket is dormant because a plugin cannot claim a WebSocket provider, host setup needs a reboot and no manifest can express that, and there is no artwork. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
3.3 KiB
Desktop
This machine's physical screen, mirrored into the browser. Extracted from the platform on 2026-08-21.
What it is, and what it is not
x11vnc attached to display :0 — the session the owner is actually logged into, not a second one.
Officer used to install a desktop of its own (XFCE on a TigerVNC Xvnc server) and stopped: mirroring the
real session means what you see remotely is what is on the screen, and there is one place for a thing to
be rather than two.
That choice is why the permission is owner-only. There is one screen; two accounts granted this would see the same one, and it is the owner's.
What moved
src/servers/sidecar/vnc/ → sidecar/ x11vnc lifecycle, password provisioning
src/servers/api/desktop/ → api/ one route, plus a dormant websocket
officerdev/src/apps/Desktop/ → web/ the noVNC panel, header, wrapper
scripts/setup-old/setup-desktop.sh → setup/ host setup, still run by hand
It was dormant when it moved: the websocket was commented out in server.tsx and the router in
hono.ts from 2026-08-13, and no officer-vnc process was running on any machine. This extraction moved
switched-off code out of the platform. It did not break a working feature, and it did not restore one.
What the platform lost, which is the point
The platform's sidecar/protocol.ts had a // ── VNC ── section: vnc:start, vnc:ensure-password,
vnc:stop, their four reply variants, and VncStartParams/VncSessionInfo. sidecar-registry.ts had
startVnc, ensureVncPassword, stopVnc and isVncConnected.
That is the platform knowing what a plugin is about — CLAUDE.md names it as a rule and this was its
clearest violation. All of it lives in sidecar/protocol.ts here now.
What replaced it is generic: sendSidecarCommand(kind, cmd) and isSidecarConnected(kind), which know
that a command has a type and an id and a reply carries the same id, and nothing else. Any plugin's
sidecar can be driven through them without a line changing in the platform.
Host setup is not automatic
setup/setup-desktop.sh is run by hand, and the plugin cannot run it. See BLOCKERS.md §1 — the short
version is that it rewrites GDM's config and needs a reboot, and a manifest can declare packages, not a
reconfigured display manager.
The manifest declares x11vnc alone, which is the one part that is a package check and the one whose
absence produces a sidecar that starts and immediately fails.
Known gaps
BLOCKERS.md is the list. The two that matter:
- the websocket is dormant and a plugin cannot claim a WebSocket provider, so
/desktopdoes not work yet — it did not work before the move either - no artwork; the glyph and colour in the manifest are the fallback
Iris depends on the other half of this
plugins/iris captures pages using sessions from a browser profile at ~/.config/officer/browser-profile
— the profile a browser running in this desktop signs into. Its wrapper says "install the desktop
plugin" when it finds no Chrome-family browser.
The browser relay (src/servers/api/browser/, src/extensions/browser-relay/) is a separate
extraction, agreed as its own plugin and not started. This plugin's setup-desktop.sh installs Brave,
which is what iris actually needs on the host.