原始内容
Oppi
Use pi from iPhone and iPad.
TestFlight · Demo video · Screenshots
There are many clankers and this one is mine: an iPhone/iPad client and self-hosted server for Pi coding agent sessions.
The goal is to bring Pi's transparency and extensibility to native iOS, render clanker output and tool use nicely, and make it easy to review and steer sessions from mobile devices.
How it works
Oppi has two session paths:
- SDK sessions: the server embeds the Pi SDK in-process, with tool execution, streaming, and standard Pi extension UI.
- TUI bridge: the
oppi-mirrorextension projects a terminal-owned Pi session into Oppi.
Extension prompts, confirmations, editor requests, status, and widgets render as iOS cards, editor sheets, rows, panels, or fallback text. Extension behavior, tools, providers, and session files stay in Pi.
┌─────────────────────┐
│ iPhone / iPad │
│ Oppi │
└──────────┬──────────┘
│ Iroh or HTTPS / WSS
│ session stream + Pi extension UI
┌──────────▼──────────┐
│ oppi-server │
│ Node.js │
└──────────┬──────────┘
│ pi SDK / TUI
┌──────────▼──────────┐
│ LLM provider │
│ + tools │
└─────────────────────┘
Using Oppi
The Workspaces tab opens All Sessions for the active server. It keeps Your Turn and Working up top, groups recent stopped sessions by day, and shows workspace names on rows. Open the Oppi sidebar or drawer to manage saved Agents and schedules, collapse the workspace catalog, open App Settings, or browse one workspace's sessions, files, and settings.
Agent, schedule, and workspace create/edit sheets can open an Oppi Control session. It is a normal Oppi timeline backed by the Default Agent: describe the configuration change, review its proposed oppi command, and explicitly approve the write. The precise forms remain available in the same sheets.
Quick Session starts a session without navigating into a workspace first. Open it from Oppi, Control Center, the Action Button, Spotlight, Siri, or Shortcuts. The Shortcuts New Session action can preload optional text and one image into the composer.
The iOS share extension accepts shared text, URLs, images, and files. Pick a paired-server workspace in the extension's Quick Session composer and start the session directly from the share sheet.
Quick start
Requires Node.js 24+ and at least one Pi provider configured (pi auth, or an API key such as ANTHROPIC_API_KEY). Linux self-signed TLS also requires openssl on PATH.
Install and start:
npm install -g oppi-server
oppi serve
On first run, oppi serve creates ~/.config/oppi/, generates owner credentials, boots local HTTPS/WSS, and prints a pairing QR code plus invite link. In the iOS TestFlight app, pair with one of the visible options: Pair Nearby Mac, Scan QR Code, or Enter manually. Opening the printed oppi://connect invite link on the phone also starts pairing.
To run Oppi as a background service on macOS:
oppi server install
oppi server status
Upgrade or uninstall with npm:
npm install -g oppi-server@latest
npm uninstall -g oppi-server
The default HTTP/TLS transport requires the phone to reach the server over LAN, Tailscale, or a public hostname. For remote HTTP pairing, generate invites with an explicit host:
oppi pair --host <hostname-or-ip>
Iroh mode removes the Oppi host, port, TLS certificate, LAN, and Tailscale requirement. It uses the signed server endpoint ID and can connect directly or through Iroh relay infrastructure:
OPPI_IROH_TRANSPORT=1 OPPI_IROH_INVITE_MODE=irohOnly oppi serve
An Iroh-only invite and its device token fail closed instead of falling back to HTTP.
Notes:
--hostexpects host/IP only (nohttps://, no:port).- Invites are single-use and short-lived (90 seconds by default). If pairing fails, generate a fresh invite.
- Invite port comes from server config (
oppi config get port).
If you use HTTP/TLS and want first-run QR output from serve to already use your Tailscale host, start with:
oppi serve --host <your-host>.ts.net
Source checkout (development)
Use the repo bootstrapper only when you are developing Oppi or testing unreleased server changes:
git clone https://github.com/duh17/oppi.git
cd oppi
bash install.sh
For regular use, prefer the npm route above so updates are just npm install -g oppi-server@latest.
Background service (macOS)
If you used oppi server install, the server runs as a LaunchAgent that starts on login and restarts on crash. Manage it with:
oppi server status # check if running
oppi server restart # restart
oppi server uninstall # remove
Commands
Use oppi ... after installing oppi-server from npm. Common entry points:
oppi serve [--host <h>] # start server
oppi init # interactive first-time setup
oppi pair [--host <h>] # regenerate pairing QR + invite link
oppi status # server, network, and pairing status
oppi doctor # security and environment diagnostics
oppi workspace ... # list/create/update/delete workspaces
oppi worktree ... # list/create/open/preview/remove worktrees
oppi session ... # create/send/watch/wait/inspect/resume/fork/delete sessions
oppi agent ... # manage saved Agents
oppi schedule ... # manage schedules and run history
oppi server ... # install/status/restart/stop/uninstall launchd service
oppi config ... # show/get/set/validate config
oppi token rotate # rotate owner bearer token
oppi update # update the npm-installed server and CLI
Saved Agents and schedules are available from the Oppi sidebar and the server CLI/API. Saved Agents hold reusable Agent definitions and can use one Unicode emoji or SF Symbol name as an icon. The icon appears in Agent management and sessions launched from that Agent; clearing it uses the generic Agent icon. Schedules store at/every/cron triggers plus a workspace, saved Agent, or existing-session action and keep run history for manual or approved automatic runs. Control sessions pass structured Agent and schedule revisions through bounded --definition-json arguments instead of temporary files. For the full CLI surface, run oppi --help or see server/README.md.
Mac app shell (experimental)
The macOS app uses the same globally installed oppi executable as humans and managed agents. Install or update it first:
npm install -g oppi-server@latest
The app does not bundle a second server runtime. oppi init, local status and pairing setup work before a phone is paired; authenticated workspace, session, Agent, and schedule commands require the local owner credentials created during setup.
Docs
- Contributing - open an issue before proposing code changes
- Changelog - release history and versioning policy
- Server README - server setup, Docker, development
- Onboarding and pairing - intended first-run user flow
- Deep links - custom URL schemes for pairing, workspaces, and sessions
- Config schema - all config options
- Dictation / ASR - server dictation setup
- Voice replies / TTS - voice extension setup
- Extensions - Oppi-specific extension behavior, workspace filtering, and mobile rendering gotchas
- Attachment rendering - message and tool-output rendering for image, audio, video, and file attachments
- Document viewers - full-screen reading controls for markdown, code, diffs, terminal output, and rendered documents
- TUI session bridge - live terminal Pi sessions in Oppi and the separate
oppi-mirrorpackage - Sandbox workspaces - Gondolin VM isolation, network boundaries, tools, and safe defaults
- Custom themes - creating color themes for the iOS app
- Telemetry and diagnostics - privacy controls, storage paths, latency, and reliability metrics
- Security - security model and privacy
Development docs
- Architecture - cross-system architecture map
- Server architecture - routes, streams, runtime ownership, and storage
- Client architecture - Apple stores, transports, and the chat timeline pipeline
- Extension native UI - native extension UI contract
- Testing - canonical test commands
- Model selection - chat model selection precedence
- Session tree semantics - session tree and fork semantics
- Protocol snapshots - canonical wire fixtures and stream topology