Your playground, explained.
Write files as text. Boot a Linux VM. Capture what changed. Share the starting point.
The snapshot is the project
A snapshot uses txtar: a short header followed by named file sections. Files appear under /project. Press Run to boot or restart with the current snapshot. Editing does not run code automatically.
# apptron snapshot v1
-- .apptron/envrc --
cd /project
python3 hello.py
-- hello.py --
print("Hello from Apptron!")That Python example also needs overlay: gallery/python in its header. Start with a gallery sample for a complete working project.
.apptron/envrc runs before the interactive shell. .apptron/envbuild rebuilds the system environment when newer than its stored overlay; it needs a relay to download packages. Binary files use a section such as -- hello.wasm (base64) --, followed by base64. Unknown header keys are preserved. The v1 marker is required, paths must be relative, and duplicate file names are rejected.
Keep the system changes, too
A text snapshot contains project files and setup scripts. A disk overlay contains changed system files: installed packages, configuration, and their permissions and links. Add overlay: gallery/python or a HashBin CID to the snapshot header. The overlay is applied before Linux boots.
Capture snapshot waits for Apptron’s five-second sync and reads project files into the editor. It asks before replacing editor changes. Files that would exceed the text limit and symbolic links are skipped and listed. Empty directories and executable permissions are not represented by txtar; set permissions from envrc when needed.
More → Capture overlay packs the VM’s changed system files into a tar.gz with a runtime manifest. Download it, or review a HashBin quote and upload it. Saving an overlay adds its CID to the editor; share or save that updated text snapshot as well. Project, home, public, proc, sys, dev, and tmp are excluded. Overlay capture records changed files and directories; removal of a file from the base image is not preserved.
An overlay made with another runtime commit triggers a warning before loading. Gallery overlays rebuild with their runtime. A self-hosted overlay can be added to the runtime artifact as a gallery overlay; arbitrary remote URLs are not accepted in the header.
What stays, and where
The editor saves a draft in this browser’s local storage. Apptron stores project, home, and public files in IndexedDB and syncs them to the service worker’s local snapshot store. System scratch changes live only for the current VM session until captured as an overlay.
Snapshot identity is a SHA-256 hash of the exact text and runtime commit. Each identity has its own project, public files, home directory, and overlay. Running identical text resumes its stored files; editing the text or upgrading the runtime starts an isolated environment. Reset VM stops the current VM and clears that identity’s stored files. It keeps the editor text. Share links contain the editor’s snapshot, so capture VM edits before sharing.
The service worker adds browser isolation headers for native Wasm workers. On a first visit to Pages, the page reloads once to enable them, keeping the selected snapshot. Runtime bundles are cached by commit in Cache Storage. Private browsing, storage quotas, clearing site data, or changing browsers can remove local state. Use a downloaded snapshot or a share link for a portable copy.
Links, QR codes, and HashBin
Share captures and compresses the current text into ?compressed= using LZString. An uncompressed # fragment is also supported. The optional is.gd button sends the source link through the AllOrigins proxy. A failed shortening request leaves the source link available.
QR code creates a locally generated QR with SVG/PNG downloads, camera scanning and image upload/paste/drop. Camera permission is requested only after choosing Scan a code. A QR has room for about 2.9 KB of link text. If the source link is too long, save to HashBin and generate a QR for that saved link instead. The QR button uses the saved link while the editor still matches that saved source.
HashBin loads accept a CID, a https://256t.us/… URL, or an Apptron #CID link. Text uses the hashbin-diagram envelope with version 1 and type apptron. Saving requires a registered public client ID. You review the size, retention, exact price and balance on hashbin.org and approve each save there; this editor never holds a HashBin sign-in. The editor goes to HashBin and returns with your snapshot. Files above 512 KiB are downloaded and uploaded on hashbin.org instead.
| Item | Limit |
|---|---|
| Text snapshot | 1 MiB of UTF-8 txtar |
| HashBin document or compressed overlay | 5 MiB |
| Overlay, unpacked | 512 MiB / 30,000 entries |
| Gallery overlay | 128 MiB compressed in CI |
| Site artifact | Checked below 1 GB |
Snapshot security
Snapshots run untrusted code. The console area belongs to that code: never enter credentials there. Sign-in, permission and price prompts appear outside it. Shared, imported and restored drafts keep their source label after edits. Explicit links open independently of local drafts. Resume saved work offers earlier documents; opening or running a link does not overwrite them.
The current runtime restricts guest DOM access, hides other snapshots’ storage, and disables direct downloads, local folder pickers and Go/JS tasks. Native WASI still works. The default deployment still shares the editor’s origin. A separate-origin VM deployment is prepared but not activated. HashBin saves are approved on hashbin.org, so no credentials are kept here.
GitHub Pages projects under one account share browser storage across paths. Credential-holding apps should use dedicated origins, such as separate accounts or subdomains.
Offline editor and updates
The editor, docs, gallery and covers use a verified atomic application cache. Available offline describes that editor copy. VM runtime bundles and package overlays download only when Run needs them and remain in their separate commit-scoped, verified caches. The first VM boot and packages not previously downloaded require a connection. Repair offline copy retries the application cache; Update and reload preserves the complete snapshot before activation. VM execution always starts with an explicit Run, including after a shared link or QR scan.
Bring your own network relay
The VM has no network by default. GitHub Pages serves static files and cannot run Apptron’s WebSocket relay. Gallery overlays include Python, C build tools, Node, or terminal toys without requiring an in-VM package download. The Go sample downloads its toolchain bundles from this site on first use and mounts /tmp as tmpfs because its linker needs mmap.
Each exact snapshot source, runtime and relay needs approval before its first networked Run in a tab and is shown beside the console. Direct guest WebSockets are restricted to that same relay; leaving the setting empty blocks them. Use Network → Revoke network access to stop the VM and revoke its grants immediately.
To run the optional relay on your computer, initialize the submodule, then build and run Apptron’s worker:
git submodule update --init # Run in upstream/apptron: docker build --target worker -t apptron-relay . docker run --rm -p 8080:8080 apptron-relay
Choose More → Network and enter ws://localhost:8080/x/net. For a remote relay, use wss:// with HTTPS termination. The setting stays in this browser and is never placed in links or QR codes. Press Run after changing it. A relay gives the VM network access; it does not host a public site for files in /public.
Build the runtime locally
git submodule update --init npm ci scripts/build-runtime.sh npm start # Open http://127.0.0.1:4173/apptron/
Docker Desktop (or Docker Engine with Buildx and i386 emulation) is required. The script builds Alpine, the kernel bundle, boot WASM, matching Wanix loader, Go bundles, and gallery overlays. Large files stay in ignored runtime/<commit>/ directories. A first build can take a while. For a quicker core-only development build use CORE_ONLY=1 scripts/build-runtime.sh; package and Go samples require the full build.
The current Wanix image has an incompatible API, so the loader is built from the exact Wanix commit used by Apptron’s Go module. This compatibility choice is recorded in the lock and runtime manifests. Brotli intermediates are recompressed to gzip for Pages; the browser explicitly unpacks them. The offline DHCP fix lives in patches/, leaving the upstream submodule unchanged.
After a runtime release is published and its manifest hash is locked, scripts/fetch-runtime.sh downloads and verifies the release instead of rebuilding. npm test runs unit tests. npm run test:browser checks desktop and phone layouts in three engines. npm run test:boot boots Linux and verifies file capture and the Python overlay.