Tested on Linux, macOS, and Windows
Remote CMD — SSH Server Management
Without the Overhead
pip install remote_cmd_manager ·
Quick Start ·
Use Cases ·
CLI Reference ·
Python API ·
Documentation ·
Contributing
Remote CMD is a lightweight Python CLI + API for managing servers over SSH. Add hosts, run commands, transfer files, and organize hosts with tags — no Ansible DSL or shell loops required.
# One command to get started
pip install remote_cmd_manager && remote-cmd host add web-01 192.168.1.10 ubuntu --key ~/.ssh/id_rsa && remote-cmd run web-01 "uptime"
v2.7.0 Release Highlights
v2.7.0 is a runtime-efficiency and error-semantics release: credential-layer exceptions are narrowed so real bugs surface, SQLite no longer truncates its WAL on every write, and the global connection budget waits on a true async queue instead of polling. Public APIs remain backward compatible. See the full migration notes.
Error Semantics
- Keyring, encryption, and host-service decrypt paths now catch only expected failure classes; programming errors propagate instead of being silently swallowed.
- Background pool monitor loops keep their catch-all guard but log full stack traces.
- Optional
asyncsshdetection usesfind_spec, so a defect in the async modules themselves can no longer masquerade as "dependency not installed".
SQLite WAL Efficiency
flush()now runs a PASSIVE checkpoint instead ofTRUNCATE— no more writer waits or WAL rewrites on every host add/update/remove.- New explicit
repo.checkpoint("TRUNCATE")(alsoPASSIVE/FULL/RESTART) for deliberate WAL compaction.
Connection Budget
ConnectionBudget.acquire_async()now waits on a real queue (asyncio.Futurewoken viacall_soon_threadsafe), removing the v2.6 polling loop; cancellation-safe and FIFO among async waiters.
Benchmark Data (P2.4)
- The sync Paramiko path costs ~100 µs per command in thread create/join and peaks at ≈ 3× sustained concurrency in live threads. A centralized channel-reader rewrite is a v2.7.x decision based on these measurements.
Table of Contents
- v2.7.0 Release Highlights
- Why Remote CMD?
- Quick Start
- Use Cases
- CLI Reference
- Python API
- Features
- Installation
- Documentation
- Project Status
- Maintainership
- Contributing
- License
Why Remote CMD?
| Feature | remote-cmd |
ssh + shell |
Ansible | Fabric |
|---|---|---|---|---|
| Host CRUD + tag groups | ✅ Built-in | ❌ Manual | ✅ Inventory | ❌ |
| Batch commands across hosts | ✅ batch-run |
❌ Write a loop | ✅ Playbook | ✅ |
| File transfer (upload/download) | ✅ Built-in | ✅ scp | ✅ copy module | ✅ |
| Python API | ✅ from remote_cmd import ... |
❌ | ❌ YAML-only | ✅ |
| Zero setup | ✅ pip install → go |
❌ Configure SSH | ❌ ansible.cfg |
❌ |
| Learning curve | Low | Low | High | Medium |
Use remote-cmd when you need a CLI that works immediately for ad-hoc SSH tasks. Use Ansible when you need full configuration management and idempotent playbooks.
Quick Start
# 1. Install
pip install remote_cmd_manager
# 2. Add a server
remote-cmd host add web-01 192.168.1.10 ubuntu --key ~/.ssh/id_rsa
# 3. Run a command
remote-cmd run web-01 "uptime"
# 4. Run across named production servers
remote-cmd batch-run web-01 web-02 db-01 "df -h /"
Use Cases
🖥️ System Administrators — Check disk across 20 servers in one command
remote-cmd batch-run web-01 web-02 db-01 "df -h / | tail -1"
# Output:
# ✓ web-01 → /dev/sda1 32G 12G 19G 40% /
# ✓ web-02 → /dev/sda1 32G 28G 3G 90% / ⚠️
# ✗ db-01 → Connection refused
🚀 Deploy — Pull code and restart a service
from remote_cmd.service.host_service import HostService
from remote_cmd.repository import JsonHostRepository
service = HostService(repository=JsonHostRepository("hosts.json"))
for host in service.list_hosts(tag="staging"):
with service.connect_to_host(host.name) as client:
client.execute("cd /app && git pull")
client.execute("pip install -r requirements.txt")
client.execute_sudo("systemctl restart app", password="sudopass")
🔥 Incident Response — Check logs across all servers
remote-cmd batch-run web-01 web-02 "journalctl -xe -n 50 | grep -i error"
🔧 Config Update — Upload and reload nginx across tagged hosts
# Upload new config, reload across web servers
remote-cmd run web-01 "sudo cp /tmp/nginx.conf /etc/nginx/nginx.conf && sudo nginx -t && sudo systemctl reload nginx"
CLI Reference
All operations are available from the terminal:
| Command | Description |
|---|---|
remote-cmd host add <name> <host> <user> |
Register a server (-k/--key, -p/--port, -t/--tag, repeatable) |
remote-cmd host list [-t TAG] |
List hosts, optionally filtered by tag |
remote-cmd host show <name> |
Show one host's details |
remote-cmd host test <name> |
Test connectivity to a host |
remote-cmd host remove <name> |
Remove a host |
remote-cmd run <name> "<cmd>" [-T SECONDS] |
Run a command on one host (--timeout/-T sets the wall-clock limit) |
remote-cmd upload <name> <local> <remote> |
Upload a file via SFTP |
remote-cmd download <name> <remote> <local> |
Download a file via SFTP |
remote-cmd batch-run <name>... "<cmd>" |
Run across named hosts (-C concurrency, -T timeout, -r retries, --async, --show-failures) |
Python API
Use Remote CMD inside your own scripts and automation:
from remote_cmd.core.ssh_client import SSHClient, ConnectionConfig
config = ConnectionConfig(
hostname="192.168.1.100",
username="ubuntu",
key_filename="~/.ssh/id_rsa",
)
with SSHClient(config) as client:
# Execute commands
result = client.execute("uptime")
print(result.stdout)
# Transfer files
client.upload_file("./local.txt", "/remote/path/file.txt")
client.download_file("/remote/path/file.txt", "./local.txt")
# List remote directory
for entry in client.list_remote_directory("/var/log"):
print(f"{entry.name}: {entry.size} bytes")
Features
| Category | Details |
|---|---|
| SSH Auth | Password + key file + ssh-agent, with pluggable credential providers |
| Credential Chain | Source passwords from environment, keyring, or arbitrary providers, in priority order |
| Credential Encryption | Fernet-encrypt secrets at rest (CredentialEncryption) |
| Commands | Single, multi-line, sudo with password |
| File Transfer | Upload/download via SFTP (remote-cmd upload/download) |
| Host Management | CRUD with pluggable JSON or SQLite persistence |
| Tag System | Filter hosts by tag (e.g., production, web, db) |
| Batch Ops | Run commands across any host group, synchronously or asynchronously; optional per-host retained-output cap (max_output_bytes) |
| Async Kernel | AsyncSSHClient / AsyncConnectionPool / AsyncBatchExecutor via the [async] extra |
| Global Connection Budget | Optional ConnectionBudget caps live SSH connections process-wide across pools and executors |
| Task Runner | Track and schedule long-running remote tasks with statuses (TaskRunner) |
| Connection Test | Test all host SSH connections and report status |
| Secure Logging | Structured logging that filters sensitive data (SensitiveDataFilter) |
| Type Safety | Full type annotations + mypy strict |
Cross-Platform Support
remote-cmd is a pure-Python client, tested and supported on Linux, macOS, and Windows. No native dependencies or platform-specific builds are required.
| Platform | Status | Notes |
|---|---|---|
| Linux | ✅ Fully tested | Primary development platform |
| macOS | ✅ Supported | Use brew install openssh for a newer OpenSSH |
| Windows | ✅ Supported | PowerShell / CMD / WSL all work |
Note on Windows file permissions: Credential encryption keys are protected with
0600permissions on Unix. On Windows this restriction is not enforced by the filesystem — the key file is still encrypted at rest. For production Windows use, consider adding filesystem-level ACLs.
Installation
# From PyPI (recommended) — keeps API and CLI in sync
pip install remote_cmd_manager
# With native async support (AsyncSSHClient / AsyncConnectionPool / AsyncBatchExecutor)
pip install "remote_cmd_manager[async]"
# From source
git clone git@github.com:Vae-Scrooge/remote-cmd.git
cd remote-cmd
pip install -e ".[dev]"
The [async] extra installs asyncssh and enables the native async execution
kernel: AsyncSSHClient, AsyncConnectionPool and AsyncBatchExecutor
(also available via BatchExecutor(use_async=True)). BatchExecutor(use_async=True)
also requires this extra. Without it, import remote_cmd still works — the async symbols
are simply not exported.
Documentation
📚 Full Documentation Center — tutorials, API reference, architecture, and troubleshooting
| Document | Contents |
|---|---|
| API Reference | Full API docs: SSHClient, AsyncSSHClient, HostService, and more |
| API Docs (auto-generated) | Complete API reference generated by pdoc |
| Quickstart Tutorial | Step-by-step walkthrough |
| Advanced Tutorial | Batch ops, error handling, production patterns |
| Architecture | System architecture and design decisions |
| Development Guide | Set up the dev environment, contributing |
| Troubleshooting | Common issues and solutions |
| Changelog | Release history |
| Mobile Remote Guide | Manage servers from your phone |
Note: The documentation center and tutorials are maintained in English. See README.zh-CN.md for the Chinese version of this page.
Project Status
Stable. The core API is stable and versioned under semantic versioning. Breaking changes are communicated via major-version bumps, and the public API surface has been stable since the 1.x line.
Roadmap:
- Async SSH operations (parallel execution) — v1.1.0
- Pluggable storage backends (JSON + SQLite) — v1.2.x
- Chainable credential providers + at-rest encryption — v1.2.x
- Configuration profiles (AWS, GCP, custom)
- Output formatting (JSON, table)
- Templated command recipes
Good first issues are labelled good first issue in the
issue tracker — contributions welcome.
Maintainership
Remote CMD is an actively maintained open-source project. It is designed and developed independently as a focused alternative to heavyweight tools for the ad-hoc SSH tasks that come up in day-to-day server work.
- Project health: CI runs on every PR, Python 3.10+ is supported, and the public API is versioned under semantic versioning.
- Your code, your servers: usage stays open under the MIT license — nothing is telemetry-driven or locked behind a service.
- Why open source? The tooling around ad-hoc SSH administration was either too heavy (Ansible) or too bare (raw shell loops). Remote CMD exists so that a single command can cover the common 90% of remote admin.
Contributing
We welcome contributions! See CONTRIBUTING.md to get started.
Before contributing, please read our Code of Conduct.
License
MIT © Vae-Scrooge
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 remote_cmd_manager-2.7.0.tar.gz.
File metadata
- Download URL: remote_cmd_manager-2.7.0.tar.gz
- Upload date:
- Size: 181.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
653de38b378787dbc8f139df829e7f84788c27608844f1a049fbd1e077e41d77
|
|
| MD5 |
07a65c553445c14fc4e10fb9cd7712a6
|
|
| BLAKE2b-256 |
769bf3d09fd136178912e96679d3146144b16d9c1fda557ed1b7ffbfc792a2fe
|
Provenance
The following attestation bundles were made for remote_cmd_manager-2.7.0.tar.gz:
Publisher:
publish.yml on Vae-Scrooge/remote-cmd
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
remote_cmd_manager-2.7.0.tar.gz -
Subject digest:
653de38b378787dbc8f139df829e7f84788c27608844f1a049fbd1e077e41d77 - Sigstore transparency entry: 2818038955
- Sigstore integration time:
-
Permalink:
Vae-Scrooge/remote-cmd@49fbb441ebd1c43916cf0d44d768007eb09e4114 -
Branch / Tag:
refs/tags/v2.7.0 - Owner: https://github.com/Vae-Scrooge
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@49fbb441ebd1c43916cf0d44d768007eb09e4114 -
Trigger Event:
release
-
Statement type:
File details
Details for the file remote_cmd_manager-2.7.0-py3-none-any.whl.
File metadata
- Download URL: remote_cmd_manager-2.7.0-py3-none-any.whl
- Upload date:
- Size: 113.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3f3229308b129e8368a984c505fd406aa750e6da4e4338f9e33473b6d25c40c3
|
|
| MD5 |
043ad196928b435d87912374c41db6cc
|
|
| BLAKE2b-256 |
7c9813217061ed016fd3625a39ab1999b55d86aa3e5e53df9e676274518c8a89
|
Provenance
The following attestation bundles were made for remote_cmd_manager-2.7.0-py3-none-any.whl:
Publisher:
publish.yml on Vae-Scrooge/remote-cmd
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
remote_cmd_manager-2.7.0-py3-none-any.whl -
Subject digest:
3f3229308b129e8368a984c505fd406aa750e6da4e4338f9e33473b6d25c40c3 - Sigstore transparency entry: 2818039003
- Sigstore integration time:
-
Permalink:
Vae-Scrooge/remote-cmd@49fbb441ebd1c43916cf0d44d768007eb09e4114 -
Branch / Tag:
refs/tags/v2.7.0 - Owner: https://github.com/Vae-Scrooge
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@49fbb441ebd1c43916cf0d44d768007eb09e4114 -
Trigger Event:
release
-
Statement type: