Back to catalogue
NotificationNotification
Slack notification on agent event
Pings your Slack when the agent needs you
Relays agent notifications (permission request, awaiting input) to a Slack channel via webhook, useful for long or unattended sessions.
What does the Slack notification on agent event hook do?
Slack notification on agent event is a Claude Code Notification hook. It fires automatically at that lifecycle event — outside the model, so it can't be skipped or forgotten. Pings your Slack when the agent needs you.
As a Notification hook it runs after the action, reacting to what just happened rather than blocking it. Because it is a deterministic Node.js script, it executes on every matching event without relying on the model to remember — the guarantee that makes agentic workflows safe to automate.
Use cases
- Long sessions
- Remote supervision
- Team collaboration
Tags
#notification#slack#webhook#monitoring
settings.json fragment
{
"hooks": {
"Notification": [
{
"hooks": [
{
"command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/notify-slack.mjs",
"type": "command"
}
]
}
]
}
}Script · .claude/hooks/notify-slack.mjs
#!/usr/bin/env node
// @hookstack notification-slack
import { execSync } from "node:child_process";
// @hookstack notification-slack
// Envoie une notification Slack quand Claude veut notifier l'utilisateur (Notification)
import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
function defaultExec(cmd) {
execSync(cmd, { stdio: "ignore", timeout: 10_000 });
}
export function run(
input,
{
exec = defaultExec,
webhook = process.env.SLACK_WEBHOOK_URL ?? "",
projectDir = process.env.CLAUDE_PROJECT_DIR,
} = {},
) {
if (!webhook) return null;
const message = input.message ?? input.notification ?? "";
if (!message) return null;
const project = projectDir?.split("/").pop() ?? "Claude";
const payload = JSON.stringify({ text: `*[${project}]* ${message}` });
try {
exec(
`curl -s -X POST -H 'Content-type: application/json' --data '${payload.replace(/'/g, "'\\''")}' '${webhook}'`,
);
} catch {
// Échec réseau — non bloquant
}
return payload;
}
/* v8 ignore next 4 */
if (process.argv[1] === fileURLToPath(import.meta.url)) {
const input = JSON.parse(readFileSync(0, "utf8"));
run(input);
}