A CLI tool to export Slack messages (DMs, groups, channels) to Google Docs with organized folder structure.
- Browser-based extraction: Access DMs and private group messages via Chrome DevTools Protocol
- API-based extraction: Access public/private channels via Slack bot token
- Google Drive integration: Creates organized folder hierarchy with daily Google Docs
- Thread support: Exports threads to separate subfolders with linked references
- @Mention linking: Converts
@mentionsto clickable Google email links in exported docs - Slack link replacement: Replaces Slack message URLs with links to the corresponding Google Docs
- Cross-conversation link resolution: Second-pass scan resolves forward references across conversations
- Batch export:
--all-dmsand--all-groupsflags for bulk export by conversation type - Parallel export:
--parallel Nexports up to N conversations concurrently - Checkpoint/Resume: Granular checkpointing after each doc — resume crashed exports with
--resume - Incremental sync:
--syncmode exports only new messages since last run - Pre-export validation: Verifies Slack session and Google token before starting long exports
- Name resolution: Converts Slack user IDs to real names in exported documents
- People discovery: Auto-populate user mappings from configured conversations
- Go 1.24+ - For building the binary
- Google Cloud Project with:
- Drive API enabled
- Docs API enabled
- OAuth 2.0 credentials (Desktop app type)
- Chrome/Chromium running with remote debugging enabled (for browser mode)
- Slack workspace access - Active session in browser or bot token
brew tap jflowers/tools
brew install get-outDownload the latest release from GitHub Releases:
- macOS (Apple Silicon):
get-out_darwin_arm64.tar.gz - macOS (Intel):
get-out_darwin_amd64.tar.gz - Linux (x86_64):
get-out_linux_amd64.tar.gz - Linux (ARM64):
get-out_linux_arm64.tar.gz
# Clone the repository
git clone https://github.com/jflowers/get-out.git
cd get-out
# Build the binary
go build -o get-out ./cmd/get-out
# Verify installation
./get-out --help- Go to Google Cloud Console
- Create a new project or select existing
- Enable Google Drive API and Google Docs API
- Create OAuth 2.0 credentials (Desktop application)
- Download
credentials.jsonto your config directory
Run init to scaffold the config directory (~/.get-out/):
get-out initThis creates ~/.get-out/, migrates any existing ~/.config/get-out/ files, and prompts for your Google Drive folder ID.
Or use a local config directory with --config ./config.
Define which conversations to export:
{
"conversations": [
{
"id": "C04KFBJTDJR",
"name": "team-engineering",
"type": "channel",
"mode": "api",
"export": true,
"share": true
},
{
"id": "D06DDJ2UH2M",
"name": "John Smith",
"type": "dm",
"mode": "browser",
"export": true,
"share": true
}
]
}Fields:
id: Slack conversation ID (C=channel, D=DM, G=group)name: Display name for the export foldertype:channel,private_channel,dm, ormpimmode:browser(uses Chrome session) orapi(uses bot token)export: Set totrueto include in exportshare: Whether to share the exported folder (future feature)shareMembers: Optional list of emails to share with
Application-wide settings:
{
"slackBotToken": "xoxb-your-bot-token-here",
"googleCredentialsFile": "/path/to/your/credentials.json",
"googleDriveFolderId": "1ABC123xyz_your_folder_id",
"localExportOutputDir": "./slack_exports",
"logLevel": "INFO"
}Fields:
slackBotToken: Slack bot token for API mode (future use)googleCredentialsFile: Custom path to Google OAuth credentials (overrides default)googleDriveFolderId: Default Google Drive folder ID for exports (can be overridden with--folder-id)localExportOutputDir: Directory for local exports (future use)logLevel: Logging verbosity (DEBUG,INFO,WARN,ERROR)
All fields are optional. CLI flags override settings values.
Map Slack user IDs to display names and preferences:
{
"people": [
{
"slackId": "U1234567890",
"email": "user@example.com",
"displayName": "John Doe"
},
{
"slackId": "U0987654321",
"displayName": "Jane Smith",
"noNotifications": true
}
]
}# 1. Initialize config directory
get-out init
# 2. Authenticate with Google
get-out auth login
# 3. Verify Chrome + Slack setup
get-out setup-browser
# 4. Export
get-out exportRun this first to complete OAuth flow:
get-out auth loginThis opens a browser for Google consent and saves the token.
Check authentication status without opening a browser:
get-out auth statusPopulate people.json with users from your configured conversations:
# Requires Chrome with Slack open (browser mode)
./get-out discover --config ./config
# Overwrite existing people.json instead of merging
./get-out discover --no-merge --config ./configThis will:
- Read
conversations.jsonto get your configured conversations - Fetch member lists for each conversation from Slack
- Look up user details (name, email, display name) for all members
- Generate/update
people.jsonwith user mappings - Skip bots, app users, and deleted users
By default, new users are merged with existing people.json entries. Use --no-merge to overwrite.
./get-out list --config ./configThe setup wizard automatically launches Chrome with a dedicated profile and guides you through Slack authentication:
# Launch Chrome, authenticate with Slack, and verify setup
get-out setup-browserThe wizard will:
- Create a dedicated Chrome profile at
~/.get-out/chrome-data/ - Launch Chrome with remote debugging enabled (or detect an existing instance)
- Open
https://app.slack.comfor you to sign in - Wait for you to authenticate, then verify credentials
- Validate against the Slack API
On subsequent runs, Chrome reuses the dedicated profile so you're already signed in.
# Dry run - see what would be exported
./get-out export --dry-run --config ./config
# Export all configured conversations
./get-out export --config ./config
# Export specific conversations
./get-out export D06DDJ2UH2M C04KFBJTDJR --config ./config
# Export all DMs or all group conversations
./get-out export --all-dms --config ./config
./get-out export --all-groups --config ./config
# Export in parallel (up to 5 conversations at once)
./get-out export --parallel 5 --config ./config
# Sync mode - export only new messages since last run
./get-out export --sync --config ./config
# Resume a crashed/interrupted export
./get-out export --resume --config ./config
# Export messages from a specific date range
./get-out export --from 2024-01-01 --to 2024-06-30 --config ./config
# Use a custom people.json for @mention linking
./get-out export --user-mapping /path/to/people.json --config ./config
# With verbose output
./get-out export --config ./config -v
# Custom Chrome port
./get-out export --chrome-port 9223 --config ./config
# Custom Drive folder name
./get-out export --folder "My Slack Archive" --config ./config
# Export to an existing Google Drive folder by ID
./get-out export --folder-id 1ABC123xyz --config ./config./get-out status --config ./configShows conversation export progress: status (complete/in-progress), message counts, doc counts, and last updated time.
--config string Config directory path (default "~/.get-out")
--no-keyring Disable OS keychain; store secrets in plaintext files (0600)
--chrome-port int Chrome DevTools Protocol port (default 9222)
-v, --verbose Verbose output
--debug Enable debug output
--folder string Google Drive root folder name (default "Slack Exports")
--folder-id string Google Drive folder ID to export into (overrides --folder)
--dry-run Show what would be exported without actually exporting
--resume Resume from last checkpoint
--sync Only export messages since last successful export
--from string Export messages from this date (YYYY-MM-DD)
--to string Export messages up to this date (YYYY-MM-DD)
--all-dms Export all DM conversations
--all-groups Export all group (MPIM) conversations
--parallel int Number of conversations to export concurrently, max 5 (default 1)
--user-mapping string Path to people.json for @mention linking
Note: The --folder-id can be found in a Google Drive folder URL: https://drive.google.com/drive/folders/{folder-id}
Exported content is organized in Google Drive as:
Slack Exports/
├── DM - John Smith/
│ ├── 2024-01-15.gdoc
│ ├── 2024-01-16.gdoc
│ └── Threads/
│ └── 2024-01-15 - Project discussion/
│ └── 2024-01-15.gdoc
├── Channel - engineering/
│ ├── 2024-01-14.gdoc
│ └── 2024-01-15.gdoc
└── Group - Alice, Bob, Carol/
└── 2024-01-16.gdoc
get-out/
├── cmd/get-out/ # CLI entry point
├── internal/cli/ # Command implementations
│ ├── root.go # Base command and global flags
│ ├── auth.go # Google OAuth commands (auth login, auth status)
│ ├── selfservice.go # Self-service commands (init, doctor, setup-browser)
│ ├── helpers.go # Shared formatting helpers
│ ├── discover.go # Discover people from conversations
│ ├── export.go # Export command
│ ├── list.go # List conversations command
│ └── status.go # Show export status
├── pkg/
│ ├── chrome/ # Chrome DevTools Protocol client
│ ├── slackapi/ # Slack API client (browser + bot modes)
│ ├── gdrive/ # Google Drive/Docs API client
│ ├── exporter/ # Export orchestration and indexing
│ ├── parser/ # Slack mrkdwn, user/person resolution
│ ├── config/ # Configuration loading
│ └── models/ # Shared data models
├── config/ # Example configuration files
└── specs/ # Feature specifications
Every push and pull request runs the full CI pipeline defined in .github/workflows/ci.yml. The pipeline includes automated code quality analysis via gaze, which enforces hard quality gates on every PR targeting main.
| Step | What it does |
|---|---|
| Build | Compiles all packages — fails fast on build errors |
| Vet | Runs go vet — catches common correctness issues |
| Test | Runs the full test suite with race detection and generates a coverage profile |
| Install gaze | Installs the gaze quality analysis tool |
| Install OpenCode | Installs the OpenCode CLI (used by gaze as its AI backend) |
| Gaze quality report | Analyses CRAP scores and contract coverage; writes a formatted report to the Step Summary tab |
The Gaze quality report step enforces three hard gates. A PR is blocked if any gate is breached:
| Gate | Threshold | What it measures |
|---|---|---|
--max-crapload |
20 | Maximum number of functions exceeding the CRAP score threshold (complexity × lack of coverage) |
--max-gaze-crapload |
8 | Maximum number of functions exceeding the GazeCRAP threshold (complexity × lack of contract coverage) |
--min-contract-coverage |
16% | Minimum average contract coverage — the percentage of contractual side effects that tests actually assert on |
When a gate is breached, the CI step exits non-zero and the PR check fails. To understand why:
- Open the failed GitHub Actions run
- Click the Summary tab at the top of the run page
- The gaze quality report is there in plain language, showing which functions exceeded their thresholds and why
No log parsing or artifact downloads needed — the full report is in the Step Summary.
All threshold values live in .github/workflows/ci.yml in the Gaze quality report step's run: block. Edit that file to tighten or loosen any gate. No changes to source code or tool configuration are required.
To disable a specific gate entirely, remove its flag from the run: block. To enforce zero tolerance, set the flag to 0 (e.g. --max-crapload=0).
The Gaze quality report step requires an OPENCODE_API_KEY secret set in the repository's GitHub Actions secrets (Settings → Secrets and variables → Actions). This key authenticates the OpenCode CLI against the OpenCode Zen model tier. Without it, the step will fail.
- Connects to Chrome via DevTools Protocol (port 9222)
- Finds active Slack tab and extracts
xoxctoken from localStorage - Extracts
xoxdcookie for authentication - Makes authenticated API calls to Slack's internal endpoints
- Uses
xoxbbot token (configured via environment or config) - Makes standard Slack API calls
- Requires bot to be installed in the workspace
- Validates Slack session and Google token (fail-fast)
- Authenticates with Google Drive
- Creates folder structure (root → conversation → threads)
- Fetches messages with pagination and rate limit handling
- Groups messages by date
- Writes to Google Docs with formatting, @mention links, and Slack URL replacement
- Saves checkpoint after each doc for resume capability
- Resolves cross-conversation links in a second pass
- Tokens are extracted at runtime from active browser sessions
- Google OAuth credentials and tokens are stored in the OS keychain (macOS Keychain, Linux Secret Service) by default; use
--no-keyringto fall back to 0600 plaintext files in~/.get-out/ - Never commit
credentials.json,token.json, orconversations.jsonwith real data - The
.gitignoreexcludes sensitive files by default
Run get-out doctor to check all common setup issues at once. It prints actionable fixes for each failing check.
Run get-out setup-browser — it will launch Chrome and guide you through Slack authentication.
If Chrome is already running, make sure you have a Slack tab open at https://app.slack.com.
Run get-out setup-browser to launch Chrome with the correct debugging flags.
If you prefer manual control, check that Chrome is running with --remote-debugging-port=9222 and the port matches --chrome-port.
Ensure you're logged into Slack in the browser. Try refreshing the Slack tab.
Download credentials.json from Google Cloud Console and place it in ~/.get-out/.
MIT