benchops
A cross-platform CLI tool that synchronizes local Frappe development environments with remote servers.
benchops automates the repetitive "ship my app to the server" workflow: it
builds your app locally, packages it into a compressed archive, uploads it to
the target server over SSH, extracts it into the remote bench, and runs the
Frappe housekeeping commands to apply the changes — all with output streamed to
your terminal in real time.
Features
- Server management — define remote servers in a local TOML config
(
~/.benchops/config.toml) with a friendly interactive CLI. - Secure authentication — store server passwords in your OS credential
store (
keyring) or use an SSH private key. - Real-time streaming — every local and remote command streams its stdout and stderr to your terminal as it runs.
- Lean transfers — source tarballs exclude
.git,__pycache__,node_modules, and*.pycto keep uploads small. - One-command deploy — build, archive, upload, extract, migrate, and clear cache with a single invocation.
Requirements
- Python
>= 3.14.6 - uv (recommended) or
pip - SSH access to the target server (password or key)
Installation
git clone <your-repo-url> benchops
cd benchops
uv sync
Install the CLI into your environment so the benchops command is available:
uv run pip install -e .
# or, if you built a distribution:
uv build && uv pip install --python .venv/bin/python dist/benchops-0.1.0-py3-none-any.whl
Verify it works:
benchops --help
Quick start
1. Initialize the configuration
benchops init
This creates ~/.benchops/config.toml with an empty [servers] table.
2. Register a server
benchops server add
You will be prompted for:
| Field | Description |
|---|---|
alias |
Short name used to reference the server |
host |
Hostname or IP address |
port |
SSH port (default: 22) |
user |
SSH username |
bench_path |
Remote path to the bench directory |
You can also pass everything non-interactively:
benchops server add --alias dev1 --host 192.168.1.10 --port 22 --user frappe --bench-path /home/frappe/bench
List your configured servers:
benchops server list
3. Configure authentication
benchops server set-auth dev1
You will be asked to choose between:
password— prompted securely (hidden input, double confirmation) and stored in your system keyring.key— path to your SSH private key (default~/.ssh/id_rsa), stored in the server's configuration.
4. Deploy
Run benchops deploy from the directory that contains your app (either inside
the local bench's apps/ folder or directly):
benchops deploy <app_name> <server_alias>
For example:
benchops deploy myapp dev1
The deploy pipeline:
- Config & auth — loads the server settings and its credentials.
- Local build — runs
bench build --app <app_name>in the app's parent directory. - Archive — compresses
<app_name>into a.tar.gz(excluding.git,__pycache__,node_modules, and*.pyc) in a temporary directory. - Connect — opens an SSH connection to the server.
- Transfer & extract — uploads the tarball and extracts it into
{bench_path}/apps. - Remote operations — runs
bench --site all migrateandbench clear-cacheinside{bench_path}. - Cleanup — closes the connection and reports success.
Configuration
All server definitions live in ~/.benchops/config.toml:
[servers]
dev1 = {host = "192.168.1.10", port = 22, user = "frappe", bench_path = "/home/frappe/bench", private_key_path = "/home/mohammad/.ssh/id_rsa"}
staging = {host = "staging.example.com", port = 22, user = "deploy", bench_path = "/srv/bench"}
Passwords are not stored in this file — they are kept in the operating
system's credential store via keyring.
Development
uv sync # install dependencies
uv build # build wheel + sdist
uv publish # upload to PyPI (set UV_PUBLISH_TOKEN first)
License
MIT
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 benchops-0.2.0.tar.gz.
File metadata
- Download URL: benchops-0.2.0.tar.gz
- Upload date:
- Size: 31.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.4 {"installer":{"name":"uv","version":"0.12.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa7b8e41edd2b862cb40ac925b46dcf40113390f0dad8dbe8256ee6f6a56d95f
|
|
| MD5 |
fa5b56c1accd33efeaf7fa486227a754
|
|
| BLAKE2b-256 |
e0fa7f1b4a7460d281c497f4c37fe0b5b41079523f7b6d98275b621545118bf2
|
File details
Details for the file benchops-0.2.0-py3-none-any.whl.
File metadata
- Download URL: benchops-0.2.0-py3-none-any.whl
- Upload date:
- Size: 9.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.4 {"installer":{"name":"uv","version":"0.12.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e2bacc37fd5e495e6711325314da32ac22f9838cdf1d9ae282fb773bd1181b9c
|
|
| MD5 |
5be60c5b296b0f98a32a252a19515338
|
|
| BLAKE2b-256 |
03ab507beee1d1739adeaef312441f5649f4cad58cba7c764cb3193c0178dc5f
|