WordPress only executes single PHP files placed directly in wp-content/mu-plugins/. It does not load plugins that live in subfolders, unlike normal plugins in wp-content/plugins/.
This small must-use (MU) package bridges that gap: it discovers MU plugins that live in subdirectories, loads their main bootstrap file, and lists them neatly under the loader entry in Plugins → Must-Use in the admin.
- Scans
mu-pluginswith WordPress’s ownget_plugins()so discovery stays aligned with core behaviour. - Skips loose PHP files at the root of
mu-pluginsand skips themu-loaderfolder itself, thenrequire_onces each detected plugin’s bootstrap file. - During installation (
WP_INSTALLING), it does nothing so core install/upgrade is not disturbed. - In the admin, each loaded subdirectory plugin appears as an indented row under the main MU loader line for easier reading.
The project was originally created and published as wemakecustom/wp-mu-loader by WeMakeCustom. BeAPI now maintains this fork as beapi/wp-mu-loader. Thanks to WeMakeCustom for the original work.
Further background:
- Original idea (gist) — Sébastien Lavoie
- Blog post explaining MU subdirectories
WordPress does not expose hooks on get_mu_plugins(), which is why a dedicated loader like this one is still useful.
Require the package (maintained under the BeAPI vendor name):
{
"require": {
"beapi/wp-mu-loader": "^1.0"
}
}Then run composer install so the package is installed under mu-plugins/mu-loader/ (see composer.json extra.installer-name in this repo).
- Clone or extract this repository into
wp-content/mu-plugins/mu-loader/. - Copy or symlink
mu-require.phpintowp-content/mu-plugins/so WordPress loads the loader.
Onlymu-require.phpmust sit at the root ofmu-plugins; the rest stays in themu-loaderfolder.
If mu-loader/mu-loader.php is missing (e.g. incomplete install), an admin notice suggests running composer install.
If you ship a must-use plugin that should install into a folder under mu-plugins, use Composer’s wordpress-muplugin type and optionally set extra.installer-name:
{
"name": "my-vendor/my-plugin",
"type": "wordpress-muplugin",
"keywords": ["wordpress", "plugins"],
"license": "GPL-2.0-or-later",
"require": {
"composer/installers": "^1.0 || ^2.0"
},
"extra": {
"installer-name": "my-plugin"
}
}extra.installer-name is optional; use it when you want the directory name under mu-plugins to differ from the Composer package name (this repo uses mu-loader for beapi/wp-mu-loader).
keywords and license are optional but recommended for published packages.
If WordPress is not at the project root, point composer/installers to your real wp-content paths, for example:
{
"extra": {
"installer-paths": {
"htdocs/wp-content/plugins/{$name}/": ["type:wordpress-plugin"],
"htdocs/wp-content/mu-plugins/{$name}/": ["type:wordpress-muplugin"],
"htdocs/wp-content/themes/{$name}/": ["type:wordpress-theme"]
}
}
}Adjust the htdocs/... segments to match your layout.
Release notes are in CHANGELOG.md. Tagged versions are listed on GitHub.
GPL-2.0-or-later (see composer.json and plugin header in mu-require.php).