PHPackages                             soloterm/notify - 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. soloterm/notify

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

soloterm/notify
===============

A PHP package to send desktop notifications via OSC escape sequences in terminal applications.

v0.1.0(5mo ago)34111MITPHPPHP ^8.1CI passing

Since Dec 16Pushed 5mo agoCompare

[ Source](https://github.com/soloterm/notify)[ Packagist](https://packagist.org/packages/soloterm/notify)[ RSS](/packages/soloterm-notify/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (1)Versions (2)Used By (1)

Notify
======

[](#notify)

[![Latest Version on Packagist](https://camo.githubusercontent.com/e66bb2ff003e404c63d175c886631b555530b8dbf6dfb57d79abb5194c23ad4c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f736f6c6f7465726d2f6e6f746966792e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/soloterm/notify)[![Total Downloads](https://camo.githubusercontent.com/8e7aa0a3ce58c982721db5eb65f7d54a1a72024d76d7e1451afc496a5ee508f1/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f736f6c6f7465726d2f6e6f746966792e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/soloterm/notify)[![License](https://camo.githubusercontent.com/55c0218c8f8009f06ad4ddae837ddd05301481fcf0dff8e0ed9dadda8780713e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265)](LICENSE)

A PHP library for sending desktop notifications via OSC escape sequences in terminal applications.

This library was built to support [Solo](https://github.com/soloterm/solo), your all-in-one Laravel command to tame local development.

**OSC Notifications (Ghostty)****OSC Notifications (iTerm2)**[![Ghostty OSC notification](art/ghostty-osc.png)](art/ghostty-osc.png)[![iTerm2 OSC notification](art/iterm-osc.png)](art/iterm-osc.png)**macOS Fallback****Fireworks (iTerm2)**[![macOS fallback notification](art/mac-fallback.png)](art/mac-fallback.png)[![iTerm2 fireworks](art/fireworks.png)](art/fireworks.png)**Progress Bars (Ghostty)****Progress Bars (iTerm2)**[![Ghostty progress bar](art/ghostty-progress.png)](art/ghostty-progress.png)[![iTerm2 progress bar](art/iterm-progress.png)](art/iterm-progress.png)Why Use This Library?
---------------------

[](#why-use-this-library)

Building CLI applications often requires notifying users when long-running tasks complete:

- Build finished
- Tests passed (or failed)
- Queue job completed
- Migration finished

Instead of relying on external tools like `notify-send` or `osascript`, this library uses OSC (Operating System Command) escape sequences that modern terminal emulators interpret directly. No dependencies, no shell commands, just pure PHP.

**When OSC isn't supported**, the library automatically falls back to system notification tools (`notify-send` on Linux, `osascript` on macOS, PowerShell on Windows).

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

[](#installation)

```
composer require soloterm/notify
```

Usage
-----

[](#usage)

```
use SoloTerm\Notify\Notify;

// Simple notification (message only)
Notify::send('Build complete!');

// Notification with title and body
Notify::send('All 142 tests passed in 3.2s', 'Tests Passed');

// Check if notifications are supported
if (Notify::canNotify()) {
    Notify::send('This will work!');
}

// Get detected terminal
$terminal = Notify::getTerminal(); // 'iterm2', 'kitty', 'wezterm', etc.

// Get selected protocol
$protocol = Notify::getProtocol(); // 'osc9', 'osc777', 'osc99'
```

### Real-World Examples

[](#real-world-examples)

```
// After a long build process
$startTime = microtime(true);
// ... build logic ...
$duration = round(microtime(true) - $startTime, 2);
Notify::send("Completed in {$duration}s", 'Build Finished');

// After running tests
$result = $testsPassed ? 'All tests passed!' : 'Some tests failed';
$title = $testsPassed ? 'Tests Passed' : 'Tests Failed';
Notify::send($result, $title);

// In a queue worker
while ($job = $queue->pop()) {
    $job->process();
    Notify::send("Processed: {$job->name}", 'Queue');
}
```

Terminal Compatibility
----------------------

[](#terminal-compatibility)

TerminalSupportProtocolNotes**iTerm2**✅OSC 9macOS**Kitty**✅OSC 99Cross-platform, full-featured**WezTerm**✅OSC 777Cross-platform**Ghostty**✅OSC 777Cross-platform**Foot**✅OSC 777Wayland**tmux**✅PassthroughRequires `allow-passthrough on`**GNU Screen**✅PassthroughAutomatic wrapping**Alacritty**⚠️FallbackUses system notifications**Terminal.app**⚠️FallbackUses system notifications**VS Code**⚠️FallbackUses system notifications**Windows Terminal**⚠️FallbackUses system notifications### tmux Configuration

[](#tmux-configuration)

For notifications to work inside tmux, add this to your `~/.tmux.conf`:

```
set -g allow-passthrough on
```

Then reload your tmux configuration:

```
tmux source-file ~/.tmux.conf
```

OSC Protocols
-------------

[](#osc-protocols)

This library supports three notification protocols:

### OSC 9 (iTerm2)

[](#osc-9-iterm2)

Simple message-only notifications. Widely supported.

```
ESC ] 9 ; message BEL

```

### OSC 777 (rxvt-unicode)

[](#osc-777-rxvt-unicode)

Supports separate title and body. Used by WezTerm, Ghostty, and VTE-based terminals.

```
ESC ] 777 ; notify ; title ; body BEL

```

### OSC 99 (Kitty)

[](#osc-99-kitty)

The most feature-rich protocol with support for urgency levels, notification IDs, and more.

```
ESC ] 99 ; metadata ; payload ST

```

Advanced Usage
--------------

[](#advanced-usage)

### Urgency Levels (Kitty/OSC 99 only)

[](#urgency-levels-kittyosc-99-only)

```
use SoloTerm\Notify\Notify;

// Send with explicit urgency
Notify::send('Background task done', 'Info', Notify::URGENCY_LOW);
Notify::send('Build complete', 'Success', Notify::URGENCY_NORMAL);
Notify::send('Server down!', 'Alert', Notify::URGENCY_CRITICAL);

// Convenience methods
Notify::sendLow('Low priority message');
Notify::sendCritical('Critical alert!');

// Set default urgency for all notifications
Notify::setDefaultUrgency(Notify::URGENCY_LOW);
```

### Notification IDs (Kitty/OSC 99 only)

[](#notification-ids-kittyosc-99-only)

Update or dismiss existing notifications using IDs - perfect for progress indicators:

```
// Send notification with an ID
Notify::send('Building... 0%', 'Build', id: 'build-progress');

// Update the same notification
Notify::send('Building... 50%', 'Build', id: 'build-progress');
Notify::send('Building... 100%', 'Build', id: 'build-progress');

// Close/dismiss a notification by ID
Notify::close('build-progress');

// Check if the terminal supports IDs
$caps = Notify::capabilities();
if ($caps['supports_id']) {
    // Use notification IDs
}
```

### External Fallback

[](#external-fallback)

When OSC notifications aren't supported, the library can fall back to system tools:

- **Linux**: `notify-send` (libnotify)
- **macOS**: `osascript` (AppleScript)
- **Windows**: PowerShell toast notifications

```
// Fallback is enabled by default - disable it if needed
Notify::disableFallback();

// Re-enable fallback
Notify::enableFallback();

// Check if fallback is available
if (Notify::canFallback()) {
    echo "System notifications available as fallback\n";
}

// Send using any available method (OSC or fallback)
Notify::sendAny('This works everywhere!', 'Hello');

// Send directly via external tools (bypassing OSC)
Notify::sendExternal('Message', 'Title');
```

### Bell Fallback

[](#bell-fallback)

```
// Send bell character (works everywhere)
Notify::bell();

// Try notification first, then external fallback, then bell
Notify::sendOrBell('Task complete', 'Done');
```

### Check Capabilities

[](#check-capabilities)

```
$caps = Notify::capabilities();
// Returns:
// [
//     'terminal' => 'kitty',
//     'protocol' => 'osc99',
//     'supports_title' => true,
//     'supports_urgency' => true,
//     'supports_id' => true,
//     'supports_progress' => true,
//     'in_multiplexer' => false,
//     'fallback_available' => true,
// ]

// List all known terminals and their support
$terminals = Notify::supportedTerminals();
// ['kitty' => 'osc99', 'iterm2' => 'osc9', 'alacritty' => null, ...]
```

### Force a Specific Protocol

[](#force-a-specific-protocol)

```
// Force OSC 777 regardless of detected terminal
Notify::forceProtocol('osc777');
Notify::send('Using OSC 777', 'Forced');

// Reset to auto-detection
Notify::forceProtocol(null);
```

### Check Multiplexer Status

[](#check-multiplexer-status)

```
if (Notify::inTmux()) {
    echo "Running inside tmux\n";
}

if (Notify::inScreen()) {
    echo "Running inside GNU Screen\n";
}
```

### Reset State

[](#reset-state)

```
// Useful for testing or when terminal changes
Notify::reset();
```

### Progress Bars (OSC 9;4)

[](#progress-bars-osc-94)

Display progress in your terminal's tab or taskbar:

```
// Check if supported
if (Notify::supportsProgress()) {
    // Show progress (0-100)
    Notify::progress(50);

    // Different states
    Notify::progressError(75);        // Red - error state
    Notify::progressPaused(60);       // Yellow - paused
    Notify::progressIndeterminate();  // Pulsing - unknown duration

    // Clear when done
    Notify::progressClear();
}
```

**Supported terminals**: Windows Terminal, Ghostty 1.2+, iTerm2 3.6.6+, ConEmu, Mintty

### Hyperlinks (OSC 8)

[](#hyperlinks-osc-8)

Create clickable links in terminal output:

```
echo Notify::hyperlink('https://example.com', 'Click here');
echo Notify::hyperlink('https://example.com'); // URL as display text
```

### Request Attention (iTerm2 only)

[](#request-attention-iterm2-only)

```
Notify::requestAttention();           // Bounce dock icon
Notify::fireworks();                  // Fireworks animation
Notify::stealFocus();                 // Bring window to front
```

How It Works
------------

[](#how-it-works)

1. **Terminal Detection**: The library checks environment variables like `KITTY_WINDOW_ID`, `ITERM_SESSION_ID`, `WEZTERM_PANE`, and `TERM_PROGRAM` to identify the terminal.
2. **Protocol Selection**: Based on the detected terminal, the optimal OSC protocol is selected.
3. **Sequence Building**: The notification message is sanitized and formatted according to the protocol.
4. **Multiplexer Passthrough**: If running inside tmux or GNU Screen, the sequence is wrapped in a DCS (Device Control String) passthrough.
5. **Output**: The escape sequence is written directly to STDOUT, which the terminal interprets and displays as a desktop notification.
6. **Fallback**: If OSC isn't supported, the library automatically tries system notification tools.

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

[](#requirements)

- PHP 8.1 or higher
- A supported terminal emulator (or system notification tools for fallback)
- For tmux: `allow-passthrough on` in your config

Testing
-------

[](#testing)

```
composer test
```

Contributing
------------

[](#contributing)

Contributions are welcome! Please feel free to submit a pull request.

License
-------

[](#license)

The MIT License (MIT).

Support
-------

[](#support)

This is free! If you want to support me:

- Check out my courses:
    - [Database School](https://databaseschool.com)
    - [Screencasting](https://screencasting.com)
- Help spread the word about things I make

Credits
-------

[](#credits)

Solo was developed by Aaron Francis. If you like it, please let me know!

- Twitter:
- Website:
- YouTube:
- GitHub:

Related Projects
----------------

[](#related-projects)

- [Solo](https://github.com/soloterm/solo) - All-in-one Laravel command for local development
- [Screen](https://github.com/soloterm/screen) - Pure PHP terminal renderer
- [Dumps](https://github.com/soloterm/dumps) - Laravel command to intercept dumps
- [Grapheme](https://github.com/soloterm/grapheme) - Unicode grapheme width calculator
- [Notify Laravel](https://github.com/soloterm/notify-laravel) - Laravel integration for soloterm/notify
- [TNotify](https://github.com/soloterm/tnotify) - Standalone, cross-platform CLI for desktop notifications
- [VTail](https://github.com/soloterm/vtail) - Vendor-aware tail for Laravel logs

###  Health Score

33

—

LowBetter than 75% of packages

Maintenance73

Regular maintenance activity

Popularity12

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity33

Early-stage or recently created project

 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

Unknown

Total

1

Last Release

153d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/033238953a59b9223a1bde703b5e4254e63c7412195da1cb9de5af44bf53fc0a?d=identicon)[aarondfrancis](/maintainers/aarondfrancis)

---

Top Contributors

[![aarondfrancis](https://avatars.githubusercontent.com/u/881931?v=4)](https://github.com/aarondfrancis "aarondfrancis (13 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/soloterm-notify/health.svg)

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

###  Alternatives

[mervick/emojionearea

WYSIWYG-like EmojiOne Converter / Picker Plugin for jQuery

941207.3k5](/packages/mervick-emojionearea)[lisachenko/protocol-fcgi

Implementation of FCGI Protocol in PHP

126104.5k2](/packages/lisachenko-protocol-fcgi)[sdboyer/gliph

A graph library for PHP.

17029.1k1](/packages/sdboyer-gliph)[pragmarx/zipcode

A worldwide address-by-zipcode searcher.

10265.4k](/packages/pragmarx-zipcode)

PHPackages © 2026

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