{"version":"https://jsonfeed.org/version/1.1","title":"Thorsten Zöller - Articles","home_page_url":"https://thorstenzoeller.com","feed_url":"/home/tzoeller/personal/net/website/build/articles/feed.json","author":{"name":"Thorsten Zöller"},"items":[{"id":"https://thorstenzoeller.com/anki-inside-xephyr","title":"

Running Anki inside Xephyr

\n","content_html":"<h1 id="running-anki-inside-xephyr">Running Anki inside Xephyr</h1>\n\n<p>2023-02-26</p>\n\n<p><a href="https://apps.ankiweb.net/">Anki</a> is a great tool for memorizing things, like\nwords in a foreign language you want to learn. I am using it for memorizing\nVietnamese words in my endeavor to learn Vietnamese.</p>\n\n<p>I am currently running Anki 2.1.16 on OpenBSD 7.1. Unfortunately, quite often\nAnki freezes after using it for some time, without any advance notice. When this\nhappens, I can no longer do anything except moving the mouse pointer. I cannot\nswitch windows and not even switch to the console in order to forcefully quit\nAnki. Apparently, it crashes the whole system, and the only way out is a\nforceful reboot.</p>\n\n<p>I do not know what causes this behavior or if there is any fix for it. It seems\nthat I am not the only one experiencing this, but I have not yet found a\nsolution to this behavior.</p>\n\n<p>I did find a workaround, however: Running Anki inside of\n<a href="https://man.openbsd.org/Xephyr">Xephyr(1)</a> (a nested X server that runs as an X\napplication and is part of OpenBSD base) seems to prevent it from freezing. The\nworkaround involves three steps:</p>\n\n<ol>\n <li>Launch <code>Xephyr</code> on display <code>:1</code> (or any other display differing from your\nmain display, which is usually <code>:0</code>).</li>\n <li>Launch <code>cwm</code> inside the <code>Xephyr</code> window just created (it is necessary to run\na window manager since Anki employs multiple windows in general; of course,\nany other window manager can be used as well).</li>\n <li>Lauch Anki inside the <code>Xephyr</code> window.</li>\n</ol>\n\n<p>For convenience, I have created a small shell script for executing these steps:</p>\n\n<pre><code>Xephyr -br -ac -noreset -screen 1920x1080 :1 &amp;\ncwm -c .cwmrc_xephyr -d :1 &amp;\nDISPLAY=:1 anki &amp;\n</code></pre>\n\n<p>Of course, the value of the <code>screen</code> command line parameter of <code>Xephyr</code> needs to\nbe adjusted to your screen size. Also, I run <code>cwm</code> in the <code>Xephyr</code> window with a\nspecific configuration file.</p>\n\n<p>It works well, but strangely, after a while <code>cwm</code> seems to stop running inside\n<code>Xephyr</code>. This is inconvenient because it makes it impossible to switch between\ndifferent Anki windows. The solution is to simply restart <code>cwm</code> by manually\nexecuting the second line of the script again.</p>\n\n<p>Obviously, this is not a real fix to the problem, but it works. Hopefully, Anki\nwill get more stable in the future so that this workaround will no longer be\nneeded.</p>\n","url":"https://thorstenzoeller.com/anki-inside-xephyr","date_published":"2023-02-26","date_modified":"2023-02-26"},{"id":"https://thorstenzoeller.com/day","title":"

The Melancholy of the Day

\n","content_html":"<h1 id="the-melancholy-of-the-day">The Melancholy of the Day</h1>\n\n<p>2023-02-11</p>\n\n<p>A new day begins, in the dark, in silence. Everything is still asleep; there is\nbarely any activity, any motion. It is a state of peace and serenity. There is\nnothing to accomplish, no hustle and bustle; everything is immersed in\nstillness.</p>\n\n<p>Then, the sun begins to rise, and slowly the world awakens from its sleep. Not\nmuch is happening yet, but the new day is full of potential, full of\nopportunities. An atmosphere of departure prevails. Everything seems possible,\nnothing impossible. As the sun continues to rise, a tension develops, as the\ninactivity of the night wants to release itself into activity.</p>\n\n<p>Around noon, when the sun is highest in the sky, the day is most powerful.\nGlittering light falls from the outside into the rooms; light which is so strong\nthat it blinds. The day is now bursting with energy. Everything is possible, and\nno end of this state is conceivable.</p>\n\n<p>But then comes the afternoon, and slowly, very slowly, the sun begins its\ndescent. At first barely visible, it does not take long until it becomes clear\nthat the day cannot maintain its power. First shades emerge, and the light is no\nlonger as glittering as it was before; it is slightly dimmer now than just a\nshort time ago. And it is constantly changing. It becomes ever softer and warmer\nthe deeper the sun is in the sky. It still fills the rooms, but instead of\ndominating them, it becomes tender. The light immerses everything in dim, warm\ncolors, and the shades become longer and longer. It is a mystical, almost\nmagical atmosphere which now accrues.</p>\n\n<p>But this change of light, of the mood, is accompanied by a certain melancholy,\nand the melancholy grows the longer the day lasts and the fainter the light\nbecomes. The steady change of light, proceeding faster and faster, leaves no\ndoubt that the end of the day approaches. Some time still remains, but it seeps\naway quickly, second for second, minute for minute. The time when the day seemed\ninvincible is now long gone; long gone is the time when it seemed that the day\nwould prevail forever. It is absolutely clear now that it will be over soon. It\nhad just brimmed over with power, with self-confidence, with energy–but now it\nbecomes weaker and ever weaker, and very soon it will be history and forever,\nirretrievably gone.</p>\n","url":"https://thorstenzoeller.com/day","date_published":"2023-02-11","date_modified":"2023-02-11"},{"id":"https://thorstenzoeller.com/ed-mastery","title":"

Michael W Lucas: “Ed Mastery”

\n","content_html":"<h1 id="michael-w-lucas-ed-mastery">Michael W Lucas: “Ed Mastery”</h1>\n\n<p>2024-09-29</p>\n\n<p>The average user may not think a lot about which text editor to use. For us,\nhowever, the choice of a text editor is a very serious matter.</p>\n\n<p>I’ll admit it: I have always felt a little proud to be a\n<a href="https://man.openbsd.org/vi">vi(1)</a> user (I even have a dedicated <a href="/vi/">vi\npage</a> on my website). After having read <a href="https://mwl.io/nonfiction/tools#ed">Ed\nMastery</a> by <a href="https://mwl.io/">Michael W\nLucas</a>, however, I feel somewhat wimpy about it.</p>\n\n<p>Only recently did I stumble across the book, and I was surprised that a book\nabout <a href="https://man.openbsd.org/ed">ed(1)</a> – “the standard Unix text editor” –\neven exists. Yet, I knew immediately that I would have to read it. The mere\nexistence of a book about <a href="https://man.openbsd.org/ed">ed(1)</a> was enough to\nconvince me that it will be worth it.</p>\n\n<p>And I was not disappointed (not that I had expected that…). Michael W Lucas’\nstyle of writing is hilarious, and first and foremost, it is simply a pleasure\nto read.</p>\n\n<p>Admittedly, I never really looked past <a href="https://man.openbsd.org/vi">vi(1)</a> in\nthe history of Unix text editors. I roughly new that\n<a href="https://man.openbsd.org/ex">ex(1)</a> and <a href="https://man.openbsd.org/ed">ed(1)</a> are\npredecessors of <a href="https://man.openbsd.org/vi">vi(1)</a> and that they are line\neditors, but they always seemed a bit too peculiar and exotic to me to justify\nlooking into them in more detail (mostly because they are line editors, stemming\nfrom a time when monitors were not yet common or even available – one cannot\ntake a line editor seriously these days, can one?). While I always felt that no\nreal progression has taken place in editor development since the advent of\n<a href="https://man.openbsd.org/vi">vi(1)</a> (which explicitly includes editors like\n<a href="https://www.vim.org/">Vim</a> or <a href="http://neovim.io/">Neovim</a>), I always implicitly\nassumed that <a href="https://man.openbsd.org/vi">vi(1)</a> <em>was</em> in fact a progression\nfrom <a href="https://man.openbsd.org/ed">ed(1)</a> and <a href="https://man.openbsd.org/ex">ex(1)</a>\n(reflecting the progression from line printers to monitors for displaying\noutput). After reading <a href="https://mwl.io/nonfiction/tools#ed">Ed Mastery</a>, though,\nI am not so certain about it anymore. I thought\n<a href="https://man.openbsd.org/vi">vi(1)</a> was the pinnacle of simplicity, beauty and\nefficiency, but maybe I was wrong all along.</p>\n\n<p>A while ago, there was a great post titled <a href="https://stackoverflow.com/a/1220118">Your problem with Vim is that you\ndon’t grok vi.</a> on Stack Overflow (read it\nif you haven’t yet!). It basically states that many of the features of\n<a href="https://www.vim.org/">Vim</a> that are generally considered improvements over\n<a href="https://man.openbsd.org/vi">vi(1)</a> (<em>Vi IMproved</em>, you know?), making it more\n“user friendly”, are in fact feature creep (visual mode? why?) and simply exist\nbecause users don’t want to take the time to get really familiar and acquainted\nwith <a href="https://man.openbsd.org/vi">vi(1)</a>. It is the antidote to Antoine de\nSaint-Exupéry’s famous statement “Perfection is achieved, not when there is\nnothing more to add, but when there is nothing left to take\naway.”<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup></p>\n\n<p>I am wondering if something similar could not be said about\n<a href="https://man.openbsd.org/ed">ed(1)</a> as well: “Your problem with vi is that you\ndon’t grok ed.”</p>\n\n<p>In any event, after reading <em>Ed Mastery</em>, many known features from\n<a href="https://man.openbsd.org/vi">vi(1)</a> will make more sense. And even though it is\nrather unlikely that most users will ditch their editor of choice right away in\nfavor of <a href="https://man.openbsd.org/ed">ed(1)</a> after reading the book, I am\nconvinced that it will improve your editing skills (if you use an editor\ndescending from <a href="https://man.openbsd.org/ed">ed(1)</a>, that is – otherwise, all\nhope is lost anyway).</p>\n\n<p>In summary: Experiencing joy while reading the book and learning profound things\nalong the way: What more could you wish for from a book?</p>\n\n<p>Therefore my recommendation: <a href="https://mwl.io/nonfiction/tools#ed">Get the book</a>,\nread it and grok <a href="https://man.openbsd.org/ed">ed(1)</a>, now!</p>\n\n<p><em>Note:</em> Peter N. M. Hansteen has already written <a href="https://nxdomain.no/~peter/ed_mastery_is_a_must_for_real_unix_person.html">a great\nreview</a>\nof the book several years ago, and actually I feel that there is not much I\ncould add to it (apart from my casual ranting you spent the last couple of\nminutes reading). You should definitely read it as well if you haven’t!</p>\n<div class="footnotes" role="doc-endnotes">\n <ol>\n <li id="fn:1">\n <p>I’ll happily admit that I do use <a href="https://neovim.io/">Neovim</a>. Have I ever\nclaimed that I live up to my own standards, after all? <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>\n </li>\n </ol>\n</div>\n","url":"https://thorstenzoeller.com/ed-mastery","date_published":"2024-09-29","date_modified":"2024-09-29"},{"id":"https://thorstenzoeller.com/how-i-use-vim","title":"

How I Use Vim

\n","content_html":"<h1 id="how-i-use-vim">How I Use Vim</h1>\n\n<p>2025-08-30</p>\n\n<p>First things first: This is a contribution to the first ever <a href="https://lazybea.rs/carnivals/">Vim\nCarnival</a>, initiated by\n<a href="https://lazybea.rs/">Hyde</a>, and it is an honor to be part of it! A big “thank\nyou” to Hyde for coming up with this great idea, organizing the carnival and\nhosting the <a href="https://lazybea.rs/vim-carnival-202509/">first one</a>!</p>\n\n<p><em>Note: In the whole article, I am mostly using “Vim” as a general term\nreferring to any Vim-like editor (i.e. it encompasses in particular both\n<a href="https://www.vim.org/">Vim</a> and <a href="https://neovim.io/">Neovim</a>), unless otherwise\nstated.</em></p>\n\n<h2 id="my-history-of-using-vim----a-personal-account">My History of Using Vim – A Personal Account</h2>\n\n<p>When I first grappled with Linux in the mid-to-late 1990s, I was inevitably\nconfronted with the question of which editor to use. There was a huge amount of\neditors to choose from, but I quickly learned that there were two editors which\nwere mentioned much more than others, and those two editors obviously were vi\nand Emacs. I started playing around a little bit with Emacs, but soon I realized\nthat it was not the right editor for me. I was looking for a tool which allowed\nme to edit text files, and nothing else. And Emacs definitely allows one to do\n<em>a lot more</em> than just editing text files.</p>\n\n<p>Now it is certainly not my intention to revive one of the most famous holy wars\never. I completely understand if people use Emacs if this is the right editor\nfor them (or any other editor, for that matter). For me, however, vi (or rather\nVim at that time) turned out to be the right editor.</p>\n\n<p>Its simplicity and minimalist appearance appealed a lot to me. I liked that the\nmouse played no role in using it. And I knew that there was no need for me to\nlook any further.</p>\n\n<p>I guess I was drawn to vi for the same reasons I was – albeit many years\nlater – drawn to the <a href="https://www.openbsd.org">OpenBSD</a> operating system: I\nlike things to be minimal. In particular, tools should do one thing only and do\nit well (the core of the <a href="https://en.wikipedia.org/wiki/Unix_philosophy">Unix philosophy</a>,\nby the way).<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup></p>\n\n<p>Once I started using Vim, I never felt any desire to switch to another editor,\nand it is now my editor of choice since more than a quarter of a century (and I\nam so fond of it that I even maintain a dedicated <a href="/vi/">vi page</a>).</p>\n\n<h2 id="so-how-do-i-actually-use-vim">So, How Do I Actually Use Vim?</h2>\n\n<p>I do basically all my editing and writing in Vim, from e-mails to my PhD thesis\n(and, obviously, this very article as well). I also do all of my programming in\nVim (no need for fancy IDEs). It is suitable for minor editing tasks just as\nwell as for large writing or programming projects, and it has never failed me.\nIt is fast – <em>really</em> fast –, and plain vi is available on basically every\nUnix installation out there – no matter what flavor of Unix or what age it is.</p>\n\n<p>I love that it is a modal editor. In contrast to most other editors, pressing a\nkey does not automatically make the corresponding character appear on the screen\n– it only does if you happen to be in insert mode. Otherwise, it is interpreted\nas a command. This allows for pretty easy key combinations for most simple and\nelementary commands (in contrast to non-modal editors, where one always has to\nescape entering characters, which necessarily leads to more complex key\ncombinations). I also love that commands are very logical in a specific way; one\ncould argue that they form some sort of a language. I will not dive into the\ndetails here; that would make for an entire new article (or two or three…). It\nhas been claimed that editing text in Vim is an almost Zen-like experience, and\nwhile I feel that this does not really do justice to Zen, I completely get what\nis meant by that statement.</p>\n\n<p>I do not use any plugins, although there is a huge ecosystem of plugins\navailable for Vim (and Neovim even declares itself a “hyperextensible Vim-based\ntext editor” on its <a href="https://neovim.io/">website</a>). I simply do not have any\nneed for them. While there are certainly plugins which aim at improving the\n<em>editing</em> experience, my impression is that many plugins try to make Vim into\nsomething more than an editor. As mentioned earlier, though, that was one of the\nmajor reasons for me <em>not</em> to use Emacs. I do not want Vim to be more than an\neditor. I want to have an editor – no more and no less, period.</p>\n\n<p>Actually, I do not even care much about many of the <em>improvements</em> of Vim over\nplain vi (Vim is “Vi IMproved”, after all…). For instance, I never use visual\nmode. While it may be helpful when one is new to Vim<sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">2</a></sup> – and in particular\nwhen one is used to GUI editors allowing one to mark text –, it is probably not\nthe most efficient way to accomplish most of the things it is used for. In fact,\nI would argue that it would be a good idea to use plain vi for quite some time\nbefore (potentially) moving on to Vim. Many people probably do not even know how\nto accomplish things in vi without resorting to the <em>improvements</em> Vim offers.\nYet, I am convinced that many of those <em>improvements</em> are improvements only in a\nsuperficial way. All this is elaborated extremely well in a reply on Stack\nOverflow, <a href="https://stackoverflow.com/a/1220118">Your problem with Vim is that you don’t grok\nvi</a>. I suggest reading it to everyone who\nis using Vim.</p>\n\n<p>So, in a perfect world, I would be using plain vi instead of Vim<sup id="fnref:3"><a href="#fn:3" class="footnote" rel="footnote" role="doc-noteref">3</a></sup>, and\nactually this is what I did for a couple of years.<sup id="fnref:4"><a href="#fn:4" class="footnote" rel="footnote" role="doc-noteref">4</a></sup> There are some reasons,\nthough, why I switched to using Neovim for most things. One reason is that\nmultiple levels of “undo” <em>is</em> in fact a real improvement over vi. Besides, I\nhail from one of those strange countries where people like to draw little dots\nabove the letters, so Unicode support is practically non-negotiable for me.\nAlso, I do use syntax highlighting, though I consider it by no means necessary\n(contrary to what I used to believe before using plain vi exclusively for a\nwhile).</p>\n\n<p>My <code>.vimrc</code> is very simple as well. While I am quite impressed by all the config\nfiles one can find on the Internet which are hundreds of lines long, and while I\nhave a tendency myself to tweak config files way too much, I prefer to keep\nthings simple here as well. Setting a few options fully suffices to make Vim\nbehave the way I like.</p>\n\n<p>Now, while one might get that impression, it is certainly not my intention to\nargue against using Vim and in favor of vi. While I do think that Vim has become\nrather bloated over time, I use it on a daily basis and am most happy with it.\nMy point is to direct the focus on the beautiful core of Vim – which is pretty\nclose to plain vi in my opinion, yet extends it in certain ways. I sometimes\nlike to compare vi and Vim to C and C++:<sup id="fnref:5"><a href="#fn:5" class="footnote" rel="footnote" role="doc-noteref">5</a></sup> There is this beautiful, rather\nsmall and well-defined, yet immensely powerful language C. And then there is\nC++, which extends C by far, adding feature over feature to it. Both are used\nheavily, and there are certainly reasons for both; but in most cases, I would\nrather use C instead of C++ (if I used them at all…).</p>\n\n<p>So, coming back to the subject of this article, the question of how I use Vim: I\nuse it mostly the way I would use plain vi, but I also happily make use of those\nextensions I find useful – which are rather few, though. While I have used Vim\nfor decades, I am sure I only employ a small fraction of the possibilities Vim\n– or even vi – offers. I might become more efficient by putting work into\nlearning more subtle and intricate features, but I feel no real need for it. I\nknow that, should I need a particular feature, I will most certainly find it –\nif not in vi, then in Vim. Most of the time, though, I am happy using a select\nset of commands in a more or less efficient way.</p>\n\n<p>There is so much more to say about Vim (maybe in the context of another Vim\nCarnival?), but for now, I will close my ramblings about Vim with one last\nobservation: I do not just <em>use</em> Vim – I <em>enjoy</em> using it, a lot.</p>\n\n<h2 id="further-reading">Further Reading</h2>\n\n<p>There are a lot of great text about Vim out there (for a selection, see my <a href="/vi/">vi\npage</a>), so I would just like to mention two particular ones here:</p>\n\n<ul>\n <li><a href="https://moolenaar.net/habits.html">Seven habits of effective text editing</a> by\nBram Moolenaar, author of <a href="https://www.vim.org/">Vim</a>.</li>\n <li><a href="http://www.viemu.com/a-why-vi-vim.html">Why, oh WHY, do those #?@! nutheads use\nvi?</a></li>\n</ul>\n\n<p>There once was another nice article called “Grokking the Zen of the Vim Wu-Wei”,\nbut unfortunately the original link is broken, and I cannot find it anywhere\nelse. If someone does manage to find it, I would be grateful for the link.</p>\n\n<p><strong>Update 2026-01-11</strong>: Thankfully, the author himself has provided the link to\nthe article, so here it is:</p>\n\n<ul>\n <li><a href="https://jeetworks.org/grokking-the-zen-of-the-vi-wu-wei/">Grokking the Zen of the Vi\nWu-Wei</a></li>\n</ul>\n\n<hr />\n\n<div class="footnotes" role="doc-endnotes">\n <ol>\n <li id="fn:1">\n <p>Strangely, I recently found two articles which make the very same point\nwith respect to coffee preparation: <a href="https://btxx.org/posts/one-thing/">My Coffee Maker Just Makes\nCoffee</a>, and <a href="https://www.fromjason.xyz/p/notebook/the-bliss-of-good-enough-an-ode-to-my-moka-pot/">The bliss of good enough—\nan ode to my moka\npot</a>. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>\n </li>\n <li id="fn:2">\n <p>And I have used it myself for many years, I should add. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>\n </li>\n <li id="fn:3">\n <p>And in an even more perfect world, I would be using <a href="/ed-mastery/">ed</a>. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>\n </li>\n <li id="fn:4">\n <p>To be more precise, I was using nvi. <a href="#fnref:4" class="reversefootnote" role="doc-backlink">&#8617;</a></p>\n </li>\n <li id="fn:5">\n <p>Though the comparison is admittedly far from perfect… <a href="#fnref:5" class="reversefootnote" role="doc-backlink">&#8617;</a></p>\n </li>\n </ol>\n</div>\n","url":"https://thorstenzoeller.com/how-i-use-vim","date_published":"2025-08-30","date_modified":"2025-08-30"},{"id":"https://thorstenzoeller.com/mail-reminder","title":"

A Simple E-Mail Reminder System Based on cron and at

\n","content_html":"<h1 id="a-simple-e-mail-reminder-system-based-on-cron-and-at">A Simple E-Mail Reminder System Based on cron and at</h1>\n\n<p>2023-02-10</p>\n\n<p>Since I cannot keep everything I have to remember in my head, I need a reminder\nsystem. While I would prefer an analog system (ideally one that integrates with\nmy system for keeping track of tasks), I have not found a satisfying analog\nsolution so far.</p>\n\n<p>I am not looking for a full-fledged calendar system. If I were, I would be using\n<a href="https://www.roaringpenguin.com/products/remind">Remind</a> or <code>calendar</code>.<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup> But\nthey offer way more features than I need.</p>\n\n<p>I basically have two requirements for my reminder system:</p>\n\n<ul>\n <li>It has to remind me reliably by e-mail about things a certain time in advance.</li>\n <li>It has to be simple and have as few external dependencies as possible.</li>\n</ul>\n\n<p>The solution I have come up with is almost too trivial to share: It employs\n<code>cron</code> and <code>at</code> to schedule reminders, which are sent as e-mails via a remote\nSMTP server when they are due.</p>\n\n<h2 id="the-setup">The Setup</h2>\n\n<p>The system depends on the following ingredients:</p>\n\n<ul>\n <li>A machine which is up 24/7 – for scheduling reminders for arbitrary\ntimes.<sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">2</a></sup> I am using a server hosted on <a href="https://openbsd.amsterdam/">OpenBSD\nAmsterdam</a>.</li>\n <li><code>smtpd</code> – for <a href="/smtpd-relay/">relaying e-mails to a remote SMTP server</a>.</li>\n <li><code>cron</code> – for scheduling recurring reminders (like birthdays).</li>\n <li><code>at</code> – for scheduling nonrecurring reminders (like one-time events, or events\nwhich recur in irregular intervals).</li>\n <li><code>mail</code> – for sending e-mails non-interactively.</li>\n</ul>\n\n<p>On <a href="https://www.openbsd.org/">OpenBSD</a>, all the required software is part of the\nbase system; see <a href="https://man.openbsd.org/smtpd.8">smtpd(8)</a>,\n<a href="https://man.openbsd.org/cron.8">cron(8)</a>,\n<a href="https://man.openbsd.org/at.1">at(1)</a>,\n<a href="https://man.openbsd.org/mail.1">mail(1)</a>.</p>\n\n<p>Both <code>cron</code> and <code>at</code> basically take two kinds of data as input: A timestamp\nwhich specifies <em>when</em> something is to be done, and an action which specifies\n<em>what</em> is to be done at the specified time.</p>\n\n<p>Regardless of whether a reminder is recurring or nonrecurring, I want an e-mail\nto be sent to me at the specified time. Therefore, the action in both cases is\nsending an e-mail to me reminding me of the given event. Since the e-mail needs\nto be sent non-interactively when the given time is reached, the <code>mail</code> utility\nis invoked, and the reminder text is passed to it as the mail subject (since\nthey are usually short, I only specify a subject and leave the body empty; then\nI don’t even have to open the e-mail).</p>\n\n<p>In order not to have to specify the non-changing details (like the e-mail\naddress) for sending the mail each time, I employ a small script called\n<code>mailrem</code> which is basically a wrapper around <code>mail</code> which takes the reminder\ntext as its argument:</p>\n\n<pre><code>#!/bin/sh\n\nfrom="John Doe &lt;john.doe@email.com&gt;"\nsubject="$1"\n\necho | mail -r "$from" -s "$subject" "$from"\n</code></pre>\n\n<p>Finally, in order for <code>mail</code> to be able to send mails to a remote SMTP server,\n<code>smtpd</code> needs to be <a href="/smtpd-relay/">configured such that it relays outgoing mail to a remote\nserver</a>.</p>\n\n<h2 id="usage">Usage</h2>\n\n<p>E-mail reminders are sent by calling <code>mailrem</code> with the specific reminder text\nas its argument, e.g.</p>\n\n<pre><code>$ mailrem "Prepare tax statement"\n</code></pre>\n\n<p>In order to schedule reminders for a specific time, <code>mailrem</code> is not invoked\ndirectly as above, but either by <code>cron</code> or by <code>at</code>, depending on whether the\nreminder is to be sent on a regular basis or just once.</p>\n\n<h3 id="recurring-reminders">Recurring reminders</h3>\n\n<p>Recurring reminders are scheduled by <code>cron</code> via corresponding crontab entries.\nStart editing the crontab file:</p>\n\n<pre><code>$ crontab -e\n</code></pre>\n\n<p>Then add an entry for each recurring reminder like this:</p>\n\n<pre><code>0 0 3 18 * $HOME/bin/mailrem "[Reminder] Paul's $(( $(/bin/date +\\%Y) - 1976 )). birthday (1976)"\n</code></pre>\n\n<p>This entry would send an e-mail each year at midnight on March 18 with subject\n“[Reminder] Paul’s <em>n</em>. birthday (1976)”, where <em>n</em> is calculated each time\nthe cron entry is triggered by subtracting Paul’s year of birth, 1976, from the\ncurrent year obtained by the <code>date</code> utility.<sup id="fnref:3"><a href="#fn:3" class="footnote" rel="footnote" role="doc-noteref">3</a></sup></p>\n\n<h3 id="nonrecurring-reminders">Nonrecurring reminders</h3>\n\n<p>Nonrecurring reminders are scheduled by <code>at</code> via corresponding atjobs. For\ninstance, to schedule an atjob for midnight in three days:</p>\n\n<pre><code>$ at midnight + 3 days\n</code></pre>\n\n<p>When prompted, enter the action to be executed at the specified time like this:</p>\n\n<pre><code>&gt; mailrem "[Reminder] Doctor's appointment at 9 am"\n</code></pre>\n\n<p>Then, press <code>&lt;Ctrl&gt; + D</code> to queue the atjob.</p>\n\n<p>That’s it. A very simple system which does its job and is easy to setup and\nmaintain.</p>\n\n<h2 id="caveats">Caveats</h2>\n\n<ul>\n <li>The system is certainly not suitable for time-critical reminders. This is\nobvious, since by nature the reminders are sent in an asynchroneous way (i.e.\nvia e-mail).</li>\n <li>There is no easy way to get a consolidated overview over all currently\nscheduled reminders. For recurring reminders, <code>crontab -l</code> could be used.\nSimilarly, <code>atq</code> displays the queue of atjobs. However, the output of <code>atq</code> is\npretty much unparseable (at least in the version which ships with OpenBSD). So\none would have to manually extract the job ID from the output of <code>atq</code> and\nthen do <code>$ at -c &lt;id&gt;</code> in order to see the content of the job.</li>\n <li>Failures cannot easily be discovered in general, and there is no recovery\nmechanism. If, e.g., for some reason the <code>cron</code> daemon is not running at the\ntime a reminder is due, it will not be sent and will subsequently be lost\nforever.</li>\n</ul>\n\n<hr />\n\n<div class="footnotes" role="doc-endnotes">\n <ol>\n <li id="fn:1">\n <p>Man page of the OpenBSD version:\n<a href="https://man.openbsd.org/calendar.1">calendar(1)</a> <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>\n </li>\n <li id="fn:2">\n <p>In principle, of course, it is also possible to run the system on a\nlaptop. The severe drawback would be that reminders were lost if the laptop\nwere not running at the scheduled time of a reminder. One could use tools\nlike anacron instead of cron. This would mitigate the risk of losing\nreminders, but the time they are sent would then depend on when the laptop\nis running (which may differ greatly from the intended time of sending). <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>\n </li>\n <li id="fn:3">\n <p>Man page of the OpenBSD version:\n<a href="https://man.openbsd.org/date.1">date(1)</a>. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>\n </li>\n </ol>\n</div>\n","url":"https://thorstenzoeller.com/mail-reminder","date_published":"2023-02-10","date_modified":"2023-02-10"},{"id":"https://thorstenzoeller.com/new","title":"

My New Website

\n","content_html":"<h1 id="my-new-website">My New Website</h1>\n\n<p>2021-06-20</p>\n\n<p>Not long ago, I created my first website. It was a static website, just like\nthis one. I wrote the content in AsciiDoc and created a small script which\nrendered the pages to HTML.</p>\n\n<p>I was very proud of it.</p>\n\n<p>The content was basically plain text with a little bit of markup and some meta\ndata – a beautifully clear separation of form and content.</p>\n\n<p>The script generating the site consisted of about 200 lines of Ruby code. It was\nsimple, and it did its job.</p>\n\n<p>But it turned out that I would spend far more time tweaking the script to\ngenerate the site than to write content. After all, it was easier and more fun\nthan to think about what to write.</p>\n\n<p>Also, the barrier to publish was too high: There were always a few steps to be\ndone before any change could be published. Not many steps, really: Make some\nchange, run the script, clone the respository for the site, delete its content,\ncopy the output of the script to the repository, commit and publish it.</p>\n\n<p>Yet too many, as it turned out.</p>\n\n<p>So I ditched the script for generating the site and started anew.</p>\n\n<p>This time, it’s just plain HTML. Everything is created manually. Sounds like\nmore work, but it’s not. It’s a profound simplification.</p>\n\n<p>This approach has its drawbacks, of course. The content is interspersed with\nmarkup – HTML is not really lightweight. It is not possible to make a change in\nthe template which is immediately reflected in all pages using this template.</p>\n\n<p>But it’s definitely worth it.</p>\n\n<p>I thought my site was simple, but it wasn’t. Or at least not simple enough.</p>\n\n<p>Lesson learned.</p>\n","url":"https://thorstenzoeller.com/new","date_published":"2021-06-20","date_modified":"2021-06-20"},{"id":"https://thorstenzoeller.com/pretended-intentionality","title":"

Pretended Intentionality

\n","content_html":"<h1 id="pretended-intentionality">Pretended Intentionality</h1>\n\n<p>2021-10-21</p>\n\n<p>I have recently become aware of an interesting – and somewhat concerning\n– behavior of mine in relation to my phone: In those spare moments when I\nam waiting for something, for instance, and the inevitable compulsion to check\nmy phone arises, I often do manage to resist that urge. But after that first\nlittle victory over myself, something interesting happens: My mind, unable to\naccept that it is denied the diversion it so much craves, is trying to come up\nwith suggestions for things that would be worth doing with my phone while\nwaiting:<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup></p>\n\n<p><em>What was it again that makes Ridge A such a special place? Now would be a good\ntime to head over to Wikipedia and check it out – after all, there is not\nmuch else you can do right now anyway!</em></p>\n\n<p><em>Which city in the world has the longest subway system, actually? Well, why not\nfigure it out quickly?</em></p>\n\n<p><em>Let’s check openbsd.org to find out whether the new OpenBSD release is already\navailable.</em></p>\n\n<p>My mind <em>knows</em> that I am trying to control myself in order not to compusively\ncheck my phone for no obvious reason whatsoever. And therefore, recognizing that\njust letting things run will not suffice this time, it becomes creative: Knowing\nthat I am trying hard to act intentionally instead of compulsively and\nreflexive, it <em>makes me believe that I do in fact act intentionally</em> by\nrationalizing using my phone.</p>\n\n<p>And thus my mind gets hold of me. It’s the monkey mind at work. But just like a\nreal monkey, it is not just jumping around like crazy; it is also very clever\nand inventive.</p>\n\n<p>What is so perfidious about it is that my mind is tricking me into the very\nbehavior I am trying to avoid by <em>convincing me that I am in fact avoiding it</em>.\nYet, this is all just another, albeit clever, strategy of my mind to run away\nfrom the slightest sign of boredom and instead indulge in distractions; that\neverlasting endeavor of the mind of not having to cope with the truly important\nthings in life – or, at the least, of not having to <a href="https://zenhabits.net/alone/">sit alone in a quiet empty\nroom</a>.</p>\n\n<p>The good thing is: Once you become aware of something you want to change, it\nbecomes possible to actually change it.</p>\n\n<hr />\n\n<div class="footnotes" role="doc-endnotes">\n <ol>\n <li id="fn:1">\n <p>I am mostly using the terms <em>me</em> and <em>my mind</em> here to refer to the\nconscious and subconscious parts of myself, respectively. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>\n </li>\n </ol>\n</div>\n","url":"https://thorstenzoeller.com/pretended-intentionality","date_published":"2021-10-21","date_modified":"2021-10-21"},{"id":"https://thorstenzoeller.com/rainloop-on-openbsd","title":"

Installation and Setup of the RainLoop Webmail Client on OpenBSD

\n","content_html":"<h1 id="installation-and-setup-of-the-rainloop-webmail-client-on-openbsd">Installation and Setup of the RainLoop Webmail Client on OpenBSD</h1>\n\n<p>2021-12-22</p>\n\n<p><a href="https://www.rainloop.net/">Rainloop</a> is a modern, simple and rather lightweight\nwebmail client. This article describes its installation and setup on a local\nOpenBSD machine and the configuration necessary for accessing a\n<a href="https://posteo.de/en">Posteo</a> e-mail account.</p>\n\n<p>Tested with OpenBSD 6.9, PHP 8.0 and RainLoop 1.16.0.</p>\n\n<h2 id="prerequisites">Prerequisites</h2>\n\n<p>On a default OpenBSD installation, only a few things are required in order to\nget RainLoop set up and running:</p>\n\n<ul>\n <li><strong>Web server</strong>. Since we are on OpenBSD, we will be using\n<a href="https://man.openbsd.org/httpd.8">httpd(8)</a>.</li>\n <li><strong>PHP</strong>. In addition to the extensions contained in the base installation,\nonly PHP-cURL is required, and optionally PHP-PDO for contacts.</li>\n</ul>\n\n<p>No database is required for the core functionality; it is only needed for\nstoring contacts, which is optional.</p>\n\n<h2 id="installation-and-setup">Installation and Setup</h2>\n\n<h3 id="httpd">httpd</h3>\n\n<p>Create an entry in <code>/etc/httpd.conf</code> for a HTTP server listening on\n<code>localhost:8080</code> (of course, any other port can be specified):</p>\n\n<pre><code>server "default" {\n listen on "127.0.0.1" port 8080\n log {\n access "default-access.log"\n error "default-error.log"\n }\n root "/rainloop"\n directory index index.php\n location "/data/*" { block }\n location "*.php" {\n fastcgi socket "/run/php-fpm.sock"\n }\n}\n</code></pre>\n\n<p>Here, it is assumed that RainLoop will be installed in <code>/var/www/rainloop</code>,\nwhich therefore needs to be set as the document root for the server. Also, web\naccess to the <code>data</code> subdirectory must be blocked.</p>\n\n<p>Start <a href="https://man.openbsd.org/httpd.8">httpd(8)</a> unless it is already running:</p>\n\n<pre><code>$ doas rcctl enable httpd\n$ doas rcctl start httpd\n</code></pre>\n\n<p>Otherwise, simply restart it:</p>\n\n<pre><code>$ doas rcctl restart httpd\n</code></pre>\n\n<h3 id="php">PHP</h3>\n\n<p>Install <a href="https://man.openbsd.org/php.1">php(1)</a> unless already done:</p>\n\n<pre><code>$ doas pkg_add php\n</code></pre>\n\n<p>Start the PHP FastCGI Process Manager (PHP-FPM):</p>\n\n<pre><code>$ doas rcctl enable php80_fpm\n$ doas rcctl start php80_fpm\n</code></pre>\n\n<p>Install the PHP-cURL extension and make it known to PHP:</p>\n\n<pre><code>$ doas pkg_add php-curl\n$ doas ln -sf /etc/php-8.0.sample/curl.ini /etc/php-8.0/\n</code></pre>\n\n<p>Optionally, install the corresponding PHP-PDO extension for the database to be\nused (in this case SQLite; other options are MySQL and PostgreSQL) and make it\nknown to PHP:</p>\n\n<pre><code>$ doas pkg_add php-pdo_sqlite\n$ doas ln -sf /etc/php-8.0.sample/pdo_sqlite.ini /etc/php-8.0/\n</code></pre>\n\n<h3 id="rainloop">RainLoop</h3>\n\n<p>Create a directory for RainLoop under <code>/var/www</code>:</p>\n\n<pre><code>$ doas mkdir /var/www/rainloop\n</code></pre>\n\n<p>Get the latest version of the <a href="https://www.rainloop.net/repository/webmail/rainloop-community-latest.zip">RainLoop Community\nedition</a>\nand unzip it in <code>/var/www/rainloop</code>:</p>\n\n<pre><code>$ doas mkdir /var/www/rainloop\n$ cd /var/www/rainloop\n$ doas ftp https://www.rainloop.net/repository/webmail/rainloop-community-latest.zip\n$ doas unzip rainloop-community-latest.zip\n$ doas rm rainloop-community-latest.zip\n</code></pre>\n\n<p>Set the owner of the <code>data</code> subdirectory to <code>www</code>:</p>\n\n<pre><code>$ doas chown -R www data\n</code></pre>\n\n<p>Finally, copy <code>/etc/resolv.conf</code> to <code>/var/www</code> (otherwise, the domain names of\nthe mail servers may not get resolved to their corresponding IP addresses):</p>\n\n<pre><code>$ mkdir -p /var/www/etc\n$ doas cp /etc/resolv.conf /var/www/etc/resolv.conf\n</code></pre>\n\n<p>RainLoop can then be accessed via the URL <code>localhost:8080</code>, and it can be\nconfigured in the admin panel which can be accessed via <code>localhost:8080?admin</code>.</p>\n\n<h3 id="accessing-a-posteo-e-mail-account">Accessing a Posteo E-Mail Account</h3>\n\n<p>Access to a <a href="https://posteo.de/en">Posteo</a> e-mail account can be set up by\ncreating the file\n<code>/var/www/rainloop/data/_data_/_default_/domains/posteo.de.ini</code> with the\nfollowing contents:</p>\n\n<pre><code>imap_host = "posteo.de"\nimap_port = 993\nimap_secure = "SSL"\nimap_short_login = Off\nsieve_use = Off\nsieve_allow_raw = Off\nsieve_host = ""\nsieve_port = 4190\nsieve_secure = "None"\nsmtp_host = "posteo.de"\nsmtp_port = 587\nsmtp_secure = "TLS"\nsmtp_short_login = Off\nsmtp_auth = On\nsmtp_php_mail = Off\n</code></pre>\n\n<p>Alternatively, the account can be set up via the admin panel.</p>\n\n<h2 id="references">References</h2>\n\n<ul>\n <li><a href="https://www.rainloop.net/docs/">Documentation on the RainLoop website</a></li>\n <li><a href="https://dev.to/nabbisen/rainloop-webmail-on-openbsd-installation-1hfg">Rainloop Webmail on OpenBSD:\nInstallation</a></li>\n <li><a href="https://brank.me/rainloop-OpenBSD.html">Rainloop And OpenBSD</a></li>\n</ul>\n","url":"https://thorstenzoeller.com/rainloop-on-openbsd","date_published":"2021-12-22","date_modified":"2021-12-22"},{"id":"https://thorstenzoeller.com/screenshots-on-openbsd","title":"

Taking Screenshots on OpenBSD

\n","content_html":"<h1 id="taking-screenshots-on-openbsd">Taking Screenshots on OpenBSD</h1>\n\n<p>2022-01-30</p>\n\n<p>I rarely need to take screenshots, but occasionally it is convenient to be able\nto do so. The method described here uses\n<a href="https://github.com/naelstrof/maim">maim</a>,\n<a href="https://man.openbsd.org/cwm.1">cwm(1)</a> and\n<a href="https://man.openbsd.org/ksh.1">ksh(1)</a>. I use it on OpenBSD, but it should work\nin a very similar way on all Unix-like operating systems.</p>\n\n<p>Here is how it works:</p>\n\n<h2 id="preparation">Preparation</h2>\n\n<p>Install <code>maim</code>:</p>\n\n<pre><code>$ doas pkg_add maim\n</code></pre>\n\n<p>Create a script with the following content and save it to <code>~/bin/screenshot</code>\n(assuming <code>~/bin</code> is in the user’s <code>PATH</code>):</p>\n\n<pre><code>#!/bin/sh\n\nmaim -s | xclip -selection clipboard -t image/png\n</code></pre>\n\n<p>All this script does is invoking <code>maim</code> to prompt the user to select the region\nof the screen he wants to take a screenshot of, upon which <code>maim</code> will create a\nPNG image of the region, which is then copied to the clipboard.</p>\n\n<p>Make the script executable:</p>\n\n<pre><code>$ cd ~/bin\n$ chmod u+x screenshot\n</code></pre>\n\n<p>Define a keybinding in <code>~/.cwmrc</code> for invoking <code>screenshot</code> via the key\ncombination <code>&lt;Alt&gt; + s</code> (of course, any other combination works as well):</p>\n\n<pre><code>bind-key M-s "bin/screenshot"\n</code></pre>\n\n<p>Define an alias in <code>~/.kshrc</code> for pasting the image from the clipboard to a\nfile:</p>\n\n<pre><code>alias clip2file='xclip -selection clipboard -o &gt;'\n</code></pre>\n\n<p>That’s it.</p>\n\n<h2 id="taking-a-screenshot">Taking a Screenshot</h2>\n\n<p>Then, to take a screenshot, do the following:</p>\n\n<ol>\n <li>\n <p>Press <code>&lt;Alt&gt; + s</code>.</p>\n </li>\n <li>\n <p>Select the region of the screen you want to take a screenshot of.</p>\n </li>\n <li>\n <p>Go to a terminal and type:</p>\n\n <pre><code>$ clip2file &lt;file&gt;.png\n</code></pre>\n </li>\n</ol>\n\n<p>The resulting screenshot will be saved to <code>&lt;file&gt;.png</code>.</p>\n\n<h2 id="see-also">See Also</h2>\n\n<ul>\n <li><a href="https://romanzolotarev.com/bin/screenshot">Another script</a> for taking\nscreenshots by <a href="https://romanzolotarev.com/">Roman Zolotarev</a>.</li>\n <li><a href="https://dataswamp.org/~solene/2021-07-19-simple-scripts.html#_Screenshot_of_a_region_and_upload">Another\nscript</a>\nfor taking screenshots by <a href="https://dataswamp.org/~solene/">Solène Rapenne</a>.</li>\n</ul>\n","url":"https://thorstenzoeller.com/screenshots-on-openbsd","date_published":"2022-01-30","date_modified":"2022-01-30"},{"id":"https://thorstenzoeller.com/sivers-how-to-live","title":"

Derek Sivers: “How to Live”

\n","content_html":"<h1 id="derek-sivers-how-to-live">Derek Sivers: “How to Live”</h1>\n\n<p>2023-03-05</p>\n\n<p>To state it upfront: <a href="https://sive.rs/h">How to Live</a> is a book which can hardly\nbe overrated. It is full of wisdom, packed even more densely with insights than\nDereks’ previous writings.</p>\n\n<p>The title of the book asks one of the most important questions of life – maybe\nthe single most important one –, and it implies that the book sets out to\nanswer this question.</p>\n\n<p>Instead of answering the titles’ question, however, the book presents us with\n<em>twenty-one</em> ways how to live. Each of the 21 short chapters explains how to\nlive a life according to a certain guiding principle. It describes how to live\nin complete accordance with that principle, to adhere to it with the utmost\nconsequence.</p>\n\n<p>But: All of the 21 ways to live are completely incompatible with each other, due\nto their conflicting guiding principles.</p>\n\n<p>So does this book answer the question posed in its title? No. Instead, it\npresents possibilities. Every single chapter is convincing and persuading, yet\nevery one is completely different than any other.</p>\n\n<p>To me, the core statement of this book is that there are no definite answers, at\nleast not to the really important questions of life. We humans yearn for\nanswers, for recipes, for certainty – yet at some point, everybody has to face\nthe fact that there are no simple, universal answers to the truly important\nquestions. Life is contradictory, often messy, rarely proceeding along a\nstraight line. And, most important: Each life is absolutely individual, and\neveryone has to find his own answers.</p>\n\n<p>Just as remarkable as the books’ content is its form. It is incredibly dense.\nDerek somehow manages to picture the different ways to live in often not more\nthan three or four pages. Most sentences are very short, often fitting on a\nsingle line, and new sentences always start on the next line. His writing is\nnever pleasing, but always sharp and to the point, and with “How to Live” he has\nperfected his style. To me, it is supremely elegant.</p>\n\n<p>Two quotes come to my mind when thinking of “How to Live”:</p>\n\n<p>“Perfection is achieved, not when there is nothing more to add, but when there\nis nothing left to take away.” by Antoine de Saint-Exupéry. It seems to me that\nthis was Dereks’ personal guiding principle in writing this book.</p>\n\n<p>The second one is by Michelangelo: “The sculpture is already complete within the\nmarble block, before I start my work. It is already there, I just have to chisel\naway the superfluous material.” I can imagine how Derek spent hours and hours\nchiseling away the superfluous words, finally achieving something which comes\nvery close to the perfection as it is defined in the quote by Antoine de\nSaint-Exupéry above.</p>\n\n<p>Making a point using many words is easy; making a point using very few words is\nexceedingly difficult. Derek has succeeded in every aspect.</p>\n\n<p>If you have not read the book yet, buy it and read it, immediately. Then, after\nsome time, read it again, and again.</p>\n","url":"https://thorstenzoeller.com/sivers-how-to-live","date_published":"2023-03-05","date_modified":"2023-03-05"},{"id":"https://thorstenzoeller.com/sivers-useful-not-true","title":"

Derek Sivers: “Useful Not True”

\n","content_html":"<h1 id="derek-sivers-useful-not-true">Derek Sivers: “Useful Not True”</h1>\n\n<p>2025-07-06</p>\n\n<p><a href="https://sive.rs/u">Useful Not True</a> is another gem by Derek Sivers. Whenever he\npublishes a new book, I order it immediately, no matter what it is about. I know\nfrom experience that everything he writes is packed with wisdom and insights I\ndon’t want to miss.</p>\n\n<p>Let me start with the form of the book (I am referring to its physical version\nhere): It is short, as Derek’s books usually are. Most chapters are one or two\npages at most, very few are longer. The font size is pretty large, as well as\nthe distance between lines, and the lines are rather narrow, which makes the\nreading a very pleasant experience. This is in contrast to many other books\nwhich look as if they were laid out with the goal to pack as many words as\npossible on each page. With Derek’s books, it is the exact opposite, with\nrespect to both form and content: They look as if the goal was to use as <em>few</em>\nwords as possible (and it was!). They are a perfect example for James Altuchers’\nmaxim “<del>To</del> increase the value of <del>your</del> words, make them\n<del>as</del> few <del>as possible</del>.”</p>\n\n<p>The content of the book perfectly matches its form: It is distilled to the bare\nminimum of what is necessary to convey its point. Nothing is superfluous; every\nword serves a purpose. One could certainly easily inflate the books’ content to\n1000 pages, but it would not be possible to reduce it to fewer pages without\nlosing content.</p>\n\n<p><em>Useful Not True</em> is a book about perspective. Everything is relative; nothing\nis absolute. There is no “right” or “wrong”, just “useful” or “useless”. While\nreading it, so many associations popped up in my mind:</p>\n\n<p>To Zen Buddhism with its belief that everything is made up by the mind alone and\nits seeking for looking at things as how they are, without making up things\nabout them in our mind.</p>\n\n<p>To phenomenology and its concept of <em>epoché</em> (and similar concepts in Stoicism\nand other philosophies), a method for refraining from subjective judgements of\nthings or situations.</p>\n\n<p>And even to physics and mathematics, in different aspects: In gauge theories,\nthere are intrinsic unphysical degrees of freedom. By fixing the gauge, those\nunphysical degrees of freedom can be removed. And this can be done in different\nways, depending on what is most useful in the respective situation.</p>\n\n<p>Also, physical theories are formulated as models which describe (physical)\nreality. They never do it perfectly, though, because they cannot capture every\naspect of reality. And yet, good models are extremely useful (and a good model\nis not necessarily one that describes reality most accurately; it may be\nperfectly sufficient to describe a very particular aspect of reality with a\ncertain coarseness if it still captures the relevant physical mechanisms). As\nGeorge E. P. Box put it: “Essentially, all models are wrong, but some are\nuseful.”</p>\n\n<p>The importance of the book lies in the fact that, while its statement seems\nperfectly plausible, we very often tend to ignore it. Ask two people standing\nopposite each other where the river is. The one says: “On the left.” The other\nsays: “On the right.” Who is right? It is remarkable how firm our belief is that\nthere is “right” and “wrong”, while it is so obvious that this is usually not\ntrue, if we just looked at things as they are. While the consequences may be\ntrivial as in the example above, they can be arbitrarily grave in other\nsituations.</p>\n\n<p>So, on the one hand, recognizing there are no absolutes can prevent us from\nmaking mistakes in judging situations. But there is another aspect, which is\nhinted at in the title of the book: We can turn this realization to our\nadvantage. You can face a wall, or you can turn around and look at a serene\nbeach. Both perspectives are “right” or valid. Why not choose the one you like\nbetter? There lies power in not being confronted with the one “true”\nperspective, but instead being able to choose ones preferred perspective, and\nthis power can be harnessed – provided we know that we can simply turn around.</p>\n\n<p>I will end with my usual recommendation of Derek’s books: Buy it, read it, and\ndigest its content as fully as possible! It is worth every word.</p>\n","url":"https://thorstenzoeller.com/sivers-useful-not-true","date_published":"2025-07-06","date_modified":"2025-07-06"},{"id":"https://thorstenzoeller.com/smtpd-relay","title":"

Relay Mail to a Remote SMTP Server With smtpd

\n","content_html":"<h1 id="relay-mail-to-a-remote-smtp-server-with-smtpd">Relay Mail to a Remote SMTP Server With <code>smtpd</code></h1>\n\n<p>2022-03-27</p>\n\n<p>Configure <a href="https://man.openbsd.org/smtpd.8">smtpd(8)</a> to relay outgoing mail to\na remote SMTP server as follows:</p>\n\n<p>Create the file <code>/etc/mail/secrets</code>:</p>\n\n<pre><code>$ doas touch /etc/mail/secrets\n$ doas chmod 640 /etc/mail/secrets\n$ doas chown root:_smtpd /etc/mail/secrets\n$ doas echo "label username:password" &gt; /etc/mail/secrets\n</code></pre>\n\n<p><code>username</code> and <code>password</code> are the credentials for accessing the remote SMTP\nserver, and <code>label</code> is an identifier for the username-password combination. It\ncan be chosen arbitrarily and is used in <code>smtpd.conf</code> (see below). Since the\ncredentials are stored in plain text, restrictive permissions are set for the\n<code>secrets</code> file.</p>\n\n<p>Replace the default content of <code>/etc/mail/smtpd.conf</code> with the following:</p>\n\n<pre><code>table aliases file:/etc/mail/aliases\ntable secrets file:/etc/mail/secrets\n\nlisten on lo0\n\naction "local" mbox alias &lt;aliases&gt;\naction "relay" relay host smtp+tls://label@smtp-server:port auth &lt;secrets&gt;\n\nmatch for local action "local"\nmatch for any action "relay"\n</code></pre>\n\n<p><code>label</code> is the corresponding label from the <code>secrets</code> file, <code>smtp-server</code> is the\nURL of the remote SMTP server, and <code>port</code> is the mail submission port (default:\n587).</p>\n\n<p>Verify that the configuration is syntactically correct:</p>\n\n<pre><code>$ doas smtpd -n\n</code></pre>\n\n<p><code>smtpd</code> will answer with:</p>\n\n<pre><code>configuration OK\n</code></pre>\n\n<p>Restart <code>smtpd</code>:</p>\n\n<pre><code>$ doas rcctl restart smtpd\n</code></pre>\n\n<p><code>smtpd</code> will answer with:</p>\n\n<pre><code>smtpd(ok)\nsmtpd(ok)\n</code></pre>\n\n<p>Test the configuration by sending an e-mail using\n<a href="https://man.openbsd.org/mail">mail(1)</a>:</p>\n\n<pre><code>$ echo "This is a test" | mail -s "Test" mail@example.com\n</code></pre>\n\n<h2 id="references">References</h2>\n\n<ul>\n <li><a href="https://man.openbsd.org/smtpd.conf">smtpd.conf(5)</a></li>\n <li><a href="https://rgz.ee/openbsd/smtpd-forward.html">Forward outgoing mail to a remote SMTP\nserver</a> by Roman Zolotarev.</li>\n</ul>\n","url":"https://thorstenzoeller.com/smtpd-relay","date_published":"2022-03-27","date_modified":"2022-03-27"},{"id":"https://thorstenzoeller.com/xterm-sel","title":"

Multiple-Click Selections in xterm

\n","content_html":"<h1 id="multiple-click-selections-in-xterm">Multiple-Click Selections in xterm</h1>\n\n<p>2022-02-12</p>\n\n<p>It is possible to configure in detail which portion of the screen – a word, a\nline, etc. – is selected in <a href="https://man.openbsd.org/xterm.1">xterm(1)</a> on\nrapid successive mouse clicks.</p>\n\n<h2 id="what-is-a-word-in-xterm-after-all">What is a Word in xterm, After All?</h2>\n\n<p>In <code>xterm</code>, words can be selected by double-clicking on any character in the\nrespective word. This will highlight the word, and it is then in the primary\nselection of the X Window System and can be pasted elsewhere.</p>\n\n<p>Characters are grouped into <em>character classes</em>. Words are defined in <code>xterm</code> as\nstrings of characters belonging to the same character class. Therefore, what\n<code>xterm</code> interprets as a word depends on the mapping of characters to character\nclasses.</p>\n\n<p>In the default mapping, alphanumeric characters and the underscore belong to one\ncharacter class, space and tab belong to another character class, and all other\ncharacters have their own character class. This definition works well when\ndealing mostly with prosaic texts, since it more or less corresponds to the\nusual definition of a word (i.e. certain characters separated by whitespace). In\nother cases, it is less convenient though. For instance, it is not possible to\nselect a path consisting of several directories by double-clicking on it, since\ndirectories are separated by a slash, which belongs to a different character\nclass than alphanumeric characters and the underscore.</p>\n\n<p>Interestingly, the mapping can be changed via a certain <code>xterm</code> resource called\n<code>charClass</code>. Its value is a list of key-value pairs, where the key is either a\nsingle character code or a range of character codes, and the value is a\ncharacter class. A given key-value pair then defines that the character(s)\nspecified by the key belong to the character class specified by the value.</p>\n\n<p>Character classes are identified by numbers (which in turn correspond to the\ncharacter code of a representative of that character class). The default mapping\nof characters to character classes is given in the <a href="https://man.openbsd.org/xterm.1#CHARACTER_CLASSES">respective section of the\nmanpage</a>. In the default\nmapping, alphanumeric characters and the underscore belong to character class 48\n(the character code of the character <code>0</code>), and space and tab belong to character\nclass 32 (the character class of <code>space</code>).</p>\n\n<p>Therefore, in order to add e.g. the characters <code>!</code> (character code 33) and <code>:</code>\n(character code 58) to character class 48, add the following line to\n<code>~/.Xresources</code>:</p>\n\n<pre><code>xterm*charClass: 33:48,58:48\n</code></pre>\n\n<p>To add all “regular” characters to character class 48, add the following line to\n<code>~/.Xresources</code>:</p>\n\n<pre><code>xterm*charClass: 33-126:48\n</code></pre>\n\n<p>Activate the change:</p>\n\n<pre><code>$ xrdb -merge ~/.Xresources\n</code></pre>\n\n<h2 id="xterm-knows-more-than-just-words">xterm Knows More Than Just Words</h2>\n\n<p>Words are just one kind of character grouping in <code>xterm</code>. The full list is:</p>\n\n<dl>\n <dt><code>word</code></dt>\n <dd>As defined above.</dd>\n <dt><code>line</code></dt>\n <dd>The entire line to which the character under the pointer belongs to.</dd>\n <dt><code>group</code></dt>\n <dd>Basically the paragraph the character under the pointer belongs to,\ni.e. all lines above and below up to the next blank line. Does not extend\noutside the current page.</dd>\n <dt><code>page</code></dt>\n <dd>All visible lines on the current page.</dd>\n <dt><code>all</code></dt>\n <dd>All lines, including i.e. saved lines.</dd>\n</dl>\n\n<p>Even that is not all there is, though. On top of that, it is even possible to\ndefine custom groupings via regular expressions (basically, all other predefined\ngroupings are just shortcuts; they could just as well be defined via a\ncorresponding regular expression). Also, there is the pseudo-grouping <code>none</code>\nwhich specifies that no selection should occur in the respective case.</p>\n\n<p>So it is possible to specify in a very fine-grained way what will be in the\nprimary selection when double-clicking on some character. But it can be\nspecified just as well what happens when clicking multiple (i.e. more than two)\ntimes in rapid succession. This is useful since one may be interested in\nselecting different character groupings depending on the respective case. For\ninstance, in the default configuration, triple-clicking usually selects the\nentire line. Which character grouping is selected when clicking 2, 3, 4 and 5\ntimes in rapid succession is specified by assigning one of the character\ngroupings defined above to the <code>xterm</code> resources <code>on2Clicks</code>, <code>on3Clicks</code>,\n<code>on4Clicks</code> and <code>on5Clicks</code>, respectively.</p>\n\n<p>As an example, in order to specify that double-clicking should select words\ndefined as a string consisting of alphanumeric characters, the underscore, the\nexclamation mark and the colon, that triple-clicking should select words defined\nas a string consisting of all regular characters except whitespace (defined via\na corresponding regular expression), and that clicking four times in rapid\nsuccession should select the entire line, add the following lines to\n<code>~/.Xresources</code>:</p>\n\n<pre><code>xterm*charClass: 33:48,58:48\nxterm*on2Clicks: word\nxterm*on3Clicks: regex [^[:space:]]+\nxterm*on4Clicks: line\n</code></pre>\n\n<p>Even when using the mouse sparingly, it is very convenient to be able to specify\nwhat gets selected on multiple clicks in <code>xterm</code>, and it certainly does save\nsome time.</p>\n","url":"https://thorstenzoeller.com/xterm-sel","date_published":"2022-02-12","date_modified":"2022-02-12"},{"id":"https://thorstenzoeller.com/quake-discoveries","title":"

Quake Discoveries

\n","content_html":"<h1 id="quake-discoveries">Quake Discoveries</h1>\n\n<p>2026-03-14</p>\n\n<p>Here is a question I am sometimes pondering: Can there be discoveries which\ncompletely shatter our worldview and our understanding of ourselves and the\nuniverse we live in? For lack of a better term, I will call such discoveries\n“quake discoveries” in the following.<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup></p>\n\n<p>To be clear: I am not talking about discoveries which simply <em>question</em> or\n<em>change</em> our worldview. I am talking about experiences which <em>shatter</em> it\naltogether, which break it apart irreparably and leave behind nothing but\ndebris.</p>\n\n<p>Take, for instance, the discovery of the theory of relativity, or of quantum\ntheory: These were certainly discoveries which adjusted our worldview. Suddenly,\nit was clear that the universe was completely different than we thought – at\nleast in certain aspects. Many people were probably confused, maybe even aghast\nwhen they first heard about these theories. Maybe they did not want to believe\nthem and were thinking that they could not be true. Yet, most likely, this is\nwhat happend to most people after having digested the initial shock: At the end\nof the day, they went to bed. The next day, they got up and went to work. And\nthat was it.<sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">2</a></sup></p>\n\n<p>These are not the kinds of discoveries I am talking about here. I am talking\nabout discoveries which will not allow one to just get up the next morning and\ngo to work. I am talking about discoveries which throw us out of our world, of\nour universe; discoveries which render it impossible to get up as the same\nperson as the day before. Discoveries which, from one moment to another, change\n<em>everything</em>. Discoveries after which nothing will ever be as it was.</p>\n\n<p>I am talking about discoveries which mankind has never made before, never in its\nentire history. Sure, most people were shocked and upset when they learned that\nthe sun does not revolve around the earth, that the earth is not the center of\nthe universe. But did that stop them from meeting friends, playing games,\nchatting with each other? Most likely not. Shortly after this discovery, they\nwent on with their lives as usual.<sup id="fnref:3"><a href="#fn:3" class="footnote" rel="footnote" role="doc-noteref">3</a></sup></p>\n\n<p>So, I am talking about discoveries of a whole different kind. But what could\nsuch discoveries look like? I do not know; after all, there are no examples to\nbe found in history. What I usually imagine is something like the discovery in\nthe film “The Matrix” that what people believed to be their real life was\nactually nothing but a simulation. I guess that would be a discovery which would\nnot allow you to simply get up and go to work the next day. But then, who knows?</p>\n\n<p>Possible future discoveries with respect to the nature of time or the mind might\nalso be candidates for discoveries of this kind. Then again, discoveries cannot\nbe predicted, and their <em>kind</em> or nature can be predicted even less.</p>\n\n<p>The point is this: So far, all discoveries mankind has ever made in its history\nhave at most <em>shaken</em> our worldview, leaving us back confused, but still\n<em>within</em> our universe. They may have thrown us on the floor, but they left us in\nour familiar environment. Our perspective has changed, but only momentarily.</p>\n\n<p>Quake discoveries, on the other hand, would kick us out of our universe and\ndestroy every bridge which might enable us to ever return to it. It would throw\nus into another universe altogether, into a distant and foreign place. It would\nleave us completely disoriented.</p>\n\n<p>Will we ever make such discoveries? Is that even possible, given that our direct\n<em>experience</em> and <em>perception</em> of the world can probably never be changed by any\ndiscovery whatsoever? After all, even if we found out that we live in a gigantic\nsimulation, we would still <em>feel</em> the warmth of the sun on our skin; we would\nstill get hungry and tired, and we would still have wishes and desires. And even\nif we <em>knew</em> that we live in a gigantic simulation, it would still <em>feel</em> like\nthe real world. So, can mere <em>knowledge</em> ever have these effects I am talking\nabout?</p>\n\n<p>I do not know the answer, but I find this a fascinating question.</p>\n\n<hr />\n\n<div class="footnotes" role="doc-endnotes">\n <ol>\n <li id="fn:1">\n <p>The term “disruptive discoveries” would probably sound more serious, but\ndoes not really seem appropriate for what I am talking about here. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>\n </li>\n <li id="fn:2">\n <p>Of course, many people – in particular those dealing professionally with\nthese theories – continued to deal with them and their consequences for a\nlong time and in many cases even fought hard fights within themselves before\nthey were able to accept them. I doubt, however, that any of those people\nperceived these discoveries as existential threats to their worldviews. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>\n </li>\n <li id="fn:3">\n <p>With the exception of those who felt threatened by those discoveries and\ntried to forcefully hide or miscredit them, of course. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>\n </li>\n </ol>\n</div>\n","url":"https://thorstenzoeller.com/quake-discoveries","date_published":"2026-03-14","date_modified":"2026-03-14"},{"id":"https://thorstenzoeller.com/vim-and-pkm","title":"

Vim and PKM

\n","content_html":"<h1 id="vim-and-pkm">Vim and PKM</h1>\n\n<p>2026-04-30</p>\n\n<p>First things first: It is a pleasure to once again participate in a <a href="https://lazybea.rs/carnivals/">Vim\nCarnival</a>, created and hosted by the fabulous\n<a href="https://lazybea.rs">Hyde</a>.</p>\n\n<p>Though the topic of the <a href="https://lazybea.rs/vim-carnival-202604/">Vim Carnival - April\n2026</a> is: “How do you use Neovim/Vim to\nbuild your knowledge management?”, let me state upfront: This article is going\nto be more about personal knowledge management (PKM) than about Vim. After all,\nVim is “just” an editor, which is <em>per se</em> agnostic to what it is employed for\n– be it writing todo lists, emails, books, doing PKM or whatever. So honestly,\nI am somewhat stretching the idea of the <em>Vim Carnival</em> with this contribution.\nFor the short (and maybe a bit disappointing) answer to the above prompt, you\ncan jump directly to the section <a href="#and-what-about-vim">And what about Vim?</a> at\nthe very end.</p>\n\n<p>A short note regarding terminology: In this article I will use “Vim” as a\nplaceholder for vi-like editors in general. In particular, it includes both\n<a href="https://www.vim.org/">Vim</a> and <a href="https://neovim.io/">Neovim</a>, but even plain\nvi<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup>.</p>\n\n<h2 id="a-short-preface">A short preface</h2>\n\n<p>Actually, this Vim carnival is a welcome prompt for a subject I intended to\nwrite about since a long time, but never came around to doing: That is, how I do\nPKM.</p>\n\n<p>I won’t delve into the “theory” of PKM in any detail here. There is a lot to say\nabout PKM, and a lot has already been said about it in the past and will be said\nabout it in the future (and I am no expert at all in this matter). The risk in\nwriting an article like this one is to completely get lost in the many aspects\nand facets of PKM. So I deliberately try <em>not</em> to let that happen and will focus\non very few aspects – mostly on the technical implementation of my PKM system\n– in the hope of not ending up with a complete mess of an article.</p>\n\n<p>So, here we go…</p>\n\n<h2 id="pkm-on-a-computer">PKM on a computer</h2>\n\n<p>I have long dabbled with the challenge of PKM (long before I even knew a term\nexisted for it and a large and active community has developed around it) – that\nis the challenge of how to manage knowledge (i.e. not just to store it, but to\nactively use it and engange with it in a meaningful way): Be it storing ideas\nfor later reference, short notes, how-tos, trivia, inspirational quotes or\nwhatever one considers worth remembering or needs to remember.</p>\n\n<p>While implementing an analog PKM system (i.e. a system not relying on a\ncomputer) is very well possible – after all, people have been doing it for\nhundreds if not thousands of years –, the advent of computers has certainly\nopened up new possibilites, like organizing documents in different fashions,\nsearching in them and filtering them according to certain criteria. I will not\ndiscuss the advantages and disadvantages of analog and digital forms of PKM here\nand instead, without further explanation, focus on digital PKM systems from here\non.<sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">2</a></sup></p>\n\n<p>The question then is: How to implement a PKM system on a computer? While\ndedicated tools – from simple to highly sophisticated and complex – abound, I\nhave always had a certain aversion to them. I guess it stems from the fact that\nI have always thought that there must be a really simple way to implement such a\nsystem, a way that is efficient and so robust that it can stand the test of time\n(and the coming and going of software tools…).</p>\n\n<p>This does not mean that there are no good tools around for implementing a PKM\nsystem. Even when taking into account some of my basic requirements, like</p>\n\n<ul>\n <li>notes must be stored as plain text,</li>\n <li>the tool must be open source (to prevent vendor lock-in, among others),</li>\n <li>it should be simple and not suffer from feature creep,</li>\n</ul>\n\n<p>there is still a respectable number of tools which satisfy these. Yet, I have\nnever come to really like them. Even <a href="https://obsidian.md/">Obsidian</a>, a tool\nwhich has many dedicated fans and which I really appreciate, is not for me,\nmostly for two reasons (which are directly connected to the requirements above):\nIt is too complex for my taste and offers way more features than I would ever\nneed, and – no matter how successful and widely used it is today –, it will\nmost likely be gone someday.<sup id="fnref:3"><a href="#fn:3" class="footnote" rel="footnote" role="doc-noteref">3</a></sup></p>\n\n<p>Therefore, I have always preferred to build my own PKM systems, tailored to my\nspecific needs (which sounds more grandiose than it actually is; hold on).</p>\n\n<h2 id="the-simplest-pkm-system">The simplest PKM system</h2>\n\n<p>But first, let us take a step back. The simplest system for storing notes – the\none most people have used decades ago, and in particular before the advent of\ngraphical user interfaces – is storing them in plain text files, one per note,\nin some directory (or directory structure). There is basically just one\ningredient necessary for setting up such a system on a computer (apart from\nrather obvious things like a file system): A text editor for creating and\nediting notes.</p>\n\n<p>With nothing more than this, working with the system is somewhat limited. But as\nsoon as basic tools available (and usually preinstalled) on essentially all\nUnix-like operating systems are taken into account, we already gain quite a bit:</p>\n\n<ul>\n <li>A pager like <code>less</code> lets us view notes.</li>\n <li><code>grep</code> lets us search notes.</li>\n <li><code>ln</code> lets us link notes (for creating aliases, for instance).</li>\n</ul>\n\n<p>and so on.</p>\n\n<p>And honestly, I still feel that not much more is needed for implementing a PKM\nsystem on a computer. While I tend to spend much time thinking about how to best\nimplement things, sooner or later I usually feel myself drawn to very simple\nsolutions with few dependencies. Here, as in many other cases, the danger lies\nin spending so much time setting up and administrating the system that one does\nnot really <em>use</em> it at all.</p>\n\n<p>There are basically just two things I would really miss with a pure plain text\napproach like this one: The ability to tag and to link notes. While tagging\nwould be possible by, for instance, prepending tags with a certain prefix like\n“#” and then using <code>grep</code> to find notes containing them, that would be a little\ncumbersome. But I have not been able to find a good solution for linking notes\n(in particular linking from a specific point in a note) with this approach.</p>\n\n<p>Here HTML comes to the rescue – or rather leightweight markup languages like\n<a href="https://daringfireball.net/projects/markdown/">Markdown</a> or\n<a href="https://asciidoc.org/">AsciiDoc</a> which translate to HTML.</p>\n\n<h2 id="a-little-bit-of-personal-history">A little bit of (personal) history</h2>\n\n<p>Before explaining the system I am currently using, however, let me briefly\nmention three of the many self-built systems I have used over the years. I have\nchosen these because of the different ideas and concepts they were based on.</p>\n\n<ul>\n <li>\n <p>A self-written simple static site generator where notes were written in\nAsciiDoc and included front-matter for metadata like tags etc. (actually, it\nwas a derivate of a static site generator I built for my website). Since the\noutput format was HTML, linking between notes was easy. Since the output was\nstatic, though, it was only possible to filter for single tags; dynamical\nfiltering was simply not possible. This may be fine for a personal website,\nfor instance, but it is definitely a drawback for a PKM system.</p>\n </li>\n <li>\n <p>A pure plain-text system where notes were stored as plain-text files without\nany structured markup (like Markdown or AsciiDoc) at all. Tags were\nimplemented via symbolic links to (empty) directories named like the given\ntag, and links between notes were implemented via symbolic links between these\nnotes (I got the idea of using symbolic links for implementing tags by the\ngreat article “The Case Against Everything Buckets” by <a href="https://al3x.net/">Alex\nPayne</a>, which unfortunately is no longer available online\nto my knowledge). What I really liked about this system was that it depended\nonly on tools which are already available on any Unix-like system (an editor,\na pager, symbolic linking etc.). All the linking was somewhat cumbersome,\nhowever, and in particular error-prone. Therefore, I wrote a simple shell\nscript which provided convenience functions for viewing, editing, tagging and\nlinking of notes (and in particular for carrying out all the linking). A major\ndisadvantage of this system was that linking was only possible on the level of\nthe notes themselves (i.e. you could link note A to note B, but you could not\nlink from <em>a specific point in note A</em> to note B).</p>\n </li>\n <li>\n <p>Another pure plain-text system with unstructured plain-text notes where tags\nof notes, links between notes and other metadata was stored in a JSON file\n(thereby separating metadata of notes from the notes themselves). This was\nmeant to solve the problem that I did not want to have metadata directly in my\nnotes, as well as the problem of having to create all those symbolic links in\nthe system mentioned above. A Ruby script provided convenience functions\nsimilar to the ones mentioned above (and in particular for managing the JSON\nfile, which would have been rather impractical and error-prone to do\nmanually). In addition, notes were stored in a Git repository, and the script\nautomatically committed changes to the repository when creating or editing\nnotes. The main disadvantage of this system probably was that, while it was\ndesigned with the idea in mind that everything should be doable without\nspecial tools like my Ruby script, editing the JSON file and committing to the\nGit repository was cumbersome and error-prone and could easily be forgotten\nwhen done manually. So, while having a separate file for storing metadata\ninformation for my notes was more robust than employing symbolic links, I felt\nthat the problems were only shifted to different areas.</p>\n </li>\n</ul>\n\n<p>While all these systems worked and did what they were meant to do, I was never\nreally satisfied with them. The main problem was that I never really <em>worked</em>\nwith them. They were based on certain ideas and principles I had in mind, but it\nturned out that the theory of conceiving them and the practice of using them\ndiverged.</p>\n\n<h2 id="my-current-system">My current system</h2>\n\n<p>The system I am currently using is the one I am most happy with so far. It does\nnot solve all problems, but it is the one which currently works best for me.</p>\n\n<p>The main design goals of my system are (and have pretty much always been):</p>\n\n<ul>\n <li>It should be usable as a pure plain-text system without any kind of dedicated\nsoftware processing the notes or operating on them (i.e. using only standard\ntools like text editor, pager, grep etc.).<sup id="fnref:4"><a href="#fn:4" class="footnote" rel="footnote" role="doc-noteref">4</a></sup></li>\n <li>It should be simple and have very few dependencies.</li>\n <li>It should be platform-independent and future-proof.</li>\n</ul>\n\n<p>All my notes are stored in a single directory called, well, <code>notes</code> (this is not\ndifferent from practically all the other systems I have used in the past, like\nthe ones mentioned above). Notes are Markdown-formatted plain text files.<sup id="fnref:5"><a href="#fn:5" class="footnote" rel="footnote" role="doc-noteref">5</a></sup>\nThere is (almost) no metadata contained in my notes. In particular, there is no\nfront-matter (i.e. structured metadata) at the top of a note. While front-matter\nmakes it easy to parse metadata programmatically, it somewhat clutters the notes\nand is not so easy to parse without specific tools (which contradicts the first\nof my design goals).</p>\n\n<p>There are only two special syntactical constructs which extend Markdown and have\na special interpretation in my system:</p>\n\n<ul>\n <li>Words prefixed with <code>#</code> at the beginning of a note are interpreted as tags.</li>\n <li>Strings matching the pattern <code>[[&lt;note&gt;]]</code> or <code>[[&lt;title&gt;|&lt;note&gt;]]</code> are\ninterpreted as internal links, i.e. links to other notes.</li>\n</ul>\n\n<p>The system is perfectly usable with nothing more than this (note in particular\nthat the syntax for the two special constructs for tags and internal links\nmentioned above is so unobtrusive yet self-explanatory that they would even work\nwithout rendering the notes). In particular, it satisfies my first design goal;\nfor instance, some basic operations could be done like this:</p>\n\n<ul>\n <li>Viewing a note: <code>less &lt;note&gt;</code></li>\n <li>Editing a note: <code>vim &lt;note&gt;</code></li>\n <li>Searching for a given string in all notes: <code>grep &lt;string&gt; *</code></li>\n <li>Filtering notes on given tags: <code>grep -l -e "#&lt;tag1&gt;" -e "#&lt;tag2&gt;"</code></li>\n <li>Finding all notes which link to a given note: <code>grep -l "\\[\\[&lt;note&gt;\\]\\]" *</code></li>\n <li>Finding all notes which are linked to from a given note:\n<code>grep -o "\\[\\[.*\\]\\]" &lt;note&gt;</code></li>\n</ul>\n\n<p>Note the small number of tools needed to achieve these operations.</p>\n\n<p>However, to be able to efficiently use tags and links (which are integral\ningredients in a PKM system), it is convenient render notes as HTML and view\nthem in a browser. In my system, the preprocessing and rendering of the notes is\nfacilitated by a small Ruby program I wrote.<sup id="fnref:6"><a href="#fn:6" class="footnote" rel="footnote" role="doc-noteref">6</a></sup> Since the notes are written in\nMarkdown, it is easy to convert them to HTML by employing standard libraries or\nAPIs available in most programming languages. The tool provides a simple web\napplication employing the <a href="https://sinatrarb.com/">Sinatra</a> web framework. This\nin particular facilitates serving content <em>dynamically</em> (in contrast to the\nstatic site generator I used as a PKM system in the past; see above). This makes\nit possible, for instance, to filter for several tags, since the code determines\nthe matching notes dynamially before they are getting rendered and served.</p>\n\n<p>While the notes are mostly simply translated from Markdown to HTML, marks and\nlinks are preprocessed as follows:</p>\n\n<ul>\n <li>Tags are extracted from the note so that they can be laid out separately in\nthe rendered note (to make them appear below the note title instead of above\nit, for instance, or to make them link to a page which lists all other notes\nwith that tag).</li>\n <li>Internal links are converted to a link to the given note, which is displayed\nwith the respective title if given. This is a Wiki-style shortcut for internal\nlinks (i.e. links to other notes).</li>\n</ul>\n\n<p>A note can then be reached via the path <code>/note/&lt;note&gt;</code> and viewed in the browser\nby entering the corresponding URL (i.e. the host – localhost if run locally –\nplus this path). <a href="/public/note.html">This</a> is what a rendered note might look\nlike in the browser.</p>\n\n<p>There is also an index page listing all the notes available (and also one for\nlisting all the tags defined), so it is easy to directly navigate to them\ninstead of having to enter the URL manually.</p>\n\n<p>Note that, according to my second design goal above, things should be simple.\nTherefore, there is basically no explicit user interface for doing things like\nfiltering (after all, I am the only one using the system…). Instead, the\nfiltering can be done by appending query parameters to the corresponding path.\nFor instance, the path for filtering notes on tags “tag1” and “tag2” would be:\n<code>/?tag=tag1,tag2</code></p>\n\n<p>In addition, there are a few endpoints for doing certain consistency checks,\nlike whether there exist links to non-existing notes, which is then reported so\nthat it can be fixed.</p>\n\n<p>Note that it is not possible to create, modify or delete notes in any way using\nthe web interface (it works in a purely functional way, one might say). This is\na deliberate choice: Deleting and renaming can easily be done using <code>rm</code> and\n<code>mv</code> on the command line, and editing is exclusively done using my editor of\nchoice – that is, of course, Vim (so, I have finally turned things around and\narrived at the <em>actual</em> subject of this article - yay!).</p>\n\n<p>So much about the technical implementation of the system. Regarding its\norganization: It is more or less based on the Zettelkasten approach<sup id="fnref:7"><a href="#fn:7" class="footnote" rel="footnote" role="doc-noteref">7</a></sup>, but I\nwill not go into any detail about it here. I am trying to write notes which are\n<em>atomic</em>, i.e. which entail a single idea or concept, and to link them to create\nsemantic connections to similar of related ideas or concepts (though I often\nfail at doing this in a good fashion, I think). As mentioned in the beginning,\nthough, this is not the focus of this article, so I will just refer to the many\ngood resources about the organizational aspects of PKM in general, and the\nZettelkasten method in particular, available out there.</p>\n\n<h2 id="and-what-about-vim">And what about Vim?</h2>\n\n<p>So, I have written a lot already, but rarely mentioned Vim at all. Considering\nthat this is a contribution to a <em>Vim Carnival</em>, the question “Where does Vim\ncome into play?” imposes itself.</p>\n\n<p>The – somewhat trivial – answer to this question is: Where it <em>always</em> comes\ninto play when I work with plain text files. I use it, obviously, to edit my\nnotes – just as I use it to edit any other kind of text file.</p>\n\n<p>So, I hope Hyde will forgive me for somewhat abusing this Vim Carnival for my\nramblings about PKM. Let me close this article, however, by emphasizing that,\nwhile there is nothing special in my using of Vim for PKM, it <em>does</em> play an\nextremely important role in it. It’s a simple syllogism:</p>\n\n<ol>\n <li>I edit plain text files in Vim.</li>\n <li>My notes are plain text files.</li>\n <li>Therefore, I edit my notes in Vim.</li>\n</ol>\n\n<p>I want to be able to edit text files as smoothly and efficiently as possible:\nThat is why I use Vim – for PKM and everything else that comes as plain text.</p>\n\n<hr />\n\n<div class="footnotes" role="doc-endnotes">\n <ol>\n <li id="fn:1">\n <p>I know it sounds somewhat strange to call plain vi “Vim”. Then again, this\nis an article for a Vim Carnival, so what… <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>\n </li>\n <li id="fn:2">\n <p>Examples of analog PKM systems are commonplace books, which have been\naround for centuries, and the Zettelkasten method, probably most famously\nemployed by Niklas Luhmann, which is often used in an analog way (though it\ncan also be implemented on a computer). <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>\n </li>\n <li id="fn:3">\n <p>I know: Since notes are stored in Markdown-formatted plain text, they can\neven be used if Obsidian (or whatever other tool) is gone someday. Yet, I\nprefer to depend as little as possible on external software. It is a rather\nmild case of vendor lock-in – much less so than with many other\napplications –, but I like to not only own my data, but also the software\nwhich operates on it (which, of course, is only possible in rather few\ncases). <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>\n </li>\n <li id="fn:4">\n <p>This basically means that my system would fall back to the basic plain\ntext approach I sketched earlier. My notes would still contain markup in the\nform of Markdown, but one of the nice properties of Markdown (even more so\nthan with other markup languages like AsciiDoc) is that Markdown does not\ndistract much from the text; it integrates rather seamlessly into it. So\neven if Markdown would cease to exist, along with every tool to generate\nHTML from it, it would still be viable as some kind of self-explanatory\nplain-text markup. <a href="#fnref:4" class="reversefootnote" role="doc-backlink">&#8617;</a></p>\n </li>\n <li id="fn:5">\n <p>In the past, I have mostly used AsciiDoc. I switched to Markdown because I\ndo not need all the power of AsciiDoc, and the markup of Markdown is less\nintrusive than that of AsciiDoc (which is more intrusive precisely because\nit is more powerful), thereby making it even more readable. <a href="#fnref:5" class="reversefootnote" role="doc-backlink">&#8617;</a></p>\n </li>\n <li id="fn:6">\n <p>The tool can be found here: <a href="https://codeberg.org/thorstenzoeller/noted">https://codeberg.org/thorstenzoeller/noted</a>.\nNote, however, that it is not quite up-to-date; in particular, this version\nonly works with AsciiDoc-formatted notes (not with Markdown-formatted\nnotes). An updated version will (hopefully) be provided soon. <a href="#fnref:6" class="reversefootnote" role="doc-backlink">&#8617;</a></p>\n </li>\n <li id="fn:7">\n <p>Some good ressources for starters are:</p>\n\n <ul>\n <li><a href="https://zettelkasten.de/">Zettelkasten knowledge and info management • Zettelkasten\nMethod</a></li>\n <li><a href="https://lazybea.rs/tags/zettelkasten/">Hyde’s Zettelkasten posts</a></li>\n <li><a href="https://ryanholiday.net/the-notecard-system-the-key-for-remembering-organizing-and-using-everything-you-read/">The Notecard System: The Key For Remembering, Organizing And Using\nEverything You\nRead</a></li>\n </ul>\n\n <p>And no, I actually do not like footnotes that much, even though it very much\nseems to be exactly so. I just usually fail <em>not</em> to extensively make use of\nthem. Fortunately, you have now made it to the last footnote of this\narticle… <a href="#fnref:7" class="reversefootnote" role="doc-backlink">&#8617;</a></p>\n </li>\n </ol>\n</div>\n","url":"https://thorstenzoeller.com/vim-and-pkm","date_published":"2026-04-30","date_modified":"2026-04-30"}]}