Install
openclaw skills install slack-thread-exportExport Slack thread messages from a logged-in Slack web tab into CSV using an attached Chrome Browser Relay tab. Use when the user wants to collect Slack con...
openclaw skills install slack-thread-exportUse this skill when Slack data must be exported from a real logged-in browser tab instead of a bot token or admin API.
This skill is intentionally optimized for logged-in Slack Web exports through an attached Chrome Browser Relay tab.
It is meant to be good at:
It is not meant to be:
profile="chrome".openclaw browser --browser-profile chrome to confirm the attached tab is the correct Slack workspace.localStorage.localConfig_v2 from the Slack tab to get the active team metadata and xoxc token used by the web client.search.messages endpoint from inside the page context using fetch('/api/search.messages', ...) so the logged-in browser session supplies the right cookies/session context.count=100, increment page).ratelimited with sleep/retry.count == 0 or < 100 for a page.thread_ts= when the user wants thread replies.This skill does not scrape visible Slack DOM rows as the primary path. Instead it piggybacks on the same internal search flow used by Slack Web:
localStorage.localConfig_v2.fetch('/api/search.messages', ...) from the attached Slack page so the request inherits the browser session cookies and client context.This is more reliable than host-side requests because Slack search often expects both the token and the live logged-in browser session.
Use these defaults unless there is a clear reason not to:
count=100 per search.messages request
sleep-seconds=0.5 between normal page requestsratelimited, sleep at least 3-5 seconds before retrying the same pagemax-pages=60 per channel as a practical ceilingPractical guidance:
Why this matters:
ratelimited if requests come too quickly or the query is too broad.These are not theoretical claims only; the workflow was exercised against a real logged-in Slack tab.
Test shape:
tech-team, moonlight, dev-partafter=2026-03-01, before=2026-03-15strictObserved result:
tech-team: 9 rowsmoonlight: 29 rowsdev-part: 0 rowsThis validated:
--before--after--channel-file--summary-json--failed-channels-out--resume-from-jsonl--preflightstrict modeTo prove that heuristic mode does more than strict, a second test included edge channels:
tech-teammoonlightrandommusicai서비스활용-loungeObserved result:
strict: 50 rows keptheuristic: 40 rows keptrandom: 9music: 1The removed examples were casual/non-work items such as chatty thread replies, celebration posts, and a YouTube link. This confirmed that heuristic mode can reduce obvious non-work noise when mixed channels are included.
A broader run used these channels:
moonlightdev-parttech-teambobcmsStress settings:
max-pages=20sleep-seconds=0.05heuristicObserved result:
Interpretation:
At this stage, the skill is suitable for beta/publication-candidate use when these caveats are respected:
strict or raw mode is chosenIf publishing publicly, describe it as an advanced/browser-relay Slack export skill rather than a universal Slack export solution.
Handle failures explicitly:
invalid_auth
ratelimited
after: date filters.Use these building blocks:
from:<@USER_ID>is:threadin:#channel-nameafter:YYYY-MM-DDTypical query:
from:<@UXXXX> is:thread in:#tech-team after:2026-01-01
Use these columns unless the user asks otherwise:
datetime_utcchannel_namechannel_idthread_tsusernametextpermalinksource_query_channelscripts/export_slack_threads.py — channel-by-channel Slack thread exporter driven through the attached Chrome relay tab.scripts/retry_failed_channels.py — rerun export using the failed-channels-out file from a previous run.Run scripts with explicit parameters instead of editing code in place.
Example:
python3 skills/slack-thread-export/scripts/export_slack_threads.py \
--target-id <attached-tab-id> \
--user-id U04SFF458BC \
--team-id T01AY79ELUC \
--channels tech-team moonlight dev-part \
--after 2026-01-01 \
--before 2026-03-15 \
--mode heuristic \
--failed-channels-out exports/slack/failed.txt \
--summary-json exports/slack/summary.json \
--out-csv exports/slack/out.csv \
--out-jsonl exports/slack/out.jsonl
Narrow the export before retrying:
When a run is partial:
--failed-channels-out.scripts/retry_failed_channels.py.--resume-from-jsonl so the retry output starts from the previous raw capture instead of rebuilding from zero.Retry example:
python3 skills/slack-thread-export/scripts/retry_failed_channels.py \
--target-id <attached-tab-id> \
--user-id U04SFF458BC \
--team-id T01AY79ELUC \
--failed-channels-file exports/slack/failed.txt \
--resume-from-jsonl exports/slack/out.jsonl \
--out-csv exports/slack/retry.csv \
--out-jsonl exports/slack/retry.jsonl \
--summary-json exports/slack/retry-summary.json \
--failed-channels-out exports/slack/retry-failed.txt
The script now supports these operational controls:
--channel-file — read channel names from a file--after / --before — date windowing--resume-from-jsonl — continue from a previous raw export--failed-channels-out — save failed channels for targeted retry--summary-json — save structured run summary--preflight — sample page-1 volume per channel before full export--mode strict|raw|heuristic
strict: export only the requested channel/date slice, no work-like heuristic filteringraw: keep everything collected after the query constraints; useful for audit/review datasetsheuristic: apply work-related channel/text filtering after collection--keyword / --channel-hint — extend heuristic filtering for a specific workspaceFor “work-related” exports, prefer this order:
If the user says "all work-related threads", explain that this is heuristic unless they provide a strict channel whitelist or date range.
Use strict when:
Use raw when:
Use heuristic when:
If unsure, start with strict or raw, then derive a second-pass heuristic export for comparison.