# pi-remote — iOS Native App Spec (v3) > **Status:** v3 nach ExtensionAPI-Audit. > Audit-Ergebnis: [`EXTENSION-API-AUDIT.md`](./EXTENSION-API-AUDIT.md). > Review-Verlauf v1: [`SPEC-ios-app-review-v1.md`](./SPEC-ios-app-review-v1.md). > > **Changelog v2 → v3:** > - Audit hat S-07, S-08 und Tree-Read als out-of-the-box machbar bestätigt → von PENDING auf firm SHOULD. > - **Tree-Navigation komplett aus iOS entfernt.** Gruppe T gestrichen. Begründung: Slash-Command-Dispatch ist in der ExtensionAPI blockiert, Workarounds (Hack oder Re-Implement) sind nicht den Aufwand wert. Tree-Navigation bleibt nativ in pi. > - Spike-0a abgeschlossen, ist nun referenziertes Audit-Dokument. > - **Q-A** geschlossen: pi-CLI `-p`/`--print` Mode funktioniert mit Haiku 4.5 in ~2s. S-09a hat jetzt konkrete CLI-Flags. > - **Q-C** geschlossen: APNs-Setup-Details unter iOS-C-02. Sidecar routet pro Device-Token nach Sandbox (Xcode-Debug) vs. Production (TestFlight/Release). --- ## 1. Vision Eine iOS-App, die laufende `pi`-Sessions **byte-genau spiegelt**, wie sie im SSH-Terminal aussehen — und durch native iOS-Mittel (Touch, Sprache, Notifications, System-Integration) die Bedienung dieser Terminal-Umgebung unterwegs angenehm macht. **Kein Hybrid-Rendering.** Was im Terminal ANSI ist, bleibt in der App ANSI. Die App fügt eine *Augmentation-Schicht* hinzu, kein paralleles UI. **Kernszenarien:** 1. **Long-Visit-Sync** — Eine Session läuft tagelang. Nutzer "besucht" sie unregelmäßig vom Mac (SSH) und iPhone (App). Beide zeigen jederzeit denselben State. Reattach ist instant. 2. **Session-Lifecycle vom Phone** — Sessions vom iPhone aus spawnen, benennen, switchen und beenden — so easy wie native iOS-Tabs. --- ## 2. Principles - **P-1** — Der Terminal-Stream ist die einzige Wahrheit für Inhalt. Strukturierte Events dienen ausschließlich Statusanzeigen, Notifications und Meta-State (z.B. Tree-Navigation). Niemals Re-Rendering von Stream-Inhalt. - **P-2** — SSH-Erfahrung bleibt unverändert. Der Mac-Workflow ändert sich durch dieses Projekt nicht spürbar. - **P-3** — Reconnect ist die wichtigste Operation. Sichtbares Ergebnis < 1s nach App-Wake. - **P-4** — Touch-UX wird *zur Terminal-Bedienung* gebaut, nicht *anstelle* von Terminal-Bedienung. - **P-5** — Solo-Use. Multi-User, Sharing, Org-Features sind out of scope. - **P-6** — Server-State wird in tmux gehalten, wo möglich. Kein paralleler State-Store im Sidecar. --- ## 3. Architecture ``` ┌──────────────────────────────────────────────────────────┐ │ Server │ │ │ │ pi (Ink TUI) ◄─► tmux session ◄─► SSH-Client (Mac) │ │ │ │ │ │ pipe-pane (raw bytes) │ │ │ send-keys │ │ ▼ │ │ pi-remote sidecar │ │ │ │ │ │ WebSocket (wss://) │ │ │ ├─ raw ANSI stream (binary) │ │ │ ├─ control (send-keys, JSON) │ │ │ └─ side-channel (state, JSON) │ └─────────────────────────┼────────────────────────────────┘ │ ▼ ┌──────────────────────────┐ │ iOS App │ │ ┌────────────────────┐ │ │ │ SwiftTerm renderer │ │ │ └────────────────────┘ │ │ ┌────────────────────┐ │ │ │ Augmentation layer │ │ │ └────────────────────┘ │ └──────────────────────────┘ ``` **Komponenten:** - **tmux** — Session-Persistenz, Multi-Client-Attach, Pane-Pipe, Send-Keys. Sessions als stable IDs, Metadaten via tmux User-Options (`@description`, `@project`, etc.). - **Sidecar** (`pi-remote-control` erweitert) — Node-Prozess. Spawn / Reattach tmux, exponiert WebSocket-API, hält Ringbuffer für Replay, leitet ExtensionAPI-Metadaten als Side-Channel weiter. - **iOS-App** — SwiftUI-Shell, SwiftTerm als Renderer-View, eigener Augmentation-Layer. **Datenfluss Stream:** `pi` → tmux pipe-pane → sidecar ringbuffer → WS (binär, `permessage-deflate`) → iOS SwiftTerm. **Datenfluss Input:** iOS → WS → sidecar → `tmux send-keys` → tmux pane → pi stdin. Mac-SSH-Client sieht denselben Input. **Konventionen:** - Terminal-Size: tmux pane fixiert auf **120 × 40**. Client rendert mit Pinch-Zoom auf die physische Display-Größe. - WebSocket-Frames: binär = ANSI-Stream-Chunk; text = JSON-Control (input, side-channel, snapshot-request). - Alternate-Screen-Buffer wird vom Client erkannt und nicht in den Scrollback-Cache aufgenommen. - Terminal-Title-Sequences werden ignoriert. - Mouse-Tracking-Sequenzen werden weitergeleitet, vom Client aber nicht visualisiert (Touch-UX). --- ## 4. Server Features (Sidecar) ### S-01 — tmux launcher / attach **MUST.** CLI `pi-remote attach []`. Existiert die Session, reattach; sonst neu spawnen (`tmux new-session -d -s 'pi'`) und attach. Default-Session: `pi-main`. Per Projekt benennbar. *Dependencies:* — ### S-02 — Raw ANSI WebSocket Stream **MUST.** Endpoint `/stream/`. - Binäre Frames für ANSI-Bytes aus `tmux pipe-pane`. - WebSocket-Extension `permessage-deflate` aktiv (3–5× Compression typisch für ANSI). - Eine Verbindung = ein Pane. - Alternate-Screen-Sequenzen werden durchgereicht; Sidecar markiert sie nicht separat (Client tracked). *Dependencies:* S-01 ### S-03 — Send-Keys-Endpoint **MUST.** WS-Text-Frames als JSON: `{type:"keys", data:"..."}` für literal-Text, oder `{type:"key", name:"escape"|"tab"|"up"|...}` für Spezialtasten. Sidecar mapped auf `tmux send-keys` oder `tmux send-keys -l`. Bracketed-Paste-Frames (`{type:"paste", data:"..."}`) wrappen automatisch mit `\e[200~ ... \e[201~`. *Dependencies:* S-01 ### S-04 — Sequence-Cursor & Delta-Replay **MUST.** Sidecar nummeriert Chunks ausgehend (monotone u64). Client sendet bei Reconnect `{type:"resume", lastSeq:}`. Server liefert ab `lastSeq+1` weiter. Falls Lücke → Snapshot (S-05). *Dependencies:* S-02 ### S-05 — Snapshot-Endpoint **MUST.** Wenn `lastSeq` außerhalb des Ringbuffers liegt: `tmux capture-pane -p -e -S -10000` als Snapshot + neuen Start-Seq. Snapshot wird komprimiert über WS geliefert. *Dependencies:* S-01, S-04 ### S-06 — Per-Session Disk Buffer **SHOULD.** Sidecar persistiert ANSI-Stream pro Session in eine einzelne Datei `/var/lib/pi-remote/buffer/.log`. - **Pro Session**: hartes Cap = **100MB** (configurable). Bei Überlauf wird der Schreibvorgang gestoppt; existierender Inhalt bleibt unangetastet. Neue Bytes ab dem Punkt fehlen im Buffer — Snapshot via S-05 funktioniert weiterhin direkt aus tmux. - **Global**: Hartes Total-Cap = **1GB** über alle Sessions; wenn überschritten, schaltet der Sidecar Buffer-Schreiben global ab und meldet `degraded` über S-13. - **Idle-Cleanup**: Sessions ohne Output UND ohne Client seit > 30 Tagen → Buffer-Datei wird gelöscht (Session selbst nur falls ebenfalls beendet). - **Disk-Watchdog**: Bei freiem Platz < 1GB → Buffer-Schreiben global aus, Health-Status `degraded`. - Konfigurierbar via `~/.config/pi-remote/config.toml`. *Dependencies:* S-02 ### S-07 — State Side-Channel **SHOULD.** Sidecar abonniert pi-ExtensionAPI-Events (`agent_start`, `agent_end`, `tool_execution_start`, `tool_execution_end`, `session_tree`, `session_compact`) und publiziert als JSON-Control-Frames: ```json {"type":"state","value":"thinking"|"tool"|"idle"|"awaiting-input", "tool":"Edit"|"Read"|...,"ts":1234567890} ``` `awaiting-input` wird abgeleitet aus `agent_end` + `ctx.isIdle()`, da kein explizites Event existiert (siehe Audit §3.1). *Dependencies:* S-01 ### S-08 — Slash-Command-Registry **SHOULD.** Endpoint `/sessions//commands` liefert JSON-Liste der verfügbaren Slash-Commands inkl. Beschreibung und Argument-Schema via `pi.getCommands()` (laut Audit out-of-the-box verfügbar). Dynamisch — Extensions die Commands hinzufügen erscheinen automatisch. *Dependencies:* S-01 ### S-09 — Multi-Session-Management **MUST.** Sidecar verwaltet mehrere tmux-Sessions parallel, alle robust gegen Sidecar-Restart (tmux überlebt, Sidecar reattached beim Boot). **Endpoints:** - `GET /sessions` — Liste mit Metadaten (Name, Description, Created, letzter Output, Connected-Clients, Pi-State). - `POST /sessions` — neue Session spawnen, Body optional `{name, project}`. - `PATCH /sessions/` — umbenennen / Description ändern. - `DELETE /sessions/` — Session beenden (tmux kill-session + Buffer optional löschen). **State:** Ausschließlich in tmux gehalten. Sessions haben Namen (stable ID), Metadaten via tmux User-Options: - `@description` — Auto- oder manuell vergeben (siehe S-09a) - `@project` — optional, vom User gesetzt - `@created` — Timestamp Kein eigener JSON-State-Store im Sidecar. *Dependencies:* S-01 ### S-09a — Auto-Naming via pi **NICE.** Nach ~3 User-Messages in einer namenlosen Session triggert der Sidecar einen One-Shot-Call via pi-CLI: ```bash pi -p --provider anthropic --model claude-haiku-4-5 \ --no-tools --no-context-files --no-extensions --no-session \ --thinking off \ "Give a 2-4 word title for: ''. Reply with title only." ``` ~2s Latenz, pi's eigene Anthropic-Auth wird verwendet — keine separaten Credentials nötig. Ergebnis landet als `@description` in tmux. Manuelles Umbenennen aus der App jederzeit möglich und überschreibt. *Dependencies:* S-09 ### S-10 — Pairing & Bearer-Token-Auth **MUST.** CLI `pi-remote pair` generiert ein kurzlebiges (5min) Pairing-Token und druckt einen QR-Code im Terminal (Unicode block chars, via `qrcode-terminal`). QR-Inhalt: `pi-remote://:?pair=&fp=` iOS-App scannt → tauscht Pairing-Token gegen permanenten Bearer-Token, pinnt den TLS-Fingerprint. Token im Keychain (iOS-G-01). CLI: - `pi-remote auth list` — alle Tokens - `pi-remote auth revoke ` — Token widerrufen - `pi-remote auth name ` — Token umbenennen (z.B. "jay's iPhone") *Dependencies:* S-11 ### S-11 — TLS via Self-Signed + Trust-on-First-Use **MUST.** Sidecar generiert beim ersten Start ein selbstsigniertes Cert (ED25519 oder RSA-2048), 10 Jahre gültig, persistent auf Disk. SHA-256-Fingerprint wird in den QR aus S-10 mit aufgenommen. Client pinnt den Fingerprint beim Pairing. Bei Cert-Rotation (z.B. neuer Host) muss re-paired werden. Kein Let's Encrypt, keine CA, kein Reverse-Proxy nötig. *Dependencies:* — ### S-12 — Health & Metrics **NICE.** `/health` Endpoint mit Session-Count, Buffer-Size, Connected-Clients, Disk-Watchdog-Status. Für Monitoring und Selbst-Debugging. *Dependencies:* — > S-13 (Tree-State Side-Channel) wurde in v3 gestrichen. > Begründung: siehe Out-of-Scope und Changelog. --- ## 5. iOS Client Features ### Gruppe A — Rendering & Stream #### iOS-A-01 — SwiftTerm-Renderer **MUST.** Vollwertiger ANSI-Terminal-View. Renderer-Setup mit Truecolor, 120×40 fixed grid, configurable Font + Theme. *Dependencies:* S-02 #### iOS-A-02 — Sequence-Cursor & Reconnect **MUST.** Client speichert lokal pro Session den letzten `seq`. Bei WS-Reconnect: schickt `{type:"resume", lastSeq}`, verarbeitet Delta oder Snapshot. *Dependencies:* S-04, S-05 #### iOS-A-03 — Stale-Frame-Display **SHOULD.** Während Sync nach App-Wake: letzten Frame einfrieren, "syncing…" als subtile Overlay-Pill anzeigen. Kein leerer Screen. *Dependencies:* iOS-A-02 #### iOS-A-04 — Local Scrollback-Cache **SHOULD.** App puffert empfangene Bytes lokal pro Session (rolling, default 5MB) für Offline-Scrolling und Suche. Alternate-Screen-Inhalt wird ausgenommen. *Dependencies:* iOS-A-01 #### iOS-A-05 — Themes & Fonts **SHOULD.** Eingebaute Themes: - Default-Dark, Default-Light - Solarized Light, Solarized Dark - Monokai, Dracula - Nord, Gruvbox Dark, Gruvbox Light - Tomorrow Night - GitHub Light, GitHub Dark - System (folgt iOS Light/Dark Mode) Eingebaute Fonts (gebundlet): - JetBrains Mono (Default) - Hack - SF Mono - Menlo - Fira Code - Cascadia Code - IBM Plex Mono - Monaspace Neon Custom Themes editierbar, iCloud-Sync nur für Custom. *Dependencies:* iOS-A-01 ### Gruppe B — Input & Modifier #### iOS-B-01 — Software-Keyboard, Direct-Passthrough **MUST.** Standard-iOS-Keyboard. **Mode (b) direct-passthrough**: jeder Tastendruck geht sofort als `send-keys`. Enter sendet `\r` an pi → pi behandelt selbst. Kein App-eigenes Compose-Feld. Shift+Enter (newline) via dediziertem `⇧↵`-Button in der Modifier-Bar (siehe iOS-B-02). *Dependencies:* S-03 #### iOS-B-02 — Modifier-Bar **MUST.** Accessory-Bar über der Tastatur: ``` [Ctrl] [Esc] [Tab] [←] [↑] [↓] [→] [⇧↵] [🎙] [📋] ``` - **Ctrl** ganz links — Sticky-Toggle: ein Tap → leuchtet → nächste Taste wird als Ctrl+X gesendet. Beliebige Ctrl-Combos möglich (Ctrl-C, Ctrl-D, Ctrl-L, Ctrl-U, ...). - **Esc** — eigener Button, dauerhaft sichtbar. - **Tab** — Autocomplete in pi. - **Pfeiltasten** (Mitte) — History scrollen, in Menüs navigieren, Input-Cursor bewegen. - **`⇧↵`** — Shift+Enter, ein Tap = `\n` (newline in pi multi-line). - **`🎙`** — Voice-Input (iOS-C-06). - **`📋`** — Paste-Button ganz rechts (öffnet Paste-Sheet, iOS-B-08). Bei knappem Platz (iPhone-Portrait) ist die Bar horizontal scrollbar. *Dependencies:* iOS-B-01 #### iOS-B-03 — Long-Press-Repeat **SHOULD.** Long-Press auf Pfeiltasten oder Backspace → repeat mit Beschleunigung. *Dependencies:* iOS-B-02 #### iOS-B-04 — Selection & Copy **MUST.** Doppel-Tap → Wort. Tripel-Tap → Zeile. Long-Press + Drag → Range. Native iOS-Copy-Menu. *Dependencies:* iOS-A-01 #### iOS-B-05 — Pinch-Zoom Font **SHOULD.** Pinch in der Terminal-View → Font-Size live. *Dependencies:* iOS-A-01 #### iOS-B-06 — Hardware-Keyboard-Support **SHOULD.** Externe iPad-Keyboards: - Caps→Esc-Remap (optional) - Modifier-Pass-Through (Cmd, Option, Ctrl) - App-Shortcuts: - Cmd-K — Clear - Cmd-T — New session - Cmd-1..9 — Session switch - Cmd-F — Scrollback-Search - Cmd-, — Settings - Cmd-Shift-P — Slash-Command-Palette *Dependencies:* iOS-B-01 #### iOS-B-07 — Reachability / One-Hand-Mode **NICE.** iPhone-Querformat: Modifier-Bar gespiegelt für einhändige Bedienung. *Dependencies:* iOS-B-02 #### iOS-B-08 — Smart Paste (Confirm) **SHOULD.** `📋`-Button in der Modifier-Bar zeigt Clipboard-Vorschau- Chip ("📋 12 lines, 847 chars"). Tap → Sheet mit vollem Preview, Insert / Cancel. Verhindert versehentliches Paste großer Blobs. *Dependencies:* iOS-B-01 #### iOS-B-09 — Bracketed-Paste-Compliance **SHOULD.** Client trackt im Stream `\e[?2004h` / `\e[?2004l`. Wenn aktiv, wird bei Paste die `{type:"paste"}` Variante an S-03 geschickt, sodass pi den ganzen Block als Paste erkennt. *Dependencies:* S-03, iOS-B-08 ### Gruppe C — Pi-aware Augmentation #### iOS-C-01 — Status-Bar **MUST.** Top-Bar zeigt: Connection-Status, Session-Name, Pi-State (`● thinking` / `⏵ tool: Edit` / `▶ awaiting` / `⏸ idle`) basierend auf S-07. *Dependencies:* S-07 #### iOS-C-02 — Push-Notification bei Awaiting-Input **MUST.** Wenn App im Background und Pi wechselt zu `awaiting-input`: Push-Notification "Pi ist fertig · ". Tap → App öffnet in der richtigen Session. **APNs-Setup:** - Apple Developer Portal: App-ID mit Push-Capability + APNs Auth-Key (`.p8`, einmaliger Download). Notiere Team-ID und Key-ID. - Dieselbe `.p8`-Datei funktioniert für Sandbox und Production. - Sidecar-Config (neue Sektion in `~/.config/pi-remote/config.toml`): ```toml [apns] team_id = "..." key_id = "..." key_path = "/etc/pi-remote/AuthKey_.p8" bundle_id = "de.vpsj.pi-remote" ``` - **Environment-Routing pro Device:** Xcode-Debug-Builds (lokales Testen via WiFi-Pair) registrieren ihre Device-Tokens bei der Sandbox; TestFlight- und Release-Builds gehen gegen Production. Beide gleichzeitig betreibbar, da derselbe Key funktioniert. Sidecar speichert pro Device-Token ein `environment: "sandbox" | "production"` Feld und routet beim Push entsprechend zu `api.sandbox.push.apple.com` bzw. `api.push.apple.com`. - **Pairing-Erweiterung (S-10):** iOS-App schickt beim Pairing zusätzlich `{deviceToken, environment, deviceName}`. `environment` bestimmt sich zur Compile-Time aus der Build-Config. - **HTTP-Headers**: - `apns-topic: ` - `apns-push-type: alert` (required ab iOS 13) - `apns-priority: 10` - `apns-collapse-id: session-` — verhindert Notification-Spam, neuere State-Wechsel überschreiben ältere im Lock-Screen. - **JWT:** ES256-signed mit `.p8`-Key, 1h gültig, im Sidecar für ~55min cachen. - **Auto-Cleanup:** APNs-Response `410 Gone` → Device-Token tot, Sidecar löscht Mapping. App registriert beim nächsten Launch neu. - **Library:** `@parse/node-apn` oder `node-apn-http2`. *Dependencies:* S-07, S-10 (Pairing trägt Device-Token), APNs Auth-Key #### iOS-C-03 — Haptic Feedback bei State-Wechseln **NICE.** Subtile Vibration bei `thinking → idle` oder `thinking → awaiting-input`. *Dependencies:* S-07 #### iOS-C-04 — Slash-Command-Palette **SHOULD.** **Long-Press auf die Modifier-Bar** → öffnet Sheet mit nativer Liste aller Slash-Commands (aus S-08), Fuzzy-Search. Tap → injiziert via `send-keys`. Commands mit Argumenten → Formular-View. *Dependencies:* S-03, S-08 #### iOS-C-05 — Voice-to-Prompt **NICE.** `🎙`-Button → Speech-Recognition (lokal, iOS native) → editable Preview → Send. *Dependencies:* iOS-B-01, Mic-Permission ### Gruppe D — Session & Navigation #### iOS-D-01 — Session-Switcher (MUST) **MUST.** Native iOS-Liste der verfügbaren Sessions (via S-09). Spawn / Rename / Kill direkt aus dem Switcher. *Dependencies:* S-09 #### iOS-D-01a — Background Pre-Connect **SHOULD.** App connectet im Hintergrund zu allen bekannten Sessions parallel, hält pro Session einen kleinen In-Memory-Stream-Buffer + letzten Frame. Switch = Renderer wechselt instant. Kosten: ein Socket pro Session, ein paar MB RAM. Akzeptabel solange < ~10 aktive Sessions. *Dependencies:* iOS-D-01 #### iOS-D-01b — Optimistic-Switch mit Stale-Frame **SHOULD.** Swipe zu Session B → sofort gecachten Frame zeigen, parallel live-Sync. Niemals leerer Screen, nur kurze "sync"-Pille. *Dependencies:* iOS-D-01, iOS-D-01a #### iOS-D-01c — Predictive Thumbnails **SHOULD.** Im Session-Switcher zeigt jede Session eine kleine Live- Mini-Vorschau (z.B. 40×12 Zeichen Snapshot via `tmux capture-pane`). Beim Öffnen des Switchers werden die Thumbnails aktualisiert. *Dependencies:* iOS-D-01 #### iOS-D-02 — Scrollback-Search **SHOULD.** Such-Sheet sucht im lokalen Scrollback-Cache (iOS-A-04) mit Highlight + Jump-to-Match. Auch offline nutzbar. *Dependencies:* iOS-A-04 ### Gruppe E — Background & Lifecycle #### iOS-E-01 — WS-Keepalive **MUST.** Ping/Pong-Frames im Foreground halten Connection. iOS suspended WS gerne ohne Notification. *Dependencies:* S-02 #### iOS-E-02 — Wake-up-Sync **MUST.** App-Foreground-Event triggert sofort Reconnect + Delta-Pull. Spinner falls > 200ms. Ziel < 1s sichtbarer Sync (P-3). *Dependencies:* iOS-A-02 ### Gruppe F — Security #### iOS-F-01 — Token im Keychain **MUST.** Bearer-Token aus S-10 wird im iOS Keychain gespeichert. *Dependencies:* S-10 #### iOS-F-02 — Face-ID / Touch-ID Gate **SHOULD.** Biometrie-Lock vorm Öffnen der App. **Opt-in via Setting, default off.** *Dependencies:* — #### iOS-F-03 — TLS-Pinning via QR-Pairing **MUST.** Beim Pairing (S-10) wird der Cert-Fingerprint gepinnt. Jede künftige Connection verifiziert dagegen. Re-Pairing bei Cert-Rotation. *Dependencies:* S-10, S-11 --- ## 6. Out of Scope (locked) - **Rich Chat-Rendering.** Wir parsen den Stream nicht. ANSI bleibt ANSI. - **Embedded Mini-Terminals / Block-Selection.** Es gibt einen Stream. - **Multi-User-Sharing.** Solo. - **Org/Team-Features, Cloud-Hosted-Service.** Selbstgehostet. - **Inline-Image-Rendering** (iTerm2 protocol etc.). Eventuell später. - **Eigenes Mosh.** tmux + WebSocket reicht. - **Cross-platform-Clients (Android / Web).** Nur iOS nativ. Die bestehende HTML-UI bleibt als separates Artefakt. - **Silent-Push-Background-Wake.** iOS coalesced unzuverlässig; manueller Wake-up-Sync (iOS-E-02) reicht. - **Marker-Detection / Jump-to-Marker.** Pi liefert keine zuverlässigen Marker. - **Tap-to-Cursor.** Ohne Marker-Detection nicht robust machbar. - **Eigener Sidecar-State-Store.** State lebt in tmux (P-6). - **Disk-Buffer-Rotation.** Ein Cap, drüber hinaus = Daten verloren. Snapshot funktioniert weiter. - **Bookmarks / manuelle Marker.** Pi-interne Tools sollen das übernehmen. - **Snippet-Library** (Prompts mit Variablen). Pi-interne Tools. - **Tree-View / Tree-Navigation in iOS** (jeglicher Form, read-only oder interaktiv). Tree wird ausschließlich nativ in pi bedient. Audit hat gezeigt: Slash-Command-Dispatch ist in der ExtensionAPI nicht sauber zugänglich; Workarounds sind die Komplexität nicht wert. --- ## 7. ExtensionAPI-Audit (abgeschlossen) Das Audit wurde durchgeführt; Ergebnis liegt in [`EXTENSION-API-AUDIT.md`](./EXTENSION-API-AUDIT.md). **Kernergebnisse:** - S-07, S-08, sowie Tree-**Read** sind out-of-the-box machbar. - Tree-**Write** (Slash-Command-Dispatch wie `/fork`, `/checkout`, `/new`) ist nicht sauber zugänglich → Gruppe T gestrichen (siehe Out-of-Scope). - Tool-Call-Daten sind vollständig verfügbar (Name, Args, Result). Kein weiterer Spike vor Phase 1 nötig. --- ## 8. Phasen > Phase-Aufwände bewusst weggelassen (sind in v1 gestrichen worden). - **Spike-0 — Stream-PoC** — `pi-remote-control` um tmux pipe-pane + WS-Stream erweitern. Verifizieren dass pi sauber in tmux läuft (kein Crash, Alternate-Screen sauber, kein Latency-Problem). - **Phase 1 — Sidecar production-ready** — S-01 bis S-12 (alle), S-09a optional. - **Phase 2 — iOS-App MVP** — Renderer (Gruppe A), Input (Gruppe B ohne Hardware-KB), Status-Bar (iOS-C-01), Session-Switcher (iOS-D-01 + a/b), Reconnect-Lifecycle (Gruppe E), Auth (Gruppe F). - **Phase 3 — iOS-App Augmentation** — Slash-Palette (iOS-C-04), Voice (iOS-C-05), Thumbnails (iOS-D-01c), Scrollback-Search (iOS-D-02), Hardware-KB (iOS-B-06). --- ## 9. Offene Punkte Keine offenen Punkte mehr in v3. Q-A und Q-C wurden in dieser Version geschlossen (siehe S-09a bzw. iOS-C-02).