<?xml version="1.0" encoding="utf-8"?><rss version="2.0"
    xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:wfw="http://wellformedweb.org/CommentAPI/"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:atom="http://www.w3.org/2005/Atom"
    xmlns:media="http://search.yahoo.com/mrss/"
    xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
    xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
>
<channel>
  <title>Srijan Choudhary, all posts tagged: gtd</title>
  <link>https://srijan.ch/feed/all/tag:gtd</link>
  <lastBuildDate>Fri, 27 Dec 2024 11:50:00 +0000</lastBuildDate>
  <image>
    <url>https://srijan.ch/assets/favicon/favicon-32x32.png</url>
    <title>Srijan Choudhary, all posts tagged: gtd</title>
    <link>https://srijan.ch/feed/all/tag:gtd</link>
  </image>
  <sy:updatePeriod>daily</sy:updatePeriod>
  <sy:updateFrequency>1</sy:updateFrequency>
  <generator>Kirby</generator>
  <atom:link href="https://srijan.ch/feed/all.xml/tag:gtd" rel="self" type="application/rss+xml" />
  <description>Srijan Choudhary&#039;s Articles and Notes Feed for tag: gtd</description>
  <item>
    <title>Capturing slack messages directly into Emacs orgmode inbox</title>
    <description><![CDATA[Learn how to seamlessly capture Slack messages into your Emacs Orgmode (GTD) inbox using a custom browser userscript.]]></description>
    <link>https://srijan.ch/capturing-slack-messages-directly-into-emacs-orgmode-inbox</link>
    <guid isPermaLink="false">tag:srijan.ch:/capturing-slack-messages-directly-into-emacs-orgmode-inbox</guid>
    <category><![CDATA[emacs]]></category>
    <category><![CDATA[orgmode]]></category>
    <category><![CDATA[slack]]></category>
    <category><![CDATA[gtd]]></category>
    <dc:creator>Srijan Choudhary</dc:creator>
    <pubDate>Fri, 27 Dec 2024 11:50:00 +0000</pubDate>
    <media:content url="https://srijan.ch/media/pages/blog/capturing-slack-messages-directly-into-emacs-orgmode-inbox/d0e1ffec00-1735275760/screenshot-2024-12-27-at-12.01.31am.png" medium="image" />
    <content:encoded><![CDATA[<figure data-ratio="auto">
    <img src="https://srijan.ch/media/pages/blog/capturing-slack-messages-directly-into-emacs-orgmode-inbox/d0e1ffec00-1735275760/screenshot-2024-12-27-at-12.01.31am.png" alt="Screenshot of a custom org capture button in Slack message popup">
  
    <figcaption class="text-center">
    Org capture button in Slack message popup  </figcaption>
  </figure>
<p>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.</p>
<p>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.</p>
<p>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 <a href="https://todoist.com/integrations/apps/slack">Slack Todoist integration</a> to save slack messages to Todoist, and <a href="https://srijan.ch/todoist-cloud-inbox-for-gtd-in-emacs-orgmode">pulling them from Todoist into my org Inbox</a>.</p>
<p>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:</p><figure>
  <video controls muted preload="auto"><source src="https://srijan.ch/media/pages/blog/capturing-slack-messages-directly-into-emacs-orgmode-inbox/4ee876ac11-1728494126/slack-to-org-demo.webm" type="video/webm"></video>    <figcaption>Demo video showing a custom slack button to trigger org capture with the selected message's contents and a link back to the message</figcaption>
  </figure>
<h2>Demo breakdown</h2>
<p>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.</p>
<h2>Setup and Implementation</h2>
<h3>Prerequisites</h3>
<ol>
<li>Slack running in a browser (instead of a desktop app)</li>
<li>Browser extention for userscripts (Tampermonkey, Violentmonkey, Greasemonkey, etc)</li>
<li>Emacs with orgmode installed</li>
<li>Org protocol setup</li>
</ol>
<p>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.</p>
<p>Update: I got a comment that using this in the Slack app is also possible, though I've not evaluated this yet. You can <a href="#komment_6503f91cf9943cf408e47743f863bc12">check this comment for details</a>.</p>
<h3>Setting up Org Protocol Capture</h3>
<p>Setting up org protocol capture involves two steps: configuring your OS to use Emacs to open <code>org-protocol://</code> links, and configuring Emacs to save the captured data as you want.</p>
<p>For OS setup, please check the guides for your OS here: <a href="https://orgmode.org/worg/org-contrib/org-protocol.html#orge00964c">https://orgmode.org/worg/org-contrib/org-protocol.html#orge00964c</a></p>
<p>On Emacs side, this is the minimal config required:</p>
<pre><code class="language-emacs-lisp">(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)</code></pre>
<p>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: <a href="https://protesilaos.com/codelog/2024-09-19-emacs-command-popup-frame-emacsclient/">https://protesilaos.com/codelog/2024-09-19-emacs-command-popup-frame-emacsclient/</a></p>
<p>To run emacsclient with the popup frame parameter, I use:</p>
<pre><code class="language-shell-session">emacsclient --create-frame -F \
    '((prot-window-popup-frame . t) (name . "org-protocol-capture") (width . 80))' \
    -- %u</code></pre>
<p>Emacsclient's args can be set in the desktop entry file (linux) or org-protocol.app file (OSX) when setting up org-protocol.</p>
<h3>The userscript</h3>
<p>For the userscript, I searched for an existing published userscript for Slack that <a href="https://greasyfork.org/en/scripts/500127-slack-quick-edit-button">adds a button</a>, then tweaked it a bit to configure the button according to my needs.</p>
<p>I've published the userscript here: <a href="https://greasyfork.org/en/scripts/521908-slack-org-protocol-capture">https://greasyfork.org/en/scripts/521908-slack-org-protocol-capture</a></p>
<p>From this, I learned about an interesting API called <a href="https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver">MutationObserver</a> that seems very useful for userscripts.</p>
<h2>Notes</h2>
<h3>Using emacs-slack</h3>
<p>Another simple approach for this can be to use the <a href="https://github.com/emacs-slack/emacs-slack">emacs-slack</a> package to directly use Slack from Emacs. I tried this, and it does not work very well for me because:</p>
<ol>
<li>My org limits Slack session authentication to 1 week, and authenticating in emacs-slack is a little cumbersome.</li>
<li>We also use Slack huddles, and it does not work well with emacs-slack.</li>
</ol>
<h3>Possible Improvements</h3>
<ol>
<li>Make org capture template configurable</li>
<li>Add tooltip to the button</li>
<li>Pass even more metadata like message timestamp, channel name, emojis, etc.</li>
<li>Maybe some keyboard shortcuts to trigger the capture?</li>
</ol>
<h3>Limitations / Drawbacks</h3>
<p>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.</p>
<p>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.</p>]]></content:encoded>
    <comments>https://srijan.ch/capturing-slack-messages-directly-into-emacs-orgmode-inbox#comments</comments>
    <slash:comments>20</slash:comments>
  </item><item>
    <title>2024-09-01-002</title>
    <description><![CDATA[My small #emacs #orgmode #gtd customization of the day: org-edna is a plugin that can be used to setup auto triggers (and blockers) when completing a task. org-gtd uses it to auto-forward the next TODO item in a project to NEXT when a task in the project is marked as DONE. The #orgedna trigger it uses is: relatives(forward-no-wrap todo-only 1 no-sort) todo!(NEXT). This works okay for me, but also …]]></description>
    <link>https://srijan.ch/notes/2024-09-01-002</link>
    <guid isPermaLink="false">tag:srijan.ch:/notes/2024-09-01-002</guid>
    <category><![CDATA[emacs]]></category>
    <category><![CDATA[orgmode]]></category>
    <category><![CDATA[gtd]]></category>
    <dc:creator>Srijan Choudhary</dc:creator>
    <pubDate>Sun, 01 Sep 2024 21:45:00 +0000</pubDate>
    <content:encoded><![CDATA[<p>My small <a href="https://srijan.ch/tags/emacs" class="p-category">#emacs</a> <a href="https://srijan.ch/tags/orgmode" class="p-category">#orgmode</a> <a href="https://srijan.ch/tags/gtd" class="p-category">#gtd</a> customization of the day:</p>
<p><a href="https://www.nongnu.org/org-edna-el/">org-edna</a> is a plugin that can be used to setup auto triggers (and blockers) when completing a task. <a href="https://github.com/Trevoke/org-gtd.el">org-gtd</a> uses it to auto-forward the next TODO item in a project to NEXT when a task in the project is marked as DONE. The #orgedna trigger it uses is: <code>relatives(forward-no-wrap todo-only 1 no-sort) todo!(NEXT)</code>.</p>
<p>This works okay for me, but also results in tickler tasks configured as repeated tasks to go to NEXT state instead of TODO state when they are completed. This results in them showing up in the org agenda even before they are due.</p>
<p>To fix this, I had to add this property to the top-level headings of the tickler file:</p>
<pre><code class="language-org">:PROPERTIES:
:TRIGGER: self todo!(TODO)
:END:</code></pre>
<p>This overrides the global triggers configured by org-gtd for these org subtrees.</p><p>Syndicated to:</p><ul><li><a href="https://bsky.app/profile/srijan4.bsky.social/post/3l35iccfebi2o">https://bsky.app/profile/srijan4.bsky.social/post/3l35iccfebi2o</a></li></ul>]]></content:encoded>
    <comments>https://srijan.ch/notes/2024-09-01-002#comments</comments>
    <slash:comments>5</slash:comments>
  </item><item>
    <title>Using Todoist as a cloud inbox for GTD in Emacs orgmode</title>
    <description><![CDATA[Using todoist as a cloud inbox for GTD in Emacs orgmode for better integration with services like Slack and Google Assistant]]></description>
    <link>https://srijan.ch/todoist-cloud-inbox-for-gtd-in-emacs-orgmode</link>
    <guid isPermaLink="false">tag:srijan.ch:/todoist-cloud-inbox-for-gtd-in-emacs-orgmode</guid>
    <category><![CDATA[emacs]]></category>
    <category><![CDATA[orgmode]]></category>
    <category><![CDATA[gtd]]></category>
    <dc:creator>Srijan Choudhary</dc:creator>
    <pubDate>Tue, 16 Jan 2024 12:10:00 +0000</pubDate>
    <media:content url="https://srijan.ch/media/pages/blog/todoist-cloud-inbox-for-gtd-in-emacs-orgmode/5e26d0c015-1705406577/austin-distel-guij0yszpig-unsplash.jpg" medium="image" />
    <content:encoded><![CDATA[<figure data-ratio="auto">
    <img src="https://srijan.ch/media/pages/blog/todoist-cloud-inbox-for-gtd-in-emacs-orgmode/5e26d0c015-1705406577/austin-distel-guij0yszpig-unsplash.jpg" alt="Person using phone and laptop">
  
    <figcaption class="text-center">
    Photo by <a href="https://unsplash.com/@austindistel">Austin Distel</a> on <a href="https://unsplash.com/">Unsplash</a>  </figcaption>
  </figure>
<p>I've been using <a href="https://www.gnu.org/software/emacs/">Emacs</a>' <a href="https://orgmode.org/">orgmode</a> as my <a href="https://gettingthingsdone.com/">GTD</a> system for the last several months. I migrated from <a href="https://todoist.com/">Todoist</a>, and one of the things I missed was integration with other services that make things easy to capture tasks into the inbox.</p>
<p>There are ways to <a href="https://srijan.ch/notes/2023-11-30-001">capture org data via email</a>, and this can be a good enough alternative, because most (though not all) services allow some kind of email forward to capture tasks. But, this depends on a complex email setup and would probably work on a single machine.</p>
<p>The main integrations/features I wanted to use were:</p>
<ol>
<li><a href="https://slack.com/">Slack</a>: Todoist has a native app for Slack using which any Slack message can be captured into Todoist as a task.</li>
<li><a href="https://todoist.com/help/articles/how-to-use-todoist-for-google-assistant-qD7srG0c">Google Assistant</a>: Todoist has integration with Google Assistant which can be used to capture tasks by talking to the google assistant.</li>
<li><a href="https://todoist.com/help/articles/task-quick-add-va4Lhpzz">Todoist quick entry</a> on mobile with date recognition: The Todoist apps have a more polished mobile capture system that can be triggered from a widget and can recognize dates using natural language entry.</li>
</ol>
<p>The workflow would look something like this:</p>
<figure><picture><source sizes="(min-width: 768px) 704px, calc(93.6vw - 45px)" srcset="https://srijan.ch/media/pages/blog/todoist-cloud-inbox-for-gtd-in-emacs-orgmode/3cf2fe7e71-1705405025/todoist-emacs-inbox-300x.avif 300w, https://srijan.ch/media/pages/blog/todoist-cloud-inbox-for-gtd-in-emacs-orgmode/3cf2fe7e71-1705405025/todoist-emacs-inbox-600x.avif 600w, https://srijan.ch/media/pages/blog/todoist-cloud-inbox-for-gtd-in-emacs-orgmode/3cf2fe7e71-1705405025/todoist-emacs-inbox-704x.avif 704w, https://srijan.ch/media/pages/blog/todoist-cloud-inbox-for-gtd-in-emacs-orgmode/3cf2fe7e71-1705405025/todoist-emacs-inbox-900x.avif 900w, https://srijan.ch/media/pages/blog/todoist-cloud-inbox-for-gtd-in-emacs-orgmode/3cf2fe7e71-1705405025/todoist-emacs-inbox-1200x.avif 1200w, https://srijan.ch/media/pages/blog/todoist-cloud-inbox-for-gtd-in-emacs-orgmode/3cf2fe7e71-1705405025/todoist-emacs-inbox-1800x.avif 1800w" type="image/avif"><source sizes="(min-width: 768px) 704px, calc(93.6vw - 45px)" srcset="https://srijan.ch/media/pages/blog/todoist-cloud-inbox-for-gtd-in-emacs-orgmode/3cf2fe7e71-1705405025/todoist-emacs-inbox-300x.webp 300w, https://srijan.ch/media/pages/blog/todoist-cloud-inbox-for-gtd-in-emacs-orgmode/3cf2fe7e71-1705405025/todoist-emacs-inbox-600x.webp 600w, https://srijan.ch/media/pages/blog/todoist-cloud-inbox-for-gtd-in-emacs-orgmode/3cf2fe7e71-1705405025/todoist-emacs-inbox-704x.webp 704w, https://srijan.ch/media/pages/blog/todoist-cloud-inbox-for-gtd-in-emacs-orgmode/3cf2fe7e71-1705405025/todoist-emacs-inbox-900x.webp 900w, https://srijan.ch/media/pages/blog/todoist-cloud-inbox-for-gtd-in-emacs-orgmode/3cf2fe7e71-1705405025/todoist-emacs-inbox-1200x.webp 1200w, https://srijan.ch/media/pages/blog/todoist-cloud-inbox-for-gtd-in-emacs-orgmode/3cf2fe7e71-1705405025/todoist-emacs-inbox-1800x.webp 1800w" type="image/webp"><img alt="" height="502" sizes="(min-width: 768px) 704px, calc(93.6vw - 45px)" src="https://srijan.ch/media/pages/blog/todoist-cloud-inbox-for-gtd-in-emacs-orgmode/3cf2fe7e71-1705405025/todoist-emacs-inbox-704x.png" srcset="https://srijan.ch/media/pages/blog/todoist-cloud-inbox-for-gtd-in-emacs-orgmode/3cf2fe7e71-1705405025/todoist-emacs-inbox-300x.png 300w, https://srijan.ch/media/pages/blog/todoist-cloud-inbox-for-gtd-in-emacs-orgmode/3cf2fe7e71-1705405025/todoist-emacs-inbox-600x.png 600w, https://srijan.ch/media/pages/blog/todoist-cloud-inbox-for-gtd-in-emacs-orgmode/3cf2fe7e71-1705405025/todoist-emacs-inbox-704x.png 704w, https://srijan.ch/media/pages/blog/todoist-cloud-inbox-for-gtd-in-emacs-orgmode/3cf2fe7e71-1705405025/todoist-emacs-inbox-900x.png 900w, https://srijan.ch/media/pages/blog/todoist-cloud-inbox-for-gtd-in-emacs-orgmode/3cf2fe7e71-1705405025/todoist-emacs-inbox-1200x.png 1200w, https://srijan.ch/media/pages/blog/todoist-cloud-inbox-for-gtd-in-emacs-orgmode/3cf2fe7e71-1705405025/todoist-emacs-inbox-1800x.png 1800w" title="" width="322"></picture></figure>
<p>I found an <a href="https://github.com/abrochard/emacs-todoist">existing Todoist integration for emacs</a>, but it's more suitable for using Todoist as the source of truth for tasks, and keeping a local buffer for operations on it in Emacs.</p>
<p>But, I was able to use it's functions to achieve what I wanted. Here's my elisp:</p>
<pre><code class="language-elisp">(use-package todoist)

(defun fetch-todoist-inbox ()
  (interactive)
  (let ((tasks (todoist--query "GET" "/tasks?project_id=&lt;project_id&gt;")))
    (mapcar (lambda (task)
              (todoist--insert-task task 1 t)
              (todoist--query
                "DELETE"
                (format "/tasks/%s" (todoist--task-id task))))
            tasks)))</code></pre>
<p>Here, the <code>project_id</code> is the Todoist project id of the project from which tasks have to be imported. This can be found by opening the project in the todoist web app - the project id is the last part of the URL.</p>
<p>The elisp function <code>fetch-todoist-inbox</code> can be called when in any org buffer (or any buffer actually). It will fetch all tasks in the specified project, insert then into the current buffer, and delete them from Todoist. It can be bound to any keybinding for easy access. Note that it requires setting the todoist token using elisp or an environment variable.</p>
<h2>Improvements Ideas</h2>
<ul>
<li>Show number of un-fetched items in status bar</li>
<li>Fetch comments and attachments</li>
<li>Fetch task labels and show as orgmode tags</li>
</ul>
<p><a class="p-category" href="https://srijan.ch/tags/gtd">#GTD</a> <a class="p-category" href="https://srijan.ch/tags/emacs">#Emacs</a> <a class="p-category" href="https://srijan.ch/tags/orgmode">#OrgMode</a></p>]]></content:encoded>
    <comments>https://srijan.ch/todoist-cloud-inbox-for-gtd-in-emacs-orgmode#comments</comments>
    <slash:comments>8</slash:comments>
  </item><item>
    <title>2023-11-30-001</title>
    <description><![CDATA[Found Samuel's nice post on capturing data for org via email. This is very close to what I was looking for to be able to do GTD capture on-the-go either from phone apps like Braintoss or from any email app. One addition I would like to make is handling attachments in the email by downloading them and attaching to the org entry. This would be useful for voice notes from Braintoss - it does …]]></description>
    <link>https://srijan.ch/notes/2023-11-30-001</link>
    <guid isPermaLink="false">tag:srijan.ch:/notes/2023-11-30-001</guid>
    <category><![CDATA[emacs]]></category>
    <category><![CDATA[gtd]]></category>
    <category><![CDATA[orgmode]]></category>
    <dc:creator>Srijan Choudhary</dc:creator>
    <pubDate>Thu, 30 Nov 2023 18:10:00 +0000</pubDate>
    <content:encoded><![CDATA[<p>Found Samuel's nice post on <a href="http://web.archive.org/web/20240101143355/https://samuelwflint.com/posts/2017/03/13/capturing-data-for-org-via-email/">capturing data for org via email</a>.</p>
<p>This is very close to what I was looking for to be able to do GTD capture on-the-go either from phone apps like <a href="https://braintoss.com/">Braintoss</a> or from any email app.</p>
<p>One addition I would like to make is handling attachments in the email by downloading them and attaching to the org entry.<br />
This would be useful for voice notes from Braintoss - it does transcription of the audio and adds it to the email body, but sometimes it doesn't work so well and I have to fall back to listening to the audio. It will also be useful for forwarded emails containing attachments.</p>
<p><a class="p-category" href="https://srijan.ch/tags/gtd">#GTD</a> <a class="p-category" href="https://srijan.ch/tags/emacs">#Emacs</a> <a class="p-category" href="https://srijan.ch/tags/orgmode">#OrgMode</a></p>]]></content:encoded>
    <comments>https://srijan.ch/notes/2023-11-30-001#comments</comments>
    <slash:comments>2</slash:comments>
  </item></channel>
</rss>
