Run kxen from a browser without giving up any feature
Browser access from the desktop app#
The desktop app runs an embedded service the moment it starts, listening on 127.0.0.1, preferring port 7824 and falling back to a random port if that's taken. The system tray menu is your management entry point:
- "Browser access (127.0.0.1:7824)": toggles browser reachability; the checked state persists to
[web] enabledin configuration. - "Open in browser": opens the full token-bearing URL in your system browser.
- "Copy access link": copies that same URL so you can paste it into another device or window.
- "Default open action": decides whether the tray's left-click opens the window or the browser (
[tray] default_open,windoworbrowser). - "Minimize to tray on close": closing the window doesn't quit the app (
[tray] close_to_tray).
The desktop app's embedded service only listens on loopback — it's never exposed to your LAN. Any exposure beyond that only ever happens through the explicit --bind flag on kxen.
The kxen headless server#
kxen is a GUI-free standalone executable, published for all six platforms — it fits a server or an always-on machine. The macOS release is Developer ID signed and Apple notarized, same as the desktop app; details are in Code signing:
kxen --bind 127.0.0.1 --port 7824On startup, stdout prints the full token-bearing access URL — open it in a browser and you have every feature. Flags:
| Flag | Default | Description |
|---|---|---|
--bind <IP> |
127.0.0.1 | Listen address; binding a non-loopback address exposes it to your LAN and prints a warning |
--port <PORT> |
7824 | Listen port; if it's taken, kxen errors out instead of silently switching ports |
--token <TOKEN> |
random each run | A fixed token lets you bookmark the URL; without it, the token changes every startup |
--allow-host <HOST> |
none | Extends the Host-header allowlist, repeatable; a remote hostname must be added explicitly |
-h, --help |
- | Print help |
The KXEN_DATA_DIR environment variable overrides the data directory, and RUST_LOG controls log filtering.
Docker#
Every kxen CLI release is also packaged as a multi-arch image (linux/amd64, linux/arm64), published at ghcr.io/stringke/kxen:
docker run -d --name kxen -p 7824:7824 -v kxen-data:/data ghcr.io/stringke/kxen:latest
docker logs kxen # view the token-bearing access URLThe image starts with kxen --bind 0.0.0.0 --port 7824 by default, and persists data in the /data volume. For remote access, terminate TLS in front of the container (tailscale, for example); override the listen address, port, or token directly on the startup arguments:
docker run -d -p 7824:7824 -v kxen-data:/data ghcr.io/stringke/kxen:latest --bind 0.0.0.0 --token <fixed-token>The image doesn't include Chrome or any desktop integration, so the Browser tool isn't available in it — everything else matches the kxen binary.
Token security model#
- The token is your only access credential. Anyone with the token-bearing URL gets full access — never share the URL, and never commit it to a repository or paste it into chat tools.
- The token is delivered exactly once, through the URL: the frontend reads it, stores it in
sessionStorage, and strips it from the address bar. No HTTP response ever carries the token. - The Host-header allowlist only permits
localhost,127.0.0.1,[::1], and the actual bind address by default. Any other hostname — including a reverse-proxy domain — must be added explicitly with--allow-host, or the request gets rejected. kxenonly serves plain HTTP and doesn't implement TLS itself. Remote access must terminate TLS in front of it.
Remote access#
We recommend tailscale to terminate TLS, since kxen doesn't implement its own:
kxen --bind 127.0.0.1 --allow-host <your-host>.ts.net
tailscale serve --bg 7824tailscale serve proxies https://<your-host>.ts.net to your local port 7824 — open that HTTPS address in a browser and you're in. Adding <your-host>.ts.net to --allow-host is a required step, or the Host allowlist rejects the request.
Binding directly to --bind 0.0.0.0 and exposing it to the public internet skips TLS entirely — the token would travel the network in plain text. That's not a supported remote setup.
What's different from the desktop app#
OS integrations your browser physically can't do degrade gracefully in Web Mode; everything else stays the same:
- App updater: no auto-update in Web Mode — upgrade
kxenby downloading a new release package. - Native dialogs: adding a Workspace becomes typing the project's absolute path; attachments go through the browser's file picker.
- OS desktop notifications: fall back to an in-app notification center.
- Window, tray, and "minimize to tray on close" desktop integrations don't exist.
- Apple's speech-recognition engine is only available in the macOS desktop app.