Skip to content

Authentication & tokens

slackctl stores every credential in your OS keyring (macOS Keychain, Linux Secret Service, Windows Credential Manager), with an encrypted-file fallback for headless hosts. Tokens are never written to a config file, and --dry-run redacts them.

Token kinds

A workspace profile can hold up to four credential kinds. Store one with slackctl auth login --kind <kind>:

Kind Looks like Where to get it Unlocks
bot (default) xoxb-… App → OAuth & Permissions → Bot User OAuth Token almost everything
user xoxp-… App → OAuth & Permissions → User OAuth Token search, saved, --as-user, listen via RTM
app xapp-… App → Basic Information → App-Level Tokens (scope connections:write) listen via Socket Mode
session xoxc-… + xoxd-… your logged-in browser everything except Socket Mode — no Slack app needed
slackctl auth login                 # bot token (default)
slackctl auth login --kind user     # user token
slackctl auth login --kind app      # app-level token
slackctl auth login --kind session  # browser session (xoxc + xoxd)
slackctl auth logout                # remove all tokens for the workspace

Which token does a command use?

Most commands use the bot token. search and saved are user-only (Slack rejects bot tokens there), so they use the user token automatically. Add --as-user to run any other command with the user token instead. listen picks app or user/session depending on the transport — see The listen command.

Bot scopes

Request the scopes matching what you'll call, under OAuth & Permissions, then reinstall the app:

channels:read groups:read im:read mpim:read (listing) · channels:history groups:history im:history mpim:history (history/replies/export) · chat:write (posting) · channels:manage groups:write im:write mpim:write (create/invite/topic/mark) · channels:join · reactions:read reactions:write · users:read users:read.email users:write (presence) · usergroups:read usergroups:write · pins:read pins:write · bookmarks:read bookmarks:write · files:read files:write (upload/download) · dnd:read · canvases:read canvases:write · emoji:read · team:read.

For the user token: search:read, stars:read, stars:write, dnd:write (snooze), users.profile:write (set status). assistant search-context works with a bot token (search:read.public + friends) — unlike search, which needs a user token.

No Slack app? Use a browser session

A Slack web-client session — an xoxc- token plus the paired xoxd- d cookie, the credentials your browser holds — authenticates as you, with no app to create. It backs bot- and user-kind commands (search and saved items included). The only thing it can't do is Socket Mode; listen uses RTM instead.

slackctl auth login --kind session      # paste the xoxc token, then the xoxd cookie
# or env-only:
export SLACK_XOXC_TOKEN=xoxc-…
export SLACK_XOXD_TOKEN=xoxd-…
slackctl auth status
slackctl conversations list
slackctl listen --dms --json            # streams over RTM

Where the values live

Both halves come from a logged-in browser session. slackctl sends the d cookie verbatim (browsers store it URL-encoded — re-encoding breaks the session) and never logs or commits either value.

Environment variables

Env vars override the keyring, so they're handy for CI:

Variable Purpose
SLACK_BOT_TOKEN / SLACK_USER_TOKEN / SLACK_APP_TOKEN per-kind tokens
SLACK_XOXC_TOKEN + SLACK_XOXD_TOKEN a browser session pair
SLACKCTL_TOKEN explicit override for any single-token kind
SLACKCTL_WORKSPACE select the active workspace profile

Precedence (per kind): SLACKCTL_TOKEN / the kind's env var → the session env pair → the keyring OAuth token → the keyring session pair.

Workspaces (profiles)

A profile is a workspace. Name them and switch freely:

slackctl auth login --workspace acme
slackctl config list-profiles
slackctl config use acme                     # set the default
slackctl conversations list --workspace other  # one-off

--profile is a hidden alias for --workspace, so generic scripts keep working.

Verify & troubleshoot

slackctl auth status     # identity, workspace, validity
slackctl doctor          # config + credentials + connectivity + clock, exits non-zero on failure

Common errors and their fixes:

Error Fix
not_authed / invalid_auth slackctl auth login (check the workspace)
missing_scope the message names the scope — add it and reinstall the app
not_allowed_token_type user-only method: auth login --kind user, then --as-user
not_in_channel slackctl conversations join --channel <id> (public) or /invite the bot