Skip to content

App Server: peer-client co-presence with the live TUI thread (RFC) #21551

@parkertoddbrooks

Description

@parkertoddbrooks

Summary

We are building a remote rich client for a local Codex TUI session. The goal is not to run a second Codex agent and not to scrape terminal pixels. The goal is for a second local client to attach to the same live Codex thread as the TUI, hydrate history, receive streamed thread events, start or steer turns when appropriate, and surface approvals or Stop state through the same App Server protocol.

The public App Server docs describe codex app-server as the interface for rich clients that need conversation history, approvals, and streamed agent events. That sounds like the right layer, but we want to confirm the intended architecture before preparing a formal PR.

Docs reference:
https://developers.openai.com/codex/app-server

We are not asking about exposing the experimental App Server WebSocket transport to the public internet. The question here is the local App Server peer-client semantics for a live TUI thread.

Related public issues:

Architecture

flowchart TD
    subgraph Local["User machine: local Codex runtime"]
        TUI["Codex TUI\nCodex-owned\nLocal interactive client"]
        AppServer["Codex App Server\nCodex-owned\nProposed peer-client surface"]
        Peer["External peer client\nIntegration-owned\nLocal App Server client"]

        TUI <--> AppServer
        AppServer <--> Peer
    end

    subgraph Transport["Optional external transport"]
        Relay["Encrypted frame transport\nNot runtime authority"]
    end

    subgraph Remote["Remote UI"]
        UI["Browser or mobile client\nThread mirror, not terminal pixels"]
    end

    Peer <--> Relay
    Relay <--> UI
Loading

In our proof, Codex still runs locally. The external client is a peer client of App Server, not a second Codex runner. Any hosted transport outside the machine only carries encrypted client frames and is not authoritative over Codex runtime state.

What we observed

With stock App Server, a separate client can initialize, resume a stored thread, hydrate persisted history, and start a turn.

With stock App Server, full co-presence was not observed in our tested build: an additional observer did not reliably receive a normal TUI-originated turn stream, and an App Server-started turn was not live-rendered back through the active TUI/browser path as one shared event bus.

With a narrow local Codex patch that adds multi-subscriber live thread event fanout, we observed full co-presence across three surfaces: TUI, desktop web, and phone web. The demo video shows three originating turns, one from each surface, each appearing live on the other two. Three originations, two observers each, no handoff, no terminal mirror.

That suggests the missing primitive may be multi-subscriber live thread events, not a product-specific remote-control feature.

Demo artifacts:

Demo video (MP4): TUI, desktop web, and phone web on the same thread, three originating turns

Static still from the WIP Remote Control Coherence demo

Static still note: captured at the end of the recording after one client had disconnected; the live three-way flow is in the video.

Codex-only patch shape

We have a narrow local branch based on upstream main that only changes Codex-side event fanout:

  • add an event fanout in CodexThread;
  • let legacy callers keep using next_event();
  • let App Server listener tasks subscribe independently;
  • add a websocket App Server test where two clients resume the same thread, one starts a turn, and both receive matching turn notifications.

Touched files:

codex-rs/core/src/codex_thread.rs
codex-rs/app-server/src/request_processors/thread_lifecycle.rs
codex-rs/app-server/tests/suite/v2/connection_handling_websocket.rs

This branch does not include any hosted relay code, browser UI, mobile UI, install flow, or product-specific protocol.

Patch branch: https://github.com/wipcomputer/codex/tree/cc-mini/app-server-multi-listener-rfc
Compare: main...wipcomputer:codex:cc-mini/app-server-multi-listener-rfc

Question

Is App Server intended to support this kind of live peer-client co-presence with the Codex TUI?

If yes, is multi-subscriber live thread event fanout the right direction for an upstream PR, or is there a different App Server surface OpenAI wants external rich clients to use for attaching to the active TUI thread?

Happy to iterate on patch shape, prepare a formal upstream PR under Apache-2.0, or redirect to a different App Server surface if maintainers indicate the intended direction.

Metadata

Metadata

Assignees

No one assigned

    Labels

    app-serverIssues involving app server protocol or interfacesenhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions