anotifier / discord

Discord notifications for AI coding agents.

Keep your agents' progress in the same place your team already hangs out. anotifier fires a Discord webhook when Claude Code, Codex, Cursor, or Gemini CLI wraps up or blocks on a question.

$ npx anotifier@latest setup
[ SET UP DISCORD ]

Wired up in a minute.

Discord's built-in webhooks are all you need — no bot token, no gateway connection. Create one on a channel and hand anotifier the URL.

agentsRun npx anotifier@latest setup once to wire your agents. It asks about phone push (ntfy) but not about webhooks, so Discord is added in the steps below.
DiscordOpen Server Settings → Integrations → Webhooks → New Webhook, pick a channel, and copy the webhook URL. You need the Manage Webhooks permission on the server.
configRun npx anotifier@latest config webhook and answer the prompts: enable the webhook, paste the URL, and enter discord as the format. Or add the block below to ~/.anotifier/config.json yourself.
testRun npx anotifier@latest test webhook. It posts anotifier and Test notification — if you see this, it works! to the channel.
[ CONFIG ]

One block in your config.

anotifier reads a single JSON file at ~/.anotifier/config.json. Drop this in and every supported agent uses it.

{
  "webhook": {
    "enabled": true,
    "url": "https://discord.com/api/webhooks/...",
    "format": "discord"
  }
}

Need auth? Add "authorization": "Bearer <token>" to the webhook block and anotifier sends it as the Authorization header.

[ WHAT IT POSTS ]

A bold title line, then the message.

Each alert is one POST to the webhook with a JSON body that has a single field, content. The title comes first in bold, and the message follows on the next line:

{
  "content": "**my-app · Claude Code**\nmy-app: Task complete"
}

anotifier sets no embeds, mentions, username or avatar, so Discord shows the post under the name and picture you gave the webhook. my-app is the name of the folder the agent was started in. What the message says depends on the agent:

AlertTitleMessage
Claude Code finished a turnmy-app · Claude CodeThe start of Claude's last reply, up to 180 characters. If no reply text can be read, my-app: Task complete.
Claude Code needs youmy-app · Claude CodeClaude's own notification text, such as a permission request or a question, up to 180 characters. Without text, a line such as my-app: Needs your input.
Codex CLI finished or wants approvalmy-app · Codexmy-app: Task complete or my-app: Needs your input. The command awaiting approval is not included.
Gemini CLI or Antigravity CLImy-app · Gemini or my-app · Antigravitymy-app: Task complete, and for Gemini CLI my-app: Needs your input.
Cursor finishedCursorTask complete. anotifier doesn't read a project folder from Cursor's event, so there is no project name.
Usage-limit and context warnings, update noticeSet by the warningPosted to the webhook as well when it is enabled.

A new agent session no longer posts Session started from 1.7.1 on; earlier versions did, and you can turn it back on with events.session_start.webhookEnabled.

  • Claude's words are on by default. webhook.richContent defaults to true, which is why the post carries what Claude said. Set it to false and every post is the generic line. Only Claude Code has reply text to send; the other agents are always generic.
[ KEEP IT QUIET ]

Mute one event, or everything for a while.

  • One event off. "events": { "task_complete": { "webhookEnabled": false } } keeps input requests and mutes completion posts. The anotifier config prompts have no per-event webhook setting, so edit config.json for this.
  • Snooze. npx anotifier@latest snooze 2h silences every channel, the webhook included. snooze off ends it early.
  • Quiet hours. "quietHours": { "enabled": true, "from": "22:00", "to": "08:00" } does the same every day on a schedule.
[ IF NOTHING ARRIVES ]

What each failure means, and the fix.

A webhook failure never reaches the agent. It is appended to ~/.anotifier/errors.log with the URL's origin only, and npx anotifier@latest status prints the latest ones. Start with npx anotifier@latest test webhook: it exits with an error if Discord doesn't answer with a 2xx status.

What you seeCauseFix
test prints webhook not configuredwebhook.enabled is off or url is empty.Run npx anotifier@latest config webhook.
webhook url is not a valid URL in the log, or webhook enabled but URL invalid from doctorThe URL was pasted with a typo, a missing https:// or stray quotes.Copy the URL from Discord again.
webhook endpoint responded 404 or 401Discord no longer accepts that URL: the webhook was deleted or its token changed.Create a new webhook in Server Settings and update webhook.url.
webhook endpoint responded 429Discord is rate-limiting the webhook. anotifier doesn't retry, so that post is lost.Mute an event or snooze to cut the volume. The next alert posts normally.
webhook request timed out after 5000msDiscord didn't answer within 5 seconds: a network, proxy or captive-portal problem.Check that this machine can reach discord.com. The next alert tries again.
test works but agent alerts don't arriveA snooze or quiet-hours window is active, the event has webhookEnabled: false, or the agent isn't wired.status shows Snooze, Quiet hours and which tools are wired.
Claude Code finished but nothing postedIts Stop hook fired while background subagents or shells were still running, so anotifier waited.Nothing is wrong. The post arrives when the background work ends.

Still stuck? Ask in the anotifier Discord.

[ SAFE BY DEFAULT ]

Your webhook is a secret, and stays one.

[+] Secrets stay secret Webhook URLs and bot tokens are never logged in full — only the URL's origin is recorded on failure.
[+] Never in the way Delivery errors go to ~/.anotifier/errors.log and never interrupt or slow the agent.
[+] Per-event off switch Silence a single event with events.task_complete.webhookEnabled: false.
[+] Rich Claude Code content Webhooks can carry what Claude actually said; other agents get generic text.
[ FAQ ]

Discord questions, answered.

How do I get a Discord notification when Claude Code finishes?

Create a Discord webhook under Server Settings → Integrations → Webhooks, then run npx anotifier@latest config webhook and enter its URL with the format discord. You can also set webhook.url and format: "discord" in ~/.anotifier/config.json yourself. anotifier posts to that channel every time an agent finishes or needs you.

Does anotifier expose my Discord webhook URL?

No. The webhook URL is treated as a secret and never logged in full — only its origin is recorded on failure, and errors are written to ~/.anotifier/errors.log without touching the running agent.

Can every AI agent post to the same Discord channel?

Yes. One config covers Claude Code, Codex CLI, Cursor, Gemini CLI, and VS Code agents, so they all report to the same Discord webhook.

How do I turn Discord alerts off for one event?

Add an events override to your config — for example { "events": { "task_complete": { "webhookEnabled": false } } } — to keep input requests but mute completion posts.

Does Discord see my code or conversation?

Only the notification text. For Claude Code that is the first 180 characters of its last reply, because webhook.richContent defaults to true. Set it to false and Discord only receives lines like my-app: Task complete. Other agents are always generic.

Does anotifier retry if Discord is down or rate-limits the webhook?

No. Each alert is one request with a 5-second timeout. An error status, a timeout or a network failure is logged to ~/.anotifier/errors.log and that post is dropped. Nothing is queued, and the next alert tries again.

Can I post to more than one Discord channel?

Not with one config. The webhook block holds a single URL, and every agent posts to it. Snooze, quiet hours and the per-event switches decide what reaches that channel.

[ WORKS WITH EVERY AGENT ]

One config, every agent.

anotifier routes the same Discord notification from every agent it supports:

[ ALSO SEND TO ]

Prefer a different destination?

anotifier can post the same alerts to slack, telegram, or phone push.

Every config key for this channel is in the docs.

Full feature tour, demo video, and install options on the anotifier home page.