soloterm/notify
Composer 安装命令:
composer require soloterm/notify
包简介
A PHP package to send desktop notifications via OSC escape sequences in terminal applications.
README 文档
README
A PHP library for sending desktop notifications via OSC escape sequences in terminal applications.
This library was built to support Solo, your all-in-one Laravel command to tame local development.
| OSC Notifications (Ghostty) | OSC Notifications (iTerm2) |
![]() |
![]() |
| macOS Fallback | Fireworks (iTerm2) |
![]() |
![]() |
| Progress Bars (Ghostty) | Progress Bars (iTerm2) |
![]() |
![]() |
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
composer require soloterm/notify
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
// 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 | Support | Protocol | Notes |
|---|---|---|---|
| iTerm2 | ✅ | OSC 9 | macOS |
| Kitty | ✅ | OSC 99 | Cross-platform, full-featured |
| WezTerm | ✅ | OSC 777 | Cross-platform |
| Ghostty | ✅ | OSC 777 | Cross-platform |
| Foot | ✅ | OSC 777 | Wayland |
| tmux | ✅ | Passthrough | Requires allow-passthrough on |
| GNU Screen | ✅ | Passthrough | Automatic wrapping |
| Alacritty | ⚠️ | Fallback | Uses system notifications |
| Terminal.app | ⚠️ | Fallback | Uses system notifications |
| VS Code | ⚠️ | Fallback | Uses system notifications |
| Windows Terminal | ⚠️ | Fallback | Uses system notifications |
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
This library supports three notification protocols:
OSC 9 (iTerm2)
Simple message-only notifications. Widely supported.
ESC ] 9 ; message BEL
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)
The most feature-rich protocol with support for urgency levels, notification IDs, and more.
ESC ] 99 ; metadata ; payload ST
Advanced Usage
Urgency Levels (Kitty/OSC 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)
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
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
// Send bell character (works everywhere) Notify::bell(); // Try notification first, then external fallback, then bell Notify::sendOrBell('Task complete', 'Done');
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 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
if (Notify::inTmux()) { echo "Running inside tmux\n"; } if (Notify::inScreen()) { echo "Running inside GNU Screen\n"; }
Reset State
// Useful for testing or when terminal changes Notify::reset();
Progress Bars (OSC 9;4)
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)
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)
Notify::requestAttention(); // Bounce dock icon Notify::fireworks(); // Fireworks animation Notify::stealFocus(); // Bring window to front
How It Works
-
Terminal Detection: The library checks environment variables like
KITTY_WINDOW_ID,ITERM_SESSION_ID,WEZTERM_PANE, andTERM_PROGRAMto identify the terminal. -
Protocol Selection: Based on the detected terminal, the optimal OSC protocol is selected.
-
Sequence Building: The notification message is sanitized and formatted according to the protocol.
-
Multiplexer Passthrough: If running inside tmux or GNU Screen, the sequence is wrapped in a DCS (Device Control String) passthrough.
-
Output: The escape sequence is written directly to STDOUT, which the terminal interprets and displays as a desktop notification.
-
Fallback: If OSC isn't supported, the library automatically tries system notification tools.
Requirements
- PHP 8.1 or higher
- A supported terminal emulator (or system notification tools for fallback)
- For tmux:
allow-passthrough onin your config
Testing
composer test
Contributing
Contributions are welcome! Please feel free to submit a pull request.
License
The MIT License (MIT).
Support
This is free! If you want to support me:
- Check out my courses:
- Help spread the word about things I make
Credits
Solo was developed by Aaron Francis. If you like it, please let me know!
- Twitter: https://twitter.com/aarondfrancis
- Website: https://aaronfrancis.com
- YouTube: https://youtube.com/@aarondfrancis
- GitHub: https://github.com/aarondfrancis/solo
Related Projects
- Solo - All-in-one Laravel command for local development
- Screen - Pure PHP terminal renderer
- Dumps - Laravel command to intercept dumps
- Grapheme - Unicode grapheme width calculator
- Notify Laravel - Laravel integration for soloterm/notify
- TNotify - Standalone, cross-platform CLI for desktop notifications
- VTail - Vendor-aware tail for Laravel logs
soloterm/notify 适用场景与选型建议
soloterm/notify 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 41 次下载、GitHub Stars 达 3, 最近一次更新时间为 2025 年 12 月 16 日, 在 PHP 生态内属于活跃度较高的组件。
我们在过去多个企业项目中使用过 soloterm/notify 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 soloterm/notify 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
统计信息
- 总下载量: 41
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 3
- 点击次数: 33
- 依赖项目数: 1
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-12-16





