machine-core
The sandboxed desktop machine: browser automation, desktop control, and capture.
Maturity: stable (90 %)
Machine core. A sandboxed Linux desktop for a user or a project that agents drive through browser and desktop automation, with a shell through the shared execute tool, a live stream in the workspace and a file source.
- Machines need access to a Docker engine; without one the platform runs with no machines.
- The first beta bundles an Ubuntu XFCE desktop; operators may configure a compatible custom image. Windows or macOS guest desktops are not offered.
- A shell inside a machine is root-equivalent there; the boundary is the container sandbox, the machine shell grant and network isolation, not per-path rules inside the machine.
- A project machine shares one browser profile among everyone who starts it.
@neuralis/machine-core is the workforce's hands and eyes: every user gets a
persistent virtual desktop — a full Linux desktop (XFCE on Ubuntu, based
on LinuxServer Webtop) running in its own Docker container and streamed into
the workspace as a widget over Selkies. An agent does not get a browser-shaped
API; it gets a computer.
Agents drive that desktop at three layers, all against the same live session:
| Layer | Surface | What it is for |
|---|---|---|
| Browser | machine_use with target: 'chromium' | A real Chromium driven over CDP — JavaScript-heavy pages, logged-in sessions, forms, visual verification |
| Desktop | machine_use with target: 'desktop' | The whole XFCE session — click any window, type anywhere, launch apps, screenshot or record the screen |
| Shell | execute with a registered source URI in cwd | Commands inside that source’s container |
The desktop is stateful across turns: browser logins stick, installed
applications stick, and files under /config/ stay on disk. The container
filesystem is also mounted as a regular source (machine://), so agents read
and write sandbox files with the standard fs_* tools — see
machine sources.
What the package provides
- Session management. Webtop containers are spawned lazily per
(project, source)through the host Docker socket, and then KEPT: an idle machine is stopped, never thrown away, so the next start takes seconds and everything installed inside it is still there. Deleting the container is an explicit act, and the persistent profile volume survives even that — the desktop feels like your machine. - Authenticated streaming. The Selkies HTTP and WebSocket stream is reverse-proxied through package routes with server-side Basic-auth injection — the browser never sees the stream credential. Minimizing the widget stops the pixels and leaves the machine running: the desktop, the browser session and anything an agent is doing on it carry on untouched, and reopening the widget picks the stream back up.
- Drive and shell.
machine_useretains itsactionenum andchromium | desktoptarget; agent-core’sexecuteroutes shell work by source URI. See the machine_use tool. - Vision capture. Screenshots come back as native image content blocks
that vision-capable models consume directly. Screen recordings are written
to the machine's recordings directory and returned as a
data://machine-core/recordings/<file>URI; the model loads it withfs_readwhen it needs the footage, and the platform then delivers it in the best form the active model can ingest. - A machine filesystem source. The manifest declares the
webtopconnector kind and onemachinesource instance on it, so the container filesystem is addressable atmachine-…://and reachable with the standardfs_*tools — see machine sources. - Skills and an always-active safety rule.
manage-machine-sessionswraps the session lifecycle routes,machine-drivingteaches the observe-act cadence, andrules/machine-safety.mdsupplies automatic constraints for machine operations when the package’s contributions are enabled — see machine-core skills. - A workspace widget. The
Machinewidget and its dock entry are declared in the manifest as App surfaces; the widget requires themachine.readfeature to appear at all.
Feature tiers
The manifest declares three features and grants them by role, deny-by-default — the standard features and access model:
| Feature | Grants | Default roles |
|---|---|---|
machine.read | View machine state, screenshots, recordings, page/DOM reads, session info — and a view-only live desktop stream | owner, admin, manager, member |
machine.drive | Mutating browser and desktop interactions — navigate, click, type, key, drag, launch apps — and control of the desktop stream: keyboard, mouse, clipboard, shell commands, upload, recording | owner, admin, manager |
exec.machine | Shell commands inside the machine container | owner, admin |
machine_use carries machine.read as its declared baseline gate; drive-class
actions escalate to machine.drive inside the handler because the required
feature depends on the action argument. Webtop shell through execute is the platform's exec rule: core.execute for the tool,
the connector-DECLARED entry exec.machine, then the source's own exec policy on the
directory the command starts in — after which the provider checks source scope and
lifecycle authority. Owners adjust grants per role through the
platform role configuration.
The desktop stream follows the same split. With machine.read alone you watch
your desktop live, but the stream server drops every keystroke, click, paste and
resize from your browser, and the widget header shows a View only badge so a
picture that ignores input never reads as broken. With machine.drive you
control it — and stream control is as powerful as the machine's own shell (a
keyboard into a terminal, or the dashboard's command runner), so grant it with
the same care as exec.machine. A default member gets the view-only stream
until an admin grants machine.drive, which also lets that member's agents run
drive actions.
Routes
| Method | Path | Feature | Purpose |
|---|---|---|---|
| GET | /api/packages/@neuralis/machine-core/health | machine.read | Docker/driver health plus a per-source isRunning map |
| GET | /api/packages/@neuralis/machine-core/sessions | machine.read | Current session info; probes container liveness on every call |
| POST | /api/packages/@neuralis/machine-core/sessions | machine.read | Ensure/spawn the session for the machine URI in body.uri (or ?uri=); omitted, the caller's first accessible webtop source is used |
| GET | /api/packages/@neuralis/machine-core/sessions/overview | machine.read | Every machine you can see, its state, and which lifecycle actions you may take |
| DELETE | /api/packages/@neuralis/machine-core/sessions | machine.read | Stop the machine — the container and everything in it are kept |
| DELETE | /api/packages/@neuralis/machine-core/sessions/container | machine.read | Delete the container; ?purge=1 also destroys the persisted profile volume of a stopped machine (409 while it runs) |
| GET/POST/PUT/PATCH/DELETE | /api/packages/@neuralis/machine-core/session/:key/stream/* | machine.read (+machine.drive for stream control) | Selkies HTTP reverse proxy over the allow-listed stream paths, with server-side auth injection |
Safety model
Every machine_use call is audit-logged with its action, target, session key,
and caller identity; every Webtop shell call is logged with the command. Each
session is owned by the user who started it: a project member can only inspect,
stop, or stream their own session, and the container filesystem
(machine-…:// via fs_*) is scoped to the owning project. The shell command
denylist is cosmetic friction, not a security boundary — the real boundary is
the container sandbox plus the exec.machine feature grant plus network
isolation. Dangerous key combos are rejected on the desktop, and recording goes
exclusively through the capped record action. The package also ships an
always-active safety rule and driving guidance — see
machine-core skills.
Sandboxed, but consequential
The machine cannot reach the Neuralis host process, but the browser inside it may be logged into real accounts and the filesystem persists. Treat drive actions as real-world actions — the shipped safety rule enforces exactly that posture on agents.
Default workflow template
The package ships a Web watch workflow template: a scheduled browser monitor that visits your URLs, extracts the meaningful content, diffs it against the previous snapshot, and reports only real changes — pair it with a channel binding to get alerts in Telegram or WhatsApp. It requires machine access, so only roles that can drive the machine see it.
Folder map
The pages in this section mirror machine-core's real package folders, so the docs map one-to-one onto the code:
| Package folder | Doc page | Cross-reference |
|---|---|---|
tools/ (machine_use) | Tools | package-system tools |
tools/machine_use.json (deep dive) | The machine_use tool | — |
src/routes/ (sessions, stream, health) | API & usage | package-system routes |
src/connectors/ (Webtop source) | Machine sources | package-system connectors |
docker/, sidecar/ (image + in-container agent) | Deployment | enterprise deployment |
skills/ (2 bundles), rules/ (machine-safety) | Skills | contributions |
workflows/ (Web watch template) | Workflows | — |
app/machine (Machine widget) | (see Deployment + App surfaces) | package-system App surfaces |
In this section
API & usage
The reach surfaces: machine_use and URI-routed execute, the HTTP routes and their feature gates, the webtop connector, and the typed cross-package API.
Tools
Browser and desktop automation through machine_use; Webtop shell through execute.
The machine_use tool
The unified action surface: navigation, interaction, capture, recording, and URI-selected shell execution.
Machine sources
The container filesystem as a source — exchanging files with the sandbox.
Deployment
Container image, Docker socket access, and runtime environment configuration.
Skills
Session lifecycle management and the machine-driving guidance.
Files UI
The Files workspace surface: browsing and searching sources, the editor and diff views, Git Control, pending-change review, and source administration.
API & usage
machine_use, URI-routed execute, the HTTP route surface and its feature gates, the webtop source connector, and the typed cross-package API.