Taut is a premium, high-fidelity Slack client for GNU Emacs designed for power users who want an immersive, keyboard-driven Slack experience without missing a single thread or reaction.
Built on an asynchronous, thread-safe architecture, Taut features a Gnus-style live Slack Activity inbox dashboard, a collapsible sidebar, real-time WebSocket syncing (Socket Mode), and a dual-mode interactive thread discussion system.
- Multi-Pane Workspace Layout: Collapsible sidebar (Starred channels, joined Channels, active DMs, watched threads, hidden channels) on the left, main conversation buffer in the center, and interactive threads on the right.
- Dual-Mode Threads:
- Side-by-Side Right Pane (
RET): Opens a dedicated sidebar to discuss threads with full context, complete with active parent-message background highlighting in the main chat. - Inline Collapsible Accordion (
TAB): Toggle replies directly inside the main chat stream, beautifully rendered with tree-branch connectors (β,ββ,ββ).
- Side-by-Side Right Pane (
- Gnus-Style Unified Inbox ("Slack Activity"): Instantly tracks and lists unread DMs, direct @mentions, and thread replies with robust on-the-fly categorization filters.
- Robust Connection (Zero Deadlocks): All REST API requests are offloaded to system-native
curlprocesses, making Taut completely immune to Emacs's internal GUI/WebSocket network locks. - Secure Credentials Storage: Integration with Emacs's
auth-sourceallows loading Slack tokens securely from~/.authinfoor~/.authinfo.gpg.
To run Taut as yourself (loading your personal channels, DMs, stars, and posting as yourself), you must configure a custom Slack App on the Slack Developer Dashboard.
- Go to the Slack App Directory and click Create New App.
- Select From scratch, name your app (e.g.,
Taut-Emacs), and choose your workspace.
To read and post as your personal user, you must set User Token Scopes (NOT Bot Token Scopes):
- In the left sidebar under Features, click OAuth & Permissions.
- Scroll down to Scopes -> User Token Scopes.
- Add the following scopes (all 25 scopes shown in your configuration):
bookmarks:read(List bookmarks)bookmarks:write(Create, edit, and remove bookmarks)calls:read(View information about ongoing and past calls)calls:write(Start and manage calls in a workspace)channels:read(View basic information about public channels)channels:history(View messages and other content in public channels)channels:write(Create, archive, invite/kick members in public channels)channels:write.topic(Set/edit topic for public channels)emoji:read(Required to fetch and display custom workspace emojis)groups:read(View basic information about private channels)groups:history(View messages and other content in private channels)groups:write(Create, archive, invite/kick members in private channels/groups)groups:write.topic(Set/edit topic for private channels/groups)im:read(View basic information about direct messages)im:history(View messages and other content in direct messages)im:write(Start direct messages with people on your behalf)mpim:read(View basic information about group direct messages)mpim:history(View messages and other content in group direct messages)mpim:write(Start group direct messages with people on your behalf)reactions:read(View emoji reactions in channels and conversations)reactions:write(Add and edit emoji reactions on your behalf)stars:read(View your starred messages and files)stars:write(Add or remove stars for your user)users:read(View people in your workspace)chat:write(Send messages on your behalf)files:read(View files shared in channels and conversations)files:write(Upload, edit, and delete files on your behalf)pins:read(View pinned content in channels and conversations)pins:write(Add and remove pinned messages and files on your behalf)search:read.mpim(Search workspace content in group direct messages)
Socket Mode allows Taut to open a real-time secure WebSocket connection (wss://) with Slack to stream activity instantly.
- In the left sidebar under Settings, click Socket Mode and toggle Enable Socket Mode on.
- Slack will prompt you to create an App-Level Token. Name it (e.g.
taut-socket-mode) and click Generate. - Copy this token (it starts with
xapp-...). This token receives theconnections:writescope automatically.
This allows Slack to route live stream events over the WebSocket connection:
- In the left sidebar under Features, click Event Subscriptions and toggle Enable Events on.
- Under Subscribe to events on behalf of users, click Add Private Channel Event and add:
message.channelsmessage.groupsmessage.immessage.mpimreaction_addedreaction_removed
- Click Save Changes at the bottom of the page.
- Scroll back up the left sidebar and click Install App.
- Click Install to Workspace and authorize.
- Once completed, copy the User OAuth Token (starts with
xoxp-...).
Taut integrates with Emacs's native auth-source library so you don't have to hardcode plaintext tokens in your init.el.
Add the following lines to your ~/.authinfo or ~/.authinfo.gpg file:
machine api.slack.com login bot password xoxp-YOUR-USER-OAUTH-TOKEN
machine api.slack.com login app password xapp-YOUR-APP-LEVEL-TOKEN
Below is the recommended configuration using use-package and straight.el to load Taut directly from GitHub with standard keybindings, custom cache expiration, and automatic secure credential loading:
(use-package taut
:straight (taut :type git :host github :repo "bunnylushington/taut")
:demand t
:bind (("C-c t c" . taut-connect)
("C-c t i" . taut-inbox)
("C-c t s" . taut-sidebar)
("C-c t q" . taut-quit)
("C-c t r" . taut-reload))
:custom
(taut-cache-keep-days 180)
:config
(message "Taut Slack client module loaded successfully!"))If you prefer checking out the repository manually, you can use the :load-path option:
(use-package taut
:load-path "~/projects/taut"
:demand t
:bind (("C-c t c" . taut-connect)
("C-c t i" . taut-inbox)
("C-c t s" . taut-sidebar)
("C-c t q" . taut-quit)
("C-c t r" . taut-reload))
:custom
(taut-cache-keep-days 180)
:config
(message "Taut Slack client module loaded successfully!"))j: Jump to any channel, group, or DM with autocomplete fuzzy completions (taut-jump).?: Open the dynamic, context-aware Dispatcher control center (taut-dispatch).
| Binding | Description |
|---|---|
RET / Click |
Open the channel, DM, or watched thread under cursor |
TAB |
Toggle collapse / expand state of the section header under cursor |
i |
Switch directly to the Gnus-style Slack Activity (Inbox) buffer |
h |
Toggle the hidden status of the channel at point (moves to HIDDEN section) |
M |
Mark all messages in the channel at point as read |
g |
Force redraw and sync sidebar unreads and stars list |
q |
Bury the sidebar |
| Binding | Description |
|---|---|
RET / Click |
Switch directly to the corresponding channel, DM, or thread |
d / e |
Mark message as read / dismiss and archive from inbox |
M |
Mark the entire parent channel of this message as read |
a |
Show all activity in the feed (Reset filters) |
u |
Filter feed to show only unread items |
D |
Filter feed to show only Direct Messages (DMs) |
m |
Filter feed to show only direct @mentions |
t |
Filter feed to show only watched thread updates |
g |
Force reload and refresh the Inbox |
q |
Bury the Inbox dashboard |
| Binding | Description |
|---|---|
r |
Compose and send a new normal reply to the channel |
R |
Reply quoting the message under point |
e |
Edit the message under point (if sent by you) |
d |
Delete the message under point (if sent by you) |
a |
Add an emoji reaction to the message at point |
b / * |
Star/bookmark the message at point |
u |
Upload a file to the channel |
n / p |
Move cursor to the next / previous message |
v |
View native code block or attachment at point in its major mode |
c |
Copy code block or attachment at point to clipboard |
s |
Save file/attachment at point to disk |
TAB |
Toggle Inline Accordion expansion of thread replies |
RET / t |
Open Side-by-Side Thread Panel on the right |
M |
Mark all messages in this conversation as read |
g |
Force reload channel history from API |
q |
Bury conversation buffer |
| Binding | Description |
|---|---|
r |
Compose and send a reply to the active thread |
R |
Reply quoting the thread message under point |
e |
Edit the thread message under point (if sent by you) |
b / * |
Star/bookmark the thread message at point |
u |
Upload a file directly to the thread |
n / p |
Move cursor to the next / previous thread message |
v / c / s |
View (v), Copy (c), or Save (s) attachments/code in thread |
g |
Force refresh thread replies from API |
q |
Close and hide the side-by-side thread window |
To byte-compile the package cleanly and check for any warnings:
emacs -L . -batch -f batch-byte-compile *.elTaut compiles cleanly with zero warnings or errors.
Copyright (C) 2026 Bunny Lushington. Distributed under the MIT License.