<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Myke's Blog</title>
    <link>https://myke.blog</link>
    <description>Personal blog about tech, general thoughts, and more</description>
    <language>en-us</language>
    <atom:link href="https://myke.blog/rss.xml" rel="self" type="application/rss+xml" />
    
      <item>
        <title>Managing a music collection with AI</title>
        <link>https://myke.blog/posts/claude-music-collection</link>
        <guid>https://myke.blog/posts/claude-music-collection</guid>
        <pubDate>Tue, 05 Aug 2025 24:00:00 GMT</pubDate>
        <description><![CDATA[&lt;p&gt;I started collecting music as soon as I found out about this new hot format called MP3 back in the 90s. Then I lost it all to streaming services - I probably still could recover it, but that would require going through old backups. And most of it was pirated anyway, which contradicts my current views on how things should work in the world (so does using Spotify, because artists get next to nothing). So I decided to rebuild my music collection officially buying it from sites like &lt;a href=&quot;https://bandcamp.com&quot;&gt;bandcamp&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Which brought up the question of organizing it all.&lt;/p&gt;
&lt;p&gt;But both back in the day and now the worst part about a music collection was keeping it well-structured, with pretty file and folder names, sorted correctly, album art and all. I used to have energy to edit metadata by hand (heck, I remember ripping my own CDs into MP3s). But I&#39;m too lazy for this shit now.&lt;/p&gt;
&lt;p&gt;Enter Claude Code (but you could do the same with gemini, opencode, claude desktop with some MCP, etc).&lt;/p&gt;
&lt;h1&gt;The Setup&lt;/h1&gt;
&lt;p&gt;I keep my music collection in &lt;code&gt;~/Sync/Music/&lt;/code&gt; with a strict directory structure: &lt;code&gt;Artist/YEAR - Album Title/&lt;/code&gt;. This folder automatically syncs using &lt;a href=&quot;https://syncthing.net/&quot;&gt;syncthing&lt;/a&gt; to my home server, from where I can stream it wherever I want. When on my computer I use &lt;a href=&quot;https://github.com/mierak/rmpc&quot;&gt;rmpc&lt;/a&gt; player to listen to it, because I&#39;m so badass that only a terminal player will satisfy me.&lt;/p&gt;
&lt;p&gt;When on the go I stream from a self-hosted &lt;a href=&quot;https://www.navidrome.org/&quot;&gt;Navidrome&lt;/a&gt;, but to be honest, I mostly listen to music while working.&lt;/p&gt;
&lt;p&gt;To maintain consistency, I created a &lt;code&gt;CLAUDE.md&lt;/code&gt; file in the music directory with organizational rules and import procedures (well, I actully told Claude what I want and it created the file for me, then I just edited it).&lt;/p&gt;
&lt;p&gt;Then I asked it to bring order and reorganize my collection, which took it about 10 minutes, including the time to look up albums and artists info online. For example I had an album where all tracks were sorted alphabetically, so I told it to order them according to the actual album. The result is a perfect folder structure of &lt;code&gt;ARTIST / YEAR - ALBUM&lt;/code&gt;, with album covers (although it did try to &lt;em&gt;generate&lt;/em&gt; album art instead of looking it up online at some point).&lt;/p&gt;
&lt;p&gt;Anyway, this is a very nice use of AI to handle a boring non-coding task. Some technical details:&lt;/p&gt;
&lt;h1&gt;The Import Process&lt;/h1&gt;
&lt;p&gt;When downloading a new album, I can run:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;claude &lt;span class=&quot;token parameter variable&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;import ~/Downloads/album.zip&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The CLAUDE.md file instructs Claude to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Extract the zip file&lt;/li&gt;
&lt;li&gt;Check if the metadata is correct and fix it if necessary&lt;/li&gt;
&lt;li&gt;Look up the release year&lt;/li&gt;
&lt;li&gt;Create the proper directory structure in my Music directory&lt;/li&gt;
&lt;li&gt;Move files to the organized location&lt;/li&gt;
&lt;li&gt;Update the MPD database, so that the new music immediately appears in the player&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Look how neat the import is:&lt;/p&gt;
&lt;img src=&quot;/media/claude-music-import.png&quot; alt=&quot;Screenshot of Claude Code ipmorting an album into the music library&quot;&gt;
&lt;p&gt;Here&#39;s the &lt;a href=&quot;/media/music_collection_claude.md&quot;&gt;CLAUDE.md&lt;/a&gt; file used in case you want to try it yourself.&lt;/p&gt;
]]></description>
        
        <category>GENERAL</category>
        
      </item>
    
      <item>
        <title>New Sanskrit Dictionary</title>
        <link>https://myke.blog/posts/new-sanskrit-dictionary</link>
        <guid>https://myke.blog/posts/new-sanskrit-dictionary</guid>
        <pubDate>Mon, 23 Dec 2024 24:00:00 GMT</pubDate>
        <description><![CDATA[&lt;p&gt;It is obvious that the hardest part (by far, far, very far) of the work was done a while ago, when the amazing people from the Cologne University in Germany digitized and published &lt;a href=&quot;https://www.sanskrit-lexicon.uni-koeln.de/&quot;&gt;Cologne Digital Sanskrit Dictionaries&lt;/a&gt;. They even made all the 36 or more dictionaries available online for anybody to use (and in different formats too).&lt;/p&gt;
&lt;p&gt;The only problem with the web interface they provided was that it is that the UI is a little... too academic for my taste. It also only searches in one dictionary at once, and only for exact matches.&lt;/p&gt;
&lt;p&gt;It was clear that improving the UI will give great advantages to researches and students, and there were several improvements I wanted:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Let the users type using IAST (Latin transcription) or Devanagari, because the program can tell the difference by itself&lt;/li&gt;
&lt;li&gt;Make it possible to search in any number of dictionaries at once&lt;/li&gt;
&lt;li&gt;Add fuzzy search (so that it was possible to find approximate matches and similar words)&lt;/li&gt;
&lt;li&gt;Add full-text search across the articles (not just the words), effectively creating the largest bi-directional dictionary out there&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, long story short, I finally made it happen and launched &lt;a href=&quot;https://sanskrit.myke.blog&quot;&gt;sanskrit.myke.blog&lt;/a&gt; with all of the above. I hope you&#39;ll enjoy using it!&lt;/p&gt;
&lt;h2&gt;Some technical stuff for the nerds&lt;/h2&gt;
&lt;p&gt;When creating the GUI version before I wrote a migrator that migrated all the articles into a SQLite database, which shipped with the dictionary. It seemed to make sense both in terms of performance and convenience of search. The resulting program is not slow, but it&#39;s not super fast either. I didn&#39;t like that.&lt;/p&gt;
&lt;p&gt;On this iteration I thought a bit more and there was a very obvious idea: you only need a database when you&#39;re going to be writing to it. That&#39;s not what a dictionary does, what it does is reading, so if I wanted to make it quick all I needed was a good data structure that sits in RAM waiting for reads.&lt;/p&gt;
&lt;p&gt;So as a result not only is the web version much quicker (minus the network transfer time), but it ended up being just a fraction of the original code base. And I know that there is additional performance improvement waiting by adding additional indexes, which I can do next time I have inspiration.&lt;/p&gt;
]]></description>
        
        <category>GENERAL</category>
        
      </item>
    
      <item>
        <title>Clojure interactive development 101</title>
        <link>https://myke.blog/posts/clojure-interactive-development-101</link>
        <guid>https://myke.blog/posts/clojure-interactive-development-101</guid>
        <pubDate>Sat, 31 Aug 2024 24:00:00 GMT</pubDate>
        <description><![CDATA[&lt;p&gt;The question was asked once again — so I&#39;m writing some code into REPL and seeing the results, but that&#39;s not very convenient. So I decided to write a small intro on how to do interactive development (a.k.a. REPL-driven development) conveniently.&lt;/p&gt;
&lt;p&gt;So, to get the elephant out of the room first: &lt;em&gt;we almost never need to type anything into REPL&lt;/em&gt;. The only exception are commands from &lt;code&gt;user.clj&lt;/code&gt; file, like &lt;code&gt;(start)&lt;/code&gt; or &lt;code&gt;(reload)&lt;/code&gt; — but that&#39;s a separate subject. But we never type anything like this into REPL:&lt;/p&gt;
&lt;pre class=&quot;language-clojure&quot;&gt;&lt;code class=&quot;language-clojure&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defn&lt;/span&gt; add-two &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;+&lt;/span&gt; n &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Moreover, we don&#39;t even type this into REPL:&lt;/p&gt;
&lt;pre class=&quot;language-clojure&quot;&gt;&lt;code class=&quot;language-clojure&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add-two&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So what do we do? The problem with talking about this is that by nature interactive development is difficult to explain without showing, so I guess I&#39;ll use some screenshots. I&#39;ll be using Emacs CIDER as my development environment, but the same can be achieved with VS Code and Calva, vim etc. I&#39;m not quite sure about Intellij IDEA, so can&#39;t help there.&lt;/p&gt;
&lt;p&gt;So let&#39;s start.&lt;/p&gt;
&lt;h1&gt;What is structural editing?&lt;/h1&gt;
&lt;p&gt;One more thing before we really start.&lt;/p&gt;
&lt;p&gt;The main difference of LISPs from &amp;quot;normal&amp;quot; languages is the infamous homoiconicity. The fact that the code is written using the languages own data structures (mostly lists). One of the conclusions from this fact is that there are very clear boundaries between each LISP expression, or s-expression (or s-exp). The brackets.&lt;/p&gt;
&lt;p&gt;There is a very practical effect from this fact. When you have something like this (let&#39;s pretend that &lt;code&gt;|&lt;/code&gt; is the cursor), your editor can easily know that it&#39;s standing right after the &lt;code&gt;(+ 2 3)&lt;/code&gt; s-exp, and inside the &lt;code&gt;(inc ...)&lt;/code&gt; s-exp.&lt;/p&gt;
&lt;pre class=&quot;language-clojure&quot;&gt;&lt;code class=&quot;language-clojure&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;inc&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;|&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&#39;s super trivial for the editor to figure this out. In Python you&#39;d need to count white-spaces to make sure of that, so it&#39;s a harder task. In any LISP it&#39;s trivial, just the position of the brackets counts.&lt;/p&gt;
&lt;p&gt;Ok, now starts the fun part.&lt;/p&gt;
&lt;h1&gt;Correct way to drive the REPL&lt;/h1&gt;
&lt;p&gt;So, as I said above we are not going to be typing into the REPL ever again (except for the commands from &lt;code&gt;user.clj&lt;/code&gt;). But we are still going to develop interactively.&lt;/p&gt;
&lt;p&gt;When we have an expression &lt;code&gt;(+ 2 3)&lt;/code&gt;, in CIDER we&#39;re going to put the cursor right after it:&lt;/p&gt;
&lt;pre class=&quot;language-clojure&quot;&gt;&lt;code class=&quot;language-clojure&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;|&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And run a command called &lt;code&gt;M-x cider-eval-last-sexp RET&lt;/code&gt; (in VS Code and Calva that would be &lt;code&gt;ctrl+alt+enter&lt;/code&gt; for &lt;code&gt;Evaluate to cursor&lt;/code&gt;), and here&#39;s what we&#39;ll get:&lt;/p&gt;
&lt;img src=&quot;/media/clojure-101/eval-sexp-01.png&quot;&gt;
&lt;p&gt;This is the most important part. The editor has sent the s-exp to REPL, retrieved the evaluation result and showed it to us right next to the s-exp. Congratulations, this is one third of everything you need to know to start developing interactively.&lt;/p&gt;
&lt;p&gt;So, we didn&#39;t type the expression into REPL, we evaluated the s-exp right from our source file. Big deal.&lt;/p&gt;
&lt;p&gt;So, let&#39;s look at a real debugging example (well, semi-real). Let&#39;s say we have a function:&lt;/p&gt;
&lt;pre class=&quot;language-clojure&quot;&gt;&lt;code class=&quot;language-clojure&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defn&lt;/span&gt; authorized? &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;handler&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;some-authrorization-logic&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&quot;You are authorized&quot;&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&quot;You are NOT authorized&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, this is a toy middleware function, that receives a request, runs it through some unknown to us authorization logic, and the returns a string, depending on the result. And this function is not working.&lt;/p&gt;
&lt;p&gt;In &amp;quot;normal&amp;quot; languages you would need a tool like Postman to debug this function, constantly reloading your app and running through middleware. But not Clojurians, we have interactive development. Let&#39;s use just the one trick we already learned — eval last s-exp.&lt;/p&gt;
&lt;p&gt;First of all, we want to capture a request, that&#39;s failing, so that we don&#39;t need to run Postman over and over again. That&#39;s quite easy, for example so:&lt;/p&gt;
&lt;pre class=&quot;language-clojure&quot;&gt;&lt;code class=&quot;language-clojure&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defn&lt;/span&gt; authorized? &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;handler&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; request request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;some-authrorization-logic&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&quot;You are authorized&quot;&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&quot;You are NOT authorized&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that def we have inserted, to define a global variable request. This is a powerful debug mechanism, but a better way to use it is a tool like &lt;a href=&quot;https://github.com/AbhinavOmprakash/snitch&quot;&gt;snitch&lt;/a&gt;. Anyway, we ran the request once and now we have the request in the current namespace. How do we check it?&lt;/p&gt;
&lt;p&gt;By putting the cursor right after the word &lt;code&gt;request&lt;/code&gt; and running the only command we have right now to eval the s-exp right before cursor (and the smallest s-exp is one word):&lt;/p&gt;
&lt;img src=&quot;/media/clojure-101/eval-request.png&quot;&gt;
&lt;p&gt;And we have our request, now we can isolate that piece that we&#39;re debugging by using the same command again, but now on the &lt;code&gt;(some-authrorization-logic request)&lt;/code&gt; s-exp:&lt;/p&gt;
&lt;img src=&quot;/media/clojure-101/eval-request-2.png&quot;&gt;
&lt;p&gt;Ah, something with method is not right. Let&#39;s experiment some more, same trick, but now we can simplify the argument by reducing request to a map with just one key, since we have a hunch that that&#39;s the only thing this function cares about:&lt;/p&gt;
&lt;img src=&quot;/media/clojure-101/eval-request-3.png&quot;&gt;
&lt;p&gt;Hm, delete didn&#39;t work either. Let&#39;s try POST:&lt;/p&gt;
&lt;img src=&quot;/media/clojure-101/eval-request-4.png&quot;&gt;
&lt;p&gt;Bingo, we have figured out what the problem in this most stupid example was using one trick from interactive development. We never restarted our app, we never had to do a second network request (very convenient when doing this right in production), and yet we have figured out what the problem was.&lt;/p&gt;
&lt;p&gt;And that&#39;s why it&#39;s called interactive development, and not REPL-driven development, cause try repeating that in a REPL.&lt;/p&gt;
&lt;h1&gt;Two more tricks&lt;/h1&gt;
&lt;p&gt;So, we have learned one trick — evaluating the expression before the cursor, but we need at least two more to be more or less fluent. I&#39;m not going to do all the screenshots, just tell you about them.&lt;/p&gt;
&lt;p&gt;By the way, while writing this I noticed that CIDER has at least 20 commands starting with &lt;code&gt;cider-eval-&lt;/code&gt;, I&#39;m using only four or five.&lt;/p&gt;
&lt;img src=&quot;/media/clojure-101/cider-eval-list.png&quot;&gt;
&lt;h2&gt;Evaluate the top-level form we are in&lt;/h2&gt;
&lt;p&gt;In CIDER this is done with &lt;code&gt;M-x cider-eval-defun-at-point RET&lt;/code&gt;, you can find the similar VS Code command and more examples and videos on the subject in the &lt;a href=&quot;https://calva.io/eval-tips&quot;&gt;eval tips&lt;/a&gt; article on Calva&#39;s website.&lt;/p&gt;
&lt;img src=&quot;/media/clojure-101/eval-defun.png&quot;&gt;
&lt;p&gt;As you can see, even though the cursor is standing somewhere inside the inner form, what gets evaluated is the entire function. This helps when you&#39;re changing some code and want to check the new definition without leaving the function.&lt;/p&gt;
&lt;h2&gt;Evaluate the entire file&lt;/h2&gt;
&lt;p&gt;Most obvious command — edit whatever, and then send the entire file to the REPL to update the running program&#39;s state. In CIDER &lt;code&gt;M-x cider-eval-buffer RET&lt;/code&gt;, in Calva something something that you can find by following the link above.&lt;/p&gt;
&lt;h1&gt;Summary&lt;/h1&gt;
&lt;p&gt;So, I hope that I managed to give you a glimpse of how convenient interactive development can be. We eval expressions that are deep within functions we work with with substituted params to quickly find and fix bugs (even in production, using nREPL).&lt;/p&gt;
&lt;p&gt;It&#39;s very important to say goodbye to the usual habit of living in the edit-compile-restart cycle and move to the Clojure&#39;s blissful cycle of starting the program once and then teaching it to do what you want.&lt;/p&gt;
&lt;h1&gt;Bonus tip&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/AbhinavOmprakash/snitch&quot;&gt;snitch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/tonsky/clj-reload&quot;&gt;clj-reload&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These two are actually a pair made in heaven. &lt;code&gt;snitch&lt;/code&gt; let&#39;s you instrument any variables that pass through a function with a simple one symbol substitution, so after &lt;code&gt;add-two&lt;/code&gt; is called at least once, &lt;code&gt;n&lt;/code&gt; will be available in the global scope:&lt;/p&gt;
&lt;pre class=&quot;language-clojure&quot;&gt;&lt;code class=&quot;language-clojure&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;;; note the asterix after defn&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;defn*&lt;/span&gt; add-two &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;+&lt;/span&gt; n &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add-two&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

n &lt;span class=&quot;token comment&quot;&gt;;; =&gt; 5&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And running &lt;code&gt;(reload)&lt;/code&gt; from &lt;code&gt;clj-reload&lt;/code&gt; will clean everything up and remove all the variables that got instrumented while playing with &lt;code&gt;snitch&lt;/code&gt;, making the namespaces clean again.&lt;/p&gt;
]]></description>
        
        <category>TECH</category>
        
      </item>
    
      <item>
        <title>Cold war times general Heitor Almendra on preventing a communist coup in Portugal</title>
        <link>https://myke.blog/posts/interview-general-almendra</link>
        <guid>https://myke.blog/posts/interview-general-almendra</guid>
        <pubDate>Wed, 08 May 2024 24:00:00 GMT</pubDate>
        <description><![CDATA[&lt;p&gt;At the time of the interview veteran General Heitor Hamilton Almendra was 92 years old, but you could never tell it by his lively spirit and vivid memory. It was a rare honor to be able to bring some of his stories to a broader audience.&lt;/p&gt;
]]></description>
        
        <category>VIDEO</category>
        
      </item>
    
      <item>
        <title>Useful Idiots: Lars von Trier</title>
        <link>https://myke.blog/posts/useful-idiot-lars-von-trier</link>
        <guid>https://myke.blog/posts/useful-idiot-lars-von-trier</guid>
        <pubDate>Wed, 23 Aug 2023 24:00:00 GMT</pubDate>
        <description><![CDATA[&lt;p&gt;So today we look at an &lt;a href=&quot;https://www.instagram.com/p/CwQF70VMWS3/&quot;&gt;instagram post&lt;/a&gt; by renowned Danish director Lars von Trier:&lt;/p&gt;
&lt;img src=&quot;/media/lars-post.png&quot; alt=&quot;Lars von Trier instagram post saying To Mr. Zelenskyj and Mr. Putin, and not least Mrs. Frederiksen (who yesterday, like someone head over heels in love, posed in the cockpit of one of the scariest killing machines of our time, grinning from ear to ear): RUSSIAN LIVES MATTER ALSO!&quot;&gt;
&lt;p&gt;The post reads:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;By the way:
To Mr. Zelenskyj and Mr. Putin, and not least Mrs. Frederiksen (who yesterday, like someone head over heels in love, posed in the cockpit of one of the scariest killing machines of our time, grinning from ear to ear):&lt;/p&gt;
&lt;p&gt;“RUSSIAN LIVES MATTER ALSO!”&lt;/p&gt;
&lt;p&gt;Best regards Lars&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Interesting point Mr. von Trier. So when Russians bomb our cities we shouldn&#39;t defend ourselves because we should care about Russian lives.&lt;/p&gt;
&lt;p&gt;What about an extremely simple way of protecting Russian lives: getting out of Ukraine?&lt;/p&gt;
&lt;p&gt;It&#39;s not the victim&#39;s fault that the attacker got injured while attacking. It&#39;s the victim&#39;s &lt;em&gt;achievement&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;So if you want to protect Russian lives then help us stop the war, not put your influence behind their aggression.&lt;/p&gt;
]]></description>
        
        <category>GENERAL</category>
        
      </item>
    
      <item>
        <title>On Russian Military Traditions</title>
        <link>https://myke.blog/posts/war-crimes</link>
        <guid>https://myke.blog/posts/war-crimes</guid>
        <pubDate>Mon, 10 Jul 2023 24:00:00 GMT</pubDate>
        <description><![CDATA[&lt;p&gt;Mastodon user @kravietz@agora.echelon.pt wrote a small &lt;a href=&quot;https://agora.echelon.pl/objects/5ee2533d-a0be-4e30-b797-5546341dd5d9&quot;&gt;post&lt;/a&gt; on how the Russian army behaved during the Afghan war of 1979-89 quoting soldier memoirs&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;, noting that nothing has changed in their behavior and they still act the same today:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In the village one of the sergeants remarked, without hiding his emotion, that &#39;the young women are good&#39;. The sergeant&#39;s words set all the others on fire like a spark, and then he threw off his overcoat and moved on one of the women: — Row, lads! In front of the aksakals and the children, our internationalists had their way with the women. The rape went on for two hours. The children huddled in a corner, screaming and shrieking, trying to help their mothers somehow. The old men, trembling, prayed to their God for mercy and salvation. Then the sergeant commanded, &amp;quot;Fire!&amp;quot; - and was the first to shoot the woman he had just raped. Quickly they finished off all the others as well. Then they poured fuel from the tank of the infantry fighting vehicle, poured it all over the dead bodies, covered them with some clothes, rags and even the scanty wooden furniture and set them on fire. The flames flared up inside the adobe...&amp;quot;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There is no surprise for me in nothing changing in thirty short years because nothing changed for hundreds of years. Let&#39;s compare the very fresh quote above with this quote from the pillar of Russian literature Leo Tolstoy&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; describing the war of the mid-nineteenth century:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The aoul&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt; which had been destroyed was that in which Haji Murad had spent the night before he went over to the Russians. Sado and his family had left the aoul on the approach of the Russian detachment, and when he returned he found his saklya&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn4&quot; id=&quot;fnref4&quot;&gt;[4]&lt;/a&gt;&lt;/sup&gt; in ruins -- the roof fallen in, the door and the posts supporting the penthouse burned, and the interior filthy. His son, the handsome bright-eyed boy who had gazed with such ecstasy at Haji Murad, was brought dead to the mosque on a horse covered with a barka; he had been stabbed in the back with a bayonet. The dignified woman who had served Haji Murad when he was at the house now stood over her son&#39;s body, her smock torn in front, her withered old breasts exposed, her hair down, and she dug her hails into her face till it bled, and wailed incessantly. Sado, taking a pick-ax and spade, had gone with his relatives to dig a grave for his son. The old grandfather sat by the wall of the ruined saklya cutting a stick and gazing stolidly in front of him. He had only just returned from the apiary. The two stacks of hay there had been burnt, the apricot and cherry trees he had planted and reared were broken and scorched, and worse still all the beehives and bees had been burnt. The wailing of the women and the little children, who cried with their mothers, mingled with the lowing of the hungry cattle for whom there was no food. The bigger children, instead of playing, followed their elders with frightened eyes. The fountain was polluted, evidently on purpose, so that the water could not be used. The mosque was polluted in the same way, and the Mullah and his assistants were cleaning it out. No one spoke of hatred of the Russians. The feeling experienced by all the Chechens, from the youngest to the oldest, was stronger than hate. It was not hatred, for they did not regard those Russian dogs as human beings, but it was such repulsion, disgust, and perplexity at the senseless cruelty of these creatures, that the desire to exterminate them -- like the desire to exterminate rats, poisonous spiders, or wolves -- was as natural an instinct as that of self-preservation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Russians are right when they are claiming that they are a country of ancient traditions. I&#39;m quite sure we could trace this kind of tradition even further back in time, maybe all the way to the Golden Horde.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot;&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://afghan-war-soldiers.ru/&quot;&gt;Soldiers of Afghan War (Russian Language)&lt;/a&gt; &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://mthoyibi.files.wordpress.com/2011/03/hadji-murad_leo-tolstoy.pdf&quot;&gt;&lt;em&gt;Haji Murad&lt;/em&gt;&lt;/a&gt; by Leo Tolstoy, Chapter XVII &lt;a href=&quot;#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;village &lt;a href=&quot;#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;house &lt;a href=&quot;#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
]]></description>
        
        <category>GENERAL</category>
        
      </item>
    
      <item>
        <title>On Small Propaganda Tricks</title>
        <link>https://myke.blog/posts/propaganda-tricks-1</link>
        <guid>https://myke.blog/posts/propaganda-tricks-1</guid>
        <pubDate>Fri, 07 Jul 2023 24:00:00 GMT</pubDate>
        <description><![CDATA[&lt;h2&gt;The Inspiration&lt;/h2&gt;
&lt;p&gt;I had a short &lt;a href=&quot;https://fosstodon.org/@yogthos@lemmy.ml/110672976582947303&quot;&gt;discussion&lt;/a&gt; on Mastodon today that started with this post:&lt;/p&gt;
&lt;img src=&quot;/media/yogthos-toot.png&quot; alt=&quot;@yogthos toot saying: Canadian ‘aid’ program set the table for post-Maidan coup land privatization drive&quot;&gt;
&lt;p&gt;Since this was a stone thrown at Ukraine I had to participate.&lt;/p&gt;
&lt;p&gt;But this blog post and this blog is not about Ukraine but about thinking, so let&#39;s look at this at a slightly different angle, which does not require us to take sides in the immediate discussion about Ukraine, Canadian aid or land ownership, but rather explains a trick that is used by propagandists all over the world so much, that it&#39;s probably one of the oldest and most used in the book. It&#39;s also one of the most effective.&lt;/p&gt;
&lt;p&gt;If you read the post again and ask yourself: what is this about? The answer is obvious: it&#39;s about the impact of some Canadian aid program on land privatization in Ukraine. Personally, I have no idea what aid program he&#39;s referring to. But that&#39;s not the point. And it&#39;s also not the point of this &amp;quot;toot&amp;quot; (as they call posts on Mastodon).&lt;/p&gt;
&lt;h2&gt;The Distraction&lt;/h2&gt;
&lt;p&gt;You see, the reference to the Canadian aid program is a distraction. As any illusionist would tell you, in order to pull off a trick you need to distract viewers attention to a place where nothing is actually happening, while you do your thing in another place altogether.&lt;/p&gt;
&lt;p&gt;Frankly, most people don&#39;t care about the Canadian aid to Ukraine and even it&#39;s impact on Ukrainian land ownership. But even if they do, they&#39;ll either agree or disagree with it, and that would mean they got distracted.&lt;/p&gt;
&lt;h2&gt;The Trick&lt;/h2&gt;
&lt;p&gt;The real trick that the author wants you to just not pay attention to, and therefore accept without critical evaluation, is in the word &lt;em&gt;&lt;strong&gt;coup&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;You see, we don&#39;t call a positive political event a coup.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;coup&lt;/strong&gt; a sudden decisive exercise of force in politics and especially the violent overthrow or alteration of an existing government by a small group (&lt;a href=&quot;https://www.merriam-webster.com/dictionary/coup&quot;&gt;Merriam-Webster&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sudden&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;, decisive, violent overthrow by a small group of people&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;. Also violent, apparently. There is also the emotional attitude that the word carries. A coup is something planned behind closed doors and executed by violent people in palaces. It&#39;s something that happens in countries you wouldn&#39;t want to visit even in the best of days.&lt;/p&gt;
&lt;p&gt;So while the poster distracts your attention by seemingly talking about Canandian aid, he is in fact smuggling a very emotionally charged and negative description to the events in Ukraine into your mind. With a single four-letter word. Not bad.&lt;/p&gt;
&lt;p&gt;Now, you have the full right to agree or disagree with his description, but if you want to be thinking critically you need to &lt;em&gt;notice&lt;/em&gt; it and ask yourself: wait a moment, do I actually agree that it was a coup and not a revolution, a peaceful protest, a democratic protest, an act of direct democracy by the people?&lt;/p&gt;
&lt;p&gt;Maybe you&#39;ll need to do some reading, maybe you&#39;re just not interested. But if you noticed it - you didn&#39;t get tricked.&lt;/p&gt;
&lt;p&gt;As I said before this trick is extremely effective and used a lot both in print and during speeches and debates. Now you know about it.&lt;/p&gt;
&lt;h2&gt;UPDATE&lt;/h2&gt;
&lt;p&gt;After I published this post and got some comments on it, I have managed to find an even better example of the same trick by the same poster.&lt;/p&gt;
&lt;img src=&quot;/media/alleged.png&quot; alt=&quot;lemmy post by @yogthos US media covers up Israeli war crimes in Jenin&quot;&gt;
&lt;p&gt;This example is even better than the first one, so I had to update the post. Look what&#39;s going on here:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;There is a clear double standard between the media hysteria over alleged Russian atrocities in Ukraine and the silence over the rampages by Israeli troops and settlers on the occupied West Bank.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Take a moment yourself and try to point out, where is the distraction and where is the trick?&lt;/p&gt;
&lt;p&gt;So the distraction is the whole part about media having double standards, and the trick, as always is in details. You see, while you&#39;re thinking about Israel and your position on what&#39;s going on there the poster is smuggling two very charged words: &lt;strong&gt;hysteria&lt;/strong&gt; and &lt;strong&gt;alleged&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Neat, ha? If this wasn&#39;t propaganda I would almost admire the cunning and elegance. So the media reaction to the largest war since WW2 with literally thousands over thousands of documented war crimes is called &amp;quot;hysteria&amp;quot; and the crimes themselves are &amp;quot;alleged&amp;quot;, unproven, maybe non-existent.&lt;/p&gt;
&lt;p&gt;As I said before, your opinion on the subject is your business. But for the sake of critical thinking you have to notice these words being smuggled while you&#39;re distracted.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot;&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Euromaidan lasted 3 months and 1 day. Does this count as sudden? &lt;a href=&quot;https://en.wikipedia.org/wiki/Euromaidan&quot;&gt;Wiki&lt;/a&gt; &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Does this group of people seem small and violent? Five hundered thousand Ukrainians singing national anthem during the 2013 revolution &lt;a href=&quot;https://www.youtube.com/watch?v=RTHpSnrKEeA&quot;&gt;YouTube&lt;/a&gt; &lt;a href=&quot;#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
]]></description>
        
        <category>GENERAL</category>
        
      </item>
    
      <item>
        <title>Instant offline emails on Mac with goimapnotify, mbsync and mu</title>
        <link>https://myke.blog/posts/push-offline-emails-mbsync</link>
        <guid>https://myke.blog/posts/push-offline-emails-mbsync</guid>
        <pubDate>Tue, 04 Jul 2023 24:00:00 GMT</pubDate>
        <description><![CDATA[&lt;h1&gt;Intro&lt;/h1&gt;
&lt;p&gt;I have spent a few hours today making sure that my emails get delivered to my offline inbox as soon as they appear on the server, and that this happens for each of my email accounts.&lt;/p&gt;
&lt;h2&gt;Tools&lt;/h2&gt;
&lt;p&gt;I assume that you already have your favorite offline email management tool (mu, notmuch etc.) set up and your emails are synced with something like mbsync (isync). So you&#39;ve got the basics covered and are ready for the advanced stuff.&lt;/p&gt;
&lt;p&gt;If you&#39;re not there yet, here are a couple of great articles to help you get started in different ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://macowners.club/posts/email-emacs-mu4e-macos/&quot;&gt;Email setup in Emacs with Mu4e on macOS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://michal.sapka.me/2023/notmuch/&quot;&gt;Managing email with notmuch and Emacs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Mailboxes&lt;/h2&gt;
&lt;p&gt;For the sake of this tutorial let&#39;s assume that you have a &lt;code&gt;.mbsyncrc&lt;/code&gt; file with two mailboxes set up: work and private. This means that you can get all mail from the server using &lt;code&gt;mbsync -a&lt;/code&gt; or selectively sync just work or private with &lt;code&gt;mbsync work&lt;/code&gt; and &lt;code&gt;mbsync private&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;At the moment you either start the sync manually, or more probably have something like a homebrew service for isync running and checking for emails every few minutes.&lt;/p&gt;
&lt;p&gt;We&#39;re going to make this experience as seamless as it is on the smartphones with new emails appearing in your inbox as soon as they hit the server.&lt;/p&gt;
&lt;h2&gt;Setup&lt;/h2&gt;
&lt;p&gt;First let&#39;s install &lt;a href=&quot;https://gitlab.com/shackra/goimapnotify&quot;&gt;goimapnotify&lt;/a&gt;. It&#39;s not available on brew and will require golang to be installed so:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;brew install golang&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;go install gitlab.com/shackra/goimapnotify@latest&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Add the target folder for go installs to &lt;code&gt;PATH&lt;/code&gt;, normally its &lt;code&gt;~/go/bin&lt;/code&gt;, so add this to &lt;code&gt;.zshrc&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;&lt;span class=&quot;token environment constant&quot;&gt;PATH&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token environment constant&quot;&gt;$HOME&lt;/span&gt;/go/bin:&lt;span class=&quot;token environment constant&quot;&gt;$PATH&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ok, the easy part is over. Now let&#39;s make config files.&lt;/p&gt;
&lt;h2&gt;Configuration&lt;/h2&gt;
&lt;p&gt;For some unknown reason &lt;code&gt;goimapnotify&lt;/code&gt; thinks that it&#39;s config files should have a &lt;code&gt;.conf&lt;/code&gt; extension, even though the content is simple json. We will not follow this strange pattern, and will create two json config files &lt;code&gt;work.json&lt;/code&gt; and &lt;code&gt;private.json&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let&#39;s assume that your work email is on Gmail, and your private is on Protonmail (as it should be, preferably with a custom domain name, so that you could leave for another provider if you wish).&lt;/p&gt;
&lt;h3&gt;work.json&lt;/h3&gt;
&lt;p&gt;The simplest version of &lt;code&gt;work.json&lt;/code&gt; for gmail would look like this:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;host&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;imap.gmail.com&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;port&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;993&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;tls&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;username&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &quot;your.work.email@gmail.com`&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;password&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;YOUR_PASSWORD&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;onNewMail&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;mbsync work&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;onNewMailPost&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;mu index --lazy-check&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;boxes&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;INBOX&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;wait&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this file we instruct &lt;code&gt;goimapnotify&lt;/code&gt; to connect to our work Gmail inbox and wait for new messages. As soon as a new message hits, we &lt;code&gt;wait&lt;/code&gt; 1 second and then run the &lt;code&gt;onNewMail&lt;/code&gt; command &lt;code&gt;mbsync work&lt;/code&gt;. This does the normal run of downloading new messages.&lt;/p&gt;
&lt;p&gt;Once this is done we run a &lt;code&gt;onNewMailPost&lt;/code&gt; command to index new emails.&lt;/p&gt;
&lt;p&gt;If you want this to be more secure, you can substitute getting your password with a command like &lt;code&gt;pass&lt;/code&gt; or &lt;code&gt;op&lt;/code&gt; (1Password CLI):&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;host&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;imap.gmail.com&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;port&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;993&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;tls&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;username&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &quot;your.work.email@gmail.com`&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;passwordCmd&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;pass email/work&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// [!code focus]&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;onNewMail&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;mbsync work&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;onNewMailPost&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;mu index --lazy-check&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;boxes&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;INBOX&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;wait&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Instead of password we provide a &lt;code&gt;passwordCmd&lt;/code&gt; to get the password from &lt;a href=&quot;https://www.passwordstore.org/&quot;&gt;pass&lt;/a&gt;. We can also do the same for the username, substituting &lt;code&gt;username&lt;/code&gt; with &lt;code&gt;usernameCmd&lt;/code&gt; and even with the &lt;code&gt;host&lt;/code&gt; to &lt;code&gt;hostCmd&lt;/code&gt;. For the most paranoid.&lt;/p&gt;
&lt;h3&gt;private.json&lt;/h3&gt;
&lt;p&gt;With Protonmail you would need to set up a &lt;a href=&quot;https://proton.me/mail/bridge&quot;&gt;Protonmail Bridge&lt;/a&gt;, so the config would look like this:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;host&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;127.0.0.1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;port&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1143&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;tls&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;username&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;your.private.email@proton.me&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;passwordCmd&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;pass email/private&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;onNewMail&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;mbsync private&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;onNewMailPost&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;mu index --lazy-check&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;boxes&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;INBOX&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;wait&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, now you&#39;re ready to test it out. Put these two config files anywhere, for example into &lt;code&gt;~/.config/goimapnotify/&lt;/code&gt; and test out your Work email integration with:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;goimapnotify &lt;span class=&quot;token parameter variable&quot;&gt;-conf&lt;/span&gt; ~/.config/goimapnotify/work.json &lt;span class=&quot;token parameter variable&quot;&gt;-debug&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;-debug&lt;/code&gt; would make sure you get enough log output to understand that everything works.&lt;/p&gt;
&lt;p&gt;Now all you need to do is send an email to your work email and watch the logs. If everything works fine, after the email appears in your Gmail inbox you should get a log message, and then &lt;code&gt;mbsync&lt;/code&gt; and the &lt;code&gt;mu&lt;/code&gt; will kick in, and email should be readily available in your offline email client of choice.&lt;/p&gt;
&lt;h2&gt;Launch as Startup&lt;/h2&gt;
&lt;p&gt;If everything works you&#39;re ready for the last step - make all of this launch at startup. On MacOS we need to use &lt;code&gt;launchd&lt;/code&gt; to run things at startup, and getting those pesky plist files is always a hassle. So in case you need to debug use something nice like &lt;a href=&quot;https://soma-zone.com/LaunchControl/&quot;&gt;LaunchControl&lt;/a&gt;, I used the free version. There is also a very neat online plist generator &lt;a href=&quot;https://launched.zerowidth.com/&quot;&gt;launched.&lt;/a&gt;, I haven&#39;t used it but it can definitely come in handy.&lt;/p&gt;
&lt;p&gt;For work create a file called &lt;code&gt;com.example.workemail.plist&lt;/code&gt; and put it to &lt;code&gt;~/Library/LaunchAgents&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token prolog&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;/span&gt;
&lt;span class=&quot;token doctype&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;!&lt;/span&gt;&lt;span class=&quot;token doctype-tag&quot;&gt;DOCTYPE&lt;/span&gt; &lt;span class=&quot;token name&quot;&gt;plist&lt;/span&gt; &lt;span class=&quot;token name&quot;&gt;PUBLIC&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-//Apple//DTD PLIST 1.0//EN&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;plist&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;1.0&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dict&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Label&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;com.example.workemail.plist&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;ProgramArguments&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
         &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;/Users/USERNAME/go/bin/goimapnotify&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
         &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;-conf&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
         &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;/Users/USERNAME/.config/goimapnotify/work.json&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;KeepAlive&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;RunAtLoad&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;true&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;StandardErrorPath&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;/Users/USERNAME/Library/Logs/CheckMailBlaster.err&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;StandardOutPath&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;/Users/USERNAME/Library/Logs/CheckMailBlaster.log&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;EnvironmentVariables&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dict&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
           &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;PATH&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
           &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/homebrew/bin&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dict&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dict&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;plist&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Replace &lt;code&gt;USERNAME&lt;/code&gt; with your user name.&lt;/p&gt;
&lt;p&gt;The most tricky part that took a good hour to debug was figuring out that you need to provide the &lt;code&gt;PATH&lt;/code&gt; variable to the running process, as it doesn&#39;t have access to the system wide one. Until I did, &lt;code&gt;goimapnotify&lt;/code&gt; would start and connect normally, and once the new email hit I got an error on the &lt;code&gt;mbsync&lt;/code&gt; step.&lt;/p&gt;
&lt;p&gt;So, as I said this simple file took two hours of debugging, so say thank you and create similar file for private email like &lt;code&gt;com.example.privateemail.plist&lt;/code&gt; in the same directory.&lt;/p&gt;
&lt;p&gt;Now all that&#39;s left is launch:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;launchctl load ~/Library/LaunchAgents/com.example.workemail.plist
launchctl load ~/Library/LaunchAgents/com.example.privateemail.plist&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Make sure that they&#39;re running with&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;launchctl list &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; com.example&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or better yet use &lt;code&gt;LaunchControl&lt;/code&gt; to monitor their status. If everything worked you should get the services started as soon as you log in, and the mail will appear in your inbox instantly.&lt;/p&gt;
&lt;p&gt;Please note, that the sync will start only when a new email appears, so if your computer was off for the night and you turn it on, the syncing will not begin until the first new email that day. To avoid that you can create a similar plist that launches once and runs&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;mbsync &lt;span class=&quot;token parameter variable&quot;&gt;-a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I leave that as an exercise for the reader.&lt;/p&gt;
]]></description>
        
        <category>TECH</category>
        
      </item>
    
      <item>
        <title>Manage git hooks with babashka tasks</title>
        <link>https://myke.blog/posts/babashka-git-hooks</link>
        <guid>https://myke.blog/posts/babashka-git-hooks</guid>
        <pubDate>Wed, 30 Nov 2022 24:00:00 GMT</pubDate>
        <description><![CDATA[&lt;p&gt;Git hooks are scripts that Git executes before or after one of the following events: commit, push, and receive.&lt;/p&gt;
&lt;p&gt;By default a git repository comes with a bunch of sample hooks, located in &lt;code&gt;.git/hooks&lt;/code&gt; directory. Let&#39;s look at a &lt;code&gt;pre-commit.sample&lt;/code&gt; hook. This is a 50 line script that checks, that the files you&#39;re committing do not contain any non-ascii characters. Sound like a good idea, but fifty lines of bash don&#39;t look friendly &lt;strong&gt;(don&#39;t read it, just take a glance)&lt;/strong&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token shebang important&quot;&gt;#!/bin/sh&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# An example hook script to verify what is about to be committed.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Called by &quot;git commit&quot; with no arguments.  The hook should&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# exit with non-zero status after issuing an appropriate message if&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# it wants to stop the commit.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# To enable this hook, rename this file to &quot;pre-commit&quot;.&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; rev-parse &lt;span class=&quot;token parameter variable&quot;&gt;--verify&lt;/span&gt; HEAD &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;/dev/null &lt;span class=&quot;token operator&quot;&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;2&lt;/span&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;&amp;amp;1&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
	&lt;span class=&quot;token assign-left variable&quot;&gt;against&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;HEAD
&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;# Initial commit: diff against an empty tree object&lt;/span&gt;
	&lt;span class=&quot;token assign-left variable&quot;&gt;against&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; hash-object &lt;span class=&quot;token parameter variable&quot;&gt;-t&lt;/span&gt; tree /dev/null&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# If you want to allow non-ASCII filenames set this variable to true.&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;allownonascii&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; config &lt;span class=&quot;token parameter variable&quot;&gt;--type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;bool hooks.allownonascii&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Redirect output to stderr.&lt;/span&gt;
&lt;span class=&quot;token builtin class-name&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;1&lt;/span&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;&amp;amp;2&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Cross platform projects tend to avoid non-ASCII filenames; prevent&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# them from being added to the repository. We exploit the fact that the&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# printable range starts at the space character and ends with tilde.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$allownonascii&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;true&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;# Note that the use of brackets around a tr range is ok here, (it&#39;s&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;# even required, for portability to Solaris 10&#39;s /usr/bin/tr), since&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;# the square bracket bytes happen to fall in the designated range.&lt;/span&gt;
	&lt;span class=&quot;token builtin class-name&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;diff&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--cached&lt;/span&gt; --name-only --diff-filter&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;A &lt;span class=&quot;token parameter variable&quot;&gt;-z&lt;/span&gt; $against &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
	  &lt;span class=&quot;token assign-left variable&quot;&gt;&lt;span class=&quot;token environment constant&quot;&gt;LC_ALL&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;C &lt;span class=&quot;token function&quot;&gt;tr&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;[ -~]&#92;0&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;wc&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-c&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;EOF
Error: Attempt to &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; a non-ASCII &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt; name.

This can cause problems &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; you want to work with people on other platforms.

To be portable it is advisable to &lt;span class=&quot;token function&quot;&gt;rename&lt;/span&gt; the file.

If you know what you are doing you can disable this check using:

  &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; config hooks.allownonascii &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
EOF
	&lt;span class=&quot;token builtin class-name&quot;&gt;exit&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# If there are whitespace errors, print the offending file names and fail.&lt;/span&gt;
&lt;span class=&quot;token builtin class-name&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; diff-index &lt;span class=&quot;token parameter variable&quot;&gt;--check&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--cached&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$against&lt;/span&gt; --&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And if you want to add more things to the pre-commit hook, like formatting all the modified files with a code formatter, you&#39;d need to append to it, making your life even harder. After all, who wants to code with bash?&lt;/p&gt;
&lt;p&gt;So, let&#39;s replace all this bash with babashka.&lt;/p&gt;
&lt;h2&gt;Project Setup&lt;/h2&gt;
&lt;p&gt;I&#39;ll assume we&#39;re working within a Clojure repo, but in fact this doesn&#39;t really matter. &lt;a href=&quot;https://babashka.org&quot;&gt;Babashka&lt;/a&gt; is a standalone binary that will work for a project in any language.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install babashka.
For Mac OS and brew just run:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;brew &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; borkdude/brew/babashka&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For everything else follow official &lt;a href=&quot;https://github.com/babashka/babashka#installation&quot;&gt;installation instructions&lt;/a&gt;.&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Create a &lt;code&gt;bb.edn&lt;/code&gt; file and a &lt;code&gt;bb&lt;/code&gt; folder.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Babashka Tasks&lt;/h2&gt;
&lt;p&gt;Babashka comes with an amazing and useful &lt;a href=&quot;https://book.babashka.org/#tasks&quot;&gt;task runner&lt;/a&gt;, which aims to replace &lt;code&gt;Makefile&lt;/code&gt;, &lt;code&gt;Justfile&lt;/code&gt;, &lt;code&gt;npm scripts&lt;/code&gt; or &lt;code&gt;lein&lt;/code&gt; and for us it has already replaced all of these. So we&#39;ll create our first task.&lt;/p&gt;
&lt;p&gt;For those of you who have never dealt with babashka tasks, let&#39;s make a really simple one. Put this in your &lt;code&gt;bb.edn&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-clojure&quot;&gt;&lt;code class=&quot;language-clojure&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:paths&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;bb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
 &lt;span class=&quot;token symbol&quot;&gt;:tasks&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;hello &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:doc&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Say hello&quot;&lt;/span&gt;
         &lt;span class=&quot;token symbol&quot;&gt;:task&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;println&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Hello from babashka tasks!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now if you run &lt;code&gt;bb tasks&lt;/code&gt; from the root of your project babashka will list all available tasks:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;$ bb tasks
The following tasks are available:

hello Say hello&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And you already now what running &lt;code&gt;bb hello&lt;/code&gt; will do:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;$ bb hello
Hello from babashka tasks&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So now that we know the tasks basics let&#39;s get back to hooks.&lt;/p&gt;
&lt;h2&gt;Basic Hooks Script&lt;/h2&gt;
&lt;p&gt;Create &lt;code&gt;bb/git_hooks.clj&lt;/code&gt; and open it in your editor of choice. And since it&#39;s a babashka script and in the wonderful world of Clojure we practice interactive (or REPL-driven) development, you can fire up a babashka REPL and play with the code while working.&lt;/p&gt;
&lt;p&gt;Let&#39;s start with moving our &lt;code&gt;hello&lt;/code&gt; task to this file to understand how this works. Put this in your &lt;code&gt;bb/git_hooks.clj&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-clojure&quot;&gt;&lt;code class=&quot;language-clojure&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;;; bb/git_hooks.clj&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;ns&lt;/span&gt; git-hooks&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defn&lt;/span&gt; hello &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&amp;amp; args&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;println&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Hello! My args are:&quot;&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&#39;s change the &lt;code&gt;bb.edn&lt;/code&gt; file to use the &lt;code&gt;hello&lt;/code&gt; function from the &lt;code&gt;git-hooks&lt;/code&gt; namespace.&lt;/p&gt;
&lt;pre class=&quot;language-clojure&quot;&gt;&lt;code class=&quot;language-clojure&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;;; bb.edn&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:paths&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;bb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
 &lt;span class=&quot;token symbol&quot;&gt;:tasks&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;hello &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:doc&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Say hello&quot;&lt;/span&gt;
         &lt;span class=&quot;token symbol&quot;&gt;:requires&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;git-hooks &lt;span class=&quot;token symbol&quot;&gt;:as&lt;/span&gt; gh&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;token symbol&quot;&gt;:task&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;apply&lt;/span&gt; gh/hello *command-line-args*&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are a few important things to note. First the &lt;code&gt;:requires&lt;/code&gt; line:&lt;/p&gt;
&lt;pre class=&quot;language-clojure&quot;&gt;&lt;code class=&quot;language-clojure&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;;; bb.edn&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:paths&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;bb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
 &lt;span class=&quot;token symbol&quot;&gt;:tasks&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;hello &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:doc&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Say hello&quot;&lt;/span&gt;
         &lt;span class=&quot;token symbol&quot;&gt;:requires&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;git-hooks &lt;span class=&quot;token symbol&quot;&gt;:as&lt;/span&gt; gh&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  // &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;!code focus&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
         &lt;span class=&quot;token symbol&quot;&gt;:task&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;apply&lt;/span&gt; gh/hello *command-line-args*&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It is slightly different from the traditional Clojure&#39;s &lt;code&gt;:require&lt;/code&gt; form (note the plural), but the idea is the same: we defined the source paths in the first line, and now we can require any namespace from it.&lt;/p&gt;
&lt;p&gt;Second, note how we ran the task now:&lt;/p&gt;
&lt;pre class=&quot;language-clojure&quot;&gt;&lt;code class=&quot;language-clojure&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;;; bb.edn&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:paths&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;bb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
 &lt;span class=&quot;token symbol&quot;&gt;:tasks&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;hello &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:doc&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Say hello&quot;&lt;/span&gt;
         &lt;span class=&quot;token symbol&quot;&gt;:requires&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;git-hooks &lt;span class=&quot;token symbol&quot;&gt;:as&lt;/span&gt; gh&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;token symbol&quot;&gt;:task&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;apply&lt;/span&gt; gh/hello *command-line-args*&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;  // &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;!code focus&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we didn&#39;t want to pass command line arguments into our function, we could just write:&lt;/p&gt;
&lt;pre class=&quot;language-clojure&quot;&gt;&lt;code class=&quot;language-clojure&quot;&gt;&lt;span class=&quot;token symbol&quot;&gt;:task&lt;/span&gt; gh/hello&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And if we do, babashka gives us access to the args with &lt;code&gt;*command-line-args*&lt;/code&gt; variable which we can pass or apply to our function. Let&#39;s try it out:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;$ bb hello world
Hello&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; My args are: &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;world&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Setting up Hooks&lt;/h2&gt;
&lt;p&gt;Since there are various tasks we&#39;ll be executing and it&#39;s quite trivial to accept commands in Clojure, let&#39;s make one task called &lt;code&gt;hooks&lt;/code&gt; which will accept and run commands, like &lt;code&gt;pre-commit&lt;/code&gt;, &lt;code&gt;pre-push&lt;/code&gt;, &lt;code&gt;install&lt;/code&gt; etc.&lt;/p&gt;
&lt;p&gt;Let&#39;s edit &lt;code&gt;bb/git_hooks.clj&lt;/code&gt; like this:&lt;/p&gt;
&lt;pre class=&quot;language-clojure&quot;&gt;&lt;code class=&quot;language-clojure&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;;; bb/git_hooks.clj&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;ns&lt;/span&gt; git-hooks&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defmulti&lt;/span&gt; hooks &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&amp;amp; args&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;first&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defmethod&lt;/span&gt; hooks &lt;span class=&quot;token string&quot;&gt;&quot;pre-commit&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&amp;amp; _&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;println&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Running pre-commit hook&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defmethod&lt;/span&gt; hooks &lt;span class=&quot;token symbol&quot;&gt;:default&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&amp;amp; args&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;println&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Unknown command:&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;first&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We&#39;re using a standard polymorphism tool in clojure — &lt;a href=&quot;https://clojuredocs.org/clojure.core/defmulti&quot;&gt;multimethod&lt;/a&gt;, which will treat the first command line argument as command.&lt;/p&gt;
&lt;p&gt;And &lt;code&gt;bb.edn&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-clojure&quot;&gt;&lt;code class=&quot;language-clojure&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;;; bb.edn&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:paths&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;bb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
 &lt;span class=&quot;token symbol&quot;&gt;:tasks&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;hooks &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:doc&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Hook related commands&quot;&lt;/span&gt;
         &lt;span class=&quot;token symbol&quot;&gt;:requires&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;git-hooks &lt;span class=&quot;token symbol&quot;&gt;:as&lt;/span&gt; gh&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;token symbol&quot;&gt;:task&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;apply&lt;/span&gt; gh/hello *command-line-args*&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;  // &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;!code --&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
         &lt;span class=&quot;token symbol&quot;&gt;:task&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;apply&lt;/span&gt; gh/hooks *command-line-args*&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;  // &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;!code ++&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Not much changed here, and in fact we will not need to edit &lt;code&gt;bb.edn&lt;/code&gt; any more, since this already has us covered for implementing hooks of any complexity. We just changed the name of the function we&#39;re calling.&lt;/p&gt;
&lt;h2&gt;Installing Hooks (manually)&lt;/h2&gt;
&lt;p&gt;We already have the simplest possible hook — our &lt;code&gt;hooks&lt;/code&gt; function when called with &lt;code&gt;pre-commit&lt;/code&gt; argument prints &amp;quot;Running pre-commit hook&amp;quot;:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;$ bb hooks pre-commit
Running pre-commit hook&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In order for the git to run our function each time we commit anything, let&#39;s add a following &lt;code&gt;.git/hooks/pre-commit&lt;/code&gt; file:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token shebang important&quot;&gt;#!/bin/sh&lt;/span&gt;

bb hooks pre-commit&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And make it executable:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;chmod&lt;/span&gt; +x .git/hooks/pre-commit&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now if we run &lt;code&gt;git add&lt;/code&gt; and &lt;code&gt;git commit&lt;/code&gt; we should see the printed text:&lt;/p&gt;
&lt;pre class=&quot;language-sh{3}&quot;&gt;&lt;code class=&quot;language-sh{3}&quot;&gt;$ git add .
$ git commit -m &quot;Test simple hook&quot;
Running pre-commit hook
[master (root-commit) c7dc8e4] Test simple hook
 2 files changed, 16 insertions(+)
 create mode 100644 bb.edn
 create mode 100644 bb/git_hooks.clj&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And indeed, here it is.&lt;/p&gt;
&lt;p&gt;Once we have &amp;quot;installed&amp;quot; the hook this way, we can now modify it&#39;s behavior in &lt;code&gt;bb/git_hooks.clj&lt;/code&gt;. But before giving a couple of examples of doing that, let&#39;s automate the boring part: installing hooks.&lt;/p&gt;
&lt;h2&gt;Installing Hooks (bb task)&lt;/h2&gt;
&lt;p&gt;Let&#39;s add a couple of helper functions and add an &lt;code&gt;install&lt;/code&gt; implementation to our &lt;code&gt;hooks&lt;/code&gt; multimethod:&lt;/p&gt;
&lt;pre class=&quot;language-clojure&quot;&gt;&lt;code class=&quot;language-clojure&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;;; bb/git_hooks.clj&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;ns&lt;/span&gt; git-hooks
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:require&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;babashka.fs &lt;span class=&quot;token symbol&quot;&gt;:as&lt;/span&gt; fs&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defn&lt;/span&gt; hook-text
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;hook&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#!/bin/sh
# Installed by babashka task on %s

bb hooks %s&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;java.util.Date.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; hook&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defn&lt;/span&gt; spit-hook
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;hook&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;println&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Installing hook: &quot;&lt;/span&gt; hook&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;file &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;.git/hooks/&quot;&lt;/span&gt; hook&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;spit&lt;/span&gt; file &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hook-text&lt;/span&gt; hook&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fs/set-posix-file-permissions&lt;/span&gt; file &lt;span class=&quot;token string&quot;&gt;&quot;rwx------&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fs/executable?&lt;/span&gt; file&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defmulti&lt;/span&gt; hooks &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&amp;amp; args&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;first&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defmethod&lt;/span&gt; hooks &lt;span class=&quot;token string&quot;&gt;&quot;install&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&amp;amp; _&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;spit-hook&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;pre-commit&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defmethod&lt;/span&gt; hooks &lt;span class=&quot;token string&quot;&gt;&quot;pre-commit&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&amp;amp; _&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;println&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Running pre-commit hook&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defmethod&lt;/span&gt; hooks &lt;span class=&quot;token symbol&quot;&gt;:default&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&amp;amp; args&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;println&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Unknown command:&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;first&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&#39;s go over this:&lt;/p&gt;
&lt;pre class=&quot;language-clojure&quot;&gt;&lt;code class=&quot;language-clojure&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defn&lt;/span&gt; hook-text
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;hook&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#!/bin/sh
# Installed by babashka task on %s

bb hooks %s&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;java.util.Date.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; hook&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is pretty straightforward. It creates a bash script string for a hook of our choice and timestamps it.&lt;/p&gt;
&lt;pre class=&quot;language-clojure&quot;&gt;&lt;code class=&quot;language-clojure&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defn&lt;/span&gt; spit-hook
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;hook&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;println&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Installing hook: &quot;&lt;/span&gt; hook&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;file &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;.git/hooks/&quot;&lt;/span&gt; hook&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;spit&lt;/span&gt; file &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hook-text&lt;/span&gt; hook&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fs/set-posix-file-permissions&lt;/span&gt; file &lt;span class=&quot;token string&quot;&gt;&quot;rwx------&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fs/executable?&lt;/span&gt; file&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This part is slightly more interesting. It writes the output of &lt;code&gt;hook-text&lt;/code&gt; into the actual hook and uses &lt;code&gt;babashka.fs&lt;/code&gt; library to make it executable.&lt;/p&gt;
&lt;p&gt;Let&#39;s run &lt;code&gt;bb hooks install&lt;/code&gt; and check that the hook file has in fact changed:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;$ bb hooks &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt;
Installing hook:  pre-commit
$ &lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; .git/hooks/pre-commit
&lt;span class=&quot;token comment&quot;&gt;#!/bin/sh&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Installed by babashka task on Wed Nov 30 01:06:37 WET 2022&lt;/span&gt;

bb hooks pre-commit&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Despite being so simple this little trick gives us an enormous advantage. You see, git hooks are user local. If we create a &lt;code&gt;pre-commit&lt;/code&gt; hook on our machine it will stay on our machine for security reasons.&lt;/p&gt;
&lt;p&gt;So if we want our entire team to use the same hooks, normally we would need to make sure that they manually implement same hooks as us. The babashka way let&#39;s us simply mention in our documentation that you need to run &lt;code&gt;bb hooks install&lt;/code&gt; after checking out the project and we&#39;re done.&lt;/p&gt;
&lt;h2&gt;Listing Changed Files&lt;/h2&gt;
&lt;p&gt;After installing hooks this way we will never have to open the &lt;code&gt;.git/hooks&lt;/code&gt; directory or edit bash files. We control every aspect of our hooks from within the &lt;code&gt;bb/git_hooks.clj&lt;/code&gt; files, and can use babashka and Clojure to implement hooks of any complexity.&lt;/p&gt;
&lt;p&gt;Before we move on to our first real hook, we need one last helper function:&lt;/p&gt;
&lt;pre class=&quot;language-clojure&quot;&gt;&lt;code class=&quot;language-clojure&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;;; bb/git_hooks.clj&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;ns&lt;/span&gt; git-hooks
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:require&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;babashka.fs &lt;span class=&quot;token symbol&quot;&gt;:as&lt;/span&gt; fs&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;clojure.string &lt;span class=&quot;token symbol&quot;&gt;:as&lt;/span&gt; str&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;clojure.java.shell &lt;span class=&quot;token symbol&quot;&gt;:refer&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;sh&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defn&lt;/span&gt; changed-files &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;-&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;git&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;diff&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;--name-only&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;--cached&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;--diff-filter=ACM&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;token symbol&quot;&gt;:out&lt;/span&gt;
       str/split-lines
       &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;filter&lt;/span&gt; seq&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
       seq&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
...&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For many real-life tasks (think code formatting), running something like &lt;a href=&quot;https://github.com/greglook/cljstyle&quot;&gt;cljstyle&lt;/a&gt; over your entire code base might take too much time. So to optimize that you&#39;d want to only run it over staged files. That&#39;s where our &lt;code&gt;changed-files&lt;/code&gt; function comes in. It returns a list of staged files, excluding any deleted files — ready to be passed to whatever logic you want to run over them.&lt;/p&gt;
&lt;h2&gt;&amp;quot;Real&amp;quot; Hook&lt;/h2&gt;
&lt;p&gt;Let&#39;s add a step to our pre-commit hook that formats all staged file using &lt;code&gt;cljstyle&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-clojure&quot;&gt;&lt;code class=&quot;language-clojure&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defmethod&lt;/span&gt; hooks &lt;span class=&quot;token string&quot;&gt;&quot;pre-commit&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&amp;amp; _&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;println&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Running pre-commit hook&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;when-let&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;files &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;changed-files&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;apply&lt;/span&gt; sh &lt;span class=&quot;token string&quot;&gt;&quot;cljstyle&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;fix&quot;&lt;/span&gt; files&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Honestly, I strongly prefer this to any bash. And if you want to add any more logic to be performed over the changed files, you can do it right in the &lt;code&gt;pre-commit&lt;/code&gt; implementation of the &lt;code&gt;hooks&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;In order to make the formatting hook production ready we need to make sure it&#39;s only run over Clojure files. Let&#39;s make another predicated for that:&lt;/p&gt;
&lt;pre class=&quot;language-clojure&quot;&gt;&lt;code class=&quot;language-clojure&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; extensions &lt;span class=&quot;token operator&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;clj&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;cljx&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;cljc&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;cljs&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;edn&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defn&lt;/span&gt; clj?
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;when&lt;/span&gt; s
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;extension &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;last&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;str/split&lt;/span&gt; s &lt;span class=&quot;token operator&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&#92;.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;extensions&lt;/span&gt; extension&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And put it all together:&lt;/p&gt;
&lt;pre class=&quot;language-clojure&quot;&gt;&lt;code class=&quot;language-clojure&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;;; bb/git_hooks.clj&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;ns&lt;/span&gt; git-hooks
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:require&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;babashka.fs &lt;span class=&quot;token symbol&quot;&gt;:as&lt;/span&gt; fs&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;clojure.string &lt;span class=&quot;token symbol&quot;&gt;:as&lt;/span&gt; str&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;clojure.java.shell &lt;span class=&quot;token symbol&quot;&gt;:refer&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;sh&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defn&lt;/span&gt; changed-files &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;-&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;git&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;diff&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;--name-only&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;--cached&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;--diff-filter=ACM&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;token symbol&quot;&gt;:out&lt;/span&gt;
       str/split-lines
       &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;filter&lt;/span&gt; seq&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
       seq&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; extensions &lt;span class=&quot;token operator&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;clj&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;cljx&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;cljc&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;cljs&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;edn&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defn&lt;/span&gt; clj?
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;when&lt;/span&gt; s
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;extension &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;last&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;str/split&lt;/span&gt; s &lt;span class=&quot;token operator&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&#92;.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;extensions&lt;/span&gt; extension&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defn&lt;/span&gt; hook-text
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;hook&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#!/bin/sh
# Installed by babashka task on %s

bb hooks %s&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;java.util.Date.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; hook&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defn&lt;/span&gt; spit-hook
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;hook&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;println&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Installing hook: &quot;&lt;/span&gt; hook&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;file &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;.git/hooks/&quot;&lt;/span&gt; hook&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;spit&lt;/span&gt; file &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hook-text&lt;/span&gt; hook&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fs/set-posix-file-permissions&lt;/span&gt; file &lt;span class=&quot;token string&quot;&gt;&quot;rwx------&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fs/executable?&lt;/span&gt; file&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defmulti&lt;/span&gt; hooks &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&amp;amp; args&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;first&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defmethod&lt;/span&gt; hooks &lt;span class=&quot;token string&quot;&gt;&quot;install&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&amp;amp; _&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;spit-hook&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;pre-commit&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defmethod&lt;/span&gt; hooks &lt;span class=&quot;token string&quot;&gt;&quot;pre-commit&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&amp;amp; _&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;println&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Running pre-commit hook&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;when-let&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;files &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;changed-files&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;apply&lt;/span&gt; sh &lt;span class=&quot;token string&quot;&gt;&quot;cljstyle&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;fix&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;filter&lt;/span&gt; clj? files&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;defmethod&lt;/span&gt; hooks &lt;span class=&quot;token symbol&quot;&gt;:default&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&amp;amp; args&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;println&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Unknown command:&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;first&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now each time we run &lt;code&gt;git commit&lt;/code&gt; every Clojure file will be formatted with &lt;code&gt;cljstyle&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now you can build from here, for example creating a &lt;code&gt;pre-push&lt;/code&gt; hook that will not allow pushing if &lt;a href=&quot;https://github.com/clj-kondo/clj-kondo&quot;&gt;clj-kondo&lt;/a&gt; finds any errors. Or building anything that you want with babashka.&lt;/p&gt;
&lt;p&gt;All without writing a single line of bash.
&lt;/PostDetail&gt;&lt;/p&gt;
]]></description>
        
        <category>TECH</category>
        
      </item>
    
      <item>
        <title>Elon Musk and the Magic of Names</title>
        <link>https://myke.blog/posts/elon-musk-and-the-magic-of-names</link>
        <guid>https://myke.blog/posts/elon-musk-and-the-magic-of-names</guid>
        <pubDate>Tue, 04 Oct 2022 24:00:00 GMT</pubDate>
        <description><![CDATA[&lt;p&gt;Yesterday a strange thing happened. You have probably seen it:&lt;/p&gt;
&lt;img src=&quot;/media/musks-tweet-2.png&quot; alt=&quot;Elon Musk&#39;s about Russian invasion to Ukraine&quot;&gt;
&lt;p&gt;I&#39;m not going to concentrate on all the ways posting this was wrong. I expect there will be a shit storm strong enough without my five cents. In the spirit of this blog I&#39;m more interested in the questions relating to thinking and knowledge. And there&#39;s an obvious one.&lt;/p&gt;
&lt;h1&gt;How do we know that we really know what we think we know?&lt;/h1&gt;
&lt;p&gt;Wow that&#39;s a stunning example of a well-formulated question right there.&lt;/p&gt;
&lt;p&gt;I admit, I&#39;m kinda using Elon Musk here as a screaming example of publicly talking about things you have no clue about. But we&#39;re all guilty at times of doing the same. Even if we&#39;re not public.&lt;/p&gt;
&lt;p&gt;But let&#39;s keep using him as an example. There must be some foundation under his opinion about Crimea: after all, he confidently states that:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Crimea formally part of Russia, as it has been since 1783 (until Khrushchev’s mistake).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And there lies the trap that most people will fall into. They will try fact checking this statement, reading the Wiki article on &lt;a href=&quot;https://en.wikipedia.org/wiki/Crimea&quot;&gt;Crimea&lt;/a&gt;, trying to figure out was it really formally a part of Russia. Reading and arguing about how Crimean Khanate was conquered and if Crimea wanted to be a part of Russia.&lt;/p&gt;
&lt;p&gt;And they will totally miss the elephant in the room. The &amp;quot;Russia&amp;quot; he talks about doesn&#39;t exist. And it didn&#39;t exist for over a century.&lt;/p&gt;
&lt;h2&gt;Wait what?&lt;/h2&gt;
&lt;p&gt;This little thought was nagging me for a long time, maybe 10 or even 20 years, and I could never put my finger exactly on it. Until I did.&lt;/p&gt;
&lt;p&gt;Being Ukrainian, for me this was kind of obvious&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; on an intuitive level. But until today I didn&#39;t see it for what it was — the most ingenious piece of Russian propaganda.&lt;/p&gt;
&lt;h3&gt;It&#39;s all in the name&lt;/h3&gt;
&lt;p&gt;Long time ago there was a country called &amp;quot;Russia&amp;quot;. Well, maybe there was such country, it&#39;s hard to tell by now, after rewriting history so many times. But there definitely was a country called &lt;a href=&quot;https://en.wikipedia.org/wiki/Russian_Empire&quot;&gt;&lt;em&gt;Russian Empire&lt;/em&gt;&lt;/a&gt;, and we can tell exactly when it started.&lt;/p&gt;
&lt;p&gt;The term and the entire ideology was coined by a Ukrainian&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; scholar &lt;a href=&quot;https://en.wikipedia.org/wiki/Theophan_Prokopovich&quot;&gt;Theophan Prokopovich (ukr. Феофан Прокопович)&lt;/a&gt;, a very educated guy lacking any moral compass. After Peter I tried destroying &lt;a href=&quot;https://en.wikipedia.org/wiki/National_University_of_Kyiv-Mohyla_Academy&quot;&gt;Kyiv Mohyla Academy&lt;/a&gt;, the only real university in the region of that time, he promoted Theophan to some important role in Saint Petersburg. There he coined the whole concept of Russian &lt;em&gt;Empire&lt;/em&gt;, following a good European tradition of claiming to be the &lt;em&gt;Third Rome&lt;/em&gt;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;In any case, in 1721 he renamed the Tsardom of Russia into Russian &lt;strong&gt;Empire&lt;/strong&gt;, and that&#39;s when the country officially started. And that country was normally referred to as &lt;strong&gt;Russia&lt;/strong&gt; in the West. That&#39;s important.&lt;/p&gt;
&lt;p&gt;Before World War I it was a pretty big country. As Elon Musk says, Crimea was formally it&#39;s part. As were other nice places, like Poland, Finland and all the Baltic states.&lt;/p&gt;
&lt;p&gt;Right until it stopped existing.&lt;/p&gt;
&lt;h3&gt;The &amp;quot;Great October Revolution&amp;quot;&lt;/h3&gt;
&lt;p&gt;You need to understand, that I&#39;m doing this as quickly as I can before I get you bored. We&#39;re almost there.&lt;/p&gt;
&lt;p&gt;In 1917 after a series of revolutions caused by the terrible decision to participate in the Great War, there finally seemed to be a clear revolutionary winner — the Bolshevik Party, which later became the Communist Party.&lt;/p&gt;
&lt;p&gt;And they wanted nothing to do with the former Imperial past. They renamed the country into &lt;a href=&quot;https://en.wikipedia.org/wiki/Soviet_Union&quot;&gt;&lt;em&gt;Union of Soviet Socialist Republics&lt;/em&gt;&lt;/a&gt;, also known as the &lt;em&gt;Soviet Union&lt;/em&gt;. And that was the country I was born in.&lt;/p&gt;
&lt;p&gt;Some places got lucky and broke off early, when this abomination of a state was just forming: like Finland. Others tried, but didn&#39;t succeed, like Ukraine&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn4&quot; id=&quot;fnref4&quot;&gt;[4]&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;But even those places that didn&#39;t succeed, were not part of Russia. They were part of the Soviet Union. Multinational. Multicultural. Calling themselves &amp;quot;soviet people&amp;quot;. Not &amp;quot;Russians&amp;quot;.&lt;/p&gt;
&lt;p&gt;USSR was a scary country with a scary ideology, and we&#39;re all lucky it didn&#39;t survive the Cold War. But until it&#39;s later days that country had principles. I don&#39;t agree with it&#39;s ideology, but it had one. I don&#39;t agree with the future it wanted to build for the humanity, but it was looking into the &lt;em&gt;future&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;That country fought in World War II and a bunch of other wars. That country was one of the founding states of United Nations and a permanent member of the UN Security Council.&lt;/p&gt;
&lt;p&gt;Right until it stopped existing in 1991.&lt;/p&gt;
&lt;h3&gt;Devil&#39;s work&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;The Devil’s cleverest wile is to make men believe that he does not exist.  -- Charles Baudelaire&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Modern day Russia is like that, but it tries to convince the world (and itself), that it&#39;s somehow, magically, the same country as USSR and Russian Empire. The whole idea behind &lt;em&gt;rashism&lt;/em&gt; is trying to bring back the past, not to build some brighter version of the future (even if it doesn&#39;t seem brighter to everybody else, like in the case of the USSR).&lt;/p&gt;
&lt;p&gt;And it&#39;s not the first time something like this happens in a dictatorship. Mussolini used to address the Italians as &lt;em&gt;Romans&lt;/em&gt;, and insisted that his Italy was magically the same country as the Roman Empire.&lt;/p&gt;
&lt;p&gt;So saying that Crimea was part of Russia, and should be left to Russia is like saying that Greece was a part of the Roman Empire, and should be left to Italy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;And the only reason it doesn&#39;t sound absurd is because during the Soviet times we kept calling the country &amp;quot;Russia&amp;quot;.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;Returning to the original question&lt;/h2&gt;
&lt;p&gt;So how do we know that we really know what we think we know? I&#39;m afraid this question is so big, that it&#39;s impossible to cover in an essay. But there are some tricks we can use:&lt;/p&gt;
&lt;h3&gt;Look for alternative points of view and alternative sources&lt;/h3&gt;
&lt;p&gt;And by point of view I don&#39;t just mean &amp;quot;opinions&amp;quot;, but also other angles to look at a the subject. Because if the subject is even a slightly bit controversial (and most interesting subjects are), and you only used one source — by definition you only heard one side of the story.&lt;/p&gt;
&lt;h3&gt;Question fundamentals&lt;/h3&gt;
&lt;p&gt;Try questioning the most fundamental parts of the subject. Like with the Musks tweet the fundamental part was not whether Crimea is or is not part of Russia, but in fact whether the &amp;quot;Russia&amp;quot; he talks about even exists.&lt;/p&gt;
&lt;p&gt;I hope you enjoyed the ride.&lt;/p&gt;
&lt;hr&gt;
&lt;hr class=&quot;footnotes-sep&quot;&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;If something seems &amp;quot;obvious&amp;quot; it&#39;s a true sign that almost everybody else sees it differently &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Fate is a bitch &lt;a href=&quot;#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Read up on &lt;em&gt;translatio imperii&lt;/em&gt;, but read something good &lt;a href=&quot;#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Read up on &lt;em&gt;Ukrainians People&#39;s Republic&lt;/em&gt; &lt;a href=&quot;#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
]]></description>
        
        <category>GENERAL</category>
        
      </item>
    
      <item>
        <title>Why write?</title>
        <link>https://myke.blog/posts/why-write</link>
        <guid>https://myke.blog/posts/why-write</guid>
        <pubDate>Tue, 20 Sep 2022 24:00:00 GMT</pubDate>
        <description><![CDATA[&lt;p&gt;Writing is a tool. And as any good tool it can be used for many things. Sharing information. Telling stories. Messaging. Influencing people to make the choice you want them to make. All these uses were clear to me for a long time, and they all were pretty self-explanatory.&lt;/p&gt;
&lt;p&gt;There was one special use though, that I was wondering about for a long time.&lt;/p&gt;
&lt;h1&gt;Writing helps you think.&lt;/h1&gt;
&lt;p&gt;A couple of days ago I was flying from Lisbon to Krakow, first part of my journey to my home in Ukraine (why go there during the war is another story).&lt;/p&gt;
&lt;p&gt;Right before the take off I stumbled upon an essay by &lt;a href=&quot;http://paulgraham.com&quot;&gt;Paul Graham&lt;/a&gt; called, ironically, &lt;a href=&quot;http://www.paulgraham.com/essay.html&quot;&gt;&lt;em&gt;The Age of the Essay&lt;/em&gt;&lt;/a&gt;. As brilliant people often do, he put in words precisely the things I felt for a long time.&lt;/p&gt;
&lt;p&gt;I recommend you read his original piece, as he did a great job about describing the history and the essence of writing essays. But I will quote one thing:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In a real essay you&#39;re writing for yourself. You&#39;re thinking out loud.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;But not quite. Just as inviting people over forces you to clean up your apartment, writing something that other people will read forces you to think well.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And this really stroke a note inside. I knew for a long time that writing helps me think. I even joked sometimes that you need to sit down and write on the subject to find out what your real opinion is.&lt;/p&gt;
&lt;p&gt;But reading Graham&#39;s piece changed two things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;This kind of writing now had a name. Essays.&lt;/li&gt;
&lt;li&gt;It gave me a good reason to publish what I write.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And now you&#39;re here. Reading.&lt;/p&gt;
&lt;p&gt;Thank you for giving me a reason to clean up my mess!&lt;/p&gt;
]]></description>
        
        <category>GENERAL</category>
        
      </item>
    
  </channel>
</rss>
