Keep simplex-chat running
If you want the SimpleX runtime to start automatically on login or machine boot, let the host OS supervise it and keep OpenClaw focused on the channel connection itself.
The plugin CLI can generate and install a host service for the current machine:
systemd —user on Linux, launchd on macOS, and SysV init as a Linux fallback. It prints the generated service file and next commands first, and it asks for interactive approval before writing files. It prints supervisor commands for the operator to run instead of executing them from the plugin. Use —provider systemd, —provider launchd, or —provider sysvinit to override detection.
Common install options:
—dry-run with install to print the plan without writing files.
The runtime must run with both
—files-folder and —temp-folder, and those directories must exist before it starts, or sending and receiving files fails. This failure is silent: simplex-chat started with -p does not log it. The service the CLI helper generates creates both folders on start, so this is handled for you. If you hand-write a service file or run simplex-chat directly, create them first with mkdir -p ~/.simplex/files ~/.simplex/tmp. openclaw simplex runtime doctor warns when the files folder is missing or not writable.examples/:
examples/docker-compose.sidecar.yml: OpenClaw plus a privatesimplex-chatsidecar network.examples/systemd/simplex-chat.service: hardened user service template.examples/caddy/Caddyfile: TLS/auth proxy example for exceptional remote WebSocket access.
Decide which settings go where
Use this rule:- put OpenClaw channel behavior in
channels.openclaw-simplex - put
simplex-chatprocess startup flags in the supervised service command line
-
connection.wsUrl -
connection.allowUnsafeRemoteWs -
connection.connectTimeoutMs -
connection.autoAcceptFiles -
connection.filesFolder -
connection.outboundFolder -
connection.outboundFolderOnClient streaming.nativeTransportand related live-reply throttling fieldsmessageTtlSecondsandfilePolicydmPolicy,allowFrom,groupPolicy
- relay and proxy selection:
—server,—xftp-server,—socks-proxy,—host-mode,—smp-proxy - local storage/layout:
—database,—files-folder,—temp-folder,—log-file - runtime process behavior:
—device-name,—maintenance,—mute,—mark-read
Locating received files (connection.filesFolder)
connection.filesFolder is the path where OpenClaw reads files the runtime received. When the runtime is started with —files-folder, it reports received files by name only (not a full path), and the plugin joins that name to connection.filesFolder (default ~/.simplex/files) to read the bytes. Without —files-folder the runtime reports absolute paths and this setting is unused.connection.filesFolder depends on the topology:
- Shared filesystem (OpenClaw and the runtime see the same paths — e.g. both on one host, or both in one container): set
connection.filesFolderto the same path as—files-folder. - Containerized runtime with a shared volume: when the runtime runs in a container, its filesystem is separate from OpenClaw’s (whether or not OpenClaw is containerized too), and each side usually mounts the shared volume at a different path — that is fine. Set
—files-folderto the runtime’s mount andconnection.filesFolderto OpenClaw’s mount of the same volume. An absolute path would break here, because the runtime’s directory does not exist on OpenClaw’s side; the name-only reporting is exactly what bridges the two mounts.
/data/files/photo.jpg and reports photo.jpg; OpenClaw reads it from /shared/simplex/photo.jpg — same volume, different mount paths, bridged by the file name.
Sending files (connection.outboundFolder)
connection.outboundFolder is the directory OpenClaw stages an outgoing file into before telling the runtime to send it. There is no runtime flag for this — on send OpenClaw passes a path that the runtime resolves on its own side, so the file must be readable there. When OpenClaw and the runtime share a filesystem (the default), leave this unset and the local file path is passed as-is; it only matters when the runtime is containerized.connection.outboundFolder:
pic.jpg into /tmp/simplex-outbound and passes /tmp/simplex-outbound/pic.jpg; the runtime reads that same path, then the staged file is removed after the send.
Different paths (path translation). When the two sides can’t mount the volume at the same path, add connection.outboundFolderOnClient — the same directory as the runtime sees it. OpenClaw writes to outboundFolder but rewrites the directory prefix to outboundFolderOnClient before sending, so no verbatim path is needed:
pic.jpg into /srv/openclaw/outbound and sends /data/.simplex/outbound/pic.jpg; the runtime reads its own path. (This is also the case when OpenClaw runs on the host and the runtime in a container — set each side’s path accordingly.)
Manual service files
The CLI helper above is the preferred path. These examples show what it writes and are useful when you want to manage the service definition yourself.- Linux
- macOS
Adjust the
ExecStart path if simplex-chat is installed somewhere other than %h/.local/bin/simplex-chat. The extra flags above are examples of runtime-owned settings that do not belong in OpenClaw channel config.Start it
- Linux
- macOS
Check status
- Linux
- macOS
active (running).Common startup flag patterns
These are reasonable patterns to consider when you runsimplex-chat as an external service:
- fixed local identity label:
—device-name “OpenClaw SimpleX” - explicit file locations:
—files-folder ~/.simplex/files —temp-folder ~/.simplex/tmp - custom relay policy:
—server “smp1.example.com smp2.example.com” —xftp-server “xftp1.example.com” - SOCKS/Tor routing:
—socks-proxy :9050 —host-mode onion —required-host-mode - stricter message routing:
—smp-proxy always —smp-proxy-fallback no
Maintenance mode
If you need to bring up the runtime without immediately serving chat traffic, run it with—maintenance and start chat manually inside the runtime later.
This is a simplex-chat operational mode, not an OpenClaw channel config field, so it belongs in the service command only when you intentionally want that behavior.
Remote WebSocket endpoints
Prefer loopback, a private sidecar network, orwss:// with access controls. Plaintext ws:// endpoints on non-loopback hosts are blocked by default because the WebSocket API controls the SimpleX runtime.
Only set connection.allowUnsafeRemoteWs: true when that endpoint is protected by a private network, firewall, or authenticated TLS proxy.