A standalone notification bridge for AI coding CLIs — stay informed without watching the terminal.
It sends macOS notifications when an agent:
- needs your decision (
DecisionRequired) - finishes a task turn (
TaskCompleted)
Supported agents:
| Agent | TaskCompleted | DecisionRequired |
|---|---|---|
| Claude Code | ✅ | ✅ |
| Codex | ✅ | ✅ |
| OpenCode | ✅ | ✅ |
| GitHub Copilot | ✅ | ✅ |
- macOS
- Node.js 20+
npm install
npm run buildInstall integrations (codex/opencode/copilot hooks in ~/.local/bin, Claude global hooks in ~/.claude/settings.json):
node dist/src/cli.js install --agents codex,claude,opencode,copilotIf ~/.local/bin is not in your PATH, add it:
export PATH="$HOME/.local/bin:$PATH"Checks platform support and whether agent binaries are resolvable.
node dist/src/cli.js doctorSends a test macOS notification.
node dist/src/cli.js test-notifyLow-level event ingestion endpoint used by adapters/hooks.
node dist/src/cli.js hook --agent codex --event exec_command_approval_request --payload '{"id":"x"}'All agents use the same approach: install writes directly to each agent's native config files. No shim or PATH manipulation required.
Merges two hooks into ~/.claude/settings.json:
{
"hooks": {
"Stop": [
{
"hooks": [{ "type": "command", "command": "node /path/to/cli.js hook --agent claude --event Stop" }]
}
],
"PermissionRequest": [
{
"matcher": "*",
"hooks": [{ "type": "command", "command": "node /path/to/cli.js hook --agent claude --event PermissionRequest" }]
}
]
}
}Claude Code passes the hook payload via stdin as JSON. For Stop:
{ "session_id": "...", "transcript_path": "/path/to/transcript.jsonl" }The Stop hook reads transcript_path to extract the last assistant response and shows its first 20 characters as the notification body.
To verify: cat ~/.claude/settings.json | jq '.hooks'
Merges a Stop hook into ~/.codex/hooks.json:
{
"hooks": {
"Stop": [
{
"hooks": [{ "type": "command", "command": "node /path/to/cli.js hook --agent codex --event Stop", "timeout": 5 }]
}
]
}
}To verify: cat ~/.codex/hooks.json | jq '.hooks'
Writes a JS plugin to ~/.aing-notify/opencode/plugin/aing-notify.js and adds to your shell profile (~/.zshrc / ~/.bashrc):
export OPENCODE_CONFIG_DIR="$HOME/.aing-notify/opencode"The plugin listens for session.idle (TaskCompleted) and permission.ask (DecisionRequired) events.
After install, restart your shell or run source ~/.zshrc for the env var to take effect.
Writes two files:
~/.aing-notify/hooks/copilot-hook.sh— shared hook script.github/hooks/aing-notify.jsonin the current directory at install time:
{
"version": 1,
"hooks": {
"sessionEnd": [{ "type": "command", "bash": "~/.aing-notify/hooks/copilot-hook.sh sessionEnd", "timeoutSec": 5 }],
"preToolUse": [{ "type": "command", "bash": "~/.aing-notify/hooks/copilot-hook.sh preToolUse", "timeoutSec": 5 }]
}
}Run install --agents copilot from each project that should receive Copilot notifications.
Each notification follows the format:
Title: Aing · <app> · <agent> · <event type>
<app>— terminal app name resolved fromTERM_PROGRAM(e.g.Superset,iTerm2,Terminal), omitted when unknown<agent>— agent name (e.g.claude,codex)<event type>—需要你做决策or任务已完成
Body:
TaskCompleted— first 20 characters of the last assistant response (from transcript), or任务已完成when no transcript is availableDecisionRequired— the permission request message, or the event label as fallback
Click behavior: clicking the notification activates the terminal app that spawned the agent.
Deduplication: repeated identical events within the TTL window (default 8 seconds) fire only one notification.
Set AING_BARK_KEY to your Bark app key to also receive push notifications on your iPhone/iPad:
export AING_BARK_KEY=your-bark-keynpm test- Notifications are macOS-only in v1.
- Copilot integration writes a project hook file (
.github/hooks/aing-notify.json) in the current repo. - Opencode integration assumes plugin loading from
OPENCODE_CONFIG_DIR/plugin/*.js. - Claude integration modifies global
~/.claude/settings.json.