Skip to main content

Python SDK for CMDOP agent interaction

Project description

CMDOP

CMDOP

Your OS. Online.

Full access to your machines from anywhere. Not files — the whole system.

Your Code ──── Cloud Relay ──── Agent (on server)
                   │
       Outbound only, works through any NAT/firewall

Why CMDOP?

Problem CMDOP Solution
VPN requires client install SDK works without VPN
SSH needs port forwarding Agent uses outbound connection
Screen sharing is laggy gRPC streaming, real-time
File sync is just files Full OS access: terminal + files
AI returns text Structured output with Pydantic
No reusable workflows Skills: predefined AI tasks with tools

Install

pip install cmdop

Quick Start

from cmdop import AsyncCMDOPClient

async with AsyncCMDOPClient.remote(api_key="cmdop_xxx") as client:
    # Terminal
    await client.terminal.set_machine("my-server")
    output, code = await client.terminal.execute("uname -a")

    # Files
    content = await client.files.read("/etc/hostname")
    await client.files.write("/tmp/config.json", b'{"key": "value"}')

    # AI Agent with typed output
    from pydantic import BaseModel

    class Health(BaseModel):
        cpu: float
        memory: float
        issues: list[str]

    await client.agent.set_machine("my-server")
    result = await client.agent.run("Check server health", output_model=Health)
    health: Health = result.data  # Typed!

    # Skills — run predefined AI workflows
    await client.skills.set_machine("my-server")
    skills = await client.skills.list()
    result = await client.skills.run("code-review", "Review the auth module")

Connection

from cmdop import CMDOPClient, AsyncCMDOPClient

# Remote (via cloud relay) - works through any NAT
client = CMDOPClient.remote(api_key="cmdop_xxx")

# Local (direct IPC to running agent)
client = CMDOPClient.local()

# Async
async with AsyncCMDOPClient.remote(api_key="cmdop_xxx") as client:
    ...

Terminal

Execute commands, stream output, SSH into machines.

async with AsyncCMDOPClient.remote(api_key="cmdop_xxx") as client:
    # Set target machine once
    await client.terminal.set_machine("my-server")

    # Execute and get output
    output, code = await client.terminal.execute("ls -la")
    print(output.decode())

    # Interactive operations
    await client.terminal.send_input("echo hello\n")
    await client.terminal.resize(120, 40)
    await client.terminal.send_signal(SignalType.SIGINT)

SSH-like interactive session:

# CLI
cmdop ssh my-server

# Python
from cmdop.services.terminal.tui.ssh import ssh_connect
asyncio.run(ssh_connect('my-server', 'cmd_xxx'))

Real-time streaming:

stream = client.terminal.stream()
stream.on_output(lambda data: print(data.decode(), end=""))
await stream.attach(session.session_id)
await stream.send_input(b"tail -f /var/log/app.log\n")

Session discovery:

# List all machines
response = await client.terminal.list_sessions()
for s in response.sessions:
    print(f"{s.machine_hostname}: {s.status}")

# Get specific machine
session = await client.terminal.get_active_session("prod-server")

MFA (Multi-Factor Authentication)

When a workspace has mfa_required enabled, attach() automatically handles the TOTP challenge — no extra code needed.

Automatic (env var) — best for CI/automation:

CMDOP_TOTP_CODE=123456 python script.py

Interactive — SDK prompts stdin if env var is not set:

MFA required. Enter TOTP code:
# Workspace with MFA enabled — SDK handles it automatically
stream = client.terminal.stream()
stream.on_output(lambda data: print(data.decode(), end=""))

# Option 1: set env var for automation
import os
os.environ["CMDOP_TOTP_CODE"] = "123456"  # or set in shell

# Option 2: SDK will prompt interactively if env not set
await stream.attach(session.session_id)

Files

Read, write, list files on remote machines. No scp/sftp needed.

# Set target machine once
await client.files.set_machine("my-server")

# File operations
files = await client.files.list("/var/log", include_hidden=True)
content = await client.files.read("/etc/nginx/nginx.conf")
await client.files.write("/tmp/config.json", b'{"key": "value"}')

# More operations
await client.files.copy("/src", "/dst")
await client.files.move("/old", "/new")
await client.files.mkdir("/new/dir")
await client.files.delete("/tmp/old", recursive=True)
info = await client.files.info("/path/file.txt")

AI Agent

Run AI tasks with structured, typed output.

from pydantic import BaseModel, Field

class ServerHealth(BaseModel):
    hostname: str
    cpu_percent: float = Field(description="CPU usage percentage")
    memory_percent: float
    disk_free_gb: float
    issues: list[str] = Field(description="List of detected issues")

await client.agent.set_machine("my-server")
result = await client.agent.run(
    prompt="Check server health and report any issues",
    output_model=ServerHealth,
)

# Typed response - not just text!
health: ServerHealth = result.data
if health.cpu_percent > 90:
    alert(f"{health.hostname} CPU critical!")

Skills

Run predefined AI workflows on remote machines. Skills are reusable prompt templates with tool access.

await client.skills.set_machine("my-server")

# List available skills
skills = await client.skills.list()
for skill in skills:
    print(f"{skill.name}: {skill.description} ({skill.origin})")

# Inspect a skill
detail = await client.skills.show("code-review")
if detail.found:
    print(detail.content)   # System prompt markdown
    print(detail.source)    # File path on machine

# Run a skill
result = await client.skills.run("code-review", "Review the auth module")
print(result.text)
print(f"Took {result.duration_seconds}s, {result.usage.total_tokens} tokens")

Structured output:

from pydantic import BaseModel

class Review(BaseModel):
    score: int
    summary: str
    issues: list[str]

result = await client.skills.run(
    "code-review",
    "Review the auth module",
    output_model=Review,
)
review: Review = result.data
print(f"Score: {review.score}/10")

Custom options:

from cmdop import SkillRunOptions

result = await client.skills.run(
    "summarize",
    "Summarize the project README",
    options=SkillRunOptions(model="openai/gpt-4o", timeout_seconds=120),
)

Download

Download files from URLs via remote server.

from pathlib import Path

async with AsyncCMDOPClient.remote(api_key="cmdop_xxx") as client:
    # Set target machine
    await client.download.set_machine("my-server")
    client.download.configure(api_key="cmdop_xxx")

    result = await client.download.url(
        url="https://example.com/large-file.zip",
        local_path=Path("./large-file.zip"),
    )

    if result.success:
        print(result)  # DownloadResult(ok, 139.2MB, 245.3s, 0.6MB/s)

Handles cloud relay limits automatically:

  • Small files (≤10MB): Direct chunked transfer
  • Large files (>10MB): Split on remote, download parts

SDKBaseModel

Auto-cleaning Pydantic model for scraped data.

from cmdop import SDKBaseModel

class Product(SDKBaseModel):
    __base_url__ = "https://shop.com"
    name: str = ""    # "  iPhone 15  \n" → "iPhone 15"
    price: int = 0    # "$1,299.00" → 1299
    rating: float = 0 # "4.5 stars" → 4.5
    url: str = ""     # "/p/123" → "https://shop.com/p/123"

products = Product.from_list(raw["items"])  # Auto dedupe + filter

Architecture

┌─────────────┐    gRPC/HTTP2    ┌─────────────┐    gRPC    ┌─────────┐
│   Python    │◀────────────────▶│   Cloud     │◀──────────▶│  Agent  │
│     SDK     │   Bidirectional  │   Relay     │  Outbound  │  (Go)   │
└─────────────┘                  └─────────────┘            └─────────┘

Key points:

  • Agent makes outbound connection (no port forwarding)
  • SDK connects via gRPC (works through any firewall)
  • All services multiplexed over single connection

Comparison

Feature CMDOP Tailscale ngrok SSH
Terminal streaming gRPC VPN + SSH No Yes
File operations Built-in SFTP No SCP
AI agent Built-in No No No
Reusable AI skills Built-in No No No
NAT traversal Outbound WireGuard Outbound Port forward
Client install None VPN client None SSH client
Structured output Pydantic No No No

Requirements

  • Python 3.10+
  • CMDOP agent running locally or API key for remote access

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cmdop-2026.3.13.tar.gz (207.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cmdop-2026.3.13-py3-none-any.whl (345.8 kB view details)

Uploaded Python 3

File details

Details for the file cmdop-2026.3.13.tar.gz.

File metadata

  • Download URL: cmdop-2026.3.13.tar.gz
  • Upload date:
  • Size: 207.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.18

File hashes

Hashes for cmdop-2026.3.13.tar.gz
Algorithm Hash digest
SHA256 6e7ce1d33ecb0f95d13c32b82feca39d5905d5ed8644a9a7bc276bba62631267
MD5 86a3073b6b8f65b76eaf60819f11d09d
BLAKE2b-256 5db6029b7c37fdcdaf69e65784a839ad202a60c80244f9faf292ddf3aa2554b9

See more details on using hashes here.

File details

Details for the file cmdop-2026.3.13-py3-none-any.whl.

File metadata

  • Download URL: cmdop-2026.3.13-py3-none-any.whl
  • Upload date:
  • Size: 345.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.18

File hashes

Hashes for cmdop-2026.3.13-py3-none-any.whl
Algorithm Hash digest
SHA256 475a64dc04ec54e3ed684e0da92d5b0404b3e91cebcef14f182a302ece00835b
MD5 fea2c31e6a2cecb7478aed90446ff2aa
BLAKE2b-256 b183e61e3d893c649ee0c6f1a60259ee761ccb22c7f5bacf76d264d0f96fa92e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page