# bench (ERPNext glossary)

Canonical: https://erpfly.com/glossary/bench/
Last updated: September 14, 2026

**Definition:** bench is the command-line tool for setting up and managing Frappe Framework and ERPNext deployments. The word also refers to the bench directory it creates, usually frappe-bench, which holds the apps, sites, Python environment and configuration shared by every site on that server.

Also called: Bench CLI, frappe-bench, Frappe Bench, bench command

If you've installed [ERPNext](https://erpfly.com/erpnext/) yourself, you've already met bench. It's the first thing you install and the tool you'll type most often afterwards. The Frappe docs are careful about one ambiguity: "bench" can mean the CLI you run or the directory it manages. In conversation people use both, and the context usually tells you which.

### The directory

`bench init` creates a folder with a fixed layout. Everything a Frappe deployment needs lives inside it:

```text
frappe-bench/
├── apps/                     # frappe, erpnext, your own apps (Git repos)
├── sites/
│   ├── apps.txt              # apps available on this bench
│   ├── assets/               # built JS and CSS
│   ├── common_site_config.json
│   └── erp.example.com/
│       ├── site_config.json
│       ├── private/
│       └── public/
├── config/                   # Redis, NGINX and supervisor config
├── env/                      # Python virtual environment
├── logs/
└── Procfile                  # processes started by bench start
```

The split between `apps` and `sites` is the idea to hold on to. Code lives once in `apps`, and each folder in `sites` is a separate database and config that can have any of those apps installed. One bench can serve several companies' sites from the same code.

Configuration follows the same split. `common_site_config.json` applies to every site on the bench, and each site's own `site_config.json` holds its database credentials and anything specific to it. `bench --site erp.example.com set-config key value` writes to the site file, while adding `-g` writes to the common one. When a setting seems to be ignored, check both files before anything else.

### Commands you'll use every week

The CLI itself is installed from PyPI as `frappe-bench`. A typical first setup, then the day-to-day commands:

```bash
bench init --frappe-branch version-15 frappe-bench
cd frappe-bench
bench new-site erp.example.com
bench get-app --branch version-15 erpnext
bench --site erp.example.com install-app erpnext
bench start                                   # development server

bench --site erp.example.com migrate          # patches, schema sync, fixtures
bench --site erp.example.com backup
bench --site erp.example.com console          # IPython with the site loaded
bench --site erp.example.com clear-cache
bench build --app my_app
```

Swap `version-15` for `version-16` on a v16 bench. The site commands need `--site` unless you've set a default with `bench use erp.example.com`.

### Two sets of commands behind one name

Not every `bench` command comes from the bench package. `init`, `get-app`, `update`, `setup production` and `restart` belong to the CLI. Site-level commands such as `new-site`, `install-app`, `migrate`, `console` and `export-fixtures` are defined by the Frappe Framework, and bench passes them through. That's why a site command can behave differently between v15 and v16 while your bench CLI version stays the same. When a flag isn't doing what you expect, check the Frappe version first.

### Mistakes that cost an afternoon

**Editing code inside `apps/erpnext` or `apps/frappe`.** `bench update` refuses to pull while an app has uncommitted changes, and `bench update --reset` fixes that by running `git reset --hard`, wiping your edits. Put changes in your own Frappe app instead. erpfly never touches those two folders; everything it generates goes into a separate app you install with `install-app`.

**Migrating production without a backup.** `migrate` runs patches that change data. Take a backup first, even though `bench update` takes one for you, because you'll often run `migrate` on its own. Our notes on [keeping customizations through an ERPNext upgrade](https://erpfly.com/blog/erpnext-upgrade-keep-customizations/) walk through a safer order.

**Developer mode on a live site.** `bench set-config -g developer_mode 1` is right for a development bench and wrong for production, where DocTypes should arrive through `migrate`, not be created by hand.

**Forgetting that a change to hooks.py may need `migrate` and a restart** before the running workers see it.

See also: https://erpfly.com/glossary/frappe-app/, https://erpfly.com/glossary/hooks-py/, https://erpfly.com/glossary/fixtures/, https://erpfly.com/glossary/doctype/

### Sources

- [Bench, Frappe Framework documentation](https://docs.frappe.io/framework/user/en/bench)
- [Frappe Commands, Frappe Framework documentation](https://docs.frappe.io/framework/user/en/bench/frappe-commands)
- [Bench Commands, Frappe Framework documentation](https://docs.frappe.io/framework/user/en/bench/bench-commands)
- [frappe/bench on GitHub](https://github.com/frappe/bench)