Skip to main content

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 | sh or a standalone archive).
  • Yank the published perplexity-remotebox 0.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

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

perplexity_remotebox-0.1.0-py3-none-macosx_14_0_x86_64.whl (4.9 MB view details)

Uploaded Python 3macOS 14.0+ x86-64

perplexity_remotebox-0.1.0-py3-none-macosx_14_0_arm64.whl (4.7 MB view details)

Uploaded Python 3macOS 14.0+ ARM64

File details

Details for the file perplexity_remotebox-0.1.0-py3-none-manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for perplexity_remotebox-0.1.0-py3-none-manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 7105393fe104bce156a4e55bcd0e5e37c01b5da2efb65d668a944a18ec74b441
MD5 d02d2d9bef058e12eb0c672991642074
BLAKE2b-256 eef54e581f295db3f153812f81b96010259046e56a484c8434c71628821dc939

See more details on using hashes here.

File details

Details for the file perplexity_remotebox-0.1.0-py3-none-manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for perplexity_remotebox-0.1.0-py3-none-manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 5a41f6bf8c759dd9c7d3e4c3eeb64ea90e50642368ce9950969c22a25e7dc344
MD5 05c6cc6f677816a3c3650630731986d8
BLAKE2b-256 7c64096a708d88307ba5251821fd29e270243875f3bb9a361615069db3e2d76d

See more details on using hashes here.

File details

Details for the file perplexity_remotebox-0.1.0-py3-none-macosx_14_0_x86_64.whl.

File metadata

File hashes

Hashes for perplexity_remotebox-0.1.0-py3-none-macosx_14_0_x86_64.whl
Algorithm Hash digest
SHA256 49e0422880fc2e7fa3c3191cbb7e268e60cda91d397441b1268cc9bd6ad80d22
MD5 fdf55cb5732ec3e21ee8c9a7dab0bf25
BLAKE2b-256 e5f0701b4ec120086342607944faafba8bee5fdc8d3ed598af37b3c0e70f3a6e

See more details on using hashes here.

File details

Details for the file perplexity_remotebox-0.1.0-py3-none-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for perplexity_remotebox-0.1.0-py3-none-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 3103798fc88b8dc8ed6e50793a3df7c8373f001428f9f2a9c64101c4a31c4dee
MD5 b26223057c64a9fc11a28a4d499bd954
BLAKE2b-256 cb70538d6050ea94dd0645ec1d332aabe074688953ff74636d9ae8ba2f7c4630

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0 This release

4 files

0.0.3

1 file

0.0.2

1 file

0.0.1

2 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