Skip to main content

exe-dev-atlas

A front door for an exe.dev VM: what is listening, what it is, and what to open.

exe.dev forwards ports 3000-9999 to https://<vm>.exe.xyz:<port>/ with no configuration, so a dev server started on one already has a URL. What it has no way to tell you is which ports are live and what is on them. The atlas serves that list on the port the bare hostname points at, so https://<vm>.exe.xyz/ becomes a launcher for everything else on the box, alongside the zellij sessions that have no port of their own.

One row per listening process, each carrying the port, the title the port served,
  the working directory, the command line, and the uptime, under a VS Code link

Install

$ uv tool install exe-dev-atlas
$ exe-dev-atlas install

exeuntu, the default exe.dev image, ships with uv, so there is nothing to install before that first line.

install writes a user systemd unit and starts it. serve runs the same server in the foreground. Both take --port (default 8000, also read from EXE_DEV_ATLAS_PORT).

Run this only on a VM you would hand somebody a shell on

Every row carries a process's full command line, its working directory, its user, and its pid, and that is the public half of what this serves. Command lines routinely carry secrets: a --backend-store-uri postgresql://user:hunter2@db/app, an --api-key, a token in an argument. /proc/<pid>/cmdline is world-readable, so the listing covers other users' processes on the box too, whatever this daemon can and cannot read of them.

So this page is only as private as the VM it runs on, and exe.dev's sharing controls are the only thing between it and a reader:

  • Never make a VM running the atlas public. share set-public <vm> drops the login requirement on the proxied port, and an unauthenticated caller sends no x-exedev-email header, so anybody who finds the hostname gets the page.
  • Read a Web share as a share of every command line on the box. share add <vm> <email> grants access to the VM's HTTPS proxy, and this page is on it. Withholding the zellij session names and the VS Code link from a non-owner is one degree less detail on the same page, not confidentiality.
  • The port itself is defended by nothing. The header the owner check reads is added by exe.dev's proxy. A caller that reaches the port without making that hop, an SSH tunnel or another user on the box, sends whatever address it likes and is served the owner's view.

share show <vm> says who has access today.

What it shows

One row per listening process in the proxied port range, pushed over SSE and updated within a second of anything changing. One port carries two rows where two processes hold it between them, one on loopback and one on a LAN address, since they are two services:

  • The port, linked, unless it is this page's own or it did not answer HTTP.
  • Whatever the port called itself: the <title> of the page it served, falling back to the process name.
  • The process behind it, its working directory, its owner, and how long it has been up.
  • 1-9 open the first nine links from the keyboard.

Listeners are found by polling, because the kernel offers no alternative: netlink's inet_diag answers a query rather than announcing a new socket, and /proc/net/tcp cannot be watched. A scan costs a few milliseconds, so it runs once a second and pushes only when the result differs from the last one.

Links are built from the browser's own location rather than from the VM name, so they stay correct whether the page was reached through the exe.dev proxy or an SSH tunnel to the same port.

What only the owner sees

The atlas is reachable by anyone the VM is shared with, so two things are withheld from everyone but the address the VM is owned by, as exe.dev's proxy reports it. This is a smaller distinction than it sounds, and the section above says what it does not cover:

  • zellij session names, which are often a project or a client name.
  • the VS Code Remote-SSH link, which only works for someone with SSH access anyway.

Ownership is decided once at startup from exe.dev's reflection integration, and the comparison fails closed: a reflection lookup that did not answer and an unauthenticated caller both produce an empty address, and an empty address matches nobody. A box whose lookup failed therefore serves the public view to everyone until it is restarted.

A zellij web server is the one port not linked directly. Arriving there without a session named in the path does not land on a picker, it creates a new session, so a link to its root would litter the box with an empty session per visit. Its existing sessions are listed individually instead, which is both the useful destination and the harmless one.

The systemd unit

install names the interpreter that ran it. exe-dev-atlas install is invoked by the installed CLI, so sys.executable is already an absolute path to an interpreter holding this package and its dependencies, and nothing has to be looked up on PATH or derived from a login shell:

ExecStart=/home/you/.local/share/uv/tools/exe-dev-atlas/bin/python -m exe_dev_atlas serve --port 8000

This tool does not fetch, build, or manage a Python environment. Whoever installed the package chose the version; install only points systemd at it. To upgrade, upgrade the package and run install again: an upgrade in place renders an identical unit, so the restart is what puts the new code in front of anything, and it happens whether the unit changed or not.

The unit carries only a standard system PATH, and nothing is looked up on it. The zellij binary a session lookup runs is read from the serving process itself, so it is the exact binary that is serving rather than whatever a lookup would find.

WantedBy=default.target starts the unit when the user manager starts, which without loginctl enable-linger <user> is at first login rather than at boot. install checks this and says so if it is off, because the failure is otherwise invisible: the unit is enabled, the file is correct, and nothing is running.

Requirements

Linux and Python 3.14. Every listener fact comes from /proc, read through psutil, so this is not portable off Linux, and the proxy's port range, its authentication header, and the reflection integration are all assumed to be exe.dev's.

Development

$ just setup
$ just test

just --list shows the rest. Built on without: without-http serves, without-web routes, without-html renders the shell, without-async supervises the scan task, and without-asgi both frames the event stream and serves the stylesheet and script out of an inventory walked once at startup.

Metadata

Release files for exe-dev-atlas 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for exe-dev-atlas 0.1.0
File Size Uploaded
exe_dev_atlas-0.1.0.tar.gz 33.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for exe-dev-atlas 0.1.0
File Interpreter ABI Platform
exe_dev_atlas-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 72.4 kB

Release files / exe_dev_atlas-0.1.0.tar.gz

Download URL exe_dev_atlas-0.1.0.tar.gz
Size 33.7 kB
Tags Source
SHA-256 checksum
How to use checksums
a5552d4c254d3f70b199938bcd6b24f4bfda4ec18f7cfb2466a80ed120432982
BLAKE2b-256 checksum
How to use checksums
a1ddec49c09a29a8168044ef2f9f971c239fdf950ce71d9a017c2aac9d6d5f3c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.6 {"installer":{"name":"uv","version":"0.12.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / exe_dev_atlas-0.1.0-py3-none-any.whl

Download URL exe_dev_atlas-0.1.0-py3-none-any.whl
Size 38.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0158cdbb67c0252b38c6759f642ccf825a33f0cccc16ccdbe05b2d8a75aca04b
BLAKE2b-256 checksum
How to use checksums
10b75ac6979aaf4600347e2431f8ecb13ade19be99dcb259f676fb2477445ce8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.6 {"installer":{"name":"uv","version":"0.12.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

0.3.0

2 release files

0.2.0

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page