Commands
Every Artisan command mod registers, the options each one takes, and the folder each one writes to in each built-in layout. php artisan mod:list shows the file types, templates and scaffolds your layout has.
Placement Options
Every generator takes these, in addition to its own options:
| Option | Takes | Example |
|---|---|---|
--in | every value of the layout's placeholders, in order, separated by /; a value spanning folders separates them with . | --in=Knowledge/IndexDocument |
--<placeholder> | one placeholder's value, one option per placeholder the command's folder uses | --module=Knowledge, --feature=Knowledge --slice=IndexDocument, --domain=Knowledge.Search |
<values>: prefix on the name | the same values as --in, before a colon | Knowledge:Document, Knowledge/IndexDocument:Handler |
The laravel layout takes no placement. A placeholder option is left out when the Laravel command already has an option of that name; see When an Option Name Is Already Taken.
A value that differs from an existing group only by case, such as knowledge for Knowledge, uses that group and says so. A near miss, such as Knowledg, asks which you meant in a terminal; with --no-interaction it creates the new group. A new value creates its folder and says so. New and Misspelled Modules shows the output.
Before writing, a generator checks every file it is about to write, related files included. When one exists, it prints an error and writes nothing. --force overwrites, on the commands that list it below.
MCP Generator Commands
Since 0.5 (unreleased). These file types are added to modules and ddd when laravel/mcp is installed. Each command runs the corresponding Laravel MCP generator and inherits that installed package version’s arguments and options, plus mod’s placement and preview options. See MCP File Types for executable examples and custom placement.
| Command | Runs | modules folder | ddd application folder |
|---|---|---|---|
mod:mcp-server | make:mcp-server | @module/Mcp/Servers | app/Modules/{domain}/Mcp/Servers |
mod:mcp-tool | make:mcp-tool | @module/Mcp/Tools | app/Modules/{domain}/Mcp/Tools |
mod:mcp-resource | make:mcp-resource | @module/Mcp/Resources | app/Modules/{domain}/Mcp/Resources |
mod:mcp-prompt | make:mcp-prompt | @module/Mcp/Prompts | app/Modules/{domain}/Mcp/Prompts |
The native make:mcp-* commands keep writing to their usual folders. mod:mcp-app-resource is not added: its native generator also writes a companion view. General delegation to arbitrary package generators is tracked separately in mod#87.
Generator Commands
Each command runs the Laravel command in the second column and takes that command's options, listed in the last column. The options come from Laravel, so they follow your Laravel version; these are Laravel 13's. Commands marked "none" have no Laravel generator: they write an empty class, or the file type's stub.
| Command | Runs | Layouts | Options |
|---|---|---|---|
mod:action | none | modules, ddd | --force |
mod:cast | make:cast | all | --inbound, --force |
mod:channel | make:channel | all | --force |
mod:class | make:class | all | --invokable, --force |
mod:command | make:command | all | --command, --test, --pest, --phpunit, --force |
mod:config | make:config | laravel, type-first | --force |
mod:controller | make:controller | all | --api, --type, --invokable, --model, --parent, --resource, --requests, --singleton, --creatable, --test, --pest, --phpunit, --force |
mod:dto | none | modules, ddd | --force |
mod:enum | make:enum | all | --string, --int, --force |
mod:event | make:event | all | --force |
mod:exception | make:exception | all | --render, --report, --force |
mod:factory | make:factory | all | --model |
mod:handler | none | slices | --force |
mod:interface | make:interface | all | --force |
mod:job | make:job | all | --sync, --batched, --test, --pest, --phpunit, --force |
mod:job-middleware | make:job-middleware | all | --test, --pest, --phpunit, --force |
mod:listener | make:listener | all | --event, --queued, --test, --pest, --phpunit, --force |
mod:mail | make:mail | all | --markdown, --view, --test, --pest, --phpunit, --force |
mod:message | none | slices | --force |
mod:middleware | make:middleware | all | --test, --pest, --phpunit |
mod:migration | make:migration | all | --create, --table, --fullpath |
mod:model | make:model | all | --all, --controller, --factory, --migration, --morph-pivot, --policy, --seed, --pivot, --resource, --api, --requests, --test, --pest, --phpunit, --force |
mod:notification | make:notification | all | --markdown, --test, --pest, --phpunit, --force |
mod:observer | make:observer | all | --model, --force |
mod:policy | make:policy | all | --model, --guard, --force |
mod:provider | make:provider | all | --force. In ddd, the provider is named as given, with no ServiceProvider suffix |
mod:query | none | modules, features, slices, type-first | --force |
mod:request | make:request | all | --force |
mod:resource | make:resource | all | --json-api, --collection, --force |
mod:rule | make:rule | all | --implicit, --force |
mod:scope | make:scope | all | --force |
mod:seeder | make:seeder | all | none |
mod:test | make:test | all | --unit, --pest, --phpunit, --force |
mod:trait | make:trait | all | --force |
mod:validator | none | features, slices | --force |
mod:value-object | none | modules, ddd | --force |
mod:view-model | none | modules, ddd | --force |
mod:migrationplaces migrations from the layout, so it exits with an error for--pathand--realpath. Use--ininstead.mod:dto,mod:view-model,mod:value-objectandmod:actionstart from starter stubs, and the firstmod:dtoormod:view-modelwrites its base class.mod:model's related-file options (--factory,--migration,--seed,--policy,--controller,--requests,--all) write each file in the same group.
Aliases
| Command | Aliases |
|---|---|
mod:dto | mod:data in modules and ddd; mod:data-transfer-object in ddd |
mod:value-object | mod:value |
Every hyphenated command or alias also works without the dash: mod:viewmodel, mod:valueobject, mod:jobmiddleware, mod:datatransferobject. When that name is already a command or alias, the existing one keeps it. php artisan list mod shows each command's aliases in brackets:
mod:value-object [mod:value|mod:valueobject] Create a new value object classCommands for Your Own File Types
A file type you add with generates() gets mod:<id>, or the name given in command:, plus any aliases:, each also without the dash: generates('api-resource', ...) answers to mod:api-resource and mod:apiresource. Without a Laravel generator, it takes --force and the placement options.
Commands From Another Layout
A built-in command your layout doesn't have exits with an error naming the layouts that have it:
php artisan mod:handler Knowledge:Thing ERROR mod:handler is not a command of the modules layout. The slices layout has it.
To add it, declare the file type in a service provider: Mod::layout('modules')->generates('handler', in: '<folder>'). Or switch layouts in config/mod.php.Customizing a built-in layout shows the generates() line.
Where Each Command Writes
Folders below each layout's group folder:
| Layout | Group folder |
|---|---|
modules | app/Modules/<Module> |
features | app/Features/<Feature> |
slices | app/<Feature>, and app/<Feature>/<Slice> for a slice's classes |
ddd | src/Domain/<Domain> |
| Command | modules | features | slices | ddd |
|---|---|---|---|---|
mod:action | Actions | Actions | ||
mod:cast | Casts | Casts | Casts | Casts |
mod:channel | Channels | Broadcasting | Broadcasting | Channels |
mod:class, mod:interface, mod:trait | the group folder | the group folder | the group folder | the group folder |
mod:command | Console | Console/Commands | Console/Commands | Commands |
mod:controller | Http/Controllers | Http/Controllers | Http/Controllers | app/Modules/<Domain>/Controllers |
mod:dto | Data | Data | ||
mod:enum | Enums | Enums | Enums | Enums |
mod:event | Events | Events | Events | Events |
mod:exception | Exceptions | Exceptions | Exceptions | Exceptions |
mod:factory | Database/Factories | Database/Factories | Database/Factories | Database/Factories |
mod:handler | <Slice>/Handler.php | |||
mod:job | Jobs | Jobs | Jobs | Jobs |
mod:job-middleware | Jobs/Middleware | Jobs/Middleware | Jobs/Middleware | Jobs/Middleware |
mod:listener | Listeners | Listeners | Listeners | Listeners |
mod:mail | Mail | Mail | Mail | Mail |
mod:message | <Slice>/Command.php | |||
mod:middleware | Http/Middleware | Http/Middleware | Http/Middleware | app/Modules/<Domain>/Middleware |
mod:migration | Database/Migrations | Database/Migrations | Database/Migrations | Database/Migrations |
mod:model | Models | Models | Models | Models |
mod:notification | Notifications | Notifications | Notifications | Notifications |
mod:observer | Observers | Observers | Observers | Observers |
mod:policy | Policies | Policies | Policies | Policies |
mod:provider | Providers | Providers | Providers | Providers |
mod:query | Queries | Queries | <Slice>/Query.php | |
mod:request | Http/Requests | Http/Requests | <Slice>/Http/Requests/Request.php | app/Modules/<Domain>/Requests |
mod:resource | Http/Resources | Http/Resources | Http/Resources | Resources |
mod:rule | Rules | Rules | Rules | Rules |
mod:scope | Scopes | Scopes | Scopes | Scopes |
mod:seeder | Database/Seeders | Database/Seeders | Database/Seeders | Database/Seeders |
mod:test | tests/Feature/Modules/<Module> | tests/Feature/<Feature> | tests/Feature/<Feature>/<Slice> | tests/Feature/<Domain> |
mod:validator | Validation | <Slice>/Validator.php | ||
mod:value-object | ValueObjects | ValueObjects | ||
mod:view-model | ViewModels | ViewModels |
- The
laravellayout writes every file where the matchingmake:*command does.type-firstuses the same folders with an optional sub-folder for the feature, such asapp/Models/Knowledgeordatabase/factories/Knowledge, and addsmod:query, which writes toapp/Queries/<Feature>. - A slice's classes have fixed names, so the name can be left out:
mod:handler --in=Knowledge/IndexDocumentwritesapp/Knowledge/IndexDocument/Handler.php. A different name is not used, and the command says so. Inslices,mod:testtakes the slice as an optional second value. mod:test --unitwrites totests/Unitinstead oftests/Feature.- In
featuresandslices,mod:commandwithout a feature writes toapp/Console/Commands. - Class names take the file type's suffix:
Controller,Request,Policy,Factory,Seeder, andServiceProviderfor providers in every layout butddd. Inddd, a provider is named as given:mod:provider Knowledge:Knowledgewritessrc/Domain/Knowledge/Providers/Knowledge.php, andKnowledge:KnowledgeServiceProviderwritesKnowledgeServiceProvider.php.
Writing Base Classes
| Command | Does |
|---|---|
mod:bases | Writes every generated base class the layout can use that is missing, whether or not a class extends it yet. It never overwrites one, and takes no options |
php artisan mod:bases INFO Created base class App\Support\Data\DataTransferObject [app/Support/Data/DataTransferObject.php].
INFO Created base class App\Support\ViewModels\ViewModel [app/Support/ViewModels/ViewModel.php].When every base exists, it prints Every base class already exists. In a layout whose file types extend no generated base, such as laravel, it prints No file type in this layout extends a generated base class. A configured base or an installed package means there is no base to write. It is registered with the mod:* commands.
Discovery Commands
| Command | Does | Also run by |
|---|---|---|
mod:cache | Scans the layout and caches the discovered providers, commands, listeners, subscribers and migration folders | php artisan optimize |
mod:clear | Removes the discovery cache file | php artisan optimize:clear |
php artisan mod:cache INFO Discovery cached in [bootstrap/cache/mod-discovery.php]: 1 providers, 0 commands, 1 listeners, 0 subscribers, 2 directories, 5 rejected.
Rejected files were found but not registered: 5 placed by no file type (helpers and plain classes; nothing to do). Run with -v to list them.The second line counts the files it found but didn't register, grouped by reason. php artisan mod:cache -v lists each rejected file with its reason; Caching Discovery in Production explains each reason.
Both are registered only while the mod:* commands and discovery are both on. Caching Discovery in Production covers when the cache is used.
Creating Templates
mod:template [type] [path] creates a generator template:
php artisan mod:template tool
php artisan mod:template dto @module/Data/linksWith no arguments, choose a starting type and name in prompts. One argument names a class template; two arguments are the starting type and the name/path. A type alone therefore names a class template: mod:template job can collide with the built-in command. Custom generators covers starting types, paths, extraction and prompts.
| Option | Does |
|---|---|
--from[=class-or-file] | Extracts namespace and declared-name tokens without loading source PHP; a bare option opens search |
--into=path | Supplies the extraction destination |
--force | Overwrites a template |
Without interaction, extraction without --into uses the source-folder suggestion and kebab-case name. Other missing answers name the flag or command form that resolves them.
Inspecting the Layout
php artisan mod:list
php artisan mod:list -v
php artisan mod:list --type=model
php artisan mod:list --jsonmod:list counts discovered factories and policies alongside providers, commands, listeners, subscribers and directories. -v adds aliases, stubs, bases, relations and discovered classes, including factory and policy targets. --type=<id> shows every detail for one file type. JSON root keys, in output order, are layout, extends, path, token, groups, types, templates, scaffolds, discovery, views, translations, package_pages, frontend_owners, assets, frontend, stack, wiring, frontend_notices, frontend_wiring, routes, connections, rename. The inventory schema describes required fields and additive keys. Scaffold tree nodes expose children and reference metadata. Invalid config exits 1; --json prints an error object. An unknown --type also exits 1 with guidance.
Inventory Fields Added in 0.6
package_pages lists registered package namespaces and directories; frontend_owners records resolved paths, page names, view namespaces and aliases for layout and mounted-root owners. assets describes static patterns, expanded executable entries, their existence and wiring status. frontend_wiring records explicit package wiring, and frontend_notices lists package frontend declarations that were skipped, each with code, path and message. connections rows contain group, connection and declared. stack adds Svelte and Livewire detection. Package route rows use kind: "package" and loaded_by: "Mod::routes" after loading.
Scaffold items expose vendor, name, id, command, provider source, Composer package when known, overrides and structured notices. mod:list --vendor=acme filters scaffold items and problems in text and JSON. Consumers should accept additive fields; the schema gives their complete shapes.
Registering Autoload Mappings
mod:autoload adds missing Composer PSR-4 entries for the active layout and reloads Composer. Existing exact or parent mappings, including autoload-dev, count as coverage:
php artisan mod:autoload --dry-run
php artisan mod:autoload --no-dump
php artisan mod:autoload| Option | Does |
|---|---|
--dry-run | Previews missing mappings without writing or running Composer |
--no-dump | Writes mappings without running Composer |
--namespace=<namespace> | Supplies the namespace for a moved group outside the mounted roots |
A moved path outside the roots prompts for a namespace, defaulting to its folder name (Areas\). Without a terminal, it uses and announces that default. A conflicting mapping exits 1 without writing; fix the mapping in composer.json and run again. When every mapping is configured, the command says so and suggests composer dump-autoload if classes do not load. A failed Composer run, including a missing executable, exits 1, keeps the written entries and names composer dump-autoload to run manually.
Scaffold Commands
A registered recipe gets mod:<scaffold>, with placement and question options, --skip-existing and --force. A child gets mod:<root>.<part> and takes the root's name and a child value. Scaffolds covers planning, collision choices and growing clusters.
Frontend Commands
| Command | Behaviour | Options |
|---|---|---|
mod:page <group>:<name> | Generates a minimal detected-stack Inertia page | --force, placement, preview |
mod:view <group>:<dotted-name> | Generates a namespaced Blade view | --extension, --test, --pest, --phpunit, --force, placement, preview |
mod:component <group>:<name> | Generates a Blade class and view | --view for anonymous, --inline, --path, test/style flags, --force, placement, preview |
Vue, React and Svelte pages follow the detected stack; components use generator templates. Grouped mod:mail --markdown / --view and mod:notification --markdown place and qualify companion views. All planned collisions are checked before a class is written.
Route Commands
| Command | Behaviour | Options |
|---|---|---|
mod:routes <group> | Generates web route files | --api, --console, --force, preview |
mod:route-registrar <group> | Generates a RegistersRoutes class | --force, preview |
Load the files through Mod::routes(). Route generators prompt about replacement in a terminal; without one, the error names --force.
Installing Inertia
php artisan mod:install inertia --dry-run --json
php artisan mod:install inertia --no-interaction--dry-run previews edits without prompting; --json requires --dry-run. --no-interaction applies recognized wiring. A custom resolver or configuration prints manual instructions and exits 0 without edits. Declining the preview changes nothing. A repeated installation prints Already wired.
Installing Assets
php artisan mod:install assets --dry-run --json
php artisan mod:install assets --no-interactionThis synchronises declared static patterns and executable entries without requiring Inertia. See Static assets and executable entries for Laravel Vite plugin requirements and loading examples.
Previewing Generator Plans
Commands that write files support --dry-run; add --json for the machine plan. Required questions use flags/defaults, with missing answers reported in warnings. Read would_write rather than the exit code alone. Cache maintenance has no file preview. Agents describes the plan and inventory schemas.
Renaming and recovery
mod:rename <old> <new> renames an explicitly selected recipe-owned cluster through its compiled layout. See Renaming and moving before execution.
| Option | Behaviour |
|---|---|
--scaffold=<recipe> | Selects the effective recipe; mandatory for ordinary planning, or selected interactively |
| Recipe question/part flags | Supply the complete historical answers; repeated list flags include grown parts |
--answer=<qualified-key=JSON> | Supplies nested/reserved answers using original part paths |
--dry-run | Read-only preview; no prompts, writes, staging or journal |
--json | Machine plan; requires --dry-run |
--table-migration | Selects complete reversible migration candidates when exact inference/planning is available; never executes them |
--yes | Accepts final confirmation after the fresh plan |
--no-interaction | Requires explicit decisions; use with --yes for approved execution |
--recover | Recovers the worktree journal without cluster arguments or recipe/table flags |
--recover --dry-run --json inspects without restoring. --recover --yes --no-interaction restores after review and refuses conflicting outside changes. Journals live in the actual worktree Git directory under mod-rename/. Ordinary execution requires a clean Git tree/index and a configured target. The staged result is never committed. There is no --force, overwrite, automatic stash or --apply-plan.
Structured Plan Warnings
Every --dry-run --json warning keeps file, line and message, and adds code and an object data. missing_placement provides file_type, dimension, accepted options and available group choices. generation_refused reports another blocking refusal; advisory is non-blocking; routes_not_loaded reminds you to wire routes. Codes and data are additive: consumers should tolerate new codes and fields, and display message for people. Missing placement messages name the running command's option, --in and the Group:Name short form.
The plan schema defines the warning envelope. Vendor reconciliation notices use vendor_scaffold_overridden, vendor_prefix_shadowed, vendor_scaffold_conflict and vendor_required; see Shipping scaffolds.