Skip to content
Portal Control Protocol

Participants

PCP defines four roles in a service-oriented topology. Each role has a defined boundary and a defined relationship to the others. Unlike monolithic in-process architectures where everything shares one address space, PCP separates concerns by process and by socket.

The daemon is the capability authority. The compositor is the surface authority. Clients connect to the daemon to invoke capabilities and receive events. Tier 1 applications serve capability handlers on their own sockets, and the daemon connects to them as a client. These four roles, and the socket connections between them, constitute the full PCP topology.

graph TD
    subgraph "PCP Daemon"
        direction TB
        Reg["Capability Registry"]
        Bus["Event Bus"]
        Aud["Audit Log"]
        Det["Detection Pipeline"]
    end

    Comp["Compositor"]
    SI["System Intelligence"]
    CLI["CLI Tools"]
    T1A["Tier 1 App A"]
    T1B["Tier 1 App B"]

    Comp -->|"Wayland protocol + domain capabilities"| Reg
    SI -->|"daemon socket (JSON frames)"| Reg
    CLI -->|"daemon socket (JSON frames)"| Reg
    Reg -->|"event subscriptions"| SI
    Reg -->|"AppClient connects"| T1A
    Reg -->|"AppClient connects"| T1B
    T1A -->|"PcpServer responses"| Reg
    T1B -->|"PcpServer responses"| Reg

The daemon sits at the center. Every other role connects to it, or it connects to them. There is no peer-to-peer communication between clients, no direct path from SI to the compositor, no back channel from Tier 1 apps to anything except the daemon. All traffic flows through the central authority.

The daemon is the capability authority. It holds the single registry of every application, capability, surface, and adapter on the system. It runs the event bus that delivers state changes to subscribers. It writes every capability invocation to the audit chain. It manages the detection pipeline that discovers and classifies running applications.

The daemon is a standalone process. It binds a Unix-domain socket, accepts connections from clients, and speaks the PCP framing protocol defined in the wire protocol specification. It also connects outbound to Tier 1 application sockets when it needs to invoke capabilities that those apps serve.

Internally, the daemon maintains four core subsystems:

Subsystem Responsibility
Capability Registry Authoritative record of every registered application, its capabilities, parameters, state, and health. Single source of truth.
Event Bus Push-based pub/sub for state changes, lifecycle events, and capability results. Clients subscribe to event streams and receive updates as they happen.
Audit Log Append-only chain recording every capability invocation with timestamp, caller identity, parameters, result, and state source.
Detection Pipeline Periodic scan of running applications. Classifies each into a tier based on integration depth. Publishes capability diffs and lifecycle events to the bus.

The daemon also hosts runtime services: learning, recovery, inspection, and coordination. These are registered as in-process servers, invoked without IPC, demonstrating the embedding path the protocol defines. The daemon owns them, so no socket crossing is needed.

The compositor is the surface authority. It manages every window, surface, input event, output configuration, workspace layout, clipboard transfer, and focus target on the system. Nothing on the desktop exists outside the compositor’s knowledge.

The compositor loads no PCP code. It runs its own process, its own event loop, and its own rendering pipeline. Surface state enters PCP through domain capabilities that the compositor exposes, not through scraping, polling, or pixel inspection.

Domain What the compositor tracks
Wayland clients Connected applications, their protocols and lifecycles
Surfaces Geometry, bounds, z-order stacking, visibility, and state flags
Input events Keyboard, pointer, touch, and gesture streams
Outputs Display configuration, resolution, scale factor, and layout
Workspaces Virtual desktop arrangement and switch state
Focus Current keyboard and pointer focus targets
Clipboard Selection ownership and transfer state

PCP enriches this compositor state with data from the accessibility layer. AT-SPI2 trees provide element roles, states, actions, text content, value ranges, selection boundaries, and caret positions. The result is a desktop model that combines the compositor’s structural authority with the accessibility layer’s semantic depth.

Because the compositor runs no PCP code, a PCP crash cannot affect the desktop. The compositor is never in PCP’s blast radius. This isolation is a deliberate architectural choice: the surface authority and the capability authority live in separate processes, communicating through defined interfaces.

Clients are any processes that connect to the daemon socket. They speak the PCP framing protocol, send capability invocations, receive events, and read state. All clients are equal before the daemon. There is no privileged connection, no back door, no out-of-band capability channel.

System Intelligence is a client. So is pcp-cli, a command-line tool for invoking capabilities from scripts or terminals. So are custom integrations, test harnesses, and diagnostic utilities. Each connects to the daemon socket, authenticates via peer-credential checks, and receives the same treatment.

Clients connect over a Unix-domain socket. The daemon validates the connecting process’s UID against an allowed user before accepting the connection. Once authenticated, the client sends framed messages and receives framed responses. The wire protocol specification covers the frame layout, encoding, and message types in full detail.

System Intelligence has a particular role among clients: it is the system identity. SI forms intent, reasons about desktop state, and invokes capabilities to act on the user’s behalf. But architecturally, it is a client. It connects the same way, authenticates the same way, and speaks the same protocol. SI draws on whatever cognitive resource serves its intelligence: a local model, a remote inference endpoint, or a hybrid pipeline. The protocol does not dictate the inference backend.

Tier 1 applications are the richest integration point in PCP. These applications serve the PcpServer contract on their own Unix-domain sockets. The daemon connects to them as a client, the same way external clients connect to the daemon.

This bidirectional socket relationship is worth understanding. The daemon is a server that accepts connections from clients. Tier 1 apps are also servers that accept connections, but their only client is the daemon. The daemon’s AppClientManager maintains a pool of connections to running Tier 1 apps, keyed by application ID, and routes capability invocations to them.

Tier 1 applications bypass accessibility-tree bridging entirely. Instead of having their UI semantics inferred from AT-SPI2 or simulated through input injection, they register structured capability handlers that the daemon can invoke directly. A presentation app might expose slides.goto_slide, slides.get_current_content, and slides.insert_text. A writing app might expose document.read_selection, document.replace_range, and document.format_block.

The message flow for a Tier 1 invocation follows a specific pattern:

  1. A client (often SI) sends an InvokeCapability message to the daemon.
  2. The daemon looks up the target app in its registry and identifies it as a Tier 1 server.
  3. The daemon’s AppClient connects to the app’s socket and forwards the invocation.
  4. The app processes the request through its PcpServer implementation and returns a result.
  5. The daemon relays the result back to the original client, annotated with audit metadata.

This indirection is not overhead. It preserves the daemon’s role as the single audit point, the single event source, and the single authority over capability routing. Tier 1 apps never see direct client connections. They see the daemon, and only the daemon.

The daemon uses adapters to extract semantic data from different classes of application surfaces. These adapters run inside the daemon process, not in the compositor, and feed their results into the capability registry.

graph LR
    subgraph "Daemon Adapters"
        direction TB
        NAT["Native Detection"]
        ATSPI["AT-SPI2 Adapter"]
        WINE["Compatibility Bridge"]
        PLAT["Platform Adapter"]
    end

    T1["Tier 1 Native"]
    GTK["GTK / Qt / Electron"]
    LEG["Legacy Applications"]
    HW["Platform Resources"]

    NAT --> T1
    ATSPI --> GTK
    WINE --> LEG
    PLAT --> HW
Adapter Integration depth What it provides
Native Detection Tier 1 Direct PcpServer invocations on signed, manifest-bearing apps
AT-SPI2 Tier 2 Widget trees, element roles, text content, action sets from standard Linux apps
Compatibility Bridge Tier 3 Fallback translation for legacy apps that lack modern accessibility support
Platform Adapter System Clipboard, notifications, display geometry, and other OS-level resources

These adapters form a progressive-fidelity stack. Deeper integration yields richer semantic access, but basic control is always available. The detection pipeline classifies each running application into a tier and registers the appropriate capability set.

Last updated: