HookStack
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);
}

Learn more

Related hooks