Generators
Partisan routes the entire make: family through a generator preset built from your package's composer.json, so every command produces files inside your package with your namespace.
Where files land
For a package named acme/widget with "Acme\\Widget\\": "src/":
| Command | Destination | Namespace |
|---|---|---|
make:model Invoice |
src/Models/Invoice.php |
Acme\Widget\Models |
make:command SyncInvoices |
src/Console/SyncInvoices.php |
Acme\Widget\Console |
make:migration create_invoices_table |
database/migrations/… |
— |
make:factory InvoiceFactory |
database/factories/… |
Acme\Widget\Database\Factories |
make:seeder InvoiceSeeder |
database/seeders/… |
Acme\Widget\Database\Seeders |
make:test InvoiceTest |
tests/Feature/… |
Acme\Widget\Tests\Feature |
make:filament-resource Invoice |
src/Filament/Resources/… |
Acme\Widget\Filament\Resources\… |
…and the rest of the suite: casts, controllers, events, jobs, listeners, mail, middleware, notifications, policies, providers, requests, rules, views, components, enums, interfaces, traits, and more. Filament generators are covered in detail in Filament plugins.
The wiring you'd normally do by hand
Generating the file is the easy part; partisan also takes care of the follow-up edits:
make:command registers the command
After generating, partisan offers to register the new command in your package's service provider (automatic under --no-interaction; opt out with --no-register). It inserts into an existing $this->commands([...]) or a spatie-style ->hasCommands([...]) block — adding the import, never duplicating an entry — and appends a fresh $this->commands([...]) block to boot() when the provider has neither.
make:model --factory wires the factory
Package factories don't resolve by Laravel's app conventions, so partisan wires them explicitly: the HasFactory docblock points at your Database\Factories namespace and a #[UseFactory(InvoiceFactory::class)] attribute is added to the model. Invoice::factory() resolves at runtime with no manual newFactory() method. If a future Laravel stub ships its own factory wiring, partisan detects it and only corrects the namespace.
make:model --fields writes the columns, casts, fillable and factory
Describe the columns once and the model, its migration and its factory come out matching each other instead of as empty stubs:
vendor/bin/partisan make:model Invoice --migration --factory \
--fields='number:string:unique,total:decimal(10,2)=0,is_paid:boolean=false,status:enum(draft,sent)=draft,notes:text:nullable,user_id:foreignId'
| File | What the spec fills in |
|---|---|
src/Models/Invoice.php |
$fillable with every column, casts() for the types that need one (total as decimal:2, is_paid as boolean), a user(): BelongsTo method |
database/migrations/…_create_invoices_table.php |
one line per field between id() and timestamps(): $table->decimal('total', 10, 2)->default(0), $table->foreignId('user_id')->constrained() |
database/factories/InvoiceFactory.php |
a definition() with a fake per type, fake()->unique() for unique columns, a fake by name for email, name, title, slug, url and phone, and a related factory for each foreign key |
The syntax is name:type[(args)][:modifier…][=default], comma-separated:
- Types are Blueprint column methods, so there is nothing new to learn:
string,text,integer,unsignedInteger,bigInteger,decimal,float,boolean,date,dateTime,timestamp,json,uuid,ulid,enum,foreignId,morphs,softDeletesand the rest. - Parentheses keep their Blueprint meaning:
string(100)is a length,decimal(8,2)precision and scale,enum(draft,sent)the allowed values. - Modifiers are bare words:
nullable,unique,index,unsigned,primary,fullText. =sets the default:capacity:unsignedInteger=10,active:boolean=true,status:enum(draft,sent)=draft.
make:migration --fields and make:factory --fields take the same spec on their own, so make:migration add_reference_to_invoices_table --table=invoices --fields=reference:string(40):nullable writes the column into the Schema::table block.
Relations
Foreign keys and morphs write the relation on the side that owns the column:
user_id:foreignIdadds$table->foreignId('user_id')->constrained(), auser(): BelongsTomethod and'user_id' => User::factory()in the factory.constrained()is the default;unconstrained,cascadeOnDelete,nullOnDeleteandrestrictOnDeleteare the foreign-key modifiers.author_id:foreignIdFor(User)names the related model when the column does not; the migration still writes aforeignId, constrained to the model's table.commentable:morphsadds the two columns to the migration and$fillable, and acommentable(): MorphTomethod.
The related class is looked up in your package's model namespace. A package cannot know the host application's classes, so User with no such class in the package is treated as the host app's user and resolved through config('auth.providers.users.model'), in the relation and in the factory (fn () => config('auth.providers.users.model')::factory()), the idiom Filament and Filament Teams use. A backslashed name (foreignIdFor(App\Models\Team)) is taken as is. Anything else is written in the package namespace, imported, and reported (unresolved[n] lines in agent mode, a warning otherwise) so you can point it at the host model or a config key. hasMany and belongsToMany live in files the generator does not write, so they stay yours.
make:test extends your base test case
Generated feature tests extend your package's own tests/TestCase.php when you have one, or Orchestra\Testbench\TestCase otherwise.
make:provider stays hands-off
The class is written into src/Providers; registering it in your package's provider chain is deliberately left to you — provider wiring is structural enough that you'll want it explicit.
Generating into the Workbench app instead
The standard Canvas presets remain available per command when you want a file in your Workbench demo app rather than the package itself:
vendor/bin/partisan make:model Demo --preset=workbench
Beyond generators
Because partisan wraps the Testbench CLI, everything Testbench can do works from the same binary — vendor/bin/partisan serve, migrate, route:list, workbench:install, and your package's own artisan commands (auto-registered from extra.laravel.providers — see Configuration).