Export your Slack conversations to markdown files that AI agents can read.
The problem: AI coding agents like Claude Code can't access Slack. They can't see what your team discussed, what decisions were made, or what tasks were assigned.
The solution: Run slack-export sync daily to maintain a local Slack archive and render your channels to markdown files. Point your AI agent at the folder, and it can now search and reference your team's conversations.
~/slack-logs/
├── 2025-01-25/
│ ├── 2025-01-25-engineering.md
│ ├── 2025-01-25-team-backend.md
│ └── 2025-01-25-dm_alice.md
├── 2025-01-26/
│ ├── 2025-01-26-engineering.md
│ ├── 2025-01-26-project-atlas.md
│ └── 2025-01-26-dm_bob.md
└── 2025-01-27/
└── 2025-01-27-engineering.md
Each file contains that day's messages in clean, readable markdown. Filenames include the date so they stay unique when you copy multiple days to one folder or upload to AI tools like Gemini or NotebookLM.
- Daily sync - resumes a persistent local archive and renders written changes
- Glob filtering - include/exclude channels by pattern (e.g.,
team-*,*-alerts) - Human-readable DMs -
dm_aliceinstead ofdm_U015ANT8LLD - Timezone-aware - accurate date boundaries for your location
- Slack Connect support - resolves external users automatically
- Late thread replies - replies posted days later appear in the reply-day file
curl -fsSL https://raw.githubusercontent.com/ChrisEdwards/slack-export/main/install.sh | shThis auto-detects your platform and installs both slack-export and slackdump to ~/.local/bin. Run the same command to upgrade. The installer tells you what to do next.
To install to a different directory:
curl -fsSL https://raw.githubusercontent.com/ChrisEdwards/slack-export/main/install.sh | INSTALL_DIR=/usr/local/bin shSee Alternative Installation for manual download or building from source.
slackdump workspace wizThis runs the workspace setup wizard, which opens a browser to authenticate with your Slack workspace. Your credentials are stored locally and encrypted. For Enterprise Grid workspaces, use the individual workspace URL (e.g., team.slack.com), not the enterprise URL.
slack-export initWalks you through configuration:
- Output directory for exported logs
- Timezone for date boundaries
- Verifies connection to Slack
Re-run with --force to reconfigure anytime.
slack-export syncOn first run, sync bootstraps a local slackdump v4 database archive, then renders markdown files from that archive. Later runs use slackdump resume -threads to fetch new messages and late thread replies, then render the channel/day files for rows written by that resume.
Run slack-export sync daily (or add it to a cron job) to keep your logs up to date.
Run slack-export sync --full from a separate off-hours schedule for the bounded full sweep. Full sweeps use a 90-day lookback, revisit stale threads up to 90 days, dedupe the archive, and render the rows that sweep wrote. Daily and full syncs share an archive lock; if a full sweep is active, a daily sync skips refresh and render instead of emitting partial markdown.
The archive can only render dates at or after its seed_date. To backfill earlier history, set seed_date before the first sync, or reseed by creating a fresh archive with an earlier date and then run slack-export render --full.
Once the archive covers a date, export renders that date or range from the local database without using Slack network calls:
# Export from a specific date through today
slack-export export --from 2025-01-01
# Export a specific date range
slack-export export --from 2025-01-01 --to 2025-01-15Typical workflow:
- Set
seed_dateto the earliest date you want preserved, or leave it empty to start from existing output/today - Run
slack-export syncto create and refresh the archive - Use
slack-export render --fullafter format changes or reseeding - Use
slack-export export --from <start-date> --to <end-date>for offline date-range rendering
By default, all channels you're a member of are exported. To see all your channels:
slack-export channelsThis shows every channel you're a member of (or have been) with any activity ever. To see which channels have recent activity:
slack-export channels --since 2025-01-20Note: The channels command shows what could be exported. When you run sync or export, only channels with actual messages on each specific day are included in that day's export.
To change which channels are exported, edit ~/.config/slack-export/slack-export.yaml:
include:
- "engineering-*" # glob pattern for channels you're a member of
- "team-*"
- "C01ABC123DE" # channel ID for a channel you're NOT a member of
exclude:
- "*-alerts" # channel name or ID works for excludes
- "bot-*"Including channels you're not a member of: Use the channel ID (e.g., C01ABC123DE), not the name. Find the channel ID in Slack by opening the channel, clicking the channel name, and scrolling to the bottom of the "About" tab.
Excluding channels: Use either the channel name or ID. Names only work for channels you're a member of.
After editing, run slack-export channels again to verify your changes.
Exports use a 3am-to-3am day boundary instead of midnight. This keeps late-night work sessions together—if you're doing customer support until 2am, those messages stay with the previous day rather than splitting at midnight.
The boundary uses your configured timezone.
archive_dir: ~/.local/share/slack-export/archive
seed_date: "" # YYYY-MM-DD; empty starts from existing output or today
lookback: 7d # recent render window
skip_stale_threads: 21d # "" disables stale-thread skipping
skip_complete_threads: true # skip complete thread refreshes during resumeThe archive is stored under archive_dir by workspace name. Dates before seed_date cannot be rendered from the archive; create a fresh archive with an earlier seed date when you need older history.
Any day file touched by a later sync can change as threads evolve or recent messages are edited. Downstream consumers should use fingerprints or mtimes instead of treating rendered day files as immutable.
Configuration is stored at ~/.config/slack-export/slack-export.yaml:
# Output directory for exported logs (default: ./slack-logs)
output_dir: ./slack-logs
# Timezone for date calculations (default: America/New_York)
timezone: America/New_York
# Channel name patterns to include (glob syntax, empty = all channels)
include:
- "engineering-*"
- "team-*"
- "project-*"
# Channel name patterns to exclude (glob syntax)
exclude:
- "*alarms"
- "*-alerts"
- "*-notifications"
- "bot-*"| Option | Default | Description |
|---|---|---|
output_dir |
./slack-logs |
Directory where exports are saved |
timezone |
America/New_York |
Timezone for date boundary calculations |
include |
[] |
Glob patterns for channels to include (empty = all) |
exclude |
[] |
Glob patterns for channels to exclude |
All options can be overridden via environment variables with the SLACK_EXPORT_ prefix:
SLACK_EXPORT_OUTPUT_DIR=/data/slack-logs
SLACK_EXPORT_TIMEZONE=UTCPatterns use glob syntax and match against both channel names and IDs:
| Pattern | Matches |
|---|---|
* |
Any sequence of characters |
? |
Any single character |
Matching is case-insensitive.
Examples:
| Pattern | Matches | Doesn't Match |
|---|---|---|
*alarms |
prod-alarms, devalarms, ALARMS |
alarms-oncall |
*-alerts |
prod-alerts, staging-alerts |
alerts, alertsbot |
bot-* |
bot-deploy, bot-notifications |
mybot-test |
team-? |
team-a, team-b |
team-ab, team |
CFAU264UU |
Channel with ID CFAU264UU |
Other channels |
Filter logic:
- If a channel matches ANY exclude pattern (by name or ID), it is skipped
- If include list is empty, all non-excluded channels are included
- If include list is non-empty, only channels matching an include pattern are included
slack-export initGuided wizard for first-time setup. Checks prerequisites, authenticates with Slack, and creates configuration.
slack-export configShows current settings and the config file being used.
# List all active channels (with include/exclude patterns applied)
slack-export channels
# List channels with activity since a specific date
slack-export channels --since 2026-01-20Use this to discover channel names for configuring patterns.
slack-export export 2026-01-22# From a specific date to today
slack-export export --from 2026-01-15
# Specific date range
slack-export export --from 2026-01-15 --to 2026-01-20slack-export sync
slack-export sync --fullThe sync command:
- Creates the workspace archive on first run
- Resumes the archive with new messages and thread replies
- Renders dated markdown files for rows written by the resume
Use sync --full from an off-hours weekly schedule. It always runs the bounded sweep instead of relying on sync to decide when a sweep is due.
slack-export render
slack-export render --fullrender regenerates files from the local archive without network calls. The default renders the normal lookback window; --full renders every date from seed_date through today.
slack-export --config /path/to/config.yaml export 2026-01-22
slack-export --version
slack-export --helpExports are organized by date and channel:
slack-logs/
├── 2026-01-20/
│ ├── 2026-01-20-engineering-general.md
│ ├── 2026-01-20-team-backend.md
│ └── 2026-01-20-dm_alice.md
├── 2026-01-21/
│ ├── 2026-01-21-engineering-general.md
│ └── 2026-01-21-team-backend.md
└── 2026-01-22/
└── 2026-01-22-engineering-general.md
Direct messages use the other participant's username (e.g., dm_alice). External Slack Connect users are resolved via the API and cached locally.
slack-export stores data in standard locations:
| Data | Location | Purpose |
|---|---|---|
| Configuration | ~/.config/slack-export/slack-export.yaml |
User settings |
| User cache | ~/.cache/slack-export/users.json |
Cached external user info |
| Slack archive | archive_dir/<workspace>/slackdump.sqlite |
Persistent source database |
| Exports | Configured output_dir (default: ./slack-logs) |
Exported messages |
The user cache stores information about external Slack Connect users to avoid repeated API calls.
- Channel Discovery: Uses Slack's Edge API to find tracked channels and resolve DM names.
- Archive Refresh: Uses slackdump v4
archiveandresume -threadsto maintain a persistent SQLite archive. - Counts Scoping: Uses Slack
client.countsactivity timestamps to skip channels that have not moved since the archive checkpoint. - Rendering: Reads the archive database in-process and writes dated markdown files only when bytes change.
Thread replies are bucketed by the day they were posted. If a reply belongs to a thread started on an earlier day, it appears at the end of the reply-day file:
---
## Thread continuations
Replies posted this day in threads started on earlier days.
Lines marked [context] are repeated from the original day for readability.
### Thread started 2026-07-01 (see 2026-07-01/2026-07-01-engineering.md)
[context] > Alice [U123] @ 01/07/2026 14:22:10 Z:
[context] Original parent message text.
| > Bob [U456] @ 03/07/2026 12:01:00 Z:
| Late reply text.-
User Resolution: Fetches workspace users and resolves DM names to human-readable usernames. External Slack Connect users are looked up via the
users.infoAPI and cached to disk. -
Filtering: Applies include/exclude glob patterns to the channel list.
-
Export: Calls slackdump to archive messages for the specified time range. If you have slackdump >= 3.1.13 installed on your system, slack-export uses it automatically. Otherwise, it uses the bundled version.
-
Format: Uses slackdump's
convertcommand to transform the archive into readable text. -
Organize: Extracts and renames files into the dated directory structure.
Run slackdump workspace wiz to authenticate with your Slack workspace.
Credentials are machine-specific. If you authenticated on a different machine, run slackdump workspace wiz again.
- Check that your include patterns match existing channels
- Try running
slack-export channelsto see what channels are available - Verify your Slack authentication is still valid
Your include/exclude patterns are too restrictive. Run slack-export channels to see available channels and adjust your patterns.
Exports use the configured timezone for date boundaries. If messages appear on the wrong date:
- Check your
timezonesetting matches your Slack workspace's primary timezone - Use
slack-export configto verify the current setting
If a DM appears as dm_U015ANT8LLD instead of dm_alice, the user couldn't be resolved. This can happen with:
- Deactivated users
- Users from Slack Connect organizations that restrict the
users.infoAPI
The user cache at ~/.cache/slack-export/users.json can be manually edited if needed.
Slack threads are exported on the date the thread was created, not when replies are added. If someone replies to a thread days later, that reply will not appear in the export for the reply date - it remains with the original thread's date.
This is a limitation of how slackdump organizes thread data.
Download the appropriate archive from Releases:
| Platform | File |
|---|---|
| macOS (Apple Silicon) | slack-export-vX.X.X-darwin-arm64.tar.gz |
| macOS (Intel) | slack-export-vX.X.X-darwin-amd64.tar.gz |
| Linux (x86_64) | slack-export-vX.X.X-linux-amd64.tar.gz |
| Linux (ARM64) | slack-export-vX.X.X-linux-arm64.tar.gz |
| Windows | slack-export-vX.X.X-windows-amd64.zip |
Extract and install:
# macOS/Linux
tar -xzf slack-export-*.tar.gz
mv slack-export slackdump ~/.local/bin/
# Windows (PowerShell)
Expand-Archive slack-export-*.zip -DestinationPath .
# Move slack-export.exe and slackdump.exe to a directory in your PATHRequires Go 1.21+:
git clone https://github.com/chrisedwards/slack-export.git
cd slack-export
make build
# Also install slackdump separately
go install github.com/rusq/slackdump/v4/cmd/slackdump@v4.4.1# Remove binaries
rm ~/.local/bin/slack-export ~/.local/bin/slackdump
# Remove config and cache (optional)
rm -rf ~/.config/slack-export ~/.cache/slack-exportmake build # Build
make test # Run tests
make check # Run linter
make check-test # Run bothMIT