Skill: slack-poster

This skill provides tools for sending messages and interactive prompts to Slack. It uses the Slack Bolt client instance that is already authenticated in the daily-standup-bot server process.

7 stars

Best use case

Skill: slack-poster is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

This skill provides tools for sending messages and interactive prompts to Slack. It uses the Slack Bolt client instance that is already authenticated in the daily-standup-bot server process.

Teams using Skill: slack-poster should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/slack-poster/SKILL.md --create-dirs "https://raw.githubusercontent.com/heldernoid/agentic-build-templates/main/projects/automation-productivity/daily-standup-bot/skills/slack-poster/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/slack-poster/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How Skill: slack-poster Compares

Feature / AgentSkill: slack-posterStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

This skill provides tools for sending messages and interactive prompts to Slack. It uses the Slack Bolt client instance that is already authenticated in the daily-standup-bot server process.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Skill: slack-poster

This skill provides tools for sending messages and interactive prompts to Slack. It uses the Slack Bolt client instance that is already authenticated in the daily-standup-bot server process.

## Tools

### `post_digest`

Post a standup digest to a Slack channel. Formats the collected answers for all submitted members into Block Kit blocks and posts them.

```typescript
interface PostDigestInput {
  window_id: number;            // Digest is built from this window's submissions
  channel_id?: string;          // Override channel; defaults to the team's configured channel
  include_missing?: boolean;    // Append a "missing members" section; default true
  include_skipped?: boolean;    // Include skipped-with-note members; default true
}

interface PostDigestOutput {
  ok: boolean;
  channel: string;
  ts: string;           // Slack message timestamp (used as message ID)
  blocks_count: number;
  members_included: number;
  members_missing: number;
}
```

**Block Kit structure:**
1. Header block: team name + date.
2. Context block: "X of Y members submitted | window closed at HH:MM".
3. Divider.
4. For each submitted member: section block with bold name + submitted-at, followed by one section block per answer (question label in mrkdwn, answer text indented).
5. If `include_missing` and there are missing members: divider + section listing them.

**Implementation notes:**
- Load the window, team, all submissions, and all answers via the database.
- Use `client.chat.postMessage({ channel, blocks, text })` where `text` is a plain-text fallback for notifications.
- Store the returned `ts` in `standup_windows.digest_ts` for later linking.

---

### `send_standup_dm`

Send a standup prompt DM to a single team member. Used by the scheduler when a window opens, and by the manual trigger flow.

```typescript
interface SendStandupDmInput {
  slack_user_id: string;
  window_id: number;
  note?: string;           // Optional extra text appended to the greeting
}

interface SendStandupDmOutput {
  ok: boolean;
  channel: string;   // The DM channel ID (im channel)
  ts: string;
  questions_count: number;
}
```

**Block Kit DM structure:**
1. Section block: greeting text with team name and window close time.
2. If `note` provided: context block with the note.
3. Divider.
4. For each question: section block showing "Question N of M" label + question text, followed by a plain-text input block (action_id: `answer_q{position}`).
5. Actions block: "Submit standup" button (value: `submit`, style: primary) + "Skip today" button (value: `skip`).

**Implementation notes:**
- Open or fetch the DM channel via `client.conversations.open({ users: slack_user_id })`.
- Post via `client.chat.postMessage`.
- Record that the DM was sent by creating a `submissions` row with `status = 'pending'` (updated to `complete`/`skipped` when the member interacts).

---

### `send_reminder_dm`

Send a reminder DM to members who have not yet submitted for the current open window.

```typescript
interface SendReminderDmInput {
  window_id: number;
  slack_user_ids?: string[];   // Omit to remind all non-submitted active members
  minutes_remaining?: number;  // Included in message, e.g. "15 minutes remaining"
}

interface SendReminderDmOutput {
  ok: boolean;
  sent_count: number;
  failed_count: number;
  recipients: string[];  // slack_user_ids that were messaged
}
```

**Message format:**
- Short block message: "Reminder: your standup for {team} is still open. {N} minutes remaining."
- Button: "Submit now" linking back to the original DM thread (uses `thread_ts` from initial prompt).

**Implementation notes:**
- Query `submissions` for the window to find members without a `complete` or `skipped` status.
- Filter to `slack_user_ids` if provided.
- Send each user a short ephemeral-style message in the existing DM channel.

---

### `update_digest_message`

Edit an already-posted digest message after a late submission arrives or the window is re-posted.

```typescript
interface UpdateDigestMessageInput {
  window_id: number;
  channel_id?: string;    // Defaults to team's configured channel
}

interface UpdateDigestMessageOutput {
  ok: boolean;
  channel: string;
  ts: string;
  updated_at: string;  // ISO 8601
}
```

**Implementation notes:**
- Look up `standup_windows.digest_ts` for the window.
- If `digest_ts` is null, call `post_digest` instead of updating.
- Rebuild the full Block Kit payload (same as `post_digest`) and call `client.chat.update({ channel, ts: digest_ts, blocks, text })`.

---

### `send_channel_message`

Send an arbitrary plain-text or Block Kit message to a Slack channel. For announcements, system alerts, or custom bot messages not tied to a standup window.

```typescript
interface SendChannelMessageInput {
  channel_id: string;
  text: string;           // Plain-text fallback and notification text
  blocks?: object[];      // Optional Block Kit blocks; if omitted, text is shown as-is
  thread_ts?: string;     // If provided, posts as a reply in a thread
}

interface SendChannelMessageOutput {
  ok: boolean;
  channel: string;
  ts: string;
}
```

---

### `lookup_slack_user`

Look up a Slack user's profile by Slack user ID to get their display name, real name, and time zone.

```typescript
interface LookupSlackUserInput {
  slack_user_id: string;
}

interface LookupSlackUserOutput {
  slack_user_id: string;
  display_name: string;
  real_name: string;
  email: string | null;
  tz: string;            // IANA timezone, e.g. "America/Chicago"
  is_bot: boolean;
  deleted: boolean;
}
```

**Implementation notes:**
- Calls `client.users.info({ user: slack_user_id })`.
- Returns the normalized fields from `user.profile`.
- Use this before `add_member` when display names are needed.

---

### `list_channel_members`

List all Slack user IDs who are members of a given channel. Useful for bulk-importing members into a team.

```typescript
interface ListChannelMembersInput {
  channel_id: string;
  exclude_bots?: boolean;  // Default true
}

interface ListChannelMembersOutput {
  channel_id: string;
  member_ids: string[];
  total: number;
}
```

**Implementation notes:**
- Calls `client.conversations.members({ channel: channel_id })` with cursor-based pagination to handle channels with more than 200 members.
- If `exclude_bots` is true, calls `client.users.info` for each and filters where `user.is_bot === true`.

Related Skills

Skill: Uptime Monitoring

7
from heldernoid/agentic-build-templates

## Overview

Skill: Status Page

7
from heldernoid/agentic-build-templates

## Overview

Skill: unit-conversion

7
from heldernoid/agentic-build-templates

## Overview

Skill: recipe-scaler

7
from heldernoid/agentic-build-templates

## Overview

reading-list

7
from heldernoid/agentic-build-templates

Operate the reading-list API to save, manage, tag, search, and export articles.

email-digest

7
from heldernoid/agentic-build-templates

Configure, test, and troubleshoot the reading-list daily email digest delivered via nodemailer.

websocket-realtime

7
from heldernoid/agentic-build-templates

Use the WebSocket connection in poll-builder to receive live vote updates. Use when you need to stream real-time poll results, monitor a poll for new votes, or build a live dashboard. Triggers include "live results", "real-time updates", "stream votes", "watch poll", or "WebSocket".

poll-builder

7
from heldernoid/agentic-build-templates

Self-hosted poll creation tool with real-time results. Use when you need to create a poll, check vote counts, close a poll, export results, or get the shareable link for a poll. Triggers include "create poll", "vote", "poll results", "survey", "collect votes", "share poll", or any task involving polling or voting.

Skill: personal-finance

7
from heldernoid/agentic-build-templates

## Overview

Skill: csv-import

7
from heldernoid/agentic-build-templates

## Overview

Skill: Syntax Highlighting

7
from heldernoid/agentic-build-templates

## Purpose

Skill: Pastebin Core

7
from heldernoid/agentic-build-templates

## Purpose