Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 08:49:36 +08:00
commit 5a38c9367b
4 changed files with 364 additions and 0 deletions

View 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