<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>André Klein Dot Net</title>
	<atom:link href="https://andreklein.net/feed/" rel="self" type="application/rss+xml" />
	<link>https://andreklein.net/</link>
	<description>Prose, Code &#38; Poetry</description>
	<lastBuildDate>Sat, 06 Jun 2026 11:50:18 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>

<image>
	<url>https://andreklein.net/wp-content/uploads/2013/05/ak-150x150.gif</url>
	<title>André Klein Dot Net</title>
	<link>https://andreklein.net/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>The Feed Is A Lie</title>
		<link>https://andreklein.net/the-feed-is-a-lie/</link>
					<comments>https://andreklein.net/the-feed-is-a-lie/#respond</comments>
		
		<dc:creator><![CDATA[André Klein]]></dc:creator>
		<pubDate>Tue, 02 Jun 2026 22:33:00 +0000</pubDate>
				<category><![CDATA[Musings]]></category>
		<category><![CDATA[tinker]]></category>
		<guid isPermaLink="false">https://andreklein.net/?p=23460</guid>

					<description><![CDATA[<p>[drop_cap]R[/drop_cap]emember the original promise of Social Media? &#8220;Connect with your friends&#8221; &#8211; &#8220;share cool stuff&#8221; &#8211; &#8220;hang out and get to meet new people&#8221;. Fast forward to 2026 and social media is a fragmented hellscape of ideological silos and algorithmic meatgrinders, everyone tap-dancing for ever-shifting virality metrics while the platform-keepers harvest each minuscule flick of [&#8230;]</p>
<p>The post <a href="https://andreklein.net/the-feed-is-a-lie/">The Feed Is A Lie</a> appeared first on <a href="https://andreklein.net">André Klein Dot Net</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a href="https://andreklein.net/wp-content/uploads/2026/06/brankojet-cow-4027725_1280.jpg"><img fetchpriority="high" decoding="async" class="alignnone wp-image-23465 size-large" src="https://andreklein.net/wp-content/uploads/2026/06/brankojet-cow-4027725_1280-1024x682.jpg" alt="" width="1024" height="682" srcset="https://andreklein.net/wp-content/uploads/2026/06/brankojet-cow-4027725_1280-1024x682.jpg 1024w, https://andreklein.net/wp-content/uploads/2026/06/brankojet-cow-4027725_1280-300x200.jpg 300w, https://andreklein.net/wp-content/uploads/2026/06/brankojet-cow-4027725_1280-768x512.jpg 768w, https://andreklein.net/wp-content/uploads/2026/06/brankojet-cow-4027725_1280.jpg 1280w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>[drop_cap]R[/drop_cap]emember the original promise of Social Media? &#8220;Connect with your friends&#8221; &#8211; &#8220;share cool stuff&#8221; &#8211; &#8220;hang out and get to meet new people&#8221;.</p>
<p>Fast forward to 2026 and social media is a <a href="https://andreklein.net/socialsox/">fragmented hellscape</a> of ideological silos and algorithmic meatgrinders, everyone tap-dancing for ever-shifting virality metrics while the platform-keepers harvest each minuscule flick of our eyeballs for ad revenue.</p>
<h2>&#8220;Don&#8217;t Show Me More Of This&#8221;</h2>
<p>You know the drill. The longer these platforms keep you glued to their &#8220;feeds&#8221; (why does this term always remind me cattle farms?) the more vigorously they can present their PowerPoint presentations and proudly proclaim &#8220;2% increase in user stickiness&#8221;.</p>
<p>The fact that it&#8217;s all slop, propped up by bots, engagement-share-croppers, vapid hot takes and rage-bait&#8211;let&#8217;s not talk about it. Business is booming. Advertisers are spending. The kids are lapping it up. And so are the oldtimers. Swiping all day long. Just don&#8217;t make them leave. Integrate, consolidate! Intersperse cute animals with geopolitical carnage, productivity hacks with celebrity gossip, thirst traps and hyper-personalized content, custom-tailored to trigger you where it hurts, smack-dab in the mammalian cortex.</p>
<p>Can&#8217;t log off. Must &#8220;monitor the situation&#8221;. Pull to refresh. The dopamine slot machine. Open your mouth wide. And feed.</p>
<p>The funniest part about all of this is: nobody asked for social media to become a behavioral optimization machine. Yet that&#8217;s where every platform eventually drifted. The open web? Who needs it anyway? Hyperlinks? Pah, where we are going you&#8217;ll get likes and comments instead!</p>
<p>Somewhere along the way, &#8220;sharing something online&#8221; quietly became a commitment. Post something and now you&#8217;re expected to monitor reactions, reply to comments, check analytics, maintain a presence. Communication was no longer enough. You had to manage its aftermath.</p>
<p>But at the end of the day, social media is just software, like anything else. Input and output of data: simple text messages, with some images and videos sprinkled in.</p>
<h2>Exodus To The Terminal</h2>
<p>A few days ago I thought to myself: what if we stripped all that extraneous nonsense away and drilled down to the very core of what social media actually is? What is left if you kill the feed, the hearts, the thumbs up, the comments, the &#8220;analytics&#8221;?</p>
<p>Just bits and bytes of data going from A to B. Mostly text, with some images and videos sprinkled in. No tracking, no ads, no bloat, just pure unfiltered sharing.</p>
<p>And what better place to build it in than the terminal, that beautiful text-based domain of data manipulation.</p>
<p>I already had most of the cross-posting-API stuff ready from my <a href="https://github.com/burninc0de/socialsox">previous project</a>, including image/video support, so porting it all to the terminal was a surprisingly quick undertaking.</p>
<p>Have a quick thought? Just pop open a terminal (or even better: bind it to a hotkey), send off your tweet/toot or whatever they call it these days, and carry on with your life.</p>
<p>No harm done. Not a single browser or app icon touched. Not an eyeball defiled by ads. Never sidetracked by &#8220;related posts&#8221;. Just share and move on.</p>
<p>If someone replies, fine. Deal with it later. If not, also fine. At least you&#8217;re not going to waste time gulping down the slop-du-jour while the C-suite books yet another &#8220;digital detox&#8221; to the Bahamas.</p>
<p>And besides, what do you need notifications for? You have your phone next to you anyway at all times, you filthy animal.</p>
<p>But isn&#8217;t that &#8220;anti-social&#8221;, you say? To just &#8220;broadcast&#8221;, unidirectionally like a fax machine possessed by a purpose?</p>
<p>When you want to share, share.</p>
<p>When you want to read, read. Got a moment of downtime? Comment, engage. On your terms.</p>
<p>Clean separation of concerns.</p>
<p><a href="https://andreklein.net/wp-content/uploads/2026/06/screenshot-2026-06-03_01-08-07.png"><img decoding="async" class="alignnone size-large wp-image-23467" src="https://andreklein.net/wp-content/uploads/2026/06/screenshot-2026-06-03_01-08-07-1024x670.png" alt="" width="1024" height="670" srcset="https://andreklein.net/wp-content/uploads/2026/06/screenshot-2026-06-03_01-08-07-1024x670.png 1024w, https://andreklein.net/wp-content/uploads/2026/06/screenshot-2026-06-03_01-08-07-300x196.png 300w, https://andreklein.net/wp-content/uploads/2026/06/screenshot-2026-06-03_01-08-07-768x502.png 768w, https://andreklein.net/wp-content/uploads/2026/06/screenshot-2026-06-03_01-08-07.png 1084w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>FOSS / MIT license</p>
<p><a href="https://github.com/burninc0de/socialsox-tui"><img decoding="async" class="alignnone" src="https://img.shields.io/badge/github-repo-blue?logo=github" alt="github" width="97" height="20" /></a></p>
<p>Github repo: <a href="https://github.com/burninc0de/socialsox-tui">github.com/burninc0de/socialsox-tui</a></p>
<p>&#8211;</p>
<p>The post <a href="https://andreklein.net/the-feed-is-a-lie/">The Feed Is A Lie</a> appeared first on <a href="https://andreklein.net">André Klein Dot Net</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://andreklein.net/the-feed-is-a-lie/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Building My Own Markdown Publishing Suite, or: Dogfooding Until It Clicks</title>
		<link>https://andreklein.net/building-my-own-markdown-publishing-suite-or-dogfooding-until-it-clicks/</link>
					<comments>https://andreklein.net/building-my-own-markdown-publishing-suite-or-dogfooding-until-it-clicks/#respond</comments>
		
		<dc:creator><![CDATA[André Klein]]></dc:creator>
		<pubDate>Mon, 18 May 2026 13:05:40 +0000</pubDate>
				<category><![CDATA[Musings]]></category>
		<category><![CDATA[tinker]]></category>
		<guid isPermaLink="false">https://andreklein.net/?p=23119</guid>

					<description><![CDATA[<p>[drop_cap]T[/drop_cap]here&#8217;s a type of writer who just writes. That ain&#8217;t me. Hand-cutting and gluing books to sell after readings. Uploading home-made PDFs to an FTP server at 2am. Spending hours in Berlin print-shops agonizing over the perfect glue-binding for a short story collection. The writing was never enough&#8211;I always needed to control the whole thing, [&#8230;]</p>
<p>The post <a href="https://andreklein.net/building-my-own-markdown-publishing-suite-or-dogfooding-until-it-clicks/">Building My Own Markdown Publishing Suite, or: Dogfooding Until It Clicks</a> appeared first on <a href="https://andreklein.net">André Klein Dot Net</a>.</p>
]]></description>
										<content:encoded><![CDATA[<div id="attachment_23399" style="width: 1034px" class="wp-caption alignnone"><a href="https://andreklein.net/wp-content/uploads/2026/05/adapation.jpg"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-23399" class="size-large wp-image-23399" src="https://andreklein.net/wp-content/uploads/2026/05/adapation-1024x555.jpg" alt="" width="1024" height="555" srcset="https://andreklein.net/wp-content/uploads/2026/05/adapation-1024x555.jpg 1024w, https://andreklein.net/wp-content/uploads/2026/05/adapation-300x163.jpg 300w, https://andreklein.net/wp-content/uploads/2026/05/adapation-768x416.jpg 768w, https://andreklein.net/wp-content/uploads/2026/05/adapation-1536x832.jpg 1536w, https://andreklein.net/wp-content/uploads/2026/05/adapation.jpg 1919w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><p id="caption-attachment-23399" class="wp-caption-text">Adaptation (2002)</p></div>
<p>[drop_cap]T[/drop_cap]here&#8217;s a type of writer who just writes. That ain&#8217;t me. Hand-cutting and gluing books to sell after readings. Uploading home-made PDFs to an FTP server at 2am. Spending hours in Berlin print-shops agonizing over the perfect glue-binding for a short story collection. The writing was never enough&#8211;I always needed to control the whole thing, soup to nuts.</p>
<p>Having written and published around twenty books for German learners over the last decade, my workflow went through many different iterations, from using OpenOffice (sue me &#8230;) to Calibre, Mobigen, InDesign, Sigil, Scrivener, Vellum, Papyrus and a bunch more. I’ve always been on the lookout for the perfect brain-to-world pipeline, with minimum amount of fiddling&#8211;and quite frankly&#8211;nonsense.</p>
<p>There’s nothing worse than fighting your own tools.</p>
<p>Some tools are very good at doing one thing&#8211;InDesign for print, Sigil for EPUBs. Others try to do everything for everyone. Some lock you into a polished but shallow box&#8211;great until you need something they didn&#8217;t anticipate. Others go the opposite direction: corkboards, character sheets, diary entries about what your protagonist had for breakfast. You stop writing and start managing the software.</p>
<p>So for many years I just went with using special tools for special purposes, which meant maintaining different versions for digital and print. Reliable, deterministic results, yes, but also two completely separate pipelines. Never-ending “version-tracking” (<code>finalv2_final_FOR_REAL.epub</code>)&#8211;wondering what got updated where, what still needed syncing. Not to mention all the copy-pasting of recurring elements like “About the Author”, “Newsletter” and whatnot. So much copy-pasting!</p>
<p>But the dream was always: one manuscript → typographically perfect PDF and crisply-coded EPUB.</p>
<p>And yes, many tools promise that. They just never clicked with me.</p>
<h2>Bootstrapping Time</h2>
<p>In early 2025, I’d finally had enough. I was just going to build my own publishing suite, from scratch.</p>
<p>The plan: write in plaintext (Markdown), export to PDF and EPUB from the same “codebase”.</p>
<p>How hard could it be? Quick 20-minute in-and-out adventure.</p>
<p>Well, it&#8217;s now mid-2026. A year and a half of iterating, rewriting, bug-fixing, and at least one complete breakdown over German hyphenation in PDFjs. It&#8217;s probably the longest time I’ve ever spent on a (non-web) software development project.</p>
<p>Anyway, I&#8217;ve just published my latest book, <a href="https://books.learnoutlive.com/learn-german-with-stories-horror-in-heidelberg-10-short-stories-for-beginners/"><em>Horror in Heidelberg</em></a>, volume 13 in the <em>Dino lernt Deutsch</em> series for German learners, which was completely written, formatted and typeset in this new pipeline. So I guess it works.</p>
<p>The core stack is pretty simple:</p>
<ul>
<li><strong>Electron React/TS</strong> (works on Linux, Mac, Windows)</li>
<li><strong>react-markdown</strong> for Markdown processing</li>
<li><strong>epub-gen-memory</strong> for crisp EPUBs</li>
<li><strong>Typst</strong> for pixel-perfect print typesetting</li>
</ul>
<h2>Building The Skeleton</h2>
<p>The first few weeks I wired up the basic skeleton: Obsidian-style “<a href="https://andreklein.net/vault-dweller-how-i-ditched-the-cloud-for-a-pi-and-a-git-repo/">filesystem-as-database</a>” approach where I can just drop <code>introduction.md</code>, <code>chapter1.md</code> into a folder and have that be my document outline. No SQLite or annoying abstractions.</p>
<p>Then I spent a lot of time on creating the actual writing area. Coming off years of working in WriteMonkey or iAWriter, I knew exactly what was needed: clean spacing, horizontal padding, nice fullscreen distraction-free mode, etc. (I’ve since recreated that same workflow in my terminal writing app <a href="https://andreklein.net/helowrite-terminal-word-processor/">Helowrite</a>).</p>
<div id="attachment_23429" style="width: 1034px" class="wp-caption alignnone"><a href="https://andreklein.net/wp-content/uploads/2026/05/zenmode.png"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-23429" class="wp-image-23429 size-large" src="https://andreklein.net/wp-content/uploads/2026/05/zenmode-1024x639.png" alt="" width="1024" height="639" srcset="https://andreklein.net/wp-content/uploads/2026/05/zenmode-1024x639.png 1024w, https://andreklein.net/wp-content/uploads/2026/05/zenmode-300x187.png 300w, https://andreklein.net/wp-content/uploads/2026/05/zenmode-768x480.png 768w, https://andreklein.net/wp-content/uploads/2026/05/zenmode-1536x959.png 1536w, https://andreklein.net/wp-content/uploads/2026/05/zenmode.png 1917w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><p id="caption-attachment-23429" class="wp-caption-text">just words and a counter</p></div>
<p>So I opted for a bare-bones textarea approach. No complex dependencies like <code>monaco</code> or <code>codemirror</code>. That kept things simple, but it also meant writing a bunch of things like search/replace and highlighting from scratch. Anything for simplicity, right?</p>
<p>Next, I started work on a templating system. I&#8217;d manually copy-pasted copyright pages, TOCs, exercises, etc. a million times before. Automating it was long overdue.</p>
<p>I ended up writing a very basic template short-code language with a bunch of variables, so I could have a <code>copyright.md</code> that would look something like this:</p>
<pre><code>**%%TITLE%%**
Copyright %%YEAR%%
[[EPUB: %%CLICKABLE_LINK%%]]
[[PDF: __CUSTOM_TYPOGRAPHIC_ELEMENT__]]</code></pre>
<p>Obviously, images had to be processed separately for print &amp; digital as well, with custom DPI and compression, etc. And then there was the whole footer, header, gutter business of typesetting.</p>
<p>It was my first time working with Typst&#8211;a steep learning curve, but nothing compared to LaTeX, a system I have spent a decade admiring from a safe distance.</p>
<p><a href="https://andreklein.net/wp-content/uploads/2026/05/latex.jpg"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-23417" src="https://andreklein.net/wp-content/uploads/2026/05/latex.jpg" alt="" width="900" height="706" srcset="https://andreklein.net/wp-content/uploads/2026/05/latex.jpg 900w, https://andreklein.net/wp-content/uploads/2026/05/latex-300x235.jpg 300w, https://andreklein.net/wp-content/uploads/2026/05/latex-768x602.jpg 768w" sizes="auto, (max-width: 900px) 100vw, 900px" /></a></p>
<p>So I wired up a simple <code>Template.config</code>, have my Electron app watch any changes in it and automatically hand it off to Typst to render changes in a PDF previewer, which made iteration extremely fast. Because let’s face it: constantly exporting a PDF just to see if you have the perfect value for a header margin or line-spacing is torture.</p>
<p>I haven&#8217;t seen other apps do this, but after experiencing &#8220;hot module reload&#8221; for PDF exports I never want to go back.</p>
<div id="attachment_23273" style="width: 1034px" class="wp-caption alignnone"><a href="https://andreklein.net/wp-content/uploads/2026/05/2026-05-17-214738_hyprcap.png"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-23273" class="size-large wp-image-23273" src="https://andreklein.net/wp-content/uploads/2026/05/2026-05-17-214738_hyprcap-1024x616.png" alt="" width="1024" height="616" srcset="https://andreklein.net/wp-content/uploads/2026/05/2026-05-17-214738_hyprcap-1024x616.png 1024w, https://andreklein.net/wp-content/uploads/2026/05/2026-05-17-214738_hyprcap-300x180.png 300w, https://andreklein.net/wp-content/uploads/2026/05/2026-05-17-214738_hyprcap-768x462.png 768w, https://andreklein.net/wp-content/uploads/2026/05/2026-05-17-214738_hyprcap-1536x924.png 1536w, https://andreklein.net/wp-content/uploads/2026/05/2026-05-17-214738_hyprcap.png 1890w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><p id="caption-attachment-23273" class="wp-caption-text">live PDF preview &#8211; export for print or digital</p></div>
<p>Once the pieces slowly started coming together, I had this dangerous feeling of: “damn, this might just work.” But a working prototype is just that. Would it survive a whole book-publishing run? Where were the critical faultlines, annoying bugs or perhaps show-stopping failures?</p>
<p>Only one way to find out &#8230;</p>
<h2>Dogfooding Until It Clicks</h2>
<p>I told myself: try to write and publish your next book with this tool. Either it’s going to work, you will fix all the bugs, or you will run into something critical, give up and just go back to the bifurcated road of maintaining separate versions for print and digital.</p>
<p>So anyway, I started dogfooding &#8230;</p>
<p>When you are developing something like a search function, you set up a keybind, have state of inputs and highlighting work and say: “There, done.”</p>
<p>But when you’re in the trenches in your fullscreen editor, just words on a page, you are not thinking like an engineer. You just need to quickly jump to a word, <strong>right now</strong>. If the search bar behaves even slightly weirdly, if it causes a micro-stutter, or if it messes with your cursor placement, you get irritated immediately.</p>
<p>The more I worked in it, the more annoyances I found and fixed. When something worked well enough that I stopped noticing it, when it became pure muscle memory, I moved on to the next problem.</p>
<p>And it wasn’t just pure UI-stuff either. I&#8217;d spent enough years on these types of materials to know exactly where the landmines were. For example, when creating glossaries with translations, it’s incredibly easy to accidentally mix up the order of words, or delete a definition that a later chapter still relies on.</p>
<p>So I ended up building a whole vocabulary manager tool that can not just keep track of this for me, but even provide a diagnostic view where I can see: “Oh, I’ve defined that word twice in chapter 2 and 4, or I’ve introduced the word in chapter 3 but only referenced it in glossary in chapter 4.”</p>
<div id="attachment_23272" style="width: 1034px" class="wp-caption alignnone"><a href="https://andreklein.net/wp-content/uploads/2026/05/2026-05-17-214708_hyprcap.png"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-23272" class="wp-image-23272 size-large" src="https://andreklein.net/wp-content/uploads/2026/05/2026-05-17-214708_hyprcap-1024x616.png" alt="" width="1024" height="616" srcset="https://andreklein.net/wp-content/uploads/2026/05/2026-05-17-214708_hyprcap-1024x616.png 1024w, https://andreklein.net/wp-content/uploads/2026/05/2026-05-17-214708_hyprcap-300x180.png 300w, https://andreklein.net/wp-content/uploads/2026/05/2026-05-17-214708_hyprcap-768x462.png 768w, https://andreklein.net/wp-content/uploads/2026/05/2026-05-17-214708_hyprcap-1536x924.png 1536w, https://andreklein.net/wp-content/uploads/2026/05/2026-05-17-214708_hyprcap.png 1890w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><p id="caption-attachment-23272" class="wp-caption-text">VocabAnalyzer &#8211; catch continuity errors in glossaries (and ANKI export)</p></div>
<p>Same with exercises. Many of my books have multiple-choice questions scattered throughout the book and an answer key at the end. Manually compiling the answer key, while possible, was time-consuming and prone to errors, especially when doing quick edits where a question had changed its position or correct answer. So I just wired up a tool that could do it deterministically: check all exercise chapters (based on template), grab the correct answers, print in answer key.</p>
<p>There are a bunch of other quality-of-life improvements like these I ended up integrating, not because they would be helpful for some theoretical “user”, but simply because I needed them, because they would relieve very particular kinds of pains I’ve been struggling with for longer than I&#8217;d care to admit.</p>
<p>This includes stuff like: automatic export of glossaries into ANKI <code>.apkg</code> decks, noun gender parsing from dictionary, LanguageTool integration for grammar and spellchecks, EPUB post-processing, on-the-fly image optimization for print/digital, automatic export of truncated preview PDFs and EPUBs, and a million other things.</p>
<h2>10/10 &#8211; Would Dogfood Again</h2>
<p>Looking back over the last couple of months working like this, I can now safely say that the software, while obviously not perfect (I know better than anyone where the bodies are buried), is battle-tested enough and works well enough that I just don’t want to go back to the old way anymore.</p>
<p>Perhaps one day I’ll end up sharing this tool with a wider audience. The “Markdown to typographically perfect PDF and EPUB” is still somewhat of a holy grail, especially for books with complex layouts.</p>
<p>Then again, for now I just want to keep writing and publishing with it and not start a second career as a software support guy.</p>
<p>But if there’s a takeaway: don’t settle for tools and workflows that fight you. Fight back by building your own. Push through the roadblocks, squash the bugs and dogfood until it clicks.</p>
<p>How hard can it be?</p>
<p>&#8211;</p>
<p>The post <a href="https://andreklein.net/building-my-own-markdown-publishing-suite-or-dogfooding-until-it-clicks/">Building My Own Markdown Publishing Suite, or: Dogfooding Until It Clicks</a> appeared first on <a href="https://andreklein.net">André Klein Dot Net</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://andreklein.net/building-my-own-markdown-publishing-suite-or-dogfooding-until-it-clicks/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Fauxmarchy: A Sacrilegious Hyprland/KDE Setup</title>
		<link>https://andreklein.net/fauxmarchy-a-sacrilegious-hyprland-setup/</link>
					<comments>https://andreklein.net/fauxmarchy-a-sacrilegious-hyprland-setup/#respond</comments>
		
		<dc:creator><![CDATA[André Klein]]></dc:creator>
		<pubDate>Wed, 13 May 2026 13:43:03 +0000</pubDate>
				<category><![CDATA[tinker]]></category>
		<guid isPermaLink="false">https://andreklein.net/?p=22894</guid>

					<description><![CDATA[<p>[drop_cap]I[/drop_cap]t’s no secret that minimalist tiling window managers and “full-fat” desktop environments are deeply at odds with each other, both in form and function. That’s why usually when someone wants to get started with Hyprland the recommendation from the Council of Greybeards is: start from scratch (set up a new machine), or at least use [&#8230;]</p>
<p>The post <a href="https://andreklein.net/fauxmarchy-a-sacrilegious-hyprland-setup/">Fauxmarchy: A Sacrilegious Hyprland/KDE Setup</a> appeared first on <a href="https://andreklein.net">André Klein Dot Net</a>.</p>
]]></description>
										<content:encoded><![CDATA[<div id="attachment_23067" style="width: 970px" class="wp-caption alignnone"><a href="https://andreklein.net/wp-content/uploads/2026/05/fauxmarchy.png"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-23067" class="wp-image-23067 size-full" src="https://andreklein.net/wp-content/uploads/2026/05/fauxmarchy.png" alt="" width="960" height="600" srcset="https://andreklein.net/wp-content/uploads/2026/05/fauxmarchy.png 960w, https://andreklein.net/wp-content/uploads/2026/05/fauxmarchy-300x188.png 300w, https://andreklein.net/wp-content/uploads/2026/05/fauxmarchy-768x480.png 768w" sizes="auto, (max-width: 960px) 100vw, 960px" /></a><p id="caption-attachment-23067" class="wp-caption-text">font: <a href="https://patorjk.com/software/taag/#p=display&amp;f=Delta+Corps+Priest+1&amp;t=fauxmarchy&amp;x=none&amp;v=4&amp;h=4&amp;w=80&amp;we=false">Delta Corps Priest 1</a></p></div>
<p>[drop_cap]I[/drop_cap]t’s no secret that minimalist tiling window managers and “full-fat” desktop environments are deeply at odds with each other, both in form and function.</p>
<p>That’s why usually when someone wants to get started with Hyprland the recommendation from the Council of Greybeards is: start from scratch (set up a new machine), or at least use a different user so your Hyprland and KDE or Gnome don’t end up in a turf-war over <code>.config</code> files, GTK/QT theming and whatnot.</p>
<p>And they are right. And so an ironclad decree was forged in the hearts of minds of the unixpr0n community: “Ye who want to taste the Rice must abstain from the ways of the <a href="https://andreklein.net/the-lost-futures-of-computing-how-we-got-boxed-into-the-desktop-metaphor/">regular desktop</a>.”</p>
<p>And I get it, if you spent too many hours jerry-rigging the perfect <code>waybar</code> setup (been there, done that) and have the borders and animation of your <code>rofi</code> or <code>walker</code> dialed in <em>juuust</em> right, you’re in for the long haul.</p>
<p>But what if you want to have your cake and eat it too?</p>
<h2>Tiling Fatigue</h2>
<p>What if sometimes you just want to lazily go about your business with a trackpad without holding down <code>SUPER</code> like a clutch (the <em>audacity</em> &#8230; I know), yet at other times, when inspiration strikes, you are pining for the neon-drenched void of the Hyprland for dev work or bashing out prose in a <a href="https://andreklein.net/helowrite-terminal-word-processor/">brutalist terminal</a>?</p>
<p>&#8220;Well,&#8221; they say. &#8220;You can’t do that! You either learn how to do <em>everything</em> in a tiling window manager or you simply are not <em>worthy</em>.&#8221;</p>
<p>So you ignore them. You set up a new user for Hyprland, but then find yourself “locked out” from your own files, configs, wallet (passwords) and whatnot. And maintaining a whole second account with second configs and everything just for switching your desktop workflow?</p>
<p>That’s no fun.</p>
<p>So for my latest experiment I wired up an ungodly alliance between my KDE Plasma desktop and Hyprland. No different user switching, no endless GTK/QT theming conflicts. Just switch the session whenever you feel like it.</p>
<p>I stole the basic look &amp; feel from “Omarchy”, but since this is neither real “Omarchy” nor even Hyprland in a classical sense (see below), I dub it: “Fauxmarchy”.</p>
<h2>The Masquerade</h2>
<p>To achieve this seamless switch between KDE and Hyprland we are essentially “tricking” Hyprland into thinking it’s KDE with this sacrilegious array of environment variables:</p>
<pre><code>env = QT_QPA_PLATFORMTHEME,kde
env = KDE_FULL_SESSION,true
env = XDG_CURRENT_DESKTOP,KDE
env = KDE_SESSION_VERSION,6
env = DESKTOP_SESSION,plasmawayland
env = GDMSESSION,plasmawayland
env = GTK_USE_PORTAL,1
env = GTK_THEME,Breeze-Dark
env = XDG_MENU_PREFIX,plasma-</code></pre>
<p>I know. It’s ugly, it’s blasphemous. It goes against the grain of everything the Greybeards have taught us. But it’s brutally effective for a number of reasons.</p>
<h3>No More Theming Bullshit</h3>
<p>KDE Plasma has a nice and convenient way of globally styling all GUIs (whether QT or GTK) via their <code>Application Style</code> menu.</p>
<p>To achieve the same in Hyprland you have to fiddle endlessly with <code>nwg-look</code>, <code>qt5ct</code> and <code>qt6ct</code> just so native Linux GUIs don’t look like an ugly stepchild from the Windows era.</p>
<p>But with our unholy environment variables we are basically letting Hyprland <em>inherit</em> the KDE space, no questions asked.</p>
<p>So you could do all your “app styling” in KDE, plop over to a Hyprland session and have it all be registered. No more worries that Hyprland&#8217;s meticulously curated QT/GTK themes will mess up your KDE Plasma look &amp; feel, or vice versa.</p>
<p>Plasma sets the tone, Hyprland follows. Zero conflict. For good measure also wipe all fake envs on exit from Hyprland:</p>
<p><code>bind = CTRL ALT, Q, exec,<br />
QT_QPA_PLATFORMTHEME= KDE_FULL_SESSION= XDG_CURRENT_DESKTOP= KDE_SESSION_VERSION= DESKTOP_SESSION= GDMSESSION= GTK_USE_PORTAL= XDG_MENU_PREFIX=<br />
&amp;&amp; hyprctl dispatch exit</code></p>
<h2>Wallet Woes</h2>
<p>Another annoying issue with switching in between Hyprland and KDE is the “secure storage” issue. You don’t want to constantly re-authenticate everything, just because you switched your session and have Hyprland scream: “new phone who dis?”</p>
<p>By masquerading our Hyprland session as <code>KDE</code> we can bypass all of that. All apps and services can continue using the same wallet, without triggering false-positive “breaches” and forcing re-auth. Because for all intents and purposes we <em>are</em> running a KDE session.</p>
<p>To get the party started without any &#8220;unlock your wallet&#8221; prompts in either KDE or Hyprland, get the <code>kwallet-pam</code> package and then we can directly hook into the wallet as soon as SDDM hands off to our Hyprland Fauxmarchy session. Note: user pw and wallet pw need to be identical for this to work.</p>
<p>In hypr <code>autostart.conf</code> :</p>
<p><code># 1. Export the core Wayland context to the systemd user session<br />
exec-once = dbus-update-activation-environment --systemd WAYLAND_DISPLAY<br />
exec-once = systemctl --user import-environment WAYLAND_DISPLAY<br />
# 2. Force the PAM handshake to claim the decrypted wallet keys left by SDDM<br />
exec-once = /usr/lib/pam_kwallet_init<br />
# 3. Tell the systemd/D-Bus environment that a KDE-compatible desktop is handling secrets<br />
exec-once = dbus-update-activation-environment --systemd DISPLAY XDG_CURRENT_DESKTOP=KDE<br />
</code></p>
<p>And there you have it. One wallet to rule them all.</p>
<h3>KRunner</h3>
<p>Yet another cool thing about this setup is this: no more need for cobbled together app launchers. You can just use KRunner.</p>
<p>I know, right? Is this allowed? Well, usually it won’t work if your <code>XDG_CURRENT_DESKTOP</code> is set to Hyprland. But since we are basically <em>lying</em> to the desktop portal at this point, KRunner works just fine.</p>
<p>It’s extremely fast and more flexible than any other Hyprland launcher I have ever used (search for files, bookmarks, do calculations, whatever) and best of all: no need to install and babysit yet another package.</p>
<h3>But, the bloat!</h3>
<p>So what’s the cost of running a system like this? Because, yes, the <code>xdg-desktop-portal-de</code> sits in RAM now, but at least it uses 0 CPU until called upon.</p>
<p>There&#8217;s a long-running obsession in this community where people scoff at an Electron app using 150MB&#8211;a rounding error on any modern system&#8211;while cheerfully running ten dockerized Alpine containers without a second thought.</p>
<p>Meanwhile the KDE portal service sits at a respectable ~354MB. Not nothing, but not a dent in real-world usage either. And look what it buys you: full KRunner integration, consistent styling across sessions, zero-effort wallet auth.</p>
<p>If your Hyprland config breaks (because it always does during updates), doesn’t matter. Switch to KDE and fix it later. Got tired of Hyprland? No problem. Just remove the <code>~/.config/hypr</code> folder and the packages and you’re back to square one.</p>
<p>No life-long commitment to the “tiling only” workflow. Non-destructive. Best of both worlds.</p>
<h2>Screenshots</h2>
<div id="attachment_23035" style="width: 1034px" class="wp-caption alignnone"><a href="https://andreklein.net/wp-content/uploads/2026/05/unholy.png"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-23035" class="size-large wp-image-23035" src="https://andreklein.net/wp-content/uploads/2026/05/unholy-1024x640.png" alt="" width="1024" height="640" srcset="https://andreklein.net/wp-content/uploads/2026/05/unholy-1024x640.png 1024w, https://andreklein.net/wp-content/uploads/2026/05/unholy-300x188.png 300w, https://andreklein.net/wp-content/uploads/2026/05/unholy-768x480.png 768w, https://andreklein.net/wp-content/uploads/2026/05/unholy-1536x960.png 1536w, https://andreklein.net/wp-content/uploads/2026/05/unholy.png 1920w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><p id="caption-attachment-23035" class="wp-caption-text">The blasphemy: KRunner in Hyprland</p></div>
<div id="attachment_23006" style="width: 1034px" class="wp-caption alignnone"><a href="https://andreklein.net/wp-content/uploads/2026/05/writing.png"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-23006" class="wp-image-23006 size-large" src="https://andreklein.net/wp-content/uploads/2026/05/writing-1024x640.png" alt="" width="1024" height="640" srcset="https://andreklein.net/wp-content/uploads/2026/05/writing-1024x640.png 1024w, https://andreklein.net/wp-content/uploads/2026/05/writing-300x188.png 300w, https://andreklein.net/wp-content/uploads/2026/05/writing-768x480.png 768w, https://andreklein.net/wp-content/uploads/2026/05/writing-1536x960.png 1536w, https://andreklein.net/wp-content/uploads/2026/05/writing.png 1920w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><p id="caption-attachment-23006" class="wp-caption-text">HeloWrite and Dolphin and pushing markdown to blog</p></div>
<div id="attachment_23009" style="width: 1034px" class="wp-caption alignnone"><a href="https://andreklein.net/wp-content/uploads/2026/05/audio.png"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-23009" class="size-large wp-image-23009" src="https://andreklein.net/wp-content/uploads/2026/05/audio-1024x640.png" alt="" width="1024" height="640" srcset="https://andreklein.net/wp-content/uploads/2026/05/audio-1024x640.png 1024w, https://andreklein.net/wp-content/uploads/2026/05/audio-300x188.png 300w, https://andreklein.net/wp-content/uploads/2026/05/audio-768x480.png 768w, https://andreklein.net/wp-content/uploads/2026/05/audio-1536x960.png 1536w, https://andreklein.net/wp-content/uploads/2026/05/audio.png 1920w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><p id="caption-attachment-23009" class="wp-caption-text">just some audio TUI goodness</p></div>
<p>Now I can go from the above workflow to the below and back, by just switching the desktop session (note how the QT GUIs retain their styling):</p>
<div id="attachment_23101" style="width: 1034px" class="wp-caption alignnone"><a href="https://andreklein.net/wp-content/uploads/2026/05/fullfat.png"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-23101" class="size-large wp-image-23101" src="https://andreklein.net/wp-content/uploads/2026/05/fullfat-1024x640.png" alt="" width="1024" height="640" srcset="https://andreklein.net/wp-content/uploads/2026/05/fullfat-1024x640.png 1024w, https://andreklein.net/wp-content/uploads/2026/05/fullfat-300x188.png 300w, https://andreklein.net/wp-content/uploads/2026/05/fullfat-768x480.png 768w, https://andreklein.net/wp-content/uploads/2026/05/fullfat-1536x960.png 1536w, https://andreklein.net/wp-content/uploads/2026/05/fullfat.png 1920w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><p id="caption-attachment-23101" class="wp-caption-text">no actual EPUBS were harmed in the making of this screenshot</p></div>
<p>And yes, both workflows have their upsides and downsides. For office and publishing work I prefer the organized mess of floating windows, for dev stuff or raw writing, there&#8217;s nothing better than the Way of the Tile. Why limit yourself to one? Just switch depending on context. And the best part:</p>
<p>No config pollution (just a neat <code>hypr</code> folder in <code>.config</code> ripped straight from the Omarchy repo, plus a few <code>waybar</code> edits and fresh keybinds). And it didn’t even take an ungodly amount of packages:</p>
<pre><code>hyprland waybar awww hyprlock
bluetui wiremix hyprpicker wlctl
wl-clipboard swayosd hyprshot</code></pre>
<p>The Greybeards will not approve. But they never do. Switch sessions whenever you feel like it, fix Hyprland when it inevitably breaks, and go back to clicking things with a mouse without shame. The rice will still be there when you need it.</p>
<p>&#8211;</p>
<p>P.S: By masquerading as &#8220;KDE&#8221;, Hyprland will complain on launch that &#8220;Your <code>XDG_CURRENT_DESKTOP</code> environment seems to be managed externally. This might cause issues unless it&#8217;s intentional.&#8221;</p>
<p>Since this is <em>definitely </em>intentional you can bypass that warning by dropping this into your <code>hyprland.conf</code>:</p>
<p><code>misc {<br />
disable_xdg_env_checks = true<br />
}</code></p>
<p>P.P.S: Of course I also had to implement the screensaver in true <em>Fauxmarchy</em> fashion. Just <code>tte</code> and a text file:</p>
<p><iframe loading="lazy" title="Fauxmarchy Screensaver" width="500" height="375" src="https://www.youtube.com/embed/ZICzZV9gh2Y?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe></p>
<p>The post <a href="https://andreklein.net/fauxmarchy-a-sacrilegious-hyprland-setup/">Fauxmarchy: A Sacrilegious Hyprland/KDE Setup</a> appeared first on <a href="https://andreklein.net">André Klein Dot Net</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://andreklein.net/fauxmarchy-a-sacrilegious-hyprland-setup/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Vault Dweller: How I Ditched The Cloud For A Pi And A Git Repo</title>
		<link>https://andreklein.net/vault-dweller-how-i-ditched-the-cloud-for-a-pi-and-a-git-repo/</link>
					<comments>https://andreklein.net/vault-dweller-how-i-ditched-the-cloud-for-a-pi-and-a-git-repo/#respond</comments>
		
		<dc:creator><![CDATA[André Klein]]></dc:creator>
		<pubDate>Thu, 07 May 2026 21:14:33 +0000</pubDate>
				<category><![CDATA[tinker]]></category>
		<guid isPermaLink="false">https://andreklein.net/?p=22767</guid>

					<description><![CDATA[<p>[drop_cap]I[/drop_cap] never understood all the hype around Obsidian as &#8220;second brain&#8221;, and the way some people throw around the German word Zettelkasten like some obscure grand cru vintage. As if the gritty business of memorization had a dress code. (By the way, the German &#8220;Z&#8221; here is a hard &#8220;ts&#8221;, not soft &#8220;z&#8221; as in [&#8230;]</p>
<p>The post <a href="https://andreklein.net/vault-dweller-how-i-ditched-the-cloud-for-a-pi-and-a-git-repo/">Vault Dweller: How I Ditched The Cloud For A Pi And A Git Repo</a> appeared first on <a href="https://andreklein.net">André Klein Dot Net</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a href="https://andreklein.net/wp-content/uploads/2026/05/fauxgritte.webp"><img loading="lazy" decoding="async" class="alignnone size-large wp-image-22839" src="https://andreklein.net/wp-content/uploads/2026/05/fauxgritte-1024x683.webp" alt="" width="1024" height="683" srcset="https://andreklein.net/wp-content/uploads/2026/05/fauxgritte-1024x683.webp 1024w, https://andreklein.net/wp-content/uploads/2026/05/fauxgritte-300x200.webp 300w, https://andreklein.net/wp-content/uploads/2026/05/fauxgritte-768x512.webp 768w, https://andreklein.net/wp-content/uploads/2026/05/fauxgritte.webp 1536w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>[drop_cap]I[/drop_cap] never understood all the hype around Obsidian as &#8220;second brain&#8221;, and the way some people throw around the German word <em>Zettelkasten</em> like some obscure grand cru vintage. As if the gritty business of memorization had a dress code.</p>
<p>(By the way, the German &#8220;Z&#8221; here is a hard &#8220;ts&#8221;, not soft &#8220;z&#8221; as in &#8220;zoom&#8221;, so at least get it right. But I digress &#8230;)</p>
<p>&#8220;Look&#8221;, the Obsidian snobs sneered from within their meticulously organized vaults: &#8220;If you don&#8217;t organize <em>everything</em> you do in markdown, you&#8217;ve already lost control of your life.&#8221;</p>
<p>I pressed &#8220;x&#8221; for doubt. Hard. And kept on pressing.</p>
<p>For years I was perfectly fine just stuffing various notes about my <a href="/books">books</a> into Evernote (before the SaaS-mandated nickel-and-diming started) or even just randomish <code>important.txt</code> and <code>todo_BK.txt</code> scattered around my local filesystem and cloud drives like demented breadcrumbs.</p>
<p>Then I started messing around with <a href="https://andreklein.net/2025-the-year-of-the-linux-desktop-for-me-anyway">Linux</a> last year, and suddenly, I had to keep track of a host of different configs, strange dotfile quirks, custom <code>systemd</code> services, <code>cmdline</code> flags, <code>fstab</code> mounts and a million other things.</p>
<p>So I gave Obsidian another try.</p>
<p>And no, before you ask &#8212; I haven&#8217;t gulped down the kool-aid. I still only use about 1% of Obsidian features. In fact, I barely ever open the app.</p>
<p>What I did embrace was the idea of &#8220;markdown files in folder&#8221; as a kind of poor man&#8217;s database. Similarly to how <a href="https://andreklein.net/i-went-back-to-boring-web-dev-and-im-not-sorry">HTMX</a> treats the DOM as state rather than a separate layer, with this paradigm of plaintext in folders and subfolders, the filetree <em>is</em> the database. Relations are mapped transparently, right there in front of you.</p>
<p>No proprietary lock-in. No esoteric SQL invocations. Extremely light-weight, low-friction and portable.</p>
<p>It was glorious.</p>
<p>And the more I worked in this way, the more I started applying this principle to other arenas. For example, I&#8217;ve been building a new <a href="https://andreklein.net/building-my-own-markdown-publishing-suite-or-dogfooding-until-it-clicks/">publishing suite</a> for my books where I can go from one codebase of raw markdown to typographically perfect PDFs (via TYPST) and EPUB.</p>
<p>Database? Nah. Just <code>chapter1.md</code> in a <code>mybook</code> folder. Done.</p>
<h2>So, what do you Sync?</h2>
<p>Since I barely use the official Obsidian app anymore, their proprietary sync mechanism is useless to me.</p>
<p>My &#8220;vaults&#8221; are just git repositories. Easy to commit, push and pull, from wherever I need.</p>
<p>And no, I am not letting Microsoft get their mittens on my &#8220;second brain&#8221;. No GitHub roundtrips here. I just have a bare repo sitting on my (diet)Pi, which acts as upstream source to all my devices. Just simple <code>ssh git</code> straight over local network.</p>
<p>And thanks to Tailscale I can now be &#8220;at home&#8221; even when away from home and push to my private local repo. It&#8217;s beautiful.</p>
<p>And for the purists: Yes, Tailscale is &#8216;managed&#8217; WireGuard. But I&#8217;m here to get stuff done, not spend three days manually configuring handshake keys. It’s the same logic as using CachyOS over a manual Arch bootstrap. Pragmatism isn&#8217;t betrayal.</p>
<p>I was only left with one gap in that setup. Since the two biggest mobile operating systems (IOS/Android) are lobotomized bricks in terms of basic file system access, it makes it very difficult to run direct git operations, unless you jump through a million hoops.</p>
<p>So I ended up building a little React app (I know, famous last words &#8230;) that talks to a tiny gunicorn backend on my Pi. And now I can have direct access to my notes from anywhere in the world, completely local, no proprietary apps or any nonsense.</p>
<p><a href="https://andreklein.net/wp-content/uploads/2026/05/reactus.webp"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-22864" src="https://andreklein.net/wp-content/uploads/2026/05/reactus.webp" alt="" width="746" height="663" srcset="https://andreklein.net/wp-content/uploads/2026/05/reactus.webp 746w, https://andreklein.net/wp-content/uploads/2026/05/reactus-300x267.webp 300w" sizes="auto, (max-width: 746px) 100vw, 746px" /></a></p>
<p>Not to make this seem like a &#8220;sponsored post&#8221; for Tailscale, but thanks to Tailscale&#8217;s HTTPS certificate feature, I was even able to install my little React app as a PWA, and now this thing just runs in standalone mode, virtually indistinguishable from a &#8220;real&#8221; app.</p>
<p>Pretty neat.</p>
<p>And I&#8217;m taking more notes than ever before. Linking, cross-linking, folders within folders. A glorious sprawling web of untethered information. And I&#8217;m never going back.</p>
<h2>The Atomic Parade</h2>
<p>As usual, all that glitters is not gold. The atomic file writing operations of this &#8220;markdown as database&#8221; paradigm can be problematic. On Linux this is very transparent where <code>inotify</code> is screaming at every daemon on the system. When you try to combine this with cloud stuff like abraunegg&#8217;s onedrive client, all hell breaks loose.</p>
<p>The official Obsidian app for some reason has still no way to <a href="https://forum.obsidian.md/t/disable-auto-save-or-change-frequency/14230/123?page=7">disable auto-save</a> or at least stagger saves, and this stuff can get chaotic <em>fast</em>.</p>
<blockquote><p>Obsidian provides no mechanism to change how this save behaviour operates. This is a serious design limitation and should be treated as a bug in the application &#8211; <a href="https://github.com/abraunegg/onedrive/blob/master/docs/usage.md#compatibility-with-obsidian">abraunegg</a></p></blockquote>
<h2>Of Backups And Unicorns</h2>
<p>For my new local-first Pi-based setup, I am literally my own one person Git provider. It&#8217;s insanely fast, but it also means, if the Pi goes bye bye, I lose my upstream.</p>
<p>But when Microsoft has a bad day and GitHub&#8217;s &#8216;Unicorn&#8217; starts puking 500 errors, the entire world stops coding. When my Pi hangs, I just walk into the other room and power cycle it. I’d rather be my own sysadmin than a helpless passenger on a sinking corporate ship.</p>
<p>My mitigation is simple: the Pi just dumps encrypted vault backups in the middle of the night to an offsite server. So: multiple local copies, across different media/devices, plus offsite backup. Belt and suspenders.</p>
<p>&#8211;</p>
<p>The post <a href="https://andreklein.net/vault-dweller-how-i-ditched-the-cloud-for-a-pi-and-a-git-repo/">Vault Dweller: How I Ditched The Cloud For A Pi And A Git Repo</a> appeared first on <a href="https://andreklein.net">André Klein Dot Net</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://andreklein.net/vault-dweller-how-i-ditched-the-cloud-for-a-pi-and-a-git-repo/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>I Went Back to Boring Web Dev, and I&#8217;m Not Sorry</title>
		<link>https://andreklein.net/i-went-back-to-boring-web-dev-and-im-not-sorry/</link>
					<comments>https://andreklein.net/i-went-back-to-boring-web-dev-and-im-not-sorry/#respond</comments>
		
		<dc:creator><![CDATA[André Klein]]></dc:creator>
		<pubDate>Thu, 30 Apr 2026 14:54:48 +0000</pubDate>
				<category><![CDATA[tinker]]></category>
		<guid isPermaLink="false">https://andreklein.net/?p=22671</guid>

					<description><![CDATA[<p>[drop_cap]I[/drop_cap] built my first home page in 1996 in Microsoft FrontPage. It looked like a digital ransom note, but it was mine. Instantly accessible from anywhere in the world, without permission, like global graffiti. In the early 2000s, like many others, I learned CSS by endlessly customizing MySpace profiles. Turns out learning to type the [&#8230;]</p>
<p>The post <a href="https://andreklein.net/i-went-back-to-boring-web-dev-and-im-not-sorry/">I Went Back to Boring Web Dev, and I&#8217;m Not Sorry</a> appeared first on <a href="https://andreklein.net">André Klein Dot Net</a>.</p>
]]></description>
										<content:encoded><![CDATA[<div id="attachment_22750" style="width: 1034px" class="wp-caption alignnone"><a href="https://andreklein.net/wp-content/uploads/2026/04/10-180.jpg"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-22750" class="size-full wp-image-22750" src="https://andreklein.net/wp-content/uploads/2026/04/10-180.jpg" alt="" width="1024" height="553" srcset="https://andreklein.net/wp-content/uploads/2026/04/10-180.jpg 1024w, https://andreklein.net/wp-content/uploads/2026/04/10-180-300x162.jpg 300w, https://andreklein.net/wp-content/uploads/2026/04/10-180-768x415.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><p id="caption-attachment-22750" class="wp-caption-text">Brazil (1985)</p></div>
<p>[drop_cap]I[/drop_cap] built my first home page in 1996 in Microsoft FrontPage. It looked like a digital ransom note, but it was mine. Instantly accessible from anywhere in the world, without permission, like global graffiti.</p>
<p>In the early 2000s, like many others, I learned CSS by endlessly customizing MySpace profiles. Turns out learning to type the same HTML and CSS tags over and over again actually does wonders for remembering. I wonder if prompting Claude Code has similar effects. Probably not.</p>
<p>Then I got into WordPress and PHP, and that&#8217;s basically where I&#8217;ve been ever since—the constant hype-cycle of new JS frameworks nothing but a faint murmur beyond the walls of my trusty LEMP stack.</p>
<p>Until very recently, my &#8220;version control&#8221; system consisted of renaming files to <code>index_FINAL_v2_FIXED_FOR_REAL.php.BAK</code>. My &#8220;deployment pipeline&#8221; was an SFTP client and a prayer. If the site broke, I edited the live code on the server while users watched. It was stupid, and I knew it, but I had other things to worry about.</p>
<p>I&#8217;m not a developer in the classical sense. My identity isn&#8217;t tied to &#8220;the craft&#8221;. I love messing around with tech, but at the end of the day I just need stuff to work so I can publish my books and get back to writing.</p>
<h2><strong>A Brave New World</strong></h2>
<p>Last year I got the Modern Dev itch. I jumped into React and Tailwind, and Vite&#8217;s hot module reload is a blast—seeing a color change instantly without a browser refresh almost made me forget I was building a single-page app held aloft by a rickety stack of ever-shifting npm modules. I finally even learned Git (though I still treat rebasing like a dark ritual that might accidentally delete my hard drive).</p>
<p>Then I needed a contact form.</p>
<p>Suddenly I wasn&#8217;t a writer anymore; I was a civil servant in a Terry Gilliam movie, shuffling JSON through pneumatic tubes just to appease the Gods of TypeScript. I was spinning up Next.js instances, worrying about serialization and environment variables, and spending three days building a space station just to send an email that says &#8220;Hi.&#8221; I&#8217;d traded my sanity for a <code>node_modules</code> folder spilling out clown-cars of esoteric dependencies.</p>
<p>Meanwhile, PHP has no build step. You write, you execute, you&#8217;re done. A PHP process runs and dies with the request—no long-running Node processes accumulating memory, no weekly vulnerability disclosures in your 47 transitive dependencies. These modern frameworks were designed by massive engineering teams at companies obsessed with scale. That&#8217;s fine for them. I&#8217;m just one dude.</p>
<p>So I tried headless WordPress—React on the front end, WordPress handling auth, email, and content management behind it, all pre-configured. It worked great, even if you accept that most of your plugins are basically useless now.</p>
<p>Then I hit the hydration problem. A single-page app is basically an empty HTML file that loads a giant JavaScript bundle, and search engines hate it. So now you need <em>two</em> versions of your site: a skeleton and the actual interface layered on top. I got it working, eventually, by mixing in some PHP. Very much reinventing the wheel. Not as bad as running your own Next.js &#8220;vulnerability accelerator,&#8221; but still annoying enough.</p>
<blockquote><p>&#8220;In 2025, attackers published 454,648 malicious npm packages. The average npm project pulls in 79 transitive dependencies. A single compromised package can cascade through entire ecosystems within hours.&#8221;<cite><a href="https://blog.cyberdesserts.com/npm-security-vulnerabilities/">cyberdesserts.com</a></cite></p></blockquote>
<h2>Back To Basics</h2>
<p>For my last two projects I went a different direction: <a href="https://htmx.org/">HTMX</a> and <a href="https://alpinejs.dev/">Alpine.js</a>. Two tiny libraries that give you 80% of React&#8217;s interactivity at maybe 10% of the complexity. No build step, no dependency hell, no fresh CVEs landing in your inbox on a Tuesday morning. You write HTML, sprinkle in a few attributes, and things respond dynamically. It&#8217;s not as slick as React with Vite, but the friction it removes makes the tradeoff feel obvious.</p>
<p>But the real kicker is the stability. React code from <del>three years</del> one week ago is usually a graveyard of deprecated hooks and broken builds. PHP and HTML? They just sit there and work. Modern web dev feels like babysitting a Tamagotchi that dies if I don’t massage it with npm audits and overrides every second day.</p>
<p>My current happy place is WordPress as the backend with a lean HTMX/Alpine theme on top, developed locally with LocalWP, versioned in Git, and deployed with a simple bash script. I&#8217;m not pretending the last few years didn&#8217;t happen—I just got selective about which parts to keep.</p>
<h2>How The Sausage is Made</h2>
<p>Let&#8217;s have a look at some concrete examples to better illustrate the madness:</p>
<h3><strong>Exhibit A: Search Suggestions</strong></h3>
<p>With React/Next.js/TS you need a Client Component, a Debounce Hook, a Fetcher, a JSON API route, and a TypeScript interface for the &#8220;Shape&#8221; of a Post:</p>
<p><a href="https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-42-27.png"><img loading="lazy" decoding="async" class="alignnone size-large wp-image-22722" src="https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-42-27-1024x696.png" alt="" width="1024" height="696" srcset="https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-42-27-1024x696.png 1024w, https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-42-27-300x204.png 300w, https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-42-27-768x522.png 768w, https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-42-27.png 1456w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>So far so good, right? But, wait! That&#8217;s only the front-end. Now go write the <code>api/search.ts</code> route, define the Post interface twice, once for the API route, once for the front-end, naturally. Oh, and don&#8217;t forget to fix the hydration error because the server time doesn&#8217;t match the client time&#8230;</p>
<p>Now let&#8217;s look at the &#8220;boring&#8221; alternative with HTMX. You don&#8217;t manage state; the DOM is the state.</p>
<p><a href="https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-46-58.png"><img loading="lazy" decoding="async" class="alignnone size-large wp-image-22725" src="https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-46-58-1024x306.png" alt="" width="1024" height="306" srcset="https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-46-58-1024x306.png 1024w, https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-46-58-300x90.png 300w, https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-46-58-768x230.png 768w, https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-46-58.png 1498w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Yup, that&#8217;s it. That&#8217;s the whole code. Back-end? Eh. Let WordPress spit out HTML. Done.</p>
<h3>Exhibit B: A Simple Toggle Or Drop-Down</h3>
<p>With React this would look something like this:</p>
<p><a href="https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-48-32.png"><img loading="lazy" decoding="async" class="alignnone size-large wp-image-22726" src="https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-48-32-1024x326.png" alt="" width="1024" height="326" srcset="https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-48-32-1024x326.png 1024w, https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-48-32-300x95.png 300w, https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-48-32-768x244.png 768w, https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-48-32.png 1472w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>With Alpine you can do the same, but with fewer lines and no bureaucratic javascript wrangling parade:</p>
<p><a href="https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-49-32.png"><img loading="lazy" decoding="async" class="alignnone size-large wp-image-22727" src="https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-49-32-1024x168.png" alt="" width="1024" height="168" srcset="https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-49-32-1024x168.png 1024w, https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-49-32-300x49.png 300w, https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-49-32-768x126.png 768w, https://andreklein.net/wp-content/uploads/2026/04/screenshot-2026-04-30_23-49-32.png 1500w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Don’t get me wrong—I haven’t completely thrown in the towel. I still maintain <a href="https://andreklein.net/project-category/react">a few SPAs</a> in React (including this headless blog) where a high-fidelity interface actually justifies the headache. But it&#8217;s simply not <em>always</em> worth the trouble. Sometimes the old way (turbocharged with some HTMX and Alpine) is just fine.</p>
<p>Maybe it&#8217;s a step backwards. I don&#8217;t care. As long as the site loads fast, my code is readable, and I can get back to doing actual work.</p>
<p>We&#8217;ve spent a decade making the web harder to build just so we can feel more important. I&#8217;m over it. I&#8217;ll take a boring site that works over a cutting-edge one that turns basic maintenance into a second job.</p>
<p>&#8211;</p>
<p>The post <a href="https://andreklein.net/i-went-back-to-boring-web-dev-and-im-not-sorry/">I Went Back to Boring Web Dev, and I&#8217;m Not Sorry</a> appeared first on <a href="https://andreklein.net">André Klein Dot Net</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://andreklein.net/i-went-back-to-boring-web-dev-and-im-not-sorry/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Create a Global Color Picker Hotkey in KDE Plasma (Without Widgets)</title>
		<link>https://andreklein.net/how-to-create-a-global-color-picker-hotkey-in-kde-plasma-without-widgets/</link>
					<comments>https://andreklein.net/how-to-create-a-global-color-picker-hotkey-in-kde-plasma-without-widgets/#respond</comments>
		
		<dc:creator><![CDATA[André Klein]]></dc:creator>
		<pubDate>Fri, 17 Apr 2026 22:06:14 +0000</pubDate>
				<category><![CDATA[tinker]]></category>
		<guid isPermaLink="false">https://andreklein.net/?p=22637</guid>

					<description><![CDATA[<p>If you need a color picker regularly enough but not every five minutes, keeping a widget on your panel 24/7 may be overkill. I prefer a global hotkey that triggers a picker and stays hidden otherwise. And we can hook right into the default KDE color picker, no need for additional packages. The Solution: KWin [&#8230;]</p>
<p>The post <a href="https://andreklein.net/how-to-create-a-global-color-picker-hotkey-in-kde-plasma-without-widgets/">How to Create a Global Color Picker Hotkey in KDE Plasma (Without Widgets)</a> appeared first on <a href="https://andreklein.net">André Klein Dot Net</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>If you need a color picker regularly enough but not every five minutes, keeping a widget on your panel 24/7 may be overkill.</p>
<p>I prefer a global hotkey that triggers a picker and stays hidden otherwise. And we can hook right into the default KDE color picker, no need for additional packages.</p>
<div id="attachment_22639" style="width: 325px" class="wp-caption alignnone"><a href="https://andreklein.net/wp-content/uploads/2026/04/colorpicker.png"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-22639" class="wp-image-22639 size-full" src="https://andreklein.net/wp-content/uploads/2026/04/colorpicker.png" alt="" width="315" height="40" srcset="https://andreklein.net/wp-content/uploads/2026/04/colorpicker.png 315w, https://andreklein.net/wp-content/uploads/2026/04/colorpicker-300x38.png 300w" sizes="auto, (max-width: 315px) 100vw, 315px" /></a><p id="caption-attachment-22639" class="wp-caption-text">the default widget is minimalist, but still distracting</p></div>
<h2>The Solution: KWin D-Bus</h2>
<p>We can do this by tapping directly into the KWin compositor using D-Bus. It&#8217;s fast and just works.</p>
<p><code><br />
dbus-send --print-reply --dest=org.kde.KWin /ColorPicker org.kde.kwin.ColorPicker.pick<br />
</code></p>
<p>This will run the color picker. Pick a spot and click. As you will see it returns a uint32 (a big number), and we&#8217;ll need to convert that to a Hex code in the next step.</p>
<p><a href="https://andreklein.net/wp-content/uploads/2026/04/dbus.png"><img loading="lazy" decoding="async" class="alignnone size-large wp-image-22640" src="https://andreklein.net/wp-content/uploads/2026/04/dbus-1024x152.png" alt="" width="1024" height="152" srcset="https://andreklein.net/wp-content/uploads/2026/04/dbus-1024x152.png 1024w, https://andreklein.net/wp-content/uploads/2026/04/dbus-300x44.png 300w, https://andreklein.net/wp-content/uploads/2026/04/dbus-768x114.png 768w, https://andreklein.net/wp-content/uploads/2026/04/dbus.png 1270w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h2>The One-Liner</h2>
<p><strong>For Wayland:</strong></p>
<p><code><br />
dbus-send --print-reply --dest=org.kde.KWin /ColorPicker org.kde.kwin.ColorPicker.pick | awk '/uint32/ {printf "#%06x\n", $2 % 16777216}' | wl-copy<br />
</code></p>
<p>This will run the color picker, convert the uint32 to hex and shove it straight into your clipboard, ready to be pasted.</p>
<p><strong>For X11:</strong><br />
Swap wl-copy for xclip -selection clipboard.</p>
<h2>Set the Global Hotkey</h2>
<p>Don&#8217;t wrap this in a shell script unless you have to. KDE can handle this natively:</p>
<ul>
<li>Open System Settings &gt; Shortcuts.</li>
<li>Go to Commands and click Add New.</li>
<li>Name: Global Color Picker.</li>
<li>Command: Paste the one-liner above.</li>
<li>Shortcut: Assign your favorite combo (e.g., Meta+Shift+C).</li>
<li>Hit Apply.</li>
</ul>
<p>And there you go. No wasted visual space. Just instant color pickings whenever you need it.</p>
<p>&#8211;</p>
<p>The post <a href="https://andreklein.net/how-to-create-a-global-color-picker-hotkey-in-kde-plasma-without-widgets/">How to Create a Global Color Picker Hotkey in KDE Plasma (Without Widgets)</a> appeared first on <a href="https://andreklein.net">André Klein Dot Net</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://andreklein.net/how-to-create-a-global-color-picker-hotkey-in-kde-plasma-without-widgets/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>The End-Boss of Linux Formatting: RTL Annotations in PDF</title>
		<link>https://andreklein.net/the-end-boss-of-linux-formatting-rtl-annotations-in-pdf/</link>
					<comments>https://andreklein.net/the-end-boss-of-linux-formatting-rtl-annotations-in-pdf/#respond</comments>
		
		<dc:creator><![CDATA[André Klein]]></dc:creator>
		<pubDate>Sun, 08 Mar 2026 14:38:13 +0000</pubDate>
				<category><![CDATA[tinker]]></category>
		<guid isPermaLink="false">https://andreklein.net/?p=22615</guid>

					<description><![CDATA[<p>Getting RTL (right-to-left) language annotations to render correctly in Linux PDF apps is the absolute end-boss of formatting. It doesn&#8217;t matter which app you use—Okular, Master PDF Editor, or whatever else is in the repos—they all seem to have a vendetta against the &#8220;wrong side of the road&#8221; languages like Hebrew, Arabic, Farsi, Urdu, Pashto, [&#8230;]</p>
<p>The post <a href="https://andreklein.net/the-end-boss-of-linux-formatting-rtl-annotations-in-pdf/">The End-Boss of Linux Formatting: RTL Annotations in PDF</a> appeared first on <a href="https://andreklein.net">André Klein Dot Net</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Getting RTL (right-to-left) language annotations to render correctly in Linux PDF apps is the absolute end-boss of formatting. It doesn&#8217;t matter which app you use—Okular, Master PDF Editor, or whatever else is in the repos—they all seem to have a vendetta against the &#8220;wrong side of the road&#8221; languages like Hebrew, Arabic, Farsi, Urdu, Pashto, etc.</p>
<p>As soon as I try to paste in an annotation saying, for example, &#8220;שלום&#8221; (shalom), it looks alright in the modal, although the left alignment is already an early warning sign that this isn&#8217;t fully parsed as RTL text:</p>
<p><a href="https://andreklein.net/wp-content/uploads/2026/03/modal.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-22616" src="https://andreklein.net/wp-content/uploads/2026/03/modal.png" alt="" width="864" height="471" srcset="https://andreklein.net/wp-content/uploads/2026/03/modal.png 864w, https://andreklein.net/wp-content/uploads/2026/03/modal-300x164.png 300w, https://andreklein.net/wp-content/uploads/2026/03/modal-768x419.png 768w" sizes="auto, (max-width: 864px) 100vw, 864px" /></a></p>
<p>But as soon as I hit &#8220;OK&#8221;? It flips. It renders as &#8220;םולש&#8221; (molash).</p>
<p><a href="https://andreklein.net/wp-content/uploads/2026/03/render.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-22617" src="https://andreklein.net/wp-content/uploads/2026/03/render.png" alt="" width="485" height="173" srcset="https://andreklein.net/wp-content/uploads/2026/03/render.png 485w, https://andreklein.net/wp-content/uploads/2026/03/render-300x107.png 300w" sizes="auto, (max-width: 485px) 100vw, 485px" /></a></p>
<p>I work with Hebrew PDF documents constantly, and this has been a consistent blight on my otherwise happy Linux life. I even went so far as to try patching Okular (my favorite PDF app, if you couldn&#8217;t tell), but my C++ skills weren&#8217;t enough to defeat the beast.</p>
<p>And then it hit me. The glorious solution to this annoying problem. It is hacky as hell. In fact, it is such a gloriously dirty fix that one might almost call it elegant.</p>
<h2>The RTL Fixer Script</h2>
<p>I present to you the RTL Fixer: four lines (three if you’re a minimalist who hates notifications) of glorious letter reversal.</p>
<p><code>#!/bin/bash<br />
content=$(wl-paste)<br />
reversed=$(echo "$content" | rev)<br />
echo -n "$reversed" | wl-copy<br />
notify-send "Clipboard reversed" "$reversed"</code></p>
<p>What does it do? Exactly what it says on the tin. It takes whatever is in your clipboard, reverses the character order, and shoves it back into the clipboard.</p>
<h2>The Workflow</h2>
<p>Once bound to a hotkey (I use Alt+R), the workflow is seamless:</p>
<ul>
<li>Type your RTL text.</li>
<li>Select and copy it. (CTRL+A, CTRL+C)</li>
<li>Hit Alt+R.</li>
<li>Paste it. (CTRL+V)</li>
</ul>
<p>Enjoy your correctly rendered RTL text. (Of course, if you hate this 4-hotkey-pronged workflow, you could easily chain them, but for the sake of this post, let&#8217;s keep it simple.)</p>
<p>It works because the PDF viewer is going to reverse the letters anyway, so we’re just preemptively reversing them so they land in the &#8220;wrong&#8221; order, which makes them look right. It’s double-negative logic for the digital age.</p>
<p>And there you have it. Finally! RTL annotations in Linux PDF apps. Just as the good Lord intended. Well, strike that. The PDF format is clearly the devil’s work.</p>
<h2>The &#8220;Legacy&#8221; Edition (X11)</h2>
<p>I see you over there, still clinging to Xorg like a comforting, slightly buggy security blanket. If you aren’t on Wayland yet, the wl-clipboard tools won&#8217;t help you. You&#8217;ll need xclip installed.</p>
<p>Your version of the &#8220;dirty fix&#8221; looks like this:</p>
<p><code>#!/bin/bash<br />
content=$(xclip -selection clipboard -o)<br />
reversed=$(echo "$content" | rev)<br />
echo -n "$reversed" | xclip -selection clipboard<br />
notify-send "Clipboard reversed" "$reversed"</code></p>
<p>Same logic, different plumbing.</p>
<h2>A Small Warning for the Multiline-Enthusiasts</h2>
<p>Because we are using the rev command, this script is a &#8220;dumb&#8221; character-by-character flipper. It works flawlessly for single lines or short phrases. However, if you try to reverse a three-paragraph manifesto, it will reverse the entire string: meaning your last line will become your first line, and your brain will melt trying to read it.</p>
<p>Stick to one line at a time, and you’ll be golden.</p>
<p>Anyway, perhaps this will help someone else out there in the struggle. Or perhaps the PDF reader maintainers will eventually fix the BiDi engine.</p>
<p>Then again, I&#8217;m not holding my breath. The Venn diagram of &#8220;Linux Desktop Users&#8221; and &#8220;RTL-enjoyers&#8221; is probably not a massive circle.</p>
<p>In the meantime, I will keep calm and hit Alt+R.</p>
<p>Molash&#8230; I mean, <strong>Shalom</strong>.</p>
<p>&#8211;</p>
<p>The post <a href="https://andreklein.net/the-end-boss-of-linux-formatting-rtl-annotations-in-pdf/">The End-Boss of Linux Formatting: RTL Annotations in PDF</a> appeared first on <a href="https://andreklein.net">André Klein Dot Net</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://andreklein.net/the-end-boss-of-linux-formatting-rtl-annotations-in-pdf/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Taming WSL into a Tactical Workbench For A Terminal-First Workflow</title>
		<link>https://andreklein.net/taming-wsl-into-a-tactical-workbench-for-a-terminal-first-workflow/</link>
					<comments>https://andreklein.net/taming-wsl-into-a-tactical-workbench-for-a-terminal-first-workflow/#respond</comments>
		
		<dc:creator><![CDATA[André Klein]]></dc:creator>
		<pubDate>Sat, 07 Feb 2026 15:47:41 +0000</pubDate>
				<category><![CDATA[tinker]]></category>
		<guid isPermaLink="false">https://andreklein.net/?p=22475</guid>

					<description><![CDATA[<p>[drop_cap]L[/drop_cap]ast year, I moved to CachyOS on my laptop. I expected a different Kernel. I was ready to do some things differently. What I didn&#8217;t expect was a total disruption of my workflow. Not just on that Linux machine, but across any other machine I would touch afterward. Once you get familiar with Linux&#8217;s terminal-first [&#8230;]</p>
<p>The post <a href="https://andreklein.net/taming-wsl-into-a-tactical-workbench-for-a-terminal-first-workflow/">Taming WSL into a Tactical Workbench For A Terminal-First Workflow</a> appeared first on <a href="https://andreklein.net">André Klein Dot Net</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a href="https://andreklein.net/wp-content/uploads/2026/02/90s.webp"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-22486" src="https://andreklein.net/wp-content/uploads/2026/02/90s.webp" alt="" width="900" height="663" srcset="https://andreklein.net/wp-content/uploads/2026/02/90s.webp 900w, https://andreklein.net/wp-content/uploads/2026/02/90s-300x221.webp 300w, https://andreklein.net/wp-content/uploads/2026/02/90s-768x566.webp 768w" sizes="auto, (max-width: 900px) 100vw, 900px" /></a></p>
<p>[drop_cap]L[/drop_cap]ast year, I moved to <a href="https://andreklein.net/2025-the-year-of-the-linux-desktop-for-me-anyway/">CachyOS</a> on my laptop. I expected a different Kernel. I was ready to do some things differently. What I didn&#8217;t expect was a total disruption of my workflow. Not just on that Linux machine, but across any other machine I would touch afterward.</p>
<p>Once you get familiar with Linux&#8217;s terminal-first approach and you&#8217;ve tasted the speed of a GPU-accelerated terminal and a shell that doesn&#8217;t fight you, going back to a standard Windows setup just feels &#8230; wrong.</p>
<p>I tried to reverse-engineer that workflow on Windows. I tried WezTerm, Starship on Git Bash, and native TUIs. I failed. Between terminal escape codes screaming into my mouse movements and Windows eating my AltGr keys, I realized the truth: Native Windows and <em>truly</em> &#8220;terminal-first&#8221; workflows are like water and oil (unless you enjoy working with Powershell. But that&#8217;s a totally different story).</p>
<h2>Elevating The Subsystem</h2>
<p>Just when I was ready to fold and relegate my TUIs to my Arch rig, I was ready for one last Hallelujah: <strong>WSL2</strong>.</p>
<p>Yeah, I know. By default, WSL is not the best experience. It’s a superior OS running inside an inferior one, burdened by a translation layer designed for trouble. But after a day of chipping away at the friction, I found a stack that almost makes me forget that I&#8217;m on a Windows machine and not mashing away at Kitty on CachyOS.</p>
<h2>Lobotomizing the WSL</h2>
<p>By default, WSL is slow because it scans your entire Windows <code>$PATH</code>—thousands of folders of legacy garbage. The trick is to cut the cord in <code>/etc/wsl.conf</code>:</p>
<p><code>[interop]<br />
appendWindowsPath = false</code></p>
<p>Setting this to <code>false</code> drastically reduces shell initialization time because WSL stops crawling through your Windows binaries.</p>
<p>To stop WSL from becoming a memory parasite, I also added some performance flags. First of all, we shutdown the virtual machine after an hour of idle, so it doesn&#8217;t keep hogging resources forever:</p>
<p><code>[wsl2]<br />
# Automatically shut down the WSL VM after 1 hour of inactivity<br />
vmIdleTimeout=3600000</code></p>
<p>Next, we add this tweak to our <code>%USERPROFILE%\.wslconfig</code> (that&#8217;s on the host system, not the WSL box) to make the RAM-usage a bit &#8220;smarter&#8221;:</p>
<p><code>[experimental]<br />
# Give RAM back to Windows as soon as Linux stops using it<br />
autoMemoryReclaim=gradual</code></p>
<h2>GPU-Accelerated Goodness</h2>
<p>I settled on Alacritty for the terminal. Unlike WezTerm it plays nice with my weird German keyboard layout, e.g. AltGr+Q = @ and Shift+7 = /, and delivers the raw speed I need for my TUI development workflows.</p>
<p>But first of all we need to get a cleaner start. Let&#8217;s edit <code>alacritty.toml</code>:</p>
<p><code>[terminal.shell]<br />
program = "C:\\Windows\\System32\\wsl.exe"<br />
args = ["-d", "Ubuntu", "--cd", "~", "fish", "--login"]</code></p>
<p>Launching with<code> --cd ~</code> ensures we start in the Linux home directory, not the<code>/mnt/c/</code> mount which is a slow and sad reminder that Linux is just a tenant on this system.</p>
<p>If the colors are off, because they probably are, we can explicitly request the full truecolor goodness like this:</p>
<p><code>[env]<br />
TERM = "alacritty"<br />
COLORTERM = "truecolor"</code></p>
<p>Once everything is done, you should get a crisp and clean terminal experience on WSL. Here&#8217;s a quick screenshot:</p>
<p><a href="https://andreklein.net/wp-content/uploads/2026/02/ls.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-22590" src="https://andreklein.net/wp-content/uploads/2026/02/ls.png" alt="" width="999" height="627" srcset="https://andreklein.net/wp-content/uploads/2026/02/ls.png 999w, https://andreklein.net/wp-content/uploads/2026/02/ls-300x188.png 300w, https://andreklein.net/wp-content/uploads/2026/02/ls-768x482.png 768w" sizes="auto, (max-width: 999px) 100vw, 999px" /></a></p>
<p>Theme is the ever-goated TokyoNight, font is Delugia (which has excellent icon support) and just overall pleasant to look at. Shell is Fish+Tide. For those sweet <code>ls</code> colors you see in the screenshot above I stole some aliases from the excellent <a href="https://github.com/CachyOS/cachyos-fish-config/blob/main/cachyos-config.fish">CachyOS fish.config</a>, most notably:</p>
<p><code>alias ls='eza -al --color=always --group-directories-first --icons'<br />
alias la='eza -a --color=always --group-directories-first --icons'<br />
alias ll='eza -l --color=always --group-directories-first --icons'<br />
alias lt='eza -aT --color=always --group-directories-first --icons'<br />
alias l.="eza -a | grep -e '^\.'"<br />
</code></p>
<p>Since we are replacing <code>ls</code> with <code>eza</code> you need to <code>sudo apt install eza</code> on Ubuntu.</p>
<p>In the same vein, I also applied CachyOS&#8217;s replacement (slightly modified) for <code>man</code> so we can get actual nice-looking manuals:</p>
<p><code>set -x MANROFFOPT "-c"<br />
set -x MANPAGER "sh -c 'col -bx | batcat -l man -p'"</code></p>
<p>For this to work you need <code>sudo apt install bat</code> on Ubuntu. And then typing <code>man git</code> will give you something like this:</p>
<p><a href="https://andreklein.net/wp-content/uploads/2026/02/man.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-22595" src="https://andreklein.net/wp-content/uploads/2026/02/man.png" alt="" width="983" height="625" srcset="https://andreklein.net/wp-content/uploads/2026/02/man.png 983w, https://andreklein.net/wp-content/uploads/2026/02/man-300x191.png 300w, https://andreklein.net/wp-content/uploads/2026/02/man-768x488.png 768w" sizes="auto, (max-width: 983px) 100vw, 983px" /></a></p>
<h2>Fixing Shell Colors, Path and Browser on WSL</h2>
<p>If for whatever reason you get the &#8220;muddy color&#8221; problem where WSL doesn&#8217;t recognize Alacritty&#8217;s capabilities, you can force it in <code>config.fish</code>:</p>
<p><code># Force Alacritty identity and TrueColor<br />
set -gx TERM alacritty<br />
set -gx COLORTERM truecolor</code></p>
<p>Once everything is set correctly <code>$TERM</code> and <code>$COLORTEM</code> should return the correct values:</p>
<p><a href="https://andreklein.net/wp-content/uploads/2026/02/Screenshot-2026-02-08-234938.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-22538" src="https://andreklein.net/wp-content/uploads/2026/02/Screenshot-2026-02-08-234938.png" alt="" width="764" height="193" srcset="https://andreklein.net/wp-content/uploads/2026/02/Screenshot-2026-02-08-234938.png 764w, https://andreklein.net/wp-content/uploads/2026/02/Screenshot-2026-02-08-234938-300x76.png 300w" sizes="auto, (max-width: 764px) 100vw, 764px" /></a></p>
<h2>The Bottom Line</h2>
<p>By effectively decoupling WSL from Windows you can genuinely improve performance and make it feel a lot more like a native Linux environment. Add a modern terminal like Alacritty with truecolor support, a user-friendly shell like Fish and you&#8217;re officially on your way to making the terminal-first workflow on Windows significantly <del>suck less</del> more palatable.</p>
<p>Since I&#8217;ve been doing lots of terminal-centric work lately, I can now seamlessly switch between my Linux and Windows rig. Same look, same commands, same muscle memory. And when I launch Alacritty now and start bashing away, it almost feels like Linux is no <em>sub</em>system at all, but the dominant driver.</p>
<p>Last but not least, to top off the TerminalCeption, here&#8217;s a screenshot of me writing the draft for this post in <a href="https://github.com/burninc0de/helowrite">HeloWrite</a> on the very stack (WSL-Alacritty-Fish) described in thist post:</p>
<p><a href="https://andreklein.net/wp-content/uploads/2026/02/writing.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-22567" src="https://andreklein.net/wp-content/uploads/2026/02/writing.png" alt="" width="771" height="547" srcset="https://andreklein.net/wp-content/uploads/2026/02/writing.png 771w, https://andreklein.net/wp-content/uploads/2026/02/writing-300x213.png 300w, https://andreklein.net/wp-content/uploads/2026/02/writing-768x545.png 768w" sizes="auto, (max-width: 771px) 100vw, 771px" /></a></p>
<p>UPDATE: once I had all of this working, I deleted the whole Ubuntu WSL instance and replaced it with a proper ArchLinux WSL install. Look and feel are the same, but using pacman and AUR on Windows is just so much fun. Almost a sacrilege. Even getting native Windows NVIDIA drivers passed through to CUDA-enabled FastWhisper on this Arch box just works.</p>
<p>Whodathunk.</p>
<p>&#8211;</p>
<p>The post <a href="https://andreklein.net/taming-wsl-into-a-tactical-workbench-for-a-terminal-first-workflow/">Taming WSL into a Tactical Workbench For A Terminal-First Workflow</a> appeared first on <a href="https://andreklein.net">André Klein Dot Net</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://andreklein.net/taming-wsl-into-a-tactical-workbench-for-a-terminal-first-workflow/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to get VS Code &#8220;Native Tabs&#8221; on KDE Plasma (Linux)</title>
		<link>https://andreklein.net/vs-code-native-tabs-linux-kde/</link>
					<comments>https://andreklein.net/vs-code-native-tabs-linux-kde/#comments</comments>
		
		<dc:creator><![CDATA[André Klein]]></dc:creator>
		<pubDate>Fri, 06 Feb 2026 11:38:10 +0000</pubDate>
				<category><![CDATA[tinker]]></category>
		<guid isPermaLink="false">https://andreklein.net/?p=22446</guid>

					<description><![CDATA[<p>[drop_cap]W[/drop_cap]hen you&#8217;re juggling three repos in VS Code and a dozen browser tabs, Alt+Tab becomes a game of Russian Roulette. You’re looking for your frontend, but you end up staring at a Slack notification or a half-finished email. MacOS users get Native Tabs in VS Code. On Linux/Windows? You get one instance per workspace and [&#8230;]</p>
<p>The post <a href="https://andreklein.net/vs-code-native-tabs-linux-kde/">How to get VS Code &#8220;Native Tabs&#8221; on KDE Plasma (Linux)</a> appeared first on <a href="https://andreklein.net">André Klein Dot Net</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>[drop_cap]W[/drop_cap]hen you&#8217;re juggling three repos in VS Code and a dozen browser tabs, Alt+Tab becomes a game of Russian Roulette. You’re looking for your frontend, but you end up staring at a Slack notification or a half-finished email.</p>
<p>MacOS users get <strong>Native Tabs</strong> in VS Code. On Linux/Windows? You get one instance per workspace and a mess of groupings on your taskbar.</p>
<p>I didn&#8217;t want a new OS; I just wanted a quick way to visualize and switch in between open workspaces.</p>
<h2>The Solution: A Focused Taskbar</h2>
<p>The native KDE Plasma Task Manager is powerful. You can customize it infinitely, drop it into top panel, massage appearance until it has a &#8220;tab-like&#8221; feel, but it lacks one crucial feature: <strong>Application Filtering. </strong>By default, the taskbar will always show <em>all</em> and <em>any</em> open tasks.</p>
<p>I hacked together a version that lets you &#8220;pin&#8221; specific apps to a dedicated panel. This creates a &#8220;Dev Mode&#8221; bar in the corner of your screen that mimics the VS Code native tabs feeling by showing only your active development tools. And it&#8217;s not limited to VS Code. You can create &#8220;tabs&#8221; like this for any combination of apps. Want to show only your active terminals and browser? Only file managers? No problem. Just filter.</p>
<div id="attachment_22449" style="width: 1034px" class="wp-caption alignnone"><a href="https://andreklein.net/wp-content/uploads/2026/02/code-tabs.png"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-22449" class="wp-image-22449 size-large" src="https://andreklein.net/wp-content/uploads/2026/02/code-tabs-1024x547.png" alt="" width="1024" height="547" srcset="https://andreklein.net/wp-content/uploads/2026/02/code-tabs-1024x547.png 1024w, https://andreklein.net/wp-content/uploads/2026/02/code-tabs-300x160.png 300w, https://andreklein.net/wp-content/uploads/2026/02/code-tabs-768x410.png 768w, https://andreklein.net/wp-content/uploads/2026/02/code-tabs.png 1421w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><p id="caption-attachment-22449" class="wp-caption-text">Who needs &#8220;native&#8221; tabs when you can get a custom taskbar?</p></div>
<ul>
<li>Only show whatever you tasks you actually need for your workflow</li>
<li>Filter by single instances like &#8220;code&#8221; or combinations like &#8220;zed,firefox&#8221;</li>
<li>Minimal task bar without hover previews, audio bubbles, etc.</li>
<li>Keep the &#8220;unrelated&#8221; junk (Slack, Spotify, Mail) in your main taskbar.</li>
</ul>
<div class="cta"><strong>Get the code:</strong><br />
<a href="https://github.com/burninc0de/kde-filtered-taskbar">github.com/burninc0de/kde-filtered-taskbar</a></div>
<h2>Quickstart</h2>
<p>Here&#8217;s a quick way to get the plasmoid, copy it to your .local/share and restart plasma:</p>
<p><code>git clone https://github.com/burninc0de/kde-filtered-taskbar.git<br />
cd kde-filtered-taskbar<br />
./install.sh</code>After that, right-click any panel, click &#8220;Add Widgets,&#8221; and search for Filtered Taskbar.</p>
<div>&#8211;</div>
<p>The post <a href="https://andreklein.net/vs-code-native-tabs-linux-kde/">How to get VS Code &#8220;Native Tabs&#8221; on KDE Plasma (Linux)</a> appeared first on <a href="https://andreklein.net">André Klein Dot Net</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://andreklein.net/vs-code-native-tabs-linux-kde/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>HeloWrite: A Minimalist Writing Tool For The Terminal</title>
		<link>https://andreklein.net/helowrite-terminal-word-processor/</link>
					<comments>https://andreklein.net/helowrite-terminal-word-processor/#respond</comments>
		
		<dc:creator><![CDATA[André Klein]]></dc:creator>
		<pubDate>Sun, 01 Feb 2026 19:53:04 +0000</pubDate>
				<category><![CDATA[tinker]]></category>
		<guid isPermaLink="false">https://andreklein.net/?p=22366</guid>

					<description><![CDATA[<p>[drop_cap]W[/drop_cap]riting is hard. It&#8217;s messy, unresolved, chaotic. You scrape scenes out of your skull and massage syntactical turds until they shine (or get thrown out in the next rewrite). Code is different. Something either works or it doesn&#8217;t. Problems usually have clear paths to solutions. Prose has no linter. You can&#8217;t pre-compile a plot-twist to [&#8230;]</p>
<p>The post <a href="https://andreklein.net/helowrite-terminal-word-processor/">HeloWrite: A Minimalist Writing Tool For The Terminal</a> appeared first on <a href="https://andreklein.net">André Klein Dot Net</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a href="https://andreklein.net/wp-content/uploads/2026/02/about.png"><img loading="lazy" decoding="async" class="alignnone wp-image-23114 size-large" src="https://andreklein.net/wp-content/uploads/2026/02/about-1024x813.png" alt="" width="1024" height="813" srcset="https://andreklein.net/wp-content/uploads/2026/02/about-1024x813.png 1024w, https://andreklein.net/wp-content/uploads/2026/02/about-300x238.png 300w, https://andreklein.net/wp-content/uploads/2026/02/about-768x610.png 768w, https://andreklein.net/wp-content/uploads/2026/02/about.png 1108w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>[drop_cap]W[/drop_cap]riting is hard. It&#8217;s messy, unresolved, chaotic. You scrape scenes out of your skull and massage syntactical turds until they shine (or get thrown out in the next rewrite).</p>
<p>Code is different. Something either works or it doesn&#8217;t. Problems usually have clear paths to solutions.</p>
<p>Prose has no linter. You can&#8217;t pre-compile a plot-twist to catch continuity leaks.</p>
<p>So this week, after making solid progress with my new book, I “relaxed” by building a writing tool in my spare time. The irony isn&#8217;t lost on me.</p>
<h2>The Calm of The Void</h2>
<p>Staring at a white page sucks. First step? Make it not white. Stop shining a flashlight into your retinas while trying to decant the subconscious. Next, ditch the Microsoft kitchen-sink ribbons of colorful icons and formatting gizmos. Stop pretending you are a typesetter and fiddling with font sizes instead of dredging up dirt on your characters.</p>
<p>In short, remove everything else except the words.</p>
<p>I&#8217;ve always been a huge fan of this type of minimalist approach.</p>
<p>The less I see, the better. For years I&#8217;ve bounced between minimalist word processors: WriteMonkey, iAwriter, FocusWriter—always configured the same way: dark background, generous horizontal padding to spare my eyes the long left-to-right trek, a clean mono/duospace font, and a subtle word counter tucked in a corner that only shows when idle.</p>
<p>Notifications off, music on, deep dive. That&#8217;s the only way to play this game.</p>
<p>This weekend I thought: why not follow this minimalist approach, but strip it down even further, in the shape of a terminal-based tool. TUIs (terminal user interfaces) are all the rage these days and I admit&#8212;it’s fun in a deliberately discordant way!</p>
<p>No graphics. No animations. No gamification or &#8220;engagement&#8221; loops. Just the brutal, high-contrast reality of text.</p>
<p>I built HeloWrite in Python with the Textual library (great starter). Here&#8217;s a screenshot of the distraction-free mode, and yes, there ain&#8217;t much to see, which is precisely the point:</p>
<div id="attachment_22443" style="width: 1034px" class="wp-caption alignnone"><a href="https://andreklein.net/wp-content/uploads/2026/02/nu1.png"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-22443" class="wp-image-22443 size-large" src="https://andreklein.net/wp-content/uploads/2026/02/nu1-1024x625.png" alt="" width="1024" height="625" srcset="https://andreklein.net/wp-content/uploads/2026/02/nu1-1024x625.png 1024w, https://andreklein.net/wp-content/uploads/2026/02/nu1-300x183.png 300w, https://andreklein.net/wp-content/uploads/2026/02/nu1-768x469.png 768w, https://andreklein.net/wp-content/uploads/2026/02/nu1.png 1262w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><p id="caption-attachment-22443" class="wp-caption-text">Cursor color follows theme, or your custom preference.</p></div>
<h2>The Secret Sauce: Performance &amp; Paranoia</h2>
<p>I realized halfway through Sunday that I wasn’t just building this for the &#8220;aesthetic.&#8221; I was building it because I’m tired of waiting for my tools to catch up to my brain. Many modern writing apps are resource hogs. They have &#8220;loading&#8221; states awkwardly disguised by splash screens. They index. They bloat.</p>
<p>HeloWrite has a cold start so fast it feels like it was never closed. We’re talking 0.5 seconds from hitting Enter to a blinking cursor. And that’s running from source—no pre-compiled binaries, no bloat, just raw Python and the void.</p>
<p>And then there&#8217;s the Git workflow. You can set your Obsidian vault dir (or any repo for that matter) in the settings and git to your heart&#8217;s content. Push and pull individual files or chapters as you work on them and get version control for your writing. Never lose a line again. Send it all to the vault, while you write.</p>
<p>Don&#8217;t use git? No problem. Auto-save is built in as well. But if you are a writer (or a developer), you&#8217;ll probably spam <code>Ctrl+S</code> anyway. Just in case, right?</p>
<div id="attachment_23115" style="width: 1034px" class="wp-caption alignnone"><a href="https://andreklein.net/wp-content/uploads/2026/02/settings-2.png"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-23115" class="wp-image-23115 size-large" src="https://andreklein.net/wp-content/uploads/2026/02/settings-2-1024x664.png" alt="" width="1024" height="664" srcset="https://andreklein.net/wp-content/uploads/2026/02/settings-2-1024x664.png 1024w, https://andreklein.net/wp-content/uploads/2026/02/settings-2-300x194.png 300w, https://andreklein.net/wp-content/uploads/2026/02/settings-2-768x498.png 768w, https://andreklein.net/wp-content/uploads/2026/02/settings-2.png 1122w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><p id="caption-attachment-23115" class="wp-caption-text">Settings Screens</p></div>
<h2>Code and Corkboards</h2>
<p>There are tons of amazing code editors out there. Vim fanatics can rice their configs until the heat death of the universe. Emacs people have basically built an operating system. Developers are spoiled for choice when it comes to terminal-based workflows.</p>
<p>Writers? Not so much.</p>
<p>We get word processors designed by committee, skeuomorphic corkboards, or minimalist apps that cost $50, do less than Notepad and still somehow end up feeling heavy.</p>
<p>I wanted something different. Something that understood the writer&#8217;s brain, but had the heart of a code editor.</p>
<p>I&#8217;ve tried other terminal-based word processors like WordGrinder, and while I loved the concept, the workflow never quite seemed clicked with me. So I just built my own, tuned exactly to the quirks of a lifetime of writing.</p>
<h2>Begin Jump Prep</h2>
<p>HeloWrite, pronounced &#8220;<em>hee-lo</em>&#8221; and named after Karl “Helo” Agathon from Battlestar Galactica, is completely free open-source software. It includes:</p>
<ul>
<li>Fully distraction-free mode with an out-of-the-way word counter</li>
<li>On the fly adjustable horizontal padding to cut eye strain</li>
<li>Many popular custom color themes including cursor styling</li>
<li>Granular git push and pull commands</li>
</ul>
<blockquote><p>“I fell in love with a machine. That&#8217;s stupid. So just call me an idiot, and let&#8217;s be done with it.” — Karl Agathon</p></blockquote>
<div style="width: 1288px;" class="wp-video"><video class="wp-video-shortcode" id="video-22366-1" width="1288" height="954" preload="metadata" controls="controls"><source type="video/mp4" src="https://andreklein.net/wp-content/uploads/2026/02/helowrite.mp4?_=1" /><source type="video/mp4" src="https://andreklein.net/wp-content/uploads/2026/02/helowrite.mp4?_=1" /><a href="https://andreklein.net/wp-content/uploads/2026/02/helowrite.mp4">https://andreklein.net/wp-content/uploads/2026/02/helowrite.mp4</a></video></div>
<p><a href="https://github.com/burninc0de/helowrite"><img decoding="async" class="alignleft" src="https://img.shields.io/badge/github-repo-blue?logo=github" alt="github" /></a></p>
<p>Clone, fork or hack here: <a href="https://github.com/burninc0de/helowrite">burninc0de/helowrite</a></p>
<p>&#8211;</p>
<p>The post <a href="https://andreklein.net/helowrite-terminal-word-processor/">HeloWrite: A Minimalist Writing Tool For The Terminal</a> appeared first on <a href="https://andreklein.net">André Klein Dot Net</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://andreklein.net/helowrite-terminal-word-processor/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		<enclosure url="https://andreklein.net/wp-content/uploads/2026/02/helowrite.mp4" length="1453287" type="video/mp4" />

			</item>
	</channel>
</rss>
