<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tim Apple</title>
    <description>The latest articles on DEV Community by Tim Apple (@ninepointlabs).</description>
    <link>https://dev.to/ninepointlabs</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4193989%2F5102901d-bf04-40d0-b061-127a71268038.jpg</url>
      <title>DEV Community: Tim Apple</title>
      <link>https://dev.to/ninepointlabs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ninepointlabs"/>
    <language>en</language>
    <item>
      <title>folderblog 0.2.11: posts ordered by date and time</title>
      <dc:creator>Tim Apple</dc:creator>
      <pubDate>Tue, 10 Nov 2026 18:27:39 +0000</pubDate>
      <link>https://dev.to/ninepointlabs/folderblog-0211-posts-ordered-by-date-and-time-4joo</link>
      <guid>https://dev.to/ninepointlabs/folderblog-0211-posts-ordered-by-date-and-time-4joo</guid>
      <description>&lt;p&gt;&lt;a href="https://folderblog.ninepointlabs.com" rel="noopener noreferrer"&gt;folderblog&lt;/a&gt; 0.2.11 puts posts in order by date and time, so several posts on the same day finally show up in the right order. The home page, archives, tag pages, feeds and the podcast list are all newest first by it.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;Every post date now carries a time of day. To set the time yourself, write it in &lt;code&gt;date&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;date: 2026-11-10 09:28
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A full timestamp with an offset works too, like &lt;code&gt;date: 2026-11-10T09:28:00-06:00&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A post with only a day (a &lt;code&gt;2026-11-10-&lt;/code&gt; filename or &lt;code&gt;date: 2026-11-10&lt;/code&gt;) gets the time it was first committed to git, or else the file’s modified time. That time is saved in &lt;code&gt;dates.toml&lt;/code&gt; the first time the post is published, so editing it later never reshuffles the day. The day, and so every address, stays the same.&lt;/p&gt;

&lt;p&gt;You can also set a &lt;code&gt;timezone&lt;/code&gt; in &lt;code&gt;blog.toml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="na"&gt;timezone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"America/Chicago"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dates written without an offset are read in that zone. Without it, folderblog uses the computer’s own zone, as before.&lt;/p&gt;

&lt;p&gt;A couple of other details:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Friendlier date typos.&lt;/strong&gt; An unreadable &lt;code&gt;date&lt;/code&gt; is now a warning (and the filename’s date is used) when the filename has one. &lt;code&gt;folderblog check&lt;/code&gt; also warns about an unreadable &lt;code&gt;updated&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Read this before you update
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;timezone&lt;/code&gt; needs 0.2.11 or newer.&lt;/strong&gt; Older versions refuse a &lt;code&gt;blog.toml&lt;/code&gt; that has it, so update every machine that builds the blog first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expect a one-time change to &lt;code&gt;dates.toml&lt;/code&gt;.&lt;/strong&gt; The first build adds a time for each post dated by filename or a date-only &lt;code&gt;date:&lt;/code&gt;. Commit it with your blog.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feeds now show real times instead of midnight,&lt;/strong&gt; and a few same-day posts may swap places in the feed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Grab it
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;System&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Arch / Omarchy&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sudo pacman -U folderblog-bin-0.2.11-1-x86_64.pkg.tar.zst&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Debian / Ubuntu&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sudo apt install ./folderblog_0.2.11-1_amd64.deb&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fedora / RHEL / openSUSE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sudo dnf install ./folderblog-0.2.11-1.x86_64.rpm&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;autonomix-cli&lt;/td&gt;
&lt;td&gt;&lt;code&gt;autonomix-cli add https://github.com/ninepointlabs/folderblog&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Already installed? Install the new package, then run &lt;code&gt;systemctl --user restart folderblog&lt;/code&gt;. The packages and a plain tarball are on the &lt;a href="https://github.com/ninepointlabs/folderblog/releases/tag/v0.2.11" rel="noopener noreferrer"&gt;v0.2.11 release&lt;/a&gt;, and the source is &lt;a href="https://github.com/ninepointlabs/folderblog" rel="noopener noreferrer"&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://blog.ninepointlabs.com/2026/11/folderblog-0-2-11/" rel="noopener noreferrer"&gt;blog.ninepointlabs.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>blogging</category>
      <category>linux</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Dogear 0.1.3: EPUB books, marked up like a PDF</title>
      <dc:creator>Tim Apple</dc:creator>
      <pubDate>Mon, 09 Nov 2026 01:31:11 +0000</pubDate>
      <link>https://dev.to/ninepointlabs/dogear-013-epub-books-marked-up-like-a-pdf-2ana</link>
      <guid>https://dev.to/ninepointlabs/dogear-013-epub-books-marked-up-like-a-pdf-2ana</guid>
      <description>&lt;p&gt;&lt;a href="https://dogear.ninepointlabs.com/" rel="noopener noreferrer"&gt;Dogear&lt;/a&gt; is the reader for studying, made for Omarchy. Version &lt;strong&gt;0.1.3&lt;/strong&gt; opens EPUB books, so it now reads, highlights and remembers your PDFs and EPUBs.&lt;/p&gt;

&lt;h2&gt;
  
  
  EPUB books
&lt;/h2&gt;

&lt;p&gt;Open an &lt;code&gt;.epub&lt;/code&gt; the same way as a PDF: from the Open dialog, the command line, by dropping it on the window, or from the library. The first time, Dogear sets the book in pages (6 × 9 in, chapters starting on a new page), which takes a second or two for a long book, and keeps those pages. After that everything works as it does for a PDF: highlights in five colors, notes, bookmarks, answer lines, search, the library and the Markdown export. The Contents panel shows the book’s own table of contents.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your marks belong to the book
&lt;/h2&gt;

&lt;p&gt;The library lists the EPUB, and the EPUB is what Dogear copies into &lt;code&gt;Library/&lt;/code&gt;. The laid-out pages live in your library folder, so they sync with your marks and another computer shows the same pages. They’re never laid out again, so your marks stay on the words you marked. Another copy of the same book (same identifier, such as its ISBN) is offered your marks, just as with PDFs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Good to know
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Books get one plain, readable style. Bold, italics, headings, lists, tables and images are kept; the publisher’s styling, links inside the book and most SVG drawings aren’t.&lt;/li&gt;
&lt;li&gt;DRM-protected EPUBs can’t be opened.&lt;/li&gt;
&lt;li&gt;There’s no choice of page size or font yet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fix:&lt;/strong&gt; the Arch package now depends on &lt;code&gt;qt6-svg&lt;/code&gt;. Without it, Dogear’s icon (and SVG images in books) couldn’t be shown. Most desktops already have it, so few noticed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Get it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;autonomix-cli add https://github.com/ninepointlabs/dogear
autonomix-cli &lt;span class="nb"&gt;install &lt;/span&gt;dogear
&lt;span class="c"&gt;# or, if you already track it:&lt;/span&gt;
autonomix-cli update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On Arch or Omarchy you can also grab &lt;code&gt;dogear-0.1.3-1-any.pkg.tar.zst&lt;/code&gt; and run &lt;code&gt;sudo pacman -U&lt;/code&gt; on it; on any other Linux, the AppImage runs as is. Both are on the &lt;a href="https://github.com/ninepointlabs/dogear/releases/tag/v0.1.3" rel="noopener noreferrer"&gt;v0.1.3 release&lt;/a&gt;, and the source is &lt;a href="https://github.com/ninepointlabs/dogear" rel="noopener noreferrer"&gt;on GitHub&lt;/a&gt;. Questions go to &lt;a href="mailto:help@ninepointlabs.com"&gt;help@ninepointlabs.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://blog.ninepointlabs.com/2026/11/dogear-0-1-3/" rel="noopener noreferrer"&gt;blog.ninepointlabs.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>opensource</category>
      <category>epub</category>
      <category>pdf</category>
    </item>
    <item>
      <title>omaforge 0.2.9: star addons to find them later</title>
      <dc:creator>Tim Apple</dc:creator>
      <pubDate>Thu, 05 Nov 2026 02:21:50 +0000</pubDate>
      <link>https://dev.to/ninepointlabs/omaforge-029-star-addons-to-find-them-later-13np</link>
      <guid>https://dev.to/ninepointlabs/omaforge-029-star-addons-to-find-them-later-13np</guid>
      <description>&lt;p&gt;&lt;a href="https://omaforge.ninepointlabs.com/" rel="noopener noreferrer"&gt;omaforge&lt;/a&gt; is the World of Warcraft addon manager for Linux and Omarchy. Version 0.2.9 lets you star addons, so you can bookmark one you haven’t installed and come back to it later.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s new
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Star any addon.&lt;/strong&gt; Click the ☆ on an addon in Explore, Search or Installed, or in its details view. Stars are saved between sessions, are shared by all your game versions, and stay when you remove the addon. An addon with no known source can’t be starred.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A new Starred tab.&lt;/strong&gt; It sits between Search and Backups and lists everything you’ve starred, with a filter, a sort (Recently starred or Name) and a Not installed toggle. Install adds the addon to the game version selected in the sidebar, and if an addon has no build for that version you get the usual “no stable release” message.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shortcut change.&lt;/strong&gt; &lt;code&gt;Ctrl&lt;/code&gt;+&lt;code&gt;4&lt;/code&gt; now opens Starred, and Backups moved to &lt;code&gt;Ctrl&lt;/code&gt;+&lt;code&gt;5&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Arch / Omarchy:&lt;/strong&gt; &lt;code&gt;sudo pacman -U omaforge-0.2.9-1-any.pkg.tar.zst&lt;/code&gt;, then &lt;code&gt;omaforge setup omarchy&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debian 13+ / Ubuntu 26.04+:&lt;/strong&gt; &lt;code&gt;sudo apt install ./omaforge_0.2.9-1_all.deb&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fedora:&lt;/strong&gt; &lt;code&gt;sudo dnf install ./omaforge-0.2.9-1.noarch.rpm&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Any other Linux:&lt;/strong&gt; the AppImage, &lt;code&gt;chmod +x omaforge-0.2.9-x86_64.AppImage &amp;amp;&amp;amp; ./omaforge-0.2.9-x86_64.AppImage&lt;/code&gt;. Add &lt;code&gt;--install-desktop-entry&lt;/code&gt; to put it in your app menu.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;With autonomix-cli:&lt;/strong&gt; &lt;code&gt;autonomix-cli add https://github.com/ninepointlabs/omaforge&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The packages are on the &lt;a href="https://github.com/ninepointlabs/omaforge/releases/tag/v0.2.9" rel="noopener noreferrer"&gt;v0.2.9 release&lt;/a&gt;, and the source is &lt;a href="https://github.com/ninepointlabs/omaforge" rel="noopener noreferrer"&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://blog.ninepointlabs.com/2026/11/omaforge-0-2-9/" rel="noopener noreferrer"&gt;blog.ninepointlabs.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>gaming</category>
      <category>opensource</category>
      <category>wow</category>
    </item>
    <item>
      <title>Persistwise: writing that outlasts the platform</title>
      <dc:creator>Tim Apple</dc:creator>
      <pubDate>Fri, 30 Oct 2026 18:32:31 +0000</pubDate>
      <link>https://dev.to/ninepointlabs/persistwise-writing-that-outlasts-the-platform-34b5</link>
      <guid>https://dev.to/ninepointlabs/persistwise-writing-that-outlasts-the-platform-34b5</guid>
      <description>&lt;p&gt;I have a bad habit with blogs. I start one somewhere that feels right, write for a while, then the platform changes, the export is a mess, and the old posts sit there like a burned CD nobody can play. Geocities. LiveJournal. A host that quietly folded. Same movie, different sequel.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;&lt;a href="https://persistwise.com" rel="noopener noreferrer"&gt;Persistwise&lt;/a&gt;&lt;/strong&gt;, and today I’d like to invite you to try it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://persistwise.com" rel="noopener noreferrer"&gt;persistwise.com&lt;/a&gt;&lt;/strong&gt; · &lt;strong&gt;&lt;a href="https://persistwise.com/registration/new" rel="noopener noreferrer"&gt;Start a free trial&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;Persistwise is not another place to write. You keep blogging wherever you already do: HEY World, Substack, your own site, a newsletter, even a social feed. You give Persistwise the feed, and it does the quiet filing in the background.&lt;/p&gt;

&lt;p&gt;It checks your feeds every 15 minutes. When it finds a new post, it keeps three copies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A Wayback Machine snapshot.&lt;/strong&gt; Persistwise asks the Internet Archive to capture the post. That snapshot lives on archive.org, it’s public, and anyone can open it without Persistwise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An IPFS pin.&lt;/strong&gt; The saved copy is pinned through Pinata onto the public IPFS network, with a content ID that points at that exact copy of your post.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A saved copy we keep.&lt;/strong&gt; The post’s HTML is stored on our own storage, so there is something to fall back on when an outside service is slow or down. Only you can open it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your Archive page shows one line per post, with a link to each copy and a plain status for each one. If the Wayback Machine is busy, Persistwise waits and tries again later, so you don’t have to babysit anything.&lt;/p&gt;

&lt;p&gt;RSS, Atom and JSON Feed all work. The first check takes in every post your feed lists at that moment, then new posts get picked up as they appear.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I wanted it
&lt;/h2&gt;

&lt;p&gt;Most of us don’t lose writing because we’re careless. We lose it because the web is a rental. The landlord changes the locks, the feed dies, the pretty URL turns into a 404. The Wayback Machine is wonderful, but it only saves what someone asks it to save. I wanted a boring, stubborn librarian whose only job is to ask every time.&lt;/p&gt;

&lt;p&gt;I also didn’t want to build another editor. I already have places I like to write, and so do you. The whole point is that you don’t have to move.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep: 30 days free, then $40 a year
&lt;/h2&gt;

&lt;p&gt;There is one plan, called Keep. It’s &lt;strong&gt;30 days free, then $40 a year&lt;/strong&gt;, and you don’t need a card to start. Create an account, press “Start free trial,” and add your feed.&lt;/p&gt;

&lt;p&gt;About three days before the trial ends, we’ll email you if you haven’t added a card. If you decide not to keep going, Keep pauses and nothing is deleted. Your Archive page stays readable, and your Wayback snapshots and IPFS pins stay where they are. The Wayback snapshots are kept by the Internet Archive, not by us, so they don’t depend on Persistwise at all. We don’t delete people for leaving.&lt;/p&gt;

&lt;p&gt;A yearly price felt right for something meant to last. Longevity and a monthly habit you cancel in February don’t get along very well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest notes
&lt;/h2&gt;

&lt;p&gt;It’s early, and I’d rather tell you the edges up front. Each post is captured once, when Persistwise first sees it, so later edits aren’t saved. The copies are the page’s HTML only, without images or stylesheets, so they may look plainer than the original. There’s no export button yet. And Wayback and IPFS copies are public, so please only add feeds for writing you’re happy to keep public.&lt;/p&gt;

&lt;h2&gt;
  
  
  Give it a try
&lt;/h2&gt;

&lt;p&gt;If you have a feed you care about, I’d be grateful if you’d let Persistwise keep it. Go to &lt;strong&gt;&lt;a href="https://persistwise.com" rel="noopener noreferrer"&gt;persistwise.com&lt;/a&gt;&lt;/strong&gt;, read &lt;a href="https://persistwise.com/how-it-works" rel="noopener noreferrer"&gt;how it works&lt;/a&gt; if you’re curious, and &lt;a href="https://persistwise.com/registration/new" rel="noopener noreferrer"&gt;start your free trial&lt;/a&gt;. If anything doesn’t work the way you expect, please write to &lt;a href="mailto:help@ninepointlabs.com"&gt;help@ninepointlabs.com&lt;/a&gt;. I’d really like to hear from you.&lt;/p&gt;

&lt;p&gt;Thanks for reading. Now go write the next one, and let the librarian do the filing.&lt;/p&gt;

</description>
      <category>blogging</category>
      <category>indieweb</category>
      <category>rss</category>
      <category>archive</category>
    </item>
    <item>
      <title>Sunsetting Rune, and why I'm writing in WordCraft now</title>
      <dc:creator>Tim Apple</dc:creator>
      <pubDate>Thu, 29 Oct 2026 18:56:19 +0000</pubDate>
      <link>https://dev.to/ninepointlabs/sunsetting-rune-and-why-im-writing-in-wordcraft-now-139l</link>
      <guid>https://dev.to/ninepointlabs/sunsetting-rune-and-why-im-writing-in-wordcraft-now-139l</guid>
      <description>&lt;p&gt;Earlier this month I started building &lt;strong&gt;&lt;a href="https://github.com/ninepointlabs/rune" rel="noopener noreferrer"&gt;Rune&lt;/a&gt;&lt;/strong&gt;, a word processor for Linux and Omarchy with AI built right into the writing surface. Today I’m archiving it, and I’d like to tell you why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I built Rune
&lt;/h2&gt;

&lt;p&gt;Word processors on Linux felt like a choice between heavyweight ports and plain text editors pretending to be word processors. And every one of them treated AI as a sidebar plugin. I wanted the opposite: a fast, native app where the model is part of the page, where you can ask it to fix a paragraph and the fix lands right in your document as one undo step.&lt;/p&gt;

&lt;p&gt;Rune got further than I expected. It went from an idea to version 0.8.7 in about two weeks, with packages for Arch, Debian and Fedora, an AppImage for most other distros, headers and footers, tables, and sign-in for ChatGPT and OpenRouter.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;Quite a lot, honestly. Rune started on LibreOfficeKit and ended up as a single Qt process that reads and writes ODF itself, because the first design had a performance ceiling I couldn’t get past. Along the way I learned to test real files instead of trusting documentation. That habit caught a bug in Qt’s own ODF writer, where a table right after a list silently disappeared when LibreOffice opened the file. By the end, Rune was checked by 504 automated tests. I’ll carry that way of working into everything I build next.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then I found WordCraft
&lt;/h2&gt;

&lt;p&gt;Recently I came across &lt;strong&gt;&lt;a href="https://getartcraft.com/apps/wordcraft" rel="noopener noreferrer"&gt;WordCraft&lt;/a&gt;&lt;/strong&gt;, a fast, open-source word processor written in Rust by the ArtCraft team. I tried it, and it’s really good.&lt;/p&gt;

&lt;p&gt;It does what Rune set out to do, and more. It has a ribbon and styles, works with .docx natively along with .odt, Markdown and more, exports PDF, and has track changes and comments, offline spelling and grammar, footnotes, a table of contents, and citations in APA, MLA, Chicago and IEEE. It runs on Linux as a Flatpak, plus macOS, Windows, FreeBSD and the web.&lt;/p&gt;

&lt;p&gt;The part that really got me is how it treats AI. Its commands are available through a command-line tool, a JSON control channel and an MCP server, so AI assistants can work inside your documents. That’s the idea I was chasing with Rune, done in a more open way: you bring whichever assistant you like.&lt;/p&gt;

&lt;p&gt;It’s still in development, but it’s already well past where Rune is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why archive instead of compete
&lt;/h2&gt;

&lt;p&gt;I could keep going. But I’m one person, word processors are a lot of work to maintain, and the world doesn’t need two small open-source editors chasing the same idea when one of them is already further along. I’d rather spend my time on things only Nine Point Labs can build, and send you to the better tool.&lt;/p&gt;

&lt;p&gt;So Rune is archived. The code stays up under the MIT license, along with the existing releases, if you’d like to learn from it or fork it. The README now points to WordCraft.&lt;/p&gt;

&lt;h2&gt;
  
  
  Give WordCraft a try
&lt;/h2&gt;

&lt;p&gt;If you write on Linux, or anywhere really, please give &lt;strong&gt;&lt;a href="https://getartcraft.com/apps/wordcraft" rel="noopener noreferrer"&gt;WordCraft&lt;/a&gt;&lt;/strong&gt; a try. The source is on &lt;strong&gt;&lt;a href="https://github.com/storytold/wordcraft" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/strong&gt; if you’d like to dig in or help out.&lt;/p&gt;

&lt;p&gt;Thank you to everyone who tried Rune or sent a kind word about it. It meant a lot.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://blog.ninepointlabs.com/2026/10/sunsetting-rune/" rel="noopener noreferrer"&gt;The Word from Nine Point Labs&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>opensource</category>
      <category>rust</category>
      <category>productivity</category>
    </item>
    <item>
      <title>StoryTracker takes its own screenshots now</title>
      <dc:creator>Tim Apple</dc:creator>
      <pubDate>Wed, 28 Oct 2026 15:29:07 +0000</pubDate>
      <link>https://dev.to/ninepointlabs/storytracker-takes-its-own-screenshots-now-44bk</link>
      <guid>https://dev.to/ninepointlabs/storytracker-takes-its-own-screenshots-now-44bk</guid>
      <description>&lt;p&gt;&lt;a href="https://ninepointlabs.com/#storytracker" rel="noopener noreferrer"&gt;StoryTracker&lt;/a&gt; is the World of Warcraft addon that keeps a record of your character’s adventures: quests, zones, levels, deaths, bosses, loot and more. It comes in two versions, one for &lt;a href="https://github.com/ninepointlabs/wow-storytracker-addon" rel="noopener noreferrer"&gt;WoW Forever&lt;/a&gt; and one for &lt;a href="https://github.com/ninepointlabs/wow-storytracker-addon-retail" rel="noopener noreferrer"&gt;Retail&lt;/a&gt;. Yesterday’s releases (Forever 1.0.4 and 1.0.5, Retail 1.1.3 to 1.1.5) add automatic screenshots at the moments that make a good story, and make the addon easier to install with an addon manager.&lt;/p&gt;

&lt;h2&gt;
  
  
  Screenshots at story moments
&lt;/h2&gt;

&lt;p&gt;StoryTracker now takes a screenshot about three quarters of a second after:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a quest turn-in&lt;/li&gt;
&lt;li&gt;a level up&lt;/li&gt;
&lt;li&gt;an achievement (on Forever, only if the client fires the achievement event)&lt;/li&gt;
&lt;li&gt;a boss kill&lt;/li&gt;
&lt;li&gt;your first visit to a zone&lt;/li&gt;
&lt;li&gt;other story moments, such as entering a dungeon or battleground, a battleground result, rare or elite kills, a new mount, epic or better loot, duels, joining a guild, a reputation standing going up, and deaths&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There’s also an optional timed shot every 15 minutes, taken only when you’re out of combat, not on a loading screen and not AFK.&lt;/p&gt;

&lt;p&gt;It takes at most one shot every 20 seconds. When two moments land together, like a turn-in that also dings, the shot is labelled with the bigger one. If you turn on “hide UI”, the interface is hidden for the shot while you’re out of combat, and it’s never touched in combat.&lt;/p&gt;

&lt;p&gt;Each shot is logged in the addon’s saved data with its time, the file name WoW gives it, what happened, the zone and subzone, and your character’s name, realm and level. Log entries older than 30 days are dropped. Addons can’t delete files, so StoryTracker never removes screenshots itself; clean up the game’s &lt;code&gt;Screenshots&lt;/code&gt; folder outside the game.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turning it on and off
&lt;/h2&gt;

&lt;p&gt;Screenshots are on by default, and everything is under &lt;code&gt;/storytracker shots&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/storytracker shots on|off&lt;/code&gt; turns automatic screenshots on or off.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/storytracker shots &amp;lt;event&amp;gt; on|off&lt;/code&gt; controls each kind: &lt;code&gt;quest&lt;/code&gt;, &lt;code&gt;levelup&lt;/code&gt;, &lt;code&gt;achievement&lt;/code&gt;, &lt;code&gt;boss&lt;/code&gt;, &lt;code&gt;newzone&lt;/code&gt; and &lt;code&gt;story&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/storytracker shots timer on|off|&amp;lt;minutes&amp;gt;&lt;/code&gt; sets the timed shot (1 to 120 minutes, 15 by default).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/storytracker shots hideui on|off&lt;/code&gt; hides the interface for out-of-combat shots (off by default).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/storytracker shots log&lt;/code&gt; shows the last few logged shots.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Easier installs with an addon manager
&lt;/h2&gt;

&lt;p&gt;Each release is now built with the BigWigs packager and comes with a small &lt;code&gt;release.json&lt;/code&gt; file that says which game it’s for. Addon managers such as &lt;a href="https://omaforge.ninepointlabs.com/" rel="noopener noreferrer"&gt;OmaForge&lt;/a&gt; use it to install the right StoryTracker for each client, so the Forever build goes to Forever and the Retail build goes to Retail. Installed copies also link back to their GitHub page now. Retail 1.1.5 updates the addon for the 12.1.5 client so it isn’t flagged as out of date.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it matters
&lt;/h2&gt;

&lt;p&gt;StoryTracker’s notes are what turn a play session into a post on &lt;a href="https://myazerothlife.com/" rel="noopener noreferrer"&gt;My Azeroth Life&lt;/a&gt;. Words were only half of it. Now each story moment comes with a picture taken right when it happened, and the log says exactly which shot goes with which moment, so a post can show the boss kill or the first look at a new zone instead of a stock image.&lt;/p&gt;

&lt;h2&gt;
  
  
  Privacy
&lt;/h2&gt;

&lt;p&gt;Nothing changes here. StoryTracker has no network access, since WoW addons can’t use the internet. Screenshots are saved by WoW to its own &lt;code&gt;Screenshots&lt;/code&gt; folder on your computer, and the log only records when and where each one was taken.&lt;/p&gt;

&lt;p&gt;Download the latest &lt;a href="https://github.com/ninepointlabs/wow-storytracker-addon/releases" rel="noopener noreferrer"&gt;Forever release&lt;/a&gt; or &lt;a href="https://github.com/ninepointlabs/wow-storytracker-addon-retail/releases" rel="noopener noreferrer"&gt;Retail release&lt;/a&gt;, or install it with OmaForge. The code is on GitHub for &lt;a href="https://github.com/ninepointlabs/wow-storytracker-addon" rel="noopener noreferrer"&gt;Forever&lt;/a&gt; and &lt;a href="https://github.com/ninepointlabs/wow-storytracker-addon-retail" rel="noopener noreferrer"&gt;Retail&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://blog.ninepointlabs.com/2026/10/storytracker-auto-screenshots/" rel="noopener noreferrer"&gt;blog.ninepointlabs.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>worldofwarcraft</category>
      <category>gaming</category>
      <category>lua</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Omostrich 0.3.3: tighter signing grants and safer profile pictures</title>
      <dc:creator>Tim Apple</dc:creator>
      <pubDate>Tue, 27 Oct 2026 14:39:21 +0000</pubDate>
      <link>https://dev.to/ninepointlabs/omostrich-033-tighter-signing-grants-and-safer-profile-pictures-215b</link>
      <guid>https://dev.to/ninepointlabs/omostrich-033-tighter-signing-grants-and-safer-profile-pictures-215b</guid>
      <description>&lt;p&gt;&lt;a href="https://omostrich.com/" rel="noopener noreferrer"&gt;Omostrich&lt;/a&gt; keeps your Nostr key on your own computer and signs for your apps from the Omarchy bar. Two releases landed this morning. Version 0.3.2 finishes the profile picture hardening that 0.3.1 started, and version 0.3.3 makes your signing permissions narrower and your approval prompts clearer, especially around direct messages.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed in 0.3.3
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"Always allow" now covers one kind of event, not everything.&lt;/strong&gt; Before, remembering a signing request for an app meant that app could sign any kind of Nostr event without asking again. Now the button names the kind it covers, for example "Always allow sign kind 4 (DM)", and Authorized apps lists each app's grants kind by kind.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Encrypt and decrypt prompts show who's on the other end.&lt;/strong&gt; Each request shows the other person as a shortened npub (marked "(you)" when it's yourself) and whether you're encrypting to them or decrypting from them. Encrypt requests also show a short preview of the plain text. A kind 4 signing request shows its recipient, and DM ciphertext is no longer previewed. None of this goes into the log.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The signer keeps running when notifications can't.&lt;/strong&gt; If &lt;code&gt;notify-send&lt;/code&gt; is missing or fails, Omostrich logs it once, with an error code only, and carries on instead of crashing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Smaller fixes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Signing requests for kind 14 and kind 1059 (private messages and gift wraps) show a warning and can only be approved once, never remembered.&lt;/li&gt;
&lt;li&gt;Your public key is handed out without a prompt only to an app that connected this session or that you've remembered. Anyone else gets asked.&lt;/li&gt;
&lt;li&gt;Gift-wrap notifications look back two days, and unlocking no longer sets off a burst of old ones.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What changed in 0.3.2
&lt;/h2&gt;

&lt;p&gt;0.3.1 put limits on how big your cached profile picture could be, but the file could still carry compressed metadata that expands while the image is being read. A small, hostile picture could push the panel to several gigabytes of memory. Now the daemon rewrites the downloaded picture down to just the parts needed to draw it, with no re-encoding and no new dependency:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PNG&lt;/strong&gt; keeps only the image data and the colour chunks it needs. An unknown critical chunk is refused.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JPEG&lt;/strong&gt; drops comments, EXIF, ICC, XMP and Photoshop data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GIF&lt;/strong&gt; keeps the first frame only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WebP&lt;/strong&gt; keeps the image data and drops everything else. Animated WebP is refused, so the placeholder shows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anything after the end of the image is dropped too, and a picture cached by 0.3.1 is fetched again on startup, so the cache only ever holds the stripped copy. This came out of the Omarchy plugin marketplace review (&lt;a href="https://github.com/omacom/omarchy-plugin-marketplace/issues/12494" rel="noopener noreferrer"&gt;#12494&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it matters
&lt;/h2&gt;

&lt;p&gt;Your signer should do exactly what you agreed to and nothing more. A blanket "always allow" was easy to click and hard to reason about later, and a DM prompt that doesn't say who it's for asks you to approve blind. Per-kind grants and clearer prompts mean you can see what each app is allowed to do and who your messages are going to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Upgrading
&lt;/h2&gt;

&lt;p&gt;Old blanket signing grants meant "sign any kind", and there's no way to tell which kind you had in mind, so they're &lt;strong&gt;removed the first time 0.3.3 starts&lt;/strong&gt;. The app and its other grants stay, &lt;code&gt;daemon.log&lt;/code&gt; names each affected app, and the app asks once more for each kind it needs.&lt;/p&gt;

&lt;p&gt;To update an existing install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/Projects/omostrich
git pull
npm ci
./install-daemon.sh
./install-plugin.sh
systemctl &lt;span class="nt"&gt;--user&lt;/span&gt; restart omostrich
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The restart matters, because the running signer keeps the old code until it's restarted. The full notes are on the &lt;a href="https://github.com/ninepointlabs/omostrich/releases/tag/v0.3.2" rel="noopener noreferrer"&gt;0.3.2&lt;/a&gt; and &lt;a href="https://github.com/ninepointlabs/omostrich/releases/tag/v0.3.3" rel="noopener noreferrer"&gt;0.3.3&lt;/a&gt; release pages, the code is on &lt;a href="https://github.com/ninepointlabs/omostrich" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, and more about Omostrich is at &lt;a href="https://omostrich.com/" rel="noopener noreferrer"&gt;omostrich.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://blog.ninepointlabs.com/2026/10/omostrich-0-3-3/" rel="noopener noreferrer"&gt;blog.ninepointlabs.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>nostr</category>
      <category>linux</category>
      <category>security</category>
      <category>opensource</category>
    </item>
    <item>
      <title>omaforge 0.2.8: fixes from a full QA pass</title>
      <dc:creator>Tim Apple</dc:creator>
      <pubDate>Mon, 26 Oct 2026 22:21:03 +0000</pubDate>
      <link>https://dev.to/ninepointlabs/omaforge-028-fixes-from-a-full-qa-pass-1cgm</link>
      <guid>https://dev.to/ninepointlabs/omaforge-028-fixes-from-a-full-qa-pass-1cgm</guid>
      <description>&lt;p&gt;&lt;a href="https://omaforge.ninepointlabs.com/" rel="noopener noreferrer"&gt;omaforge&lt;/a&gt; is the World of Warcraft addon manager for Linux and Omarchy. Version 0.2.8 is a fixes release from a full QA pass, coming the same day as 0.2.7.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s fixed
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Safer uninstall.&lt;/strong&gt; &lt;code&gt;omaforge uninstall&lt;/code&gt; now asks before removing an addon it can’t trace to a source, such as one you wrote yourself. Without a terminal it refuses unless you pass &lt;code&gt;--yes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Damaged files no longer crash omaforge or lose data.&lt;/strong&gt; A broken &lt;code&gt;config.toml&lt;/code&gt; or &lt;code&gt;flavors.toml&lt;/code&gt; gives a one-line message naming the file and the problem, and omaforge never writes over it. In the app, a red banner names the file and offers Open file, Rescan, or setting it aside (it’s kept as &lt;code&gt;&amp;lt;name&amp;gt;.broken-&amp;lt;time&amp;gt;&lt;/code&gt;). A damaged &lt;code&gt;state.json&lt;/code&gt; is moved to &lt;code&gt;state.json.damaged-&amp;lt;time&amp;gt;&lt;/code&gt; and a fresh one is started, with a warning in both the CLI and the app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fits half a screen.&lt;/strong&gt; The window now goes down to 640 px wide. Below 1000 px the sidebar narrows, the tabs move under the title, and less-used actions (Import/Export, and each addon’s channel, Pin, Ignore and Remove) move into a &lt;code&gt;⋯&lt;/code&gt; menu. Alt+↑ and Alt+↓ switch between game versions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Clearer messages.&lt;/strong&gt; An unknown addon id, an AddOns folder omaforge can’t write to, an unknown root or provider, and an empty GitHub search now say what went wrong in plain words. CurseForge versions no longer show up as &lt;code&gt;1.0.1.zip&lt;/code&gt; or offer an update that isn’t there, &lt;code&gt;check&lt;/code&gt; lists each addon it couldn’t check and why, and Wago says plainly that it isn’t supported yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Arch / Omarchy:&lt;/strong&gt; &lt;code&gt;sudo pacman -U omaforge-0.2.8-1-any.pkg.tar.zst&lt;/code&gt;, then &lt;code&gt;omaforge setup omarchy&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debian 13+ / Ubuntu 26.04+:&lt;/strong&gt; &lt;code&gt;sudo apt install ./omaforge_0.2.8-1_all.deb&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fedora:&lt;/strong&gt; &lt;code&gt;sudo dnf install ./omaforge-0.2.8-1.noarch.rpm&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Any other Linux:&lt;/strong&gt; the AppImage, &lt;code&gt;chmod +x omaforge-0.2.8-x86_64.AppImage &amp;amp;&amp;amp; ./omaforge-0.2.8-x86_64.AppImage&lt;/code&gt;. Add &lt;code&gt;--install-desktop-entry&lt;/code&gt; to put it in your app menu.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;With autonomix-cli:&lt;/strong&gt; &lt;code&gt;autonomix-cli add https://github.com/ninepointlabs/omaforge&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The packages are on the &lt;a href="https://github.com/ninepointlabs/omaforge/releases/tag/v0.2.8" rel="noopener noreferrer"&gt;v0.2.8 release&lt;/a&gt;, and the source is &lt;a href="https://github.com/ninepointlabs/omaforge" rel="noopener noreferrer"&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://blog.ninepointlabs.com/2026/10/omaforge-0-2-8/" rel="noopener noreferrer"&gt;blog.ninepointlabs.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>opensource</category>
      <category>gaming</category>
      <category>archlinux</category>
    </item>
    <item>
      <title>omaforge 0.2.7: ready for World of Warcraft: Forever</title>
      <dc:creator>Tim Apple</dc:creator>
      <pubDate>Mon, 26 Oct 2026 16:31:25 +0000</pubDate>
      <link>https://dev.to/ninepointlabs/omaforge-027-ready-for-world-of-warcraft-forever-ki</link>
      <guid>https://dev.to/ninepointlabs/omaforge-027-ready-for-world-of-warcraft-forever-ki</guid>
      <description>&lt;p&gt;&lt;a href="https://omaforge.ninepointlabs.com/" rel="noopener noreferrer"&gt;omaforge&lt;/a&gt; is the World of Warcraft addon manager for Linux and Omarchy. Version 0.2.7 gets it ready for World of Warcraft: Forever, which launches on November 4.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s new
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;omaforge knows the Forever release client.&lt;/strong&gt; Battle.net installs Forever in its own &lt;code&gt;_forever_&lt;/code&gt; folder (product &lt;code&gt;wowf&lt;/code&gt;). omaforge now lists that install as &lt;strong&gt;Forever&lt;/strong&gt;, even before you’ve started the game for the first time and there’s no &lt;code&gt;Interface/AddOns&lt;/code&gt; folder yet. If Battle.net hasn’t filled in a version, omaforge shows &lt;code&gt;not installed yet&lt;/code&gt; instead of guessing. The first addon you install creates &lt;code&gt;Interface/AddOns&lt;/code&gt; for you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pick it from the command line with &lt;code&gt;-c forever&lt;/code&gt;.&lt;/strong&gt; The beta client is still &lt;code&gt;-c classic_beta&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Leftover beta folders get a proper name.&lt;/strong&gt; If you played the beta, you may still have a &lt;code&gt;_classic_beta_&lt;/code&gt; folder that Battle.net no longer lists. It now shows up as &lt;strong&gt;Forever Beta&lt;/strong&gt; rather than an unknown game.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it matters
&lt;/h2&gt;

&lt;p&gt;You can have your addons in place before launch day instead of waiting for the game to create its folders. Install Forever through Battle.net, open omaforge, and set it up the same way you already do for Retail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Arch / Omarchy:&lt;/strong&gt; &lt;code&gt;sudo pacman -U omaforge-0.2.7-1-any.pkg.tar.zst&lt;/code&gt;, then &lt;code&gt;omaforge setup omarchy&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debian 13+ / Ubuntu 26.04+:&lt;/strong&gt; &lt;code&gt;sudo apt install ./omaforge_0.2.7-1_all.deb&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fedora:&lt;/strong&gt; &lt;code&gt;sudo dnf install ./omaforge-0.2.7-1.noarch.rpm&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Any other Linux:&lt;/strong&gt; the AppImage, &lt;code&gt;chmod +x omaforge-0.2.7-x86_64.AppImage &amp;amp;&amp;amp; ./omaforge-0.2.7-x86_64.AppImage&lt;/code&gt;. Add &lt;code&gt;--install-desktop-entry&lt;/code&gt; to put it in your app menu.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;With autonomix-cli:&lt;/strong&gt; &lt;code&gt;autonomix-cli add https://github.com/ninepointlabs/omaforge&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The packages are on the &lt;a href="https://github.com/ninepointlabs/omaforge/releases/tag/v0.2.7" rel="noopener noreferrer"&gt;v0.2.7 release&lt;/a&gt;, and the source is &lt;a href="https://github.com/ninepointlabs/omaforge" rel="noopener noreferrer"&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://blog.ninepointlabs.com/2026/10/omaforge-0-2-7/" rel="noopener noreferrer"&gt;blog.ninepointlabs.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>opensource</category>
      <category>gaming</category>
      <category>archlinux</category>
    </item>
    <item>
      <title>folderblog 0.2.10: podcast download stats with OP3</title>
      <dc:creator>Tim Apple</dc:creator>
      <pubDate>Mon, 26 Oct 2026 15:29:14 +0000</pubDate>
      <link>https://dev.to/ninepointlabs/folderblog-0210-podcast-download-stats-with-op3-33d2</link>
      <guid>https://dev.to/ninepointlabs/folderblog-0210-podcast-download-stats-with-op3-33d2</guid>
      <description>&lt;p&gt;&lt;a href="https://folderblog.ninepointlabs.com" rel="noopener noreferrer"&gt;folderblog&lt;/a&gt; 0.2.10 adds one thing podcasters have been asking about: download numbers. If you publish a show with folderblog, you can now count how often your episodes are downloaded with &lt;a href="https://op3.dev" rel="noopener noreferrer"&gt;OP3&lt;/a&gt;, the free, open-source podcast stats service.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;Add one line under &lt;code&gt;[podcast]&lt;/code&gt; in &lt;code&gt;blog.toml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="n"&gt;analytics_prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"https://op3.dev/e/"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every episode in your feeds then goes through OP3 in the form OP3 documents, including your show’s guid so OP3 can attribute downloads sooner. There’s no account to create. After a few days, your public stats page is at &lt;code&gt;https://op3.dev/show/&amp;lt;your podcast guid&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A few details:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It’s off by default.&lt;/strong&gt; Existing feeds don’t change unless you add the line.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Only the feed changes.&lt;/strong&gt; Uploads, the deploy’s size check and the player on your episode pages keep using your own address. That also means plays on your episode pages aren’t counted, only downloads from podcast apps.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;folderblog podcast&lt;/code&gt; tells you whether stats are on.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Other prefix services work too,&lt;/strong&gt; as long as the prefix starts with &lt;code&gt;https://&lt;/code&gt; and ends in &lt;code&gt;/&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;a href="https://myazerothlife.com/podcast/" rel="noopener noreferrer"&gt;My Azeroth Life podcast&lt;/a&gt; is already running on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read this before you update
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;analytics_prefix&lt;/code&gt; needs 0.2.10 or newer.&lt;/strong&gt; Older versions refuse a &lt;code&gt;blog.toml&lt;/code&gt; that has it, so update every machine that builds the blog first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If you used the old, undocumented &lt;code&gt;op3 = true&lt;/code&gt;:&lt;/strong&gt; it now means the same thing, and your episode addresses gain &lt;code&gt;,pg=&amp;lt;guid&amp;gt;&lt;/code&gt;. Podcast apps keep track of episodes by guid, so nothing gets downloaded twice.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Grab it
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;System&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Arch / Omarchy&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sudo pacman -U folderblog-bin-0.2.10-1-x86_64.pkg.tar.zst&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Debian / Ubuntu&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sudo apt install ./folderblog_0.2.10-1_amd64.deb&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fedora / RHEL / openSUSE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sudo dnf install ./folderblog-0.2.10-1.x86_64.rpm&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;autonomix-cli&lt;/td&gt;
&lt;td&gt;&lt;code&gt;autonomix-cli add https://github.com/ninepointlabs/folderblog&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Already installed? Install the new package, then run &lt;code&gt;systemctl --user restart folderblog&lt;/code&gt;. The packages and a plain tarball are on the &lt;a href="https://github.com/ninepointlabs/folderblog/releases/tag/v0.2.10" rel="noopener noreferrer"&gt;v0.2.10 release&lt;/a&gt;, and the source is &lt;a href="https://github.com/ninepointlabs/folderblog" rel="noopener noreferrer"&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://blog.ninepointlabs.com/2026/10/folderblog-0-2-10/" rel="noopener noreferrer"&gt;blog.ninepointlabs.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>blogging</category>
      <category>podcast</category>
      <category>rust</category>
      <category>opensource</category>
    </item>
    <item>
      <title>folderblog 0.2.9: Fixes from a full QA pass, and podcast addresses that stay put</title>
      <dc:creator>Tim Apple</dc:creator>
      <pubDate>Sun, 25 Oct 2026 01:29:24 +0000</pubDate>
      <link>https://dev.to/ninepointlabs/folderblog-029-fixes-from-a-full-qa-pass-and-podcast-addresses-that-stay-put-jke</link>
      <guid>https://dev.to/ninepointlabs/folderblog-029-fixes-from-a-full-qa-pass-and-podcast-addresses-that-stay-put-jke</guid>
      <description>&lt;p&gt;&lt;a href="https://folderblog.ninepointlabs.com" rel="noopener noreferrer"&gt;folderblog&lt;/a&gt; 0.2.9 is a fix release that came out of a full QA pass over &lt;a href="https://blog.ninepointlabs.com/2026/10/folderblog-0-2-8/" rel="noopener noreferrer"&gt;this morning’s 0.2.8&lt;/a&gt;. That pass followed the published instructions step by step, the way a new user would, and the rough edges it found are fixed here. Most of it is podcast polish, plus a change that keeps your post addresses the same when you clone or copy a blog.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read this before you update
&lt;/h2&gt;

&lt;p&gt;Three changes are worth knowing about first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The podcast feed’s own title changes.&lt;/strong&gt; If your show has the same name as your blog, the feed itself is now titled “&lt;em&gt;Your Blog&lt;/em&gt; (Podcast)”, not just the link to it. Podcast apps will pick up the new name. To keep the old one, give the show its own name in &lt;code&gt;podcast/index.md&lt;/code&gt; or with &lt;code&gt;[podcast] title&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;There’s a new file to commit: &lt;code&gt;dates.toml&lt;/code&gt;.&lt;/strong&gt; A post without a date of its own gets its address from the day folderblog first saw it. That date used to live only in the ignored &lt;code&gt;.blog/&lt;/code&gt; folder, so a fresh clone could give the post a different address. It’s now kept in &lt;code&gt;dates.toml&lt;/code&gt; in the blog folder. After you update, the service writes it from the dates already recorded, so no address changes. If your blog is in git, commit &lt;code&gt;dates.toml&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A new &lt;code&gt;[podcast.storage] prefix&lt;/code&gt; setting needs 0.2.9 or newer.&lt;/strong&gt; It pins the folder your episode files use on the audio host, so renaming the blog folder no longer changes every episode’s address. If you leave it out, nothing changes. &lt;code&gt;podcast setup&lt;/code&gt; now writes it, and &lt;code&gt;folderblog check&lt;/code&gt; suggests the exact line for existing shows. Older versions refuse a &lt;code&gt;blog.toml&lt;/code&gt; that has it, so update every machine that builds the blog first.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Podcasts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Publishing an episode keeps your notes.&lt;/strong&gt; &lt;code&gt;folderblog podcast publish --episode&lt;/code&gt; (and the MCP &lt;code&gt;publish_episode&lt;/code&gt; tool) now changes only the &lt;code&gt;draft:&lt;/code&gt; line. Before, it rewrote the whole front matter and dropped the comments from the template.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;check&lt;/code&gt; looks at draft episodes too.&lt;/strong&gt; Problems like a missing &lt;code&gt;guid&lt;/code&gt; show up as warnings, and the suggested guid is the same every time you run it. &lt;code&gt;folderblog podcast&lt;/code&gt; now counts episodes left out because of a problem, and a draft no longer needs audio hosting set up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No more doubled page title.&lt;/strong&gt; The default podcast page no longer reads “Blog · Blog”.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;S3-compatible storage is documented.&lt;/strong&gt; With &lt;code&gt;type = "s3"&lt;/code&gt; and no key, folderblog now tells you how to give it one (&lt;code&gt;FOLDERBLOG_STORAGE_KEY_ID&lt;/code&gt; and &lt;code&gt;FOLDERBLOG_STORAGE_SECRET&lt;/code&gt;, or a key file) instead of pointing you at the R2-only &lt;code&gt;podcast setup&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Clearer messages everywhere else
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Honest retry messages.&lt;/strong&gt; A held publish only says it’ll be retried when the background service is actually running. Otherwise it tells you what to run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Machines without a systemd user session.&lt;/strong&gt; &lt;code&gt;folderblog status&lt;/code&gt; says so plainly, and a failed &lt;code&gt;install-service&lt;/code&gt; removes the unit file it wrote (or puts the old one back) and tells you what to do instead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;check&lt;/code&gt; names pictures nothing shows.&lt;/strong&gt; Pictures in &lt;code&gt;posts/&lt;/code&gt; and &lt;code&gt;pages/&lt;/code&gt; that no page uses are still published, and now you’ll know which ones they are. It also notes that a robots.txt under a &lt;code&gt;base_url&lt;/code&gt; path isn’t read by search engines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs that don’t break.&lt;/strong&gt; Install links are pinned to the release, building from source uses &lt;code&gt;--tag&lt;/code&gt;, and there’s new coverage of template route headers, &lt;code&gt;base_url&lt;/code&gt; for other hosts, machines without a systemd user session, the preview address and &lt;code&gt;folderblog data&lt;/code&gt; examples.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Grab it
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;System&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Arch / Omarchy&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sudo pacman -U folderblog-bin-0.2.9-1-x86_64.pkg.tar.zst&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Debian / Ubuntu&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sudo apt install ./folderblog_0.2.9-1_amd64.deb&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fedora / RHEL / openSUSE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sudo dnf install ./folderblog-0.2.9-1.x86_64.rpm&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;autonomix-cli&lt;/td&gt;
&lt;td&gt;&lt;code&gt;autonomix-cli add https://github.com/ninepointlabs/folderblog&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Already installed? Install the new package, then run &lt;code&gt;systemctl --user restart folderblog&lt;/code&gt;, and commit the new &lt;code&gt;dates.toml&lt;/code&gt; if your blog is in git. The packages and a plain tarball are on the &lt;a href="https://github.com/ninepointlabs/folderblog/releases/tag/v0.2.9" rel="noopener noreferrer"&gt;v0.2.9 release&lt;/a&gt;, and the source is &lt;a href="https://github.com/ninepointlabs/folderblog" rel="noopener noreferrer"&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://blog.ninepointlabs.com/2026/10/folderblog-0-2-9/" rel="noopener noreferrer"&gt;blog.ninepointlabs.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>blogging</category>
      <category>podcast</category>
      <category>rust</category>
      <category>opensource</category>
    </item>
    <item>
      <title>folderblog 0.2.8: Podcast setup that works on real R2, and a Subscribe box</title>
      <dc:creator>Tim Apple</dc:creator>
      <pubDate>Sat, 24 Oct 2026 15:27:45 +0000</pubDate>
      <link>https://dev.to/ninepointlabs/folderblog-028-podcast-setup-that-works-on-real-r2-and-a-subscribe-box-9jp</link>
      <guid>https://dev.to/ninepointlabs/folderblog-028-podcast-setup-that-works-on-real-r2-and-a-subscribe-box-9jp</guid>
      <description>&lt;p&gt;&lt;a href="https://folderblog.ninepointlabs.com" rel="noopener noreferrer"&gt;folderblog&lt;/a&gt; 0.2.8 is a small fix release on top of &lt;a href="https://blog.ninepointlabs.com/2026/10/folderblog-0-2-7/" rel="noopener noreferrer"&gt;yesterday’s 0.2.7&lt;/a&gt;, the one that turned a blog folder into a podcast. If you tried &lt;code&gt;folderblog podcast setup&lt;/code&gt; and it stopped at the “find it again” step, this is the release you want.&lt;/p&gt;

&lt;h2&gt;
  
  
  Podcast setup works with real Cloudflare R2
&lt;/h2&gt;

&lt;p&gt;After setup uploads a small test file, it checks that the file can be found again. On real Cloudflare R2 that check failed even though the upload had worked. R2 compresses some files on the way out, and when it does, its reply leaves out the file size, so folderblog read the missing size as a missing file.&lt;/p&gt;

&lt;p&gt;folderblog now asks R2 for uncompressed replies, so the size comes back. If a reply still has no size, any successful answer counts as “the file is there”, and the size is only compared when R2 sends one. The same fix applies when a deploy checks whether an episode’s audio is already uploaded, so a working upload isn’t treated as missing. The tests now use a fake R2 that compresses the way the real one does, which is how this slipped through before.&lt;/p&gt;

&lt;p&gt;This is the fix that got the first real show on folderblog running. &lt;a href="https://myazerothlife.com/podcast/" rel="noopener noreferrer"&gt;My Azeroth Life&lt;/a&gt; was set up with it, and &lt;a href="https://blog.ninepointlabs.com/2026/10/how-my-azeroth-life-is-made/" rel="noopener noreferrer"&gt;the story of how that show is made&lt;/a&gt; is here on the blog.&lt;/p&gt;

&lt;h2&gt;
  
  
  Easier to subscribe
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The podcast feed has its own title.&lt;/strong&gt; When the show and the blog share a name, the podcast feed is now called “&lt;em&gt;Your Blog&lt;/em&gt; (Podcast)”, so feed readers and browsers can tell it apart from the blog feed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A Subscribe box on the show page.&lt;/strong&gt; The podcast page that &lt;code&gt;folderblog podcast on&lt;/code&gt; sets up now has a Subscribe section near the top, with the full feed address ready to select and paste into a podcast app. It’s plain CSS that uses your theme’s colors, with no JavaScript.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Grab it
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;System&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Arch / Omarchy&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sudo pacman -U folderblog-bin-0.2.8-1-x86_64.pkg.tar.zst&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Debian / Ubuntu&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sudo apt install ./folderblog_0.2.8-1_amd64.deb&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fedora / RHEL / openSUSE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sudo dnf install ./folderblog-0.2.8-1.x86_64.rpm&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;autonomix-cli&lt;/td&gt;
&lt;td&gt;&lt;code&gt;autonomix-cli add https://github.com/ninepointlabs/folderblog&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Already installed? Install the new package, then run &lt;code&gt;systemctl --user restart folderblog&lt;/code&gt;. The packages and a plain tarball are on the &lt;a href="https://github.com/ninepointlabs/folderblog/releases/tag/v0.2.8" rel="noopener noreferrer"&gt;v0.2.8 release&lt;/a&gt;, and the source is &lt;a href="https://github.com/ninepointlabs/folderblog" rel="noopener noreferrer"&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://blog.ninepointlabs.com/2026/10/folderblog-0-2-8/" rel="noopener noreferrer"&gt;blog.ninepointlabs.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>blogging</category>
      <category>podcast</category>
      <category>rust</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
