Comparing two backup versions
modsx:diff has always compared your application against a version. Give it a second version and the application drops out of the comparison entirely:
php artisan modsx:diff Blog 0002 0004The version named first is the baseline in both forms, so modsx:diff Blog 0002 and modsx:diff Blog 0002 0004 ask the same question from the same starting point — only the other side moves. Swapping the two arguments gives the same comparison seen from the other end: what was added becomes what is gone.
The wording follows. Against the application, the useful frame is what a restore would do next:
Added (restore would delete)
Modified (restore would overwrite)
Removed (restore would bring back)
Between two versions no restore is in sight, so describing those numbers by an action nobody asked for would simply be untrue:
Added (only in 0004)
Modified (differs between the two)
Removed (only in 0002)
Your working tree is not read at all in this mode, so the answer is the same whatever state the application happens to be in. --summary and --json work here too; the JSON carries from and to in place of version, which is how a script tells the two modes apart by shape alone.
A manifest can no longer place files outside the project
modsx:import takes a version number and a list of paths out of a manifest that somebody else wrote, and checked neither.
A version of ../../.. and a path of ../../escaped each wrote outside the project root. Both were reproduced before being fixed, rather than assumed — and ZipArchive::extractTo() was verified not to be the way in, since it sanitises entry names itself.
The version is now validated in the one place it becomes a path, and a manifest path is refused if it escapes with .., is absolute, or carries a drive letter.
If you only ever import archives you exported yourself, none of this was reachable. It starts to matter the moment an archive arrives from anywhere else.
A generator's options no longer need --
php artisan modsx:make component blog.alert --view # now
php artisan modsx:make component blog.alert -- --view # beforeAnything else used to be refused with Symfony's The "--view" option does not exist — a message that says nothing about the separator you forgot. Which is easy to forget: --resource, -m, --view and --api come up constantly.
modsx:make answers to one option of its own, --dry-run. It now sorts the raw tokens itself and passes everything else to the generator, which is also why a generator from any package needs nothing declared. Writing -- still works, and remains the way to reach a generator option that collides with ours.
The cost, stated plainly: a misspelling of --dry-run is no longer caught by Symfony. It is checked for by name instead, and answered with Did you mean --dry-run? rather than forwarded to a generator that would blame itself.
An exported archive is named after its module
Blog-0002.zip, not 0002.zip — which said nothing at all once the file had been moved or mailed anywhere.
modsx:prune removes both names, so an archive written under the old one is still swept along with the version it belongs to, rather than left behind for good.
modsx:backuplist counts files and archived migrations
A version has held both since 0.3.0, so listing its directories alone described less than half of what was in it.
Version Created Directories Files Archived Comment
0002 2026-09-01T21:14:07 3 2 1 before the rewrite
Also
modsx:backupnames the files it did find when a module has files but no directories, instead of reporting the module as missing. It still refuses: a module is a set of directories, and the unclaimed-file check rests on that.public/buildjoins the defaultexcludelist, so a compiled asset bundle is not walked while looking for a module's directories.- CI rebuilds
docs/and fails if it differs from what is committed, and checks that the two READMEs keep the same headings, the same number of code blocks and the same number of table rows.
Upgrading
While Modsx is on 0.x, this release will not arrive with a plain composer update. Ask for it by name:
composer require --dev synerdy/modsx:^0.7Composer treats anything below 1.0.0 with pre-release caution: there, ^0.6.1 means >=0.6.1 <0.7.0, putting the minor where the major normally sits. So composer update stays on the minor you installed — by design, not by accident — and composer why-not synerdy/modsx 0.7.0 will tell you as much.
The one thing to check before upgrading: if anything of yours refers to an exported archive by filename, it is Blog-0002.zip now.