Skip to content

docs(desktop): add PTY supervisor implementation plan#803

Closed
Kitenite wants to merge 1 commit into
mainfrom
daemon-transfer
Closed

docs(desktop): add PTY supervisor implementation plan#803
Kitenite wants to merge 1 commit into
mainfrom
daemon-transfer

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented Jan 18, 2026

Summary

  • Adds documentation for the PTY Supervisor architecture pattern
  • Documents how to split the daemon into supervisor + proxy to survive app updates
  • Includes implementation phases, IPC protocol, and upgrade flow diagrams

Context

When the app updates, the terminal daemon restarts, killing all PTYs and shell processes. This plan documents an architecture where:

  • Supervisor: Owns PTYs and sessions, rarely updated
  • Daemon: Protocol bridge to app, can be updated freely

Test plan

  • Review documentation for clarity and completeness
  • Validate architecture approach before implementation

Summary by CodeRabbit

  • Documentation
    • Added architectural plan for PTY subsystem restructuring and process reorganization.

Note: This PR contains primarily internal planning documentation with no immediate user-facing changes or feature updates.

✏️ Tip: You can customize this high-level summary in your review settings.

Add RFC document outlining the architecture for splitting the terminal
daemon into two processes (daemon + supervisor) to allow daemon updates
without killing running shell processes.

The plan includes:
- Architecture diagrams and responsibility split
- 4 implementation phases
- IPC protocol definition
- Daemon upgrade flow
- File changes summary and effort estimate
- Tradeoffs vs enhanced cold restore alternative
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 18, 2026

📝 Walkthrough

Walkthrough

Implements a two-process PTY architecture by introducing a Supervisor process that owns PTYs and sessions, while the Daemon becomes a stateless proxy. Includes new supervisor subsystem, terminal-host reorganization, and phased integration plan.

Changes

Cohort / File(s) Summary
New pty-supervisor subsystem
apps/desktop/src/main/pty-supervisor/index.ts, pty-supervisor/supervisor.ts, pty-supervisor/session.ts, pty-supervisor/types.ts
New supervisor component with entry point, session management, IPC protocol types, and Session class moved from terminal-host.
Terminal-host reorganization
apps/desktop/src/main/terminal-host/index.ts, terminal-host/supervisor-client.ts
Index simplified to proxy-only behavior; new supervisor-client connects daemon to supervisor. Existing session and terminal-host implementations moved to supervisor subsystem.
Daemon client bridge
lib/terminal-host/client.ts
Updated to spawn and communicate with supervisor instead of managing PTYs directly, becoming a stateless protocol bridge.
Architecture documentation
apps/desktop/docs/PTY_SUPERVISOR_PLAN.md
Design document outlining two-process architecture with four-phase implementation plan (creation, daemon integration, restart handling, optional upgrade path).

Sequence Diagram(s)

sequenceDiagram
    participant App
    participant Daemon as Daemon<br/>(Stateless Proxy)
    participant Supervisor as Supervisor<br/>(PTY Owner)

    App->>Daemon: Create Session Request
    Daemon->>Supervisor: Forward to Supervisor via IPC
    Supervisor->>Supervisor: Create PTY<br/>& Session
    Supervisor-->>Daemon: Session Handle
    Daemon-->>App: Session Handle
    
    App->>Daemon: Write to Terminal
    Daemon->>Supervisor: Proxy Write Operation
    Supervisor->>Supervisor: Write to PTY
    Supervisor-->>Daemon: Operation Complete
    Daemon-->>App: Response
    
    Note over Daemon,Supervisor: Daemon restarts<br/>without data loss
    Daemon->>Supervisor: Reconnect & Sync
    Supervisor-->>Daemon: Buffered Operations
    Daemon-->>App: Resume Stream
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 A supervisor rises, noble and true,
Taking PTY ownership—a grand debut!
The daemon stands ready, stateless and fleet,
Forwarding messages, oh what a treat!
Two processes dancing, a hop and a bound,
Robustness and simplicity perfectly found! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the primary change: adding documentation for a PTY supervisor implementation plan.
Description check ✅ Passed The description follows the template structure with Summary, Context, and Test plan sections, providing sufficient detail about the architecture change.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@apps/desktop/docs/PTY_SUPERVISOR_PLAN.md`:
- Around line 33-49: Add explicit IPC access-control requirements to the plan:
specify socket file ownership and restrictive permissions/umask for the
supervisor socket (~/.superset/pty-supervisor.sock) and terminal-host socket
(~/.superset/terminal-host.sock), require credential verification (validate peer
UID/PID) on accept, and define an optional shared secret or signed handshake
exchanged by SupervisorClient <-> Terminal Host Daemon before any session
operations; document where checks occur (PTY Supervisor, Session,
HeadlessEmulator, pty-subprocess lifecycle and node-pty PTY creation) and
failure-handling policy (reject/reset connection and log security events).
- Around line 33-41: The document currently lists Unix socket paths
(~/.superset/terminal-host.sock and ~/.superset/pty-supervisor.sock) for the
Terminal Host Daemon / SupervisorClient but doesn’t mention Windows; update the
PTY_SUPERVISOR_PLAN to explicitly call out Windows transport by adding a note
that on Windows the daemon and SupervisorClient will use named pipes (e.g.,
\\.\pipe\superset\terminal-host and \\.\pipe\superset\pty-supervisor or a
documented app-specific pipe namespace), include any path/namespace conventions
and permission/authentication considerations, and mention fallback behavior or
detection logic so the implementation (Terminal Host Daemon and
SupervisorClient) can choose the appropriate transport per-OS.
- Around line 14-24: The fenced code blocks in PTY_SUPERVISOR_PLAN.md are
missing language identifiers (tripping MD040); update each triple-backtick fence
that contains the ASCII diagrams and listings (e.g., the blocks starting with
"CURRENT:/NEW:" diagram, the large Terminal/Daemon/PTY diagram, the
apps/desktop/src/main/pty-supervisor/ tree, the
apps/desktop/src/main/terminal-host/ tree, and the numbered upgrade flow block)
by adding "text" (or another appropriate language) immediately after the opening
``` so each fenced block becomes ```text; ensure every fenced block in the
ranges flagged (lines with the diagrams and trees) is updated consistently.
🧹 Nitpick comments (1)
apps/desktop/docs/PTY_SUPERVISOR_PLAN.md (1)

35-38: Handshake should include an explicit protocol version.
The architecture mentions protocol versioning, but the IPC hello only carries daemonVersion. Add a protocolVersion (or feature flags) so mixed versions can negotiate safely.

Suggested doc update
 type SupervisorRequest =
-  | { type: "hello"; daemonPid: number; daemonVersion: string }
+  | { type: "hello"; daemonPid: number; daemonVersion: string; protocolVersion: number }
   | { type: "createSession"; sessionId: string; workspaceId: string; paneId: string; cwd: string; shell: string; env: Record<string, string>; cols: number; rows: number }
   | { type: "attachSession"; sessionId: string }
   | { type: "detachSession"; sessionId: string }
   | { type: "write"; sessionId: string; data: string }
   | { type: "resize"; sessionId: string; cols: number; rows: number }
   | { type: "getSnapshot"; sessionId: string }
   | { type: "killSession"; sessionId: string; signal?: string }
   | { type: "listSessions" }

 type HelloResponse = {
   supervisorPid: number;
   supervisorVersion: string;
+  protocolVersion: number;
   sessions: SessionInfo[];  // Existing sessions for reconnection
 }

Also applies to: 122-139

Comment on lines +14 to +24
```
CURRENT:
App → Daemon → pty-subprocess → PTY
(dies on update, kills PTYs)

NEW:
App → Daemon → Supervisor → pty-subprocess → PTY
↓ ↓
(can restart) (stays alive, PTYs survive)
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add fenced code block languages to satisfy markdownlint (MD040).
This is flagged by static analysis; add text (or a more specific language if applicable) to each fenced block.

Suggested fix
-```
+```text
 CURRENT:
 App → Daemon → pty-subprocess → PTY
        ↓
    (dies on update, kills PTYs)

 NEW:
 App → Daemon → Supervisor → pty-subprocess → PTY
        ↓            ↓
    (can restart)  (stays alive, PTYs survive)
-```
+```

-```
+```text
 ┌─────────────────────────────────────────────────────────────┐
 │ Electron App                                                │
 │   └── TerminalHostClient                                    │
 └──────────────┬──────────────────────────────────────────────┘
                │ Unix socket: ~/.superset/terminal-host.sock
 ┌──────────────▼──────────────────────────────────────────────┐
 │ Terminal Host Daemon         ← Can restart on app update    │
 │   - Client authentication                                   │
 │   - Protocol versioning                                     │
 │   - Event routing                                           │
 │   └── SupervisorClient                                      │
 └──────────────┬──────────────────────────────────────────────┘
                │ Unix socket: ~/.superset/pty-supervisor.sock
 ┌──────────────▼──────────────────────────────────────────────┐
 │ PTY Supervisor               ← Rarely restarts              │
 │   - Session lifecycle                                       │
 │   - HeadlessEmulator state                                  │
 │   - pty-subprocess management                               │
 │   └── Session                                               │
 │         └── pty-subprocess                                  │
 │               └── node-pty PTY                              │
 └─────────────────────────────────────────────────────────────┘
-```
+```

-```
+```text
 apps/desktop/src/main/pty-supervisor/
 ├── index.ts          # Entry point, socket server
 ├── supervisor.ts     # Session management (from terminal-host.ts)
 ├── session.ts        # Session class (from terminal-host/session.ts)
 └── types.ts          # Supervisor IPC protocol
-```
+```

-```
+```text
 apps/desktop/src/main/terminal-host/
 ├── index.ts              # Simplified - proxy only
 └── supervisor-client.ts  # NEW - connection to supervisor
-```
+```

-```
+```text
 1. App v2 launches, detects daemon v1 running

 2. App sends "shutdown" to daemon v1
    ┌────────┐     ┌──────────┐     ┌────────────┐
    │ App v2 │────▶│ Daemon v1│     │ Supervisor │
    └────────┘     └────┬─────┘     └────────────┘
                        │ shutdown        │
                        ▼                 │ (stays alive)
                       💀                 │

 3. App spawns daemon v2, connects to existing supervisor
    ┌────────┐     ┌──────────┐     ┌────────────┐
    │ App v2 │────▶│ Daemon v2│────▶│ Supervisor │
    └────────┘     └──────────┘     └────────────┘

 4. Daemon v2 sends "hello", gets session list

 5. Daemon v2 attaches to sessions, gets snapshots

 6. App resubscribes - terminals continue seamlessly
    (Running shells never noticed anything)
-```
+```

Also applies to: 28-51, 66-72, 85-89, 154-176

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

14-14: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
In `@apps/desktop/docs/PTY_SUPERVISOR_PLAN.md` around lines 14 - 24, The fenced
code blocks in PTY_SUPERVISOR_PLAN.md are missing language identifiers (tripping
MD040); update each triple-backtick fence that contains the ASCII diagrams and
listings (e.g., the blocks starting with "CURRENT:/NEW:" diagram, the large
Terminal/Daemon/PTY diagram, the apps/desktop/src/main/pty-supervisor/ tree, the
apps/desktop/src/main/terminal-host/ tree, and the numbered upgrade flow block)
by adding "text" (or another appropriate language) immediately after the opening
``` so each fenced block becomes ```text; ensure every fenced block in the
ranges flagged (lines with the diagrams and trees) is updated consistently.

Comment on lines +33 to +49
│ Unix socket: ~/.superset/terminal-host.sock
┌──────────────▼──────────────────────────────────────────────┐
│ Terminal Host Daemon ← Can restart on app update │
│ - Client authentication │
│ - Protocol versioning │
│ - Event routing │
│ └── SupervisorClient │
└──────────────┬──────────────────────────────────────────────┘
│ Unix socket: ~/.superset/pty-supervisor.sock
┌──────────────▼──────────────────────────────────────────────┐
│ PTY Supervisor ← Rarely restarts │
│ - Session lifecycle │
│ - HeadlessEmulator state │
│ - pty-subprocess management │
│ └── Session │
│ └── pty-subprocess │
│ └── node-pty PTY │
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Define explicit IPC access-control requirements between daemon and supervisor.
Right now the plan mentions “client authentication” but doesn’t spell out how the supervisor socket is protected. This is a security risk (any local process could attach to or write into PTYs if permissions are lax). Please add explicit requirements: socket file permissions/owner/umask, credential verification (uid/pid), and/or a shared token or signed handshake.

Also applies to: 117-150

🤖 Prompt for AI Agents
In `@apps/desktop/docs/PTY_SUPERVISOR_PLAN.md` around lines 33 - 49, Add explicit
IPC access-control requirements to the plan: specify socket file ownership and
restrictive permissions/umask for the supervisor socket
(~/.superset/pty-supervisor.sock) and terminal-host socket
(~/.superset/terminal-host.sock), require credential verification (validate peer
UID/PID) on accept, and define an optional shared secret or signed handshake
exchanged by SupervisorClient <-> Terminal Host Daemon before any session
operations; document where checks occur (PTY Supervisor, Session,
HeadlessEmulator, pty-subprocess lifecycle and node-pty PTY creation) and
failure-handling policy (reject/reset connection and log security events).

Comment on lines +33 to +41
│ Unix socket: ~/.superset/terminal-host.sock
┌──────────────▼──────────────────────────────────────────────┐
│ Terminal Host Daemon ← Can restart on app update │
│ - Client authentication │
│ - Protocol versioning │
│ - Event routing │
│ └── SupervisorClient │
└──────────────┬──────────────────────────────────────────────┘
│ Unix socket: ~/.superset/pty-supervisor.sock
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Call out Windows transport explicitly.
The socket paths are Unix‑specific; please add a note about Windows named pipes (and any path convention) so the plan is unambiguous across platforms.

🤖 Prompt for AI Agents
In `@apps/desktop/docs/PTY_SUPERVISOR_PLAN.md` around lines 33 - 41, The document
currently lists Unix socket paths (~/.superset/terminal-host.sock and
~/.superset/pty-supervisor.sock) for the Terminal Host Daemon / SupervisorClient
but doesn’t mention Windows; update the PTY_SUPERVISOR_PLAN to explicitly call
out Windows transport by adding a note that on Windows the daemon and
SupervisorClient will use named pipes (e.g., \\.\pipe\superset\terminal-host and
\\.\pipe\superset\pty-supervisor or a documented app-specific pipe namespace),
include any path/namespace conventions and permission/authentication
considerations, and mention fallback behavior or detection logic so the
implementation (Terminal Host Daemon and SupervisorClient) can choose the
appropriate transport per-OS.

@Kitenite
Copy link
Copy Markdown
Collaborator Author

This is likely too complicated and the supervisor still has too much responsibility that would be updated over time. Best if we just restart the daemon or do rolling.

@Kitenite Kitenite closed this Jan 18, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ⚠️ Neon database branch
  • ⚠️ Electric Fly.io app

Thank you for your contribution! 🎉

@Kitenite Kitenite deleted the daemon-transfer branch January 18, 2026 22:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant