Multi-Client
CMDOP sessions support multiple concurrent client connections with two access modes: Operator (full read-write) and Observer (read-only). This enables real-time collaborative debugging between developers, AI-assisted monitoring in observer mode, seamless device switching from laptop to phone, and training/shadowing scenarios. Commands from multiple operators are processed in queue order.
CMDOP sessions support multiple concurrent client connections. This enables collaboration, AI assistance, and seamless device switching.
What is the multi-client model?
All clients see same output. Operators can send input. Observers can only watch.
What access modes are available?
What can an Operator do?
Full read-write access:
| Permission | Allowed |
|---|---|
| View output | Yes |
| Send input | Yes |
| Execute commands | Yes |
| File read | Yes |
| File write | Yes |
| Resize terminal | Yes |
| Send signals | Yes |
What can an Observer do?
Read-only access:
| Permission | Allowed |
|---|---|
| View output | Yes |
| Send input | No |
| Execute commands | No |
| File read | Yes |
| File write | No |
| Resize terminal | No |
| Send signals | No |
What are the multi-client use cases?
1. How does device switching work?
Start on laptop, continue on phone:
# Start a long-running deploy on the laptop via CLI
# On laptop (CLI)
await client.terminal.set_machine("prod-server")
await client.terminal.execute("./deploy.sh")
# Deploy starts...
# Close laptop (detach, but session continues on agent)
# On phone (mobile app)
# Attach to same session from a different device
# See deploy progress
# Can send input if needed2. How does collaborative debugging work?
Two developers on same session:
3. How does AI assistance work in a session?
Human operates, AI watches and helps:
# Human attaches as operator with full control
human_stream = client.terminal.stream()
await human_stream.attach(session_id)
# AI attaches as observer β can read output but cannot send input
ai_stream = client.terminal.stream(mode="observer")
await ai_stream.attach(session_id)
# AI callback: analyze each output chunk and send suggestions
async def on_output(data):
analysis = await ai.analyze(data)
if analysis.has_suggestion:
send_notification(analysis.suggestion)
ai_stream.on_output(on_output)
# Human works normally; AI suggests improvements via notifications4. How does training / shadowing work?
Junior watches senior work:
5. How does audit / compliance observation work?
Security team monitors operations:
How does input arbitration work?
When multiple operators send input:
How is queue-based processing handled?
Commands processed in order received. Each command gets unique ID.
How does output correlation work?
# Send a command and get back a unique ID for tracking
command_id = await stream.send_command("ls -la")
# Wait for output tagged with the matching command ID
output = await stream.wait_for_command(command_id)How does real-time streaming work?
All operators see all output in real-time, regardless of who sent the command.
How do you use multi-client in the SDK?
How do you attach as Operator?
from cmdop import AsyncCMDOPClient
async with AsyncCMDOPClient.remote(api_key="cmd_xxx") as client:
# Look up the active session for a machine by hostname
session = await client.terminal.get_active_session("my-server")
# Open a bidirectional stream (defaults to operator mode)
stream = client.terminal.stream()
# Print decoded output as it arrives in real-time
stream.on_output(lambda data: print(data.decode(), end=""))
# Attach to the session and send a command
await stream.attach(session.session_id)
await stream.send_input(b"ls -la\n")How do you attach as Observer?
# Attach in observer mode β read-only, cannot send input
stream = client.terminal.stream(mode="observer")
stream.on_output(lambda data: print(data.decode(), end=""))
await stream.attach(session.session_id)
# Sending input in observer mode will raise an errorHow do you check attached clients?
# Retrieve session metadata including the list of all attached clients
session = await client.terminal.get_session(session_id)
print(f"Attached clients: {session.attached_clients}")
# [
# {"user": "[email protected]", "mode": "operator", "client": "cli"},
# {"user": "[email protected]", "mode": "observer", "client": "web"},
# ]How does authorization work for multi-client?
How does workspace-based access work?
All workspace members can attach to sessions:
# Alice and Bob are both in "acme-corp" workspace
# Both can attach to any session in that workspace
# Alice finds the active session for "server"
session = await alice_client.terminal.get_active_session("server")
# Bob can also attach β same workspace grants access
await bob_client.terminal.attach(session.session_id)How is role enforcement applied?
# Workspace roles determine the maximum access level for sessions
# Owner/Admin: Can attach to any session as operator
# Member: Can attach to any session as operator
# Guest: Can only attach as observer (if configured)What are the best practices for multi-client?
1. Use Observer Mode When Appropriate
# If you only need to watch, use observer mode to prevent accidental input
stream = client.terminal.stream(mode="observer")2. Coordinate with Team
# Check if another operator is already attached before taking over
session = await client.terminal.get_session(session_id)
if session.has_active_operator:
# Notify the team before attaching as a second operator
notify_team(f"Taking over session on {session.machine}")3. Use AI for Non-Critical Observation
# AI observer for automated monitoring and alerting
ai_stream = client.terminal.stream(mode="observer")
ai_stream.on_output(detect_errors_and_alert)4. Document Collaborative Sessions
# Enable session recording for audit and review
session = await client.terminal.get_active_session(
"server",
record=True # Enable recording
)What are the limitations of multi-client?
Concurrent Operators
Multiple operators can send input, but:
- Commands are queued, not merged
- No conflict resolution
- Last command wins for stateful operations
Observer Restrictions
Observers cannot:
- Send any input
- Execute commands
- Modify files
- Send signals
- Change session state
Network Considerations
Each client uses bandwidth:
- Output broadcast to all clients
- More clients = more bandwidth on Control Plane
- Consider observer-only for large audiences
Next
- AI Operators β AI as session participant
- Sessions β Session lifecycle
- Security β Access control