pi-client
Transport-neutral client for remote pi sessions. PiClient exchanges length-prefixed CBOR messages through a small ByteTransport protocol. The core package has no platform-specific imports; pi_client.unix provides the Unix-domain-socket transport.
from pi_client import ByteTransportHandlers, PiClient, PiClientOptions
class MyTransport:
async def send(self, chunk: bytes) -> None:
# Deliver chunks in invocation order and honor backpressure.
return None
def close(self) -> None:
return None
async def transport_factory(handlers: ByteTransportHandlers) -> MyTransport:
# Connect using WebSocket, Unix socket, or another ordered byte transport.
# Call handlers.on_data(), handlers.on_close(), or handlers.on_error() for inbound activity.
return MyTransport()
async def main() -> None:
client = PiClient(PiClientOptions(transport_factory=transport_factory))
await client.connect()
session = await client.create_session(cwd="/workspace")
unsubscribe = session.subscribe(lambda snapshot: print(snapshot))
await session.prompt("Inspect this project")
unsubscribe()
await session.dispose()
await client.dispose()
Call handlers.on_data(chunk) for inbound bytes, handlers.on_close() for an orderly terminal close, and handlers.on_error(error) for transport failures. A factory must create a fresh transport for every connection attempt and complete any transport-specific authentication before resolving. For example, a WebSocket factory can provide credentials in its upgrade request.
PiClient does not reconnect automatically. Call reconnect() after disconnection. One connection can attach several sessions. Requests are correlated by ID. Server snapshots and successful response snapshots are authoritative, while progress events do not mutate snapshot state optimistically. Read cached session metadata from client.snapshot["sessions"] when a snapshot exists; call list_sessions() to request refreshed durable metadata from the server. Runtime state is available after acquiring a session.
acquire_session() returns an independent SessionHandle; handles cannot be constructed directly for active protocol use. Use mode="exclusive" for a lifecycle or mutation coordinator and mode="shared" when multiple low-level consumers intentionally share the session. Exclusive acquisition fails with PiSessionOwnershipError while any lease exists, and shared acquisition fails while an exclusive lease exists. attach_session() is a shared-acquisition convenience method. create_session() returns an exclusive handle for the newly created session.
Calling dispose() or detach() releases only that handle. A handle rejects commands as soon as release begins. The client sends the protocol detach request after the final handle is released. If explicit detach() fails, the handle becomes active again for retry. If cleanup-oriented dispose() fails, it reports the protocol error but relinquishes local ownership; PiClient reconciles the failed protocol cleanup before the next acquisition. A released handle becomes unavailable without affecting other shared handles. Server removal or disconnection invalidates every handle for the affected attachment, and disposing an invalidated handle is a no-op. Commands fail with PiDisconnectedError while the client is disconnected and PiSessionDetachedError when the client is connected but a handle is releasing, released, or invalidated. SessionHandle supports async with.
subscribe() observes authoritative snapshots. on_event() observes protocol events. Both return an unsubscribe function. Structured errors returned by the server are exposed as PiServerError.
Limits and security
PiClientOptions.max_frame_length bounds inbound and outbound CBOR payloads. Configure matching limits on the client and server. Transports should separately bound queued outbound bytes and preserve send order.
Treat peers as untrusted. Use a secure transport with appropriate access controls and authenticate during transport establishment.
Subscriber exceptions are isolated from protocol state. Set on_listener_error in PiClientOptions to report them to application logging or diagnostics.
Unix-domain sockets
Consumers can use the separately exported Unix-domain socket transport:
from pi_client import PiClient, PiClientOptions, create_unix_transport_factory
async def main() -> None:
client = PiClient(
PiClientOptions(
transport_factory=create_unix_transport_factory(
".scratch/pi.sock",
max_pending_bytes=64 * 1024 * 1024,
),
)
)
await client.connect()
max_pending_bytes bounds queued outbound data. It defaults to four times the protocol frame limit. The transport preserves send order and waits for socket backpressure before resolving each send.
The pi_client root remains transport-neutral except for re-exporting the Unix factory for convenience. The implementation also lives at the explicit pi_client.unix module path.
Development
From the repository root:
uv sync --all-packages
uv run pytest packages/pi-client
uv run ruff check packages/pi-client
pp-rpc-client is developed in HSPK/pp_rpc_client. It was split out of the pp monorepo; sibling packages (pp-ai, pp-agent-core, pp-tui, pp-coding-agent, ...) each live in their own
repository and are consumed from PyPI.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
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 pp_rpc_client-0.1.0.tar.gz.
File metadata
- Download URL: pp_rpc_client-0.1.0.tar.gz
- Upload date:
- Size: 28.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
00efd50734bff5cc56ec490cabdbcdce2cab3d1516f6fb433f77e9d4850780fb
|
|
| MD5 |
117c101b66bdc5dca0ff62ff20bcd8b7
|
|
| BLAKE2b-256 |
9261171540be34490c5abf1bb1737048fc0e0f8253a92656a0f70f288c6c044a
|
Provenance
The following attestation bundles were made for pp_rpc_client-0.1.0.tar.gz:
Publisher:
release.yml on HSPK/pp_rpc_client
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pp_rpc_client-0.1.0.tar.gz -
Subject digest:
00efd50734bff5cc56ec490cabdbcdce2cab3d1516f6fb433f77e9d4850780fb - Sigstore transparency entry: 2466705280
- Sigstore integration time:
-
Permalink:
HSPK/pp_rpc_client@336e17a644fd2f19b9849eff861a9bcb90bec48d -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/HSPK
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@336e17a644fd2f19b9849eff861a9bcb90bec48d -
Trigger Event:
push
-
Statement type:
File details
Details for the file pp_rpc_client-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pp_rpc_client-0.1.0-py3-none-any.whl
- Upload date:
- Size: 18.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d4480b83ba9cb9adbb086682bf6b58e629738f083cefe8e02a1f0fa288e2b86b
|
|
| MD5 |
19a697f863435a6b1ca0eaf7a2f83a60
|
|
| BLAKE2b-256 |
8b3374375e8cf17c23d44553ad7cb304bcfbdaaf099708d2835e4f1837fc9b55
|
Provenance
The following attestation bundles were made for pp_rpc_client-0.1.0-py3-none-any.whl:
Publisher:
release.yml on HSPK/pp_rpc_client
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pp_rpc_client-0.1.0-py3-none-any.whl -
Subject digest:
d4480b83ba9cb9adbb086682bf6b58e629738f083cefe8e02a1f0fa288e2b86b - Sigstore transparency entry: 2466705291
- Sigstore integration time:
-
Permalink:
HSPK/pp_rpc_client@336e17a644fd2f19b9849eff861a9bcb90bec48d -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/HSPK
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@336e17a644fd2f19b9849eff861a9bcb90bec48d -
Trigger Event:
push
-
Statement type: