remotebox-connect
The remotebox outbound connector — the sole connector implementation. It
started as a dependency-free native port of the Python connector CLI that
lived in pplx/python/sdks/remotebox (published as perplexity-remotebox);
that CLI has since been deleted. One static binary replaces the Python 3.12+
runtime and its dependency floor for BYOC dogfooding; see ASI-6627. Run it
from the repo with bin/remotebox-connect.
One documented exception to "dependency-free": if Cloudflare blocks the
built-in HTTP client's TLS fingerprint during the browser OAuth token
exchange (seen on devboxes), the flow falls back to the system curl binary
(src/auth.rs). Steady-state connector operation — connect, exec, file
transfer, reconnect — never shells out to external tools.
The wire protocol, reconnect behavior, auth flows, token-cache paths, and CLI
flag surface are 1:1 ports of the retired Python connector — except the
experimental sidecar flags below, which are new — and must stay compatible
with the fs-ws-mux broker, whose protocol implementation lives in
pplx/python/sdks/remotebox/protocol.py. When changing that protocol, mirror
the change here (and vice versa) — the loopback tests in tests/loopback.rs
encode the shared contract, and the fs-ws-mux loopback suite
(pplx/python/apps/asi/src/workers/fs_ws_mux/tests/test_remotebox_loopback.py)
runs this binary against the real broker.
Known wire divergence, kept deliberately: pydantic parses arbitrary-precision
integers, so the Python protocol implementation accepts integer fields that
overflow the Rust field's storage (e.g. a max_output_bytes above
i64::MAX); the Rust connector rejects such frames at parse time with an
error frame. No real client emits these values — the broker and SDKs stay
within i64 — and every case is pinned by the DIVERGES rows in
tests/python_golden.rs.
System proxies are honored like the Python connector was (it inherited them
from websockets' proxy=True default): wss_proxy/https_proxy (or
ws_proxy/http_proxy for ws:// brokers) with no_proxy bypass, tunneled
via HTTP CONNECT with optional Basic auth. https:// (TLS-to-proxy) and
SOCKS proxies are rejected with a clear error instead of dialing directly
(src/proxy.rs).
Experimental EnvD-compatible sidecar (opt-in)
--envd-binary <path> makes the connector spawn a compatible EnvD binary
as its child process and proxy v2 envd_request frames to it over loopback
(--envd-port, default 49983); without the flag the connector serves legacy
frames only. After successful startup the connector advertises EnvD executor
eligibility during registration. Sidecar mode is Linux-only (supervision relies on PDEATHSIG);
on other platforms --envd-binary fails at startup while the legacy path
keeps working. Exactly one EnvD may exist per box, and it must be the one this
connector spawned, because initialization hands it the generated access
token.
Startup enforces that invariant rather than assuming it: it refuses to start
if anything already listens on the port (an EnvD orphaned by an earlier
kill -9, or an unrelated squatter — either would answer the health check
in place of a child that lost the bind race and exited), and it re-verifies
the spawned child is alive after initialization. On exit the child dies with
the connector, including SIGTERM/SIGKILL (PDEATHSIG), so no stale EnvD can
survive to shadow the next run. The sidecar's HTTP client never uses system
proxies.
The supported sidecar is the :envd_host Bazel target in this package. It
builds a pinned EnvD 0.6.13 source revision with the small downstream
envd-host.patch: --host allows the connector to bind it to 127.0.0.1,
commands may run as the current user when EnvD is unprivileged, and self-upgrade
is disabled in host mode. The upstream defaults are unchanged. The connector
still verifies /proc/net/tcp before initialization and fails closed unless
the listener is exclusively loopback.
Production asi-prod runs spaced-svc inside its Firecracker guest, not a
standalone EnvD binary. The host build therefore targets the same EnvD API
behavior, not a byte-identical Space runtime.
Build and test
cargo build -p remotebox-connect
cargo test -p remotebox-connect
bin/bazel build //pplx/rust/apps/remotebox-connect/...
bin/bazel test //pplx/rust/apps/remotebox-connect/...
# Current connector plus pinned EnvD host build in one Linux tarball.
bin/bazel build //pplx/rust/apps/remotebox-connect:remotebox_bundle
# Exercise stock AsyncSandbox through broker -> connector -> packaged EnvD.
bin/builder execute-functional-test \
//pplx/python/apps/asi/src/workers/fs_ws_mux:remotebox_canary_test
Install
Release 0.1.0 and later of perplexity-remotebox ship the native Rust
connector. Install it from PyPI into an isolated tool environment:
uv tool install perplexity-remotebox
remotebox-connect --email you@perplexity.ai
The Linux wheels also install the pinned EnvD sidecar as
remotebox-envd. Opt in to the preview executor with:
remotebox-connect \
--email you@perplexity.ai \
--envd-binary "$(command -v remotebox-envd)"
macOS wheels contain only remotebox-connect; sidecar mode is Linux-only.
The connector itself has no Python runtime dependency after installation.
Run
target/debug/remotebox-connect --email you@perplexity.ai
target/debug/remotebox-connect --doctor
bazel-bin/pplx/rust/apps/remotebox-connect/remotebox-connect \
--email you@perplexity.ai \
--remotebox-id "$DEVBOX_ID" \
--dir /home/dev \
--envd-binary bazel-bin/pplx/rust/apps/remotebox-connect/envd-host
Flags match the retired Python remotebox-connect CLI (--email,
--doctor, --default-url, --broker-url, --auth-base-url,
--oauth-token-base-url, --remotebox-id, --dir, --fresh-login,
--verbose).
Versioning
Cargo and unstamped Bazel builds report 0.0.0+local. Stamped Bazel builds
embed the workspace version (same pattern as pplx-cli):
bin/bazel build --config=stamp //pplx/rust/apps/remotebox-connect:remotebox-connect
# remotebox-connect 2026.07.14.1784060218+5d78235
The version is sent as X-App-Version on every broker connection and is what
broker-side minimum-version enforcement keys on.
Publish to PyPI
The PyPI publisher builds the Linux amd64/arm64 and macOS amd64/arm64 wheels before uploading any of them. Preview and publish a release with:
bin/builder publish-wheels \
//pplx/rust/apps/remotebox-connect:remotebox_connect_package \
--registry pypi \
--version 0.1.0 \
--dry-run
PYPI_TOKEN=pypi-... bin/builder publish-wheels \
//pplx/rust/apps/remotebox-connect:remotebox_connect_package \
--registry pypi \
--version 0.1.0
PyPI versions are immutable. Confirm the version is unused and run the wheel
tests before removing --dry-run.
Status / follow-ups (ASI-6627)
The Python connector CLI and its perplexity-remotebox PyPI publish rail are
deleted; the shared Python protocol remains at pplx/python/sdks/remotebox
for broker-side consumers and compatibility tests. Remaining follow-ups:
- A non-PyPI install path for machines without Python (
curl | shor a standalone archive). - Yank the published
perplexity-remotebox0.1.0.dev1 from PyPI (manual, outside the repo).
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file perplexity_remotebox-0.1.0-py3-none-manylinux2014_x86_64.whl.
File metadata
- Download URL: perplexity_remotebox-0.1.0-py3-none-manylinux2014_x86_64.whl
- Upload date:
- Size: 14.3 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7105393fe104bce156a4e55bcd0e5e37c01b5da2efb65d668a944a18ec74b441
|
|
| MD5 |
d02d2d9bef058e12eb0c672991642074
|
|
| BLAKE2b-256 |
eef54e581f295db3f153812f81b96010259046e56a484c8434c71628821dc939
|
File details
Details for the file perplexity_remotebox-0.1.0-py3-none-manylinux2014_aarch64.whl.
File metadata
- Download URL: perplexity_remotebox-0.1.0-py3-none-manylinux2014_aarch64.whl
- Upload date:
- Size: 13.4 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5a41f6bf8c759dd9c7d3e4c3eeb64ea90e50642368ce9950969c22a25e7dc344
|
|
| MD5 |
05c6cc6f677816a3c3650630731986d8
|
|
| BLAKE2b-256 |
7c64096a708d88307ba5251821fd29e270243875f3bb9a361615069db3e2d76d
|
File details
Details for the file perplexity_remotebox-0.1.0-py3-none-macosx_14_0_x86_64.whl.
File metadata
- Download URL: perplexity_remotebox-0.1.0-py3-none-macosx_14_0_x86_64.whl
- Upload date:
- Size: 4.9 MB
- Tags: Python 3, macOS 14.0+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
49e0422880fc2e7fa3c3191cbb7e268e60cda91d397441b1268cc9bd6ad80d22
|
|
| MD5 |
fdf55cb5732ec3e21ee8c9a7dab0bf25
|
|
| BLAKE2b-256 |
e5f0701b4ec120086342607944faafba8bee5fdc8d3ed598af37b3c0e70f3a6e
|
File details
Details for the file perplexity_remotebox-0.1.0-py3-none-macosx_14_0_arm64.whl.
File metadata
- Download URL: perplexity_remotebox-0.1.0-py3-none-macosx_14_0_arm64.whl
- Upload date:
- Size: 4.7 MB
- Tags: Python 3, macOS 14.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3103798fc88b8dc8ed6e50793a3df7c8373f001428f9f2a9c64101c4a31c4dee
|
|
| MD5 |
b26223057c64a9fc11a28a4d499bd954
|
|
| BLAKE2b-256 |
cb70538d6050ea94dd0645ec1d332aabe074688953ff74636d9ae8ba2f7c4630
|