Attention hooks
An agent blocked on a permission prompt, or one that finished twenty minutes
ago, is only useful if you find out. magus session notify normalizes one host event
and, with --desktop, posts a desktop notification.
It does not publish an event to the daemon or Console. Use it to bring a person back to the host where the agent needs an answer.
printf '%s\n' "needs your approval" | magus session notify --outcome Notification --desktop
printf '%s\n' "finished" | magus session notify --outcome Stop -o json
Why this is not an MCP tool
An MCP server only ever observes tool calls. A blocked agent makes no call at all - the blockage IS the silence, and silence is precisely what MCP has no way to report. The host's own hook system is the only surface that fires on it. So this is a hook sink rather than a tool, and it stays one whether or not the daemon is up.
The envelope
--outcome takes whatever the host calls its event. It is classified by
substring, case-insensitively, into canonical outcomes: waiting,
permission, failed, finished, diagnostic, update. Anything
unrecognized becomes other and still notifies, because a missed alert is the
failure this exists to prevent.
When a host hands you JSON, shape it into the canonical envelope before piping it in. The command deliberately does not know host field names:
jq -c '{schema_version: 1, outcome: .hook_event_name, source: {kind: "agent"}, message: .message}' \
| magus session notify --desktop
Wiring it per host
The event names below are the ones each host documents. Check yours against its current documentation, because these move; the magus side never changes.
| host | event(s) to wire |
|---|---|
| Claude Code | Notification, Stop, SubagentStop |
| Codex | its hook or notify program setting |
| OpenCode | its plugin surface |
| Cursor | its agent hook surface |
| any other host | any event that means "a human is needed" |
Claude Code's Notification fires both on a permission prompt and on idle
waiting for input; its event JSON carries hook_event_name, message and
session_id. Its page has the config.
Fail quietly, on purpose
A notifier hook should exit 0 and swallow its own output. A notifier that can fail is a hook that can break the session it was meant to watch - the same reasoning as the guard's fail-open contract.
Resolve the binary the way the guard does: prefer a repo-local ./magus, then
PATH, and do nothing if neither exists. Do not fall back to a fixed path like
/tmp/magus; a stale binary there runs happily and enforces months-old rules
while looking perfectly healthy. magus doctor's guard binary check reports
which binary a hook would actually run and fails when it is older than your
working tree.