Skip to main content
ClaudeWave
Skill11k repo starsupdated 15d ago

hive.slack-notifications-setup

Set up a Slack notification channel (Sentinel) for a colony by driving the browser — reuse or create the "Hive Sentinel" Slack app from a JSON manifest, install it, capture the bot + app tokens, create/select the channel via the Slack API, and turn Sentinel on so the colony can ping the user on Slack and accept replies. Use when the user asks to "set up Slack notifications", "get pinged on Slack", "connect Slack for alerts", "set up Sentinel on Slack", or clicks the in-app "Set this up with the agent" button on the Slack channel step. Requires hive.browser-automation.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/aden-hive/hive /tmp/hive.slack-notifications-setup && cp -r /tmp/hive.slack-notifications-setup/core/framework/skills/_default_skills/slack-notifications-setup ~/.claude/skills/hive.slack-notifications-setup
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# Slack Notifications Setup (Sentinel)

Sentinel pings the user on Slack when a colony stalls and lets them reply from
Slack to keep it going. It needs a Slack app with two tokens:

- a **Bot User OAuth Token** (`xoxb-…`) — stored under credential id `slack`, used to *send* alerts and call the Slack API.
- an **App-Level Token** (`xapp-…`) with `connections:write` — stored under credential id `slack_app`, used by Socket Mode to *receive* the user's reply.

You do the whole thing end to end: reuse-or-create the app, read the tokens, store
them with the **`sentinel_setup`** tool (the same API the desktop connector uses),
create/select the channel **via the Slack API**, and turn Sentinel on — without
making the user paste anything.

**Activate `hive.browser-automation` first** — this skill assumes you know the
lifecycle rules (the bridge attaches to the user's own Chrome; never launch or kill
a browser), the screenshot + viewport-fraction coordinate workflow, and
`hive-browser interact`.

## Before you start — check what already exists

1. Run `sentinel_setup({"action": "status"})`. If it shows **both** `slack bot` and
   `slack app` already configured, the app and tokens are already in place — skip
   Steps 1–4 entirely and go to **Step 5 (channel)**. Don't recreate anything.
2. Confirm the user is signed into the right Slack workspace: run
   `hive-browser navigate https://api.slack.com/apps --json` in the terminal. If it shows a sign-in screen,
   ask them to log into the workspace they want alerts in. If they have several
   workspaces, ask which one.
3. **Reuse before create.** Scan the apps list for an app named **Hive Sentinel**.
   If it exists, open it and skip to **Step 2** (app-level token) / **Step 3**
   (install) — do **not** create a second app. Only create one if none exists.

## Step 1 — Create the app from a JSON manifest

The manifest sets the name, bot scopes (including channel management), Socket Mode,
and event subscriptions in one shot.

1. Click **Create New App → From a manifest**, pick the workspace, click **Next**.
2. Switch to the **JSON** tab (not YAML — the browser type tools strip newlines and
   break YAML).
3. Inject the manifest with `hive-browser evaluate` (run in the terminal) using CodeMirror's API — see
   **"Filling the manifest editor"** below for the exact, non-doubling method. Use
   this manifest verbatim:

```json
{
  "display_information": { "name": "Hive Sentinel" },
  "features": { "bot_user": { "display_name": "Hive Sentinel", "always_online": true } },
  "oauth_config": {
    "scopes": {
      "bot": [
        "chat:write",
        "chat:write.public",
        "channels:read",
        "channels:history",
        "channels:manage",
        "groups:read",
        "groups:history",
        "users:read"
      ]
    }
  },
  "settings": {
    "event_subscriptions": { "bot_events": ["message.channels", "message.groups"] },
    "socket_mode_enabled": true,
    "org_deploy_enabled": false,
    "token_rotation_enabled": false
  }
}
```

`channels:manage` is included **up front** so you can create the channel by API in
Step 5 without ever reinstalling. Valid manifest keys only: `socket_mode_enabled`
(not `socket_mode`), and there is no `org_domains` field.

4. With the editor showing a single copy and no "can't translate" error, click
   **Next**, then **Create**.

### Filling the manifest editor (JSON tab — do this, nothing else)

Slack's manifest editor is **CodeMirror 5**, and it validates from React state, not
the DOM. Two traps, both avoided by the method below:

- `hive-browser interact`/`insert_text` **strips newlines** (breaks the manifest) and the
  type path tries to parse the braces. Don't type into it.
- A `paste`/`InputEvent` that **carries the text** gets *appended on top of* the
  current value — paste it after `setValue` and you get the manifest **twice**.

Set the value once, then fire a **value-less** input event so React re-reads it.
Run this with `hive-browser evaluate` in the terminal — because the script is
multi-line and quote-heavy, pass it via `--js -` (stdin) or `--js @file` rather than
inline `--js '…'`:

```js
// JSON tab must be active first (click the tab labelled "JSON").
const cm = document.querySelector('.CodeMirror').CodeMirror;
// Embed the manifest as a single-quoted JS string (it contains only double quotes).
const manifest = '{"display_information":{"name":"Hive Sentinel"}, ... }';
cm.setValue(manifest);                 // setValue REPLACES — it never appends
cm.getInputField().dispatchEvent(      // notify React WITHOUT carrying any text
  new InputEvent('input', { bubbles: true, inputType: 'insertFromPaste' })
);
return { valueLen: cm.getValue().length };  // sanity-check: one copy, not double
```

If `valueLen` is ~2× the manifest length, it doubled — `cm.setValue('')` then
`cm.setValue(manifest)` once and re-dispatch. Never solve a "Next is disabled" by
pasting again.

## Step 2 — Generate the App-Level Token (`xapp-…`)

Manifests can't mint app-level tokens. In the app: **Basic Information → App-Level
Tokens → Generate Token and Scopes**, name it (e.g. `socket`), add the scope
**`connections:write`**, **Generate**, then read the `xapp-…` value.

## Step 3 — Install to the workspace, get the Bot Token (`xoxb-…`)

1. Open **OAuth & Permissions** and click **Install to Workspace** → **Allow**.
2. Read the **Bot User OAuth Token** (`xoxb-…`). Read it from the input's value, not
   off a screenshot, so you don't truncate it:

```js
Array.from(document.querySelectorAll('input')).map(i => i.value).filter(v => v.startsWith('xoxb-'));
```

## Step 4 — Store both tokens with `sentinel_setup`

```
sentinel_setup({"action": "store_token", "provider": "slack",     "token": "xoxb-…"})
sentinel_setup({"action": "store_token", "provider": "slack_app", "token": "xapp-…"})
```

The bot token is validated (`auth.test`) before storing and reports the workspace.
If it's rejected, re-read the token from the input value (you likely