Part of the Brigade fleet from Escoffier Labs

Push notifications that phone no one home.

agent-notify is the Aboyeur of your stack: the expediter that calls out when an agent finishes or needs input. Messages go from your machine straight to Discord, Telegram, or a self-hosted Signal CLI. No telemetry, no update checks, no vendor push service in the middle. Just a single Go binary and the channels you configured.

View on GitHub →

Same push UX you lose when you disable harness telemetry, with zero data flow you did not ask for.

How it works

Agent emits an event

  • Claude Code Stop and Notification hooks via --hook claude-code-*
  • Codex CLI notify line via --hook codex-notify
  • OpenClaw or Hermes session-end hooks pipe canonical JSON on stdin
  • Any tool: a shell wrapper with jq and --hook custom is the escape hatch
  • Or call it directly with a one-line message argument

Channels you configured

  • Env-only for the quick path: set a channel's vars and send
  • config.toml when you outgrow env: named channels and profiles
  • Secrets referenced by env-var name, never written to the file
  • Profiles group channels, set prefixes, and mark a default
  • doctor and status validate the wiring without sending
What you get

Zero telemetry, by design

No telemetry endpoints, ever. No update checks at startup or runtime. Outbound HTTP goes only to the channel URLs you configured, and nowhere else.

No persistent state

No state file, no log file, no cache. Each run reads your config and env, sends, and exits. A privacy test in the repo asserts these properties hold.

Secrets stay in env vars

The config references env-var names, not literal tokens. Bot tokens, webhook URLs, and Signal credentials never live in the config file on disk.

Single Go binary

One static binary you build and drop in ~/bin or /usr/local/bin. No runtime, no daemon, no third-party push infrastructure standing between your machine and the channel.

Routing precedence you control

Explicit --to overrides everything, then --profile, then a default profile, then all channels. --skip filters from any of them. Wiring is predictable and inspectable.

Honest exit codes

Exit 0 when every send succeeds, a count of failed channels otherwise, and 2 for a config or input error before any send. Easy to gate scripts on.

Three channels

Set env vars for the channels you want and send. A message with multiple channels configured fans out to all of them. Each channel formats the canonical message in its native style.

Discord

Setup. Set DISCORD_WEBHOOK_URL to a channel webhook.

Format. Embed with title and body, color by level, tags as inline fields, source as footer.

Telegram

Setup. Set TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID for the Bot API.

Format. Markdown V2 with a level emoji prefix, bold title, and tags as an italicized footer.

Signal

Setup. Set SIGNAL_CLI_URL, SIGNAL_FROM, and SIGNAL_TO for a self-hosted Signal CLI.

Format. Plain text with a level emoji prefix, title on its own line, and a [tag] footer.

Privacy posture

If you set DISABLE_TELEMETRY=1 to stop a harness from phoning home, you also lose its built-in mobile push, because that feature routes through the same telemetry plumbing. agent-notify gives you the same UX with zero data flow you did not ask for.

  • No telemetry endpoints. Ever.
  • No update checks at startup or runtime.
  • No persistent state. No state file, log file, or cache.
  • Outbound HTTP only to the channel URLs you configured.
  • A repo test asserts the above properties hold.

The v1 release is deliberately small: no retry queue, no templating, and three channels. A rate-limited or down channel means a dropped notification, and the canonical message goes through as-is. The boundaries are documented, not hidden.

Read the full README →
Command reference
CommandWhat it does
agent-notify "build finished"Send a message. The bare form is shorthand for the send subcommand.
agent-notify send "..."Explicit send. Fans out to the resolved channels for this run.
agent-notify initGenerate a starter config file at ~/.config/agent-notify/config.toml.
agent-notify status --jsonReport configured channels and profiles without sending anything.
agent-notify doctorValidate channel and profile wiring before you trust it. --json for scripts.
agent-notify hooks print claude-codePrint a ready-to-paste hook snippet for Claude Code settings.
agent-notify hooks print codexPrint the notify line for the Codex CLI config.toml.
agent-notify versionPrint version, commit, build date, Go version, and platform.