Skip to content

xernot/SlackCLI

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SlackCLI

A terminal-based Slack client built with Python and curses. Browse channels, send messages, reply to threads, and manage multiple workspaces — all from your terminal.

┌─────────────────────────────────────────────────────────────────────┐
│ strg / #general    <<< 3 new messages >>>    (s) STRG  (c) CONTENT │
├──────────────┬──────────────────────────────────────────────────────┤
│  UNREAD      │  <<< wednesday - 2026.03.11 >>>                     │
│  > #general  │                                                     │
│    #random(2)│  alice [10:32]                                      │
│              │  hey, check out this fix                             │
│  STARRED     │  │ def process(data):                               │
│    #eng      │  │     return data.strip()                          │
│              │                                                     │
│  CHANNELS    │  bob [10:34]                                        │
│    #design   │  yeah, looks good. metrics are stable               │
│    #ops      │  │ alice: nice, thanks for checking!                │
│              │                                                     │
│  DMs         │  ─────────────────────────────────                  │
│    alice     │  > write a message...                               │
│    bob       │                                                     │
└──────────────┴──────────────────────────────────────────────────────┘

Features

  • Multi-workspace — Switch workspaces with first-letter shortcuts in the sidebar (e.g. s for STRG)
  • Real-time messages — Socket Mode (WebSocket) for instant delivery, with polling fallback
  • Threads — View and reply to threaded conversations
  • Code blocks — Triple-backtick code rendered with prefix in green; inline code highlighted in green
  • Search — Fuzzy search across channels and users with /
  • @mentions — Autocomplete popup when typing @
  • Group DMs — Create new group conversations with n
  • Unread tracking — Syncs read state with Slack servers; reads/writes in other clients are reflected in SlackCLI and vice versa
  • Organized sidebar — Channels grouped by: Unread, Starred, Channels, DMs, Groups
  • File attachments — Displays [image: name], [pdf: name], [file: name]
  • Emoji — Slack shortcodes (:smile:, :+1:) rendered as Unicode emoji
  • Reactions — Message reactions shown below each message; add your own with e
  • Live updates — Message edits and deletions reflected in real-time

Requirements

  • Python 3.10+
  • A terminal with curses support (Linux, macOS, WSL)
  • A Slack workspace you have access to

Installation

git clone https://github.com/xernot/SlackCLI.git
cd SlackCLI
python -m venv .venv
source .venv/bin/activate
pip install -e .

Slack App Setup

SlackCLI needs a Slack App to authenticate. You have two options:

Option A: User OAuth Token (quickest)

  1. Go to api.slack.com/apps and create a new app (or use an existing one)

  2. Under OAuth & Permissions, add these User Token Scopes:

    Scope Purpose
    channels:history Read channel messages
    channels:read List channels
    channels:write Mark channels as read
    chat:write Send messages
    groups:history Read private channel messages
    groups:read List private channels
    groups:write Mark private channels as read
    im:history Read direct messages
    im:read List direct messages
    im:write Mark DMs as read
    mpim:history Read group DMs
    mpim:read List group DMs
    mpim:write Mark group DMs as read
    reactions:read View emoji reactions
    reactions:write Add emoji reactions
    users:read List users
    stars:read List starred channels
  3. Install the app to your workspace

  4. Copy the User OAuth Token (xoxp-...) from the OAuth page

Option B: OAuth Flow (browser-based)

  1. Create a Slack App as above
  2. Under OAuth & Permissions, add the redirect URL: https://localhost:8338/callback
  3. Note your Client ID and Client Secret from Basic Information

Socket Mode (optional, recommended)

For real-time message delivery via WebSocket instead of polling:

  1. In your Slack App settings, go to Socket Mode and enable it
  2. Generate an App-Level Token with connections:write scope
  3. Under Event Subscriptions, subscribe to these bot events:
    • message.channels
    • message.groups
    • message.im
    • message.mpim
  4. Save the app token (xapp-...) — you'll need it during setup

Usage

First workspace

./slackcli.sh --add-workspace

You'll be prompted for:

  • Workspace name
  • Authentication method (paste token or OAuth flow)
  • App token for Socket Mode (optional)

Running

./slackcli.sh

Adding more workspaces

./slackcli.sh --add-workspace

Re-authenticating (legacy)

./slackcli.sh --reauth

Keybindings

The message pane uses vim-like normal/insert modes to separate shortcuts from text input.

Global

Key Action
Shift+Tab Switch pane (sidebar / messages)
Ctrl+C Quit (with confirmation)

Sidebar

Key Action
Up / Down Navigate channels
Enter Open channel
/ Search channels and users
n New group message
R Reload server stats / refresh unread counts
q Quit (with confirmation)
First letter Switch workspace (e.g. s for STRG, c for CONTENT-GARDEN)

Messages — Normal mode

Shortcuts are active. No text input.

Key Action
i Enter insert mode (start typing a message)
r Select message to reply to
e Select message to react to (opens emoji picker)
d Select message to delete
n New group message
/ Search channels and users
R Reload server stats / refresh unread counts
q Quit (with confirmation)
Up / Down Scroll messages / navigate selection
PgUp / PgDn Page scroll
Enter Confirm reply, react, or delete target

Messages — Insert mode

All keys go to the input buffer.

Key Action
Esc Return to normal mode (or cancel active sub-mode first)
Enter Send message (returns to normal mode)
@ Open mention autocomplete
Up / Down Scroll messages
PgUp / PgDn Page scroll

Search overlay

Key Action
Up / Down Navigate results
Enter Open selected result
Esc Close search

New group dialog

Key Action
Tab Switch from user selection to message
Backspace Remove selected user or delete character
Enter Confirm selection / send message
Esc Cancel

Configuration

All configuration is stored in ~/.slackcli/config.json:

{
  "workspaces": [
    {
      "name": "My Workspace",
      "token": "xoxp-...",
      "app_token": "xapp-...",
      "client_id": "...",
      "client_secret": "..."
    }
  ]
}

File locations

Path Purpose
~/.slackcli/config.json Workspace configuration
~/.slackcli/certs/ Self-signed certificates for OAuth redirect
~/.slackcli/error.log Error log

Architecture

src/slackcli/
├── __main__.py       # CLI entry point, workspace setup flows
├── app.py            # Main event loop, key handling, threading
├── config.py         # Config load/save, format migration
├── defaults.py       # All configurable constants (strings, timings, dimensions)
├── oauth.py          # Browser-based OAuth 2.0 flow
├── slack_client.py   # Slack API wrapper (REST + Socket Mode)
├── state.py          # AppState, WorkspaceData, thread-safe state
└── ui/
    ├── colors.py     # Terminal color pair definitions
    ├── layout.py     # Header, sidebar/message pane layout, borders
    ├── sidebar.py    # Channel list with sections and unread counts
    ├── messages.py   # Message rendering, threads, Slack markup
    ├── search.py     # Channel/user search overlay
    ├── mention.py    # @mention autocomplete popup
    ├── newgroup.py   # New group DM dialog
    ├── confirm.py    # Quit confirmation dialog
    ├── delete.py     # Delete message confirmation dialog
    ├── emoji_picker.py # Emoji reaction picker overlay
    └── overlay.py    # Shared overlay/border drawing utilities

Threading model

  • Main thread — UI rendering and keyboard input
  • Background threads — Workspace initialization, Socket Mode connections, DM sorting, thread reply fetching, unread sync, mark-as-read

Real-time events

When Socket Mode is available (app token provided), messages arrive instantly via WebSocket. Without it, SlackCLI falls back to polling every 5 seconds with round-robin channel rotation and rate-limit backoff.

Unread sync

SlackCLI syncs read state with Slack's servers so unread counts stay consistent across clients:

  • On startup — Fetches initial unread counts from the Slack API
  • On channel open — Calls conversations.mark to tell Slack you've read the channel
  • Own messages — Messages you send from other clients are not counted as unread
  • Periodic re-sync — Every 30 seconds, checks unread channels against the server to detect reads from other clients

Message rendering

Slack markup is converted for terminal display:

  • <@U123> becomes @username
  • <#C123|general> becomes #general
  • <https://example.com|label> becomes label
  • <!here>, <!channel>, <!everyone> render as-is
  • Bold, italic, and strikethrough markers are stripped
  • Code blocks (```) rendered with prefix in green, preserving whitespace
  • Inline code (`) rendered in green
  • Emoji shortcodes (:smile:) converted to Unicode (😄)
  • Reactions displayed as 👍 3 ❤️ 1 below messages

Troubleshooting

"No workspaces configured" — Run ./slackcli.sh --add-workspace to set up your first workspace.

Messages not appearing in real-time — You're likely in polling mode. Add an app token with Socket Mode enabled for instant delivery.

OAuth certificate warning in browser — The OAuth flow uses a self-signed certificate for localhost. Accept the warning to complete authentication.

Rate limiting — If polling mode hits Slack's rate limits, SlackCLI automatically backs off using the Retry-After header.

Errors — Check ~/.slackcli/error.log for detailed error information.

License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages