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 |
with_timeout(fn, sec, cleanup) |
Run with timeout, skip if hangs |
with_timeout() - Smart timeout for long operations:
# Sync
result, ok = browser.with_timeout(
lambda: process_item(browser, item),
timeout_sec=60,
on_timeout=lambda: browser.press_key('Escape'),
)
if not ok:
print("Skipped - timed out")
# Async
result, ok = await browser.with_timeout(
process_item(browser, item), # coroutine
timeout_sec=60,
on_timeout=lambda: browser.press_key('Escape'),
)
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
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
File details
Details for the file cmdop-0.1.21.tar.gz.
File metadata
- Download URL: cmdop-0.1.21.tar.gz
- Upload date:
- Size: 164.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5e0b016c80924bcab40e4457a29d1a2f768968ed67fa9d0976201e954d29434a
|
|
| MD5 |
7a2db8247e2c224312faf598ab65c2d3
|
|
| BLAKE2b-256 |
13370b52322bfba5b1ed89ec95c1301e49aa764c456b1d355506e0f3f846bca0
|
File details
Details for the file cmdop-0.1.21-py3-none-any.whl.
File metadata
- Download URL: cmdop-0.1.21-py3-none-any.whl
- Upload date:
- Size: 273.1 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 |
8ba8eacc5765a1852e670e249f85b861dbfd44567e71f96a5c17052d52d58481
|
|
| MD5 |
472298ea8ad468dace2aaff98438ce37
|
|
| BLAKE2b-256 |
ccbfc0931fb4276e135dcc977e4d61e8570c68b94577bc5d177ac3c75fce6bb6
|