.claude/skills/slack-fetch/SKILL.md
Fetch Slack messages via MCP tools and write raw exports for /slack processing
npx skillsauth add dcurlewis/ai-context-system .claude/skills/slack-fetchInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Fetch Slack channel and DM messages using MCP Slack tools. Produces one markdown file per channel/DM in Raw-Materials/Slack/ for subsequent processing by /slack.
weekly = forces 7-day lookback for all channelschannel:#name = single channel debug modeParse $ARGUMENTS to determine mode.
Read Scripts/sync_config.json and extract:
slack.channels (both channels and DMs)slack.last_synced_channelsCompute the oldest Unix timestamp (seconds) for each channel:
last_synced_channels.{id} exists: parse that ISO timestamp to Unix secondsnow - 86400 (24h fallback)weekly mode: force now - 604800 (7 days) for all channelsFor channel:#name mode: filter to only the matching channel and use the same timestamp logic.
Store now as a reference timestamp for state updates later.
Spawn a single Haiku sub-agent to discover channels where you were active but that are not in the monitored list.
Agent prompt:
Search Slack for recent activity by the user (user ID: <YOUR_SLACK_USER_ID>) using Slack MCP search tools.
Run two searches (IMPORTANT: must use
response_format: "detailed"because only the detailed format includes channel IDs):
query: "from:<@YOUR_SLACK_USER_ID> after:YYYY-MM-DD"(yesterday's date) withinclude_context: false, response_format: "detailed", limit: 20query: "to:<@YOUR_SLACK_USER_ID> after:YYYY-MM-DD"(yesterday's date) withinclude_context: false, response_format: "detailed", limit: 20For each search, if the response includes a pagination cursor, fetch the next page as well (up to 2 pages per search, i.e. up to 40 results each).
From all results, extract channel IDs from the
Channel: ... (ID: ...)lines in each result.Filter out:
- Any channel IDs that are in this monitored list: [list all channel IDs from Step 1]
- Any bot DMs (participants named "Google Calendar", "Slackbot", or any name that looks like a bot/integration rather than a person)
Return a JSON array of objects:
[{"id": "C...", "name": "channel-name-or-DM-description"}, ...]If no new channels found, return an empty array:[]Do NOT write any files. Only return the JSON result.
Wait for this agent to complete. Parse the discovered channels (cap at 10 max). Discovered channels always use oldest = now - 86400 regardless of mode.
Combine: full export list = monitored channels + discovered channels.
Skip this step entirely in channel:#name mode.
Process the full channel list in batches of 8 channels. For each batch, spawn all agents in parallel, then wait for all to complete before starting the next batch. Pause 3 seconds between batches.
For each channel, spawn a Haiku sub-agent with this prompt:
Export Slack channel "{name}" (ID: {id}).
Call the Slack MCP
read_channeltool with:
- channel_id: "{id}"
- oldest: "{oldest_unix_timestamp}"
- limit: 100
- response_format: "concise"
If the response includes a
next_cursor, make additional calls with that cursor until all messages are fetched or you reach 500 messages total.If you receive a rate_limited error, wait 5 seconds and retry once.
Format the output as a markdown file with this structure:
# Slack Export: {name} *Fetched: {ISO_NOW} | Since: {oldest_ISO_date} | Messages: {count}* --- **{sender}** ({timestamp}): {message body} **Thread Replies:** - **{sender}**: {reply}If there are thread replies in the response, include them nested under the parent message.
If no messages were found since the oldest timestamp, use this format:
# Slack Export: {name} *Fetched: {ISO_NOW} | Since: {oldest_ISO_date} | Messages: 0* --- No new messages.Write the file to:
Raw-Materials/Slack/{YYYYMMDD}-{safe_name}.mdwhere {YYYYMMDD} is today's date and {safe_name} is the channel name with spaces replaced by hyphens and special characters removed. For DMs, use the formatDM-{PersonName}.After writing, respond with a single line:
OK:{message_count}orERROR:{description}
Collect results from all agents, tracking total messages and any errors.
After all batches complete, read Scripts/sync_config.json again (to avoid stale reads), then update:
slack.last_synced = current ISO timestamp (UTC)slack.last_synced_channels.{id} = current ISO timestamp for each monitored channel that was exported (not discovered channels)slack.total_messages = previous value + total messages fetched this runWrite the updated JSON back to Scripts/sync_config.json with proper formatting (2-space indent).
Output a brief summary:
/slack-fetch complete
Mode: daily|weekly|channel
Channels exported: {monitored_count} monitored + {discovered_count} discovered = {total} total
Files written: {count} (Raw-Materials/Slack/)
Messages fetched: {total_messages}
Errors: {error_count}
If there were errors, list each one.
read_channel, note it in the report and skip that DMdevelopment
Add article/book to Professional Philosophies library
business
Process a Slack export from Raw-Materials/Slack queue
data-ai
Interactive end-of-day reflection; surfaces carryover items for next /morning; appends to daily journal
tools
Interactive onboarding — personalise the system for your role, team, tools, and morning routine