# Pi Live

**Stable remote terminal access for Pi Coding Agent.**

Pi Live turns the current Pi session into a browser-accessible terminal using a PTY + WebSocket bridge. It is designed to stay lightweight: Pi still runs as the real TUI, while desktop and mobile browsers connect to the same terminal stream through `xterm.js`.

This release uses our connection strategy:

- local Web UI is always available
- public access uses `cloudflared` when installed
- one command family only: `/live`

---

## Why this architecture

Pi is a TUI. The stable way to expose it remotely is to expose the terminal, not to reconstruct Pi's chat events.

Pi Live therefore uses:

```txt
Browser/xterm.js  ← WebSocket →  PTY  ←→  Pi
Local terminal    ←──────────────┘
```

This avoids event-stream duplication, React chat re-render pressure, and lag inside the local Pi terminal.

---

## Features

- **PTY-based remote terminal** — Pi runs inside a pseudo-terminal.
- **Local terminal preserved** — the original terminal remains attached to the same PTY.
- **Browser terminal** — powered by `xterm.js`.
- **Mobile keybar** — arrows, Enter, Tab, Esc, Ctrl+C.
- **Replay buffer** — reconnecting clients receive recent terminal output.
- **Token auth** — WebSocket and API access require a per-session token.
- **Local-first** — works without Cloudflare.
- **Cloudflare optional** — `/live` creates a public `trycloudflare.com` tunnel when `cloudflared` is installed.
- **QR code** — printed in the terminal and shown in the web UI.

---

## Install

```bash
pi install npm:pi-live
```

Then reload Pi extensions:

```txt
/reload
```

<details>
<summary>Manual install from source</summary>

```bash
mkdir -p ~/.pi/agent/extensions
cd ~/.pi/agent/extensions
git clone https://github.com/ketchh/pi-live.git pi-live
cd pi-live
npm install
npm run build
```

</details>

---

## Usage

Start remote terminal mode from inside Pi:

```txt
/live
```

Pi Live will:

1. wait for Pi to become idle
2. preserve the current session file
3. shut down the current Pi process
4. restart Pi inside a PTY wrapper
5. start the local web server
6. start `cloudflared` if available
7. print local/public URLs and QR code

Inside remote mode:

```txt
/live status
/live stop
```

---

## Commands

```txt
/live          start Pi Live remote terminal mode
/live status   show current remote access info
/live stop     stop the remote Pi session when already in remote mode
```

The initial release intentionally supports only the `/live` command family.

---

## Cloudflare

Install `cloudflared` and make sure it is on `PATH`:

```bash
cloudflared --version
```

When present, Pi Live starts:

```bash
cloudflared tunnel --url http://127.0.0.1:<port>
```

Each session gets its own free metrics port, so multiple sessions can run concurrently.

If `cloudflared` is missing or fails, Pi Live continues with the local/LAN web UI.

---

## Environment variables

```bash
PI_REMOTE_PORT=0                       # 0 = random free port
PI_REMOTE_BIND_HOST=127.0.0.1          # local-only by default
PI_REMOTE_TUNNEL=cloudflared           # cloudflared | none
PI_REMOTE_CLOUDFLARED_TUNNEL_NAME=...  # optional named tunnel
PI_REMOTE_DEBUG=1                      # print cloudflared logs
```

---

## Development

```bash
npm install
npm run check
npm run build
```

Smoke-load the extension:

```bash
node --input-type=commonjs - <<'NODE'
const jiti = require('jiti')(process.cwd() + '/smoke.js');
const ext = jiti('./index.ts').default;
ext({ registerCommand(){}, registerMessageRenderer(){}, on(){} });
console.log('ok');
NODE
```

---

## Future work

Advanced features are tracked in [`future.md`](./future.md). The core release stays minimal and terminal-first.

---

## License

MIT
