@clevercloud/pi-remote-control

pi.dev extension: bridge a live pi session to the remote-control relay

Packages

Package details

extension

Install @clevercloud/pi-remote-control from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:@clevercloud/pi-remote-control
Package
@clevercloud/pi-remote-control
Version
0.1.5
Published
Jul 8, 2026
Downloads
256/mo · 40/wk
Author
judu
License
Apache-2.0
Types
extension
Size
67.7 KB
Dependencies
0 dependencies · 0 peers
Pi manifest JSON
{
  "extensions": [
    "./dist/index.js"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-remote-control extension

A pi.dev extension that bridges your live pi session to the remote-control relay, so a remote device (the iOS app, or cli-test) can watch the session and send prompts.

Install

pi install npm:@clevercloud/pi-remote-control

No clone, no build, no dependencies — pi loads the extension directly (the built dist/ is committed; the extension is dependency-free: node builtins + the global WebSocket/fetch). Just start pi:

pi   # relay defaults to wss://pidev-remote.cleverapps.io

The session is named automatically from the project directory pi runs in (the git repo root), plus a distinguishing word: the git worktree name when pi runs in a linked worktree, an animal otherwise (e.g. dev-foo-4fa9c1-otter). Your devices list your sessions and connect with a tap — nothing to configure or share, and no hand-named sessions.

From source (dev): npm install && npm run build, then pi --extension ./dist/index.js. Re-commit dist/ after editing src/.

Sign in — inside pi

No separate binary, no token copy-pasting:

/remote-login          # opens your browser; tokens stored + auto-refreshed
/remote-status         # relay state · session · auth · mode
/remote-logout
/remote-beta-invite you@apple-id.com   # join the iOS TestFlight beta

Credentials live at ~/.config/pidev/credentials.json. Auth resolution order: PIDEV_OIDC_TOKEN (env override, for CI) → stored /remote-login credentials (auto-refreshed) → none (dev mode, loopback relay only). An off-loopback (wss://) relay requires one of the first two.

Keycloak: the public client needs the exact loopback redirect URIs http://127.0.0.1:8765/callback, :8766, :8767 registered (a http://127.0.0.1/* wildcard does NOT cover the port). /remote-login uses the first free of these ports.

Once pinned to a pi version and published, it can instead be installed with pi install git:github.com/clevercloud/pi-dev-remote-controll (extension sub-path TBD). The Rust pidev (../server/cli-test) shares the same credential file and remains only as an optional device tester.

What it does (skeleton)

Direction Mapping
device → pi {type:"prompt"}pi.sendUserMessage(text, { streamingBehavior })
pi → device message_update (text deltas) → {type:"delta"}
pi → device tool_execution_start/end{type:"tool"}
pi → device agent_end{type:"turn_end"}

Transport test (no real pi / no model key)

test/harness.mjs runs the real extension against a mocked pi — only the LLM brain is faked. With a local Pulsar + relay running, it lets a prompt from cli-test round-trip device → pi → device through the broker:

npm run build
PIDEV_RELAY_URL=ws://localhost:8080 bun test/harness.mjs &
# then, from server/: cargo run -p cli-test -- sessions   # grab the printed id
#       cargo run -p cli-test -- send --session <id> --prompt "hi"
# → prints "received: hi"

This was validated end-to-end against apachepulsar/pulsar:4.0.4 standalone: both pidev-demo-to-pi and pidev-demo-from-pi topics are created and carry the traffic (subscriptions pi and device-0).

Tool approvals (on("tool_call") → block, paired with {type:"approval"}) are implemented with UUID request ids and default-deny on timeout/disconnect. History replay (ctx.sessionManager.getEntries()) is still pending.

Transport policy: off-loopback the extension requires wss:// and PIDEV_OIDC_TOKEN, failing closed otherwise (see ../docs/SECURITY.md).

The ExtensionAPI type here is modelled loosely from pi's docs/extensions.md; tighten it once we pin a pi release and depend on its published types.