<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>gemini</title>
<description>Recent posts on gemini</description>
<lastBuildDate>Sat  9 May 10:00:01 CEST 2026</lastBuildDate><atom:link href="gemini://gemini/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>Types of Wrong</title>
<link>gemini://gemini/types_of_wrong.gmi</link>
<pubDate>2026-05-07T00:00:00</pubDate>

<guid>types_of_wrong</guid>
<description>
<p>I know two ways to be wrong very well, but people have more ways to be wrong, and I don&#8217;t know the rest very well at all.
But I&#8217;d like to.</p>
<p>The first way to be wrong - and the most wrong someone can be - is to make a contradiction.
People do this when they get their sums wrong, miscounting how much money to give to a shopkeeper; or when they make contradictory statements, claiming that a politician they dislike has no right to do something, then claiming that everyone has a right to do the thing the next day, because their own political party&#8217;s members did the thing.</p>
<p>People who study types of wrong call this first type &#8216;analytically wrong&#8217;.</p>
<p>The second way to be wrong is saying something is the case when it isn&#8217;t.
People do this kind of wrong all day, and we judge the wrong by degrees (when you&#8217;re only a bit wrong), or justification (when you had good reason to think something, overlooking a subtle detail) or intentions (because saying &#8216;you&#8217;ll be fine&#8217; is fine, but saying &#8216;I think we ate the last cake already&#8217; with the intention of checking the fridge later, alone, isn&#8217;t).</p>
<p>People who study types of wrong call this second type &#8216;synthetically wrong&#8217;, and focus on how universities and corporations can avoid being wrong, but almost never discuss the messy little allowances and unstated rules of being wrong-about-facts.</p>
<p>People have many more ways to be wrong.</p>
<blockquote>
<p>This VPN uses military-grade encryption!</p>
</blockquote>
<p>People say this about VPNs, which gives uninformed listeners the impression that:</p>
<ul>
<li>encryption comes in grades (it could, but it doesn&#8217;t),</li>
<li>one of the highest is &#8216;military grade&#8217;, which is therefore &#8216;good encryption&#8217; (unlike the standard encryption you buy at the shops),</li>
<li>so this extra encryption must make you safer.</li>
</ul>
<p>These statements are all synthetically wrong, but the original sentence?
Is it wrong?
The &#8216;military&#8217; (whether that means Italian soldiers who look at Tik-Tok, or Chinese generals who want to transfer plans across China, or any other meaning), all use standard encryption, like TLS certs, mostly on their outdated Android phones and Windows 10 PCs.
So is the sentence right?
It seems about as right as saying &#8216;I eat military-grade breakfast cereal&#8217;.</p>
<p>For now, I&#8217;m calling this &#8216;presumptuously wrong&#8217;.
It&#8217;s possible to show someone has a presumption, and to show it&#8217;s wrong when they&#8217;re making making short inferences.
I have a Polish friend who noticed someone checking up on her, to make sure she didn&#8217;t steal anything, moments after learning she&#8217;s Polish.
There&#8217;s only one difference to make the difference, so the check-up clearly came from bigotry.
And more than clearly, her thinking was analytic.</p>
<ul>
<li>Premise 1: This person is Polish.</li>
<li>Premise 2: <strong>Redacted</strong></li>
<li>Conclusion: Therefore, we must check she&#8217;s not trying to steal anything.</li>
</ul>
<p>The missing step is as plain as <code>x + 2 = 4</code>.
People may obfuscate this process, objecting &#8216;no, in fact:&#8217;</p>
<pre><code class="language-maths">    0!
x = ───
    0.5
</code></pre>
<p>&#8230;and the assumptions around theft were not concerned with being Polish, but &#8216;<em>simply that they were concerned about certain things, after reading certain reports, and taking certain facts into account&#8230;</em>&#8217; et c. ad obfuscatium.
However it goes, following this thread just means taking the long-way around.</p>
<p>But that little trick-of-the-Maths works rarely.
Mostly, people degenerate quickly into mind-reading accusations.
Most people don&#8217;t act on a single piece of information simply because they have a lot more information.
Give the aforementioned bigot another day, and he would have plenty of other facts he could plausibly have taken into account.
Or if not &#8216;plausibly&#8217;, we could not deduce the bigotry from clean (not &#8216;pure&#8217;, but still &#8216;clean&#8217;) Mathematics.
Likewise in the case of people advertising Nord VPN&#8217;s &#8216;military-grade encryption&#8217;, I can&#8217;t see any room for good motivations, but I can&#8217;t Mathematically verify bad intentions.</p>
<p>This kind of presumptuously wrong might just be the regular wrong but inferred, but it has sharp differences.
It often looks like someone holding a world-view that&#8217;s wrong, and the statements are more of an indicator of the wrong than actually wrong themselves.</p>
<p>I found myself being presumptuously wrong a while ago while watching a CGP Grey video with a slippery question.</p>
<blockquote>
<p>Which planet is closest to Earth?</p>
</blockquote>
<p>The &#8216;gotcha&#8217; here is that Earth and Mars revolve around the Sun, so they spend some time far away from each other.
Once you start looking at how close other planets are to Earth on average, the answer turns out to be Mercury.
But the video&#8217;s not about getting the question wrong, it&#8217;s about the underlying world-view that makes us think in terms of planets in a line.</p>
</description>
</item>
<item>
<title>ed</title>
<link>gemini://gemini/ed.gmi</link>
<pubDate>2026-05-07T00:00:00</pubDate>

<guid>ed</guid>
<description>
<p>For the past month or so, I&#8217;ve been using the standard editor: <code>ed</code>.
It&#8217;s standard because it&#8217;s old and has outlived everything which came before it.
And it&#8217;s so old that using it has become a bit of a <a href="https://www.gnu.org/fun/jokes/ed-msg.html">meme</a>, but it has lessons for anyone who wants to take it seriously.</p>
<p>Ken Thompson created <code>ed</code> to run on a typewriter connected to a computer (i.e. a &#8216;terminal&#8217;).
He would type out what he wanted, and the typewriter would type any response.
But long responses, like <code>DOCUMENT SAVED SUCCESSFULLY</code> or <code>ALTERATIONS ACCEPTED.  NEW LINE READS AS FOLLOWS: ...</code> would waste paper.
Instead,  <code>ed</code> communicated success by staying silent, and communicated errors in your coding by typing <code>?</code>.
If you want to know what that <code>?</code> means, you can get help by typing <code>h</code>.
And if you want to know that typing <code>h</code> will help you then Ken Thompson expects you to read the manual before you start using the thing (it&#8217;s only 11,000 words, about the length of a newspaper if you ignore most of it).</p>
<p>Typing in <code>ed</code> won&#8217;t teach you much, except that you don&#8217;t like <code>ed</code>.
But <code>ed</code> is not just made to type, save, and forget - Ken Thompson made it to edit files, and that&#8217;s where things get interesting.</p>
<p>Open a file to edit, and you see this:</p>
<pre><code class="language-ed">
9162
</code></pre>
<p>And that scares people.
But don&#8217;t be scared.
It&#8217;s a character-count for the document, so if you print out the document, the typewriter will need to go &#8216;thwack!&#8217; 9,162 times to type the entire thing out.
Sounds expensive!</p>
<p>Unlike Ken, I edit markdown files, which become pages like this thing you&#8217;re reading.
So I start a session with <code>ed</code> by asking where the headers are in the document.</p>
<pre><code class="language-ed">13  # Why Don&#39;t You Love Me, ChatGPT?
24  ## Generating Content
97  # How Double Your Content Output
118 ## Making Content with Makefiles
144 # Where is the Love?
194 ## How to be a Content-Chad Like Me
</code></pre>
<p>We can look at the section &#8216;<a href="content_creator.md">Generating Content</a>&#8217; by asking <code>ed</code> to print lines 25 to 96:</p>
<pre><code class="language-ed">25,96p
</code></pre>
<p>It&#8217;s a drag, but an interesting one.
To move, to <em>think</em> around the document, you must deliberate in the document&#8217;s own terms (line-numbers) about which lines to read, and then what to add or change.
And you can, of course, change; but again <code>ed</code> demands deliberation.
You must specify which word you want to change to what, and the result (in the best case scenario) is nothing, because <code>ed</code> does not show you how the new line looks.
The text document must live mostly in your head.</p>
<p>The syntax consists of basic mnemonics.
You type <code>s&#47;one&#47;two&#47;</code> to <em>s</em>ubstitute &#8216;one&#8217; with &#8216;two&#8217;,
or <code>c</code> to change a line.
Moving lines uses &#8216;t&#8217; for &#8216;to&#8217;, as in <code>37t24</code>: &#8216;move line 37 to line 24&#8217;.
The syntax matches <code>sed</code> exactly, which makes sense, since <code>sed</code> is the &#8216;stream editor<code>, so the early users of</code>sed<code>would presumably think &#39;oh this is easy, it&#39;s just like</code>ed<code>&#39;.
But we rarely use</code>sed<code>enough to really learn it;
or I never do.
I look up a command when I need it, can&#39;t figure out *why* the command works like that,
then forget the command immediately.
Working a week with</code>ed<code>has made it easy to parse</code>&#47;^#&#47;s&#47;Ed&#47;ed` 
(meaning &#8216;find the next line starting with &#8220;#&#8221; and substitute &#8216;Ed&#8217; with &#8216;ed&#8217;).</p>
<p>Some of these substitution commands can look verbose, but <code>ed</code> comes with a rare feature;
something present but mostly forgotten in <code>vim</code>, and entirely lost to modern editors like VS Code.
You can script <code>ed</code>.
Just like <code>sed</code> and <code>awk</code>, you can use this tool to work on a document  until you feel sure you know what you&#8217;re doing, and a little bored.
Once bored and certain, you can place your command in a script and make the computer do the work for you.
I don&#8217;t use this feature much, just like I never used to imagine changing metadata with <code>sed</code>.
Perhaps if I use it for another month it&#8217;ll become second nature.
<a href="https://jvns.ca/blog/2018/05/11/batch-editing-files-with-ed/">Some</a> just find it easier to use than <code>sed</code>.</p>
<p>Whatever its direct uses on a document, it will always retain a similar benefit to using a paper-and-pen: it demands deliberation.
No hopping around the document like a drunk hummingbird.
No colour syntax or spellchecker.
Just a blank page, and the question of what exactly you want to do in order to get your ideas pressed into the disk.</p>
</description>
</item>
<item>
<title>Markdown Processors: Surprisingly Bad</title>
<link>gemini://gemini/wikis.gmi</link>
<pubDate>2026-04-24T00:00:00</pubDate>

<guid>wikis</guid>
<description>
<p>Modern wiki software only fits other people&#8217;s purposes - none seem designed for someone who has markdown notes and wants to interact with them.
Switching wiki software demands changing the notes to adhere to the software&#8217;s new standards.
I can&#8217;t find a single project which says &#8216;we will process your markdown&#8217;.</p>
<p>Gitlab&#8217;s wiki uses Gollum, which insists that links look like this:</p>
<pre><code class="language-markdown">Golum is an awful wiki.  See my [review here](&#47;wikis&#47;golum_review&#47;).
</code></pre>
<p>But while you&#8217;re writing the file <code>wikis&#47;overview.md</code>, then the natural way to link to <code>wikis&#47;golum_review.md</code> should be a link to that file:</p>
<pre><code class="language-sh">Golum is an awful wiki.  See my [review here](golum_review.md).
</code></pre>
<p>The link to another markdown file should say where that markdown file is.
The linking system here clearly thinks in terms of a website address rather than linked notes.</p>
<p>The Gitea wiki has no such limit, but somehow manages to find a worse one: it cannot show files inside a directory and they don&#8217;t plan to change that limitation.
This basic directory structure is impossible:</p>
<pre><code class="language-tree">writing&#47;
├── ed.md
├── emacs.md
├── ghostwriter.md
├── helix.md
└── vim.md
wikis&#47;
├── gitea.md
├── golum.md
├── links.md
└── vim.md

</code></pre>
<p>Instead, everything must remain in the root directory.
People have raised this as an <a href="https://github.com/go-gitea/gitea/issues/27858">issue</a>, and the Gitea devs closed it, so now all the wikis have this structure:</p>
<pre><code class="language-tree">├── ed.md
├── emacs.md
├── helix.md
├── ghostwriter.md
├── gitea.md
├── golum.md
├── links.md
├── vim.md
└── vim_2.md

</code></pre>
<p>Worst of all, both Gitea and Gollum suffer from a GUI which demands that spaces are represented with hyphens.</p>
<table>
<thead>
<tr>
<th style="text-align: center">Filename you write</th>
<th style="text-align: center">Title you get</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center"><code>Forest_Walks.md</code></td>
<td style="text-align: center">Forest_Walks</td>
</tr>
<tr>
<td style="text-align: center"><code>Forest-Walks.md</code></td>
<td style="text-align: center">Forest Walks</td>
</tr>
<tr>
<td style="text-align: center"><code>Walks_-_Forestry.md</code></td>
<td style="text-align: center">Walks__Forestry</td>
</tr>
</tbody>
</table>
<p>It&#8217;s a shite state of affairs.</p>
<p><a href="md_gui.md">Markdown apps are no better.</a></p>
</description>
</item>
<item>
<title>My Documents</title>
<link>gemini://gemini/my_documents.gmi</link>
<pubDate>2026-04-20T00:00:00</pubDate>

<guid>my_documents</guid>
<description>
<p>Every computer I see up-close has the same sad story.
A mess of files sit on the desktop.
In &#8216;Pictures&#8217;, random pictures sit (the user downloaded them before making a half-hearted attempt to organize) with a few folders, some marked &#8216;holiday&#8217; (which one?), and others given names by the computer.
Renaming the lot would require an unknown amount of time, none of it rewarding.</p>
<p>But it&#8217;s not the users&#8217; fault.
It&#8217;s like moving into a house with a &#8216;room for small things&#8217;, containing books and a toothbrush rack on the wall, and a &#8216;room for wet things&#8217;, containing the toilet, shower, and kitchen sink.
The place comes with an in-built ontology, a default way of thinking, and all of it&#8217;s wrong.</p>
<p>People cannot organize their own basic files, and the blame for this horrifying mess lies entirely with Windows 98.
People were told to have a &#8216;My Documents&#8217; folder, and a &#8216;My Music&#8217; folder, so that&#8217;s what they used.</p>
<p>These documents were created by engineers, who think in terms of filetypes.
The <code>.pngs</code> and the <code>.jpgs</code> and <code>.gifs</code> into &#8216;My Pictures&#8217;, while the <code>.mp3s</code> and <code>.wavs</code> go into &#8216;My Music&#8217;, and
<code>.doc</code> and <code>.pdf</code> documents use &#8216;My Documents&#8217;.</p>
<p>But people don&#8217;t think like this.
They don&#8217;t organize their head or activities by filetype.
They think in terms of work&#47; home, or friends&#47; family, or maybe pidgeons&#47; home-renovation, because people can be strange.
These file structures are too important to have a default.
People should make their own.</p>
<p>I deleted my defaults documents and rebuilt slowly, finding my own structure.</p>
<pre><code>├── arc
│    { "Archives" for picturese, and other things I don&#39;t want to lose.
├── dl
│    ⎧ Downloaded items, to be sorted.
│    ⎨ Currently this sits at 541MB, so I really should think
│    ⎩ of a better way to handle downloads, that doesn&#39;t involve house-keeping.
├── img
│    { Art, memes, and surrealism.
├── kn
│    { "Knowledge Bases" mostly full of PDFs.
├── pro
│    ⎧ This chonky folder contains every git I&#39;ve taken an interest in over the
│    ⎨ last five years, all my own writing, and a boat-load of forgotten dreams
│    ⎩ which I will never fully realise.
├── rec
│    ⎧ "Records" of bills, bibliographies, and any other list-type information. 
│    ⎩ Some are automated, like the list of all WiFis I&#39;ve connected to.
├── sync
│    { Files synchronized with phone, like pictures, podcasts, music and notes.
├── vids
│    { "Videos" I want to watch later.
</code></pre>
</description>
</item>
<item>
<title>Review: Kubernetes Built-In Docs</title>
<link>gemini://gemini/kubernetes.gmi</link>
<pubDate>2026-04-20T00:00:00</pubDate>

<guid>kubernetes</guid>
<description>
<p>Kubernetes documentation feels like malicious compliance, a rebellion against
the concept of clarity.</p>
<p>Kubernetes lets you ask about anything with the command <code>kubectl explain $thing</code>.
So I did:</p>
<pre><code class="language-sh">kubectl explain namespace
</code></pre>
<p>The results make me wonder if anyone sober has read the &#8216;explanations&#8217;.</p>
<pre><code>KIND:       Namespace
VERSION:    v1

DESCRIPTION:
    Namespace provides a scope for Names. Use of multiple namespaces is
    optional.


</code></pre>
<p>Uhuh.  So &#8216;namespace&#8217; is a space, or &#8216;scope&#8217;, for &#8216;Names&#8217; (why the capital?).</p>
<blockquote>
<p>Use of multiple namespaces is optional.</p>
</blockquote>
<p>Okay, so if I use one namespace, not two, or three, then Kubernetes will not
create an error.  This is similar behaviour to:</p>
<ul>
<li>Variables,</li>
<li>functions,</li>
<li>variables which begin with the letter &#8216;l&#8217;,</li>
<li>owning a dog,</li>
<li>and eating breakfast.</li>
</ul>
<p>This sentence feels about as informative and surprising as saying that &#8216;Namespaces begin with the letter &#8220;N&#8221;&#8217;.</p>
<p>But the docs continue to inform us:</p>
<pre><code>FIELDS:
  apiVersion    &#60;string&#62;
    APIVersion defines the versioned schema of this representation of an object.
    Servers should convert recognized schemas to the latest internal value, and
    may reject unrecognized values. More info:
    https:&#47;&#47;git.k8s.io&#47;community&#47;contributors&#47;devel&#47;sig-architecture&#47;api-conventions.md#resources

</code></pre>
<blockquote>
<p>APIVersion defines the versioned schema&#8230;</p>
</blockquote>
<p>So the &#8216;API version&#8217;&#8230;tells you the version?!
But the version of what?</p>
<blockquote>
<p>&#8230;of this representation of an object.</p>
</blockquote>
<p>Well at least it didn&#8217;t say &#8216;API&#8217;.</p>
<p>So these objects are not real objects (like spoons and rocks) but
representations of an object.  Or perhaps the writers have drunk so much Python
that they think some computer objects are comparatively real.</p>
<pre><code>
  metadata  &#60;ObjectMeta&#62;
    Standard object&#39;s metadata. More info:
    https:&#47;&#47;git.k8s.io&#47;community&#47;contributors&#47;devel&#47;sig-architecture&#47;api-conventions.md#metadata

</code></pre>
<p>Presumably these &#8216;standard objects&#8217; are more objects than the mere
representation of objects.  Am I studying Kant again?</p>
<pre><code>  status    &#60;NamespaceStatus&#62;
    Status describes the current status of a Namespace. More info:
    https:&#47;&#47;git.k8s.io&#47;community&#47;contributors&#47;devel&#47;sig-architecture&#47;api-conventions.md#spec-and-status

</code></pre>
<blockquote>
<p>Status describes the current status of a Namespace.</p>
</blockquote>
<p>I think that should have been:</p>
<blockquote>
<p>&#8216;Status&#8217; describes the current status of a Namespace.</p>
</blockquote>
<p>Even by the standards of a vacuous pedant, the docs fail.</p>
<blockquote>
<p>More info:</p>
</blockquote>
<p>I really doubted this statement, but the URL ends in <code>.md</code>, which felt
promising.  In fact, the docs are in html, and not even very readable html.</p>
</description>
</item>
<item>
<title>AD vs CE</title>
<link>gemini://gemini/ad_vs_ce.gmi</link>
<pubDate>2026-04-19T11:00:00</pubDate>

<guid>ad_vs_ce</guid>
<description>
<p>I&#8217;m not a fan of the change from AD to CE, for two reasons.</p>
<p>The first reason is the weird assumptions built into the standard reasons to
update.</p>
<blockquote>
<p>&#8220;&#8216;AD&#8217; means &#8216;anno domini&#8217;, or &#8216;in the year of our lord&#8217;.  It&#8217;s not an
inclusive world-wide standard, not appropriate for countries of other faiths,
or people of no faith.  It smacks of our colonial history, so the term
&#8216;common era&#8217; (CE) works much better.</p>
</blockquote>
<p>This sounds reasonable when &#8216;our history&#8217; is colonialist, because we assume
that the &#8216;us&#8217; in question is the European nations who did all the colonialism.
It sounds less reasonable when you say it in Serbia, a culture which has plenty
of hang-ups from colonialism, but not their own.  Within Serbia, Poland, and
plenty of other nations outside of the &#8216;we, with our colonialist past&#8217;, it&#8217;s
just a request to update their books and habits from outside.  And why should
they listen?  Why should the academics of the UK tell people how to track time?
Who are these outsiders who control the naming standards?</p>
<p>The demand to update does not come from colonised people.  It comes from the
ivory tower, washing their hands of their embarrassing past.</p>
<p>The second problem with changing the names is that you can&#8217;t.  We can <em>add</em> a
new name for &#8216;100 AD&#8217;, but cannot remove the old one.  Old books will not be
updated.  Old contracts must be respected.  We can&#8217;t outgrow the history of
literature, so we cannot change this word.  We can only add another word which
means the same thing.</p>
</description>
</item>
<item>
<title>A Bland Knowledge Base in Vim</title>
<link>gemini://gemini/vim_lk.gmi</link>
<pubDate>2026-04-16T00:00:00</pubDate>

<guid>vim_lk</guid>
<description>
<ul>
<li><em>This article was written for the <a href="https://lazybea.rs/vim-carnival-202604/">lazy bear&#8217;s Vim Carnival</a></em></li>
</ul>
<p>I have notes on lots of things.
When you write notes in markdown it&#8217;s called &#8216;a knowledge base&#8217;, which sounds classy.
So now I have lots of knowledge bases, and I strive to keep them bland and featureless.</p>
<p>A good knowledge base has no fancy features.
<a href="features_are_bad.md">Features are bad</a>.
They tie you down to particular software, or one workflow.
Everything &#8216;integrated&#8217; with the notes also holds onto your notes, jealously.</p>
<p>Proprietary solutions are prone to the <a href="https://en.wikipedia.org/wiki/Comparison_of_open-source_and_closed-source_software">usual abuse</a>, but many <a href="md_gui.md">open source note apps</a> aren&#8217;t much better - they have their own oddities, and special markdown abilities, which won&#8217;t work in other contexts.
This leaves you unable to publish notes, as that special in-line image format from a fancy app won&#8217;t work on a website.</p>
<p>The websites are no better.
I publish with Hugo, and it&#8217;s great, but every theme also invites you to place special snippets for graphs or video</p>
<pre><code>`{{ .video | youtube.com&#47;?url=thing }}`
</code></pre>
<p>It looks harmless, but it&#8217;s a trap.
The video link won&#8217;t work on other web compilers, or gemini, so the knowledge base will be tied to that particular software.</p>
<p>Hence Vim.
Vim is harmless.
It won&#8217;t tell you how to write or organize your notes.
It just makes editing easy.
Because <a href="vim.md">vim is easy</a>.</p>
<h1 id="the-linux-knowledge-base">The Linux Knowledge Base</h1>
<p>The collection of text notes on how to do stuff in Linux has grown and become opinionated.
I&#8217;m slowly going over the pages to try and tag every single page with knowledge dependencies, i.e. what you need to know before reading the page.</p>
<p>Here&#8217;s the head of one page on editing files encrypted with GPG:</p>
<pre><code>---
title: Edit gpg encrypted files with vim
tags: 
- vim
- data
- gpg
- comfy
requires: 
- data&#47;gpg.md
- writing&#47;vim.md
---

The `vim-gnupg` plugin lets vim edit gpg-encrypted files as if they were unencrypted.

[...]

</code></pre>
<p>That &#8216;requires&#8217; tag means I can generate a note at the top of the pages saying what you need to know <em>before</em> reading the page.</p>
<p>I have not tagged all pages yet, but once I do, the <a href="https://splint.rs/docs/writing/vim/vi/?query=vim">website</a> will state what&#8217;s required to read an article at the front.
This will make me happy, because <a href="no_links.md">documentation should not have links in the body</a>.</p>
<h1 id="vim-with-a-knowledge-base">Vim with a Knowledge Base</h1>
<h2 id="file-navigation">File Navigation</h2>
<h3 id="open-search">Open &#38; Search</h3>
<p>Open a file at line 20:</p>
<pre><code class="language-sh">vim writing&#47;ed.md +20
</code></pre>
<p>Open the file while searching for the word &#8216;Delete`:</p>
<pre><code class="language-sh">vim writing&#47;ed.md +&#47;Delete
</code></pre>
<h3 id="buffers-tabs">Buffers &#38; Tabs</h3>
<p>You can open multiple files with Vim and navigate with &#8216;buffers&#8217; (the word still feels strange).</p>
<pre><code class="language-sh">vim writing&#47;*.md

</code></pre>
<p>The command <code>:ls</code> shows the buffer, and <code>b2</code> takes you to buffer 2 (<code>writing&#47;vim.md</code>) in this case.</p>
<pre><code class="language-vi">:ls
  1 %a   "writing&#47;ed.md"                line 1
  2      "writing&#47;vim.md"               line 0
  3      "writing&#47;vim_tricks.md"        line 0
:b2
</code></pre>
<p>You can also cycle through them.</p>
<ul>
<li>Select the next buffer with <code>:bNext</code> (or  <code>:bn</code>).</li>
<li>Select the previous buffer with <code>:bPrevious</code> (or <code>:bp</code>).</li>
<li>Select the last buffer on the list with <code>:bLast</code> (or <code>:bl</code>).</li>
</ul>
<p>Tabs are similar, but you can see the tabs at the top.</p>
<p>Open files in tabs with <code>-p</code>.</p>
<pre><code class="language-sh">vim -p writing&#47;*.md
</code></pre>
<p>Then use <code>:tabedit %</code> to open a new tab.</p>
<h3 id="go-to-file">Go-to-File</h3>
<p>If you put the cursor on a file&#8217;s name, you can go to the file immediately with <code>gf</code>.
This is excellent, as it lets you wander your own knowledge base as if a palace.</p>
<p>Weird markdown formats, like Gollum sometimes demand that you leave out the <code>.md</code> suffix in links, so your link to <code>[GPG](gpg.md)</code> won&#8217;t work.
You have to write <code>[GPG](gpg)</code>.
Vim lets you navigate to <code>gpg.md</code> anyway by adding a standard suffix:</p>
<pre><code class="language-vi">set suffixesadd=.md
</code></pre>
<p>Now you can go to the word <code>gpg</code> and press <code>gf</code>, and instantly enter that file.</p>
<p>If the file is in another directory, you can link to it like this:</p>
<pre><code class="language-markdown">Check [the standard editor](writing&#47;ed.md) for why `sed` works like this.
</code></pre>
<p>But you might want to link to it like this:</p>
<pre><code class="language-markdown">Check [the standard editor](ed.md) for why `sed` works like this.
</code></pre>
<p>In this case, you can still navigate to it by adding all the other directories to the path where Vim checks.
Just add this to your <code>vimrc</code> file:</p>
<pre><code class="language-vi">set path+=**
</code></pre>
<h3 id="edit-jumps">Edit Jumps</h3>
<ul>
<li><code>g;</code> to go to the last place you edited.</li>
<li><code>g,</code> to jump back through edit-locations.</li>
</ul>
<h3 id="netwr-navigator">Netwr Navigator</h3>
<p>On rare occasions, I&#8217;ll use the in-built navigator: Netwr.
There&#8217;s an excellent setup guide <a href="https://vonheikemen.github.io/devlog/tools/using-netrw-vim-builtin-file-explorer/">here</a> as it&#8217;s not very good &#8216;out-of-the-box&#8217;.</p>
<h2 id="editing">Editing</h2>
<h3 id="mapping-keys-to-output">Mapping Keys to Output</h3>
<p>Notes on Linux means lots of code-blocks, which look like this:</p>
<pre><code> ```
 ls
 ls -a
 ```
</code></pre>
<p>This is boring to type, so now I just type &#8216;comma&#8217; then &#8216;grave&#8217;, and vim produces the code block.
You can map the keypress by sticking this in <code>~&#47;.vim&#47;vimrc</code>:</p>
<pre><code class="language-vi">map ,` o```&#60;Enter&#62;```&#60;Esc&#62;kA
</code></pre>
<h3 id="interactive-find-and-replace">Interactive Find and Replace</h3>
<p>Sometimes you want to find and replace a word in a lot of files, but also confirm each change.
Vim lets you do this by starting up with a &#8216;find and replace&#8217; command:</p>
<pre><code class="language-sh">vim -c "%s&#47;${nano}&#47;${vim}&#47;gc" -c &#39;wq&#39; **&#47;*.md
</code></pre>
<h3 id="input-command-outputs">Input Command Outputs</h3>
<p>Vim can run a command and type out the results for you:</p>
<pre><code class="language-vi">:r!date

Thu 16 Apr 13:08:48 CEST 2026
</code></pre>
<h2 id="writing-with-markdown">Writing with Markdown</h2>
<h3 id="set-up-a-spell-checker">Set up a Spell Checker</h3>
<p>I have the standard spell-checking commands in my <code>vimrc</code>, but the command to actually use the spell-checker hides in the markdown-only file, because you don&#8217;t always want a spell-checker on.</p>
<pre><code class="language-vi">
set spelllang=en_gb
set complete+=kspell

hi clear SpellBad
hi SpellBad cterm=underline
hi SpellCap cterm=underline
hi SpellLocal cterm=underline
hi SpellRare cterm=underline

</code></pre>
<p>All those <em>hi</em>-light commands make Vim&#8217;s spell-highlights less nauseating.</p>
<p>In the markdown-only setting, add this to actually use those spell-checking commands:</p>
<pre><code class="language-vi">setlocal spell

</code></pre>
<p>Once you have the spell-checker working, it just has a few commands:</p>
<ul>
<li><code>z=</code> asks the wordlist for suggestions on better spelling.</li>
<li><code>zg</code> accepts a word as a word, and adds it to your dictionary in <code>~&#47;.vim&#47;spell&#47;</code>.</li>
<li><code>zug</code> removes a word which is not a word.</li>
</ul>
<p>If, like me, you speak a kind of English which people describe as &#8216;not default&#8217;, you should share this spelling file with all your computers, so you don&#8217;t have to rebuilt it every time.</p>
<p>This next command is amazing.
Once you start using it, you won&#8217;t stop, and may look back on all the years you never had it and weep.</p>
<pre><code class="language-vi">inoremap &#60;C-l&#62; &#60;c-g&#62;u&#60;Esc&#62;[s1z=gi&#60;c-g&#62;u
</code></pre>
<p>If you type a typo, you can press Control + L to jump back, fix the typo (with Vim&#8217;s first guess at the correct spelling) and then jump back, <em>all during insert mode</em>.</p>
<h3 id="formatting-text-lines">Formatting Text Lines</h3>
<p>I still don&#8217;t know how to do this.
On the one hand, writing one sentence per line helps when using <code>git</code>, and feels natural.
But it feels less natural to read.</p>
<p>As an example, that last paragraph has a new line on each sentence:</p>
<pre><code class="language-markdown">I still don&#39;t know how to do this.
On the one hand, writing one sentence per line helps when using `git`, and feels natural.
But it feels less natural to read.
</code></pre>
<p><em>Option 1</em>: have a separate markdown reader.<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>
Markdown is supposed to wrap lines for you, so you can break anywhere.</p>
<p><em>Option 2</em>: wrap the lines with vim.</p>
<p>I can press <code>gqap</code> to reformat the paragraph, and it looks better.</p>
<pre><code class="language-markdown">I still don&#39;t know how to do this.  On the one hand, writing one sentence per
line helps when using `git`, and feels natural.  But it feels less natural to
read.
</code></pre>
<p>However, every time you edit, you need to wrap the lines again.</p>
<h1 id="not-vim-with-a-knowledge-base">Not Vim with a Knowledge Base</h1>
<p>The best thing about using Vim is not using Vim.
After all, it&#8217;s just a text editor.
As mentioned above, <a href="features_are_bad.md">features are bad</a>.
Vim happily works with other tools by integrating those command.
Like the Tao, it does nothing, and accomplishes everything.</p>
<h2 id="link-checks">Link Checks</h2>
<p>Having plain text means easy parsing.
I have a little bash script which searches markdown files for links, and checks to see if they work, then spits out a list of dead links.
I&#8217;ll stick the script at the end in case anyone wants to use it for their weighty collection of markdown files.</p>
<h2 id="make-stuff">Make Stuff</h2>
<p>The Makefile at the root of knowledge base automates the standard commands.
The first command is a help menu.
I want the project to be friendly in case anyone else wants to join me in my <a href="no_links.md">quest</a> to rid documentation of links inside the body.</p>
<pre><code class="language-sh">make

article         Write a new article
clean           Remove all generated files
database        Make a recfiles database
help            Print the help message
map             Show knowledge dependency map
</code></pre>
<p><code>make article</code> will create a standard article template then commit it to the <code>git</code> repository.</p>
<h3 id="the-dependencies-map">The Dependencies Map</h3>
<p>Each setup guide and note lists what you need to understand before starting.
If you have <code>graph-easy</code> installed, you can run <code>make map</code> and see a full graph of dependencies (example at the end).</p>
<h2 id="recfiles">Recfiles</h2>
<p><a href="https://handwiki.org/wiki/Recfiles">Recfiles</a> are plain-text files which are also a relational database.
They look like this:</p>
<pre><code class="language-recfile">%rec: guide
%key: title
%type: requires rec guide
%type: provides rec guide
%type: wordcount int
%sort: wordcount

file: data&#47;gpg.md
title: gpg
tag: data
tag: gpg 
wordcount: 13

file: hardware&#47;brightness.md
title: brightness
tag: hardware
tag: laptop 
wordcount: 16

[...]
</code></pre>
<p>This file is a record of every file in the knowledge base, along with the word-count.</p>
<h3 id="the-commands-list">The Commands List</h3>
<p>Recently, I&#8217;ve begun another recfile database for commands.
I have a boat-load of little commands that don&#8217;t merit their own page&#47;post&#47;article, and really just exist so I can search for them quickly.</p>
<pre><code class="language-sh">  $ recsel ~&#47;LK&#47;command.rec -q qr

aim: Make a QR Code image:
cmd: qrencode &#39;https:&#47;&#47;play.google.com&#47;store&#47;apps&#47;details?id=org.briarproject.briar.android&#39; -o "$FILE".png
bin: qrencode
tag: qr

aim: Make a QR Coded message in the terminal:
cmd: qrencode -t ansi "Hello World"
bin: qrencode
tag: qr

aim: Read a QR Code image:
cmd: zbarimg $FILE
bin: qrencode
tag: qr

aim: Show wifi QR code (only with Network Manager):
cmd: nmcli device wifi show-password
bin: qrencode
tag: qr
tag: wifi
</code></pre>
<h1 id="links">Links</h1>
<p>If you want to check the project, it&#8217;s available over ssh:</p>
<pre><code class="language-sh">ssh -p 2222 soft.dmz.rs -t lk
</code></pre>
<p>&#8230;or at <a href="https://gitlab.com/andonome/lk">Gitlab</a>.</p>
<h1 id="appendix-a">Appendix A</h1>
<h2 id="link-check-script">Link Check Script</h2>
<pre><code class="language-sh">
#!&#47;bin&#47;sh

set -e

timeout=4

find_links(){
    echo "$1"
    sed &#39;&#47;```&#47;,&#47;&#47;d&#39; "$1" | \
    sed -nr &#39;s&#47;.*\[.+\]\(([^ )]+).*&#47;\1&#47;p ; s&#47;^\[[^\^]*\]:\s(.*)&#47;\1&#47;p&#39;
}

check_link(){
    while read link; do
        if "${link##*:*}"; then
            check_file "$link" "$file"
        else
            prefix="${link%%:*}"
            case "${prefix}" in 
                http) check_http_link "$link"
                ;;
                https) check_http_link "$link"
                ;;
                gemini) check_gemini_link "$link"
                ;;
                mailto) echo "ignoring email: $link"
                ;;
                magnet) echo "ignoring torrent: $link"
                ;;
                *) echo "$file: unknown protocol $link"
                ;;
            esac
        fi || dead_link_error "$link" "$file"
    done
}

dead_link_error(){
    echo "$2: $1"
}

check_file(){
    path="${1#&#47;}"
    path="${path%#*}"
    test -f "$path" \
    || test -f "$path".md \
    || (
        cd "$(dirname "$2")" &#38;&#38; \
        test -f "$path" || test -f "$path".md
    )
}

check_gemini_link(){
    gemget --max-time "$timeout" "$1" -o- &#62;&#47;dev&#47;null
}

check_http_link(){
    timeout=$(( timeout + 1 ))
    curl --connect-timeout "$timeout" -Is "$1" &#62;&#47;dev&#47;null
}

check_markdown_links(){
    find_links "$1" | check_link
}

#################

test -z "$1" &#38;&#38; targets="*.md" || targets="$@"

for file in $targets; do
    test "${file##*.}" != "md" || check_markdown_links "$file" &#38;
done

wait
</code></pre>
<h2 id="the-dependencies-map-1">The Dependencies Map</h2>
<p>A lot of work remains, but right now the dependencies map looks like this:</p>
<pre><code class="language-graph">
                            ┌──────────────────────┐     ┌−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┐     ┌−−−−−−−−−−−−−−−−−−−−┐
                            │      GPG Basics      │ ──&#62; ╎              pass              ╎ ──&#62; ╎   pass with otp    ╎
                            └──────────────────────┘     └−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┘     └−−−−−−−−−−−−−−−−−−−−┘
                              │
                              │
                              ∨
                            ┌−−−−−−−−−−−−−−−−−−−−−−┐
  ┌───────────────────────&#62; ╎     gpg with vim     ╎
  │                         └−−−−−−−−−−−−−−−−−−−−−−┘
  │                         ┌──────────────────────┐     ┌−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┐     ┌−−−−−−−−−−−−−−−−−−−−┐
  │                         │   Kubernetes Setup   │ ──&#62; ╎       Kubernetes Basics        ╎ ──&#62; ╎  Kubernetes Docs   ╎
  │                         └──────────────────────┘     └−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┘     └−−−−−−−−−−−−−−−−−−−−┘
  │                                                        │
  │                                                        │
  │                                                        ∨
  │  ┌−−−−−−−−−−−−−−−−┐     ┌──────────────────────┐     ┌−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┐
  │  ╎   virtualbox   ╎ &#60;── │   Managing Groups    │     ╎           Proxy API            ╎
  │  └−−−−−−−−−−−−−−−−┘     └──────────────────────┘     └−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┘
  │                           │
  │                           │
  │                           ∨
  │                         ┌−−−−−−−−−−−−−−−−−−−−−−┐     ┌−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┐
  │                         ╎        Docker        ╎ ──&#62; ╎      Ansible with Docker       ╎
  │                         └−−−−−−−−−−−−−−−−−−−−−−┘     └−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┘
  │                         ┌──────────────────────┐     ┌−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┐                                ┌−−−−−−−−−−−−−−−−−−−−−−−−−−┐
  │                         │    LaTeX Packages    │ ──&#62; ╎            Calendar            ╎                                ╎ nginx logs with recfiles ╎ &#60;───────────────────────────────────┐
  │                         └──────────────────────┘     └−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┘                                └−−−−−−−−−−−−−−−−−−−−−−−−−−┘                                     │
  │                                                                                                                          ∧                                                              │
  │                                                                                                                          │                                                              │
  │                                                                                                                          │                                                              │
  │                         ┌──────────────────────┐     ┌−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┐     ┌────────────────────┐     ┌──────────────────────────┐     ┌−−−−−−−−−−−−−−−−−−−−−−−−−−−−┐  │
  │                         │       Makefile       │ ──&#62; ╎  Recfile Bibliography for TeX  ╎ &#60;── │        TeX         │     │                          │ ──&#62; ╎ Board Games with Recfiles  ╎  │
  │                         └──────────────────────┘     └−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┘     └────────────────────┘     │                          │     └−−−−−−−−−−−−−−−−−−−−−−−−−−−−┘  │
  │                                                        ∧                                                               │                          │                                     │
  │                                                        └────────────────────────────────────────────────────────────── │         Recfiles         │                                     │
  │                                                                                                                        │                          │                                     │
  │                         ┌──────────────────────┐     ┌−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┐                                │                          │     ┌−−−−−−−−−−−−−−−−−−−−−−−−−−−−┐  │
  │                         │      Makefiles       │ ──&#62; ╎ Python Projects with Makefiles ╎                                │                          │ ──&#62; ╎ IP Addresses with Recfiles ╎  │
  │                         └──────────────────────┘     └−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┘                                └──────────────────────────┘     └−−−−−−−−−−−−−−−−−−−−−−−−−−−−┘  │
  │                                                                                                                          │                                                              │
  │                                                                                                                          │                                                              │
  │                                                                                                                          ∨                                                              │
  │                         ┌──────────────────────┐     ┌−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┐                                ┌−−−−−−−−−−−−−−−−−−−−−−−−−−┐                                     │
  │                         │    Shell Scripts     │ ──&#62; ╎            Newsraft            ╎                                ╎         Recfixes         ╎                                     │
  │                         └──────────────────────┘     └−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┘                                └−−−−−−−−−−−−−−−−−−−−−−−−−−┘                                     │
  │                         ┌──────────────────────┐     ┌−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┐                                                                                                 │
  │                         │     Taskwarrior      │ ──&#62; ╎   Taskwarrior Configuration    ╎                                                                                                 │
  │                         └──────────────────────┘     └−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┘                                                                                                 │
  │                           │                                                                                                                                                             │
  │                           │                                                                                                                                                             │
  │                           ∨                                                                                                                                                             │
  │                         ┌−−−−−−−−−−−−−−−−−−−−−−┐                                                                                                                                        │
  │                         ╎ Taskwarrior Contexts ╎                                                                                                                                        │
  │                         └−−−−−−−−−−−−−−−−−−−−−−┘                                                                                                                                        │
  │                         ┌──────────────────────┐     ┌−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┐                                                                                                 │
  │                         │       certbot        │ ──&#62; ╎       radicale and nginx       ╎ &#60;─────┐                                                                                         │
  │                         └──────────────────────┘     └−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┘       │                                                                                         │
  │                         ┌──────────────────────┐     ┌−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┐       │                                                                                         │
  │                         │         cron         │ ──&#62; ╎         Search System          ╎       │                                                                                         │
  │                         └──────────────────────┘     └−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┘       │                                                                                         │
  │                                                                                               │                                                                                         │
  │                           ┌───────────────────────────────────────────────────────────────────┼──────────────────────────┐                                                              │
  │                           │                                                                   │                          ∨                                                              │
  │                         ┌──────────────────────┐     ┌−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┐     ┌────────────────────┐     ┌−−−−−−−−−−−−−−−−−−−−−−−−−−┐                                     │
  │                         │                      │ ──&#62; ╎     Soft Serve Maintenance     ╎ &#60;── │                    │ ──&#62; ╎ Soft Serve through https ╎                                     │
  │                         │                      │     └−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┘     │                    │     └−−−−−−−−−−−−−−−−−−−−−−−−−−┘                                     │
  │                         │                      │                                            │                    │                                                                      │
  │                         │         git          │ ────────────────────────────────────────┐  │       nginx        │ ─────────────────────────────────────────────────────────────────────┘
  │                         │                      │                                         │  │                    │
  │                         │                      │     ┌−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┐  │  │                    │     ┌−−−−−−−−−−−−−−−−−−−−−−−−−−┐
  │                         │                      │ ──&#62; ╎           git stash            ╎  │  │                    │ ──&#62; ╎        Soft-Serve        ╎
  │                         └──────────────────────┘     └−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┘  │  └────────────────────┘     └−−−−−−−−−−−−−−−−−−−−−−−−−−┘
  │                           │                                                              │                               ∧
  │                           │                                                              └───────────────────────────────┘
  │                           ∨
  │                         ┌−−−−−−−−−−−−−−−−−−−−−−┐
  │                         ╎       git-lfs        ╎
  │                         └−−−−−−−−−−−−−−−−−−−−−−┘
  │                         ┌──────────────────────┐     ┌−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┐     ┌────────────────────┐
  │                         │      partitions      │ ──&#62; ╎          Install Arch          ╎ &#60;── │        time        │
  │                         └──────────────────────┘     └−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┘     └────────────────────┘
  │
  │                           ┌───────────────────────────────────────────────────────────────────┐
  │                           │                                                                   ∨
  │  ┌−−−−−−−−−−−−−−−−┐     ┌──────────────────────┐     ┌−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┐     ┌−−−−−−−−−−−−−−−−−−−−┐
  │  ╎   ssh-tricks   ╎ &#60;── │         ssh          │ ──&#62; ╎         Ansible Basics         ╎     ╎       sshfs        ╎
  │  └−−−−−−−−−−−−−−−−┘     └──────────────────────┘     └−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┘     └−−−−−−−−−−−−−−−−−−−−┘
  │                           │
  │                           │
  │                           ∨
  │                         ┌−−−−−−−−−−−−−−−−−−−−−−┐
  │                         ╎       fail2ban       ╎
  │                         └−−−−−−−−−−−−−−−−−−−−−−┘
  │
  └───────────────────────────┐
                              │
     ┌−−−−−−−−−−−−−−−−┐     ┌─────────────────────────────────────────────────────────────┐     ┌−−−−−−−−−−−−−−−−−−−−┐
     ╎  vim linewrap  ╎ &#60;── │                                                             │ ──&#62; ╎ How to Learn `vim` ╎
     └−−−−−−−−−−−−−−−−┘     │                                                             │     └−−−−−−−−−−−−−−−−−−−−┘
     ┌−−−−−−−−−−−−−−−−┐     │                                                             │     ┌−−−−−−−−−−−−−−−−−−−−┐
     ╎ vim navigation ╎ &#60;── │                         vim basics                          │ ──&#62; ╎  find and replace  ╎
     └−−−−−−−−−−−−−−−−┘     │                                                             │     └−−−−−−−−−−−−−−−−−−−−┘
     ┌−−−−−−−−−−−−−−−−┐     │                                                             │     ┌−−−−−−−−−−−−−−−−−−−−┐
     ╎  vim windows   ╎ &#60;── │                                                             │ ──&#62; ╎       sc-im        ╎
     └−−−−−−−−−−−−−−−−┘     └─────────────────────────────────────────────────────────────┘     └−−−−−−−−−−−−−−−−−−−−┘
                              │                            │
                              │                            │
                              ∨                            ∨
                            ┌−−−−−−−−−−−−−−−−−−−−−−┐     ┌−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┐
                            ╎    vim completion    ╎     ╎          vim in bash           ╎
                            └−−−−−−−−−−−−−−−−−−−−−−┘     └−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┘

</code></pre>
<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>My favourite reader is <code>mdless</code> (which is just a link to <code>mdcat -p</code>).&#160;<a href="#fnref1" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
</description>
</item>
<item>
<title>Managing Dotfiles with a Makefile</title>
<link>gemini://gemini/mkdots.gmi</link>
<pubDate>2026-04-10T00:00:00</pubDate>

<guid>mkdots</guid>
<description>
<p><strong>Assumed Knowledge:</strong> <code>make</code>, <code>GPG</code>, <code>git</code>.</p>
<p>You can manage dotfiles with nothing but <code>make</code> and standard tools.</p>
<ul>
<li>Copy standard configs.</li>
<li>Track changes with <code>git</code>.</li>
<li>Keep separate branches for each computer.</li>
<li>Securely handle secret files with GPG.</li>
<li>Manage crontab.</li>
</ul>
<h1 id="the-setup">The Setup</h1>
<p>Mine looks like this:</p>
<pre><code class="language-sh">config&#47;:
 aerc         cava       khard         rofi      tut            picom.conf
 alacritty    cmus       lf            s         vdirsyncer     powerbash.sh
 amfora       dunst      ncmpcpp       sc-im     waybar         powerbashrc
 bat          gtk-3.0    newsraft      sway      zathura        redshift.conf
 bottom       himalaya   procps        systemd   compton.conf
 bugwarrior   i3         profanity     task      mpd.conf
 calcurse     i3blocks   qutebrowser   tspreed   mpv.conf

home&#47;:
 gnupg   mozilla   vim   bash_profile   gitconfig          inputrc     xinitrc
 local   unison    w3m   bashrc         gitignore_global   tmux.conf   Xresources
</code></pre>
<h2 id="hard-links">Hard Links</h2>
<p>Standard configs are made with hard links, which means these two files are the same file:</p>
<ul>
<li><code>dotfiles&#47;home&#47;bashrc</code></li>
<li><code>.bashrc</code></li>
</ul>
<p>Once you edit <code>~&#47;.bashrc</code>, that also changes <code>dotfiles&#47;home&#47;bashrc</code>.
A make pattern takes care of the path, so there&#8217;s no need for dots in your dotfile manager.</p>
<pre><code class="language-make">$HOME&#47;.%: home&#47;%
    ln -f $&#60; $@
</code></pre>
<h2 id="command-based-files">Command-Based Files</h2>
<p>Some files are usually created through commands, like <code>~&#47;.gitconfig</code>.
These can change on different computers, as you add <code>git lfs</code> on one, or a credential helper on another.
So if you don&#8217;t want to keep them in sync, you can just put the universal commands into a Makefile.
If your name ever changes, then all computers receive that change, but nothing will touch the strange git helpers installed on that old laptop.</p>
<pre><code class="language-make">$(HOME)&#47;.gitconfig: git.mk
    git config --global user.name "$yerName"
    ...
</code></pre>
<p>The same approach lets you manage secrets.
For example, you can set the secret token value in <code>glab</code> (the Gitlab CLI tool):</p>
<pre><code class="language-make">git_token != pass gitlab-token
glab config set token "$(git_token)" --host gitlab.com
</code></pre>
<h2 id="secrets-management">Secrets Management</h2>
<p>You can use <code>pass</code> to manage secrets with <code>make</code>.
For example, to keep <code>~&#47;.config&#47;aerc&#47;accounts.conf</code> as a secret file, just throw it into <code>pass</code>:</p>
<pre><code class="language-sh">cat ~&#47;.config&#47;aerc&#47;accounts.conf | pass insert --echo config&#47;aerc&#47;accounts.conf
</code></pre>
<p>Add this file as a secret, and make a rule to create these secrets from all the files in <code>~&#47;.password-store&#47;</code>:</p>
<pre><code class="language-make">secrets += ${HOME}&#47;.config&#47;aerc&#47;accounts.conf

$(secrets): ${HOME}&#47;.% : ${HOME}&#47;.password-store&#47;%.gpg
    mkdir -p $(@D)
    chmod 700 $(@D)
    gpg --quiet --decrypt $&#60; &#62; $@ 
    chmod 600 $@
</code></pre>
<h2 id="handling-crontab">Handling Crontab</h2>
<p>Changes in different computers&#8217; <code>crontab</code> files can inflict a lot of merges.
Avoid this by just making each set of tasks its own file:</p>
<pre><code class="language-sh">echo &#39;@daily import_events.sh "https:&#47;&#47;dmz.rs&#47;events.ical"&#39; &#62; extra&#47;cron&#47;calendar
echo &#39;@hourly mbsync -a&#39; &#62; extra&#47;cron&#47;email
</code></pre>
<p>Combine the lot with cat, then import this into <code>cron</code>:</p>
<pre><code class="language-make">cron.txt: $(wildcard extra&#47;cron&#47;*)
    cat $^ &#62; $@
    crontab $@
</code></pre>
<h1 id="example-repo">Example Repo</h1>
<p>You can find my basic setup here:</p>
<pre><code class="language-sh">ssh -p 2222 soft.dmz.rs -t mkdots
</code></pre>
<p>Or just clone the repo and see how it works:</p>
<pre><code class="language-sh">git clone ssh:&#47;&#47;soft.dmz.rs:2222&#47;mkdots .dots
cd .dots
make -n
</code></pre>
</description>
</item>
<item>
<title>Newcomb's Box is Empty</title>
<link>gemini://gemini/take_both.gmi</link>
<pubDate>2026-03-30T17:00:00</pubDate>

<guid>take_both</guid>
<description>
<p>If we accept the premises of the <a href="https://en.wikipedia.org/wiki/Newcomb%27s_problem">Newcomb Problem</a>, then it&#8217;s not
possible to receive $1,001,000 from playing this game.  But you have the choice
to take both boxes, and therefore the mystery-box is empty.</p>
<p>Once you approach the boxes to make your decision, the boxes have been
determined.  From this point, we know that:</p>
<blockquote>
<p><code>(A)</code> You cannot end this game with $1,001,000.</p>
</blockquote>
<p>We know this because it&#8217;s a stipulation of the problem: nobody walks out of
here with both boxes full of cash.  We can&#8217;t violate this rule, or we are
negating the premise of the paradox.</p>
<p>Another stipulation is the choice:</p>
<blockquote>
<p><code>(B)</code> You may choose to take both boxes.</p>
</blockquote>
<p>If the mystery-box contains $1,000,000 and you have the option to take both
boxes, then you can walk out of here with $1,001,000.  But since you cannot
leave with this money, and you may take both boxes, we can conclude that the
mystery box is empty.</p>
<p>Suppose the opposite:</p>
<blockquote>
<p><code>(C)</code> The mystery box contains $1,000,000.</p>
</blockquote>
<p>More formally:</p>
<blockquote>
<p>C ∧ B -&#62; ¬ A</p>
<p>A -&#62; ¬ (C ∧ B)</p>
<p>¬C ∨ ¬B</p>
</blockquote>
<p>So if we accept <em>B</em> (another stipulation of the puzzle itself) then we must
accept that <em>C</em> is false.</p>
</description>
</item>
</channel>
</rss>
