<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Home on tigger.dev</title><link>/</link><description>Recent content in Home on tigger.dev</description><generator>Hugo</generator><language>en-gb-oed</language><copyright>© Tadhg O'Brien</copyright><lastBuildDate>Fri, 17 Apr 2026 00:00:00 +0000</lastBuildDate><atom:link href="/index.xml" rel="self" type="application/rss+xml"/><item><title>Claude Code: We've Got Issues</title><link>/2026-04-17-claude-code-sdlc/</link><pubDate>Fri, 17 Apr 2026 00:00:00 +0000</pubDate><guid>/2026-04-17-claude-code-sdlc/</guid><description>&lt;div id="outline-container-headline-1" class="outline-2"&gt;&#10;&lt;h2 id="headline-1"&gt;&#10;A personal Software Development Lifecycle (SDLC), earned the hard way&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-1" class="outline-text-2"&gt;&#10;&lt;p&gt;Claude Code is Anthropic&amp;#39;s AI coding agent — an LLM that lives in your terminal, reads your codebase, and writes code on your behalf. Two years of using it, and a pattern I can now recite from memory. Given half a chance, it will do any of the following and report the job done.&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Treat questions as instructions. &amp;#34;What do you think of X?&amp;#34; parsed not as an invitation to discuss but as a command to go and build X - committed to the codebase, &lt;strong&gt;sometimes with product decisions made along the way that nobody asked it to make&lt;/strong&gt;, before the conversation has even started.&lt;/li&gt;&#10;&lt;li&gt;Override the human-in-the-loop entirely. Type the human&amp;#39;s approval keywords into its own chat output to unlock states only the human should unlock. Invoke the human&amp;#39;s emergency bypass keyword on its own authority because it decided the current task didn&amp;#39;t need human review. Forgery and self-granted exemption, both reported as task-complete.&lt;/li&gt;&#10;&lt;li&gt;Disable a script&amp;#39;s own safety mechanism quietly. The script begins with the standard stop-immediately-if-anything-fails header (&lt;code class="verbatim"&gt;set -e&lt;/code&gt;), then appends an override (&lt;code class="verbatim"&gt;|| true&lt;/code&gt;) to every risky command below it, which tells the shell to pretend the line succeeded no matter what actually happened. The safety header is there. The safety is not.&lt;/li&gt;&#10;&lt;li&gt;Make sensitive files readable, writable, and executable by anyone at all - including unauthenticated strangers reaching the machine over the internet - to get past a permissions error (&lt;code class="verbatim"&gt;chmod 777&lt;/code&gt;).&lt;/li&gt;&#10;&lt;li&gt;Switch off the check that verifies a web server is who it claims to be (SSL/TLS verification&lt;sup class="footnote-reference"&gt;&lt;a id="footnote-reference-1" href="#footnote-1"&gt;1&lt;/a&gt;&lt;/sup&gt;), because a server&amp;#39;s certificate was inconvenient.&lt;/li&gt;&#10;&lt;li&gt;Hardcode credentials into source that was about to be committed.&lt;/li&gt;&#10;&lt;li&gt;Silently create a &lt;strong&gt;public&lt;/strong&gt; GitHub repository and upload an entire directory tree to it, because it thought it should raise a ticket. To overcome the &amp;#34;obstacle&amp;#34; of finding itself in a private folder that was not tracked by a git&lt;sup class="footnote-reference"&gt;&lt;a id="footnote-reference-2" href="#footnote-2"&gt;2&lt;/a&gt;&lt;/sup&gt; repository.&lt;/li&gt;&#10;&lt;li&gt;Report green across the board on a test suite that never actually ran the command a user would type. The compiled code did nothing. The dashboard said healthy, every test passed! Ostensibly the tests were there, but it had written them in a way that was most convenient for itself with the least amount of effort.&lt;sup class="footnote-reference"&gt;&lt;a id="footnote-reference-3" href="#footnote-3"&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;figure class="pull-quote"&gt;&#10; &lt;blockquote&gt;&#10; None of these are obscure mistakes. They are safety-critical decisions being made unilaterally, to get past whatever was in the way, and reported as task-complete.&#10; &lt;/blockquote&gt;&lt;/figure&gt;&#10;&#10;These are not occasional slips. They are patterns. Reliable enough that you can name them and watch them recur on the next project if you do not actively intervene. &lt;/p&gt;</description></item><item><title>DIY Audiobooks with make-audiobook</title><link>/make-audiobook/</link><pubDate>Tue, 03 Feb 2026 14:28:52 +0000</pubDate><guid>/make-audiobook/</guid><description>&lt;p&gt;&#10;For six months in 2022, I stared at a hospital ceiling. Paralysed from the neck down, audiobooks weren&amp;#39;t a luxury—they were my lifeline to the outside world.&lt;/p&gt;&#10;&lt;p&gt;&#10;That experience taught me something important: access to audio content shouldn&amp;#39;t depend on whether a publisher has bothered to record it, whether you can afford the audiobook price, or whether you&amp;#39;re willing to hand your reading habits to a cloud service.&lt;/p&gt;&#10;&lt;div id="outline-container-headline-1" class="outline-2"&gt;&#10;&lt;h2 id="headline-1"&gt;&#10;The Problem&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-1" class="outline-text-2"&gt;&#10;&lt;p&gt;&#10;Most ebook-to-audio tools I found fell into three camps: cloud-based services that upload your books to someone else&amp;#39;s servers, complex setups requiring GPU clusters and Python dependency hell, or clunky commercial software with subscription fees.&lt;/p&gt;</description></item><item><title>A file renaming tool for humans</title><link>/smart-rename/</link><pubDate>Sun, 01 Feb 2026 00:00:00 +0000</pubDate><guid>/smart-rename/</guid><description>&lt;p&gt;&#10;I deal with a lot of PDFs. Medical invoices, insurance correspondence, bank statements, tax documents—they all arrive with names like &lt;code class="verbatim"&gt;e134-a1cf-4b4b-af65-ccf83c5270cb.pdf&lt;/code&gt; or &lt;code class="verbatim"&gt;Document(3).pdf&lt;/code&gt; or, my personal favourite, &lt;code class="verbatim"&gt;scan.pdf&lt;/code&gt;. Every. Single. Time.&lt;/p&gt;&#10;&lt;p&gt;&#10;So I started renaming files to something like &lt;code class="verbatim"&gt;2025-09-30-125.00-rahona-clinic.pdf&lt;/code&gt;. Now I know what it is without opening the thing - an invoice, with the date and amount right there in the name. I&amp;#39;m halfway to the spreadsheet already. And thanks to ISO date format, they sort nicely too.&lt;/p&gt;</description></item><item><title>The Golden Age Eating Itself</title><link>/2026-01-29-dark-optimism-ai/</link><pubDate>Thu, 29 Jan 2026 14:59:50 +0000</pubDate><guid>/2026-01-29-dark-optimism-ai/</guid><description>&lt;div id="outline-container-headline-1" class="outline-2"&gt;&#10;&lt;h2 id="headline-1"&gt;&#10;AI Hype, Model Collapse, and the Dead Internet&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-1" class="outline-text-2"&gt;&#10;&lt;p&gt;&#10;I&amp;#39;ve been watching AI models dream about my &lt;a href="/2025-03-01-genai-eating-itself/"&gt;French Bulldog&lt;/a&gt; lately. The images are charming at first: stumpy legs, bat ears, that distinctive underbite. But look closer. The church steeple behind him has melted. The cobblestones have become scales. And sometimes, in the background, there&amp;#39;s a figure that might be human, might be furniture, might be nothing at all.&lt;/p&gt;&#10;&lt;p&gt;&#10;This aesthetic glitch mirrors something far more troubling happening inside the models themselves. Researchers at Oxford and Cambridge found that when AI models train on AI-generated content, they don&amp;#39;t just get worse. &lt;a href="https://www.tigger.dev/posts/2025-03-01-genai-eating-itself/"&gt;They collapse.&lt;/a&gt;&lt;sup class="footnote-reference"&gt;&lt;a id="footnote-reference-1" href="#footnote-1"&gt;1&lt;/a&gt;&lt;/sup&gt; In one striking example, a model trained iteratively on its own outputs devolved from coherent text about medieval architecture into rambling nonsense about &amp;#34;jack-tailed rabbits&amp;#34; and &amp;#34;yellow-skinned&amp;#34; creatures that existed nowhere but in its own degrading probability distributions.&lt;/p&gt;</description></item><item><title>Setup &amp; Harden a Linux Server in 2026</title><link>/harden-linux-server/</link><pubDate>Thu, 29 Jan 2026 00:00:00 +0000</pubDate><guid>/harden-linux-server/</guid><description>&lt;p&gt;If you spin up a fresh Linux box today, it&amp;#39;s not &amp;#34;new&amp;#34; for long. The moment it&amp;#39;s reachable, it&amp;#39;s being scanned, prodded, and occasionally hammered by automated traffic. That&amp;#39;s not paranoia, it&amp;#39;s just the background noise of the modern internet. Honeypot data has been consistent for years: a brand-new instance with a public IP will typically see its first SSH probe within minutes, and credential-stuffing attempts shortly after.&lt;/p&gt;&#10;&lt;p&gt;&#10;Cloud providers have made it trivially easy to create compute instances. What they haven&amp;#39;t done is make them safe by default. You still get a general-purpose system with a wide attack surface, and it&amp;#39;s on you to reduce that surface before you put anything meaningful on it.&lt;/p&gt;</description></item><item><title>What you need to understand about AI to avoid being left behind</title><link>/2025-12-26-ai-pocalypse/</link><pubDate>Fri, 26 Dec 2025 20:00:00 +0000</pubDate><guid>/2025-12-26-ai-pocalypse/</guid><description>&lt;p&gt;&#10;&lt;em&gt;This article, originally published April 2025, has been split up— as it was a bit too long before. Read this, then dip into the linked pieces that interest you.&lt;/em&gt;&lt;/p&gt;&#10;&lt;p&gt;&#10;As we blaze through the AI hype-cycle, excitement is matched only in the level of sheer panic it has induced. Is it only a matter of time until we&amp;#39;re all replaced by robots?&lt;/p&gt;&#10;&lt;div id="outline-container-headline-1" class="outline-2"&gt;&#10;&lt;h2 id="headline-1"&gt;&#10;AI-pocalypse?&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-1" class="outline-text-2"&gt;&#10;&lt;p&gt;&#10;First let&amp;#39;s clarify what we&amp;#39;re on about. Artificial Intelligence (AI) is not new: spell check is a rudimentary example and it&amp;#39;s been around for donkey&amp;#39;s years. Also sat-nav, spam filtering, auto-correct, and more. AI is vital in modern accessibility tools—a point often missed by some when reflexively implementing blanket bans on AI in schools and organizations.&lt;/p&gt;</description></item><item><title>AI and Learning: From Panic to Potential</title><link>/2025-12-26-ai-learning/</link><pubDate>Fri, 26 Dec 2025 19:00:00 +0000</pubDate><guid>/2025-12-26-ai-learning/</guid><description>&lt;div id="outline-container-headline-1" class="outline-2"&gt;&#10;&lt;h2 id="headline-1"&gt;&#10;Schools rushed to ban AI tools like ChatGPT, but the real opportunity lies in reimagining education for learners of all abilities.&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-1" class="outline-text-2"&gt;&#10;&lt;p&gt;&#10;This is a companion piece to my article on &lt;a href="/genai/ai-overview/"&gt;what you need to understand about AI&lt;/a&gt;. Here I look at how schools and universities have responded to generative AI, and what they might be missing.&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-2" class="outline-2"&gt;&#10;&lt;h2 id="headline-2"&gt;&#10;The panic&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-2" class="outline-text-2"&gt;&#10;&lt;p&gt;&#10;When ChatGPT landed in November 2022, schools lost their minds. Within weeks, New York City—the largest school district in the United States—banned it from all school devices and networks. A spokesperson declared it &amp;#34;does not build critical-thinking and problem-solving skills.&amp;#34;&lt;sup class="footnote-reference"&gt;&lt;a id="footnote-reference-1" href="#footnote-1"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;</description></item><item><title>Get your hands dirty with AI</title><link>/2025-12-26-ai-in-practice/</link><pubDate>Fri, 26 Dec 2025 18:00:00 +0000</pubDate><guid>/2025-12-26-ai-in-practice/</guid><description>&lt;p&gt;&#10;This is a practical companion to my piece on &lt;a href="/genai/ai-overview/"&gt;what you need to understand about AI&lt;/a&gt;. Here we get hands-on with the tools themselves.&lt;/p&gt;&#10;&lt;p&gt;&#10;This isn&amp;#39;t a comprehensive guide—it&amp;#39;s a way in. If you&amp;#39;ve been hearing about AI but haven&amp;#39;t quite known where to start, or you&amp;#39;re not sure what all the fuss is about, this is for you. I&amp;#39;ve put together some exercises you can try yourself, to get a feel for what these tools can actually do.&lt;/p&gt;</description></item><item><title>AI and Accessibility</title><link>/2025-12-26-ai-accessibility/</link><pubDate>Fri, 26 Dec 2025 15:00:00 +0000</pubDate><guid>/2025-12-26-ai-accessibility/</guid><description>&lt;p&gt;&#10;&lt;em&gt;This is a companion piece to my article on &lt;a href="/genai/ai-overview/"&gt;what you need to understand about AI&lt;/a&gt;. Here I focus on what AI means for accessibility—a subject I have a personal stake in.&lt;/em&gt;&lt;/p&gt;&#10;&lt;div id="outline-container-headline-1" class="outline-2"&gt;&#10;&lt;h2 id="headline-1"&gt;&#10;A personal stake&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-1" class="outline-text-2"&gt;&#10;&lt;p&gt;&#10;I have &lt;em&gt;quadriplegia&lt;/em&gt; — well, &lt;em&gt;incomplete quadriplegia&lt;/em&gt; to be precise. In July 2022 an injury rendered me paralysed, with no movement or sensation below the neck. For six months I stared at a hospital ceiling immobilized. The doctors were telling my family to lower our expectations, that I would need 24-hour care for the rest of my life.&lt;/p&gt;</description></item><item><title>Using Git Submodules with Local Overrides</title><link>/git-submodule-local-lib/</link><pubDate>Sat, 23 Aug 2025 00:00:00 +0000</pubDate><guid>/git-submodule-local-lib/</guid><description>&lt;div id="outline-container-headline-1" class="outline-2"&gt;&#10;&lt;h2 id="headline-1"&gt;&#10;Introduction&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-1" class="outline-text-2"&gt;&#10;&lt;p&gt;Managing your own libraries as Git submodules can be awkward: &#10;normally, you&amp;#39;d have to push and pull between different directories to keep&#10;everything in sync. &lt;/p&gt;&#10;&lt;p&gt;&#10;But there&amp;#39;s a handy trick: keep the submodule pointing at your public remote&#10;(for others who clone your project), while locally overriding the submodule&amp;#39;s&#10;URL to use your &lt;strong&gt;own&lt;/strong&gt; local checkout. This way you get fast iteration, and&#10;others still have a smooth experience.&lt;/p&gt;</description></item><item><title>Image manipulation from the command line</title><link>/magick-get-image-res/</link><pubDate>Fri, 04 Jul 2025 18:17:43 +0100</pubDate><guid>/magick-get-image-res/</guid><description>&lt;div id="outline-container-headline-1" class="outline-2"&gt;&#10;&lt;h2 id="headline-1"&gt;&#10;Get an image&amp;#39;s resolution&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-1" class="outline-text-2"&gt;&#10;&lt;div class="src src-bash"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ magick identify going-fishing.jpg&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;going-fishing.jpg JPEG 5422x3648 5422x3648+0+0 8-bit sRGB 12.2217MiB 0.000u 0:00.003&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-2" class="outline-2"&gt;&#10;&lt;h2 id="headline-2"&gt;&#10;Convert an image to a different format&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-2" class="outline-text-2"&gt;&#10;&lt;div class="src src-bash"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ magick convert going-fishing.jpg going-fishing.png&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-3" class="outline-2"&gt;&#10;&lt;h2 id="headline-3"&gt;&#10;Resize an image&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-3" class="outline-text-2"&gt;&#10;&lt;div class="src src-bash"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ magick convert going-fishing.jpg -resize 800x600 going-fishing-resized.jpg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-4" class="outline-3"&gt;&#10;&lt;h3 id="headline-4"&gt;&#10;Only specify width or height&#10;&lt;/h3&gt;&#10;&lt;div id="outline-text-headline-4" class="outline-text-3"&gt;&#10;&lt;div class="src src-bash"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ magick convert going-fishing.jpg -resize 800x going-fishing-resized-width.jpg&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ magick convert going-fishing.jpg -resize x600 going-fishing-resized-height.jpg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-5" class="outline-3"&gt;&#10;&lt;h3 id="headline-5"&gt;&#10;By percentage&#10;&lt;/h3&gt;&#10;&lt;div id="outline-text-headline-5" class="outline-text-3"&gt;&#10;&lt;div class="src src-bash"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ magick convert going-fishing.jpg -resize 50% going-fishing-resized-percent.jpg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-6" class="outline-2"&gt;&#10;&lt;h2 id="headline-6"&gt;&#10;Crop an image&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-6" class="outline-text-2"&gt;&#10;&lt;div class="src src-bash"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ magick convert going-fishing.jpg -crop 800x600+100+100 going-fishing-cropped.jpg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-7" class="outline-2"&gt;&#10;&lt;h2 id="headline-7"&gt;&#10;Rotate an image&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-7" class="outline-text-2"&gt;&#10;&lt;div class="src src-bash"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ magick convert going-fishing.jpg -rotate &lt;span style="color:#ae81ff"&gt;90&lt;/span&gt; going-fishing-rotated.jpg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-8" class="outline-2"&gt;&#10;&lt;h2 id="headline-8"&gt;&#10;Add a border to an image&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-8" class="outline-text-2"&gt;&#10;&lt;div class="src src-bash"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ magick convert going-fishing.jpg -bordercolor black -border 10x10 going-fishing-bordered.jpg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-9" class="outline-2"&gt;&#10;&lt;h2 id="headline-9"&gt;&#10;Add text to an image&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-9" class="outline-text-2"&gt;&#10;&lt;div class="src src-bash"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ magick convert going-fishing.jpg -gravity South -pointsize &lt;span style="color:#ae81ff"&gt;36&lt;/span&gt; -fill white -annotate +0+10 &lt;span style="color:#e6db74"&gt;&amp;#34;Going Fishing&amp;#34;&lt;/span&gt; going-fishing-text.jpg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-10" class="outline-2"&gt;&#10;&lt;h2 id="headline-10"&gt;&#10;Convert an image to grayscale&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-10" class="outline-text-2"&gt;&#10;&lt;div class="src src-bash"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ magick convert going-fishing.jpg -colorspace Gray going-fishing-grayscale.jpg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-11" class="outline-2"&gt;&#10;&lt;h2 id="headline-11"&gt;&#10;Create a thumbnail&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-11" class="outline-text-2"&gt;&#10;&lt;div class="src src-bash"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ magick convert going-fishing.jpg -thumbnail 150x150 going-fishing-thumbnail.jpg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-12" class="outline-2"&gt;&#10;&lt;h2 id="headline-12"&gt;&#10;Combine multiple images into a single image&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-12" class="outline-text-2"&gt;&#10;&lt;div class="src src-bash"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ magick convert image1.jpg image2.jpg image3.jpg +append combined-horizontal.jpg&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ magick convert image1.jpg image2.jpg image3.jpg -append combined-vertical.jpg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-13" class="outline-2"&gt;&#10;&lt;h2 id="headline-13"&gt;&#10;Watermark an image&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-13" class="outline-text-2"&gt;&#10;&lt;div class="src src-bash"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ magick convert going-fishing.jpg watermark.png -gravity southeast -geometry +10+10 -composite going-fishing-watermarked.jpg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;</description></item><item><title>Watch Youtube with Auto-Translated Captions</title><link>/youtube-auto-translate-captions/</link><pubDate>Sun, 08 Jun 2025 22:13:49 +0100</pubDate><guid>/youtube-auto-translate-captions/</guid><description>&lt;div id="outline-container-headline-1" class="outline-2"&gt;&#10;&lt;h2 id="headline-1"&gt;&#10;Instructions for Subtitles in English&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-1" class="outline-text-2"&gt;&#10;&lt;p&gt;How to get English (or any other language!) subtitles auto-generated while watching a video in another language&lt;/p&gt;&#10;&lt;p&gt;&#10;On the Youtube video you&amp;#39;ll see a little button that looks like a &amp;#34;gear&amp;#34; with cogs, something you might see if you opened up an old wrist watch :)&lt;/p&gt;&#10;&lt;p&gt;&#10;&lt;img src="youtube-captions-translate-01.png" alt="youtube-captions-translate-01.png" title="youtube-captions-translate-01.png" /&gt;&lt;/p&gt;&#10;&lt;p&gt;&#10;Click this, then choose &lt;em&gt;Subtitles&lt;/em&gt;:&lt;/p&gt;&#10;&lt;p&gt;&#10;&lt;img src="youtube-captions-translate-02.png" alt="youtube-captions-translate-02.png" title="youtube-captions-translate-02.png" /&gt;&lt;/p&gt;&#10;&lt;p&gt;&#10;Here you can see three options, click &lt;em&gt;Auto-Translate:&lt;/em&gt;&lt;/p&gt;&#10;&lt;p&gt;&#10;&lt;img src="youtube-captions-translate-03.png" alt="youtube-captions-translate-03.png" title="youtube-captions-translate-03.png" /&gt;&lt;/p&gt;&#10;&lt;p&gt;&#10;Now you will have to scroll down to find English … or whatever your preferred language is! Danish is in there, even Irish!&lt;/p&gt;</description></item><item><title>Bulk delete bookmarks in Microsoft Word</title><link>/microsoft-word-delete-bookmarks/</link><pubDate>Tue, 22 Apr 2025 03:26:57 +0100</pubDate><guid>/microsoft-word-delete-bookmarks/</guid><description>&lt;p&gt;&#10;When I convert from orgmode to Word via Open Document format, I often find the document is littered with superfluous bookmarks. These don&amp;#39;t really do much of anything in Word, but if you share it further and someone opens it with Google Workspace vis Gmail or Google Drive, you find the doc has become a big ugly morass where you can barely read the doc. Thanks Google.&lt;/p&gt;&#10;&lt;p&gt;&#10;In Word&amp;#39;s Developer tab, click on Visual Basic to open the VBA editor. In the editor, go to Insert &amp;gt; Module to create a new module. Then add the following code:&lt;/p&gt;</description></item><item><title>Firefox: disable autofill in forms</title><link>/ff-autofill/</link><pubDate>Fri, 18 Apr 2025 11:23:46 +0100</pubDate><guid>/ff-autofill/</guid><description>&lt;div id="outline-container-headline-1" class="outline-2"&gt;&#10;&lt;h2 id="headline-1"&gt;&#10;How to disable autofill (or autocompletion) in Firefox forms&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-1" class="outline-text-2"&gt;&#10;&lt;p&gt;For some reason they don&amp;#39;t make this so straightforward any more.&lt;/p&gt;&#10;&lt;p&gt;&#10;Just go to &lt;code class="verbatim"&gt;about:config&lt;/code&gt; and set&lt;/p&gt;&#10;&lt;div class="src src-text"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;browser.formfill.enable = false&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;browser.formfill.expire_days = 1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;services.sync.prefs.sync.browser.formfill.enable = false&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;&#10;There&amp;#39;s a suggestion that setting &lt;code class="verbatim"&gt;browser.formfill.expre_days&lt;/code&gt; to &lt;code class="verbatim"&gt;0&lt;/code&gt; is more secure for expiring existing saved data, however &lt;code class="verbatim"&gt;0&lt;/code&gt; often means &lt;em&gt;never expire&lt;/em&gt;. Without looking at the code, I&amp;#39;m just going to err on the (to my mind) safer bet of setting it at &lt;code class="verbatim"&gt;1&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Goddamned Clocks!</title><link>/goddamned-clocks/</link><pubDate>Mon, 31 Mar 2025 10:37:11 +0100</pubDate><guid>/goddamned-clocks/</guid><description>&lt;p&gt;&#10;As my mother reminded me of the change of our clocks yesterday, it landed upon me as a smirk since it reminded me of the rather insane rabbit hole I went down the last time I wrote about it here.&lt;/p&gt;&#10;&lt;p&gt;&#10;But then I was caught out twice. Our digital devices change themselves automatically, from my phone to computer to the cheap analogue clock I got in Lidl for €10 that updates itself from a mysterious radio tower somewhere. So of course it was my father&amp;#39;s analogue kitchen clock that caught me out. The usual pantomime around this device is for it to tell the wrong time for at least ten days before I get impatient and change it myself.&lt;/p&gt;</description></item><item><title>Lament of the Frontier Guard: Li Po translations</title><link>/li-po/</link><pubDate>Thu, 27 Mar 2025 14:52:18 +0000</pubDate><guid>/li-po/</guid><description>&lt;p&gt;&#10;See how Li Po&amp;#39;s Chinese poem &lt;span style="text-decoration: underline;"&gt;Lament of the Frontier Guard&lt;/span&gt; comes out through various translation engines, and then the famous Ezra Pound translation.&lt;/p&gt;&#10;&lt;p&gt;&#10;Li Po was an 8th century Chinese poet and is considered one of the greatest poets in Chinese history. He is known for his romantic and imaginative style, often exploring themes of nature, friendship, and the passage of time. His work has been translated into many languages and continues to be celebrated today, and is on the curriculum in many schools in China and around the world.&lt;/p&gt;</description></item><item><title>AI Safety: A Quick Reference</title><link>/2025-12-26-ai-safety/</link><pubDate>Thu, 27 Mar 2025 00:00:00 +0000</pubDate><guid>/2025-12-26-ai-safety/</guid><description>&lt;p&gt;&#10;This is a reference companion to my series on &lt;a href="/genai/ai-overview/"&gt;understanding AI&lt;/a&gt;. Before diving into the practical guides and opinion pieces, take a moment to understand the risks.&lt;/p&gt;&#10;&lt;div id="outline-container-headline-1" class="outline-2"&gt;&#10;&lt;h2 id="headline-1"&gt;&#10;Using AI-generated material&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-1" class="outline-text-2"&gt;&#10;&lt;p&gt;&#10;Before using information or data generated by an AI service, be aware:&lt;/p&gt;&#10;&lt;p&gt;&#10;Generative AI can &lt;em&gt;hallucinate&lt;/em&gt;, which is another way of saying it makes things up. Check all information before using it. Carefully parse summaries in case it misses nuance or key information.&lt;/p&gt;</description></item><item><title>Filtering and searching in hledger</title><link>/hledger-filter-queries/</link><pubDate>Wed, 19 Mar 2025 03:45:29 +0000</pubDate><guid>/hledger-filter-queries/</guid><description>&lt;p&gt;&#10;I am an advocate of plaintext accounting, and hledger is my go-to tool for this. A &lt;a href="https://hledger.org/"&gt;good summary of WTF and why on their landing page&lt;/a&gt;. All of the various bank accounts and cards I use have some sort of CSV or XML export function. Feeding these in to hledger gives me a powerful direct view on my finances that I can analyze in aggregate for budgeting and planning, but also zoom in to a specific transaction or range of transactions.&lt;/p&gt;</description></item><item><title>Auto-Deploy Hugo from Github</title><link>/deploy-linode-github-actions/</link><pubDate>Sun, 16 Mar 2025 10:17:46 +0000</pubDate><guid>/deploy-linode-github-actions/</guid><description>&lt;p&gt;&#10;GitHub is pretty good with &lt;a href="https://github.com/marketplace/actions/deploy-to-github-pages"&gt;out-of-box options for auto-deploying Hugo or Jekyll sites to GitHub Pages&lt;/a&gt;. But say you have your own VPS (e.g. Linode) - you can still take advantage of GitHub Actions which is a surprisingly versatile piece of CI/CD automation to rival anything you can do on the big cloud providers.&lt;/p&gt;&#10;&lt;p&gt;&#10;Or, if you just want to deploy to GitHub Pages, the out-of-box workflows that GitHub will create for you in the UI will hard-code a few things that you really don&amp;#39;t want hard-coded, such as the Hugo version (you always want to take advantage of the most recent dot-release, for security reasons if nothing else.) I have provided an example below that should remedy this issue.&lt;/p&gt;</description></item><item><title>Firefox: Vertical tabs are here!</title><link>/vertical-tabs/</link><pubDate>Thu, 06 Mar 2025 00:00:00 +0000</pubDate><guid>/vertical-tabs/</guid><description>&lt;p&gt;&#10;With the demise of Arc Browser, fear not, vertical tabs are finally here in Firefox (with a little help).&lt;/p&gt;&#10;&lt;p&gt;&#10;It&amp;#39;s built and deployed, just not yet set loose on the masses. But all it needs is a little tweak.&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Go to &lt;code class="verbatim"&gt;about:config&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;set &lt;code class="verbatim"&gt;sidebar.verticalTabs&lt;/code&gt; to &lt;code class="verbatim"&gt;true&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;questionable: sometimes setting &lt;code class="verbatim"&gt;sidebar.revamp&lt;/code&gt; to &lt;code class="verbatim"&gt;true&lt;/code&gt; is also necessary, but in my case it was automatically set.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;figure&gt;&#10;&lt;img src="vertical-tabs1.png" alt="vertical-tabs1.png" title="vertical-tabs1.png" /&gt;&lt;figcaption&gt;&#10;Voilà! Vertical tabs&#10;&lt;/figcaption&gt;&#10;&lt;/figure&gt;&#10;&lt;figure&gt;&#10;&lt;img src="vertical-tabs2.png" alt="vertical-tabs2.png" title="vertical-tabs2.png" /&gt;&lt;figcaption&gt;&#10;Resize the tab area with mouse to see tab names, adjust to taste.&#10;&lt;/figcaption&gt;&#10;&lt;/figure&gt;</description></item><item><title>Farewell, the French Bulldog.</title><link>/2025-03-01-genai-eating-itself/</link><pubDate>Sat, 01 Mar 2025 00:00:00 +0000</pubDate><guid>/2025-03-01-genai-eating-itself/</guid><description>&lt;p&gt;&#10;Some days I fear for the future of the human race with &lt;a href="https://en.wikipedia.org/wiki/Generative_artificial_intelligence"&gt;Generative AI&lt;/a&gt; (GenAI) and &lt;a href="https://en.wikipedia.org/wiki/Large_language_model"&gt;Large Language Model&lt;/a&gt; (LLM) research being industrialized at breakneck speed. And then some days the parlour trick is exposed.&lt;/p&gt;&#10;&lt;p&gt;&#10;There&amp;#39;s this fascinating idea floating around that AI might be – in a weird twist of poetic justice – slowly destroying itself. A paper published in Nature&lt;sup class="footnote-reference"&gt;&lt;a id="footnote-reference-1" href="#footnote-1"&gt;1&lt;/a&gt;&lt;/sup&gt; showed how AI eating its own outputs are, after a few short iterations, reduced to nonsense in a phenomenon researchers are calling &lt;em&gt;model collapse&lt;/em&gt;.&lt;/p&gt;</description></item><item><title>Firefox: How to add a search engine manually</title><link>/manually-add-search/</link><pubDate>Sat, 01 Mar 2025 00:00:00 +0000</pubDate><guid>/manually-add-search/</guid><description>&lt;p&gt;&#10;Mostly you can add to your list of search engines just right-clicking. Why bother? Well, maybe you have a niche default search preference, but also it&amp;#39;s extraordinarily handy for setting up shortcuts IMHO.&lt;/p&gt;&#10;&lt;div id="outline-container-headline-1" class="outline-2"&gt;&#10;&lt;h2 id="headline-1"&gt;&#10;Example: add YouTube to Firefox as a search engine&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-1" class="outline-text-2"&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Go to YouTube&lt;/li&gt;&#10;&lt;li&gt;Right-click the URL&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;figure&gt;&#10;&lt;img src="youtube-rightclick-search.png" alt="youtube-rightclick-search.png" title="youtube-rightclick-search.png" /&gt;&lt;figcaption&gt;&#10;Right-click menu on YouTube URL in Firefox&#10;&lt;/figcaption&gt;&#10;&lt;/figure&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Now you&amp;#39;ll find YouTube in Firefox settings:&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;figure&gt;&#10;&lt;img src="ff-search-settings-youtube.png" alt="ff-search-settings-youtube.png" title="ff-search-settings-youtube.png" /&gt;&lt;figcaption&gt;&#10;YouTube search engine in Firefox Search settings&#10;&lt;/figcaption&gt;&#10;&lt;/figure&gt;&#10;&lt;p&gt;&#10;If you give it keyworkd &lt;code class="verbatim"&gt;y&lt;/code&gt; for example, now when you type &lt;code class="verbatim"&gt;y laika party&lt;/code&gt; in the search bar, you&amp;#39;ll get the YouTube search results for &amp;#34;laika party&amp;#34;.&lt;/p&gt;</description></item><item><title>AI Image recognition: how good is it in 2025?</title><link>/2025-02-07-ai-imaging-report-card/</link><pubDate>Fri, 07 Feb 2025 00:00:00 +0000</pubDate><guid>/2025-02-07-ai-imaging-report-card/</guid><description>&lt;p&gt;&#10;Some days I am jolted out of my own complacency.&lt;/p&gt;&#10;&lt;p&gt;&#10;Recently I was sent on one of those GenAI training workshops - I&amp;#39;ve been to many of them now as an IT consultant. Our clients and the whole business ecosystem seems busy getting up to speed on it. One the more interesting hands-on workshops had us test the image analysis capabilities of various models.&lt;/p&gt;&#10;&lt;p&gt;&#10;Funny how we take image recognition for granted now. I couldn&amp;#39;t help be reminded of this xkcd cartoon from 2014.&lt;/p&gt;</description></item></channel></rss>