Add, trace and remove modules
Adding is one command and removing is three, because removal edits grim.json before it asks anything and never touches the lock. A commit between the two halves is what makes every step reversible.
Before you start
Commit what you are working on. Of everything these commands write, git tracks two files, grim.json and grim.lock. With a clean tree, git diff on those two is the full record of a change, and git checkout is the way back.
Bring the stack up. Adding a module ends with the autoloader and the migrations in the app container. With the container down both are skipped, and the steps still show a tick.
$ git status --short
$ grim upThe ritual, in order
Seven steps. The first and the third only read. The second and the fifth are the ones that write, and the commit of step four stands between them on purpose.
Find the module
Look before you build.
grim searchmatches one word against names and descriptions in the catalogue, andgrim module:inforeads a single entry from GitHub.$ grim search orders $ grim module:info cart-orders --readmeThe
Namecolumn holds the short name, and that is what every later command takes. Read two rows of the entry:Archivedhas to sayno, andLatest releaseis the newest release anywhere, which can be on a train ahead of yours. With no word in mind,grim list:availableprints the whole catalogue.Add it
grim requirepicks the newest release on the train ingrim.lock, installs the module with everything it requires, and writesgrim.jsonand the lock.$ grim require cart-orders Requiring module: cart-orders ✓ [1/7] Resolving dependencies (2s) ✓ [2/7] Installing modules (6s) … ✓ [7/7] Running migrations (3s) $ git diff grim.json grim.lockThe
Packages addedtable under the steps names only what you asked for. The diff names everything.grim.jsongains one line,"cart-orders": "~2.4". The lock gains the module and each of its dependencies. The whole project is resolved again on the train, so a module you already had can move to a newer patch release in the same run. That shows in the diff too.Trace what came along
A module you did not name is now in
src/.grim whyprints the chain fromgrim.jsondown to it.$ grim why payments payments v2.4.0 shop (project) └─ cart-orders (grim.json) └─ payments (requires)Only the module you named was switched on in
storage/config/modules-enabled.php. A dependency is installed and locked, and it is not in that list. When the app needs it switched on, add its line by hand, in the shape of the ones already there:Modules\Payments\PaymentsProvider::class,.Test, then commit the pair
grim.jsonsays what you asked for andgrim.locksays what you got. They belong in one commit, oncegrim testagrees.$ grim test $ git add grim.json grim.lock $ git commit -m "feat: add cart-orders"This commit is also the safety net of the next step.
Remove a module
Ask first who else needs it, then let
grim removedrop it. Skip its--dry-run: the dry run looks for orphans without taking the module out first, so it lists less than the real run deletes.$ grim why cart-orders $ grim remove cart-orders ✓ Removed cart-orders from grim.json Orphan modules (not required by grim.json): • cart-orders (1.2 MB) • payments (412.0 KB) Delete 2 orphan module(s)? [y/N]grim.jsonis already saved when the question appears. Read the list: it holds every module nothing reaches any more, including leftovers that are older than this removal. Answeryand the directories undersrc/go, together with their lines inmodules-enabled.php. Answer no and the edit ofgrim.jsonstays.git checkout grim.jsontakes it back.cart-orders stays installed — still reachable transitivelymeans another module requires it. It leftgrim.jsonand stays on disk, which is correct.An installed module is a git checkout, and edits inside it exist nowhere else.
--forceskips the question and the check for uncommitted changes, and the work is deleted with the directory.Sweep what is left
grim pruneis the same cleanup without the edit. Run its dry run after a removal you answered no to, after a merge that dropped a line fromgrim.json, or simply to see that nothing is left.$ grim prune --dry-run No orphan modules — every installed module is reachable from grim.json.Unlike the dry run of
remove, this one is exact: it readsgrim.jsonas it is on disk. When it lists modules,grim prunewithout the flag asks and deletes.Write the lock again, then commit
Neither
removenorprunetouchesgrim.lock, so it still names what you deleted.grim installresolvesgrim.jsonagain and writes it.--no-composerkeeps that to files and lock.$ grim install --no-composer $ grim test $ git add grim.json grim.lock $ git commit -m "chore: remove cart-orders"git diff grim.json grim.lockbefore the commit shows the same two files, this time with lines leaving.
What you have now
A grim.json that lists what the project asks for, a lock that matches it, and a src/ with nothing in it that the two do not explain.
"requires": {
"cart": "~2.4",
"cart-orders": "~2.4"
}The database is the exception. Removing a module deletes its code and leaves the tables its migrations created. Drop them yourself when the data is no longer wanted. A module fix on the same train is Take one module fix mid-train.
When it does not work
“Module 'cart-orders' has no available versions (required by grim.json)”
The module has no release on the project's train. Nothing was written. Wait for its release on your train, or move the project with Move a project to a new train when the module is only released ahead of you.
“1 package cannot be installed:”
The run stops before anything is cloned, and the lines below say why: archived, or not visible to your GitHub account. Nothing was installed. is meant literally. An archived module that became part of core is already in the project.
A class of the new module is not found
The stack was down while you ran grim require, so the autoloader and the migrations were skipped behind a green tick. Catch up by hand.
$ grim up
$ grim composer dump-autoload
$ grim artisan migrate“'payments' is not listed in grim.json requires.”
You can only remove what you required. payments is somebody's dependency, and grim why payments shows whose. It goes when the module that needs it goes.
“⚠ 1 module has uncommitted changes that would be lost.”
The clean orphans are deleted and the edited one stays. Commit and push from inside src/<Module>/, then run grim prune.
Next recipe
First deploy to a fresh VPS
Take a bare Ubuntu or Debian server and a project that runs on your machine, and end with the project live on its own domain over HTTPS.
Read itSpells used here
grim search
Search the shelves
Find modules and themes in the catalogue by a word in their name or description, before you build one again.
grim module:info
Read a module's entry
Show a module's description, latest release, last push and archived status straight from GitHub, with its README on request.
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.
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 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 prune
Clear what nothing asks for
Delete the modules under src/ that can no longer be reached from the requires in grim.json.
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.