Capturing slack messages directly into Emacs orgmode inbox
Ever since switching to orgmode as my GTD system, I've been trying to (slowly) optimize my capture system for things coming to me from different places. One of the things that I was not satisfied with was capturing and processing inputs from Slack.
Slack messages can easily get lost in the fast-paced stream of conversations. Manually copying and pasting messages introduces too much friction, and also removes some context (backlinks), unless a link to the original message is also manually copied. There are ways to save messages in Slack itself, but it just makes it another Inbox to check, and I'm trying to reduce that.
I started by using the saved messages feature to save messages in a single place, and later either shifting them to my org inbox manually, or directly working on them and completing them. Then, I shifted to using the Slack Todoist integration to save slack messages to Todoist, and pulling them from Todoist into my org Inbox.
I've now found a better mechanism that allows me to seamlessly capture Slack message with it's context into orgmode. Here's a demo:
Demo breakdown
This method uses userscripts to add a custom button to the hover menu that comes up for any message in slack, and triggers org protocol capture with the message details when the button is clicked. The message details include the sender, message text, and a direct link back to the message. I've set up this protocol handler to ask me to enter the heading of the capured item, but it can be as easily set up to directly capture the message without user input.
Setup and Implementation
Prerequisites
- Slack running in a browser (instead of a desktop app)
- Browser extention for userscripts (Tampermonkey, Violentmonkey, Greasemonkey, etc)
- Emacs with orgmode installed
- Org protocol setup
I didn't find a good way to inject userscripts into the Slack destop app, so for now, this method requires using Slack in a browser. It also works when Slack is installed using the "Install Page as App" feature of the browser.
Setting up Org Protocol Capture
Setting up org protocol capture involves two steps: configuring your OS to use Emacs to open org-protocol://
links, and configuring Emacs to save the captured data as you want.
For OS setup, please check the guides for your OS here: https://orgmode.org/worg/org-contrib/org-protocol.html#orge00964c
On Emacs side, this is the minimal config required:
(server-start)
(setq-default org-agenda-files '("~/org"))
(setq-default my-org-inbox
(expand-file-name "inbox.org" "~/org"))
(setq-default org-capture-templates
'(
("i" "Inbox" entry (file my-org-inbox)
"* %?\n%i\n%U"
:kill-buffer t)
("l" "Inbox with link" entry (file my-org-inbox)
"* %?\n%i\n%a\n%U"
:kill-buffer t)))
(setq-default org-protocol-default-template-key "l")
(require 'org-protocol)
An optional enhancement that can be seen in the demo is: open a new emacs frame to capture this message, then close it automatically after the capture has been done. For this, I use the config snippet from prot's excellent post: https://protesilaos.com/codelog/2024-09-19-emacs-command-popup-frame-emacsclient/
To run emacsclient with the popup frame parameter, I use:
emacsclient --create-frame -F \
'((prot-window-popup-frame . t) (name . "org-protocol-capture") (width . 80))' \
-- %u
Emacsclient's args can be set in the desktop entry file (linux) or org-protocol.app file (OSX) when setting up org-protocol.
The userscript
For the userscript, I searched for an existing published userscript for Slack that adds a button, then tweaked it a bit to configure the button according to my needs.
I've published the userscript here: https://greasyfork.org/en/scripts/521908-slack-org-protocol-capture
From this, I learned about an interesting API called MutationObserver that seems very useful for userscripts.
Notes
Using emacs-slack
Another simple approach for this can be to use the emacs-slack package to directly use Slack from Emacs. I tried this, and it does not work very well for me because:
- My org limits Slack session authentication to 1 week, and authenticating in emacs-slack is a little cumbersome.
- We also use Slack huddles, and it does not work well with emacs-slack.
Possible Improvements
- Make org capture template configurable
- Add tooltip to the button
- Pass even more metadata like message timestamp, channel name, emojis, etc.
- Maybe some keyboard shortcuts to trigger the capture?
Limitations / Drawbacks
Since this is dependent on the HTML structure of the slack web app, it can be fragile and can break easily if there are changes in the app.
This userscript uses the MutationObserver API to observe DOM changes in the whole slack workspace. So, it has some impact on performance. However, I've been using this daily for the last several months and I have not noticed any issues.
Interactions
👍 8 likes
🔁 2 reposts
Bookmark: srijan.ch/capturing-slac...
When Slack's html changes, this will have to be updated.
Yes, I've mentioned this in the limitations section.
You can use free Zapier account for this as well.
Trigger: New Emoji on message (pick your emoji) Action: Dropbox (or Google Drive etc.) Append to text file
Thanks for the reminder. I tried this as well, but (I think) it does not work in private channel or private messages.