Drupal
Local Drupal development for Mac, Composer and Drush included.
Bothy is a native Mac app that runs PHP, MySQL or MariaDB and HTTPS for your local sites. A new Drupal site is one step: composer create-project drupal/recommended-project and a database, served from web/ at https://intranet.test, ready for Drupal's installer.
How a modern Drupal project is laid out
Current Drupal is a Composer project. drupal/recommended-project puts composer.json and vendor/ at the top level and Drupal core, contributed modules and themes under web/, which is the only folder the web server should serve. Configuration is exported to YAML (usually a config/sync folder) and committed; content stays in the database. Drush is the command-line tool you'll use for nearly everything.
Bothy detects web/ as the document root automatically, and translates the RewriteRules in Drupal's web/.htaccess into the site's Caddy config, which is what clean URLs depend on, so there's no nginx config to write. Anything it can't translate is listed in the site's Routing tab.
A new Drupal site
The Drupal starter runs composer create-project drupal/recommended-project and creates a database. You finish setup in Drupal's browser installer at https://intranet.test, where the database details are the usual local ones:
- Database type: MySQL, MariaDB or equivalent
- Host:
127.0.0.1, port3306for the first server (Advanced options) - Username:
root, no password
Extra MySQL or MariaDB servers run on their own ports, shown in the Databases screen. If you'd rather skip the browser, Drush can install from the command line; see the steps below.
Drush and Composer on the right PHP
Drush is a per-project Composer dependency. Add it once, then run it through bothy site exec, which runs commands in the site folder with that site's PHP first on PATH:
bothy site exec intranet -- composer require drush/drush
bothy site exec intranet -- vendor/bin/drush status
bothy site exec intranet -- vendor/bin/drush cr
bothy site exec intranet -- vendor/bin/drush uli --uri=https://intranet.test
That matters because Drupal versions have firm PHP minimums (Drupal 11 needs PHP 8.3), and older client sites may need something earlier. Each Bothy site has its own PHP version and FPM pool, so bothy site php legacy 8.1 changes one site only. Per-site php.ini overrides (bothy site ini intranet memory_limit 512M) help with Composer-heavy updates and large imports. See PHP versions.
Config sync and the database
The standard loop after pulling changes is database updates, then config import, then a cache rebuild:
bothy site exec intranet -- vendor/bin/drush updb -y
bothy site exec intranet -- vendor/bin/drush cim -y
bothy site exec intranet -- vendor/bin/drush cr
Updates and config imports are exactly the steps you want an undo for. Take a snapshot first and restore if it goes wrong:
bothy db snapshot intranet
# …
bothy db restore intranet intranet-2026-09-27.sql.gz
Restore drops and recreates the database. phpMyAdmin is at phpmyadmin.test (bothy pma intranet) when you need to look at tables directly. More in MySQL and MariaDB.
Working on an existing Drupal site
Clone the repository, install dependencies and create the database in one go, then import a production dump. Imports accept .sql, .sql.gz and .zip and strip DEFINER clauses:
bothy site add client --git git@github.com:you/client.git --composer --db
bothy db import client ~/Downloads/client-prod.sql.gz
Then give the site local database credentials, usually in a git-ignored web/sites/default/settings.local.php, and add '^client.test$' to $settings['trusted_host_patterns']. The site's Git tab shows which config files changed after a drush cex, before you commit.
Email, caching and debugging
Drupal's default mail backend uses PHP's mail(), which Bothy wires to Mailpit for every site, so account emails and webform notifications land at mail.test. If you use an SMTP module, point it at 127.0.0.1 port 1025 with no authentication.
Redis and Memcached are available as add-ons, with the PHP extensions installed per version (bothy addon php-ext redis 8.3), for trying the Redis or Memcache contrib modules locally. Enable Node if your theme builds with npm.
When a page white-screens, the site's Logs tab follows its PHP and access logs live with a filter (or bothy logs intranet --kind php), and the slow log helps find the view that takes three seconds. bothy site xdebug intranet on turns on Xdebug for that site only, on port 9003.
Drupal with an AI assistant
Bothy's MCP server gives Claude, Codex, Cursor and other clients tools for sites, databases and raw SQL, logs and mail, and bothy site exec means an agent in a terminal runs Drush on the right PHP too. See AI development and the CLI.
Set it up in a minute
- 1Install Bothy
Open the app and let setup install PHP, MySQL, Caddy and dnsmasq. See installation.
- 2Create the site from the Drupal starter
Choose the Drupal starter when you add a new site in the app. It creates the project and a database; finish in the browser installer.
- 3Or install from the command line with Drush
Add Drush and run the installer against the site's database;
bothy site db intranetshows its name.bothy site exec intranet -- composer require drush/drush bothy site exec intranet -- vendor/bin/drush site:install standard --db-url=mysql://root:@127.0.0.1:3306/intranet -y
- 4Open it
bothy site open intranet # https://intranet.test
Questions
Yes. web/ is detected as the document root automatically, and you can pick another folder in the site's General tab.
You shouldn't need any. Bothy translates the RewriteRules in the site's .htaccess into its Caddy config, and lists anything it can't translate in the Routing tab.
Add it with Composer, then bothy site exec intranet -- vendor/bin/drush … runs it with the site's PHP version.
Bothy's own database servers are MySQL and MariaDB. Drupal also supports SQLite through PHP, but Bothy doesn't manage it for you.
$69 once, including every 1.x update. See pricing.