communicate via slack-chat channels and direct messages with users

0 stars
0 forks
Python
55 views

SKILL.md


name: slack-chat description: communicate via slack-chat channels and direct messages with users

Slack Chat

Overview

The slack command is installed globally (located in the $PATH).

It is a dual-mode Slack client with offline-first architecture:

  1. Online Mode: Pull messages from Slack to local Markdown storage, resolve IDs
  2. Offline Mode: Query and manage stored messages without Slack connectivity

The system is designed for AI agents to integrate Slack processing into workflows, supporting:

  • Batch message ingestion with deduplication
  • Message marking (read/unread) with offline metadata
  • ID resolution caching (users, channels)
  • Integration with other tools and scripts

Uses browser-use (via Chrome DevTools Protocol) for Slack API access.

Core Concepts

Message IDs

  • Slack ID: channel_id:timestamp or channel_id:timestamp@thread_ts for threads
  • SHA1 Hash: 40-character hex hash of Slack ID, used as filename
  • Short ID: First 6 characters of hash (e.g., b89c7a), used for Git-like partial matching

Example:

Slack ID:   C01TECH01:1767815267.099869
SHA1 Hash:  b89c7a14755df6dca57ece8e14f38652e727cbd8
Short ID:   b89c7a

# Thread reply:
Slack ID:   G01GROUP01:[email protected]
SHA1 Hash:  4cea849d8625c020f8716b8024e256942d6b440b
Short ID:   4cea84

Storage Format

Each message is stored as a Markdown file in storage/ with YAML front matter containing metadata, and rendered content below:

---
channel_id: C01TECH01
timestamp: '1767815267.099869'
thread_ts: null
user_id: WNARLG5HB
type: message
text: Thank you all!
permalink: https://bigco-producta.slack.com/archives/C01TECH01/p1767815267099869
reactions: []
attachments: []
files: []
_stored_id: b89c7a14755df6dca57ece8e14f38652e727cbd8
_stored_at: '2026-01-07T20:06:28.667864+00:00'
offline:
  read: false
---

# Message in C01TECH01

**From:** WNARLG5HB
**Channel:** C01TECH01
**Timestamp:** 1767815267.099869
**Permalink:** [https://...](https://...)

---

Thank you all!

ID Matching (Git-style)

All CLI commands support partial IDs. The system matches the longest unique prefix:

# These all refer to the same message:
slack-chat inbox view b89c7a14755df6dca57ece8e14f38652e727cbd8  # Full (40 chars)
slack-chat inbox view b89c7a14                                   # 8 chars
slack-chat inbox view b89c7a                                     # 6 chars (short)
slack-chat inbox view b89c                                       # 4 chars (if unique)

Error on ambiguity:

❌ Ambiguous ID 'b8' matches: b89c7a14..., b8a3f2c1...

ID Resolution Cache

User and channel IDs are cached to storage/_cache/ to reduce API calls:

storage/_cache/
├── users.yml      # User ID → full profile
└── channels.yml   # Channel ID → full info

When you run slack-chat user resolve or slack-chat channel resolve, the result is cached. Subsequent lookups hit the cache first.

Quick Reference

Task Command
Server
Start Server slack-chat server start
Stop Server slack-chat server stop
Server Status slack-chat server status
Pull (Online)
Pull Messages slack-chat pull --since "7 days ago" [--limit N] [--type TYPE]
Inbox (Offline)
Summary slack-chat inbox summary
List slack-chat inbox list [--type TYPE] [--limit N] [--since DATE] [--all]
View slack-chat inbox view <id>
Mark Read slack-chat inbox read <id>
Mark Thread Read slack-chat inbox mark-thread <id>
Mark Channel Read slack-chat inbox mark-channel <channel_id>
Mark Unread slack-chat inbox unread <id>
Resolve (Online, Cached)
Resolve Channel slack-chat channel resolve <channel_id>
Resolve User slack-chat user resolve <user_id>
Lookup (Offline)
List Channels slack-chat channel list
Find Channels slack-chat channel find <keyword>
List Users slack-chat user list
Find Users slack-chat user find <keyword>
Context (Online)
Message Around slack-chat message around <event_id> [-B N] [-A N]
View Thread slack-chat client read-message-thread-replies <channel> <thread_ts>
Write (Online)
Reply slack-chat reply <id | #channel> "message"
React slack-chat react <id> <emoji>
Mute Channel slack-chat mute <channel_id>
Post Message slack-chat client post-message <channel> "text"
Reply to Thread slack-chat client post-thread-reply <channel> <thread_ts> "text"
Add Reaction slack-chat client add-reaction <channel> <ts> "emoji"

Online Mode: Fetching Messages from Slack

Command: slack-chat pull

Purpose: Fetch unread messages from Slack, store locally as Markdown files.

IMPORTANT: Always fetch with reasonable limits. Use --limit 10 or --limit 20 for controlled processing. This ensures manageable batches for review.

Command:

slack-chat pull --since <date> [--limit N] [--type TYPE]

Parameters:

  • --since <date>: Required. Fetch messages received on/after this date
    • Formats: YYYY-MM-DD, yesterday, "7 days ago", "1 day ago"
  • --limit <n>: Optional. Max messages per category (default: 100)
  • --type <type>: Optional. Filter: channels, dms, threads, mentions, all (default: all)
  • --quiet: Suppress verbose output

Behavior:

  1. Fetches unread channels, DMs, subscribed threads, and @mentions
  2. Skips already-stored files (deduplication via SHA1)
  3. Stores each message as Markdown under storage/<id>.md
  4. Does NOT mark as read on Slack (that's done via inbox read)
  5. Prints progress for each stored message

Examples:

# Pull from last 24 hours
slack-chat pull --since "1 day ago" --limit 10

# Pull only threads
slack-chat pull --since yesterday --type threads

# Pull everything from past week (use with caution)
slack-chat pull --since "7 days ago"

# Quiet mode for scripts
slack-chat pull --since yesterday --limit 50 --quiet

Output Example:

📥 Pulling messages since 2026-01-06...
  📢 Fetching channel messages...
    + 19aaf82d... (C02PROJ01)
    + 60e86087... (CL80UCYF5)
  💬 Fetching DM messages...
  🧵 Fetching thread replies...
    + e04ada37... (thread in C0919MFSA4X)
    + 8e206898... (thread in C098Q7ALDNU)
  📣 Fetching mentions...
    + b89c7a14... (mention)

✅ Done: 11 stored, 0 skipped, 23 fetched total

Best Practices:

  • Use --limit 10 or --limit 20 for manageable batches
  • Use --since "1 day ago" for daily processing
  • After pulling, use slack-chat inbox list to review new messages
  • The permalink field in stored files opens the message in Slack

Offline Mode: Analysis & Metadata

All slack-chat inbox commands work offline, reading/writing files in storage/.

Command: slack-chat inbox summary

Purpose: Get overall message statistics from local storage.

Command:

slack-chat inbox summary

Output:

summary:
  unread: 11
  read: 0
  total: 11
  by_type:
    channel: 6
    dm: 0
    thread: 5
    mention: 0

Use Cases:

  • Verify message counts before processing
  • Track unread vs read ratio
  • Check if pull was successful

Online Mode: Add --online to fetch live counts from Slack API instead.

Command: slack-chat inbox list

Purpose: List messages with filtering.

Command:

slack-chat inbox list [--type TYPE] [--limit N] [--since DATE] [--all]

Options:

  • -t, --type <type>: Filter by type (channels, dms, threads, mentions, all)
  • -n, --limit <n>: Max results (default: 20)
  • --since <date>: Filter messages after date
  • -a, --all: Include read messages (default: unread only)
  • --online: Use live API instead of local storage

Output Format:

<short_id> / <date> / <channel_id> / <user_id> (type)
  <text preview>

Output Example:

Showing 5 of 11 messages:

b89c7a / 2026-01-07 19:47 / C01TECH01 / WNARLG5HB 
  Thank you all!

4aab08 / 2026-01-07 19:24 / C01TECH01 / WM1HR6E1G 
  ok, puppet ran, nginx restarted

e04ada / 2026-01-07 19:06 / C0919MFSA4X / U025R2RLLM8 (thread)
  Have been back and forth with cloud a bit on camel support

... and 6 more

Use Cases:

  • Scan unread messages
  • Filter by type (threads only, DMs only, etc.)
  • Find messages from specific period

Command: slack-chat inbox view <id>

Purpose: Display full content of a message.

Command:

slack-chat inbox view <id>

Supports:

  • Partial IDs: b89c7a
  • Full IDs: b89c7a14755df6dca57ece8e14f38652e727cbd8
  • Event ID format: C01TECH01:1767815267.099869

Output: Complete Markdown file with YAML frontmatter and rendered body.

Use Cases:

  • Read full message content
  • Extract data for analysis
  • Check message metadata (reactions, attachments, etc.)

Example:

# View by short ID
slack-chat inbox view b89c7a

# View by event ID
slack-chat inbox view C01TECH01:1767815267.099869

How to interpet messsages

When I ask you to view a message, the output will have ID numbers in place of channel and user names, for example:

events:
- id: D04R3C0G1JT:1766426423.335079
  type: mention
  channel: '#USLACKBOT'
  from: slackbot
  text: <@WNHDFCXTJ> archived the channel <#C08TR8S0QJ0>
  timestamp: '1766426423.335079'
- id: D0849DD71UP:1765928154.858059
  type: reaction
  channel: '#WNHDFCXTJ'
  text: From here not much needed apart from those future meetings y
  timestamp: '1765928154.858059'
  thread_ts: '1765321208.614079'
  url: https://bigco-producta.slack.com/archives/D0849DD71UP/p1765928154858059
- id: G01GROUP01:[email protected]
  type: reaction (thread reply)
  channel: '#sre-nexus'
  text: <@WM1HR6E1G|teddy> I want you to be the coordinator
  timestamp: '1765909149.353759'
  thread_ts: '1765321208.614079'
  url: https://bigco-producta.slack.com/archives/G01GROUP01/p1765909149353759

where:

  • @WNHDFCXTJ is an example of a user_id
    • indicated by the @ (may not always appear) as well as the W prefix (part of the identifier)
  • #C08TR8S0QJ0 is an example of a channel_id
    • indicated by the # (may not always appear) as well as the C prefix (part of the identifier)
  • thread_ts indicates the message is part of a thread (value is the parent message timestamp)
  • Event IDs for threaded messages use the format: CHANNEL_ID:TIMESTAMP@THREAD_TS

Use the slack-chat channel resolve <id> and slack-chat user resolve <id> commands to find out what the human-readable version of these are, and only cite these when replying back to me (I don't want to see IDs, unless names are not available.)

Command: slack-chat inbox read <id>

Purpose: Mark a message as read.

Command:

slack-chat inbox read <id> [--offline-only]

Behavior:

  • Updates offline.read: true in local file
  • By default, also marks as read on Slack server
  • Use --offline-only to skip server-side marking

Output:

ok: true
marked_read_locally: b89c7a14...
marked_read_on_slack: true

Use Cases:

  • Mark messages as processed
  • Track which messages have been reviewed

Command: slack-chat inbox mark-thread <id>

Purpose: Mark all messages in a thread as read.

Command:

slack-chat inbox mark-thread <id> [--offline-only]

Behavior:

  • Finds all stored messages with the same thread_ts
  • Marks them all as read locally
  • By default, also marks thread as read on Slack server
  • Use --offline-only to skip server-side marking

Output:

ok: true
thread_ts: '1767773973.649239'
channel_id: C0919MFSA4X
marked_count: 5
marked_ids:
- e04ada37
- 8e206898
- a1b2c3d4
marked_read_on_slack: true

Use Cases:

  • Done reviewing a thread, mark all at once
  • Clean up multiple thread replies efficiently

Command: slack-chat inbox mark-channel <channel_id>

Purpose: Mark all messages in a channel as read.

Command:

slack-chat inbox mark-channel <channel_id> [--offline-only]

Behavior:

  • Finds all stored messages in the channel
  • Marks them all as read locally
  • By default, also marks channel as read on Slack (up to latest message)
  • Use --offline-only to skip server-side marking

Output:

ok: true
channel_id: C01TECH01
marked_count: 12
marked_ids:
- b89c7a14
- 4aab08f1
- 7d8e9bce
marked_read_on_slack: true

Use Cases:

  • Done with a channel's backlog, mark all at once
  • Clear noisy channels efficiently

Command: slack-chat inbox unread <id>

Purpose: Mark a message as unread (local only).

Command:

slack-chat inbox unread <id>

Effect:

  • Sets offline.read: false in local file
  • Does NOT sync to Slack (Slack API doesn't support marking unread)

Output:

ok: true
marked_unread_locally: b89c7a14...

Use Cases:

  • Recover from accidental marks
  • Re-queue messages for processing

ID Resolution (Online, Cached)

Command: slack-chat channel resolve <id>

Purpose: Convert channel ID to human-readable info.

slack-chat channel resolve C01TECH01

Output:

name: engineering
is_archived: false
is_private: false
created: 1563498384
creator: U0A4DBTGDPZ
topic: Technical discussions
purpose: Engineering team collaboration
members:
- WNARLG5HB
- WMCH36A6Q

Caching: Result is saved to storage/_cache/channels.yml. Subsequent calls return cached data.

Command: slack-chat user resolve <id>

Purpose: Convert user ID to human-readable info.

slack-chat user resolve WNARLG5HB

Output:

name: Alice Johnson
is_bot: false
is_admin: false
email: [email protected]
display_name: alice
title: Software Engineer
tz: America/Los_Angeles

Caching: Result is saved to storage/_cache/users.yml. Subsequent calls return cached data.

When to use: Whenever you see a raw ID (like WNARLG5HB or C01TECH01) and need the human-readable name.

Lookup Commands (Offline)

These commands search the offline cache without making API calls.

Command: slack-chat channel list

Purpose: List all cached channels.

slack-chat channel list

Output (tab-separated columns): id | name | description

C01TECH01	prod-tech-internal-ProductA	Production tech discussion
C098Q7ALDNU	engineering-general	General engineering chat
C6M7U8DFF	ProductA-server-team	ProductA server team coordination

Use Cases:

  • See all channels you've resolved/cached
  • Find channel IDs for posting

Command: slack-chat channel find <keyword>

Purpose: Find cached channels by name keyword.

slack-chat channel find prod
slack-chat channel find ProductA

Output (tab-separated columns): id | name | description

Matches channels whose name contains the keyword (case-insensitive). For example, hal matches thal, fhaly, etc.

Use Cases:

  • Find a channel when you only remember part of the name
  • Look up channel ID before posting with slack-chat reply

Command: slack-chat user list

Purpose: List all cached users.

slack-chat user list

Output (tab-separated columns): id | name | title | project

WNARLG5HB	Alice Johnson	Associate Lead Software Engineer	ProductA IV
WMCH36A6Q	Charlie Brown	Senior Software Engineer	ProductA
U04MYEUTJLU	Dana Evans	Engineering Manager	IT Infrastructure

Use Cases:

  • See all users you've resolved/cached
  • Find user IDs for @ mentions

Command: slack-chat user find <keyword>

Purpose: Find cached users by keyword (searches all fields).

slack-chat user find john
slack-chat user find ProductA
slack-chat user find infrastructure

Output (tab-separated columns): id | name | title | project

Searches all fields in the user object (case-insensitive), including:

  • Name, real_name, display_name
  • Title, email
  • Team/project custom fields
  • Any other string value

Examples:

# Find by name
slack-chat user find shelly

# Find by project/team
slack-chat user find ProductA
slack-chat user find "producta"

# Find by title
slack-chat user find "software engineer"

Use Cases:

  • Find a user when you only remember part of the name
  • Find all users on a specific team/project
  • Look up user ID for mentions

Context Commands (Online)

Often, viewing one message in isolation does not provide enough information; To truly understand a given message, often its necessary to look at messages in the surrounding (channel/thread) context (before and after), similar to grep -B and -A flags.

Command: slack-chat message around <event_id>

Purpose: View messages before/after a target message for context.

slack-chat message around C6M7U8DFF:1766558024.931179 -B 3 -A 3

Options:

  • -B <n>: Number of messages before (default: 3)
  • -A <n>: Number of messages after (default: 3)

Use Cases:

  • Understand conversation context
  • See what led to a message
  • Review thread context

Command: slack-chat inbox context <event_id>

Purpose: View surrounding context (thread or channel messages).

slack-chat inbox context C6M7U8DFF:1766558024.931179 --limit 5

Write Commands (Online)

Command: slack-chat reply <target> <message>

Purpose: Reply to a channel or thread with smart targeting.

Command:

slack-chat reply <target> "<message>"

Smart Targeting - accepts multiple ID formats:

  • Channel ID: C01TECH01 → posts to channel
  • Channel name: #prod-tech-internal-ProductA → posts to channel (looks up from cache)
  • Storage ID: b89c7a → replies to that message's thread
  • Event ID: C01TECH01:1767815267.099869 → replies to thread
  • Event ID with thread: C01TECH01:[email protected]

Channel Name Resolution: When using a channel name (with # prefix), the system:

  1. Looks up the name in the offline cache (storage/_cache/channels.yml)
  2. If found, uses the cached channel ID
  3. If not found, returns an error with suggestion to use slack-chat channel find

To cache a channel, use slack-chat channel resolve <id> first.

Output:

ok: true
channel: C01TECH01
message_ts: '1767820123.456789'
thread_ts: '1767815267.099869'
permalink: https://bigco-producta.slack.com/archives/...

Examples:

# Post to channel by ID
slack-chat reply C01TECH01 "Hello everyone!"

# Post to channel by name
slack-chat reply "#prod-ProductA" "Hello world!"

# Reply to a thread (by storage ID)
slack-chat reply b89c7a "Thanks for the update!"

# Reply to a thread (by event ID)
slack-chat reply C01TECH01:1767815267.099869 "Got it, will look into this."

Use Cases:

  • Quick replies to messages you just viewed
  • Respond to threads without looking up thread_ts manually
  • Post updates to channels by name

Command: slack-chat react <target> <emoji>

Purpose: Add an emoji reaction to a message.

Command:

slack-chat react <target> <emoji>

Smart Targeting - accepts:

  • Storage ID: b89c7a → reacts to that message
  • Event ID: C01TECH01:1767815267.099869 → reacts to message
  • Event ID with thread: C01TECH01:[email protected]

Emoji formats (with or without colons):

  • thumbsup, +1, eyes, white_check_mark
  • :thumbsup:, :+1:, :eyes:

Output:

ok: true
channel: C01TECH01
timestamp: '1767815267.099869'
emoji: thumbsup

Examples:

# React by storage ID
slack-chat react b89c7a thumbsup

# React by event ID
slack-chat react C01TECH01:1767815267.099869 eyes

# Acknowledge with checkmark
slack-chat react b89c7a white_check_mark

Use Cases:

  • Acknowledge messages quickly
  • React to messages you just viewed
  • Signal agreement/approval without writing a reply

Command: slack-chat mute <channel_id>

Purpose: Mute a channel to stop receiving notifications.

Command:

slack-chat mute <channel_id>

Output:

ok: true
channel: C01TECH01
muted: true

Examples:

# Mute a noisy channel
slack-chat mute C01TECH01

# Mute after resolving channel name
slack-chat channel resolve C6M7U8DFF  # Check it's the right channel
slack-chat mute C6M7U8DFF

Use Cases:

  • Silence noisy channels
  • Stop notifications from low-priority channels
  • Reduce distractions during focus time

Workflow Scenarios

Scenario 1: Daily Slack Processing

Goal: Pull messages daily, review, mark processed.

# 1. Start server
slack-chat server start

# 2. Pull recent messages
slack-chat pull --since "1 day ago" --limit 20

# 3. Check statistics
slack-chat inbox summary
# Output: unread: 15, read: 0, total: 15

# 4. List messages for review
slack-chat inbox list --limit 20

# 5. View specific message
slack-chat inbox view b89c7a

# 6. Resolve user ID to name
slack-chat user resolve WNARLG5HB

# 7. Mark as processed
slack-chat inbox read b89c7a

# 8. Verify
slack-chat inbox summary
# Output: unread: 14, read: 1, total: 15

Scenario 2: Thread-focused Processing

Goal: Focus on thread replies only.

# 1. Pull only threads
slack-chat pull --since "3 days ago" --type threads

# 2. List thread messages
slack-chat inbox list --type threads

# 3. View thread reply
slack-chat inbox view e04ada

# 4. Get full thread context (online)
slack-chat message around C0919MFSA4X:[email protected] -B 5 -A 5

# 5. Mark as read
slack-chat inbox read e04ada

Scenario 3: Incremental Processing

Goal: Process in small batches.

# Pull small batch
slack-chat pull --since yesterday --limit 5

# Process each
for id in b89c7a 4aab08 7d8e9b; do
  echo "=== Message: $id ==="
  slack-chat inbox view $id
  # ... analyze ...
  slack-chat inbox read $id
done

# Check remaining
slack-chat inbox summary

Agent Workflow: Processing Unread Activity

When the user asks to "check Slack" or "process my unreads":

Step 1: Pull Fresh Data

slack-chat pull --since "1 day ago" --limit 20

Step 2: Get Overview

slack-chat inbox summary

If all counts are 0, report "No unread activity" and stop.

Step 3: List Messages

slack-chat inbox list --limit 20

Step 4: Present Summary

Parse the output. Present to user:

  • Count by type (channels, DMs, threads)
  • Preview of important messages

Example:

You have 11 unread messages: 6 in channels, 5 thread replies. Notable: Thread reply from U025R2RLLM8 about "camel support"

Step 5: Drill Down (on request)

slack-chat inbox view e04ada              # View message
slack-chat user resolve U025R2RLLM8       # Get user name
slack-chat channel resolve C0919MFSA4X    # Get channel name

Step 6: Mark as Read (on request)

slack-chat inbox read e04ada

File Organization

slack-chat/
├── src/
│   ├── cli.py         # Main CLI
│   ├── server.py      # Browser server (FastAPI)
│   ├── storage.py     # Storage operations
│   └── pull.py        # Pull command
├── storage/           # Local message cache
│   ├── _cache/
│   │   ├── users.yml
│   │   └── channels.yml
│   ├── b89c7a14...md
│   ├── 4aab08f1...md
│   └── ...
└── doc/
    └── SPEC1.md       # Architecture spec

Tips for AI Agents

  1. Pull first: Always slack-chat pull before reading messages to get fresh data
  2. Use partial IDs: b89c7a instead of full b89c7a14755df6dca...
  3. Check summary: slack-chat inbox summary to understand data volume
  4. Resolve IDs: Use slack-chat user resolve and slack-chat channel resolve to convert IDs to names
  5. Test with limits: Use --limit 5 when prototyping workflows
  6. Mark processed: Always inbox read after processing to track state
  7. Use relative dates: yesterday, "7 days ago" are clearer than exact dates
  8. Cache is your friend: ID resolution is cached, so feel free to resolve repeatedly

Architecture Notes

  • Storage: All files in storage/ are Markdown with YAML frontmatter (Git-friendly)
  • No database: Direct filesystem access
  • Offline-first: Inbox commands work without server running
  • Deduplication: SHA1 hashing ensures same message = same storage file
  • ID cache: User/channel info cached to reduce API calls
  • Server required: For pull, resolve commands, and write operations

Troubleshooting

  • if a command returns HTTP 500,
    slack-chat server status # check if server is healthy
    slack-chat server stop # stop it
    slack-chat server start # re-start it