Cross-platform notifications for long-running agentic CLI tools
Project description
agent-notifier
agent-notifier sends notifications when long-running CLI/agent tasks finish.
It supports two usage styles:
- Wrap a command (
agent-notifier run -- ...) - Receive task-level events from interactive agents (Codex, Claude Code, Gemini, Ollama pipelines)
Why People Use This
- You can keep coding in one window and get notified when a background task completes.
- Notifications include success/failure, duration, and exit code.
- Works on macOS, Windows, and Linux (with console fallback when desktop notifications are unavailable).
Install
Recommended:
python3 -m pip install --user pipx
python3 -m pipx ensurepath
pipx install agent-notifier
agent-notifier setup codex
If you use multiple interactive CLIs from the current project:
agent-notifier setup all --project "$PWD"
Alternative:
pip install agent-notifier
Windows desktop toasts:
pipx install "agent-notifier[windows]"
If you already installed the base package on Windows, inject the fallback backend:
pipx inject agent-notifier win10toast
Linux desktop prerequisite:
sudo apt install libnotify-bin
If you want the latest local checkout instead of the current PyPI release:
cd /path/to/AgentPulse/packages/agent-notifier
pipx install .
From source:
python -m pip install -e .
Confirm install:
agent-notifier --help
agent-notifier setup codex
agent-notifier doctor --project "$PWD"
agent-notifier test-notifier --channel console
For safety, install does not silently edit your CLI configs.
Run agent-notifier setup codex once after install to wire Codex automatically.
Verified install status:
- PyPI package
agent-notifier 0.1.2was reachable and installable viapipx install agent-notifieron March 11, 2026. - If install succeeds but
agent-notifieris still not found, runpipx ensurepathand start a new shell.
Zero-To-Working Setup (macOS, Verified)
Validated on March 2, 2026 with:
- macOS 26.2
- iTerm2
codex-cli 0.107.0- Gemini CLI (
AfterAgenthook)
Run the helper from the repo checkout:
cd /path/to/AgentPulse/packages/agent-notifier
./examples/setup_macos.sh --trust-dir "/absolute/path/to/your/project" --open-settings
What this script does:
- Installs
terminal-notifierwith Homebrew when available. - Installs/updates
agent-notifierfrom local source checkout. - Configures Codex hook in
~/.codex/config.tomlusingnotify = [...]. - Configures Gemini
AfterAgenthook in~/.gemini/settings.json. - Marks your project as trusted in
~/.gemini/trustedFolders.json. - Creates timestamped backups before editing existing Codex/Gemini config files.
- Runs
test-notifierand a Codex bridge smoke test.
Important limitation:
- macOS notification permissions cannot be auto-granted by CLI tools.
- You must manually allow notifications for your terminal app (Terminal/iTerm) in System Settings -> Notifications.
2-Minute Quickstart
Run any long command through the wrapper:
agent-notifier run -- python3 -c "import time; time.sleep(8)"
If the command fails, the notification title changes to Failed.
Behavior Model
agent-notifier is task-level first for interactive tools.
It notifies when hook events fire (Codex/Claude/Gemini integrations), not when you exit your shell.
Interactive Tool Setup
Codex CLI
Codex provides a notification hook.
Recommended one-time setup after pipx install or pip install:
agent-notifier setup codex
That command:
- Writes the installed
agent-notifier-codex-hookentrypoint name by default. - Creates
~/.codex/config.tomlif it does not exist. - Adds the notifier hook without removing other existing
notifycommands. - Creates a timestamped backup before changing an existing config file.
That default keeps the generated config portable across machines. If you need to pin an absolute path on one machine, pass it explicitly:
agent-notifier setup codex --hook-command "$(command -v agent-notifier-codex-hook)"
If you want to inspect the hook path manually:
BRIDGE_PATH="$(command -v agent-notifier-codex-hook)"
echo "$BRIDGE_PATH"
If you're running from a source checkout, use the included script bridge:
chmod +x examples/codex_notifier_bridge.sh
BRIDGE_PATH="$(realpath examples/codex_notifier_bridge.sh)"
echo "$BRIDGE_PATH"
Manual config form:
notify = [
"agent-notifier-codex-hook"
]
You can also use an absolute path if your Codex environment does not inherit a reliable PATH.
Codex key naming:
notifyis the Codex config key (official in current Codex CLI builds).- It is unrelated to this package's internal naming (
agent-notifier).
Legacy filename examples/codex_notify_bridge.sh is also supported.
Optional debug logs:
export AGENT_NOTIFIER_DEBUG=1
Log location:
~/.agentnotifier/logs/codex_notifier.log
Manual Verified Flow: macOS + iTerm + Codex
Use this exact flow if you do not use examples/setup_macos.sh or agent-notifier setup codex:
- Set Codex config key to
notify(notnotifier) in~/.codex/config.toml:
notify = [
"agent-notifier-codex-hook"
]
If you are running directly from a source checkout without installing the package, use the script bridge path instead.
- Ensure the bridge is executable:
chmod +x examples/codex_notifier_bridge.sh
-
Restart Codex fully (fresh process), then complete one prompt.
-
If you still do not see a popup, enable debug and inspect hook calls:
export AGENT_NOTIFIER_DEBUG=1
tail -n 80 ~/.agentnotifier/logs/codex_notifier.log
- Manual bridge test (copy-paste safe):
./examples/codex_notifier_bridge.sh --channel both --verbose type=agent-turn-complete turn-id=manual-check
Expected behavior:
- You should hear a chime and/or see a desktop notification.
- The debug log should show
type=agent-turn-completepayloads andexit=0.
Common causes when chime works but popup does not:
- macOS notification permissions disabled for your terminal app.
- Focus / Do Not Disturb enabled.
- Banner style disabled in System Settings -> Notifications.
Claude Code
Recommended one-time setup from your project root:
agent-notifier setup claude --project "$PWD"
Preferred bridge command (installed via pipx/pip):
command -v agent-notifier-claude-hook
agent-notifier setup claude writes agent-notifier-claude-hook by default so the config stays portable.
If Claude runs in an environment with a restricted PATH, rerun setup with --hook-command "$(command -v agent-notifier-claude-hook)".
Configure hooks in .claude/settings.local.json (or user settings):
{
"hooks": {
"Stop": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "agent-notifier-claude-hook --event Stop"
}
]
}
],
"SubagentStop": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "agent-notifier-claude-hook --event SubagentStop"
}
]
}
]
}
}
Gemini CLI
Config files:
~/.gemini/settings.json(hooks)~/.gemini/trustedFolders.json(folder trust)
Preferred bridge command (installed via pipx/pip):
command -v agent-notifier-gemini-hook
agent-notifier setup gemini writes agent-notifier-gemini-hook by default so the config stays portable.
If Gemini runs without your normal shell PATH, rerun setup with --hook-command "$(command -v agent-notifier-gemini-hook)".
Recommended one-time setup from the project root:
agent-notifier setup gemini --project "$PWD"
Configure AfterAgent hook:
{
"hooksConfig": {
"enabled": true
},
"hooks": {
"AfterAgent": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "agent-notifier-gemini-hook",
"timeout": 10000
}
]
}
]
}
}
Gemini trust requirement:
- Hooks may not run in untrusted project folders.
- If
AfterAgentdoes not fire, confirm the current project path is trusted in~/.gemini/trustedFolders.json.
Quick check ($PROJECT_DIR is the folder where you run Gemini):
PROJECT_DIR="/absolute/path/to/your/project"
rg -n "\"$PROJECT_DIR\"|TRUST_FOLDER" ~/.gemini/trustedFolders.json
Example update:
PROJECT_DIR="/absolute/path/to/your/project"
jq --arg p "$PROJECT_DIR" '. + {($p):"TRUST_FOLDER"}' ~/.gemini/trustedFolders.json > /tmp/trustedFolders.json && mv /tmp/trustedFolders.json ~/.gemini/trustedFolders.json
Restart Gemini after changing trust settings.
Temporary hook-fire debug:
{
"type": "command",
"command": "agent-notifier-gemini-hook >> /tmp/gemini_afteragent.log 2>&1",
"timeout": 10000
}
Then run:
tail -n 20 /tmp/gemini_afteragent.log
Ollama
- Pure interactive
ollama runcurrently has no native per-turn completion hook. - If you use
ollama launch codexorollama launch claude, configure Codex/Claude hooks above. - For non-interactive JSON output (
--format json), pipe intoagent-notifier ollama-hook.
Example:
ollama run llama3 --format json | agent-notifier ollama-hook --name ollama --channel both
Core Commands
agent-notifier run -- <cmd...>
- Run and notify on completion.
- Wrapper exits with the same exit code as the wrapped command.
agent-notifier watch --pid <pid>
- Watch an existing process ID until exit.
agent-notifier test-notifier
- Send a sample notification.
agent-notifier doctor --project <path>
- Show backend, PATH, and hook configuration diagnostics for the current machine.
agent-notifier setup codex
- Configure Codex
notify = [...]automatically.
agent-notifier setup gemini --project <path>
- Configure Gemini
AfterAgentand trust the project folder.
agent-notifier setup claude --project <path>
- Configure Claude Code
StopandSubagentStophooks.
agent-notifier setup all --project <path>
- Configure Codex, Gemini, and Claude Code in one pass.
agent-notifier tail --file <path> --pattern <text>
- Notify when a log pattern appears.
Hook bridge commands used by integrations:
agent-notifier-codex-hookagent-notifier-gemini-hookagent-notifier-claude-hookagent-notifier codex-hook(direct mode)agent-notifier gemini-hook(direct mode)agent-notifier claude-hook(direct mode)agent-notifier ollama-hook
Common Customizations
Suppress notifications while terminal is focused (macOS):
agent-notifier gemini-hook --quiet-when-focused
Note: --quiet-when-focused is optional. If you copied older hook examples that included it by default and notifications seem missing, remove that flag.
Add sound:
agent-notifier claude-hook --chime ping
Force console output:
agent-notifier run --channel console -- your-command
Configuration
Environment variables:
AGENT_NOTIFIER_TITLE_PREFIX="Agent"AGENT_NOTIFIER_CHANNELS="desktop,console"AGENT_NOTIFIER_TAIL_LINES=20AGENT_NOTIFIER_POLL_INTERVAL=1.0
Optional TOML config at ~/.agentnotifier/config.toml:
title_prefix = "Agent"
channels = ["desktop"]
tail_lines = 20
poll_interval = 1.0
Environment variables override file values.
Troubleshooting
I only get notifications when I exit the CLI
Check your tool hooks configuration. This project intentionally focuses on task-level notifications.
If notifications only appear on session exit, verify your CLI is calling codex-hook, claude-hook, or gemini-hook on task completion events.
Desktop notifications do not appear
Run the doctor first:
agent-notifier doctor --project "$PWD"
- Test fallback path:
agent-notifier test-notifier --channel console
- Test desktop + diagnostics:
agent-notifier test-notifier --channel both --verbose
- Verify platform backend:
- macOS uses
terminal-notifierfirst, thenosascript - Windows uses PowerShell/BurntToast (with
win10toastfallback) - Linux uses
notify-send(packagelibnotify-binon Debian/Ubuntu)
- macOS uses
- macOS permission gate:
- Notifications must be allowed manually for your terminal app in System Settings -> Notifications.
Codex notifications not firing
- Confirm
notifyis configured in~/.codex/config.toml. - Confirm bridge command/path resolves:
command -v agent-notifier-codex-hook(preferred), orchmod +x examples/codex_notifier_bridge.sh(source checkout)
- Restart Codex after config changes (required).
- Enable bridge debug logs with
AGENT_NOTIFIER_DEBUG=1and inspect~/.agentnotifier/logs/codex_notifier.log. - Do not use the
notifierkey in Codex config; usenotify. - If Codex cannot find the command from
PATH, rerun setup with:agent-notifier setup codex --hook-command "$(command -v agent-notifier-codex-hook)"
Scenario Matrix (Quick Diagnosis)
Use this section to map a symptom to a concrete next action.
| Symptom | What it usually means | Verify | Fix |
|---|---|---|---|
| No notifications from Codex and log file never updates | Codex hook not wired | tail -n 20 ~/.agentnotifier/logs/codex_notifier.log after a completed turn |
Use notify = [...] in ~/.codex/config.toml and restart Codex |
Codex log updates with agent-turn-complete payloads but no popup |
Hook runs, desktop backend or OS UI is blocking | agent-notifier test-notifier --channel both --verbose |
Enable notifications for your terminal app, disable Focus/Do Not Disturb, enable banners |
| Chime plays but no popup | Sound path works, visual notifications blocked by OS settings | Run agent-notifier test-notifier --channel both --verbose |
In System Settings -> Notifications, allow alerts for terminal/iTerm and terminal-notifier (if listed) |
zsh: command not found: agent-notifier |
Installed in a different Python env or not on PATH |
command -v agent-notifier |
Use pipx ensurepath, update PATH, or pin the hook with agent-notifier setup codex --hook-command "$(command -v agent-notifier-codex-hook)" |
Manual bridge test prints [codex] Done but Codex turns show nothing |
Bridge itself is healthy; Codex config/session issue | Run manual test and compare with Codex log updates | Restart Codex fully; confirm notify = ["agent-notifier-codex-hook"] or the pinned absolute hook path |
Manual bridge command returns no output but exit code is 0 |
Event did not match (often malformed payload text) | Use key-value payload form | Run: ./examples/codex_notifier_bridge.sh --channel both --verbose type=agent-turn-complete turn-id=manual-check |
Gemini AfterAgent hook never runs |
Project path is untrusted in Gemini | Set hook command to write /tmp/gemini_afteragent.log and verify file updates |
Add project path as TRUST_FOLDER in ~/.gemini/trustedFolders.json, restart Gemini |
Desktop backend failure mentions terminal-notifier |
terminal-notifier present but failing/crashing |
agent-notifier test-notifier --channel both --verbose |
Reinstall/fix terminal-notifier or rely on osascript fallback |
| Linux desktop popup missing | notify-send missing/unavailable |
command -v notify-send |
Install libnotify-bin (Debian/Ubuntu) or use --channel console |
| Windows desktop popup missing | BurntToast/PowerShell path unavailable | agent-notifier test-notifier --channel both --verbose |
Install optional extras: pip install "agent-notifier[windows]" |
Platform Notes
macOS:
- Desktop notifications via
terminal-notifier(preferred, third-party) or Notification Center (osascriptfallback). terminal-notifieris not an Apple-official binary; it is a widely used open-source tool.- Install with Homebrew:
brew install terminal-notifier - You can still work without it because
osascriptfallback is built in.
Windows:
- Primary backend: PowerShell + BurntToast.
- Recommended install:
pipx install "agent-notifier[windows]". - If the package is already installed, add the Python fallback with
pipx inject agent-notifier win10toast.
Linux:
- Desktop notifications via
notify-send. - Debian/Ubuntu install:
sudo apt install libnotify-bin.
For Maintainers
Development checks:
python -m pip install -e ".[dev]"
ruff check .
pytest -q
python -m build
twine check dist/*
Release checklist:
docs/release_checklist.md
Project/process docs:
SECURITY.md
License
MIT (LICENSE)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agent_notifier-0.1.4.tar.gz.
File metadata
- Download URL: agent_notifier-0.1.4.tar.gz
- Upload date:
- Size: 41.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f6676ee0a39576a4e635bc02315d7a124a7879478b33487abfff44b7f98b2ff6
|
|
| MD5 |
7d624667afd4afaf969385fec0d99a90
|
|
| BLAKE2b-256 |
987b44e2269185f22eaa954e08cba06aafde2ce5ea6604393436c30462cc800f
|
File details
Details for the file agent_notifier-0.1.4-py3-none-any.whl.
File metadata
- Download URL: agent_notifier-0.1.4-py3-none-any.whl
- Upload date:
- Size: 42.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2bf700ccb88abc9de9514eb9b639768d2930ab6e6483eea928880f103ebe38f0
|
|
| MD5 |
aead4d94d05f865565879bdbce1196c3
|
|
| BLAKE2b-256 |
6af36886c89fa32aa46297e705e764f19af3a21cda0ef5ab4fc6199d3212e439
|