Skip to content

CLI Reference

This is the complete reference for the public elsewindow command. The installed console command, repository launcher, python -m elsewindow, and standalone executables accept the same options. See Getting started for installation and the Xpra guide for runtime requirements, ownership, and troubleshooting.

Invocation

Choose one SSH authority, then put the remote executable and its arguments after --:

elsewindow [OPTIONS] --ssh-alias ALIAS -- APP [ARG ...]
elsewindow [OPTIONS] --host HOST --user USER [--port PORT] -- APP [ARG ...]

All Elsewindow options go before the application. Values after -- belong to the application, even when they look like Elsewindow flags. Quote arguments containing whitespace in the local shell. Argument boundaries and empty arguments are preserved; the application is passed as argv, not as an operator-supplied shell script.

The executable must be nonempty. The complete application argv is limited to 256 items and 16,384 UTF-8 bytes in total; NUL bytes are rejected. Executables without a slash are resolved on the remote PATH; paths with a slash refer to the remote host, not the client. Use an application mode that stays in the foreground instead of delegating to an existing instance.

All Options

disabled means that the flag is absent. — means there is no default value. The option inventory, defaults, and allowed choice tables are checked against the current CLI parser by the test suite.

Option Default Description
-h, --help — Print help and exit without starting a session.
--version — Print the Elsewindow version and exit.
--diagnose disabled Report packaged identities and local prerequisites without connecting.
--prepare-xpra disabled Prepare the isolated local Xpra Python environment without connecting.
--ssh-alias — Select a trusted OpenSSH host alias.
--host — Select a direct remote hostname or IP address; requires --user.
--user — Select the remote login user for --host.
--port 22 Select the direct SSH port; alias ports come from OpenSSH configuration.
--env — Set an application variable with NAME=VALUE, or copy a named local variable; repeat as needed.
--encoding-profile rgb Select a reviewed pixel transport profile.
--network-profile gigabit_lan Select the attaching client's quality and network policy.
--clipboard both Select clipboard synchronization on both peers.
--persistent disabled Keep the remote application after disconnect and resume it by argv.
--log-level warning Select one Elsewindow/Xpra logging policy on both hosts and for local terminal output.
--connect-timeout 120 s Limit startup of the owned SSH master, including authentication.
--ready-timeout 45 s Limit waiting for the owned remote Xpra session to become ready.
--probe-timeout 8 s Limit an individual remote session-metadata readiness probe.
--poll-interval 1 s Set the readiness and persistent-service observation interval.
--heartbeat-interval 10 s Set the ordinary session's ownership-heartbeat interval.
--lease-timeout 45 s Set how long an ordinary remote supervisor may wait without a valid heartbeat.
--cleanup-grace 5 s Allow graceful termination of the ordinary remote process group before forced cleanup.

Application Environment

Repeat --env NAME=VALUE to set variables for the remote application, or use --env NAME to copy an existing local variable before opening SSH:

elsewindow --ssh-alias workstation \
  --env APP_MODE=debug --env 'APP_LABEL=one two' --env LANG -- xterm

--env NAME= sets an empty value. An unset local name is an error. Repeated names use the last assignment; names are case-sensitive and must match [A-Za-z_][A-Za-z0-9_]*. Values preserve whitespace, newlines, equals signs, and Unicode. The local shell's normal quoting applies; Elsewindow does not expand variables or execute shell syntax remotely. Options after -- remain application arguments.

The overrides affect only the application and its descendants. They supplement its remote environment without changing SSH, Xpra, the supervisor, or desktop helpers. PATH also controls remote lookup of an executable without a slash. DISPLAY, WAYLAND_DISPLAY, XDG_RUNTIME_DIR, and names beginning with DBUS_ or ELSEWINDOW_ are reserved for the owned session. Up to 128 variables and 8,192 UTF-8 bytes are accepted, counting each name, value, equals sign, and terminating NUL; NUL bytes inside values are invalid.

For --persistent, the initial explicit variable set is part of the recorded launch configuration. Reconnect with the same names and values; their order does not matter. Changing or omitting a recorded override produces persistent_environment_mismatch. Exit the application before starting it with different values. The session key remains based on the resolved application argv. Setup and diagnosis cannot be combined with --env.

Informational Commands

-h / --help prints the accepted syntax. --version prints the version resolved from the packaged version authority. Neither requires an authority or application, and neither opens SSH.

--diagnose reports the Elsewindow and installed ssh-wrapper identities, SHA-256 digests of the packaged YAML, remote-helper sources and Xpra lock, Linux support, and resolution of local commands. It also revalidates the prepared Xpra environment. It exits with status 1 if these checks fail, otherwise 0. It does not start Xpra, validate GPU rendering, or inspect the remote host. Run it without a session authority or application:

elsewindow --diagnose

Prepare Xpra

--prepare-xpra explicitly creates or repairs the local Xpra environment using the system Python and the bundled hash-locked PyOpenGL pair from PyPI. It needs the distribution's Xpra, Python venv support, GTK and OpenGL libraries already installed. It does not install system packages or open SSH. This works with the repository launcher, installed package, and standalone executable. It cannot be combined with --diagnose, a session authority, or an application.

Preparation prefers the accelerator's prebuilt wheel. If none exists for the system interpreter and architecture (including Linux arm64), it builds the hash-verified source archive using separately locked temporary build tools. That route also needs the system C compiler and Python development headers (build-essential and python3-dev on Debian/Ubuntu). Preparation never installs those system prerequisites automatically. The temporary build packages are removed from the Xpra environment after installation.

The repository's make runtime-venv prepares both environments, storing the Xpra additions in .venvs/<machine-user-key>/venv-xpra. Installed and standalone commands default to the elsewindow/<machine-user-key>/xpra-venv directory beneath the user's XDG data directory. The key is an application-specific hash of /etc/machine-id and the local UID, so a shared data directory keeps each host's interpreter and native additions separate. A missing or invalid machine ID is an error. ELSEWINDOW_XPRA_VENV can select an exact dedicated absolute directory instead; an explicit override must not be shared between hosts. Ordinary startup only validates the prepared environment and fails with setup guidance if its current lock, system interpreter, or installed package bytes differ. Setup, diagnosis, and session startup resolve symbolic links to the same system Xpra executable. Installed-file validation allows up to three minutes for slow shared storage. A validation timeout is reported separately from a stale environment and does not trigger reinstallation; retry the command once storage is responsive.

SSH Authority

--ssh-alias ALIAS uses a trusted OpenSSH configuration entry, including its user, port, identity, host-key policy, and supported authentication setup. Do not combine it with --host, --user, or a direct port override. Configure an alias's port in OpenSSH itself.

Alternatively, use --host HOST --user USER. The host is a hostname or IP address, not an SSH URI or a combined user@host string. --port PORT accepts an integer from 1 through 65,535 and defaults to 22 in direct mode. IPv6 addresses must be unbracketed.

elsewindow --ssh-alias workstation -- xterm
elsewindow --host host.example --user desktop-user --port 2222 -- xterm

Both forms perform one deliberate authentication and use only channels backed by the owned master. They never reconnect automatically after master loss. See the security model for the fixed SSH isolation policy.

Profiles And Clipboard

Only reviewed profiles are selectable. There are no public switches for an Xpra backend, display, session name, title, individual encoder, decoder, colorspace converter, pixel format, or renderer. Those choices come from the packaged profile configuration; the remote backend is always Wayland.

Custom application cursors, vertical and horizontal mouse-wheel forwarding, keyboard-state synchronization, and modal-window handling are enabled by default in both session lifetime modes, as are remote application notifications. The local desktop's notification service presents them; its do-not-disturb, permissions, and visibility policies still apply. DPI is detected instead of forced to a fixed value. Client scaling is allowed but starts at 1:1; there is no automatic zoom or extra Elsewindow CLI switch for these ordinary GUI features. See the minimal-base review for the retained restrictions.

Encoding Profile

--encoding-profile PROFILE selects the pixel transport used by both peers. The default is rgb.

CLI value Canonical transport and policy
rgb rgb.strict
h264 h264.adaptive-alpha

The strict RGB policy disables video codecs and CSC and uses the non-OpenGL client path. The adaptive-alpha H.264 policy selects native libva H.264, server-side libyuv, and native client OpenGL while retaining the canonical alpha-capable and lossless alternatives declared by the fork.

H.264 requires usable DRM render nodes and hardware-specific VA-API drivers on both hosts. Before SSH startup, Elsewindow checks the public local xpra opengl result. Missing local acceleration selects the RGB client profile; an inaccessible remote render device selects RGB on both peers. Each fallback warns with driver/package guidance and does not install anything. Detailed codec, alpha, GPU, and application acceptance belongs to the maintained fork.

Network Profile

--network-profile PROFILE selects the attaching client's minimum quality, minimum speed, auto-refresh delay, refresh rate, and bandwidth limit. The default is gigabit_lan. The complete table is checked against the packaged YAML mirror:

Profile Minimum quality Minimum speed Auto refresh Refresh rate Bandwidth limit
gigabit_lan (default) 90 90 0.10 s 60 Hz unlimited (0)
fast_wired 82 80 0.20 s 60 Hz 50 Mbps
mobile_5g 78 75 0.30 s 45 Hz 25 Mbps
mobile_4g 68 70 0.45 s 30 Hz 8 Mbps
power_saving 72 70 0.50 s 30 Hz 8 Mbps

A persistent session may be resumed with a different network profile because this option affects only the new local client.

Clipboard

--clipboard POLICY applies the clipboard policy explicitly to both Xpra peers. The default is bidirectional both.

Value Synchronization
off Disabled on the local client and remote server.
to-server Local client to remote server only.
both Bidirectional.

Clipboard contents cross the owned SSH mux as Xpra protocol data; no forwarding socket is opened. Use a narrower policy when data must not cross that trust boundary. See the security model and clipboard logging before debugging with sensitive data.

elsewindow --ssh-alias workstation --encoding-profile h264 \
  --network-profile mobile_5g --clipboard=to-server \
  -- /opt/application/bin/application

Session Lifetime

Native journal recording is optional. If journald is unavailable on either host, Elsewindow warns with the systemd package and service setup guidance and keeps the application, terminal output, and owned remote log relay running.

Optional Desktop Features

--diagnose reports local optional support once the essential local setup is valid. Missing optional support does not make diagnosis fail. Remote checks run after the single SSH authentication; portal startup is checked once the remote display exists.

Every invocation checks notification prerequisites on both hosts. Missing local desktop notification service/bindings or remote D-Bus bindings disables delivery for that connection with a warning identifying the affected host and the Debian/Ubuntu packages: dbus-daemon python3-dbus python3-gi. The local desktop must also provide a running notification service; dunst is an option for a desktop without one. Do-not-disturb and presentation permissions remain local desktop policy.

Some applications draw their own notification windows instead of calling the desktop notification service. Zed's agent notifications are such windows, and the remote backend is always Wayland. With Zed's default "notify_when_agent_waiting": "primary_screen", Zed opens no notification window in any Wayland session: its Wayland backend reports no primary display, attention requests have no Wayland effect, and the completion sound is not forwarded. Set this in the remote Zed settings:

{ "agent": { "notify_when_agent_waiting": "all_screens" } }

Zed then opens one small borderless window per remote output. Elsewindow forwards it like any other application window, and the local window manager places it; Wayland does not let Zed choose the corner of the screen.

Remote portal file dialogs and portal notifications additionally require xdg-desktop-portal xdg-desktop-portal-gtk python3-gi. If these are missing or cannot start on the private session bus/display, Elsewindow warns and starts the application without portal support. Ordinary freedesktop notifications do not require the portal packages. File dialogs select remote files. OpenURI and local file/URL opening remain disabled.

The clipboard, cursor, wheel, keyboard-state, scaling and modal-window features use the maintained Xpra packages and GTK already required to display the application; they do not require xclip, wl-clipboard, a portal, or a desktop notification daemon. SSH, Python, the verified Xpra installation, the graphical display, and session-ownership checks remain essential: without them there is no usable owned GUI session to continue.

Persistent

--persistent starts or resumes an owned transient user systemd service. Without it, the ordinary heartbeat-supervised session ends on client or SSH loss. In persistent mode, client exit and SSH loss leave the remote application running. Repeat the same invocation to resume it:

elsewindow --persistent --ssh-alias workstation -- /opt/application/bin/application

The session key uses the absolute remote executable invocation path and exact ordered arguments, including empty arguments, within the remote account and host. Changing arguments creates a different session. Executable symlinks are preserved, including virtualenv interpreters and links to versioned programs. Names without a slash are resolved on remote PATH before deriving the key.

An existing session must retain its encoding, clipboard, and logging policy. Optional remote feature decisions also remain fixed for that running session; installing or removing packages affects new sessions, not the existing server. Reconnect still checks current local capabilities and can disable local delivery or use RGB without replacing the persistent application. An incompatible reconnect is refused without stopping or replacing it; use the original settings or exit the application first. The network profile may change because it applies only to the attaching client. Services created before journal support cannot be adopted.

The remote account must have a working user systemd manager and linger. Elsewindow checks this on every invocation. If linger is off, the invoking terminal must supply exact y or yes before Elsewindow enables it for that account, using remote sudo when required, and verifies the result. A refusal or missing terminal leaves the account unchanged. If persistence prerequisites are unavailable or consent is not granted, a new application runs as an ordinary session with an explicit warning: disconnecting the client or SSH will stop it. On Debian/Ubuntu the relevant remote packages are systemd libpam-systemd; a working user manager and approved linger are also required. Recorded persistent state prevents this fallback, including when its service cannot be inspected: restore the prerequisites to resume it. Elsewindow never starts a duplicate application to work around an uncertain existing session. Linger remains enabled afterwards and affects the account's other user services too; ask the administrator to disable it when no longer wanted.

Persistent sessions survive detach, client crashes, terminal closure, and SSH loss, but not host reboot, an administrative service stop, or an Xpra crash. Exiting the foreground application with any status ends its session. There is no automatic reconnect or restart; each manual invocation authenticates once. The application starts immediately under the service, so a failed first attach may leave it running. Retry the same command to inspect and resume it. Ordinary sessions start the application only after the graphical client connects. See lifecycle and isolation.

Logging

Log Level

--log-level LEVEL selects the same logging policy for Elsewindow and Xpra on both hosts. The default is warning.

Value Included records
critical Critical failures only.
error Errors and critical failures.
warning Warnings, errors, and critical failures.
info Informational records and all more severe messages, including Elsewindow lifecycle events.
debug General Xpra debugging and all more severe records.
debug-clipboard Clipboard diagnostics in addition to the warning baseline, including local XFixes selection events.

The local journal and terminal contain four explicitly marked sources:

Source Journal identifier and terminal prefix
Local Elsewindow elsewindow-local
Remote Elsewindow helper elsewindow-remote
Local Xpra elsewindow-xpra-local
Remote Xpra elsewindow-xpra-remote

Every message includes [session=<id>]; the same ID is stored in the native ELSEWINDOW_SESSION journal field on both hosts. Ordinary invocations have unique IDs. Persistent IDs remain stable across reconnects and distinguish remote machines, accounts, and executable/argument combinations. Concurrent clients observing the same persistent application share its session ID; ELSEWINDOW_SOURCE_PID distinguishes their producing processes.

The server writes only its two remote sources to its journal. New remote records travel to the client through the existing authenticated SSH master. History produced during a disconnection is not replayed. Locally the same filtered records go to the journal and terminal: warning/error/critical to stderr, and info/debug to stdout. There is no separate terminal verbosity. Both debug modes warn that logs may expose clipboard contents or other sensitive data; use only non-sensitive test data. Persistent startup briefly buffers early local diagnostics until the remote identity is known, then writes them with that same ID. If startup fails before identification, its diagnostics use one unique invocation ID instead.

elsewindow --log-level=debug-clipboard --ssh-alias workstation -- xterm

A persistent service retains its original level; reconnect with that same level or exit the application before starting with a new policy. A service created by an older helper without log forwarding must also exit before this logging protocol can be used; the client never silently replaces it. See the system journal for reading records, session filters, availability requirements, and host-controlled retention.

Timeouts And Intervals

All seven timing options in the option table accept finite seconds from 0.1 through 900, inclusive. Fractional values are supported. --lease-timeout must be strictly greater than twice --heartbeat-interval. These values are validated before opening SSH.

--connect-timeout applies to each new owned SSH master. --ready-timeout bounds the readiness-wait phase after the server or service has been started or selected; --probe-timeout limits each remote session-metadata query in that phase. They are not global launch deadlines: capability checks, persistent control operations, and linger consent have their own handling. --poll-interval controls readiness polling and repeated observation of a persistent service, not the Xpra frame rate.

--heartbeat-interval, --lease-timeout, and --cleanup-grace govern the ordinary remote process group. Lease expiry leads to owned cleanup; the grace period allows termination before escalation. They do not configure the persistent service, although the same CLI validation still applies. Connection, readiness, and probe timeouts remain relevant to each persistent attach attempt. No timing option enables reconnection or extends ownership to unrelated resources.

See errors and diagnostics for runtime failure codes and the security model for cleanup boundaries.