Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/HypathStack/model-scribe/llms.txt

Use this file to discover all available pages before exploring further.

Without an active retention policy, audit log tables grow without bound. Every model create, update, and delete appends a new row, and in high-traffic applications those rows can accumulate into millions of records over time — inflating storage costs, degrading query performance, and making manual cleanup painful. ModelScribe’s prune command gives you a single, schedulable entry point that enforces your retention rules and reports exactly how many records were removed.

How pruning works

When you run model-scribe:prune, the command calls ModelScribe::prune() on the application’s ModelScribe instance, which in turn delegates to the configured driver’s own prune() method. Each driver knows how to clean up its own storage, so the command itself stays thin:
// PruneLogsCommand — what runs under the hood
$deleted = $scribe->prune($driver); // null = use the configured default
$this->components->info("Pruned {$deleted} audit log record(s).");

Running the command

# Prune using the default configured driver
php artisan model-scribe:prune

# Prune a specific driver
php artisan model-scribe:prune --driver=database
php artisan model-scribe:prune --driver=file
After the command finishes it prints a single confirmation line:
INFO  Pruned 1 248 audit log record(s).
The number reflects the total rows deleted across all tables touched by the driver during that run.

Pruning programmatically

You can invoke pruning from your own code — for example inside a custom Artisan command, a job, or a maintenance script — using the ModelScribe facade:
use HypathBel\ModelScribe\Facades\ModelScribe;

$deleted = ModelScribe::prune();           // default driver
$deleted = ModelScribe::prune('database'); // explicit driver
The return value is the integer count of deleted records, identical to what the Artisan command displays.

How each driver handles pruning

database

The database driver is the only driver that actively deletes records. When prune() is called it first collects every table it manages — the default model_scribe_logs table plus every table referenced by named stores under drivers.database.stores — and then applies your configured retention rule to each one:
Retention typeBehaviour
permanentNo records are deleted. Returns 0.
daysDeletes all rows whose created_at is older than the configured days value.
rotatingKeeps only the latest keep records across the entire table and deletes the rest.
The method deduplicates the table list before querying, so a store that points to the same physical table as the default will never be pruned twice.
Pruning has no effect when retention type is permanent. This is the default, so you must explicitly set the type to days or rotating in config/model-scribe.php before running the prune command will remove anything.
The rotating retention type keeps the latest keep records across the whole table, not per subject or per model. If you have 500 App\Models\Invoice records and 500 App\Models\Order records in the same table and keep is set to 500, half of those records will be pruned regardless of which model they belong to.

file

The file driver is a no-op — prune() always returns 0. File rotation (size-based splitting, log archiving, and deletion of old files) is handled entirely by Laravel’s built-in logging system via the daily or single channel you configure. There is nothing for ModelScribe to manage on top of that.

stack

The stack driver calls prune() on each of its configured sub-drivers in turn and returns the sum of their individual counts. If your stack contains both a database and a file driver, you get back the number of database rows deleted (since the file driver always returns 0).

Scheduling daily pruning

Add the prune command to your scheduler in routes/console.php so old records are cleaned up automatically:
use Illuminate\Support\Facades\Schedule;

Schedule::command('model-scribe:prune')->daily();

// Or prune a specific driver on a different schedule
Schedule::command('model-scribe:prune --driver=database')->dailyAt('03:00');
Running pruning at a quiet time (e.g. 03:00) minimises lock contention on the audit table. On very large tables you may want to combine a days-based policy with a nightly schedule rather than rotating, which issues a single bulk DELETE that could be expensive on tables with tens of millions of rows.
For full details on configuring retention types and values, see the Retention configuration reference.

Build docs developers (and LLMs) love