Import from Slack
Import a Slack workspace export — public channels, private channels, DMs, reactions, threads, and mentions — into Comms in a single pass. Admin-only. Reversible in one click.
Before you start
- Slack Workspace Owner access on the source workspace (required to create an export).
- An admin account in Comms. The importer rejects members and
owners server-side with
403 Forbidden. - Comms users already created for the Slack users you want messages attributed to. The importer joins Slack → Comms by email (case-insensitive). Anyone not in Comms lands in the "unmatched" bucket on the preview screen.
- A modern Chromium-based browser. Zip parsing, content conversion, and the NDJSON progress stream all run client-side.
Step 1 — Export from Slack
- Sign in to Slack as a Workspace Owner.
- Go to Settings & administration → Workspace settings →
Import/Export Data → Export (or
https://<your-workspace>.slack.com/services/export). - Pick a date range — entire history, or a smaller window for a proof-of-concept first.
- Click Start Export. Slack emails a download link when it's ready — a few minutes for small workspaces, hours for years of history.
- Download the
.zip. Don't unzip it. Comms ingests the zip directly.
What the export contains
| Slack plan | Public | Private | DMs | Group DMs |
|---|---|---|---|---|
| Free / Pro | ✓ | — | — | — |
| Business+ / Enterprise Grid (Corporate Export enabled) | ✓ | ✓ | ✓ | ✓ |
If your plan only exports public channels, the private/DM sections simply won't appear in the preview — you don't need to do anything special.
Step 2 — Prepare Comms
- Invite the active Slack participants into Comms using the same email addresses they had in Slack. Email is the join key — any Slack user with no matching Comms user will be "unmatched".
- Sign in to Comms as an admin. The importer is gated at two
layers:
- The
/admin/importroute is hidden from non-admins. - The edge function re-checks
user_profiles.roleagainst'admin'and returns403 Forbiddenotherwise.
- The
- Navigate to Admin → Import Data.
Step 3 — Upload the zip
On the Import Data page, drag the .zip onto the Upload
Slack Export drop zone, or click Choose file. Only .zip is
accepted — folders and .tar.gz are rejected.
Parsing runs in your browser: the archive is loaded, channel files are read, system-event messages (joins, leaves, topic changes) are filtered out, threads are reattached to their parents, and Slack's mrkdwn + blocks are converted to Comms HTML. A 500-message export is near-instant; 20,000 messages takes a couple of seconds.
Step 4 — Review the preview
Summary
Totals for channels, messages (parents + thread replies), and users.
User matching
- Matched (green) — Slack users with a Comms user at the same email. Expand the row to verify each mapping before continuing.
- Unmatched (amber) — Slack users with no matching Comms user. Either let the strategy below handle them, or pick a Comms user from the Map to user... dropdown per row.
- Skipped — bots and deactivated Slack users. Excluded unconditionally.
Unmatched-user strategy
Shown only if there's at least one unmatched user. Pick one:
| Strategy | Behavior |
|---|---|
| Skip | Messages from unmatched users are dropped entirely. |
| Attribute to admin | Messages are imported as you, content unchanged. |
| Label in content | Messages are imported as you, but each body is prefixed with [Slack: U12345] so the original author stays visible. Recommended for first imports. |
Channels
One row per channel in the export, with message count, date range,
and a matched/total count of channel members that map to Comms
users. All channels are selected by default — use Select all /
Deselect all or toggle individually.
Step 5 — Run the import
Click Start Import. The edge function returns an NDJSON progress stream; the UI shows the current channel name and running counts of messages, thread replies, and reactions. Numbers advance every 1,000-row database batch.
Typical timing:
| Size | Wall-clock |
|---|---|
| 500 messages | ~5–10 s |
| 5,000 messages | ~30–60 s |
| 20,000 messages | ~45 s |
| 50,000+ messages | May exceed the edge function's CPU budget — split into smaller channel selections. |
Step 6 — Verify
When the import finishes you'll see a Results screen with a
green success banner and final counts. Small deltas from the
preview numbers are normal (bots skipped, skip strategy trims the
total). Big deltas usually mean warnings — expand the yellow
Warnings panel to see per-row errors.
Click Go to Chats and spot-check:
- Open an imported channel — name, topic, member list.
- Scroll to the top — the earliest message should match the date range from the preview.
- Open a thread — replies nested under their parent in timestamp order.
- Find a message with
@mentions— mapped users render as user pills, unmapped render as plain@U12345text. - Find a formatted message — bold, italic, code blocks, links, blockquotes, lists should all render.
- Find a message with reactions — emoji and counts visible.
Step 7 — Rollback
Scroll to Past Imports at the bottom of the import page. Every completed import appears as a row with date, channel count, message count, and batch ID. Click Remove, confirm the dialog, and Comms deletes every reaction, thread reply, parent message, and channel member — then removes the channels themselves and the history row. A 20k-message rollback takes 15–20 seconds.
Channels are removed from the channelIds list persisted on the
history entry, not derived from message rows. That means channels
the importer created but never populated (for example, an
unmatched-user Skip strategy that left a channel empty) still get
cleaned up.