Initial commit
This commit is contained in:
304
skills/searching-slack-history/SKILL.md
Normal file
304
skills/searching-slack-history/SKILL.md
Normal file
@@ -0,0 +1,304 @@
|
||||
---
|
||||
name: searching-slack-history
|
||||
description: Use when needing to search Slack message history, find past conversations, or retrieve channel messages - provides Slack Web API patterns for search.messages and conversations.history endpoints using WebFetch or curl
|
||||
---
|
||||
|
||||
# Searching Slack History
|
||||
|
||||
## Overview
|
||||
|
||||
Search Slack message history using the Slack Web API.
|
||||
|
||||
**Core principle:** Use Slack's REST API endpoints with WebFetch or curl to search messages, retrieve channel history, and find past conversations.
|
||||
|
||||
**Prerequisites:** Slack Bot token with appropriate scopes (setup guide below)
|
||||
|
||||
## Setup Guide (One-Time)
|
||||
|
||||
### Creating a Slack Bot Token
|
||||
|
||||
1. Visit https://api.slack.com/apps → Click "Create New App"
|
||||
2. Choose "From scratch"
|
||||
3. Name it (e.g., "Claude Search Bot")
|
||||
4. Select your workspace
|
||||
5. Navigate to "OAuth & Permissions" in sidebar
|
||||
6. Scroll to "Scopes" → "Bot Token Scopes"
|
||||
7. Add these scopes:
|
||||
- `search:read` - Search messages across workspace
|
||||
- `channels:history` - Read public channel history
|
||||
- `channels:read` - List public channels
|
||||
- `groups:history` - Read private channel history (if needed)
|
||||
- `groups:read` - List private channels (if needed)
|
||||
8. Click "Install to Workspace" at top of page
|
||||
9. Authorize the app
|
||||
10. Copy the "Bot User OAuth Token" (starts with `xoxb-`)
|
||||
11. Store securely as environment variable:
|
||||
```bash
|
||||
export SLACK_TOKEN="xoxb-your-token-here"
|
||||
```
|
||||
|
||||
**Security:** Never commit tokens to git. Use environment variables or secure credential storage.
|
||||
|
||||
**Private channels:** Bot must be invited to private channels before it can search them (`/invite @YourBotName`).
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Task | Endpoint | Key Parameters |
|
||||
|------|----------|----------------|
|
||||
| Search all messages | `search.messages` | `query`, `sort`, `count` |
|
||||
| Get channel history | `conversations.history` | `channel`, `limit`, `oldest` |
|
||||
| Find channel ID | `conversations.list` | `types`, `exclude_archived` |
|
||||
| Search by date range | `search.messages` | `query` with date operators |
|
||||
|
||||
## API Patterns
|
||||
|
||||
**Security Note:** Never echo commands containing tokens. Use silent execution to prevent token exposure in terminal output.
|
||||
|
||||
### Search Messages Globally
|
||||
|
||||
**Endpoint:** `POST https://slack.com/api/search.messages`
|
||||
|
||||
**Use case:** Find messages across all channels the bot has access to.
|
||||
|
||||
**Secure pattern (use this):**
|
||||
```bash
|
||||
# Create curl command without echoing it
|
||||
cat > /tmp/slack_search.sh << 'SCRIPT'
|
||||
curl -s -X POST https://slack.com/api/search.messages \
|
||||
-H "Authorization: Bearer $SLACK_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"query": "your search terms",
|
||||
"count": 20,
|
||||
"sort": "timestamp"
|
||||
}'
|
||||
SCRIPT
|
||||
|
||||
# Execute without showing token in terminal
|
||||
bash /tmp/slack_search.sh
|
||||
rm /tmp/slack_search.sh
|
||||
```
|
||||
|
||||
**Alternative secure pattern:**
|
||||
```bash
|
||||
# Use curl config file (doesn't appear in terminal/history)
|
||||
cat > /tmp/slack.curl << EOF
|
||||
header = "Authorization: Bearer $SLACK_TOKEN"
|
||||
header = "Content-Type: application/json"
|
||||
EOF
|
||||
|
||||
curl -s -K /tmp/slack.curl -X POST https://slack.com/api/search.messages \
|
||||
-d '{"query": "your search terms", "count": 20, "sort": "timestamp"}'
|
||||
|
||||
rm /tmp/slack.curl
|
||||
```
|
||||
|
||||
**Query operators:**
|
||||
- `"exact phrase"` - Match exact phrase
|
||||
- `from:@username` - Messages from specific user
|
||||
- `in:#channel` - Messages in specific channel
|
||||
- `after:YYYY-MM-DD` - Messages after date
|
||||
- `before:YYYY-MM-DD` - Messages before date
|
||||
|
||||
**Example with operators:**
|
||||
```json
|
||||
{
|
||||
"query": "deployment after:2025-01-01 in:#engineering",
|
||||
"count": 50
|
||||
}
|
||||
```
|
||||
|
||||
**Rate limit:** Tier 3 (20 requests/minute)
|
||||
|
||||
### Get Channel History
|
||||
|
||||
**Endpoint:** `POST https://slack.com/api/conversations.history`
|
||||
|
||||
**Use case:** Retrieve recent messages from a specific channel.
|
||||
|
||||
**Important:** Requires channel ID, not channel name. Use `conversations.list` first if you only have the name.
|
||||
|
||||
**Secure pattern:**
|
||||
```bash
|
||||
# Use config file to hide token
|
||||
cat > /tmp/slack.curl << EOF
|
||||
header = "Authorization: Bearer $SLACK_TOKEN"
|
||||
header = "Content-Type: application/json"
|
||||
EOF
|
||||
|
||||
curl -s -K /tmp/slack.curl -X POST https://slack.com/api/conversations.history \
|
||||
-d '{"channel": "C1234567890", "limit": 100}'
|
||||
|
||||
rm /tmp/slack.curl
|
||||
```
|
||||
|
||||
**Time filtering:**
|
||||
```json
|
||||
{
|
||||
"channel": "C1234567890",
|
||||
"oldest": "1609459200.000000",
|
||||
"latest": "1640995200.000000",
|
||||
"limit": 100
|
||||
}
|
||||
```
|
||||
|
||||
Timestamps are Unix epoch time with microseconds (e.g., `1609459200.000000` = 2021-01-01).
|
||||
|
||||
### Find Channel ID from Name
|
||||
|
||||
**Endpoint:** `POST https://slack.com/api/conversations.list`
|
||||
|
||||
**Use case:** Get channel ID when you only know the channel name.
|
||||
|
||||
**Secure pattern:**
|
||||
```bash
|
||||
cat > /tmp/slack.curl << EOF
|
||||
header = "Authorization: Bearer $SLACK_TOKEN"
|
||||
header = "Content-Type: application/json"
|
||||
EOF
|
||||
|
||||
curl -s -K /tmp/slack.curl -X POST https://slack.com/api/conversations.list \
|
||||
-d '{"types": "public_channel,private_channel", "exclude_archived": true}'
|
||||
|
||||
rm /tmp/slack.curl
|
||||
```
|
||||
|
||||
**Filter response:** Look for channel with matching `name` field, extract `id`.
|
||||
|
||||
### Handling Pagination
|
||||
|
||||
All endpoints return paginated results. Check for `response_metadata.next_cursor`:
|
||||
|
||||
```bash
|
||||
# Create reusable config (do this once)
|
||||
cat > /tmp/slack.curl << EOF
|
||||
header = "Authorization: Bearer $SLACK_TOKEN"
|
||||
header = "Content-Type: application/json"
|
||||
EOF
|
||||
|
||||
# First request
|
||||
curl -s -K /tmp/slack.curl -X POST https://slack.com/api/search.messages \
|
||||
-d '{"query": "search", "cursor": ""}'
|
||||
|
||||
# If response contains "next_cursor": "dXNlcjpVMDYxTkZUVDI="
|
||||
# Second request with cursor
|
||||
curl -s -K /tmp/slack.curl -X POST https://slack.com/api/search.messages \
|
||||
-d '{"query": "search", "cursor": "dXNlcjpVMDYxTkZUVDI="}'
|
||||
|
||||
# Clean up when done
|
||||
rm /tmp/slack.curl
|
||||
```
|
||||
|
||||
Continue until `next_cursor` is empty or not present.
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
### 1. Missing Token Scopes
|
||||
**Symptom:** `{"ok": false, "error": "missing_scope"}`
|
||||
|
||||
**Fix:** Add required scopes in Slack App OAuth settings, then reinstall app to workspace.
|
||||
|
||||
### 2. Using Channel Names Instead of IDs
|
||||
**Symptom:** `{"ok": false, "error": "channel_not_found"}`
|
||||
|
||||
**Fix:** Call `conversations.list` first to map channel name → ID.
|
||||
|
||||
### 3. Ignoring Pagination
|
||||
**Symptom:** Only getting first 20-100 results, missing older messages.
|
||||
|
||||
**Fix:** Check for `response_metadata.next_cursor` and make subsequent requests with cursor parameter.
|
||||
|
||||
### 4. Rate Limit Errors
|
||||
**Symptom:** `{"ok": false, "error": "rate_limited"}` or HTTP 429
|
||||
|
||||
**Fix:** Implement exponential backoff. Wait time often provided in `Retry-After` header.
|
||||
|
||||
### 5. Private Channel Access
|
||||
**Symptom:** Empty results or permission errors for private channels.
|
||||
|
||||
**Fix:**
|
||||
- Add `groups:history` and `groups:read` scopes
|
||||
- Invite bot to private channel: `/invite @YourBotName`
|
||||
|
||||
### 6. Token Exposure in Terminal
|
||||
**Risk:** Running curl with `-H "Authorization: Bearer $SLACK_TOKEN"` displays token in terminal output and shell history.
|
||||
|
||||
**Fix:**
|
||||
- **ALWAYS** use curl config files (`-K /tmp/slack.curl`) to hide token
|
||||
- Create config file with headers, run curl referencing it, delete config after
|
||||
- Never echo commands containing `$SLACK_TOKEN`
|
||||
- Add `.env` to `.gitignore` if storing tokens in files
|
||||
- Rotate token immediately if exposed in logs or history
|
||||
|
||||
## Response Format
|
||||
|
||||
Successful responses have `"ok": true`:
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"messages": {
|
||||
"matches": [
|
||||
{
|
||||
"type": "message",
|
||||
"user": "U1234567890",
|
||||
"text": "Message content",
|
||||
"ts": "1234567890.123456",
|
||||
"permalink": "https://workspace.slack.com/archives/...",
|
||||
"channel": {
|
||||
"id": "C1234567890",
|
||||
"name": "general"
|
||||
}
|
||||
}
|
||||
],
|
||||
"total": 150
|
||||
},
|
||||
"response_metadata": {
|
||||
"next_cursor": "dXNlcjpVMDYxTkZUVDI="
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Error responses have `"ok": false`:
|
||||
```json
|
||||
{
|
||||
"ok": false,
|
||||
"error": "invalid_auth"
|
||||
}
|
||||
```
|
||||
|
||||
## Real-World Workflow
|
||||
|
||||
**Scenario:** Find all messages about "deployment" in #engineering from last week.
|
||||
|
||||
```bash
|
||||
# 1. Create secure config file
|
||||
cat > /tmp/slack.curl << EOF
|
||||
header = "Authorization: Bearer $SLACK_TOKEN"
|
||||
header = "Content-Type: application/json"
|
||||
EOF
|
||||
|
||||
# 2. Get channel ID (pipe to jq to extract)
|
||||
curl -s -K /tmp/slack.curl -X POST https://slack.com/api/conversations.list \
|
||||
-d '{"types": "public_channel"}' \
|
||||
| jq -r '.channels[] | select(.name=="engineering") | .id'
|
||||
# Returns: C1234567890
|
||||
|
||||
# 3. Search messages with date filter
|
||||
curl -s -K /tmp/slack.curl -X POST https://slack.com/api/search.messages \
|
||||
-d '{
|
||||
"query": "deployment in:#engineering after:2025-10-24",
|
||||
"count": 100,
|
||||
"sort": "timestamp"
|
||||
}'
|
||||
|
||||
# 4. Clean up config file
|
||||
rm /tmp/slack.curl
|
||||
```
|
||||
|
||||
## Further Reading
|
||||
|
||||
- Slack Web API Documentation: https://api.slack.com/web
|
||||
- search.messages: https://api.slack.com/methods/search.messages
|
||||
- conversations.history: https://api.slack.com/methods/conversations.history
|
||||
- OAuth Scopes Reference: https://api.slack.com/scopes
|
||||
Reference in New Issue
Block a user