Terminal im Server: Claude-Code-Sessions und Shell auf iPhone, iPad und Mac-Remote-Fenster #274

Open
opened 2026-10-31 14:10:53 +00:00 by alf · 11 comments
Owner

Warum

Auf dem iPhone öffnet „Fortsetzen“ in der Claude-Code-Sessions-Liste das Terminal auf dem Mac Studio (dem Server). Der Schalter in der Kopfleiste (Smartphone/Mac-Symbol, openLocallyOnTap) soll das steuern: Zeigt er das Gerät, läuft das Terminal in der App; zeigt er den Mac, öffnet sich wie heute Terminal.app auf dem Server. Dazu braucht Iris ein Terminal, das der Server per Netz bereitstellt (Anregung: Alfs Projekt web-appliance-dashboard, dort ttyd + xterm.js).

Entscheidungen (grill-me, 2026-10-31)

  • Technik: nativ im Mac-Server (Swift, forkpty), Routen /terminal/* (öffnen, lesen per Long-Poll, schreiben, Größe ändern, schließen, Liste). Kein WebSocket, kein Plugin-Dienst, kein Proxy (die vorhandenen Proxys puffern und reichen keine Streams durch).
  • Freigabe: pro Gerät im Companion-Panel (Terminal-Symbol neben Bildschirmfreigabe, Bearbeiten, Sperren, Löschen), Standard aus; Server sperrt /terminal/* mit 403 ohne Freigabe (Muster /screen/*, RegisteredDeviceStore). Eine Sitzung gehört dem Gerät, das sie öffnet.
  • Umfang: claude --resume <id> und neue Claude-Sessions im Arbeitsordner der Session, dazu eine freie Shell; beides hinter derselben Gerätefreigabe.
  • Lebensdauer: läuft bei Verbindungsverlust weiter, wieder anhängen mit Scrollback, Ende nach Leerlauf (Vorschlag 30 Minuten, einstellbar), Liste offener Sitzungen.
  • Anzeige: Vollbild-Fenster (iPhone/iPad) bzw. Fenster (Mac) mit xterm.js und Tastenleiste (Esc, Tab, Strg, Pfeile, Bild auf/ab), „Trennen“. Die Oberfläche liefert der Server aus; die App zeigt sie in einer WebView. Die Claude-Sessions-Seite gibt nur einen Link vor.
  • Schalter: der bestehende auf dem iPhone, neu auch im Mac-Remote-Fenster (gleiche Bedeutung).
  • Freie Shell: Einstieg im „…“-Menü (iOS) bzw. der Werkzeugleiste (Mac), nur sichtbar, wenn das Gerät freigegeben ist.
  • Stufe 1: iPhone/iPad, Mac-Remote-Fenster, Mac-Server. Linux-Server später auf demselben Protokoll.

Etappen

  • E1 (am echten Server geprüft, 19/19; Mac PR #275, #276, #278) Server: /terminal/*, Freigabe pro Gerät im Companion-Panel, Terminal-Seite (xterm.js); Test per curl und Browser. Wire-Protokoll (02-Wire-Protokoll.md).
  • E2 iPhone: Vollbild-Fenster, Link aus dem Claude-Sessions-Plugin (iris/2ndbrain-ios, iris/iris-plugins).
  • E3 Mac-Remote-Fenster mit Schalter.
  • E4 Einstieg für die freie Shell (iOS und Mac).
  • später Linux-Server.
## Warum Auf dem iPhone öffnet „Fortsetzen“ in der Claude-Code-Sessions-Liste das Terminal auf dem Mac Studio (dem Server). Der Schalter in der Kopfleiste (Smartphone/Mac-Symbol, `openLocallyOnTap`) soll das steuern: Zeigt er das Gerät, läuft das Terminal in der App; zeigt er den Mac, öffnet sich wie heute Terminal.app auf dem Server. Dazu braucht Iris ein Terminal, das der Server per Netz bereitstellt (Anregung: Alfs Projekt web-appliance-dashboard, dort ttyd + xterm.js). ## Entscheidungen (grill-me, 2026-10-31) - **Technik:** nativ im Mac-Server (Swift, `forkpty`), Routen `/terminal/*` (öffnen, lesen per Long-Poll, schreiben, Größe ändern, schließen, Liste). Kein WebSocket, kein Plugin-Dienst, kein Proxy (die vorhandenen Proxys puffern und reichen keine Streams durch). - **Freigabe:** pro Gerät im Companion-Panel (Terminal-Symbol neben Bildschirmfreigabe, Bearbeiten, Sperren, Löschen), Standard aus; Server sperrt `/terminal/*` mit 403 ohne Freigabe (Muster `/screen/*`, `RegisteredDeviceStore`). Eine Sitzung gehört dem Gerät, das sie öffnet. - **Umfang:** `claude --resume <id>` und neue Claude-Sessions im Arbeitsordner der Session, dazu eine freie Shell; beides hinter derselben Gerätefreigabe. - **Lebensdauer:** läuft bei Verbindungsverlust weiter, wieder anhängen mit Scrollback, Ende nach Leerlauf (Vorschlag 30 Minuten, einstellbar), Liste offener Sitzungen. - **Anzeige:** Vollbild-Fenster (iPhone/iPad) bzw. Fenster (Mac) mit xterm.js und Tastenleiste (Esc, Tab, Strg, Pfeile, Bild auf/ab), „Trennen“. Die Oberfläche liefert der Server aus; die App zeigt sie in einer WebView. Die Claude-Sessions-Seite gibt nur einen Link vor. - **Schalter:** der bestehende auf dem iPhone, neu auch im Mac-Remote-Fenster (gleiche Bedeutung). - **Freie Shell:** Einstieg im „…“-Menü (iOS) bzw. der Werkzeugleiste (Mac), nur sichtbar, wenn das Gerät freigegeben ist. - **Stufe 1:** iPhone/iPad, Mac-Remote-Fenster, Mac-Server. Linux-Server später auf demselben Protokoll. ## Etappen - [x] **E1** (am echten Server geprüft, 19/19; Mac PR #275, #276, #278) Server: `/terminal/*`, Freigabe pro Gerät im Companion-Panel, Terminal-Seite (xterm.js); Test per curl und Browser. Wire-Protokoll (`02-Wire-Protokoll.md`). - [ ] **E2** iPhone: Vollbild-Fenster, Link aus dem Claude-Sessions-Plugin (iris/2ndbrain-ios, iris/iris-plugins). - [ ] **E3** Mac-Remote-Fenster mit Schalter. - [ ] **E4** Einstieg für die freie Shell (iOS und Mac). - [ ] **später** Linux-Server.
Author
Owner

PR #275 gemergt: feat(terminal): TerminalHost — Pseudo-Konsolen mit Long-Poll und Gerätebindung (#274)
http://docker:3000/iris/Iris/pulls/275

Commits:

  • feat(terminal): TerminalHost — Pseudo-Konsolen mit Long-Poll und Gerätebindung (#274)

Stand: Terminal-Kern TerminalHost (E1, Schritt 1)

Geändert: Neue Datei Iris/TerminalHost.swift ohne App-Abhängigkeiten (gehört durch die synchronisierte Gruppe automatisch auch zu IrisClient, kompiliert dort ohne weiteres): Pseudo-Konsole je Sitzung, Kindprozess per posix_spawn mit eigener Sitzung (POSIX_SPAWN_SETSID, POSIX_SPAWN_CLOEXEC_DEFAULT, Arbeitsordner per addchdir), Ringpuffer der Ausgabe (1 MiB, absolute Offsets), wartende Leser (Long-Poll bis 25 s), Schreiben, Größe, Schließen (HUP, nach 2 s KILL), Liste je Gerät, Leerlauf-Ende (Standard 30 Minuten), beendete Sitzungen 5 Minuten les- und listbar, höchstens 8 laufende Sitzungen. Zugriff nur für die Geräte-ID, die die Sitzung geöffnet hat (leere ID = dieser Mac). Logging über Logger ohne Ein- und Ausgabe des Terminals. Test: scripts/test-terminal-host.sh.

Befund beim Bau: fork/forkpty im laufenden Server wäre unsicher (viele Threads). posix_spawn mit SETSID liefert ein echtes Steuerterminal (ps zeigt Ss+); macOS verwirft aber eine VOR dem Start gesetzte Fenstergröße, daher wird sie danach gesetzt (Größe 0 0 im ersten Versuch).

Geprüft: swiftc mit den Projekt-Flags (-swift-version 5 -default-isolation MainActor); scripts/test-terminal-host.sh: 35 Prüfungen mit echten Prozessen grün (Ein-/Ausgabe, Exit-Status, Steuerterminal, Größe 30x100 und Änderung per SIGWINCH, Umgebung und Arbeitsordner, Zugriff nur für das eigene Gerät, Long-Poll mit und ohne Wecken, Schließen, Leerlauf, Sitzungsgrenze, 1,5 MB Ausgabe mit Scrollback-Begrenzung, Eingabegrenze, Startfehler). Gegenprobe: absichtlich falsche Erwartungen lassen den Test scheitern (2 von 35).

Nicht geprüft: In der App (Xcode-Build des Ziels Iris und IrisClient steht aus), Verhalten unter Last, claude als Kindprozess.

Offen: Routen /terminal/* und Geräte-Freigabe im Server, Claude-Start über das bestehende Skript, Companion-Panel, Terminal-Seite, Wire-Protokoll.

PR #275 gemergt: feat(terminal): TerminalHost — Pseudo-Konsolen mit Long-Poll und Gerätebindung (#274) http://docker:3000/iris/Iris/pulls/275 Commits: - feat(terminal): TerminalHost — Pseudo-Konsolen mit Long-Poll und Gerätebindung (#274) --- **Stand: Terminal-Kern `TerminalHost` (E1, Schritt 1)** **Geändert:** Neue Datei `Iris/TerminalHost.swift` ohne App-Abhängigkeiten (gehört durch die synchronisierte Gruppe automatisch auch zu IrisClient, kompiliert dort ohne weiteres): Pseudo-Konsole je Sitzung, Kindprozess per `posix_spawn` mit eigener Sitzung (`POSIX_SPAWN_SETSID`, `POSIX_SPAWN_CLOEXEC_DEFAULT`, Arbeitsordner per `addchdir`), Ringpuffer der Ausgabe (1 MiB, absolute Offsets), wartende Leser (Long-Poll bis 25 s), Schreiben, Größe, Schließen (HUP, nach 2 s KILL), Liste je Gerät, Leerlauf-Ende (Standard 30 Minuten), beendete Sitzungen 5 Minuten les- und listbar, höchstens 8 laufende Sitzungen. Zugriff nur für die Geräte-ID, die die Sitzung geöffnet hat (leere ID = dieser Mac). Logging über `Logger` ohne Ein- und Ausgabe des Terminals. Test: `scripts/test-terminal-host.sh`. **Befund beim Bau:** `fork`/`forkpty` im laufenden Server wäre unsicher (viele Threads). `posix_spawn` mit SETSID liefert ein echtes Steuerterminal (`ps` zeigt `Ss+`); macOS verwirft aber eine VOR dem Start gesetzte Fenstergröße, daher wird sie danach gesetzt (Größe `0 0` im ersten Versuch). **Geprüft:** `swiftc` mit den Projekt-Flags (`-swift-version 5 -default-isolation MainActor`); `scripts/test-terminal-host.sh`: 35 Prüfungen mit echten Prozessen grün (Ein-/Ausgabe, Exit-Status, Steuerterminal, Größe 30x100 und Änderung per SIGWINCH, Umgebung und Arbeitsordner, Zugriff nur für das eigene Gerät, Long-Poll mit und ohne Wecken, Schließen, Leerlauf, Sitzungsgrenze, 1,5 MB Ausgabe mit Scrollback-Begrenzung, Eingabegrenze, Startfehler). Gegenprobe: absichtlich falsche Erwartungen lassen den Test scheitern (2 von 35). **Nicht geprüft:** In der App (Xcode-Build des Ziels Iris und IrisClient steht aus), Verhalten unter Last, `claude` als Kindprozess. **Offen:** Routen `/terminal/*` und Geräte-Freigabe im Server, Claude-Start über das bestehende Skript, Companion-Panel, Terminal-Seite, Wire-Protokoll.
Author
Owner

PR #276 gemergt: feat(terminal): /terminal/* im Mac-Server, Freigabe pro Gerät, Terminal-Seite (#274)
http://docker:3000/iris/Iris/pulls/276

Commits:

  • feat(terminal): /terminal/* im Mac-Server, Freigabe pro Gerät, Terminal-Seite (#274)

Stand: Terminal im Mac-Server, Freigabe pro Gerät, Terminal-Seite (E1)

Geändert:

  • Server (IrisRemoteServer): Routen GET /terminal/access, POST /terminal/open, GET /terminal/list, GET /terminal/<id>/read (Long-Poll bis 20 s, Antwort per Keep-Alive), POST …/write, …/resize, …/close, dazu die statische Seite GET /terminal/ui[/<datei>] (nur eine feste Dateiliste, Content-Security-Policy). Alle außer Seite und access verlangen die Geräte-Freigabe (403 sonst; Loopback ausgenommen), die Seite registriert kein Gerät. stop() beendet alle Sitzungen.
  • Freigabe: RegisteredRemoteDevice.isTerminalAllowed (Standard aus, ältere gespeicherte Geräte bleiben lesbar), RegisteredDeviceStore.allowTerminal/revokeTerminal; Entzug, Sperren und Löschen beenden die Sitzungen des Geräts (TerminalHost.closeAll(owner:), mit Test). Companion Panel: Terminal-Symbol in der Gerätezeile (grün = erlaubt) neben Bildschirmfreigabe.
  • Claude-Start: CompanionManager.currentAgentLaunchConfig() herausgezogen (vorher inline), neues prepareClaudeCodeTerminalScript(…) schreibt dasselbe Start-Skript wie das Terminal-Fenster (Sitzungs-Proxy, Modell, --resume/--name), aber ohne abschließendes exec $SHELL; die Pseudo-Konsole führt es mit /bin/zsh -l aus. Freie Shell: /bin/zsh -il. Eigene kleine Umgebung für die Kindprozesse (nicht die der App).
  • Terminal-Seite (Resources/iris-terminal.{html,js,css}, xterm.js 5.5.0 und Fit-Addon, MIT, mit Lizenztext): Long-Poll-Schleife, Eingabe gebündelt in Reihenfolge, Tastenleiste (Esc, Tab, Strg einrastend, Pfeile, Bild auf/ab, Pos1, Ende, Strg-C, | ~ / -), Größe folgt Fenster und Bildschirmtastatur, Trennen (iris-terminal://detach), Beenden mit zweiter Bestätigung, Theme über --iris-* live. Sitzung und Anmeldung im Fragment der Adresse, das sofort entfernt wird.
  • Wire-Protokoll: Abschnitt „Terminal“ in Entwicklerdokumentation/02-Wire-Protokoll.md (separater PR im Wurzel-Repo).

Geprüft:

  • scripts/test-terminal-host.sh: 38 Prüfungen mit echten Prozessen grün (inkl. closeAll(owner:)).
  • Terminal-Seite im Headless-Chrome gegen einen Nachbau der Routen (Python, echte Pseudo-Konsole) per DevTools-Protokoll: 13 Prüfungen grün (Eingabe → Ausgabe, Rechenergebnis aus dem Terminal, Strg-C-Taste, Strg einrasten, Größenänderung Hoch- zu Querformat 44×47 → 19×105 erreicht die Konsole, Theme-Wechsel live auf Papier hell und Graphit dunkel, Neu-Anhängen mit Verlauf, Beenden mit Bestätigung, Fragment aus der Adresse entfernt); Screenshots angesehen.
  • Iris.xcodeproj baut (Xcode, Binary-Zeitstempel kontrolliert); die sechs Terminal-Dateien liegen im App-Paket und sind identisch zu den Quellen.

Nicht geprüft:

  • Die echten Routen im laufenden Server. Der Nachbau folgt dem Vertrag, ist aber nicht der Swift-Code: Gerätefreigabe (403), X-Device-ID-Bindung, Keep-Alive, das Gate für die statische Seite, /terminal/open mit claude und dem Agent-LLM-Skript.
  • claude als Kindprozess (nur sh/zsh getestet), das Verhalten bei vielen Sitzungen, IrisClient-Build (die neuen Dateien kommen über die synchronisierte Gruppe auch dorthin, IrisRemoteServer nicht).
  • Die Gerätezeile im Companion Panel (nicht gestartet).

Offen: Alf baut und startet die App lokal; dann prüfe ich Freigabe und Routen gegen den echten Server. Danach E2 (iPhone-Fenster, Link aus dem Claude-Sessions-Plugin).

PR #276 gemergt: feat(terminal): /terminal/* im Mac-Server, Freigabe pro Gerät, Terminal-Seite (#274) http://docker:3000/iris/Iris/pulls/276 Commits: - feat(terminal): /terminal/* im Mac-Server, Freigabe pro Gerät, Terminal-Seite (#274) --- **Stand: Terminal im Mac-Server, Freigabe pro Gerät, Terminal-Seite (E1)** **Geändert:** - **Server** (`IrisRemoteServer`): Routen `GET /terminal/access`, `POST /terminal/open`, `GET /terminal/list`, `GET /terminal/<id>/read` (Long-Poll bis 20 s, Antwort per Keep-Alive), `POST …/write`, `…/resize`, `…/close`, dazu die statische Seite `GET /terminal/ui[/<datei>]` (nur eine feste Dateiliste, Content-Security-Policy). Alle außer Seite und `access` verlangen die Geräte-Freigabe (403 sonst; Loopback ausgenommen), die Seite registriert kein Gerät. `stop()` beendet alle Sitzungen. - **Freigabe:** `RegisteredRemoteDevice.isTerminalAllowed` (Standard aus, ältere gespeicherte Geräte bleiben lesbar), `RegisteredDeviceStore.allowTerminal/revokeTerminal`; Entzug, Sperren und Löschen beenden die Sitzungen des Geräts (`TerminalHost.closeAll(owner:)`, mit Test). Companion Panel: Terminal-Symbol in der Gerätezeile (grün = erlaubt) neben Bildschirmfreigabe. - **Claude-Start:** `CompanionManager.currentAgentLaunchConfig()` herausgezogen (vorher inline), neues `prepareClaudeCodeTerminalScript(…)` schreibt dasselbe Start-Skript wie das Terminal-Fenster (Sitzungs-Proxy, Modell, `--resume`/`--name`), aber ohne abschließendes `exec $SHELL`; die Pseudo-Konsole führt es mit `/bin/zsh -l` aus. Freie Shell: `/bin/zsh -il`. Eigene kleine Umgebung für die Kindprozesse (nicht die der App). - **Terminal-Seite** (`Resources/iris-terminal.{html,js,css}`, xterm.js 5.5.0 und Fit-Addon, MIT, mit Lizenztext): Long-Poll-Schleife, Eingabe gebündelt in Reihenfolge, Tastenleiste (Esc, Tab, Strg einrastend, Pfeile, Bild auf/ab, Pos1, Ende, Strg-C, | ~ / -), Größe folgt Fenster und Bildschirmtastatur, Trennen (`iris-terminal://detach`), Beenden mit zweiter Bestätigung, Theme über `--iris-*` live. Sitzung und Anmeldung im Fragment der Adresse, das sofort entfernt wird. - Wire-Protokoll: Abschnitt „Terminal“ in `Entwicklerdokumentation/02-Wire-Protokoll.md` (separater PR im Wurzel-Repo). **Geprüft:** - `scripts/test-terminal-host.sh`: 38 Prüfungen mit echten Prozessen grün (inkl. `closeAll(owner:)`). - Terminal-Seite im Headless-Chrome gegen einen **Nachbau der Routen** (Python, echte Pseudo-Konsole) per DevTools-Protokoll: 13 Prüfungen grün (Eingabe → Ausgabe, Rechenergebnis aus dem Terminal, Strg-C-Taste, Strg einrasten, Größenänderung Hoch- zu Querformat 44×47 → 19×105 erreicht die Konsole, Theme-Wechsel live auf Papier hell und Graphit dunkel, Neu-Anhängen mit Verlauf, Beenden mit Bestätigung, Fragment aus der Adresse entfernt); Screenshots angesehen. - Iris.xcodeproj baut (Xcode, Binary-Zeitstempel kontrolliert); die sechs Terminal-Dateien liegen im App-Paket und sind identisch zu den Quellen. **Nicht geprüft:** - **Die echten Routen im laufenden Server.** Der Nachbau folgt dem Vertrag, ist aber nicht der Swift-Code: Gerätefreigabe (403), `X-Device-ID`-Bindung, Keep-Alive, das Gate für die statische Seite, `/terminal/open` mit `claude` und dem Agent-LLM-Skript. - `claude` als Kindprozess (nur `sh`/`zsh` getestet), das Verhalten bei vielen Sitzungen, IrisClient-Build (die neuen Dateien kommen über die synchronisierte Gruppe auch dorthin, `IrisRemoteServer` nicht). - Die Gerätezeile im Companion Panel (nicht gestartet). **Offen:** Alf baut und startet die App lokal; dann prüfe ich Freigabe und Routen gegen den echten Server. Danach E2 (iPhone-Fenster, Link aus dem Claude-Sessions-Plugin).
Author
Owner

PR #140 gemergt: docs(wire): Terminal /terminal/* im Mac-Server (iris/Iris#274)
http://docker:3000/alf/2ndbrain/pulls/140

Commits:

PR #140 gemergt: docs(wire): Terminal /terminal/* im Mac-Server (iris/Iris#274) http://docker:3000/alf/2ndbrain/pulls/140 Commits: - docs(wire): Terminal /terminal/* im Mac-Server (iris/Iris#274)
Author
Owner

PR #277 gemergt: test(terminal): Prüfskript gegen den laufenden Server (#274)
http://docker:3000/iris/Iris/pulls/277

Commits:

  • test(terminal): Prüfskript gegen den laufenden Server (#274)

Stand: Prüfung gegen den laufenden Server (E1)

Geprüft am echten, neu gebauten Server (Port 8765, ohne Token, von Loopback): GET /terminal/ui/ und alle fünf Dateien kommen mit richtigen Typen und den Größen der Quellen (11637, 3278, 289441, 5559, 1497 Bytes), mit Content-Security-Policy und Cache-Control: no-store; unbekannte Dateien und Pfad-Tricks (..%2f, %2e%2e/, NUL) ergeben 404; GET /terminal/access, POST /terminal/open, GET /terminal/list, GET /terminal/<id>/read ohne Token oder mit falschem Token ergeben 401; der Gerätespeicher bleibt beim Laden der Seite unverändert (kein Phantomgerät).

Neu: scripts/terminal-e2e.sh prüft die geschützten Routen gegen den laufenden Server von der LAN-Adresse aus (Loopback ist von der Freigabe ausgenommen): 403 ohne Freigabe, Freigabe im Companion Panel, Shell mit Rechenergebnis und Größe, Größenänderung, Liste, 404 bei unbekannter Sitzung, neue Claude-Code-Session, Entzug beendet die Sitzungen (Zählung der Kindprozesse von Iris). Das Token übergibt der Nutzer per Umgebungsvariable, es geht nie an Claude.

Nicht geprüft: Die geschützten Routen (Freigabe, Geräte-ID-Bindung, open mit Claude Code) laufen erst mit dem Skript.

PR #277 gemergt: test(terminal): Prüfskript gegen den laufenden Server (#274) http://docker:3000/iris/Iris/pulls/277 Commits: - test(terminal): Prüfskript gegen den laufenden Server (#274) --- **Stand: Prüfung gegen den laufenden Server (E1)** **Geprüft am echten, neu gebauten Server** (Port 8765, ohne Token, von Loopback): `GET /terminal/ui/` und alle fünf Dateien kommen mit richtigen Typen und den Größen der Quellen (11637, 3278, 289441, 5559, 1497 Bytes), mit Content-Security-Policy und `Cache-Control: no-store`; unbekannte Dateien und Pfad-Tricks (`..%2f`, `%2e%2e/`, NUL) ergeben 404; `GET /terminal/access`, `POST /terminal/open`, `GET /terminal/list`, `GET /terminal/<id>/read` ohne Token oder mit falschem Token ergeben 401; der Gerätespeicher bleibt beim Laden der Seite unverändert (kein Phantomgerät). **Neu:** `scripts/terminal-e2e.sh` prüft die geschützten Routen gegen den laufenden Server von der LAN-Adresse aus (Loopback ist von der Freigabe ausgenommen): 403 ohne Freigabe, Freigabe im Companion Panel, Shell mit Rechenergebnis und Größe, Größenänderung, Liste, 404 bei unbekannter Sitzung, neue Claude-Code-Session, Entzug beendet die Sitzungen (Zählung der Kindprozesse von Iris). Das Token übergibt der Nutzer per Umgebungsvariable, es geht nie an Claude. **Nicht geprüft:** Die geschützten Routen (Freigabe, Geräte-ID-Bindung, `open` mit Claude Code) laufen erst mit dem Skript.
Author
Owner

PR #278 gemergt: fix(terminal): Prüfskript wartet per Abfrage, Bash-3.2-tauglich (#274)
http://docker:3000/iris/Iris/pulls/278

Commits:

  • fix(terminal): Prüfskript wartet per Abfrage, Bash-3.2-tauglich (#274)

Stand: Prüfskript repariert (erster Lauf des Nutzers)

Erster Lauf (Alf, Mac Studio, LAN-Adresse): Teil 1 bestand (4 von 4): ohne Freigabe antwortet der echte Server access mit 200 und allowed: false, open und list mit 403. Teil 2 bis 3 schlugen fehl, weil das Skript nicht gewartet hat: read bekommt in der Claude-Code-Sitzung keine Eingabe und kehrte sofort zurück, das Terminal-Symbol war beim Prüfen noch aus (403). Das ist ein Fehler des Skripts, kein Befund am Server.

Fehler im Skript (behoben): (1) read-Pausen durch Abfrage von GET /terminal/access ersetzt (wartet bis zu 3 Minuten auf Einschalten und Ausschalten, braucht keine Tastatur). (2) case innerhalb von $(…) bricht in der macOS-Bash 3.2 ab; bash -n mit einer neueren Bash hatte das nicht gezeigt, jetzt #!/bin/bash und Prüfung mit /bin/bash -n. (3) Falsch-positiv: grep -q "" bei leerer Sitzungs-ID wertete „Liste enthält die Sitzung“ als bestanden; jetzt nur mit nicht leerer ID. (4) Die Entzugsprüfung verlangt, dass vorher mindestens ein Kindprozess lief.

Nicht geprüft: Der geschützte Teil (Freigabe, Shell, Claude-Session, Entzug) steht bis zum zweiten Lauf aus.

PR #278 gemergt: fix(terminal): Prüfskript wartet per Abfrage, Bash-3.2-tauglich (#274) http://docker:3000/iris/Iris/pulls/278 Commits: - fix(terminal): Prüfskript wartet per Abfrage, Bash-3.2-tauglich (#274) --- **Stand: Prüfskript repariert (erster Lauf des Nutzers)** **Erster Lauf (Alf, Mac Studio, LAN-Adresse):** Teil 1 bestand (4 von 4): ohne Freigabe antwortet der echte Server `access` mit 200 und `allowed: false`, `open` und `list` mit 403. Teil 2 bis 3 schlugen fehl, weil das Skript nicht gewartet hat: `read` bekommt in der Claude-Code-Sitzung keine Eingabe und kehrte sofort zurück, das Terminal-Symbol war beim Prüfen noch aus (403). Das ist ein Fehler des Skripts, kein Befund am Server. **Fehler im Skript (behoben):** (1) `read`-Pausen durch Abfrage von `GET /terminal/access` ersetzt (wartet bis zu 3 Minuten auf Einschalten und Ausschalten, braucht keine Tastatur). (2) `case` innerhalb von `$(…)` bricht in der macOS-Bash 3.2 ab; `bash -n` mit einer neueren Bash hatte das nicht gezeigt, jetzt `#!/bin/bash` und Prüfung mit `/bin/bash -n`. (3) Falsch-positiv: `grep -q ""` bei leerer Sitzungs-ID wertete „Liste enthält die Sitzung“ als bestanden; jetzt nur mit nicht leerer ID. (4) Die Entzugsprüfung verlangt, dass vorher mindestens ein Kindprozess lief. **Nicht geprüft:** Der geschützte Teil (Freigabe, Shell, Claude-Session, Entzug) steht bis zum zweiten Lauf aus.
Author
Owner

E1 am echten Server geprüft (Alf lief scripts/terminal-e2e.sh auf dem Mac Studio gegen die LAN-Adresse; 19 von 19 Prüfungen):

  • Ohne Freigabe: GET /terminal/access 200 mit allowed: false; POST /terminal/open und GET /terminal/list 403.
  • Mit eingeschaltetem Terminal-Symbol im Companion Panel: freie Shell geöffnet (100×30), Eingabe stty size; echo e2e-$((20+22)); pwd liefert 30 100, e2e-42, /private/tmp; Größe ändern 200; Liste enthält die Sitzung; unbekannte Sitzung 404.
  • Neue Claude-Code-Session in /tmp mit dem aktuellen Agent-LLM: Sitzung öffnet (200) und liefert Ausgabe (1012 Zeichen, Claude-Code-Oberfläche).
  • Entzug des Symbols: open wieder 403, Lesen der alten Sitzung 403, beide offenen Sitzungen sind beendet (Kindprozesse von Iris 2 → 0).
  • Statische Seite ohne Anmeldung 200. Davor ohne Token geprüft: Seite und Dateien mit richtigen Typen, Pfad-Tricks 404, API ohne oder mit falschem Token 401, kein Phantomgerät.

Beim ersten Lauf lagen Fehler im Prüfskript (kein Warten bei fehlender Tastatur, case in $(…) in Bash 3.2, falsch-positive Prüfung), nicht im Server; behoben in PR #278.

Nicht geprüft: Terminal-Seite gegen den echten Server in einer WebView; --resume einer bestehenden Session; Gerätezeile im Companion Panel wurde bedient (Einschalten und Ausschalten wirkten), aber nicht angesehen.

Weiter: E2 (iPhone-Fenster, Link aus der Claude-Sessions-Seite).

**E1 am echten Server geprüft (Alf lief `scripts/terminal-e2e.sh` auf dem Mac Studio gegen die LAN-Adresse; 19 von 19 Prüfungen):** - Ohne Freigabe: `GET /terminal/access` 200 mit `allowed: false`; `POST /terminal/open` und `GET /terminal/list` 403. - Mit eingeschaltetem Terminal-Symbol im Companion Panel: freie Shell geöffnet (100×30), Eingabe `stty size; echo e2e-$((20+22)); pwd` liefert `30 100`, `e2e-42`, `/private/tmp`; Größe ändern 200; Liste enthält die Sitzung; unbekannte Sitzung 404. - Neue Claude-Code-Session in `/tmp` mit dem aktuellen Agent-LLM: Sitzung öffnet (200) und liefert Ausgabe (1012 Zeichen, Claude-Code-Oberfläche). - Entzug des Symbols: `open` wieder 403, Lesen der alten Sitzung 403, **beide offenen Sitzungen sind beendet** (Kindprozesse von Iris 2 → 0). - Statische Seite ohne Anmeldung 200. Davor ohne Token geprüft: Seite und Dateien mit richtigen Typen, Pfad-Tricks 404, API ohne oder mit falschem Token 401, kein Phantomgerät. Beim ersten Lauf lagen Fehler im Prüfskript (kein Warten bei fehlender Tastatur, `case` in `$(…)` in Bash 3.2, falsch-positive Prüfung), nicht im Server; behoben in PR #278. **Nicht geprüft:** Terminal-Seite gegen den echten Server in einer WebView; `--resume` einer bestehenden Session; Gerätezeile im Companion Panel wurde bedient (Einschalten und Ausschalten wirkten), aber nicht angesehen. **Weiter:** E2 (iPhone-Fenster, Link aus der Claude-Sessions-Seite).
Author
Owner

PR #279 gemergt: feat(terminal): Wischen zum Scrollen, Tastatur ausblenden (iris/Iris#274)
http://docker:3000/iris/Iris/pulls/279

Commits:

  • feat(terminal): Wischen zum Scrollen, Tastatur ausblenden (iris/Iris#274)

Stand: Terminal-Seite – Wischen und Tastatur ausblenden

Geändert (iris-terminal.js/.css)

  • Senkrechtes Wischen im Terminal scrollt den Verlauf (Finger nach oben = weiter nach unten). In Vollbild-Programmen ohne Verlauf (alternativer Puffer) gehen Pfeil-hoch/-runter an das Programm.
  • Tastatur ausblenden: Taste „⌨︎↓“ am Anfang der Tastenleiste und Wischen nach unten auf der Tastenleiste. Tippen ins Terminal bringt sie zurück.
  • Tasten der Leiste lösen jetzt beim Loslassen und nur ohne Wischbewegung aus; vorher drückte schon der Fingerkontakt die Taste, und die Leiste ließ sich nicht seitlich verschieben.

Geprüft

  • Syntax (node --check).

Nicht geprüft

  • Alles auf dem iPhone: Wischgefühl (Geschwindigkeit je Zeile), Verhalten in Claude Code (normaler oder alternativer Puffer), Tastatur-Ausblenden, Leiste verschieben.

Hinweis: Die Seite liegt im Mac-Server; die Änderung wirkt nach Neubau der Mac-App.

PR #279 gemergt: feat(terminal): Wischen zum Scrollen, Tastatur ausblenden (iris/Iris#274) http://docker:3000/iris/Iris/pulls/279 Commits: - feat(terminal): Wischen zum Scrollen, Tastatur ausblenden (iris/Iris#274) --- **Stand: Terminal-Seite – Wischen und Tastatur ausblenden** **Geändert** (`iris-terminal.js`/`.css`) - Senkrechtes Wischen im Terminal scrollt den Verlauf (Finger nach oben = weiter nach unten). In Vollbild-Programmen ohne Verlauf (alternativer Puffer) gehen Pfeil-hoch/-runter an das Programm. - Tastatur ausblenden: Taste „⌨︎↓“ am Anfang der Tastenleiste und Wischen nach unten auf der Tastenleiste. Tippen ins Terminal bringt sie zurück. - Tasten der Leiste lösen jetzt beim Loslassen und nur ohne Wischbewegung aus; vorher drückte schon der Fingerkontakt die Taste, und die Leiste ließ sich nicht seitlich verschieben. **Geprüft** - Syntax (`node --check`). **Nicht geprüft** - Alles auf dem iPhone: Wischgefühl (Geschwindigkeit je Zeile), Verhalten in Claude Code (normaler oder alternativer Puffer), Tastatur-Ausblenden, Leiste verschieben. **Hinweis:** Die Seite liegt im Mac-Server; die Änderung wirkt nach Neubau der Mac-App.
Author
Owner

PR #280 gemergt: fix(terminal): Wischen im Chat scrollt den Chat, in der Eingabe die Historie (iris/Iris#274)
http://docker:3000/iris/Iris/pulls/280

Commits:

  • fix(terminal): Wischen im Chat scrollt den Chat, in der Eingabe die Historie (iris/Iris#274)

Stand: Terminal-Seite – Wischen im Chat scrollt den Chat, in der Eingabe die Eingabe-Historie

Befund: In Claude Code (alternativer Puffer) gingen alle Wischbewegungen als Pfeil-hoch/-runter ans Programm und schalteten nur die früheren Prompts durch.

Geändert (iris-terminal.js)

  • Der Beginn des Wischens entscheidet: Liegt er in der Eingabe (Zeilen um den Cursor, −3 bis +2), gehen Pfeiltasten ans Programm. Liegt er woanders, scrollt der Chat.
  • Chat-Scrollen: als SGR-Mausrad an der Fingerstelle, wenn das Programm die Maus abfragt (modes.mouseTrackingMode); sonst als Bild-hoch/-runter je halber Bildschirmhöhe.
  • Normaler Puffer unverändert: scrollt den Terminal-Verlauf.

Geprüft: Syntax (node --check).

Nicht geprüft: Alles auf dem iPhone; ob Claude Code bei dir die Maus abfragt (sonst greift der Bild-hoch/-runter-Weg); ob die Eingabe-Zone von −3/+2 Zeilen bei mehrzeiligen Prompts passt.

PR #280 gemergt: fix(terminal): Wischen im Chat scrollt den Chat, in der Eingabe die Historie (iris/Iris#274) http://docker:3000/iris/Iris/pulls/280 Commits: - fix(terminal): Wischen im Chat scrollt den Chat, in der Eingabe die Historie (iris/Iris#274) --- **Stand: Terminal-Seite – Wischen im Chat scrollt den Chat, in der Eingabe die Eingabe-Historie** **Befund:** In Claude Code (alternativer Puffer) gingen alle Wischbewegungen als Pfeil-hoch/-runter ans Programm und schalteten nur die früheren Prompts durch. **Geändert** (`iris-terminal.js`) - Der Beginn des Wischens entscheidet: Liegt er in der Eingabe (Zeilen um den Cursor, −3 bis +2), gehen Pfeiltasten ans Programm. Liegt er woanders, scrollt der Chat. - Chat-Scrollen: als SGR-Mausrad an der Fingerstelle, wenn das Programm die Maus abfragt (`modes.mouseTrackingMode`); sonst als Bild-hoch/-runter je halber Bildschirmhöhe. - Normaler Puffer unverändert: scrollt den Terminal-Verlauf. **Geprüft:** Syntax (`node --check`). **Nicht geprüft:** Alles auf dem iPhone; ob Claude Code bei dir die Maus abfragt (sonst greift der Bild-hoch/-runter-Weg); ob die Eingabe-Zone von −3/+2 Zeilen bei mehrzeiligen Prompts passt.
Author
Owner

PR #281 gemergt: fix(terminal): Chat-Scrollen gebündelt und mit Auslaufen (iris/Iris#274)
http://docker:3000/iris/Iris/pulls/281

Commits:

  • fix(terminal): Chat-Scrollen gebündelt und mit Auslaufen (iris/Iris#274)

Stand: Terminal-Seite – Scrollen im Chat flüssiger

Befund: Das Chat-Scrollen auf dem iPhone funktionierte, ruckelte aber (laut Alf). Vermutete Ursachen: jede Zeile als eigene, nacheinander abgearbeitete Anfrage; kein Auslaufen nach dem Loslassen.

Geändert (iris-terminal.js)

  • Mausrad-Ticks werden gesammelt und höchstens alle 60 ms in einer Anfrage geschickt (bis 30 Ticks).
  • Auslaufen nach dem Loslassen eines schnellen Wischs (Geschwindigkeit aus den letzten Bewegungen, Abbremsen um etwa 96 % pro Sekunde); nicht bei Wischen in der Eingabe.
  • Umsetzung der Modi (emitScroll/takeLines) vereinheitlicht.

Geprüft: Syntax (node --check).

Nicht geprüft: Alles auf dem iPhone; ob die 60 ms und die Abbremsung sich gut anfühlen (Stellschrauben: Verzögerung in queueWheel, Faktor 0.04 in startInertia).

PR #281 gemergt: fix(terminal): Chat-Scrollen gebündelt und mit Auslaufen (iris/Iris#274) http://docker:3000/iris/Iris/pulls/281 Commits: - fix(terminal): Chat-Scrollen gebündelt und mit Auslaufen (iris/Iris#274) --- **Stand: Terminal-Seite – Scrollen im Chat flüssiger** **Befund:** Das Chat-Scrollen auf dem iPhone funktionierte, ruckelte aber (laut Alf). Vermutete Ursachen: jede Zeile als eigene, nacheinander abgearbeitete Anfrage; kein Auslaufen nach dem Loslassen. **Geändert** (`iris-terminal.js`) - Mausrad-Ticks werden gesammelt und höchstens alle 60 ms in einer Anfrage geschickt (bis 30 Ticks). - Auslaufen nach dem Loslassen eines schnellen Wischs (Geschwindigkeit aus den letzten Bewegungen, Abbremsen um etwa 96 % pro Sekunde); nicht bei Wischen in der Eingabe. - Umsetzung der Modi (`emitScroll`/`takeLines`) vereinheitlicht. **Geprüft:** Syntax (`node --check`). **Nicht geprüft:** Alles auf dem iPhone; ob die 60 ms und die Abbremsung sich gut anfühlen (Stellschrauben: Verzögerung in `queueWheel`, Faktor `0.04` in `startInertia`).
Author
Owner

PR #282 gemergt: feat(terminal): Terminal im Mac-Remote-Fenster mit Rechner/Server-Schalter und Sitzungsliste (iris/Iris#274)
http://docker:3000/iris/Iris/pulls/282

Commits:

  • feat(terminal): Terminal im Mac-Remote-Fenster mit Rechner/Server-Schalter und Sitzungsliste (iris/Iris#274)

Stand: Etappe 3 – Terminal im Mac-Remote-Fenster (Iris/IrisClient)

Geändert

  • Neu RemoteTerminal.swift: RemoteTerminalClient (access/open/list/close gegen /terminal/* über die gepinnte Sitzung), RemoteTerminalWindowController (ein Fenster je Sitzung mit der Terminal-Seite des Servers; „Trennen“ schließt es, die Sitzung läuft weiter), RemoteTerminalListView (offene Sitzungen: Öffnen, Beenden, „Neue Shell“).
  • Seitenpanel „Plugin“ im Remote-Fenster (PluginPanelView): Statuszeile zeigt, sobald der Server das Terminal für dieses Gerät freigegeben hat, den Schalter Rechner/Server (laptopcomputer/server.rack, Standard Server = bisheriges Verhalten) und einen Terminal-Knopf für die Liste samt freier Shell.
  • Die Plugin-Seite bekommt window.irisHost.terminal wie auf dem iPhone (available, target = device/mac); iris-terminal://open?... aus der Seite öffnet Claude Code im Fenster (nur Claude, Sitzungs-ID muss UUID sein).
  • PinnedWebView: iris-terminal://-Adressen abfangen, Skript nach jedem Laden.
  • RemoteServerClient.terminalPageURL.

Geprüft

  • Xcode-Build des Schemas Iris erfolgreich.

Nicht geprüft

  • Ob das Fenster mit Terminal-Seite tatsächlich lädt (Zertifikats-Pinning, Fragment, Theme), Schalter, Liste, Hand-off aus dem Plugin — alles nur gebaut, nicht gestartet.
  • Build des Schemas IrisClient.
  • Die Freigabe-Prüfung für das lokale Gerät (Loopback ist ausgenommen; auf dem Server-Mac selbst wird das Terminal-Symbol nicht gebraucht).
PR #282 gemergt: feat(terminal): Terminal im Mac-Remote-Fenster mit Rechner/Server-Schalter und Sitzungsliste (iris/Iris#274) http://docker:3000/iris/Iris/pulls/282 Commits: - feat(terminal): Terminal im Mac-Remote-Fenster mit Rechner/Server-Schalter und Sitzungsliste (iris/Iris#274) --- **Stand: Etappe 3 – Terminal im Mac-Remote-Fenster (Iris/IrisClient)** **Geändert** - Neu `RemoteTerminal.swift`: `RemoteTerminalClient` (access/open/list/close gegen `/terminal/*` über die gepinnte Sitzung), `RemoteTerminalWindowController` (ein Fenster je Sitzung mit der Terminal-Seite des Servers; „Trennen“ schließt es, die Sitzung läuft weiter), `RemoteTerminalListView` (offene Sitzungen: Öffnen, Beenden, „Neue Shell“). - Seitenpanel „Plugin“ im Remote-Fenster (`PluginPanelView`): Statuszeile zeigt, sobald der Server das Terminal für dieses Gerät freigegeben hat, den Schalter Rechner/Server (`laptopcomputer`/`server.rack`, Standard Server = bisheriges Verhalten) und einen Terminal-Knopf für die Liste samt freier Shell. - Die Plugin-Seite bekommt `window.irisHost.terminal` wie auf dem iPhone (`available`, `target` = `device`/`mac`); `iris-terminal://open?...` aus der Seite öffnet Claude Code im Fenster (nur Claude, Sitzungs-ID muss UUID sein). - `PinnedWebView`: `iris-terminal://`-Adressen abfangen, Skript nach jedem Laden. - `RemoteServerClient.terminalPageURL`. **Geprüft** - Xcode-Build des Schemas Iris erfolgreich. **Nicht geprüft** - Ob das Fenster mit Terminal-Seite tatsächlich lädt (Zertifikats-Pinning, Fragment, Theme), Schalter, Liste, Hand-off aus dem Plugin — alles nur gebaut, nicht gestartet. - Build des Schemas IrisClient. - Die Freigabe-Prüfung für das lokale Gerät (Loopback ist ausgenommen; auf dem Server-Mac selbst wird das Terminal-Symbol nicht gebraucht).
Author
Owner

PR #283 gemergt: docs(handbuch): Kapitel Terminal auf iPhone und Mac-Client (iris/Iris#274)
http://docker:3000/iris/Iris/pulls/283

Commits:

  • docs(handbuch): Kapitel Terminal auf iPhone und Mac-Client (iris/Iris#274)

Stand: Handbuch-Kapitel „Terminal auf iPhone und Mac-Client“

Geändert

  • Neues Kapitel (Quelle im Vault, Manifest und Index ergänzt): Freigabe im Companion Panel, Schalter Gerät/Server, Fortsetzen/Neue Session, freie Shell und Liste, Tastenleiste, Wischen, Tastatur ausblenden, Fehlerbilder. Kurzer Abschnitt „Terminal erlauben“ im Kapitel Remote-Server und Geräteverwaltung.
  • Gebaut mit build_handbuch.py (30 Kapitel); BENUTZERHANDBUCH.md (Iris-Hilfe-Kontext) in Iris/Resources/ aktualisiert, die HTML-Site in Handbuch/ beider Apps neu erzeugt (dort ungetrackt).

Geprüft: Build ohne Fehler.
Nicht geprüft: Darstellung der Site in der App; das Kapitel beschreibt auch den Stand des Mac-Remote-Fensters, der noch nicht von Hand ausprobiert ist.
Offen: Linux-Server hat noch kein Terminal (steht im Kapitel).

PR #283 gemergt: docs(handbuch): Kapitel Terminal auf iPhone und Mac-Client (iris/Iris#274) http://docker:3000/iris/Iris/pulls/283 Commits: - docs(handbuch): Kapitel Terminal auf iPhone und Mac-Client (iris/Iris#274) --- **Stand: Handbuch-Kapitel „Terminal auf iPhone und Mac-Client“** **Geändert** - Neues Kapitel (Quelle im Vault, Manifest und Index ergänzt): Freigabe im Companion Panel, Schalter Gerät/Server, Fortsetzen/Neue Session, freie Shell und Liste, Tastenleiste, Wischen, Tastatur ausblenden, Fehlerbilder. Kurzer Abschnitt „Terminal erlauben“ im Kapitel Remote-Server und Geräteverwaltung. - Gebaut mit `build_handbuch.py` (30 Kapitel); `BENUTZERHANDBUCH.md` (Iris-Hilfe-Kontext) in `Iris/Resources/` aktualisiert, die HTML-Site in `Handbuch/` beider Apps neu erzeugt (dort ungetrackt). **Geprüft:** Build ohne Fehler. **Nicht geprüft:** Darstellung der Site in der App; das Kapitel beschreibt auch den Stand des Mac-Remote-Fensters, der noch nicht von Hand ausprobiert ist. **Offen:** Linux-Server hat noch kein Terminal (steht im Kapitel).
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
iris/Iris#274
No description provided.