{"id":51551322,"url":"https://github.com/DevinoSolutions/ai-agent-notifier","last_synced_at":"2026-07-12T14:01:14.896Z","repository":{"id":357955128,"uuid":"1239204116","full_name":"DevinoSolutions/ai-agent-notifier","owner":"DevinoSolutions","description":"Desktop \u0026 phone notifications for AI coding agents (Claude Code, Codex, Gemini CLI, Cursor). Native VS Code support. Toast + ntfy push. Zero dependencies.","archived":false,"fork":false,"pushed_at":"2026-06-19T19:21:31.000Z","size":294,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-19T21:14:50.489Z","etag":null,"topics":["ai-agent","ai-coding","claude-code","cli","codex","coding-agent","cross-platform","cursor","desktop-notifications","developer-tools","gemini-cli","hooks","nodejs","notifications","ntfy","productivity","push-notifications","toast","vscode"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DevinoSolutions.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-14T21:36:46.000Z","updated_at":"2026-06-19T19:21:35.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/DevinoSolutions/ai-agent-notifier","commit_stats":null,"previous_names":["devinosolutions/ai-agent-notifier"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/DevinoSolutions/ai-agent-notifier","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevinoSolutions%2Fai-agent-notifier","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevinoSolutions%2Fai-agent-notifier/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevinoSolutions%2Fai-agent-notifier/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevinoSolutions%2Fai-agent-notifier/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DevinoSolutions","download_url":"https://codeload.github.com/DevinoSolutions/ai-agent-notifier/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevinoSolutions%2Fai-agent-notifier/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35393398,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-12T02:00:06.386Z","response_time":87,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agent","ai-coding","claude-code","cli","codex","coding-agent","cross-platform","cursor","desktop-notifications","developer-tools","gemini-cli","hooks","nodejs","notifications","ntfy","productivity","push-notifications","toast","vscode"],"created_at":"2026-07-10T00:00:52.211Z","updated_at":"2026-07-12T14:01:14.885Z","avatar_url":"https://github.com/DevinoSolutions.png","language":"JavaScript","funding_links":[],"categories":["Remote Control, Notifications \u0026 Voice I/O"],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003eai-agent-notifier\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eDesktop \u0026 phone notifications for AI coding agents\u003c/strong\u003e\u003cbr /\u003e\n  One tool. One config. Every agent. Never miss when your AI finishes or needs input.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/icons/claude.png\" alt=\"Claude Code\" width=\"36\" /\u003e\u0026nbsp;\u0026nbsp;\n  \u003cimg src=\"assets/icons/codex.png\" alt=\"Codex CLI\" width=\"36\" /\u003e\u0026nbsp;\u0026nbsp;\n  \u003cimg src=\"assets/icons/cursor.png\" alt=\"Cursor\" width=\"36\" /\u003e\u0026nbsp;\u0026nbsp;\n  \u003cimg src=\"assets/icons/gemini.png\" alt=\"Gemini CLI\" width=\"36\" /\u003e\u0026nbsp;\u0026nbsp;\n  \u003cimg src=\"assets/icons/vscode.png\" alt=\"VS Code\" width=\"36\" /\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.npmjs.com/package/ai-agent-notifier\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/ai-agent-notifier?color=cb3837\u0026label=npm\" alt=\"npm version\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/ai-agent-notifier\"\u003e\u003cimg src=\"https://img.shields.io/npm/dm/ai-agent-notifier?color=blue\" alt=\"npm downloads\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/DevinoSolutions/ai-agent-notifier/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-AGPL--3.0-blue\" alt=\"License: AGPL-3.0\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://nodejs.org\"\u003e\u003cimg src=\"https://img.shields.io/badge/node-%3E%3D18-brightgreen\" alt=\"Node.js \u003e= 18\" /\u003e\u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/badge/dependencies-zero-success\" alt=\"Zero Dependencies\" /\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Windows-0078D6?style=flat-square\u0026logo=windows\u0026logoColor=white\" alt=\"Windows\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/macOS-000000?style=flat-square\u0026logo=apple\u0026logoColor=white\" alt=\"macOS\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Linux-FCC624?style=flat-square\u0026logo=linux\u0026logoColor=black\" alt=\"Linux\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Android-3DDC84?style=flat-square\u0026logo=android\u0026logoColor=white\" alt=\"Android\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/iOS-000000?style=flat-square\u0026logo=ios\u0026logoColor=white\" alt=\"iOS\" /\u003e\n\u003c/p\u003e\n\n---\n\n## Demo\n\nhttps://github.com/user-attachments/assets/5714b528-7e04-478e-abfd-2a3d05db562c\n\n[Watch with sound on YouTube](https://www.youtube.com/watch?v=QVVOIIud4-I)\n\n## Quick Start\n\n```bash\nnpx ai-agent-notifier setup\n```\n\nThat's it. The setup wizard detects your platform and installed AI tools, wires the hooks, and optionally configures phone push notifications. Restart your AI tools to activate.\n\n## Features\n\n- **Desktop toast notifications** -- Windows (BurntToast), macOS (Notification Center), Linux (libnotify)\n- **WSL-native toasts** -- real Windows toast notifications from inside WSL, no Linux notification daemon needed\n- **Phone push notifications** -- Android \u0026 iOS via [ntfy](https://ntfy.sh) (free, no account required)\n- **Webhook notifications** -- Slack, Discord, Telegram, or any HTTP endpoint, with an optional auth header\n- **Rich notification content** -- Claude Code toasts and webhooks show what the agent actually said or asked, not a generic line\n- **Terminal bell** -- audible ding in the terminal that launched the agent (works over SSH/tmux)\n- **Click-to-focus** -- click the toast to jump back to the terminal or VS Code window (Windows)\n- **Codex approval alerts** -- get notified the instant Codex asks for permission, not just when it finishes\n- **Per-tool branded icons** -- each tool gets its own logo in the notification\n- **One unified config** -- shared `~/.ai-agent-notifier/config.json` across all tools\n- **Atomic deduplication** -- prevents double notifications (e.g. Cursor's duplicate hook fires)\n- **Zero dependencies** -- pure Node.js built-ins only, no npm production packages\n\n## Supported Tools\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003cth\u003eTool\u003c/th\u003e\n    \u003cth\u003eVS Code\u003c/th\u003e\n    \u003cth\u003eCLI\u003c/th\u003e\n    \u003cth\u003eTask Complete\u003c/th\u003e\n    \u003cth\u003eNeeds Input\u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003cimg src=\"assets/icons/claude.png\" width=\"18\" /\u003e\u0026nbsp; \u003cstrong\u003eClaude Code\u003c/strong\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003eNative\u003c/td\u003e\n    \u003ctd align=\"center\"\u003eNative\u003c/td\u003e\n    \u003ctd\u003e\u003ccode\u003eStop\u003c/code\u003e\u003c/td\u003e\n    \u003ctd\u003e\u003ccode\u003eNotification\u003c/code\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003cimg src=\"assets/icons/codex.png\" width=\"18\" /\u003e\u0026nbsp; \u003cstrong\u003eCodex CLI\u003c/strong\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003eNative\u003c/td\u003e\n    \u003ctd align=\"center\"\u003eNative\u003c/td\u003e\n    \u003ctd\u003e\u003ccode\u003eStop\u003c/code\u003e\u003c/td\u003e\n    \u003ctd\u003e\u003ccode\u003ePermissionRequest\u003c/code\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003cimg src=\"assets/icons/cursor.png\" width=\"18\" /\u003e\u0026nbsp; \u003cstrong\u003eCursor\u003c/strong\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003eNative\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e--\u003c/td\u003e\n    \u003ctd\u003e\u003ccode\u003estop\u003c/code\u003e\u003c/td\u003e\n    \u003ctd\u003e--\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003cimg src=\"assets/icons/gemini.png\" width=\"18\" /\u003e\u0026nbsp; \u003cstrong\u003eGemini CLI\u003c/strong\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e--\u003c/td\u003e\n    \u003ctd align=\"center\"\u003eNative\u003c/td\u003e\n    \u003ctd\u003e\u003ccode\u003eAfterAgent\u003c/code\u003e\u003c/td\u003e\n    \u003ctd\u003e\u003ccode\u003eNotification\u003c/code\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nAll four tools are wired automatically by the setup wizard. No manual config editing needed. Codex's `PermissionRequest` hook fires the same \"needs your input\" alert when Codex asks for approval to run a command -- verified with Codex CLI \u003e=0.144.0.\n\n### VS Code Native Support\n\nClaude Code, Codex, and Cursor all run inside VS Code. **ai-agent-notifier** hooks directly into each tool's native hook system -- no VS Code extension required. The setup wizard detects installed tools and patches their configs automatically. Click a notification toast to jump straight back to your VS Code window.\n\n## Installation\n\n### npm (recommended)\n\n```bash\n# One-shot setup (no install needed)\nnpx ai-agent-notifier setup\n\n# Or install globally\nnpm i -g ai-agent-notifier\nai-agent-notifier setup\n```\n\n### Claude Code Plugin\n\n```\n/install-plugin https://github.com/DevinoSolutions/ai-agent-notifier\n```\n\nHooks auto-register. Use `/ai-agent-notifier:setup` to wire other tools.\n\n### Standalone (no npm)\n\n**Windows (PowerShell):**\n```powershell\nirm https://raw.githubusercontent.com/DevinoSolutions/ai-agent-notifier/main/setup/install.ps1 | iex\n```\n\n**macOS / Linux:**\n```bash\ncurl -fsSL https://raw.githubusercontent.com/DevinoSolutions/ai-agent-notifier/main/setup/install.sh | bash\n```\n\n## CLI Commands\n\n```\nai-agent-notifier setup          # First-time setup wizard\nai-agent-notifier status         # Show wired tools, config, backends\nai-agent-notifier test [channel] # Fire test notification (toast | ntfy | webhook | bell | both)\nai-agent-notifier config         # Interactive settings menu\nai-agent-notifier uninstall      # Remove hooks from all tools\n```\n\n## Configuration\n\nConfig lives at `~/.ai-agent-notifier/config.json`:\n\n```json\n{\n  \"ntfy\": {\n    \"enabled\": true,\n    \"server\": \"https://ntfy.sh\",\n    \"topic\": \"ai-agent-notifier-\u003crandom\u003e\",\n    \"click\": \"\"\n  },\n  \"toast\": {\n    \"enabled\": true,\n    \"clickToFocus\": true\n  },\n  \"terminalBell\": {\n    \"enabled\": true\n  },\n  \"webhook\": {\n    \"enabled\": false,\n    \"url\": \"\",\n    \"format\": \"generic\"\n  },\n  \"sentry\": {\n    \"enabled\": false,\n    \"dsn\": \"\"\n  },\n  \"events\": {\n    \"task_complete\": { \"toastSound\": \"IM\", \"priority\": \"default\" },\n    \"needs_input\": { \"toastSound\": \"Reminder\", \"priority\": \"urgent\" },\n    \"session_start\": { \"toastSound\": \"Default\", \"priority\": \"low\", \"terminalBellEnabled\": false }\n  }\n}\n```\n\n`ntfy.click` is the URL opened when you tap a phone notification (empty = no link). `terminalBell` rings the terminal that launched the agent -- for Claude Code (\u003e=2.1.141) it rings through Claude Code's own terminal write path (hook JSON `terminalSequence`), which is safe in tmux, GNU screen, and on Windows per Claude Code's docs; other agents get a direct TTY/console bell. `webhook` posts to Slack, Discord, Telegram, or any URL (see below). `sentry` is opt-in error reporting (see [Error visibility](#error-visibility)). Per-event `toastSound` names a Windows [BurntToast](https://github.com/Windos/BurntToast) sound and is ignored on macOS/Linux; `priority` (`min` / `low` / `default` / `high` / `urgent`) drives both the ntfy push priority and the Linux `notify-send` urgency.\n\n### ntfy -- Phone Push Notifications\n\n[ntfy](https://ntfy.sh) sends free push notifications to your phone -- no account needed.\n\n1. Install the ntfy app ([Android](https://play.google.com/store/apps/details?id=io.heckel.ntfy) / [iOS](https://apps.apple.com/app/ntfy/id1625396347))\n2. Subscribe to your topic (shown during setup)\n3. All your AI tools' notifications appear in one stream\n\n### Webhook -- Slack, Discord, Telegram, or anything\n\nSet `webhook.enabled: true` and a `webhook.url` to POST a notification to any HTTP endpoint. `format` selects the payload shape:\n\n**Slack:**\n```json\n{\n  \"webhook\": {\n    \"enabled\": true,\n    \"url\": \"https://hooks.slack.com/services/...\",\n    \"format\": \"slack\"\n  }\n}\n```\n\n**Discord:**\n```json\n{\n  \"webhook\": {\n    \"enabled\": true,\n    \"url\": \"https://discord.com/api/webhooks/...\",\n    \"format\": \"discord\"\n  }\n}\n```\n\n**Telegram:**\n```json\n{\n  \"webhook\": {\n    \"enabled\": true,\n    \"url\": \"https://api.telegram.org/bot\u003ctoken\u003e/sendMessage\",\n    \"format\": \"telegram\",\n    \"chatId\": \"123456789\"\n  }\n}\n```\n\n**Generic (anything else):**\n```json\n{\n  \"webhook\": {\n    \"enabled\": true,\n    \"url\": \"https://example.com/hook\",\n    \"format\": \"generic\",\n    \"authorization\": \"Bearer \u003ctoken\u003e\"\n  }\n}\n```\nGeneric POSTs `{title, message, source, project, event, timestamp}` as JSON. `authorization`, if set, is sent as the `Authorization` header for any format, not just generic.\n\nWebhook failures are logged with the URL's origin only, never the full URL -- a Slack/Discord webhook URL or a Telegram bot token is a secret, and errors.log can be mirrored to Sentry.\n\nTest it with `ai-agent-notifier test webhook`, or turn it off for one event type with `\"events\": {\"task_complete\": {\"webhookEnabled\": false}}`.\n\n### Rich notification content\n\nFor Claude Code, toast and webhook notifications show what actually happened instead of a generic \"task complete\" line: a \"needs input\" notification carries Claude's own question, and a \"task complete\" notification carries the last assistant message, both read from the Claude Code transcript and trimmed to a short snippet. Session-start notifications stay generic (nothing to show yet). Other agents (Codex, Cursor, Gemini) always get the generic text -- transcript reading is Claude Code-only.\n\nControlled per channel:\n\n| Channel | Config key | Default |\n|---------|-----------|:-------:|\n| Toast | `toast.richContent` | `true` |\n| Webhook | `webhook.richContent` | `true` |\n| ntfy | `ntfy.richContent` | `false` |\n\n`ntfy.richContent` defaults to **false** for privacy: the default `ntfy.sh` server is public, ntfy topic names are guessable rather than access-controlled secrets, and a snippet of your conversation would leak to anyone who guesses or stumbles on your topic. Only enable `ntfy.richContent` if you run your own private ntfy server, or you've deliberately accepted that risk on the public one.\n\n### Per-Event Settings\n\n| Event | Default `toastSound` | Default `priority` | Description |\n|-------|:------------:|:-------------:|-------------|\n| `task_complete` | IM | default | Agent finished its task |\n| `needs_input` | Reminder | urgent | Agent needs your input or permission |\n| `session_start` | Default | low | New session started (all channels off by default) |\n\n### Error visibility\n\nHook and channel errors never interrupt your agent -- they're appended to `~/.ai-agent-notifier/errors.log` and surfaced by `npx ai-agent-notifier status`, so a misconfigured toast backend or unreachable ntfy topic shows up as a logged error instead of a silent no-op. Set `sentry.enabled` to `true` (with a `sentry.dsn`) to also mirror those errors to [Sentry](https://sentry.io) through a built-in, zero-dependency envelope client: no SDK is bundled, no telemetry is collected, and nothing leaves your machine unless you opt in -- only error data is sent.\n\n## How It Works\n\nEach AI tool's hook system pipes event data to `notify.mjs`:\n\n```\nHook fires (stdin JSON + --source flag)\n  -\u003e parse-input.mjs   (normalize across tools)\n  -\u003e router.mjs        (map event to notification type)\n  -\u003e transcript.mjs    (Claude Code only: derive rich message text)\n  -\u003e platform toast    (Windows / macOS / Linux / WSL)\n  -\u003e ntfy push         (phone notification)\n  -\u003e webhook POST      (Slack / Discord / Telegram / generic)\n  -\u003e terminal bell     (Claude Code: terminalSequence in the hook reply;\n                        other tools: BEL to the controlling terminal)\n```\n\n## Platform Details\n\n### Windows\n\n- [BurntToast](https://github.com/Windos/BurntToast) PowerShell module for rich toast notifications\n- Click-to-focus via custom `agentfocus://` URI protocol\n- BurntToast auto-installed during setup if missing\n- Requires PowerShell 7+ (pwsh)\n\n### macOS\n\n- Uses built-in `osascript` -- zero additional dependencies\n- Falls back to `terminal-notifier` for richer features if available\n\n### Linux\n\n- Uses `notify-send` (libnotify) -- available on most desktop distributions\n- Fails silently on headless systems without a GUI (see WSL below for WSL2)\n\n### WSL\n\n- Auto-detected -- no config needed\n- Toast notifications route to a real Windows toast via PowerShell interop (`powershell.exe`/`pwsh.exe` across the `/mnt/c` boundary), not `notify-send`/D-Bus\n- Needs WSL2 interop enabled and a Windows PowerShell present -- both are on by default\n- Terminal bell and ntfy behave exactly as on native Linux\n\n## Requirements\n\n| Requirement | Details |\n|-------------|---------|\n| **Node.js** | \u003e= 18.0.0 (already present for all supported AI tools) |\n| **Windows** | PowerShell 7+ (pwsh) |\n| **macOS** | osascript (built-in) |\n| **Linux** | notify-send (optional, for desktop toasts) |\n\n## Uninstall\n\n```bash\nai-agent-notifier uninstall\n```\n\nRemoves all managed hooks from every tool's config. Original configs are backed up at `~/.ai-agent-notifier/backups/`.\n\n## Testing\n\nEverything below is verified against the **real thing** — no mocks, no stubs, no fakes. Real ntfy.sh push delivery, a real Linux notification daemon receiving the exact payload, the real agent CLIs installed from npm and driven end to end, and the real native OS toast backends actually firing. Every job is **required** and **hard-fails**: a broken key, a renamed secret, or a hook that doesn't deliver turns CI red instead of skipping silently.\n\n### What CI verifies on every run — all real, all platforms\n\nEach job runs as its own GitHub Actions workflow. The badge in every row is its **live status on `main`** — not a screenshot — so click any badge to see the actual run and its per-test logs.\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth\u003eJob\u003c/th\u003e\n      \u003cth align=\"center\" width=\"180\"\u003eLive status\u003c/th\u003e\n      \u003cth\u003ePlatforms\u003c/th\u003e\n      \u003cth\u003eWhat is actually exercised (no mocks)\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003cstrong\u003eUnit\u003c/strong\u003e\u003c/td\u003e\n      \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/DevinoSolutions/ai-agent-notifier/actions/workflows/unit.yml\"\u003e\u003cimg src=\"https://github.com/DevinoSolutions/ai-agent-notifier/actions/workflows/unit.yml/badge.svg?branch=main\" alt=\"Unit\" /\u003e\u003c/a\u003e\u003c/td\u003e\n      \u003ctd\u003eLinux · macOS · Windows\u003c/td\u003e\n      \u003ctd\u003eThe full unit + integration suite against the real exported code (not inline copies)\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003cstrong\u003eE2E real-world\u003c/strong\u003e\u003c/td\u003e\n      \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/DevinoSolutions/ai-agent-notifier/actions/workflows/e2e.yml\"\u003e\u003cimg src=\"https://github.com/DevinoSolutions/ai-agent-notifier/actions/workflows/e2e.yml/badge.svg?branch=main\" alt=\"E2E\" /\u003e\u003c/a\u003e\u003c/td\u003e\n      \u003ctd\u003eLinux · macOS · Windows\u003c/td\u003e\n      \u003ctd\u003eReal \u003ccode\u003esetup\u003c/code\u003e/\u003ccode\u003euninstall\u003c/code\u003e subprocesses against an isolated HOME · real \u003ccode\u003enotify.mjs\u003c/code\u003e hook invocation per source · \u003cstrong\u003ereal ntfy.sh round-trip\u003c/strong\u003e (push sent, then read back off the server)\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003cstrong\u003eInstall + smoke-load\u003c/strong\u003e\u003c/td\u003e\n      \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/DevinoSolutions/ai-agent-notifier/actions/workflows/agents.yml\"\u003e\u003cimg src=\"https://github.com/DevinoSolutions/ai-agent-notifier/actions/workflows/agents.yml/badge.svg?branch=main\" alt=\"Agents\" /\u003e\u003c/a\u003e\u003c/td\u003e\n      \u003ctd\u003eLinux · macOS · Windows\u003c/td\u003e\n      \u003ctd\u003eInstalls the \u003cstrong\u003ereal\u003c/strong\u003e Claude, Codex, Gemini (and Cursor where available) CLIs from npm, asserts they launch, and smoke-loads each hook (Codex classification pinned — drift fails CI)\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003cstrong\u003eLive Claude\u003c/strong\u003e\u003c/td\u003e\n      \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/DevinoSolutions/ai-agent-notifier/actions/workflows/live-claude.yml\"\u003e\u003cimg src=\"https://github.com/DevinoSolutions/ai-agent-notifier/actions/workflows/live-claude.yml/badge.svg?branch=main\" alt=\"Live Claude\" /\u003e\u003c/a\u003e\u003c/td\u003e\n      \u003ctd\u003eLinux\u003c/td\u003e\n      \u003ctd\u003eDrives the \u003cstrong\u003ereal\u003c/strong\u003e Claude CLI end to end (paid); hard-fails if the hook doesn't deliver a notification\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003cstrong\u003eLive Gemini\u003c/strong\u003e\u003c/td\u003e\n      \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/DevinoSolutions/ai-agent-notifier/actions/workflows/live-gemini.yml\"\u003e\u003cimg src=\"https://github.com/DevinoSolutions/ai-agent-notifier/actions/workflows/live-gemini.yml/badge.svg?branch=main\" alt=\"Live Gemini\" /\u003e\u003c/a\u003e\u003c/td\u003e\n      \u003ctd\u003eLinux\u003c/td\u003e\n      \u003ctd\u003eDrives the \u003cstrong\u003ereal\u003c/strong\u003e Gemini CLI end to end; hard-fails if the hook doesn't deliver a notification\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003cstrong\u003eLive Codex\u003c/strong\u003e\u003c/td\u003e\n      \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/DevinoSolutions/ai-agent-notifier/actions/workflows/live-codex.yml\"\u003e\u003cimg src=\"https://github.com/DevinoSolutions/ai-agent-notifier/actions/workflows/live-codex.yml/badge.svg?branch=main\" alt=\"Live Codex\" /\u003e\u003c/a\u003e\u003c/td\u003e\n      \u003ctd\u003eLinux\u003c/td\u003e\n      \u003ctd\u003eValidates \u003ccode\u003eOPENAI_API_KEY\u003c/code\u003e against the \u003cstrong\u003elive OpenAI API\u003c/strong\u003e + the real Codex config-patch wiring ¹\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003cstrong\u003eLive Cursor\u003c/strong\u003e\u003c/td\u003e\n      \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/DevinoSolutions/ai-agent-notifier/actions/workflows/live-cursor.yml\"\u003e\u003cimg src=\"https://github.com/DevinoSolutions/ai-agent-notifier/actions/workflows/live-cursor.yml/badge.svg?branch=main\" alt=\"Live Cursor\" /\u003e\u003c/a\u003e\u003c/td\u003e\n      \u003ctd\u003eLinux\u003c/td\u003e\n      \u003ctd\u003eValidates the real Cursor config-patch wiring (BYO key) ¹\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003cstrong\u003eLive Toast Linux\u003c/strong\u003e\u003c/td\u003e\n      \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/DevinoSolutions/ai-agent-notifier/actions/workflows/toast-linux.yml\"\u003e\u003cimg src=\"https://github.com/DevinoSolutions/ai-agent-notifier/actions/workflows/toast-linux.yml/badge.svg?branch=main\" alt=\"Toast Linux\" /\u003e\u003c/a\u003e\u003c/td\u003e\n      \u003ctd\u003eLinux\u003c/td\u003e\n      \u003ctd\u003eFires through the real \u003ccode\u003enotify-send\u003c/code\u003e backend into a \u003cstrong\u003ereal \u003ccode\u003edunst\u003c/code\u003e daemon\u003c/strong\u003e, then reads its history and asserts it captured the exact title + body\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003cstrong\u003eLive Toast Native\u003c/strong\u003e\u003c/td\u003e\n      \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/DevinoSolutions/ai-agent-notifier/actions/workflows/toast-native.yml\"\u003e\u003cimg src=\"https://github.com/DevinoSolutions/ai-agent-notifier/actions/workflows/toast-native.yml/badge.svg?branch=main\" alt=\"Toast Native\" /\u003e\u003c/a\u003e\u003c/td\u003e\n      \u003ctd\u003emacOS · Windows\u003c/td\u003e\n      \u003ctd\u003eFires the \u003cstrong\u003ereal\u003c/strong\u003e \u003ccode\u003eosascript\u003c/code\u003e / BurntToast backend and asserts the OS accepted the toast\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n¹ Codex and Cursor don't round-trip a prompt through their API in CI — `codex exec` needs OpenAI Tier 1+ WebSocket access, and Cursor is a GUI editor. Their hook **delivery** is fully covered by the unit + e2e suites; these jobs verify the live key and the real config wiring.\n\n### Run it yourself\n\n```bash\nnpm test            # offline: the full unit + integration suite\nnpm run test:e2e    # real ntfy.sh round-trip, needs network\nnpm run toast:demo  # fire real desktop toasts, every event\n```\n\n### The one thing CI can't prove\n\nHeadless CI has no display or login session, so it verifies **delivery** (a real daemon received the payload) and **backend success** (the OS accepted the call) — but it cannot prove a human visually *sees* a banner appear. macOS and Windows also silently suppress toasts under Do Not Disturb / Focus or denied notification permission, returning success either way. To confirm with your own eyes on your own machine, run `npm run toast:demo` and watch them pop.\n\n## Contributing\n\nContributions are welcome. Please open an issue first to discuss what you'd like to change.\n\n## License\n\n[AGPL-3.0](LICENSE) -- Copyright (c) 2026 [DevinoSolutions](https://github.com/DevinoSolutions)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDevinoSolutions%2Fai-agent-notifier","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FDevinoSolutions%2Fai-agent-notifier","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDevinoSolutions%2Fai-agent-notifier/lists"}