Skip to Content

Architecture

TL;DR

CMDOP’s architecture has three components: Agents (Go binaries on target machines), a Control Plane (Django backend), and Clients (CLI, SDK, mobile, web). All communication uses gRPC over HTTP/2 with TLS encryption. Agents connect outbound only. Sessions are first-class objects stored in the database, isolated by workspace, and persist independently of any client or agent connection.

CMDOP is a distributed system with three primary components: Agents, Control Plane, and Clients. This architecture enables persistent sessions that exist independently of any client connection.

What does the system overview look like?

What are the core components?

What does the Agent do?

The agent is a lightweight process that runs on target machines.

Responsibilities:

  • Execute terminal commands (PTY)
  • Perform file operations
  • Run browser automation
  • Report system telemetry
  • Maintain outbound connection to Control Plane

Key Design Decisions:

DecisionRationale
Outbound-onlyNo exposed ports, works through any firewall
Single binaryEasy deployment, no dependencies
Multi-platformGo compiles to macOS, Linux, Windows, iOS
Session-scopedEach session has isolated execution context

Source: projects/software/cmdop_go/

What does the Control Plane do?

The Control Plane is a Django application that orchestrates all communication.

Responsibilities:

  • Maintain session objects (independent of connections)
  • Route messages between agents and clients
  • Authenticate and authorize requests
  • Publish real-time events via Centrifugo

Key Components:

ComponentPurpose
Session ManagerCreate, maintain, cleanup sessions
Message RouterBidirectional gRPC streaming
Auth ServiceOAuth tokens, workspace isolation
CentrifugoWebSocket events to clients

Source: projects/solution/django/apps/terminal/

What client types connect to the Control Plane?

Multiple client types connect to the Control Plane.

ClientTechnologyUse Case
CLIGoPower users, scripting
Python SDKPython + gRPCAutomation, integrations
Mobile AppSwiftRemote access on the go
Web DashboardReactBrowser-based control

How does data flow through the system?

How does command execution flow?

How is a session created?

How does multi-client attachment work?

What does the session object model look like?

Sessions are first-class objects with their own lifecycle:

# Session is a first-class persistent object — it survives client and agent disconnects class Session: id: UUID # Globally unique identifier for this session status: SessionStatus # Current state: CONNECTED, BACKGROUND, GRACE_PERIOD, DISCONNECTED workspace: Workspace # Workspace this session belongs to (tenant isolation boundary) machine: Machine # The target machine running the agent created_at: datetime last_heartbeat_at: datetime # Tracks agent liveness — updated every 30s grace_period_started_at: datetime # When the 30s reconnection window began

Key Properties:

  1. Independent of Connections

    • Session exists in database
    • Persists across client disconnects
    • Agent disconnect triggers grace period, not immediate termination
  2. Workspace-Scoped

    • All sessions belong to a workspace
    • Multi-tenant isolation
    • Authorization at session level
  3. Lifecycle States

    • PENDING → CONNECTED → GRACE_PERIOD → DISCONNECTED
    • BACKGROUND state for mobile apps

What protocol does CMDOP use?

What transport layer is used?

All communication uses gRPC over HTTP/2:

ConnectionProtocolSecurity
Agent → Control PlanegRPC (outbound)TLS
Client → Control PlanegRPCTLS + OAuth
Control Plane → Client (events)WebSocketTLS + Auth

What message types are exchanged?

// AgentMessage: sent from Agent to Control Plane over the outbound gRPC stream message AgentMessage { string session_id = 1; // Links this message to a specific session oneof payload { RegisterRequest register = 2; // Initial registration with hostname, platform, capabilities TerminalOutput output = 3; // PTY output from command execution HeartbeatUpdate heartbeat = 4; // Periodic liveness + system metrics FileOperationResult file_result = 5; // Result of a file read/write/list operation // ... } } // ControlMessage: sent from Control Plane to Agent as commands to execute message ControlMessage { string command_id = 1; // Unique ID for correlating output back to the requesting client oneof payload { StartSessionCommand start_session = 2; // Initialize session after registration SendInputCommand send_input = 3; // Terminal input from a client (keystrokes/commands) FileOperationRequest file_request = 4; // Read, write, or list files on the agent // ... } }

How does CMDOP scale?

How does horizontal scaling work?

How does session affinity work?

  • gRPC streams are sticky (HTTP/2)
  • Session state can be shared via Redis
  • Agent reconnects to any node
  • Client can attach from any node

How are security boundaries enforced?

  • Workspaces are completely isolated
  • Sessions cannot cross workspace boundaries
  • OAuth tokens scoped to workspace
  • Machine hostnames unique within workspace

Next

Last updated on