The fast way to develop Frappe apps. Weg means "way" in German and "speed" (वेग) in Marathi/Sanskrit — a modern replacement for Frappe's bench CLI.
- One TOML file, whole environment. Declare apps, sites, and services in
weg.tomlorpyproject.toml [tool.weg];weg syncmakes reality match. No more replayingbenchincantations from memory. - Fast by construction. A single static Go binary orchestrating devbox (reproducible system deps via Nix), uv (fast Python), and process-compose (service management).
- Your shell is a Frappe client.
weg api get User,weg doc field set,weg db query "SELECT ...",weg py "print(frappe.get_all('ToDo'))"— direct document, API, and database access without HTTP boilerplate or console copy-paste. - Remote sites with real git history.
weg remote clonepulls a site's customizations (Server Scripts, Client Scripts, Custom Fields, …) into a local git repo — and reconstructs the full document version history into commits, streamed and resumable. Then edit locally andweg remote push. - Built for AI workflows.
weg mcp installgives Claude Code and other MCP clients 12 structured tools for driving your Frappe environment. - Scriptable everywhere.
-o jsonon status/list/introspection commands, meaningful exit codes, andweg doctorthat fails loudly enough to gate CI.
Download a release binary (Linux/macOS):
curl -fsSL https://github.com/gavindsouza/weg/releases/latest/download/weg-$(uname -s)-$(uname -m) -o weg
chmod +x weg && mkdir -p ~/.local/bin && mv weg ~/.local/bin/Or with Go:
go install github.com/gavindsouza/weg@latestOr build from source (Go 1.24+):
git clone https://github.com/gavindsouza/weg && cd weg
go build -o ~/.local/bin/weg .Weg needs git; everything else (devbox, direnv, …) can be installed with weg self install-tools. Run weg self doctor to check your system.
Weg supports three development modes. Pick the one that matches how you work.
The bench lives hidden in .weg/; config lives in pyproject.toml [tool.weg]. Ideal for developing a single Frappe app with modern tooling.
weg new myapp
cd myapp
weg start
weg site browse # Opens the site, auto-logged-in as Administratorapps/ and sites/ at the root; config lives in weg.toml. Use this for multi-app projects or when adopting an existing bench.
cd frappe-bench
weg init
weg startWork on a hosted site (Frappe Cloud or any Frappe site) by cloning its customizations into a local git repo:
weg remote clone https://mysite.frappe.cloud mysite
cd mysite
# Edit Client Scripts, Server Scripts, Custom Fields... as local files
weg remote push -n # Preview what would change
weg remote sync -m "Add priority field to Todo"The clone reconstructs each document's version history into git commits, so git log and git blame work on customizations that never had version control. History fetching is streamed and resumable — interrupt a large clone and run it again to pick up where it left off (or pass --no-history for a fast single-commit clone). weg remote pull keeps that history going: it replays the Version records created since the last sync as individual commits, with a trailing snapshot commit for anything not attributable to a Version. Pass --no-history to pull as a single snapshot commit instead.
Just want to try an app? weg run https://github.com/frappe/hrms clones it, builds a throwaway environment, creates a site, and starts the server.
Run weg --help for the full grouped listing; every command has detailed --help with examples. Highlights:
weg new myapp # Create a new Frappe app (app-centric)
weg create mybench # Create a new bench (bench-centric)
weg init # Adopt an existing app or bench directory
weg run frappe/hrms # Disposable environment for any app
weg scaffold ai # Add CLAUDE.md + AI agent skills to a projectweg start # Start db, redis, web, workers, scheduler, watcher
weg start -f # Same, in the foreground with a TUI
weg stop # Stop everything
weg status # What's installed, what's running, is sync needed
weg doctor # Health checks; exits non-zero on failure
weg build # Build frontend assets (weg build watch for watch mode)
weg test # Run app tests (--all-versions for a version matrix)
weg log tail web # Tail web/worker/schedule/error logsweg site new mysite.localhost # Create a site
weg site use mysite.localhost # Set the default site
weg site backup --with-files # Backup to .weg/backups/
weg site maintenance on # Maintenance mode
weg site hosts add # Add sites to /etc/hosts
weg api get User -F '{"enabled":1}' # REST-style document access, no HTTP setup
weg api call frappe.ping # Call any whitelisted method
weg doc field set User Administrator enabled 0
weg db migrate # Run database migrations
weg db query "SELECT name FROM tabUser LIMIT 5"
weg py "print(frappe.db.count('User'))" # Python with frappe pre-connected
weg exec -- bench migrate # Escape hatch: any command in the bench envweg add frappe/erpnext version-15 # Declare an app in config...
weg sync # ...and apply the config
weg app get frappe/hrms # Or clone + install immediately (with deps)
weg app switch frappe version-15 # Switch an app's branch
weg update # Update all apps within the current version
weg upgrade --dry-run # Preview a major-version upgrade (15 → 16)weg docker init # Generate docker-compose.yml (--mode prod)
weg image build --target web # Multi-stage OCI images for production
weg cloud login # Frappe Cloud: deploy, logs, marketplace
weg cloud deploy mysite.frappe.cloudweg remote login https://mysite.frappe.cloud # Save credentials (0600, global)
weg remote clone https://mysite.frappe.cloud # Clone with full version history
weg remote status # Local vs remote diff
weg remote pull # Replay version history since last sync
weg remote pull --no-history # Fast single snapshot commit
weg remote sync -m "description" # Pull, commit, push
weg workspace expand # Extract scripts from JSON into .py/.js files
weg workspace collapse # Pack IDE edits back into JSONSee docs/guide.md for the full guide.
[frappe]
version = "15"
database = "mariadb"
[apps.erpnext]
url = "https://github.com/frappe/erpnext"
branch = "version-15"
[[sites]]
name = "mysite.localhost"
default = true
apps = ["frappe", "erpnext"]
[services.workers]
short = 1
long = 1[tool.weg.compatibility]
frappe = ["15", "16"] # Versions your app supports
databases = ["mariadb"]
[tool.weg.dev]
frappe = "15" # Version to develop against
database = "mariadb"
[[tool.weg.dependencies.apps]]
name = "erpnext"
url = "https://github.com/frappe/erpnext"
branch = "version-15"Apps can also declare extra devbox packages and processes they need under [tool.weg.services] — see the guide for details, including customizing generated services with process-compose.override.yaml.
| Feature | weg | bench |
|---|---|---|
| Configuration | Declarative (TOML) | Imperative (commands) |
| Development modes | App-centric, bench-centric, remote-site | Bench-centric only |
| Python management | uv (fast) | pip |
| System dependencies | devbox/Nix (reproducible) | Manual |
| Process management | process-compose | honcho/supervisord |
| Container support | Built-in (Compose + image builds) | frappe_docker (separate) |
| API access | Direct (no HTTP) | Via HTTP |
| Remote site editing | Built-in (git-backed, with history) | Not available |
| Cloud integration | Built-in | Separate tool |
Command mapping: coming from bench?
| weg | bench |
|---|---|
weg new |
bench new-app |
weg init |
bench init |
weg sync |
(declarative — no equivalent) |
weg start / weg stop |
bench start / (Ctrl+C) |
weg build |
bench build |
weg test |
bench run-tests |
weg db migrate |
bench migrate |
weg db console |
bench mariadb |
weg site new |
bench new-site |
weg site drop |
bench drop-site |
weg site use |
bench use |
weg site install |
bench install-app |
weg site backup / weg site restore |
bench backup / bench restore |
weg site password |
bench set-admin-password |
weg site browse |
bench browse |
weg site hosts add |
bench add-to-hosts |
weg app get |
bench get-app |
weg app remove |
bench remove-app |
weg cache clear |
bench clear-cache |
weg scheduler enable / disable |
bench enable-scheduler / disable-scheduler |
weg scheduler jobs |
bench show-pending-jobs |
weg scheduler purge |
bench purge-jobs |
weg user create |
bench add-user |
weg user disable |
bench disable-user |
weg fixtures export |
bench export-fixtures |
weg api call |
bench execute |
weg update |
bench update |
weg version |
bench version |
weg convert |
(new — switch app-centric ⇄ bench-centric layout) |
weg exec -- <cmd> |
(new — run any command in the bench env) |
weg api / weg doc / weg doctype / weg py |
(new — direct data access) |
weg remote / weg workspace |
(new — remote-site development) |
weg cloud / weg docker / weg image |
(new — deployment) |
weg mcp |
(new — AI integration) |
Anything not covered still works via passthrough: weg bench <any-bench-command>.
weg mcp install # Adds weg to .mcp.json (merges with existing servers)Weg ships an MCP (Model Context Protocol) server exposing 12 structured tools — running Python against your site, calling APIs, managing sites and services — so AI assistants like Claude Code drive your environment through safe, typed operations instead of guessing at shell commands.
weg -C ~/projects/myapp status # Run against another directory (like git -C)
weg site list -o json | jq . # JSON output on status/version/doctor/config
# show/site list/app list/cloud marketplace
weg -v sync # Verbosity: -v, -vv, -vvv (or --log-level)
weg -y site drop old.localhost # Assume yes for prompts
weg doctor || exit 1 # Non-zero exit on failed checks — CI-friendlyExit codes are meaningful (0 success, 2 usage, 3 config, 5 network, 6 not found, …) — the full contract lives in docs/CLI_CONVENTIONS.md.
Weg is pre-1.0 software: used daily for real Frappe development, but interfaces may still change between releases. Design decisions are recorded in docs/decisions/.
Licensed under Apache 2.0.