Clear what nothing asks for
$ grim prune --dry-run
grim.json was edited by hand, or a merge dropped a line from it, and the module it named is still sitting in src/. It may still be enabled in the app, though nothing asks for it any more. grim prune finds those leftovers and deletes them.
You rarely need to call it yourself. grim remove ends with the same cleanup, and grim install offers it when it notices orphans.
Usage
$ grim prune --dry-run # list the orphans, delete nothing
$ grim prune # list them, then ask
$ grim prune --force # no prompt, local changes discardedRun it from the project root, next to grim.json. It needs no network and no login: everything it reads is on disk.
Arguments and options
Remove installed modules that are no longer required by grim.json
Usage
grim prune [--dry-run] [-f|--force] [--no-autoload-dump]Options
| Option | Description |
|---|---|
--dry-run |
List orphan modules without deleting anything |
-f, --force |
Skip confirmation prompt and dirty-module warning; list committed local modules in grim.json "local" without asking |
--no-autoload-dump |
Skip composer dump-autoload after removal |
What it actually does
- Reads what is installed. The
module.jsonof every directory undersrc/. Modules that belong to core are left out, so they can never be listed. - Walks the requirements. From the
requiresand thelocalofgrim.json, through therequiresof each installed module. Whatever the walk does not reach is an orphan, but only when agrim.lockonce named it: the current one or any committed one. A module that was never in a lock was never a unit, and prune does not delete it. - Lists the orphans with their size on disk, and marks those with uncommitted changes. With none it prints
No orphan modules — every installed module is reachable from grim.json.and stops. - Asks.
Delete 2 orphan module(s)? [y/N], with no as the default. - Deletes. Each orphan's directory under
src/, and its line instorage/config/modules-enabled.php. - Runs
composer dump-autoload -oin theappcontainer, unless--no-autoload-dump. - Runs
pnpm installon your machine when a deleted module carried its ownpackage.json: it leaves the pnpm workspace. It says✓ pnpm install — commit pnpm-lock.yaml with grim.json,unchanged, nothing to commit, or what to run when pnpm is missing or the install failed. A project that keeps no pnpm lock is left alone. The cleanup thatgrim installandgrim updateoffer skips this step: when it deletes a module with apackage.json, runpnpm installyourself.
A local module, one made with grim make:module --no-repo, is never an orphan: grim.json lists it under local. A module no lock ever named and local does not list is never deleted either. Prune names it in one of two ways:
ℹ Local module not listed in grim.json "local": committed in the instance repository,module.jsonof typemodule, no.github/workflows/validate.yml. Most likely a local module from beforelocalexisted. In a terminal prune asksAdd them to grim.json "local"? [Y/n];--forceadds without asking;--dry-run,-nand CI only name it. Adding also writesconfig/modules-available.phpagain. Commit both files.ℹ Not a unit and not listed in grim.json "local": untracked, outside git, or a module repository in the making (grim make:modulewithout--no-repo, beforegrim require). Commit and list it, require it, or delete the directory yourself. A local module made by an oldergrim make:module --no-repostill carries that.github/: delete it, commit, and the next prune offers the module forlocal.
Themes are not looked at. A theme taken out of grim.json stays in resources/themes/ until you delete the directory.
Pitfalls
Modules with local changes are skipped
⚠ 1 module has uncommitted changes that would be lost. git status of the project shows changes under that module's directory, and those exist nowhere else. Prune deletes the clean orphans and leaves the edited one. Commit or discard the changes, then run it again; a committed module stays in the project's history after the delete.
--force skips both the prompt and the check for uncommitted changes. Work inside src/<Module>/ that was never pushed is deleted with the directory.
The lock and the database stay as they were
Prune does not rewrite grim.lock, and it does not roll back the migrations of what it deletes. The lock is written again by the next grim install or grim update.
After it finishes
Run the suite: a module that was used without being required shows up here as a missing class. If that happens, grim require brings it back, this time with an entry in grim.json.
$ grim testRelated spells
grim remove
Banish a module
Drop a module from grim.json and delete it from src/ together with every installed module nothing requires any more.
grim why
Ask why a module is here
Show the chain of requirements that leads from grim.json to an installed module, and what that module requires in turn.
grim install
Assemble the whole project
Turn grim.json into a working project by fetching core, every module and theme, writing grim.lock, building the image and starting the stack.
grim require
Summon a module or theme
Add a module or theme to grim.json, install it with everything it depends on, and rewrite grim.lock, all inside the train the project is on.