Skip to content

frappe/bench-cli

Repository files navigation

bench-cli

Unit Tests

A zero-dependency CLI for managing Frappe environments with Admin UI. Single bench.toml. No Docker.

Apps

Improvements from legacy bench

Legacy bench-cli
Dependencies ~20 Python packages Zero — stdlib only
Marketplace None App registry apps.json
Config None Single bench.toml
Folder layout Wherever you bench init All benches under bench-cli/benches/
Process manager Honcho / Supervisor Built-in Procfile runner
Python env pip + virtualenv uv (auto-installed)
Admin UI None Built-in — app status, sites, logs, task runner

Requirements

Ubuntu 22.04+ — Python 3.11+, sudo access
macOS — Python 3.11+, Homebrew (dev only)

Install

curl -fsSL https://raw.githubusercontent.com/frappe/bench-cli/main/install.sh | bash

Clones to ~/bench-cli and adds bench to PATH. Or manually:

git clone https://github.com/frappe/bench-cli ~/bench-cli
echo 'export PATH="$HOME/bench-cli:$PATH"' >> ~/.zshrc && source ~/.zshrc

Quick start

bench new my-bench       # creates bench.toml — edit it to set MariaDB password
bench init               # installs deps, creates venv, clones frappe, generates Procfile
bench get-app https://github.com/frappe/erpnext --branch version-16
bench new-site site1.localhost
bench start              # starts web, workers, Redis, and admin UI
  • App: http://site1.localhost:8000
  • Admin UI: http://localhost:8002

bench.toml

[bench]
name = "my-bench"
python = "3.14"

[[apps]]
name = "frappe"
repo = "https://github.com/frappe/frappe"
branch = "version-16"

[mariadb]
host = "localhost"
port = 3306
root_password = "your_root_password"

[redis]
port = 13000

[workers]
default = 2
short = 1
long = 1

[admin]
port = 8002
password = "your-admin-password"   # required — admin refuses to start without this
domain = "admin.example.com"       # optional — serve admin over HTTPS via nginx

Apps and sites are tracked by the filesystem — no need to list them in bench.toml.

Commands

Command What it does
bench new <name> Scaffold a new bench
bench init Install deps, create venv, clone framework, generate Procfile
bench start Start all processes (web, workers, Redis, admin UI)
bench stop Stop a running bench from another terminal
bench restart Restart supervisor processes (production only)
bench get-app <repo> Clone and install an app
bench new-site <name> Create a site
bench build Download pre-built assets (use --force to rebuild from source)
bench update git pull + reinstall + migrate all sites
bench upgrade Pull latest bench-cli and download the admin frontend
bench setup config Regenerate Procfile and config files from bench.toml
bench build-admin Rebuild admin frontend assets from source
bench setup nginx Generate and install nginx config
bench setup letsencrypt Obtain SSL certificates
bench setup production Full production setup (nginx + SSL + supervisor)

With multiple benches: bench -b my-bench start

Production

[nginx]
enabled = true

[letsencrypt]
email = "ops@example.com"

[admin]
port = 8002
password = "your-admin-password"
domain = "admin.example.com"   # optional — serve admin UI over HTTPS
bench setup production         # nginx + supervisor
bench setup letsencrypt        # SSL certs for all sites + admin domain

When admin.domain is set, bench setup letsencrypt obtains a certificate for that domain and bench setup nginx generates an HTTPS proxy block for it. HTTP redirects to HTTPS automatically.

Directory layout

bench-cli/
└── benches/
    └── my-bench/
        ├── bench.toml              # infra config (python, db, redis, workers)
        ├── apps/                   # cloned app source
        ├── sites/
        │   ├── apps.txt
        │   ├── common_site_config.json
        │   └── site1.localhost/
        ├── env/                    # Python virtualenv (managed by uv)
        ├── logs/                   # per-process log files
        ├── pids/                   # bench.pid + per-process PID files
        └── config/                 # Procfile, Redis configs, Nginx configs

Testing

# Install test dependencies
pip install -e ".[test]"

# Run unit tests
pytest tests/ --ignore=tests/integration

# Run with coverage
pytest tests/ --ignore=tests/integration --cov=bench_cli --cov-report=term-missing

Unit tests run against mocked filesystems — no MariaDB, Redis, or network required.

Integration tests (in tests/integration/) run the full bench initbench new-site lifecycle against real services and are triggered by CI on push to main.

About

[Experimental] One bench to rule them all

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors