CMDOP Bot - Multi-channel bot integrations for remote machine access
Project description
CMDOP Bots
Multi-channel bot integrations for remote machine access.
Control your servers via Telegram, Discord, or Slack. Simple, reliable, open-source.
📖 Documentation: cmdop.com/docs/sdk/python-bot
📖 Read the article: PicoClaw and OpenClaw Are Not Infrastructure: The $10 AI Agent Myth
Getting Started
- Download agent from cmdop.com/downloads
- Install and authorize the agent on your machine
- Get API key from my.cmdop.com/dashboard/settings
- Install the bot (see below)
Install
pip install cmdop-bot
# With Telegram support
pip install "cmdop-bot[telegram]"
# With Discord support
pip install "cmdop-bot[discord]"
# With Slack support
pip install "cmdop-bot[slack]"
# With all channels
pip install "cmdop-bot[all]"
Quick Start
Telegram Bot
from cmdop_bot import Model
from cmdop_bot.channels.telegram import TelegramBot
bot = TelegramBot(
token="YOUR_TELEGRAM_BOT_TOKEN",
cmdop_api_key="cmdop_xxx", # https://my.cmdop.com/dashboard/settings/
allowed_users=[123456789], # Your Telegram user ID
machine="my-server", # Optional: target machine
model=Model.balanced(), # Optional: AI model tier
)
bot.run()
Discord Bot
from cmdop_bot.channels.discord import DiscordBot
bot = DiscordBot(
token="YOUR_DISCORD_BOT_TOKEN",
cmdop_api_key="cmdop_xxx", # https://my.cmdop.com/dashboard/settings/
guild_ids=[123456789], # Optional: for faster command sync
)
bot.run()
Slack App
from cmdop_bot.channels.slack import SlackApp
app = SlackApp(
bot_token="xoxb-YOUR-BOT-TOKEN",
app_token="xapp-YOUR-APP-TOKEN",
cmdop_api_key="cmdop_xxx", # https://my.cmdop.com/dashboard/settings/
)
app.run()
Commands
| Channel | Command | Description |
|---|---|---|
| Telegram | /shell <cmd> |
Execute shell command |
| Telegram | /exec <cmd> |
Alias for /shell |
| Telegram | /agent <task> |
Run AI agent task |
| Telegram | /ls [path] |
List directory |
| Telegram | /cat <path> |
Read file |
| Telegram | /skills list|show|run |
Skills management |
| Telegram | /skill <name> <prompt> |
Run a skill (shorthand) |
| Telegram | /machine <host> |
Set target machine |
| Discord | /shell <cmd> |
Execute shell command |
| Discord | /agent <task> |
Run AI agent task |
| Discord | /ls [path] |
List directory |
| Discord | /cat <path> |
Read file |
| Discord | /skills <action> [name] [prompt] |
List, show, or run skills |
| Discord | /skill <name> <prompt> |
Run a skill (shorthand) |
| Discord | /machine <host> |
Set target machine |
| Discord | /status |
Show connection status |
| Slack | /cmdop shell <cmd> |
Execute shell command |
| Slack | /cmdop agent <task> |
Run AI agent task |
| Slack | /cmdop ls [path] |
List directory |
| Slack | /cmdop cat <path> |
Read file |
| Slack | /cmdop skills list|show|run |
Skills management |
| Slack | /cmdop skill <name> <prompt> |
Run a skill (shorthand) |
| Slack | /cmdop machine <host> |
Set target machine |
| Slack | /cmdop status |
Show connection status |
Features
Telegram
- Chat mode: Just type messages - no
/agentneeded - MarkdownV2 formatting
- Code block syntax highlighting
- Typing indicators
- User allowlist
Discord
- Slash commands
- Rich embeds
- Ephemeral messages for sensitive data
- Deferred responses for slow operations
- Guild-specific command sync
Slack
- Socket Mode (no public webhooks needed)
- Block Kit messages
- Interactive buttons
- Slash command handling
CMDOPHandler
Use CMDOPHandler directly in your own bot:
from cmdop_bot import CMDOPHandler, Model
# Create handler with all CMDOP logic
async with CMDOPHandler(
api_key="cmdop_xxx",
machine="my-server",
model=Model.balanced(),
) as cmdop:
# Run AI agent
result = await cmdop.run_agent("List files in /tmp")
print(result.text)
# Execute shell command
output, exit_code = await cmdop.execute_shell("ls -la")
print(output.decode())
# List files
files = await cmdop.list_files("/var/log")
for f in files.entries:
print(f.name)
# Read file
content = await cmdop.read_file("/etc/hostname")
print(content.decode())
# List available skills
skills = await cmdop.list_skills()
for s in skills:
print(f"{s.name}: {s.description}")
# Run a skill
result = await cmdop.run_skill("code-review", "Review this PR")
print(result.text)
# Switch machine
await cmdop.set_machine("other-server")
Permissions
Control who can use your bot:
from cmdop_bot import PermissionManager, PermissionLevel
pm = PermissionManager()
# Add admin (full access)
pm.add_admin("telegram:123456789")
# Grant execute permission
pm.grant("discord:987654321", machine="prod-server", level=PermissionLevel.EXECUTE)
# Use with bot
bot = TelegramBot(
token="...",
cmdop_api_key="...",
permissions=pm,
)
Model Selection
Choose AI model tier for /agent command:
from cmdop_bot import Model
# Available tiers (cheapest to most capable)
Model.cheap() # "@cheap+agents" - Most economical
Model.budget() # "@budget+agents" - Budget-friendly
Model.fast() # "@fast+agents" - Fastest response
Model.standard() # "@standard+agents" - Standard performance
Model.balanced() # "@balanced+agents" - Best value (default)
Model.smart() # "@smart+agents" - Highest quality
Model.premium() # "@premium+agents" - Premium tier
# With capabilities
Model.smart(vision=True) # "@smart+agents+vision"
Model.balanced(code=True) # "@balanced+agents+code"
# Use in bot
bot = TelegramBot(
token="...",
cmdop_api_key="...",
model=Model.cheap(), # Use cheapest model
)
Models are resolved dynamically by SDKRouter - the actual LLM is selected server-side based on current best options for each tier.
Architecture
+--------------+
| Telegram |
| Discord |---> CMDOPHandler ---> CMDOP SDK ---> Your Servers
| Slack |
+--------------+
All bots share the same CMDOPHandler class which encapsulates:
-
CMDOP client initialization and connection management
-
Machine targeting (switch between servers)
-
Model selection (AI tier for agent commands)
-
Shell command execution
-
File operations (list, read)
-
AI agent execution
-
Skills (list, inspect, run)
-
Simple: Each bot uses CMDOPHandler for all CMDOP logic
-
Reliable: Proper error handling, reconnection
-
Secure: Permission system, user allowlists
Development
# Clone repository
git clone https://github.com/commandoperator/cmdop-bot
cd cmdop-bot
# Install dev dependencies
pip install -e ".[dev,all]"
# Run tests
pytest
# Type check
mypy src/cmdop_bot
# Lint
ruff check src/cmdop_bot
Environment Variables
| Variable | Description | Required |
|---|---|---|
TELEGRAM_BOT_TOKEN |
Telegram bot token | For Telegram |
DISCORD_BOT_TOKEN |
Discord bot token | For Discord |
SLACK_BOT_TOKEN |
Slack bot token (xoxb-...) | For Slack |
SLACK_APP_TOKEN |
Slack app token (xapp-...) | For Slack |
CMDOP_API_KEY |
CMDOP API key from my.cmdop.com | Yes |
CMDOP_MACHINE |
Default target machine | No |
CMDOP_MODEL |
Model tier (@cheap, @balanced, @smart) | No |
ALLOWED_USERS |
Comma-separated user IDs | No |
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_bot-2026.3.10.1.tar.gz.
File metadata
- Download URL: cmdop_bot-2026.3.10.1.tar.gz
- Upload date:
- Size: 36.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1ebf4bf72dca68b714a47fa46fd42e99c468436944d8b50aa7bff777f4d85846
|
|
| MD5 |
9bba567ed69a30b8aafc4eb1d3dfa6fd
|
|
| BLAKE2b-256 |
f4cf0eae80d5dbb7df89c7955452bed9352a3ccd9a2e5af84fb243a86592491c
|
File details
Details for the file cmdop_bot-2026.3.10.1-py3-none-any.whl.
File metadata
- Download URL: cmdop_bot-2026.3.10.1-py3-none-any.whl
- Upload date:
- Size: 59.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 |
4c631e899b0d1bc9b572d2b6bd957e3d7b86b27c6347e9c5358bdae84fe35ede
|
|
| MD5 |
b04e96ee19ac1c55128d6ac3fd688bcd
|
|
| BLAKE2b-256 |
cbe8a010eb02555cef6e455517e2a12d77d4b03fa6a54818df5fe62ee3fe0163
|