zudo-slack-notify

Type to search...

to open search from anywhere

Agent Skill

The notify-slack Claude Code skill, how to install it, and the approval boundary.

skills/notify-slack/SKILL.md teaches a Claude Code agent to send a notification. The agent supplies the facts of the moment (target, kind, title, message, links); the skill resolves the checkout, loads the sender credentials, and runs the CLI.

How it runs

  • The checkout is found from the environment variable ZUDO_SLACK_NOTIFY_ROOT.

  • The sender env file defaults to $DROPBOX_ROOT/env/zudo-slack-notify/credentials/sender.env.

  • The skill writes the payload to a JSON file and runs:

node --env-file=<sender env file> "$ZUDO_SLACK_NOTIFY_ROOT/app/cli/notify.ts" --file <json>

The key is passed through the env file, never on argv, and the agent never sees the Slack bot token.

Install

Copy or symlink the skill directory into your Claude Code skills directory:

ln -s "$ZUDO_SLACK_NOTIFY_ROOT/skills/notify-slack" ~/.claude/skills/notify-slack

A symlink stays current as the checkout updates; a copy needs refreshing. Then set ZUDO_SLACK_NOTIFY_ROOT in your shell environment to the checkout path and make sure sender.env exists (see Configure secrets and deploy).

Project wrappers

The generic skill sends what it is told. A project-specific wrapper knows the procedure, which stage needs a human, and the review URL. skills/notify-slack/references/project-wrapper.md describes the pattern:

  1. The project skill follows its real candidate workflow and completes its own checks.

  2. It records the real package, version, commit, and approval location.

  3. It calls notify-slack once for the right target.

  4. It records the returned receipt, or the delivery problem, in its own state.

  5. It continues or pauses according to the project's existing process. A failed notification does not change candidate state, and a successful one does not approve anything.

  6. Once the real workflow confirms publication, it may send a success follow-up in the original thread, if the original receipt exists.

Every example value in app/examples/ must be replaced with actual facts; do not copy "checks passed" as an assumption. This repository does not install or overwrite a personal skill.

Approval boundary

A notification never grants permission

A sent receipt means a message was posted. It is not approval to publish, merge, deploy, or take any irreversible step. Slack replies, reactions, and elapsed time are not observed by this service and cannot unblock an agent. source and kind are the agent's own claims, not verified facts.

Dry run

Ask the skill for a preview, or use it while building a wrapper, and it appends --dry-run. That validates and prints the request and Slack payload with no credentials and no network, so --env-file may be omitted. A dry run is never reported as delivered.

Receipts

After a sent result the skill records the receipt immediately in the task's private local record (an ignored file or the workflow's existing status store), and checks that record before sending again on resume. The server does not deduplicate, and a fresh requestId is not a deduplication key.

The receipt contains the Slack channel ID, so it stays out of public text. In issues, pull requests, commit messages, and shared logs, delivery and requestId are fine; keep channel and ts private. To thread a follow-up, use the same target and the parent receipt's ts as threadTs (or --thread-ts); never invent a timestamp.

Handling outcomes

  • Exit 0: record the ts if replies will thread.

  • Exit 1 or 2: the message was not sent; report the error and fix the input or setup.

  • Exit 3: no post was accepted. Wait the full retryAfterSeconds (or the textual retryAfter) before a deliberate retry, never shorten the wait, and retry in a bounded way only if the calling workflow authorizes it.

  • Exit 4, or a transport failure without a valid receipt: delivery is uncertain. Do not retry automatically. Ask the user to check the destination, or use existing task evidence to see whether the message is present.

Revision History

CreatedUpdated