home / skills / vm0-ai / vm0-skills / slack-webhook

slack-webhook skill

/slack-webhook

This skill helps you send Slack messages via Incoming Webhooks, enabling quick, channel-specific notifications without OAuth setup.

npx playbooks add skill vm0-ai/vm0-skills --skill slack-webhook

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
4.2 KB
---
name: slack-webhook
description: Send messages to Slack using Incoming Webhooks. Simple one-way messaging to a specific channel without OAuth setup.
vm0_secrets:
  - SLACK_WEBHOOK_URL
---

# Slack Incoming Webhook

Send messages to a Slack channel using Incoming Webhooks. No OAuth or bot setup required.

## When to Use

- Send notifications to a specific channel
- CI/CD notifications, alerts, status updates
- Quick integration without full Slack app setup

## Prerequisites

```bash
export SLACK_WEBHOOK_URL=https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXX
```

### Get Webhook URL

1. Create app: https://api.slack.com/apps → **Create New App** → **From scratch**
2. Select **Incoming Webhooks** → Toggle **On**
3. Click **Add New Webhook to Workspace**
4. Select channel → **Allow**
5. Copy Webhook URL

> **Important:** When using `$VAR` in a command that pipes to another command, wrap the command containing `$VAR` in `bash -c '...'`. Due to a Claude Code bug, environment variables are silently cleared when pipes are used directly.
> ```bash
> bash -c 'curl -s "https://api.example.com" -H "Authorization: Bearer $API_KEY"' | jq .
> ```

## Usage

### Simple Message

Write to `/tmp/slack_request.json`:

```json
{
  "text": "Hello, world."
}
```

Then run:

```bash
bash -c 'curl -X POST $SLACK_WEBHOOK_URL -H "Content-type: application/json" -d @/tmp/slack_request.json'
```

### With Formatting

Write to `/tmp/slack_request.json`:

```json
{
  "text": "*Bold* and _italic_ text"
}
```

Then run:

```bash
bash -c 'curl -X POST $SLACK_WEBHOOK_URL -H "Content-type: application/json" -d @/tmp/slack_request.json'
```

### With Link

Write to `/tmp/slack_request.json`:

```json
{
  "text": "Check <https://example.com|this link>"
}
```

Then run:

```bash
bash -c 'curl -X POST $SLACK_WEBHOOK_URL -H "Content-type: application/json" -d @/tmp/slack_request.json'
```

### With Blocks (Rich Layout)

Write to `/tmp/slack_request.json`:

```json
{
  "text": "New review submitted",
  "blocks": [
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": "Danny left the following review:"
      }
    },
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": "<https://example.com|Overlook Hotel>\n:star:\nDoors had too many axe holes."
      }
    }
  ]
}
```

Then run:

```bash
bash -c 'curl -X POST $SLACK_WEBHOOK_URL -H "Content-type: application/json" -d @/tmp/slack_request.json'
```

### With Fields

Write to `/tmp/slack_request.json`:

```json
{
  "text": "Deployment status",
  "blocks": [
    {
      "type": "section",
      "fields": [
        {
          "type": "mrkdwn",
          "text": "*Environment:*\nProduction"
        },
        {
          "type": "mrkdwn",
          "text": "*Status:*\nSuccess"
        }
      ]
    }
  ]
}
```

Then run:

```bash
bash -c 'curl -X POST $SLACK_WEBHOOK_URL -H "Content-type: application/json" -d @/tmp/slack_request.json'
```

## Message Formatting

| Syntax | Result |
|--------|--------|
| `*bold*` | **bold** |
| `_italic_` | _italic_ |
| `~strike~` | ~~strike~~ |
| `` `code` `` | `code` |
| `\n` | newline |
| `<URL\|text>` | hyperlink |
| `:emoji:` | emoji |

## Shell Escaping

Messages with `!` may fail due to shell history expansion. Use heredoc:

```bash
bash -c 'curl -s -X POST $SLACK_WEBHOOK_URL -H "Content-type: application/json" -d @-' << 'EOF'
{"text":"Deploy completed! :rocket:"}
EOF
```

## Response

Success: `ok` (HTTP 200)

Errors:
- `invalid_payload` - Malformed JSON
- `no_text` - Missing `text` field
- `no_service` - Webhook disabled or invalid
- `channel_not_found` - Channel deleted
- `channel_is_archived` - Channel archived
- `action_prohibited` - Admin restriction

## Limitations

- One webhook = one channel only
- Cannot override username or icon (set in app config)
- Send only (no reading messages)
- Cannot delete messages after posting
- Rate limit: 1 message/second

For full API access, use the `slack` skill with Bot Token.

## API Reference

- Webhooks Guide: https://docs.slack.dev/messaging/sending-messages-using-incoming-webhooks
- Block Kit Builder: https://app.slack.com/block-kit-builder
- Message Formatting: https://docs.slack.dev/messaging/formatting-message-text

Overview

This skill sends messages to a Slack channel using Incoming Webhooks. It provides a lightweight, one-way integration that requires no OAuth or bot setup. Use it to push alerts, CI/CD updates, or simple notifications to a fixed channel quickly.

How this skill works

The skill posts a JSON payload to a preconfigured Slack Incoming Webhook URL using curl or a similar HTTP client. It supports simple text, Slack formatting, links, emoji, and Block Kit payloads by sending the appropriate JSON body to the webhook. Environment variables should be used to store the webhook URL and shell escaping/here-documents help avoid history expansion or variable-clearing issues when piping commands.

When to use it

  • Send notifications or alerts to a single, dedicated Slack channel
  • CI/CD pipelines that need simple status messages without full app auth
  • Quick integrations where creating a full Slack app or bot is unnecessary
  • Posting formatted messages or Block Kit blocks from scripts
  • Lightweight uptime or deployment notifications from servers or cron jobs

Best practices

  • Keep the webhook URL in an environment variable (e.g., SLACK_WEBHOOK_URL) and never commit it to source control
  • Use JSON files or here-documents to build payloads when they include special characters or newlines
  • Respect the rate limit (about 1 message per second) and batch or debounce frequent events
  • Validate JSON payloads to avoid invalid_payload errors and include a text field for basic compatibility
  • Configure username and icon in the Incoming Webhook app settings instead of trying to override them in payloads

Example use cases

  • Post a deployment summary with status fields and a link to release notes using Block Kit
  • Send CI build success/failure messages from a pipeline step to a monitoring channel
  • Notify on-critical alerts (CPU, memory, or service errors) from a server script
  • Publish scheduled reports or digest messages from cron jobs using formatted text
  • Send a simple hello or test message to verify webhook configuration

FAQ

Can I send messages to multiple channels with one webhook?

No. Each webhook is tied to a single channel. Create additional webhooks for other channels.

What causes an invalid_payload error?

invalid_payload occurs when the JSON is malformed or missing required fields. Validate your JSON and include at least a text field.