| name | package-dev |
| metadata | {"compatible_agents":["claude-code"],"tags":["laravel","php","package","sdk","composer","packagist"]} |
| description | Complete Laravel package development skill — scaffolds package directory structure with src, config, migrations, tests, README, and CHANGELOG; generates service providers, facades, config publishing patterns; sets up Pest test suites with Orchestra Testbench integration; manages release workflows including version bumps, changelog updates, git tags, and Packagist publishing; generates professional README files with badges, installation instructions, usage examples, testing commands, and changelog sections. Use this skill whenever the user asks to create a Laravel package, scaffold a PHP package, set up a Composer library, generate a service provider, add facade support, configure Testbench tests, prepare a package release, write a package README, publish to Packagist, or manage package versioning — including: "create a new Laravel package", "scaffold package structure", "set up package tests", "prepare a release", "generate package README", "add a facade to my package", "configure Testbench", "publish my package", "buat package Laravel baru", "scaffold struktur package", "sediakan test untuk package", "sediakan release", "jana README package", "tambah facade", "konfigurasi Testbench", "terbitkan package ke Packagist", "uruskan versioning package", "upgrade Laravel version", "bump PHP version constraint", "update package dependencies", "naik taraf versi Laravel", "kemaskini versi PHP", or "upgrade dependencies package".
|
Package Development Skill
Scaffold, test, document, and release production-quality Laravel/PHP packages — from initial
directory structure through Packagist publishing. Follows Laravel ecosystem conventions and
integrates with Orchestra Testbench for package testing.
Command Reference
| Command | Description |
|---|
/package scaffold | Generate complete package directory structure with all boilerplate files |
/package test | Set up Pest test suite with Orchestra Testbench integration |
/package release | Run release checklist: version bump, changelog, git tag, Packagist |
/package readme | Generate professional README with badges, installation, usage, and testing sections |
/package upgrade | Upgrade PHP/Laravel version constraints and dependencies |
1. /package scaffold — Generate Package Structure
Step 1: Gather Package Information
Ask the user for:
- Vendor name — always ask, default:
cleaniquecoders
- Package name — kebab-case, all lowercase (e.g.
laravel-helper, profile)
- Package type — Laravel package or pure PHP package
- Package description (one-liner for composer.json)
- PHP minimum version (default:
^8.4)
- Laravel version constraint (default:
^12.0, Laravel packages only)
- Namespace (default: derived from vendor/package, e.g.
CleaniqueCoders\Profile)
- Features to include (config, migrations, views, routes, commands — pick applicable ones)
If the user already provided context, extract what you can and only ask for what is missing.
Skeleton Templates
Use Spatie's skeleton templates to scaffold the package:
After cloning, run the skeleton's configure script to replace placeholders with the actual vendor name, package name, namespace, and author details.
Step 2: Generate Directory Structure
Create the following structure:
packages/vendor/package-name/
├── src/
│ ├── PackageNameServiceProvider.php
│ ├── Facades/
│ │ └── PackageName.php
│ ├── Actions/
│ ├── Concerns/
│ └── Contracts/
├── config/
│ └── package-name.php
├── database/
│ ├── factories/
│ └── migrations/
├── resources/
│ └── views/
├── routes/
│ └── web.php
├── tests/
│ ├── Pest.php
│ ├── TestCase.php
│ └── Feature/
├── stubs/
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── composer.json
└── phpunit.xml
Only include directories for features the user selected. Always include src/, tests/,
composer.json, README.md, CHANGELOG.md, and LICENSE.
Step 3: Generate composer.json
Read references/package-structure.md for the full template. Key sections:
{
"name": "vendor/package-name",
"description": "Package description here",
"keywords": ["laravel", "php"],
"license": "MIT",
"require": {
"php": "^8.4",
"illuminate/support": "^12.0"
},
"require-dev": {
"orchestra/testbench": "^10.0",
"pestphp/pest": "^3.0",
"pestphp/pest-plugin-laravel": "^3.0",
"laravel/pint": "^1.0"
},
"autoload": {
"psr-4": {
"Vendor\\PackageName\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Vendor\\PackageName\\Tests\\": "tests/"
}
},
"extra": {
"laravel": {
"providers": [
"Vendor\\PackageName\\PackageNameServiceProvider"
],
"aliases": {
"PackageName": "Vendor\\PackageName\\Facades\\PackageName"
}
}
},
"config": {
"sort-packages": true,
"allow-plugins": {
"pestphp/pest-plugin": true
}
},
"minimum-stability": "dev",
"prefer-stable": true
}
Step 4: Generate ServiceProvider
Read references/package-structure.md for the full ServiceProvider patterns. The provider must:
- Extend
Illuminate\Support\ServiceProvider
- Use
register() for bindings and merging config
- Use
boot() for publishing assets, loading routes, views, migrations, and commands
- Include conditional
if ($this->app->runningInConsole()) blocks for publishable assets
- Group publishes with tags:
{package-name}-config, {package-name}-migrations, etc.
Step 5: Generate Facade
<?php
declare(strict_types=1);
namespace Vendor\PackageName\Facades;
use Illuminate\Support\Facades\Facade;
class PackageName extends Facade
{
protected static function getFacadeAccessor(): string
{
return \Vendor\PackageName\PackageName::class;
}
}
Step 6: Generate Config File
<?php
return [
];
Step 7: Generate Starter Files
Generate .gitignore, LICENSE (MIT), initial CHANGELOG.md, and phpunit.xml.
2. /package test — Pest + Orchestra Testbench Setup
Step 1: Check Existing Test Setup
Scan the package for existing tests/ directory and phpunit.xml. If they exist, extend
rather than overwrite.
Step 2: Generate TestCase Base Class
Read references/testbench-patterns.md for the full Testbench TestCase patterns.
<?php
declare(strict_types=1);
namespace Vendor\PackageName\Tests;
use Orchestra\Testbench\TestCase as Orchestra;
use Vendor\PackageName\PackageNameServiceProvider;
class TestCase extends Orchestra
{
protected function setUp(): void
{
parent::setUp();
}
protected function getPackageProviders($app): array
{
return [
PackageNameServiceProvider::class,
];
}
protected function getPackageAliases($app): array
{
return [
'PackageName' => \Vendor\PackageName\Facades\PackageName::class,
];
}
protected function getEnvironmentSetUp($app): void
{
config()->set('database.default', 'testing');
config()->set('database.connections.testing', [
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
]);
}
protected function defineDatabaseMigrations(): void
{
$this->loadMigrationsFrom(__DIR__ . '/../database/migrations');
}
}
Step 3: Generate Pest.php
<?php
declare(strict_types=1);
use Vendor\PackageName\Tests\TestCase;
uses(TestCase::class)->in('Feature');
Step 4: Generate Starter Tests
Generate tests based on what the package provides:
| Package Feature | Test File | Key Assertions |
|---|
| ServiceProvider | tests/Feature/ServiceProviderTest.php | Provider loads, bindings resolve, config merges |
| Config | tests/Feature/ConfigTest.php | Config file publishable, default values correct |
| Migrations | tests/Feature/MigrationTest.php | Tables created, columns match expectations |
| Commands | tests/Feature/CommandTest.php | Command registered, executes without error |
| Routes | tests/Feature/RouteTest.php | Routes registered, middleware applied, responses correct |
| Facade | tests/Feature/FacadeTest.php | Facade resolves, methods callable |
Step 5: Generate phpunit.xml
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
>
<testsuites>
<testsuite name="Feature">
<directory>tests/Feature</directory>
</testsuite>
</testsuites>
<source>
<include>
<directory>src</directory>
</include>
</source>
</phpunit>
3. /package release — Release Checklist
Step 1: Pre-Release Validation
Run through these checks before releasing:
| Check | Command | Pass Condition |
|---|
| Tests pass | composer test or ./vendor/bin/pest | Exit code 0, no failures |
| Code style | ./vendor/bin/pint --test | No style violations |
| No uncommitted changes | git status | Clean working tree |
| README up to date | Manual review | Installation, usage, and changelog sections current |
| License file present | ls LICENSE | File exists |
Step 2: Version Bump
Follow Semantic Versioning (SemVer):
| Change Type | Version Bump | Example |
|---|
| Bug fix, patch | PATCH | 1.0.0 -> 1.0.1 |
| New feature, backward-compatible | MINOR | 1.0.1 -> 1.1.0 |
| Breaking change | MAJOR | 1.1.0 -> 2.0.0 |
Update the version in composer.json if a version field exists (most packages rely on
git tags instead).
Step 3: Update CHANGELOG.md
Follow Keep a Changelog format:
# Changelog
All notable changes to this project will be documented in this file.
## [Unreleased]
## [1.1.0] - 2026-02-27
### Added
- New feature X for handling Y
- Support for Laravel 12
### Changed
- Updated minimum PHP version to 8.2
### Fixed
- Resolved issue with config publishing (#42)
## [1.0.0] - 2026-01-15
### Added
- Initial release
- Service provider with config publishing
- Facade support
- Migration publishing
[Unreleased]: https://github.com/vendor/package/compare/1.1.0...HEAD
[1.1.0]: https://github.com/vendor/package/compare/1.0.0...1.1.0
[1.0.0]: https://github.com/vendor/package/releases/tag/1.0.0
Step 4: Commit and Tag
git add -A
git commit -m "chore: release 1.1.0"
git tag -a 1.1.0 -m "1.1.0"
git push origin main --tags
Step 5: Packagist Publishing
- First release: Register at packagist.org
with the GitHub repository URL
- Subsequent releases: Packagist auto-updates if the GitHub webhook is configured;
otherwise run
curl -X POST https://packagist.org/api/update-package?username=USER&apiToken=TOKEN
- Verify the release appears on Packagist within a few minutes
4. /package readme — README Generation
Step 1: Scan Package
Read composer.json, src/, and config/ to understand what the package provides.
Step 2: Generate README Structure
# Package Name
[](https://packagist.org/packages/vendor/package-name)
[](https://github.com/vendor/package-name/actions?query=workflow%3Arun-tests+branch%3Amain)
[](https://packagist.org/packages/vendor/package-name)
Short description of the package — one or two sentences.
## Installation
You can install the package via Composer:
\```bash
composer require vendor/package-name
\```
You can publish the config file with:
\```bash
php artisan vendor:publish --tag="package-name-config"
\```
Optionally, you can publish the migrations with:
\```bash
php artisan vendor:publish --tag="package-name-migrations"
\```
## Usage
\```php
use Vendor\PackageName\Facades\PackageName;
// Example usage
$result = PackageName::doSomething();
\```
## Testing
\```bash
composer test
\```
## Changelog
Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.
## Contributing
Please see [CONTRIBUTING](CONTRIBUTING.md) for details.
## Security Vulnerabilities
Please review [our security policy](../../security/policy) on how to report security
vulnerabilities.
## Credits
- [Author Name](https://github.com/author)
- [All Contributors](../../contributors)
## License
The MIT License (MIT). Please see [License File](LICENSE) for more information.
Step 3: Customise Sections
Based on the package scan:
| Package Feature | README Section to Add |
|---|
| Config file | "Configuration" section with key options documented |
| Migrations | "Database" section explaining tables created |
| Commands | "Commands" section listing artisan commands |
| Routes | "Routes" section with endpoint table |
| Views | "Views" section explaining publishable views |
| Events | "Events" section listing dispatched events |
| Middleware | "Middleware" section with registration instructions |
5. /package upgrade — Upgrade Dependencies
Bump PHP, Laravel, and ecosystem dependency version constraints in an existing package.
Step 1: Read Current State
Parse composer.json for current constraints:
require.php
- All
illuminate/* packages
orchestra/testbench
pestphp/pest-plugin-laravel
laravel/pint
- Any other Laravel-ecosystem dependencies
Step 2: Check Dependency Availability
For each dependency being upgraded, verify the target version exists on Packagist:
- Use
composer show {package} --available or check https://packagist.org/packages/{vendor}/{package} to confirm the target version/constraint is published
- Flag any dependency that does not yet have a compatible release for the target Laravel/PHP version
- If a dependency is not available, warn the user and suggest alternatives: wait for the release, find a fork, or drop the dependency
Step 3: Show Current vs Target
Display a comparison table with availability status:
| Dependency | Current | Target | Available? |
|---|
php | ^8.2 | ^8.4 | ✅ |
illuminate/support | ^11.0 | ^12.0 | ✅ |
orchestra/testbench | ^9.0 | ^10.0 | ✅ |
pestphp/pest-plugin-laravel | ^2.0 | ^3.0 | ✅ |
Step 4: Ask Target Versions
Confirm with the user before proceeding. Defaults:
- PHP:
^8.4
- Laravel:
^12.0
- Testbench:
^10.0
Step 5: Reference Upgrade Guide
Point the user to the official Laravel upgrade guide for breaking changes:
https://laravel.com/docs/{targetMajor}.x/upgrade
For example, when upgrading to Laravel 12: https://laravel.com/docs/12.x/upgrade
Step 6: Update composer.json
Bump version constraints for:
require.php
- All
illuminate/* packages in require and require-dev
orchestra/testbench
pestphp/pest-plugin-laravel
laravel/pint
- Any other Laravel-ecosystem dev dependencies
Step 7: Run Composer Update
composer update
If dependency resolution fails, report which packages conflict and suggest resolution steps.
Step 8: Run Tests
composer test
Or ./vendor/bin/pest if no test script is defined. Report any failures so the user can address breaking changes.
Step 9: Update README
If the README contains version badges or a "Requirements" section referencing specific PHP/Laravel versions, update those to match the new constraints.
Version Compatibility Matrix
| Laravel | PHP | Testbench | Pest Plugin Laravel |
|---|
| 12.x | ^8.2 | ^10.0 | ^3.0 |
| 11.x | ^8.2 | ^9.0 | ^2.0 / ^3.0 |
| 10.x | ^8.1 | ^8.0 | ^2.0 |
6. Anti-Patterns to Avoid
| Anti-Pattern | Correct Approach |
|---|
| Hardcoding Laravel version in ServiceProvider | Use illuminate/* packages with version ranges |
Registering everything in boot() | Use register() for bindings, boot() for bootstrapping |
Missing declare(strict_types=1) | Include in every PHP file |
| No publish tags | Always tag publishable assets: {package}-config, {package}-migrations |
| Monolithic ServiceProvider | Extract to separate concerns if provider exceeds 100 lines |
| Testing against real database | Always use SQLite :memory: via Testbench |
Missing extra.laravel in composer.json | Required for auto-discovery to work |
No .gitignore for vendor/ and composer.lock | Packages must ignore composer.lock (apps keep it) |
Reference Files
| File | Read When |
|---|
references/package-structure.md | Scaffolding package structure, ServiceProvider, Facade, and composer.json patterns |
references/testbench-patterns.md | Setting up Orchestra Testbench, writing package tests |