Python SDK for CMDOP agent interaction
Project description
cmdop
Any machine. One API.
from cmdop import CMDOPClient
with CMDOPClient.remote(api_key="cmd_xxx") as server:
server.terminal.execute("docker restart app")
server.files.write("/etc/nginx/nginx.conf", new_config)
logs = server.files.read("/var/log/app.log")
No SSH. No VPN. No open ports.
How
Your Code ──── Cloud Relay ──── Agent (on server)
│
Outbound only, works through any NAT/firewall
Agent connects out. Your code connects to relay. Done.
Install
pip install cmdop
from cmdop import CMDOPClient, AsyncCMDOPClient
# Remote (via cloud relay)
with CMDOPClient.remote(api_key="cmd_xxx") as client:
client.files.list("/home")
# Local (direct IPC)
with CMDOPClient.local() as client:
client.terminal.execute("ls -la")
# Async
async with AsyncCMDOPClient.remote(api_key="cmd_xxx") as client:
await client.files.read("/etc/hostname")
Terminal
session = server.terminal.create()
server.terminal.send_input(session.session_id, "kubectl get pods\n")
output = server.terminal.get_history(session.session_id)
| Method | Description |
|---|---|
create(shell) |
Start session |
send_input(id, data) |
Send commands |
get_history(id) |
Get output |
resize(id, cols, rows) |
Resize |
send_signal(id, signal) |
SIGINT/SIGTERM |
close(id) |
End session |
Files
server.files.list("/var/log")
server.files.read("/etc/nginx/nginx.conf")
server.files.write("/tmp/config.json", b'{"key": "value"}')
| Method | Description |
|---|---|
list(path) |
List dir |
read(path) |
Read file |
write(path, content) |
Write file |
delete(path) |
Delete |
copy/move(src, dst) |
Copy/Move |
mkdir(path) |
Create dir |
info(path) |
Metadata |
Agent
from pydantic import BaseModel
class Health(BaseModel):
status: str
cpu: float
issues: list[str]
result = server.agent.run("Check server health", output_schema=Health)
health: Health = result.output # Typed!
Browser
with client.browser.create_session() as b:
b.navigate("https://shop.com/products")
b.close_modal() # Close popups
# BeautifulSoup parsing
soup = b.soup() # SoupWrapper with chainable API
for item in soup.select(".product"):
title = item.select_one("h2").text()
price = item.attr("data-price")
# Scrolling with random delays
for _ in range(10):
soup = b.soup(".listings")
# ... parse ...
b.scroll("down", 700)
b.wait_random(0.8, 1.5) # Random delay
# Click with cursor movement (human-like)
b.click("button.buy", move_cursor=True) # Moves cursor before clicking
# Click all "See more" buttons
b.click_all_by_text("See more")
# Native mouse operations
b.mouse_move(500, 300) # Smooth cursor movement
b.hover(".tooltip-trigger") # Hover to reveal tooltip
# JS fetch (bypass CORS, inherit cookies)
data = b.fetch_json("https://api.site.com/v1/items")
| Method | Description |
|---|---|
navigate(url) |
Go to URL |
click(selector, move_cursor) |
Click element (optionally move cursor first) |
click_all_by_text(text, role) |
Click all matching elements |
type(selector, text) |
Type text |
wait_for(selector, ms) |
Wait for element |
wait_seconds(n) |
Sleep |
wait_random(min, max) |
Random sleep |
extract(selector, attr) |
Get text/attr |
get_html(selector) |
Get HTML |
soup(selector) |
→ SoupWrapper |
parse_html(html) |
→ BeautifulSoup |
fetch_json(url) |
JS fetch → dict |
fetch_all(urls) |
Parallel fetch |
execute_js(code) |
Run async JS |
screenshot() |
PNG bytes |
scroll(dir, amount, ...) |
Native scroll page |
scroll_to(selector) |
Scroll element into view |
get_scroll_info() |
Position + page size |
get_page_info() |
Comprehensive page info |
mouse_move(x, y, steps) |
Move cursor to coordinates |
hover(selector) |
Hover over element |
select(selector, value) |
Dropdown select |
close_modal() |
Close dialogs |
press_key(key, selector) |
Press keyboard key |
get/set_cookies() |
Cookie management |
scroll() parameters:
direction: "up", "down", "left", "right"amount: pixels to scrollsmooth: animate scroll (default True)selector: scroll element into view (alternative to direction/amount)
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
Utilities
Logging:
from cmdop import get_logger
log = get_logger(__name__)
log.info("Starting") # Rich console + auto file logging
TOON Format (30-50% token savings):
from cmdop import json_to_toon, JsonCleaner
toon = json_to_toon({"name": "Alice", "age": 25})
# → "name: Alice\nage: 25"
Requirements
- Python 3.10+
- CMDOP agent on target
Links
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
cmdop-0.1.20.tar.gz
(163.4 kB
view details)
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
cmdop-0.1.20-py3-none-any.whl
(271.8 kB
view details)
File details
Details for the file cmdop-0.1.20.tar.gz.
File metadata
- Download URL: cmdop-0.1.20.tar.gz
- Upload date:
- Size: 163.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d3b74e80e05efea74d57ad52b630a0b580af5ea330e39a011c3680a2537fef22
|
|
| MD5 |
cbbb4f146c1bd80f96d620ac3bbb1a0f
|
|
| BLAKE2b-256 |
d692778abd5f40ae40467455f76405070ff620f884ecbf930eec5c07915c2ad3
|
File details
Details for the file cmdop-0.1.20-py3-none-any.whl.
File metadata
- Download URL: cmdop-0.1.20-py3-none-any.whl
- Upload date:
- Size: 271.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4519a302ab3b941f49235d7a917e9472f88e03572fc31bf3b8cd4fa655a30243
|
|
| MD5 |
ad03917f790f606e71e4167cfd95eda9
|
|
| BLAKE2b-256 |
385eb606520d23b8e49183747d3b745a0a6ef9cbc4adcd8ae784b1975b87340c
|