Skip to content
kumar-waafPublic
forked from WAMF/slack_cli

About

Simple Slack cli

Resources

Stars

0 stars

Watchers

0 watching

Forks

 
 

Repository files navigation

dart_slack

style: very good analysis License: MIT

A Dart package and CLI for interacting with the Slack Web API.

Package API

Use dart_slack as a library in any Dart or Flutter app:

import 'package:dart_slack/dart_slack.dart';

Slack

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 in

SlackApiClient

Lower-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();

SocketModeClient

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.

OAuthFlow

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.

CredentialsStore

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();

Models

Credentials

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.

SlackMessage

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

SlackChannel

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

CLI

Prerequisites

  • Dart SDK ^3.10.0 (included with Flutter 3.41+)
  • A Slack app with the required OAuth scopes (see Slack App Setup)

Slack App Setup

  1. Go to https://api.slack.com/apps and create a new app From scratch.
  2. Under OAuth & Permissions, add these User Token Scopes:
    • channels:history
    • channels:read
    • channels:write
    • chat:write
    • groups:read
    • im:write
    • users:read
  3. Under OAuth & Permissions > Redirect URLs, add:
    https://localhost:8585/callback
    
  4. Copy your Client ID and Client Secret from Basic Information.
  5. Create a .env file in the project root (see .env.example):
    SLACK_CLIENT_ID=<your-client-id>
    SLACK_CLIENT_SECRET=<your-client-secret>
    
    Alternatively, set these as environment variables.

Socket Mode (optional, for stream command)

  1. Under Socket Mode, toggle it on and generate an App-Level Token with the connections:write scope.
  2. Under Event Subscriptions, enable events and subscribe to message.channels.
  3. Add the token to your .env file:
    SLACK_APP_TOKEN=xapp-...

Getting Started

dart pub get

Authentication

Authenticated commands resolve a token in this order:

  1. ~/.dart_slack/credentials.json, written by dart_slack login.
  2. The SLACK_TOKEN environment variable — read from the process environment or a .env file 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

Commands

# 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 logout

Running Tests

dart test

With coverage

dart 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

About

Simple Slack cli

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages