Integration

How the Flutter app and Parachute Computer server connect: API contracts, authentication, communication patterns, and deployment modes.

Communication Overview

┌────────────────────────────────────────────────────────────────────────────┐
│                           PARACHUTE APP                                     │
│                                                                             │
│    ┌─────────────────┐                                                     │
│    │   ChatService   │ ───── HTTP POST /api/chat ────────────────────┐    │
│    │   (2,059 lines) │ ◀──── SSE Stream ─────────────────────────────│    │
│    └─────────────────┘                                                │    │
│                                                                        │    │
│    ┌─────────────────┐                                                │    │
│    │ SyncService     │ ───── HTTP POST /api/sync/* ──────────────────│    │
│    │                 │ ◀──── JSON Response ──────────────────────────│    │
│    └─────────────────┘                                                │    │
│                                                                        │    │
│    ┌─────────────────┐                                                │    │
│    │ FileBrowserSvc  │ ───── HTTP GET /api/fs/* ─────────────────────│    │
│    │ (remote)        │ ◀──── JSON Response ──────────────────────────│    │
│    └─────────────────┘                                                │    │
│                                                                        │    │
└────────────────────────────────────────────────────────────────────────│────┘
                                                                         │
                                                                         │
                                          ┌──────────────────────────────▼────┐
                                          │      COMPUTER SERVER             │
                                          │     http://localhost:3333        │
                                          │                                  │
                                          │  ┌───────────────────────────┐  │
                                          │  │      FastAPI Router       │  │
                                          │  │                           │  │
                                          │  │  /api/chat   → chat.py    │  │
                                          │  │  /api/auth   → auth.py    │  │
                                          │  │  /api/fs     → filesystem │  │
                                          │  │  /api/sync   → sync.py    │  │
                                          │  │  /api/health → health.py  │  │
                                          │  └───────────────────────────┘  │
                                          │                                  │
                                          └──────────────────────────────────┘
                    

Service to Endpoint Mapping

App Service Server Endpoint Protocol Purpose
ChatService POST /api/chat SSE AI chat with streaming
ChatService GET /api/chat HTTP List sessions
ChatService GET /api/chat/{id} HTTP Get session details
SyncService POST /api/sync/* HTTP Journal sync
RemoteFileBrowserService GET /api/fs/* HTTP Remote file browsing
BaseServerService GET /api/health HTTP Server health check

Authentication Flow

┌─────────────────┐                              ┌─────────────────┐
│       App       │                              │   Computer      │
└────────┬────────┘                              └────────┬────────┘
         │                                                │
         │ 1. First launch (no API key)                   │
         │                                                │
         │    GET /api/health (localhost)                 │
         │ ──────────────────────────────────────────────▶│
         │                                                │ Auth bypassed
         │ ◀────────────── {"status": "ok"} ─────────────│ (localhost)
         │                                                │
         │ 2. Create API key (Settings)                   │
         │                                                │
         │    POST /api/auth/keys                         │
         │    {"label": "My iPhone"}                      │
         │ ──────────────────────────────────────────────▶│
         │                                                │
         │ ◀──── {"key": "para_abc...", "id": "k_..."} ──│
         │                                                │
         │ 3. Store key in SharedPreferences              │
         │                                                │
         │ 4. Future requests (any network)               │
         │                                                │
         │    POST /api/chat                              │
         │    X-API-Key: para_abc...                      │
         │ ──────────────────────────────────────────────▶│
         │                                                │ Validate key
         │ ◀──────────── SSE response ───────────────────│
         │                                                │
                    

Key Storage Locations

Location What's Stored Format
App (SharedPreferences) Full API key para_aBcDeFgHiJkLmNoPqRsT1234
Server (server-config.json) Key hash + metadata sha256:abc123...

Deployment Modes

🌐

Client Mode

App connects to external server URL. User configures server address in Settings. Used for remote/cloud deployments.

  • Server URL from user input
  • API key required (remote)
  • Sync enabled
🖥️

Computer Mode (Lima)

Server runs in isolated Lima VM on macOS. App auto-starts VM on launch. Most secure option.

  • Server at localhost:3333
  • Auth bypassed (localhost)
  • Shared vault (no sync)

Computer Mode (Bare Metal)

Server runs directly on macOS. Best performance, full hardware access. For dedicated Parachute machines.

  • Server at localhost:3333
  • Auth bypassed (localhost)
  • Shared vault (no sync)

Shared Vault Architecture

In Computer mode, app and server share the same vault directory:

┌─────────────────────────────────────────────────────────────────────┐
│                        ~/Parachute (Vault)                           │
│                                                                      │
│   ┌──────────────────────────────────────────────────────────────┐  │
│   │                          Daily/                               │  │
│   │                                                               │  │
│   │     ┌─────────────────┐         ┌─────────────────┐          │  │
│   │     │   App writes    │         │  Server reads   │          │  │
│   │     │   journal       │ ◀─────▶ │  for agents     │          │  │
│   │     │   entries       │         │                 │          │  │
│   │     └─────────────────┘         └─────────────────┘          │  │
│   └──────────────────────────────────────────────────────────────┘  │
│                                                                      │
│   ┌──────────────────────────────────────────────────────────────┐  │
│   │                          Chat/                                │  │
│   │                                                               │  │
│   │     ┌─────────────────┐         ┌─────────────────┐          │  │
│   │     │   App reads     │         │  Server writes  │          │  │
│   │     │   sessions      │ ◀─────▶ │  sessions       │          │  │
│   │     │                 │         │                 │          │  │
│   │     └─────────────────┘         └─────────────────┘          │  │
│   └──────────────────────────────────────────────────────────────┘  │
│                                                                      │
│   ┌──────────────────────────────────────────────────────────────┐  │
│   │                         .claude/                              │  │
│   │                                                               │  │
│   │     Server writes SDK transcripts here                        │  │
│   │     App doesn't access directly (reads via API)               │  │
│   └──────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────────┘

  Benefits:
  ✓ No sync needed (same files)
  ✓ Immediate updates
  ✓ No data duplication

  Considerations:
  ⚠ File locking important (concurrent access)
  ⚠ App must use server's vault path
                    

Error Handling

Connection Errors

When the server is unreachable:

  • Chat: Shows "Server unavailable" banner, retries on next message
  • Daily: Works offline, queues sync for later
  • Vault: Shows cached content, remote features disabled

Authentication Errors

When API key is invalid or expired:

  • 401 response triggers key re-entry prompt
  • Settings opens to API key section
  • User can create new key from server

Streaming Errors

When SSE connection drops mid-stream:

  • Partial message shown with error indicator
  • Session can be resumed (session_id preserved)
  • User can resend last message

Next Steps