Skip to content

guberm/pi-android-client

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Pi Android Client

Unofficial Android client for running Pi Coding Agent through a small self-hosted REST bridge.

The Android app does not talk to Pi directly. Instead, it connects to server/pi_bridge.py, which runs on a machine where the pi CLI is installed and authenticated.

Features

  • English-only Android UI.
  • Server URL and API key settings.
  • Fetches available Pi models from the bridge.
  • Sends prompts to Pi with the selected provider/model.
  • Reads Pi session history from local Pi JSONL session files.
  • Can open an existing session and continue it.
  • Includes an adaptive/vector Android app icon.

How it works

Android app
  -> HTTPS + Bearer token
  -> pi_bridge.py
  -> local pi CLI
  -> ~/.pi/agent/sessions/*.jsonl

The bridge wraps a few Pi CLI/data operations:

  • pi --list-models for available models.
  • pi --print --session-id <id> --provider <provider> --model <model> <prompt> for chat.
  • ~/.pi/agent/sessions for session history.

Requirements

Android app

  • Android SDK / Gradle wrapper for building from source.
  • Android device or emulator.
  • A bridge URL and API key.

Bridge host

  • Python 3.10+.
  • Pi CLI installed and authenticated.
  • Access to the Pi session directory, usually ~/.pi/agent/sessions.
  • Optional but recommended: HTTPS reverse proxy such as Caddy, Nginx, Cloudflare Tunnel, or ngrok.

Server setup guide

For full server configuration steps - Pi CLI setup, bridge API key, local verification, HTTPS reverse proxy, persistence, Android app settings, and troubleshooting - see docs/SERVER_SETUP.md.

Quick start

1. Create a bridge API key

On the bridge host:

mkdir -p ~/.config/pi-android-bridge
python3 - <<'PY'
import secrets, pathlib
path = pathlib.Path.home() / '.config/pi-android-bridge/api_key'
path.write_text(secrets.token_urlsafe(32) + '\n')
path.chmod(0o600)
print(path)
PY

2. Run the bridge

python3 server/pi_bridge.py

By default, the bridge listens on 127.0.0.1:8766.

3. Expose it to the Android device

For local testing, use an SSH tunnel, ngrok, Cloudflare Tunnel, or put an HTTPS reverse proxy in front of the bridge.

Example Caddy reverse proxy:

pi.example.com {
    reverse_proxy 127.0.0.1:8766
}

Use the resulting base URL in the Android app, for example:

https://pi.example.com

4. Configure the Android app

Open the app settings and enter:

  • Server URL: your bridge base URL, for example https://pi.example.com
  • API key: the value from ~/.config/pi-android-bridge/api_key

Do not commit the real API key or bake it into the APK.

Authentication

All /api/* endpoints require a bearer token. Curl examples below use --oauth2-bearer "$API_TOKEN", which sends the standard bearer-token authorization header.

GET /health is public and does not require authentication.

If authentication fails, the bridge returns HTTP 401:

{
  "error": "unauthorized"
}

API reference

Set these shell variables for the examples:

BASE_URL=https://pi.example.com
API_TOKEN=replace-with-your-api-key

GET /health

Public health check.

Request:

curl "$BASE_URL/health"

Response 200:

{
  "ok": true,
  "service": "pi-android-bridge",
  "time": "2026-06-14T22:30:26Z"
}

GET /api/models

Returns the available provider/model list parsed from pi --list-models.

Request:

curl \
  --oauth2-bearer "$API_TOKEN" \
  -H "User-Agent: PiAndroidClient/1.0" \
  "$BASE_URL/api/models"

Response 200:

{
  "models": [
    {
      "provider": "anthropic",
      "id": "claude-3-5-haiku-20241022",
      "context": "200K",
      "max_output": "8.2K",
      "thinking": "no",
      "images": "yes"
    }
  ]
}

Possible errors:

  • 401 - missing or wrong bearer key.
  • 500 - pi --list-models failed; response body contains { "error": "..." }.

GET /api/sessions

Returns up to 100 most recently modified Pi sessions.

Request:

curl \
  --oauth2-bearer "$API_TOKEN" \
  -H "User-Agent: PiAndroidClient/1.0" \
  "$BASE_URL/api/sessions"

Response 200:

{
  "sessions": [
    {
      "id": "019ec6e7-5885-748b-81f3-2a9c09d4d5c0",
      "title": "Example prompt title",
      "updated_at": "2026-06-14T16:11:50.789Z",
      "message_count": 2,
      "provider": "anthropic",
      "model": "claude-opus-4-8"
    }
  ]
}

Notes:

  • title is derived from the first user message when possible.
  • updated_at is the session timestamp from the JSONL file when available.
  • provider and model are the last model_change values seen in the session file.

Possible errors:

  • 401 - missing or wrong bearer key.

GET /api/sessions/{id}

Returns a single Pi session with messages.

Request:

curl \
  --oauth2-bearer "$API_TOKEN" \
  -H "User-Agent: PiAndroidClient/1.0" \
  "$BASE_URL/api/sessions/019ec6e7-5885-748b-81f3-2a9c09d4d5c0"

Response 200:

{
  "id": "019ec6e7-5885-748b-81f3-2a9c09d4d5c0",
  "title": "Example prompt title",
  "updated_at": "2026-06-14T16:11:50.789Z",
  "message_count": 2,
  "provider": "anthropic",
  "model": "claude-opus-4-8",
  "messages": [
    {
      "role": "user",
      "text": "Example prompt",
      "timestamp": "2026-06-14T16:16:38.284Z"
    },
    {
      "role": "assistant",
      "text": "Example response",
      "timestamp": "2026-06-14T16:16:47.456Z"
    }
  ]
}

Possible errors:

  • 401 - missing or wrong bearer key.
  • 404 - session was not found:
{
  "error": "session not found"
}

POST /api/chat

Runs Pi in non-interactive print mode with the selected provider/model.

Request:

curl \
  -X POST \
  --oauth2-bearer "$API_TOKEN" \
  -H "User-Agent: PiAndroidClient/1.0" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "github-copilot",
    "model": "gpt-5.4-mini",
    "session_id": "android-smoke-test",
    "message": "Respond with exactly: PONG"
  }' \
  "$BASE_URL/api/chat"

Request body:

{
  "provider": "github-copilot",
  "model": "gpt-5.4-mini",
  "session_id": "optional-existing-or-new-session-id",
  "message": "User prompt text"
}

Fields:

  • message - required, non-empty prompt text.
  • model - required Pi model id.
  • provider - optional but recommended; when present the bridge passes --provider <provider> to pi.
  • session_id - optional. If empty or missing, the bridge generates a UUID and returns it.

Response 200:

{
  "ok": true,
  "session_id": "android-smoke-test",
  "answer": "PONG"
}

Possible errors:

  • 400 - message or model missing:
{
  "error": "message and model are required"
}
  • 401 - missing or wrong bearer key.
  • 502 - pi exited non-zero:
{
  "error": "pi failed",
  "exit_code": 1,
  "stderr": "...last 4000 chars...",
  "stdout": "...last 4000 chars..."
}
  • 504 - pi did not finish within 600 seconds:
{
  "error": "pi timed out"
}
  • 500 - unexpected bridge exception:
{
  "error": "..."
}

Runtime configuration

Environment variables supported by server/pi_bridge.py:

PI_BRIDGE_HOST       default: 127.0.0.1
PI_BRIDGE_PORT       default: 8766
PI_BRIDGE_KEY_FILE   default: ~/.config/pi-android-bridge/api_key
PI_SESSION_ROOT      default: ~/.pi/agent/sessions
PI_BIN               default: pi

Example:

PI_BRIDGE_HOST=127.0.0.1 \
PI_BRIDGE_PORT=8766 \
PI_BRIDGE_KEY_FILE="$HOME/.config/pi-android-bridge/api_key" \
PI_SESSION_ROOT="$HOME/.pi/agent/sessions" \
python3 server/pi_bridge.py

Build from source

ANDROID_HOME=$HOME/Android/Sdk ./gradlew :app:assembleDebug --console=plain --no-daemon

Debug APK output:

app/build/outputs/apk/debug/app-debug.apk

Security notes

  • Treat the bridge API key as a secret.
  • Do not expose the bridge directly to the public internet without HTTPS and a strong API key.
  • Prefer binding the bridge to 127.0.0.1 and exposing it through a reverse proxy or tunnel.
  • The Android app stores the server URL and API key locally on the device.
  • The bridge can run local Pi commands, so anyone with the API key can use your Pi CLI account on that host.

Status

This is a small utility client and bridge, not an official Pi product.

About

Unofficial Android client and REST bridge for Pi Coding Agent

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors