A Dart package and CLI for interacting with the Slack Web API.
Use dart_slack as a library in any Dart or Flutter app:
import 'package:dart_slack/dart_slack.dart';High-level facade with typed return values. This is the recommended entry point.
final slack = Slack(token: 'xoxp-...');
// Post a message
final msg = await slack.postMessage(channel: 'C0123ABCDEF', text: 'Hello!');
print(msg.ts); // message timestamp
// Reply to a thread
await slack.postMessage(
channel: 'C0123ABCDEF',
text: 'Thread reply',
threadTs: '1234567890.123456',
);
// Send a DM (pass a user ID as the channel)
await slack.postMessage(channel: 'U0123ABCDEF', text: 'Hey!');
// List channels
final channels = await slack.listChannels();
for (final channel in channels) {
print('${channel.name} (${channel.id})');
}
// Join a public channel
await slack.joinChannel('C0123ABCDEF');
// Release resources when done
slack.close();postMessage returns a SlackMessage, listChannels returns a List<SlackChannel>. All methods throw SlackApiException when the API returns an error. postMessage automatically joins the channel on not_in_channel and retries.
You can also create an instance from stored credentials:
final slack = Slack.fromStore(); // returns null if not logged inLower-level HTTP client that returns raw Map<String, dynamic> responses. Use this when you need direct access to the full Slack API response.
final client = SlackApiClient(token: 'xoxp-...');
final json = await client.postMessage(channel: 'C0123ABCDEF', text: 'Hello!');
print(json['ts']);
client.close();Real-time event streaming over WebSocket using Slack's Socket Mode. Requires an app-level token (xapp-*).
import 'package:dart_slack/dart_slack.dart';
final client = SocketModeClient(appToken: 'xapp-...');
await client.connect();
client.events.listen((event) {
print('${event.channel}: <${event.user}> ${event.text}');
});
// Later...
await client.close();Events are automatically acknowledged. The client reconnects with exponential backoff on disconnect.
Runs the Slack OAuth 2.0 V2 authorization flow over a local HTTPS server.
final flow = OAuthFlow(
clientId: 'your-client-id',
clientSecret: 'your-client-secret',
logger: Logger(),
);
final credentials = await flow.execute();
print('Token: ${credentials.accessToken}');
print('Team: ${credentials.teamName}');Opens the user's browser, listens on https://localhost:8585/callback, and exchanges the authorization code for a user token. A self-signed TLS certificate is generated automatically in ~/.dart_slack/. CSRF protection is handled via the OAuth state parameter.
Persists OAuth credentials to ~/.dart_slack/credentials.json with 0600 file permissions.
final store = CredentialsStore();
// Save after login
store.save(credentials);
// Load later
final loaded = store.load(); // returns null if not logged in
// Check existence
if (store.hasCredentials) { ... }
// Remove on logout
store.delete();Data class holding the access token and workspace metadata.
| Field | Type | Description |
|---|---|---|
accessToken |
String |
OAuth user token (xoxp-...) |
teamId |
String |
Workspace ID |
teamName |
String |
Workspace name |
userId |
String? |
Authenticated user ID |
Supports fromJson / toJson for serialization.
Returned by Slack.postMessage.
| Field | Type | Description |
|---|---|---|
channel |
String |
Channel the message was posted to |
ts |
String |
Message timestamp (used for threading) |
text |
String |
Message text content |
Returned by Slack.listChannels.
| Field | Type | Description |
|---|---|---|
id |
String |
Channel identifier (e.g. C0123ABCDEF) |
name |
String |
Channel name without the # prefix |
isPrivate |
bool |
Whether this is a private channel |
- Dart SDK
^3.10.0(included with Flutter 3.41+) - A Slack app with the required OAuth scopes (see Slack App Setup)
- Go to https://api.slack.com/apps and create a new app From scratch.
- Under OAuth & Permissions, add these User Token Scopes:
channels:historychannels:readchannels:writechat:writegroups:readim:writeusers:read
- Under OAuth & Permissions > Redirect URLs, add:
https://localhost:8585/callback - Copy your Client ID and Client Secret from Basic Information.
- Create a
.envfile in the project root (see.env.example):Alternatively, set these as environment variables.SLACK_CLIENT_ID=<your-client-id> SLACK_CLIENT_SECRET=<your-client-secret>
- Under Socket Mode, toggle it on and generate an App-Level Token with the
connections:writescope. - Under Event Subscriptions, enable events and subscribe to
message.channels. - Add the token to your
.envfile:SLACK_APP_TOKEN=xapp-...
dart pub getAuthenticated commands resolve a token in this order:
~/.dart_slack/credentials.json, written bydart_slack login.- The
SLACK_TOKENenvironment variable — read from the process environment or a.envfile in the current directory, the same way the OAuth secrets (SLACK_CLIENT_ID, etc.) are resolved.
The environment fallback lets the CLI run non-interactively — in CI, containers, or agent workspaces — where a token is injected rather than obtained through an interactive login. A token from the credentials file always wins over the environment.
export SLACK_TOKEN=xoxp-… # or add SLACK_TOKEN=xoxp-… to .env
dart run bin/dart_slack.dart channels # no `login` step required# Authenticate
dart run bin/dart_slack.dart login
# List channels
dart run bin/dart_slack.dart channels
# Show channel details
dart run bin/dart_slack.dart info -c <channel-id>
# List channel members
dart run bin/dart_slack.dart members -c <channel-id>
# Show recent messages
dart run bin/dart_slack.dart history -c <channel-id> -l 20
# Show thread replies
dart run bin/dart_slack.dart thread -c <channel-id> --ts <thread_ts>
# Send a message
dart run bin/dart_slack.dart send -c <channel-id> -t "Hello from the CLI"
# Reply to a thread
dart run bin/dart_slack.dart reply -c <channel-id> -r <thread_ts> -t "Thread reply"
# Edit a message
dart run bin/dart_slack.dart edit -c <channel-id> --ts <message_ts> -t "Updated text"
# Delete a message
dart run bin/dart_slack.dart delete -c <channel-id> --ts <message_ts>
# Send a DM
dart run bin/dart_slack.dart dm -u <user-id> -t "Hey there"
# List workspace users
dart run bin/dart_slack.dart users
# Look up a user profile
dart run bin/dart_slack.dart whois -u <user-id>
# Watch a channel (poll-based, uses user token)
dart run bin/dart_slack.dart watch -c <channel-id> -i 5 -n 10
# Stream a channel in real time (Socket Mode, uses app-level token)
dart run bin/dart_slack.dart stream -c <channel-id>
# Log out
dart run bin/dart_slack.dart logoutdart testdart pub global activate coverage 1.15.0
dart test --coverage=coverage
dart pub global run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info
genhtml coverage/lcov.info -o coverage/
open coverage/index.html