PHPackages                             keshavmansure/laravel-chronicle - 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. keshavmansure/laravel-chronicle

ActiveLibrary

keshavmansure/laravel-chronicle
===============================

Lightweight Laravel package that automatically tracks Eloquent model changes.

00PHPCI failing

Since Jul 31Pushed todayCompare

[ Source](https://github.com/keshavmansure/laravel-chronicle)[ Packagist](https://packagist.org/packages/keshavmansure/laravel-chronicle)[ RSS](/packages/keshavmansure-laravel-chronicle/feed)WikiDiscussions main Synced today

READMEChangelogDependenciesVersions (1)Used By (0)

Laravel Chronicle
=================

[](#laravel-chronicle)

Lightweight Eloquent change tracker for Laravel.

Add one trait to a model — creates, updates, and deletes are recorded automatically with before/after snapshots, optional request metadata, and almost zero configuration.

**Package:** `keshavmansure/laravel-chronicle`

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 11 or 12

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

[](#installation)

```
composer require keshavmansure/laravel-chronicle
```

Publish the config (optional):

```
php artisan vendor:publish --tag=chronicle-config
```

Publish the migration (optional — migrations also auto-load):

```
php artisan vendor:publish --tag=chronicle-migrations
```

Or publish both:

```
php artisan vendor:publish --tag=chronicle
```

Run migrations:

```
php artisan migrate
```

> If you publish the migration **and** leave package auto-loading enabled, keep only one copy so the table is not created twice.

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

[](#quick-start)

```
use KeshavMansure\Chronicle\Traits\HasChronicle;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasChronicle;
}
```

That's it.

```
$post = Post::create(['title' => 'Hello', 'body' => 'World']);
$post->update(['title' => 'Updated']);
$post->delete();
```

Reading history
---------------

[](#reading-history)

```
use KeshavMansure\Chronicle\Models\ChronicleEntry;

ChronicleEntry::query()
    ->where('model_type', Post::class)
    ->where('model_id', $post->id)
    ->latest()
    ->get();

// Via the model relationship
$post->chronicleEntries;
```

Excluding attributes
--------------------

[](#excluding-attributes)

**Global** — `config/chronicle.php`:

```
'exclude' => [
    'password',
    'remember_token',
],
```

**Per model** — merged with the global list:

```
class User extends Model
{
    use HasChronicle;

    protected array $chronicleExclude = [
        'api_token',
        'two_factor_secret',
    ];
}
```

Per-model overrides
-------------------

[](#per-model-overrides)

```
class User extends Model
{
    use HasChronicle;

    protected array $chronicleEvents = ['created', 'updated'];

    protected array $chronicleExclude = ['api_token'];

    protected array $chronicleOnly = ['name', 'email'];

    protected string $chronicleSnapshot = 'changes'; // or "full"
}
```

PropertyPurpose`$chronicleEvents`Which events to track on this model`$chronicleExclude`Extra attributes to omit (merged with config)`$chronicleOnly`If set, only these attributes are stored`$chronicleSnapshot``full` or `changes`Configuration
-------------

[](#configuration)

Publish to `config/chronicle.php`. Only `enabled` reads from the environment (`CHRONICLE_ENABLED`); everything else is config-only.

OptionDefaultDescription`enabled``true` (`CHRONICLE_ENABLED`)Globally enable/disable tracking`connection``null`DB connection (app default if null)`table``chronicle_entries`Table name`snapshot``full``full` or `changes``events``created`, `updated`, `deleted`Events to track`exclude``password`, `remember_token`Attributes never stored`only``[]`When set, only these attributes are stored`metadata.user_id``true`Store authenticated user ID`metadata.ip``true`Store request IP`metadata.user_agent``true`Store user agent`pretty_print``false`Pretty-print JSON snapshotsWhat gets stored
----------------

[](#what-gets-stored)

ColumnDescription`model_type`Eloquent morph class`model_id`Model primary key`event``created`, `updated`, or `deleted``before`JSON snapshot before the change`after`JSON snapshot after the change`user_id`Authenticated user (if available)`ip_address`Request IP (if available)`user_agent`User agent (if available)`created_at` / `updated_at`TimestampsExtensibility
-------------

[](#extensibility)

Recording goes through the `ChronicleRecorder` contract. Bind your own implementation to swap storage or queue writes later without changing the public API:

```
$this->app->singleton(
    \KeshavMansure\Chronicle\Contracts\ChronicleRecorder::class,
    \App\Chronicle\QueuedChronicleRecorder::class,
);
```

Testing
-------

[](#testing)

```
composer install
composer test
```

CI runs on PHP 8.2 / 8.3 against Laravel 11 and 12 (SQLite in-memory).

If your local PHP has no `pdo_sqlite`:

```
cp .env.testing.example .env.testing
# set DB_* and create the database, then:
composer test
```

Or install SQLite: `sudo apt install php8.2-sqlite3`

Roadmap
-------

[](#roadmap)

Not in the current version:

- Rollback support
- Diff viewer / dashboard UI
- Soft delete &amp; restore tracking
- Queue support
- Multi-tenant support
- Custom metadata providers

License
-------

[](#license)

MIT © [Keshav Mansure](https://github.com/keshavmansure)

###  Health Score

20

—

LowBetter than 12% of packages

Maintenance65

Regular maintenance activity

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity11

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/119107022?v=4)[keshavmansure](/maintainers/keshavmansure)[@keshavmansure](https://github.com/keshavmansure)

---

Top Contributors

[![keshavmansure](https://avatars.githubusercontent.com/u/119107022?v=4)](https://github.com/keshavmansure "keshavmansure (1 commits)")

### Embed Badge

![Health badge](/badges/keshavmansure-laravel-chronicle/health.svg)

```
[![Health](https://phpackages.com/badges/keshavmansure-laravel-chronicle/health.svg)](https://phpackages.com/packages/keshavmansure-laravel-chronicle)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
