PHPackages                             schenke-io/packaging-tools - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. schenke-io/packaging-tools

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

schenke-io/packaging-tools
==========================

Tools to simplify publishing github packages

v0.2.13(yesterday)01.7k↑23.3%9MITPHPPHP ^8.3 || ^8.4CI passing

Since Jan 22Pushed 4d agoCompare

[ Source](https://github.com/schenke-io/packaging-tools)[ Packagist](https://packagist.org/packages/schenke-io/packaging-tools)[ Docs](https://github.com/schenke-io/packaging-tools)[ RSS](/packages/schenke-io-packaging-tools/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (66)Versions (23)Used By (9)

[![Coverage](workbench/resources/md/svg/coverage.svg)](workbench/resources/md/svg/coverage.svg)[![PHPStan](workbench/resources/md/svg/phpstan.svg)](workbench/resources/md/svg/phpstan.svg)[![Version](https://camo.githubusercontent.com/44dbb1e267b0bdf713d1c2aaa13a562aa9ab5b18854246eaf612724da146a38c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f736368656e6b652d696f2f7061636b6167696e672d746f6f6c733f7374796c653d666c6174)](https://packagist.org/packages/schenke-io/packaging-tools)[![Downloads](https://camo.githubusercontent.com/77aa5bf5aaa126ae3f37b54896868aaa2a1026710bf5edc6d3f378314adf8389/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f736368656e6b652d696f2f7061636b6167696e672d746f6f6c733f7374796c653d666c6174)](https://packagist.org/packages/schenke-io/packaging-tools)[![Tests](https://github.com/schenke-io/packaging-tools/actions/workflows/run-tests.yml/badge.svg)](https://github.com/schenke-io/packaging-tools/actions/workflows/run-tests.yml)[![License](https://camo.githubusercontent.com/2486a4c6cbcf5e72040f560bf82d20cfe777b633fb2ec05f831005b179c20d09/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f736368656e6b652d696f2f7061636b6167696e672d746f6f6c733f7374796c653d666c6174)](https://github.com/schenke-io/packaging-tools/blob/main/LICENSE.md)[![PHP](https://camo.githubusercontent.com/485ad4202d4454be91e1158200f0ad883c3bc808d565ac377477aaf119dac605/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f736368656e6b652d696f2f7061636b6167696e672d746f6f6c733f7374796c653d666c6174)](https://packagist.org/packages/schenke-io/packaging-tools)

Packaging Tools
==========================================================

[](#packaging-tools)

> Tools to simplify publishing github packages

[![cover](workbench/resources/md/cover.png)](workbench/resources/md/cover.png)

This package is a collection of tools to simplify package and project development.

The main elements are:

- **Markdown:** Assemble the `README.md` file from small Markdown files, class comments, and other sources.
- **Badge:** Create custom badges or generate them from existing files.
- **Setup:** Read the `.packaging-tools.neon` configuration file and modify scripts in `composer.json`.
- **Boost Skills &amp; Guidelines:** This package supports the [Laravel Boost](https://laravel.com/docs/12.x/boost) standard for AI-ready packages.

### Skill-based documentation

[](#skill-based-documentation)

Documentation for this package is partly generated from **AI Skills**. These skills are small, focused pieces of documentation that describe specific features or workflows. They are located in `resources/boost/skills/` and are also compatible with Laravel Boost.

By using these skills, the package ensures that both human developers and AI assistants have clear, actionable instructions on how to use the provided tools.

- [Packaging Tools](#packaging-tools)
    - [Skill-based documentation](#skill-based-documentation)
- [Packaging Tools](#packaging-tools)
    - [Purpose](#purpose)
    - [When to Use](#when-to-use)
    - [Sub-skills](#sub-skills)
- [Badges](#badges)
    - [Purpose](#purpose)
    - [When to Use](#when-to-use)
    - [Quick start](#quick-start)
    - [Auto-detected badge types](#auto-detected-badge-types)
    - [PHP API](#php-api)
    - [Badge styles](#badge-styles)
    - [Forge badge (requires explicit parameters)](#forge-badge-requires-explicit-parameters)
- [AI Guidelines and Skills for Boost](#ai-guidelines-and-skills-for-boost)
    - [Purpose](#purpose)
    - [When to Use](#when-to-use)
    - [AI Guidelines](#ai-guidelines)
        - [Example `core.blade.php`](#example-core-blade-php)
    - [AI Skills](#ai-skills)
        - [Open Knowledge Format (OKF)](#open-knowledge-format-okf)
            - [Example `SKILL.md`](#example-skill-md)
    - [Including skills in Markdown assembly](#including-skills-in-markdown-assembly)
- [Database Migrations](#database-migrations)
    - [Purpose](#purpose)
    - [When to Use](#when-to-use)
    - [Quick start](#quick-start)
    - [Configuration (`.packaging-tools.neon`)](#configuration-packaging-tools-neon)
    - [Process](#process)
    - [Workbench support](#workbench-support)
    - [Using the trait in an Artisan command](#using-the-trait-in-an-artisan-command)
- [Markdown Assembler](#markdown-assembler)
    - [Purpose](#purpose)
    - [When to Use](#when-to-use)
    - [Script location](#script-location)
    - [Minimal example](#minimal-example)
    - [Assembler methods](#assembler-methods)
    - [Badges: `badges()`](#badges-badges)
    - [Classes: `classes()`](#classes-classes)
    - [Tables: `tables()`](#tables-tables)
    - [Skills: `skills()`](#skills-skills)
    - [Table of Contents](#table-of-contents)
- [Setup](#setup)
    - [Purpose](#purpose)
    - [When to Use](#when-to-use)
    - [Installation](#installation)
    - [Commands](#commands)
    - [Configuration file: `.packaging-tools.neon`](#configuration-file-packaging-tools-neon)
    - [Configuration keys](#configuration-keys)
    - [Custom tasks](#custom-tasks)
    - [Concept](#concept)
- [Speed Seeding](#speed-seeding)
    - [Purpose](#purpose)
    - [When to Use](#when-to-use)
    - [How it works](#how-it-works)
    - [Usage](#usage)
    - [Generating the SQL dump](#generating-the-sql-dump)
    - [Important](#important)
        - [MarkdownAssembler](#markdownassembler)
            - [How to assemble a markdown](#how-to-assemble-a-markdown)
                - [Bootstrapping](#bootstrapping)
                - [Assembly Example](#assembly-example)
                - [Key Methods](#key-methods)
            - [Public methods of MarkdownAssembler](#public-methods-of-markdownassembler)
        - [MakeBadge](#makebadge)
            - [Public methods of MakeBadge](#public-methods-of-makebadge)
        - [Config](#config)
            - [Public methods of Config](#public-methods-of-config)

TitleDescription[packaging-tools](resources/boost/skills/packaging-tools/SKILL.md)Tools to simplify publishing github packagesPackaging Tools
==========================================================

[](#packaging-tools-1)

Purpose
------------------------------------------

[](#purpose)

This skill provides a set of tools to simplify publishing GitHub packages, including badge generation, AI guidelines, migration management, markdown assembly, setup, and speed seeding.

When to Use
--------------------------------------------------

[](#when-to-use)

Use when developing Laravel packages and wanting to automate documentation, badges, migrations, or testing setup.

Sub-skills
------------------------------------------------

[](#sub-skills)

SkillDescription[packaging-tools-badges](sub-skills/packaging-tools-badges.md)Generate SVG badges for project metrics[packaging-tools-guidelines](sub-skills/packaging-tools-guidelines.md)Write AI guidelines and skills for projects based on Laravel Boost standards[packaging-tools-imported-migrations](sub-skills/packaging-tools-imported-migrations.md)Regenerate package migrations from a live database schema[packaging-tools-markdown-assembly](sub-skills/packaging-tools-markdown-assembly.md)Assemble modular documentation and class references into a README[packaging-tools-setup](sub-skills/packaging-tools-setup.md)Install, configure, and run packaging tools via composer scripts[packaging-tools-speed-seeding](sub-skills/packaging-tools-speed-seeding.md)Speed up tests by loading a pre-generated SQL dump instead of running migrationsBadges
========================================

[](#badges)

Purpose
------------------------------------------

[](#purpose-1)

Generate SVG badges for project metrics including coverage, PHP version, and more.

When to Use
--------------------------------------------------

[](#when-to-use-1)

Use when you need to generate or update SVG badge files for a project's README, or when adding badge configuration to a Markdown assembler script.

Quick start
--------------------------------------------------

[](#quick-start)

Generate all auto-detected badges at once:

```
composer pack-to badges
```

This calls `MakeBadge::auto()`, which scans for known source files (clover.xml, phpstan.neon, infection-report.json, composer.json) and writes SVG files to `resources/md/svg/` (or `workbench/resources/md/svg/`).

Auto-detected badge types
------------------------------------------------------------------------------

[](#auto-detected-badge-types)

BadgeSourceDetectionCoverageclover.xmlpath from phpunit.xmlPhpStanphpstan.neon / phpstan.neon.distauto-discoveredInfectioninfection-report.jsonauto-discoveredPHP versioncomposer.json`require.php` constraintLatest versioncomposer.jsonpackage name → PackagistDownloadscomposer.jsonpackage name → PackagistLaravel versioncomposer.json`require.laravel/framework`Testscomposer.jsonGitHub repo → ActionsLicensecomposer.json`license` fieldPHP API
------------------------------------------

[](#php-api)

```
use SchenkeIo\PackagingTools\Badges\MakeBadge;

// auto-generate all detected badges
MakeBadge::auto();

// generate specific badges (path optional, auto-detected when omitted)
MakeBadge::makeCoverageBadge();                          // from clover.xml
MakeBadge::makePhpStanBadge(color: '2563eb');            // blue by default
MakeBadge::makeInfectionBadge();
MakeBadge::makePhpVersionBadge();

// with explicit paths
MakeBadge::makeCoverageBadge('build/logs/clover.xml');
MakeBadge::makePhpStanBadge('phpstan.neon', '16a34a');

// custom badge
MakeBadge::define('My Label', 'passing', '27AE60')
    ->store('resources/md/svg/my-badge.svg');
```

`store()` signature: `store(?string $filepath = null, ?BadgeStyle $style = null)`. When `$filepath` is null, the badge is stored at `$markdownDir/svg/{subject-slug}.svg`.

Badge styles
----------------------------------------------------

[](#badge-styles)

```
use SchenkeIo\PackagingTools\Enums\BadgeStyle;

BadgeStyle::Flat          // flat (default)
BadgeStyle::FlatSquare    // flat-square
BadgeStyle::Plastic       // plastic
BadgeStyle::ForTheBadge   // for-the-badge
```

Forge badge (requires explicit parameters)
--------------------------------------------------------------------------------------------------------------

[](#forge-badge-requires-explicit-parameters)

The Forge deployment badge is not auto-detected and must be added via the Markdown assembler:

```
$assembler->badges()->forge(
    hash: 'your-hash',
    server: 123456,
    site: 654321,
    date: 1,   // 1 = show date, 0 = hide
    label: 1   // 1 = show label, 0 = hide
);
```

AI Guidelines and Skills for Boost
================================================================================================

[](#ai-guidelines-and-skills-for-boost)

Purpose
------------------------------------------

[](#purpose-2)

Provide a standardized way to write AI guidelines and skills so they can be automatically loaded by Boost-compatible projects and integrated into package documentation.

When to Use
--------------------------------------------------

[](#when-to-use-2)

Use when creating or updating AI guidelines (`core.blade.php`) or skill files (`SKILL.md`) for a Laravel package so that Boost-compatible projects can load them automatically.

AI Guidelines
------------------------------------------------------

[](#ai-guidelines)

Add a `resources/boost/guidelines/core.blade.php` file to your package. When users run `php artisan boost:install`, Boost loads it automatically as AI context.

Guidelines should:

- Briefly describe what the package does
- List key conventions and file structures
- Show example commands and code snippets
- Be concise and actionable — written for AI, not humans

#### Example `core.blade.php`

[](#example-corebladephp)

```
## vendor/package-name

This package provides [brief description].

### Features

- Feature 1: [description].
- Feature 2: [description]. Example:

```php
$result = PackageName::featureTwo($param1, $param2);
```

```

The `@verbatim` / `` wrapper is processed by the Skills assembler into a plain fenced code block when included in Markdown output.

## AI Skills

Add a `resources/boost/skills/{skill-name}/SKILL.md` file. Boost skills follow the [Open Knowledge Format (OKF)](https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md) specification.

### Open Knowledge Format (OKF)

OKF is a minimal, agent-friendly format for representing knowledge as Markdown files with YAML frontmatter. Every concept (skill) requires exactly one frontmatter field: `type`. Other fields like `title`, `description`, and `timestamp` are highly recommended.

Required and recommended frontmatter keys for Boost skills:
- `type`: (Required) For Boost skills, use `Agent Skill`.
- `title`: (Recommended) The display name of the skill.
- `description`: (Recommended) A short summary of what the skill does.
- `timestamp`: (Recommended) Last update date in `YYYY-MM-DD` format.

#### Example `SKILL.md`

```markdown
---
type: Agent Skill
title: package-name-feature
description: Build and work with PackageName features.
timestamp: 2026-06-29
---

# Feature Title

## Purpose
Briefly describe the purpose of this feature.

## When to Use
Use when working with PackageName features...

## Features

- Feature 1: description.
- Feature 2: description. Example:

```php
$result = PackageName::featureTwo($param1, $param2);

```

```

## Including skills in Markdown assembly

The `MarkdownAssembler` can embed skill content or render a summary table:

```php
use SchenkeIo\PackagingTools\Markdown\MarkdownAssembler;

$assembler = new MarkdownAssembler('resources/md');

// embed full content of all skills
$assembler->skills()->all();

// embed a specific skill
$assembler->skills()->add('my-skill-name');

// render a summary table (name + description) for all skills
$assembler->skillOverview();

```

`skillOverview()` generates a Markdown table with linked skill names and their descriptions, sourced from each SKILL.md's frontmatter.

Database Migrations
==================================================================

[](#database-migrations)

Purpose
------------------------------------------

[](#purpose-3)

Maintain package migration files in sync with a live development database using a database-first workflow.

When to Use
--------------------------------------------------

[](#when-to-use-3)

Use when you want to keep your package's migration files in sync with a development database. This is a "database-first" workflow: you modify the database manually, then regenerate the migrations from it.

Requires `kitloong/laravel-migrations-generator` to be installed (not included by default).

Quick start
--------------------------------------------------

[](#quick-start-1)

```
composer migrations
```

This runs the full migration regeneration cycle: deletes old migrations, generates new ones from the configured database connection, then cleans environment-specific connection calls from the files.

Configuration (`.packaging-tools.neon`)
-----------------------------------------------------------------------------------------------------

[](#configuration-packaging-toolsneon)

```
migrations: mysql:*
```

Format: `connection:tables` — use `*` to auto-detect tables from your Eloquent models.

Examples:

- `mysql:*` — use `mysql` connection, detect tables from models
- `sqlite:users,posts` — use `sqlite` connection, only those tables
- `null` — disable migration generation

Process
------------------------------------------

[](#process)

1. Checks that `kitloong/laravel-migrations-generator` is installed. If missing, it outputs an error message with installation instructions.
2. Reads the connection and table list from `.packaging-tools.neon`.
3. If `*` is used, scans for Eloquent models in (in priority order):
    - `workbench/app/Models`
    - `app/Models`
    - `src/Models`
4. Cleans the migrations folder.
5. Runs `migrate:generate` with `--skip-log --default-index-names --date=2020-10-10`.
6. Strips environment-specific `connection()` calls from generated files.
7. Sets generated files to read-only (mode 444) to prevent manual edits.

Workbench support
--------------------------------------------------------------

[](#workbench-support)

If `workbench/database/migrations` exists, it is used as the migration output path instead of `database/migrations`.

Using the trait in an Artisan command
------------------------------------------------------------------------------------------------------

[](#using-the-trait-in-an-artisan-command)

```
use SchenkeIo\PackagingTools\Traits\GeneratesPackageMigrations;
use Illuminate\Console\Command;

class MyMigrationCommand extends Command
{
    use GeneratesPackageMigrations;

    public function handle(): void
    {
        $this->generatePackageMigrations();
    }
}
```

The trait must be used inside a class that extends `Illuminate\Console\Command` (it calls `$this->call()`). It reads `.packaging-tools.neon` automatically and performs the same steps as `composer migrations`.

Markdown Assembler
================================================================

[](#markdown-assembler)

Purpose
------------------------------------------

[](#purpose-4)

Assemble modular documentation, class references, badges, and tables into a single README file.

When to Use
--------------------------------------------------

[](#when-to-use-4)

Use when building or editing the script that generates `README.md` from modular source files. The assembler compiles badges, markdown partials, class docs, tables, and a table of contents into a single output file.

Script location
----------------------------------------------------------

[](#script-location)

The assembler script is auto-generated by `composer pack-to`. Depending on the project structure:

- **Package with workbench**: `workbench/app/Console/Commands/MakeMarkdown.php` (Laravel console command)
- **Standalone package**: `.make-markdown.php` (plain PHP script, run via `php .make-markdown.php`)

Initialize source markdown files (creates `resources/md/` with placeholder files):

```
MarkdownAssembler::init('resources/md');
```

Minimal example
----------------------------------------------------------

[](#minimal-example)

```
use SchenkeIo\PackagingTools\Markdown\MarkdownAssembler;

$assembler = new MarkdownAssembler('resources/md');

$assembler
    ->addTableOfContents()
    ->addMarkdown('header.md')
    ->badges()->all()
    ->addMarkdown('installation.md')
    ->addMarkdown('usage.md')
    ->classes()->all()
    ->writeMarkdown('README.md');
```

`MarkdownAssembler` takes the markdown source directory as its first argument. All `addMarkdown()` paths are relative to that directory.

Assembler methods
--------------------------------------------------------------

[](#assembler-methods)

MethodPurpose`addTableOfContents()`Inserts a linked TOC (auto-generated from all headings)`addMarkdown(string $file)`Includes a markdown file from the source directory`addText(string $content)`Inlines raw markdown text`autoHeader(?string $title)`Auto-generates title, description, cover image, and all badges`skipWrittenBy()`Omits the "DO NOT EDIT" header comment and footer`image(string $alt, string $path, string $url)`Adds a linked image`addContentProvider(MarkdownPieceInterface $provider)`Adds a custom content block`writeMarkdown(string $filepath)`Assembles and writes the final fileBadges: `badges()`
-----------------------------------------------------------

[](#badges-badges)

```
$assembler->badges()->all();                             // all auto-detected badges
$assembler->badges()->version(BadgeStyle::Flat);
$assembler->badges()->test('run-tests.yml');
$assembler->badges()->download(BadgeStyle::FlatSquare);
$assembler->badges()->php();
$assembler->badges()->local('My Badge', 'resources/md/svg/my-badge.svg');
$assembler->badges()->forge(hash: 'abc', server: 1, site: 2, date: 1, label: 1);
```

`all()` automatically includes local SVG badges from `$markdownDir/svg/` and remote badges (version, downloads, tests, php) detected from `composer.json`.

Classes: `classes()`
---------------------------------------------------------------

[](#classes-classes)

Documents PHP classes by extracting PHPDoc and method signatures:

```
$assembler->classes()->all();                            // all classes in src/
$assembler->classes()->add(MyClass::class);              // single class
$assembler->classes()->glob('src/Models/*.php');         // glob pattern
$assembler->classes()->custom(MyClass::class, fn($data) => "## {$data->name}");
```

Only classes with `@markdown` in their PHPDoc or significant documentation are rendered.

Tables: `tables()`
-----------------------------------------------------------

[](#tables-tables)

```
$assembler->tables()->fromFile('data/table.csv');
$assembler->tables()->fromCsvString($csv, ',');
$assembler->tables()->fromArray([['Col1', 'Col2'], ['a', 'b']]);
```

Skills: `skills()`
-----------------------------------------------------------

[](#skills-skills)

```
$assembler->skills()->all();                             // all skills in resources/boost/skills/
$assembler->skills()->add('my-skill-name');              // specific skill
$assembler->skillOverview();                             // summary table (name + description)
```

Table of Contents
--------------------------------------------------------------

[](#table-of-contents)

The TOC is auto-built from all `#` headings across all assembled blocks. Use `addTableOfContents()` to place a placeholder; it is replaced with the full linked TOC at write time. Heading anchors (``) are injected automatically.

Setup
======================================

[](#setup)

Purpose
------------------------------------------

[](#purpose-5)

Simplify the installation and configuration of packaging tools, providing a single source of truth via `.packaging-tools.neon`.

When to Use
--------------------------------------------------

[](#when-to-use-5)

Use when installing the package for the first time, updating the configuration, or running any of the built-in task commands (`test`, `analyse`, `coverage`, `markdown`, etc.).

Installation
----------------------------------------------------

[](#installation)

```
composer require schenke-io/packaging-tools
```

Add the setup script to `composer.json`:

```
{
    "scripts": {
        "setup": "SchenkeIo\\PackagingTools\\Setup::handle"
    }
}
```

Commands
--------------------------------------------

[](#commands)

CommandAction`composer pack-to`Show current config status and any pending changes`composer pack-to config`Create or sync `.packaging-tools.neon``composer pack-to update`Apply pending composer.json script additions and install missing packages`composer pack-to badges`Generate all auto-detected SVG badges`composer pack-to `Run a specific configured task (e.g., `test`, `pint`, `quick`)Configuration file: `.packaging-tools.neon`
--------------------------------------------------------------------------------------------------------------

[](#configuration-file-packaging-toolsneon)

```
analyse: true
coverage: true
infection: true
markdown: php .make-markdown.php
migrations: mysql:*
pint: true
test: pest
quick:
    - pint
    - test
    - markdown
release:
    - pint
    - analyse
    - coverage
    - infection
    - markdown
sql-cache: true
customTasks: {}
```

Configuration keys
----------------------------------------------------------------

[](#configuration-keys)

KeyTypeDescription`analyse``bool`PHPStan static analysis (auto-detects Larastan)`coverage``bool`Adds coverage flags to test run; requires `clover.xml``infection``bool`Mutation testing via `infection/infection``markdown``string|null`Command to run the Markdown assembler script`migrations``string|null`Migration regeneration: format `connection:tables` or `connection:*``pint``bool`Code style with Laravel Pint`test``string`Test runner: `pest`, `phpunit`, or `''` to disable`quick``array`Task group for fast iteration (default: pint, test, markdown)`release``array`Task group for pre-release checks`sql-cache``bool|string|null`Dump SQLite DB to SQL file; `true` = `tests/Data/seeded.sql``customTasks``array`Map of custom task names to shell commands or class namesCustom tasks
----------------------------------------------------

[](#custom-tasks)

```
customTasks:
    lint: php -l src/
    my-task: App\Console\Commands\MyTask
```

Run with: `composer pack-to lint` or `composer pack-to my-task`.

Concept
------------------------------------------

[](#concept)

- Configuration is the single source of truth — editing `.packaging-tools.neon` controls everything.
- Manual edits to `composer.json` scripts are preserved; the tool warns before overwriting.
- `composer pack-to` (no args) shows a diff of what would change — it never modifies without an explicit subcommand.
- All keys define their own schema via `nette/schema`; invalid config produces a clear error with a "did you mean?" suggestion.

Speed Seeding
======================================================

[](#speed-seeding)

Purpose
------------------------------------------

[](#purpose-6)

Optimize test suite execution time by loading a pre-generated SQL dump instead of re-running migrations and seeders for every test run.

When to Use
--------------------------------------------------

[](#when-to-use-6)

Use in test suites where running full migrations and seeders on every test is too slow. Load a pre-generated SQL dump once per test run instead.

This is a companion to the `sql-cache` configuration key, which generates the dump.

How it works
----------------------------------------------------

[](#how-it-works)

1. **Generate the dump** — `sql-cache: true` in `.packaging-tools.neon` makes `composer pack-to` dump the current SQLite DB to `tests/Data/seeded.sql` (configurable path).
2. **Load in tests** — the `LoadsSeededSql` trait loads that dump on first access, detected by checking if the `users` table exists.

Usage
--------------------------------------

[](#usage)

```
use SchenkeIo\PackagingTools\Traits\LoadsSeededSql;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\TestCase;

class MyFeatureTest extends TestCase
{
    use DatabaseTransactions;  // wrap each test in a transaction — do NOT use RefreshDatabase
    use LoadsSeededSql;

    public function setUp(): void
    {
        parent::setUp();
        $this->loadSeededSql();           // default: tests/Data/seeded.sql
        // $this->loadSeededSql('tests/Data/custom.sql');   // custom path
    }
}
```

`loadSeededSql()` is a no-op if the `users` table already exists in the current connection, so it is safe to call in every test without redundant reloads.

Generating the SQL dump
--------------------------------------------------------------------------

[](#generating-the-sql-dump)

In `.packaging-tools.neon`:

```
sql-cache: true            # dumps to tests/Data/seeded.sql
# sql-cache: tests/Data/custom.sql   # custom path
# sql-cache: null          # disabled
```

To run migrations and then dump in one step, add `@sql-cache` as a step in a custom task:

```
customTasks:
    seed: "@sql-cache"
```

Important
----------------------------------------------

[](#important)

- Use `DatabaseTransactions`, **not** `RefreshDatabase`. `RefreshDatabase` re-runs migrations and undoes the seeded state.
- The SQL file must be committed to the repository so CI can load it without running seeders.
- Regenerate the dump whenever your schema or seed data changes.

keydescriptionanalysefalse = disabled, true = enabled (uses phpstan/phpstan-phpunit or larastan/larastan)badgestrue = enabled (auto-generate badges), false = disabledcoveragefalse = disabled, true = enabled (adds --coverage to the test runner)infectionfalse = disabled, true = enabled (requires infection/infection)markdownnull = disabled, string = enabled (command to assemble Markdown files)migrationsnull = disabled, connection:\* = auto-detect, connection:table1,table2 = enabled (with connection and tables)pintfalse = disabled, true = enabled (uses laravel/pint)quickan array of scripts to include in this group: pint, test, markdownreleasean array of scripts to include in this group: pint, analyse, test, coverage, infection, markdownsql-cachenull = disabled, true = default path, 'path/to/file.sql' = custom pathtest'' = disabled, 'pest' or 'phpunit' = enabled### MarkdownAssembler

[](#markdownassembler)

Core engine for assembling Markdown documentation.

#### How to assemble a markdown

[](#how-to-assemble-a-markdown)

To assemble a markdown you need:

- a directory with markdown source files (e.g., `workbench/resources/md`)
- an assembly script (e.g., `workbench/MakeMarkdown.php`)

The `MarkdownAssembler` helps you combine static markdown files with dynamically generated content like badges, tables, and class documentation.

##### Bootstrapping

[](#bootstrapping)

You can initialize a markdown directory with standard files:

```
use SchenkeIo\PackagingTools\Markdown\MarkdownAssembler;

MarkdownAssembler::init('workbench/resources/md');
```

##### Assembly Example

[](#assembly-example)

```
