Architecture
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:
| Decision | Rationale |
|---|---|
| Outbound-only | No exposed ports, works through any firewall |
| Single binary | Easy deployment, no dependencies |
| Multi-platform | Go compiles to macOS, Linux, Windows, iOS |
| Session-scoped | Each 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:
| Component | Purpose |
|---|---|
| Session Manager | Create, maintain, cleanup sessions |
| Message Router | Bidirectional gRPC streaming |
| Auth Service | OAuth tokens, workspace isolation |
| Centrifugo | WebSocket 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.
| Client | Technology | Use Case |
|---|---|---|
| CLI | Go | Power users, scripting |
| Python SDK | Python + gRPC | Automation, integrations |
| Mobile App | Swift | Remote access on the go |
| Web Dashboard | React | Browser-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 beganKey Properties:
-
Independent of Connections
- Session exists in database
- Persists across client disconnects
- Agent disconnect triggers grace period, not immediate termination
-
Workspace-Scoped
- All sessions belong to a workspace
- Multi-tenant isolation
- Authorization at session level
-
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:
| Connection | Protocol | Security |
|---|---|---|
| Agent β Control Plane | gRPC (outbound) | TLS |
| Client β Control Plane | gRPC | TLS + OAuth |
| Control Plane β Client (events) | WebSocket | TLS + 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
- How It Works β Detailed connection flow
- Security β Authentication and encryption
- Sessions Concept β Session lifecycle deep dive