Skip to main content

Bonsai CLI

bonsai is a macOS-first CLI for managing parallel local development workspaces with git worktrees, unique port slots, generated .env.local files, and optional Caddy HTTPS URLs.

Use it when you need several branches running side by side, want predictable per-branch app URLs, or need to give an agent exact workspace facts without guessing paths or ports.

Capabilities

  • Clone or adopt a repository into a Bonsai workspace layout.
  • Create, move, check out, and remove managed git worktrees.
  • Prepare GitHub PR worktrees with bonsai add --pr <number> or bonsai checkout --pr <number>.
  • Generate branch-specific environment values such as SLOT, service ports, BONSAI_BRANCH, BONSAI_WORKTREE_PATH, and BONSAI_PRIMARY_URL.
  • Start, stop, restart, and inspect configured app services.
  • Maintain optional Caddy routes for *.localhost HTTPS URLs, with direct port fallback when Caddy is unavailable.
  • Print rich text and JSON status for humans, scripts, and AI agents.
  • Repair generated files, port slot conflicts, and workspace state.
  • Clean up worktrees for merged PRs.

Install

brew tap mggwxyz/tap
brew install bonsai

From source:

cd apps/bonsai
bun install
bun src/main.ts --help
bun run typecheck
bun test
bun run build

The source build compiles a standalone binary to apps/bonsai/dist/bonsai.

Fastest First Run

bonsai doctor --preflight
bonsai start-here git@github.com:org/my-app.git my-app

start-here performs the newcomer flow: preflight checks, clone, guided config review, shell integration offer, first worktree creation, app start, Caddy setup when available, and final URL output.

Success ends with:

done - your app is at <url>

The URL can be a Caddy URL such as https://<slug>.<app>.localhost or a direct fallback such as http://localhost:<port>.

Existing Checkout Flow

If the project is already cloned:

cd ~/Projects/my-app
bonsai adopt --dry-run
bonsai adopt

adopt converts the current folder into the Bonsai layout in place. The current checkout moves to my-app/main/, and future worktrees become peers under my-app/.

Daily Workflow

bonsai add ma-123-implement-auth
bonsai checkout ma-123-implement-auth
bonsai start
bonsai open
bonsai status

Useful variants:

bonsai add --pr 123
bonsai up
bonsai logs --command start
bonsai exec -- npm test
bonsai each -- git status --short
bonsai cleanup --apply

bonsai checkout changes the parent shell directory only after shell integration is installed:

bonsai install-shell zsh

Use bash or fish instead of zsh when appropriate.

Configuration

Each workspace uses .bonsai.toml, resolved at the workspace root first and then inside the default worktree. Add .bonsai.local.toml beside the selected config for machine-local overrides.

name = "my-app"
base_branch = "main"

[commands]
install = "npm install"
setup = "npm run db:migrate"
start = "npm run dev"

[[shared_files]]
source = ".env"
target = ".env"
mode = "copy"

[[services]]
name = "frontend"
start = "npm run dev:web"
port_env = "FRONTEND_PORT"
base_port = 4200
primary = true
url = "https://${slug}.my-app.localhost"

See the Configuration guide for every key.

Reference Pages