PHPackages                             skaisser/howl - 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. [Logging &amp; Monitoring](/categories/logging)
4. /
5. skaisser/howl

ActiveLibrary[Logging &amp; Monitoring](/categories/logging)

skaisser/howl
=============

Multi-driver Laravel notifier with Discord-first rich embeds, mentions, and bot-parseable metadata.

v1.0.1(4w ago)1193—7.4%MITPHPPHP ^8.3CI passing

Since May 11Pushed 2w agoCompare

[ Source](https://github.com/skaisser/howl)[ Packagist](https://packagist.org/packages/skaisser/howl)[ Docs](https://howl.skaisser.dev)[ RSS](/packages/skaisser-howl/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (2)Dependencies (7)Versions (8)Used By (0)

[![Howl — Multi-driver Laravel notifier](docs/public/logo-howl.svg)](docs/public/logo-howl.svg)**Multi-driver Laravel notifier — Discord, Slack, and Telegram with rich embeds.**

*When something goes wrong, your app should howl into the night.*

 [![Latest Version](https://camo.githubusercontent.com/b109cf56e8773ae0ed34a65ca6e123bb6c0a1457ab2727d150ead81248efbb53/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f736b6169737365722f686f776c2e7376673f7374796c653d666f722d7468652d6261646765266c6162656c3d5061636b616769737426636f6c6f723d454434323435)](https://packagist.org/packages/skaisser/howl) [![Total Downloads](https://camo.githubusercontent.com/78f8978c36ef34f6d20fc2fae9efbdfe237dd8b0650d381a7655b149ad6b4469/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f736b6169737365722f686f776c2e7376673f7374796c653d666f722d7468652d6261646765266c6162656c3d446f776e6c6f61647326636f6c6f723d353746323837)](https://packagist.org/packages/skaisser/howl) [![License](https://camo.githubusercontent.com/868e37da3b1e820baff23beb81fd6d472ea7798da841e52ad41894e3c5acc568/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f736b6169737365722f686f776c2e7376673f7374796c653d666f722d7468652d6261646765266c6162656c3d4c6963656e736526636f6c6f723d343136394531)](LICENSE)

 [![Tests](https://camo.githubusercontent.com/d9676ebff2ff85175e82dd669b3b99640c312a7d0505e470e4aa31aa9a0c240d/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f736b6169737365722f686f776c2f746573742e796d6c3f7374796c653d666f722d7468652d6261646765266c6162656c3d5465737473266c6f676f3d676974687562)](https://github.com/skaisser/howl/actions/workflows/test.yml) [![487 Tests Passing](https://camo.githubusercontent.com/019cc685c29a3e2a1376f5ca632f200694757c3d0e3d30796814606061e74427/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f54657374732d34383725323070617373696e672d737563636573733f7374796c653d666f722d7468652d6261646765266c6f676f3d70657374706870)](https://camo.githubusercontent.com/019cc685c29a3e2a1376f5ca632f200694757c3d0e3d30796814606061e74427/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f54657374732d34383725323070617373696e672d737563636573733f7374796c653d666f722d7468652d6261646765266c6f676f3d70657374706870) [![100% Coverage](https://camo.githubusercontent.com/63c60e2465f011a1170f9fb4b72a96604333ccb296101dbce57d9074483a8e90/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f436f7665726167652d3130302532352d627269676874677265656e3f7374796c653d666f722d7468652d6261646765266c6f676f3d636f6465636f76)](https://camo.githubusercontent.com/63c60e2465f011a1170f9fb4b72a96604333ccb296101dbce57d9074483a8e90/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f436f7665726167652d3130302532352d627269676874677265656e3f7374796c653d666f722d7468652d6261646765266c6f676f3d636f6465636f76)

 [![PHP 8.3 | 8.4](https://camo.githubusercontent.com/b2e3192e09b6e281d18a9fa24efadbd5311b135ca77470a8ccaf54dd70b7039b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e33253230253743253230382e342d3737374242343f7374796c653d666f722d7468652d6261646765266c6f676f3d706870266c6f676f436f6c6f723d7768697465)](https://camo.githubusercontent.com/b2e3192e09b6e281d18a9fa24efadbd5311b135ca77470a8ccaf54dd70b7039b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e33253230253743253230382e342d3737374242343f7374796c653d666f722d7468652d6261646765266c6f676f3d706870266c6f676f436f6c6f723d7768697465) [![Laravel 12 | 13](https://camo.githubusercontent.com/ede601864a8332e6ed6cbdd616cf9c98153d9d5a404f855289e0f116b719ee66/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d31322e7825323025374325323031332e782d4646324432303f7374796c653d666f722d7468652d6261646765266c6f676f3d6c61726176656c266c6f676f436f6c6f723d7768697465)](https://camo.githubusercontent.com/ede601864a8332e6ed6cbdd616cf9c98153d9d5a404f855289e0f116b719ee66/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d31322e7825323025374325323031332e782d4646324432303f7374796c653d666f722d7468652d6261646765266c6f676f3d6c61726176656c266c6f676f436f6c6f723d7768697465) [![Pest 3 | 4](https://camo.githubusercontent.com/77240199bd9cc72777f36a14cec01d92bfa8de88b925481958a8aa948091c642/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f506573742d332e78253230253743253230342e782d3564336565663f7374796c653d666f722d7468652d6261646765266c6f676f3d70657374706870266c6f676f436f6c6f723d7768697465)](https://camo.githubusercontent.com/77240199bd9cc72777f36a14cec01d92bfa8de88b925481958a8aa948091c642/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f506573742d332e78253230253743253230342e782d3564336565663f7374796c653d666f722d7468652d6261646765266c6f676f3d70657374706870266c6f676f436f6c6f723d7768697465)

 [![Discord](https://camo.githubusercontent.com/8c0fca73564f21d7a6f235747eb4d739a2e4aaa348b8e074904127baeb944b9e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446973636f72642d3538363546323f7374796c653d666f722d7468652d6261646765266c6f676f3d646973636f7264266c6f676f436f6c6f723d7768697465)](https://camo.githubusercontent.com/8c0fca73564f21d7a6f235747eb4d739a2e4aaa348b8e074904127baeb944b9e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446973636f72642d3538363546323f7374796c653d666f722d7468652d6261646765266c6f676f3d646973636f7264266c6f676f436f6c6f723d7768697465) [![Slack](https://camo.githubusercontent.com/28edab52068e19592d957d96845ade6c7b996a9e20bceea4eca1946ff449ec3c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f536c61636b2d3441313534423f7374796c653d666f722d7468652d6261646765266c6f676f3d736c61636b266c6f676f436f6c6f723d7768697465)](https://camo.githubusercontent.com/28edab52068e19592d957d96845ade6c7b996a9e20bceea4eca1946ff449ec3c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f536c61636b2d3441313534423f7374796c653d666f722d7468652d6261646765266c6f676f3d736c61636b266c6f676f436f6c6f723d7768697465) [![Telegram](https://camo.githubusercontent.com/f426e29bb7c70e6f7f69e9ddb8fbcde286bf79d74d1411ec0dee2843b54ea07e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f54656c656772616d2d3236413545343f7374796c653d666f722d7468652d6261646765266c6f676f3d74656c656772616d266c6f676f436f6c6f723d7768697465)](https://camo.githubusercontent.com/f426e29bb7c70e6f7f69e9ddb8fbcde286bf79d74d1411ec0dee2843b54ea07e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f54656c656772616d2d3236413545343f7374796c653d666f722d7468652d6261646765266c6f676f3d74656c656772616d266c6f676f436f6c6f723d7768697465)

**[📖 Full documentation at howl.skaisser.dev →](https://howl.skaisser.dev)**

---

✨ Why Howl?
-----------

[](#-why-howl)

A single driver-agnostic API for Discord, Slack, and Telegram. Drop it into any Laravel 12 or 13 app and start delivering rich, structured notifications in minutes.

- 🎯 **One fluent API for all three drivers** — switch per-call without touching business logic
- 🎨 **Rich, native formatting per platform** — Discord embeds, Slack Block Kit, Telegram HTML — with mentions, fields, code blocks, buttons, attachments
- 🛰️ **Channel failover &amp; fan-out** — automatic backup channel dispatch on failure
- 📦 **Seven built-in event templates** — exceptions, deployments, audits, cron heartbeats, job failures, manual ops, generic info
- 🧪 **HowlFake test helper** — assert notifications without real HTTP calls; per-driver assertions
- ⚡ **Queue-aware** with exponential backoff and opt-in Redis rate limiting
- ✅ **100% line coverage** across 487 tests, enforced by `pest --coverage --min=100`
- 📚 **Versioned docs** at `howl.skaisser.dev` plus machine-readable `llms.txt` for AI agents

---

🛠️ Compatibility
----------------

[](#️-compatibility)

PHPLaravelPestPHPUnitTestbenchStatus8.312.x3.x11.x10.x✅8.313.x4.x12.x11.x✅8.412.x3.x11.x10.x✅8.413.x4.x12.x11.x✅Composer constraints support all four combinations. CI validates the latest combo (PHP 8.4 × Laravel 13) on every push and PR targeting `main`; the other rows are validated locally before each release.

---

📦 Installation
--------------

[](#-installation)

```
composer require skaisser/howl
php artisan vendor:publish --tag=howl-config
```

Add your driver credentials to `.env`:

```
HOWL_DRIVER=discord                            # discord | slack | telegram
HOWL_DEFAULT_CHANNEL=errors                    # primary channel name

# Discord
HOWL_DISCORD_DEFAULT=https://discord.com/api/webhooks/...

# Slack (optional — only if you use the slack driver)
HOWL_SLACK_BOT_TOKEN=xoxb-...
HOWL_SLACK_DEFAULT_CHANNEL=C0XXXXXXX

# Telegram (optional — only if you use the telegram driver)
HOWL_TELEGRAM_BOT_TOKEN=123456:ABC-DEF...
HOWL_TELEGRAM_CHAT_ID=-1001234567890
```

---

🚀 Quick Start
-------------

[](#-quick-start)

```
use Skaisser\Howl\Facades\Howl;
use Skaisser\Howl\Events\GenericExceptionEvent;

// Direct severity verbs — use config('howl.driver') by default
Howl::error(new GenericExceptionEvent($exception));
Howl::info('Scheduled job completed');
Howl::audit($auditEvent);

// Channel routing — per-call override beats event default beats config
Howl::on('audits')->audit($event);

// Per-call driver override — same payload, different destination
Howl::driver('slack')->info('Deploy succeeded');
Howl::driver('telegram')->error('Database connection lost');

// Chainable: pick driver + channel + severity in one go
Howl::driver('slack')->channel('deployments')->success('v1.2.0 shipped');
```

### 📨 Built-in event templates

[](#-built-in-event-templates)

```
use Skaisser\Howl\Events\{
    GenericExceptionEvent,
    DeploymentEvent,
    AuditEvent,
    CronHeartbeatEvent,
    JobRetryExhaustedEvent,
    ManualOperationEvent,
    GenericInfoEvent,
};

Howl::error(new GenericExceptionEvent($e));
Howl::deployment(new DeploymentEvent(version: 'v1.2.0', env: 'production', commit: 'abc1234'));
Howl::audit(new AuditEvent(actor: $user->email, action: 'role.changed', target: $role));
```

---

🛰️ Channel Failover &amp; Fan-Out
---------------------------------

[](#️-channel-failover--fan-out)

Configure a backup channel and pick the mode:

```
// config/howl.php
'channel' => 'errors',
'channel_backup' => 'errors-backup',
'channel_mode' => 'failover',   // try primary; on failure, backup once
// or
'channel_mode' => 'fan_out',    // dispatch to BOTH channels in parallel
```

- **`failover`** (default): primary first, backup only on failure. `true` on first success, `false` if both fail.
- **`fan_out`**: dispatch to primary AND backup sequentially. `true` if at least one succeeds. **Doubles rate-limit consumption** — size your `RateLimiter::for()` quota accordingly.

---

🧪 Testing with HowlFake
-----------------------

[](#-testing-with-howlfake)

```
use Skaisser\Howl\Facades\Howl;

$fake = Howl::fake();

Howl::error('Something broke');
Howl::driver('slack')->info('Deploy started');

// Global assertions
$fake->assertSent(fn ($p) => $p->severity === 'error');
$fake->assertNothingSent(); // negation form
expect($fake->sent())->toHaveCount(2); // count via the sent() accessor

// Per-driver assertions (v1.0+)
$fake->assertSentVia('discord', fn ($p) => $p->severity === 'error');
$fake->assertSentVia('slack', fn ($p) => $p->severity === 'info');
$fake->assertSentViaNothing('telegram');
```

No real HTTP calls. No mocks of HTTP clients. Drop-in replacement.

---

⚡ Queue Mode + Rate Limiting
----------------------------

[](#-queue-mode--rate-limiting)

```
HOWL_QUEUE=true
HOWL_QUEUE_CONNECTION=redis
HOWL_QUEUE_NAME=default
HOWL_RATE_LIMITER_KEY=howl-discord   # opt-in Redis rate limiter
```

```
// AppServiceProvider::boot()
use Illuminate\Cache\RateLimiter;
use Illuminate\Cache\RateLimiting\Limit;

RateLimiter::for('howl-discord', fn () => Limit::perMinute(28));
```

`SendHowlJob` ships with 3 retries + exponential backoff. Queue-failure events always force sync to avoid recursive loops.

---

📖 Documentation
---------------

[](#-documentation)

The full docs site at **[howl.skaisser.dev](https://howl.skaisser.dev)** covers everything in depth:

- 🚦 [Installation &amp; Quick Start](https://howl.skaisser.dev/v1.0.0/guide/installation)
- 🤖 Drivers: [Discord](https://howl.skaisser.dev/v1.0.0/drivers/discord) · [Slack](https://howl.skaisser.dev/v1.0.0/drivers/slack) · [Telegram](https://howl.skaisser.dev/v1.0.0/drivers/telegram)
- 🎛️ [Configuration reference](https://howl.skaisser.dev/v1.0.0/configuration/reference)
- 🧪 [HowlFake testing guide](https://howl.skaisser.dev/v1.0.0/testing/howl-fake)
- 📜 [API reference](https://howl.skaisser.dev/v1.0.0/reference/api)
- ⬆️ [Upgrade guide v0.x → v1.0](https://howl.skaisser.dev/v1.0.0/upgrade)
- 📝 [Release notes](https://howl.skaisser.dev/v1.0.0/releases)

**For AI agents:** [llms.txt](https://howl.skaisser.dev/llms.txt) (index) · [llms-full.txt](https://howl.skaisser.dev/llms-full.txt) (inline)

---

🤝 Contributing
--------------

[](#-contributing)

Issues and pull requests welcome at [github.com/skaisser/howl](https://github.com/skaisser/howl).

Before opening a PR, run the full suite locally:

```
composer install
vendor/bin/pest --parallel
vendor/bin/pest --coverage --min=100   # enforces 100% line coverage
vendor/bin/pint                         # code style
```

---

📜 License
---------

[](#-license)

MIT — see [LICENSE](LICENSE). Copyright © Shirleyson Kaisser. // worktree test commit Wed May 13 03:12:54 -03 2026

###  Health Score

46

—

FairBetter than 92% of packages

Maintenance95

Actively maintained with recent releases

Popularity17

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 92.9% 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.

###  Release Activity

Cadence

Every ~0 days

Total

4

Last Release

28d ago

Major Versions

v0.2.1 → v1.0.02026-05-12

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/1593505?v=4)[Shirleyson Kaisser](/maintainers/skaisser)[@skaisser](https://github.com/skaisser)

---

Top Contributors

[![skaisser](https://avatars.githubusercontent.com/u/1593505?v=4)](https://github.com/skaisser "skaisser (13 commits)")[![cloudflare-workers-and-pages[bot]](https://avatars.githubusercontent.com/in/85455?v=4)](https://github.com/cloudflare-workers-and-pages[bot] "cloudflare-workers-and-pages[bot] (1 commits)")

---

Tags

alertsdiscordembedseventslaravellaravel-packageloggingmonitoringnotificationsobservabilityphpqueueslacktelegramwebhookwebhookslaravelloggingeventsnotificationswebhookobservabilitydiscordembeds

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/skaisser-howl/health.svg)

```
[![Health](https://phpackages.com/badges/skaisser-howl/health.svg)](https://phpackages.com/packages/skaisser-howl)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3325.1M337](/packages/psalm-plugin-laravel)

PHPackages © 2026

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