<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>The Word from Ninepoint Labs</title>
<link>https://blog.ninepointlabs.com/</link>
<description>The Word from Ninepoint Labs</description>
<language>en</language>
<atom:link href="https://blog.ninepointlabs.com/feed.xml" rel="self" type="application/rss+xml"/>
<generator>folderblog 0.2.0</generator>
<lastBuildDate>Tue, 13 Oct 2026 00:00:00 -0500</lastBuildDate>
<item>
<title>Rune 0.8: From ODF experiment to a word processor you can install</title>
<link>https://blog.ninepointlabs.com/2026/10/rune-0-8/</link>
<guid isPermaLink="true">https://blog.ninepointlabs.com/2026/10/rune-0-8/</guid>
<pubDate>Tue, 13 Oct 2026 00:00:00 -0500</pubDate>
<dc:creator>Tim</dc:creator>
<category>Rune</category>
<category>ODF</category>
<category>Word Processing</category>
<category>Qt</category>
<category>AI</category>
<category>Writing</category>
<description><![CDATA[<p>Yesterday’s <a href="https://github.com/ninepointlabs/rune">Rune</a> post was about a principle: ODF is home, DOCX is a guest. Since then Rune has gone from 0.2 to 0.8.4 in about two days, and it has stopped being an idea about formats and started being an app you can install and write a book in.</p>
]]></description>
<content:encoded><![CDATA[<p>Yesterday’s <a href="https://github.com/ninepointlabs/rune">Rune</a> post was about a principle: ODF is home, DOCX is a guest. Since then Rune has gone from 0.2 to 0.8.4 in about two days, and it has stopped being an idea about formats and started being an app you can install and write a book in.</p>
<h2 id="install-it-like-a-real-app">Install it like a real app</h2>
<p>Every <a href="https://github.com/ninepointlabs/rune/releases/latest">GitHub release</a> now ships packages for Arch/Omarchy, Debian 13 and Fedora 42, with a desktop entry. The easiest path keeps it updated for you:</p>
<pre class="highlight"><code class="language-sh"><span class="hl-source hl-shell hl-bash"><span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">autonomix-cli</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> add https://github.com/ninepointlabs/rune</span>
</span></code></pre>
<h2 id="the-everyday-editor-filled-in">The everyday editor filled in</h2>
<ul>
<li>A <strong>File menu</strong> with save-button states and autosave.</li>
<li><strong>Font and text-color pickers</strong>, and a toolbar that fits any window: Table and alignment menus, with a <code>⋯</code> overflow for the rest.</li>
<li>A <strong>Table menu</strong>: insert rows and columns, delete a table.</li>
<li>A <strong>command palette</strong> on <code>Ctrl+K</code>.</li>
<li><strong>Pages and margins</strong>: a real page view, Page setup, and paper size picked from your locale.</li>
<li><strong>Headers and footers</strong> edited in place, with page number and page count fields that round-trip through both ODF and .docx.</li>
</ul>
<h2 id="rune-writes-its-own-odf-now">Rune writes its own ODF now</h2>
<p>Rune used to lean on Qt’s document writer, and it kept losing things: headings saved as bold text, nested tables lost content, a table after a list could vanish. Rune now writes the whole <code>.odt</code> itself: real Heading 1–6 styles, links, lists that keep their numbering across interruptions, and tables with widths, borders, merged cells and nesting. If ODF is the home format, Rune has to be a good citizen of it, and now it is one.</p>
<h2 id="tools-for-people-writing-long-things">Tools for people writing long things</h2>
<p>0.8.3 added author tooling:</p>
<ul>
<li>Headings from the toolbar (<code>Ctrl+Alt+0</code>–<code>3</code>) and an <strong>outline sidebar</strong> with chapters, scenes and word counts. Drag a section to move it in one undo step.</li>
<li><strong>Story notes</strong> saved inside the file.</li>
<li><strong>Sources</strong> from a form, CSL-JSON or BibTeX, with <strong>citations</strong> (<code>Ctrl+Shift+C</code>) in APA 7, MLA 9, Chicago author-date or IEEE, and a bibliography that keeps up with every edit.</li>
</ul>
<p>Citations survive a trip through .docx. Word and LibreOffice see the text, and Rune finds the citations again when the file comes back.</p>
<h2 id="ai-edits-that-dont-wreck-your-paragraphs">AI edits that don’t wreck your paragraphs</h2>
<p>The AI can read your notes and sources, cite with <code>[@key]</code>, and add sources, which are marked unreviewed until you check them. 0.8.4 fixed a nasty one: models copied 80-column line wraps into their edits, and every wrap became a paragraph break. The context now goes out one paragraph per line, and slightly garbled quotes still match. The same edit came out clean in 15 of 15 live ChatGPT runs, where every run checked before had broken paragraphs.</p>
<h2 id="see-it-first">See it first</h2>
<p>The <a href="https://rune.ninepointlabs.com">site</a> now has screenshots, a narrated 1:47 demo recorded from the real app, and a seven-page how-to guide covering formatting, pages, the AI, writing a book, and citations. Under all of it are 487 automated checks.</p>
<p>ODF by default still holds. The difference now is that Rune gives you a real reason to choose it.</p>
]]></content:encoded>
</item>
<item>
<title>Speakeasy 0.3: Your bots can start the tasks now</title>
<link>https://blog.ninepointlabs.com/2026/10/speakeasy-mcp/</link>
<guid isPermaLink="true">https://blog.ninepointlabs.com/2026/10/speakeasy-mcp/</guid>
<pubDate>Tue, 13 Oct 2026 00:00:00 -0500</pubDate>
<dc:creator>Tim</dc:creator>
<category>Speakeasy</category>
<category>MCP</category>
<category>Omarchy</category>
<category>AI</category>
<category>agents</category>
<category>Claude Code</category>
<category>Grok Bot</category>
<description><![CDATA[<p><a href="https://github.com/ninepointlabs/speakeasy">Speakeasy</a> already kept coding agents in named, hidden terminals so you could see what was running without drowning in windows. As of 0.3, other programs can hand it work the same way you do from the bar.</p>
]]></description>
<content:encoded><![CDATA[<p><a href="https://github.com/ninepointlabs/speakeasy">Speakeasy</a> already kept coding agents in named, hidden terminals so you could see what was running without drowning in windows. As of 0.3, other programs can hand it work the same way you do from the bar.</p>
<h2 id="an-mcp-server-on-stdio">An MCP server on stdio</h2>
<p><code>speakeasy mcp</code> speaks the Model Context Protocol over standard input and output. No network port, no daemon to babysit. Point Claude Code, Grok Bot, Hermes, or any other MCP client at the binary and it gets four tools:</p>
<ul>
<li><code>list_agents</code> — which agents are installed and visible, with models and effort levels</li>
<li><code>find_repo</code> — where a GitHub repo is checked out on this machine</li>
<li><code>create_task</code> — start a task with title, description, agent, and optional model, effort, and repo or folder</li>
<li><code>list_tasks</code> — what is already running, so a bot does not start a duplicate</li>
</ul>
<p>A bot watching your repos can pick Claude or Codex, write the brief, and park the job in the right local checkout. It shows up in your Speakeasy list like anything you started yourself. The client’s name is stored as the task’s <code>origin</code>, and Speakeasy leaves your new-task picker defaults alone.</p>
<h2 id="approvals-stay-yours">Approvals stay yours</h2>
<p>The MCP path deliberately cannot pass extra agent arguments, so a bot cannot flip permission prompts off. It also cannot peek at a task’s screen, type into it, or stop it. The agent still asks you before risky actions; you still answer.</p>
<p><code>find_repo</code> strips credentials out of remote URLs before it reports them. Add the MCP server only to clients you trust, same as you would any tool that can start processes in your project folders.</p>
<h2 id="titles-and-prompts-off-the-process-list">Titles and prompts off the process list</h2>
<p>0.3.1 closes a quieter hole. The Omarchy panel used to put the task title and description on the <code>speakeasy new</code> command line, where any other user on the machine could read them with <code>ps</code>. They now go over stdin as one line of JSON (<code>--stdin-json</code>). The CLI already avoided stuffing prompts into argv for normal use; the panel catches up.</p>
<h2 id="try-it">Try it</h2>
<pre class="highlight"><code class="language-bash"><span class="hl-source hl-shell hl-bash"><span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">speakeasy</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> mcp</span>
<span class="hl-comment hl-line hl-number-sign hl-shell"><span class="hl-punctuation hl-definition hl-comment hl-begin hl-shell">#</span></span><span class="hl-comment hl-line hl-number-sign hl-shell"> or wire it into Claude Code:</span><span class="hl-comment hl-line hl-number-sign hl-shell">
</span><span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">claude</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> mcp add speakeasy<span class="hl-keyword hl-operator hl-end-of-options hl-shell"> --</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> <span class="hl-meta hl-group hl-expansion hl-tilde"><span class="hl-variable hl-language hl-tilde hl-shell">~</span></span>/.local/bin/speakeasy mcp</span>
</span></code></pre>
<p>Upgrade with your usual Omarchy plugin path, or pull <a href="https://github.com/ninepointlabs/speakeasy">ninepointlabs/speakeasy</a> and run <code>./install.sh</code>. If your workflow is “bot finds the problem, I approve the fix,” Speakeasy is now the handoff.</p>
]]></content:encoded>
</item>
<item>
<title>Kestrel: Post to X from Your Terminal (or Let Your AI Do It)</title>
<link>https://blog.ninepointlabs.com/2026/10/kestrel/</link>
<guid isPermaLink="true">https://blog.ninepointlabs.com/2026/10/kestrel/</guid>
<pubDate>Mon, 12 Oct 2026 00:00:00 -0500</pubDate>
<dc:creator>Tim</dc:creator>
<category>Kestrel</category>
<category>X</category>
<category>Twitter</category>
<category>CLI</category>
<category>MCP</category>
<category>Rust</category>
<category>AI</category>
<description><![CDATA[<p>If you have ever wanted to fire off a tweet without leaving your terminal, or better yet, hand the keys to an AI agent and trust it not to burn through your X API budget, <a href="https://github.com/ninepointlabs/kestrel">Kestrel</a> has you covered.</p>
]]></description>
<content:encoded><![CDATA[<p>If you have ever wanted to fire off a tweet without leaving your terminal, or better yet, hand the keys to an AI agent and trust it not to burn through your X API budget, <a href="https://github.com/ninepointlabs/kestrel">Kestrel</a> has you covered.</p>
<p>Kestrel is a Rust CLI that posts to X (Twitter) and doubles as an MCP server so AI agents can post through it. The killer feature: a hard daily post limit, shared between the CLI and the MCP server. Your agent might be chatty, but Kestrel knows when to say “that’s enough for today.”</p>
<h2 id="two-modes-one-binary">Two modes, one binary</h2>
<p>From the terminal, it is dead simple:</p>
<pre class="highlight"><code class="language-sh"><span class="hl-source hl-shell hl-bash"><span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">kestrel</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> post <span class="hl-string hl-quoted hl-double hl-shell"><span class="hl-punctuation hl-definition hl-string hl-begin hl-shell">&quot;</span>Hello world<span class="hl-punctuation hl-definition hl-string hl-end hl-shell">&quot;</span></span></span>
<span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">kestrel</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> post <span class="hl-string hl-quoted hl-double hl-shell"><span class="hl-punctuation hl-definition hl-string hl-begin hl-shell">&quot;</span>check this out<span class="hl-punctuation hl-definition hl-string hl-end hl-shell">&quot;</span></span><span class="hl-variable hl-parameter hl-option hl-shell"><span class="hl-punctuation hl-definition hl-parameter hl-shell"> --</span>image</span> ./photo.png</span>
<span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">kestrel</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> status         <span class="hl-comment hl-line hl-number-sign hl-shell"><span class="hl-punctuation hl-definition hl-comment hl-begin hl-shell">#</span></span><span class="hl-comment hl-line hl-number-sign hl-shell"> Posts today: 3/50 (6%)</span><span class="hl-comment hl-line hl-number-sign hl-shell">
</span></span></span></code></pre>
<p>Fire up the MCP server with <code>kestrel serve</code> and suddenly Claude Code, Claude Desktop, or Hermes can post on your behalf with exactly the same guardrails. No separate config, no backdoor. If the daily limit is hit, the MCP tool returns an error result instead of posting. Your credit card stays safe.</p>
<h2 id="the-economics-of-x-posting-in-2026">The economics of X posting in 2026</h2>
<p>Here is the part that makes Kestrel genuinely useful instead of just fun. Since February 2026, X’s API is pay-per-use with no free tier. Every post costs real money:</p>
<ul>
<li>Plain text tweet: $0.015</li>
<li>Tweet with a URL: <strong>$0.200</strong> (yes, 13x more)</li>
<li>Summoned reply: $0.010</li>
</ul>
<p>A link surcharge that steep means one careless agent posting URLs could run up a bill fast. Kestrel’s daily limit is your safety net. At 50 posts per day, plain text costs $22.50/month. With links mixed in at 30%, that jumps to $90/month. Kestrel makes sure you know exactly where you stand.</p>
<h2 id="built-to-be-boring-in-the-best-way">Built to be boring (in the best way)</h2>
<p>The config lives in <code>~/.config/kestrel/config.toml</code> with <code>0600</code> permissions. State is tracked in a tiny JSON file that resets at midnight local time. One binary, one config file, one state file. No daemon, no database, no cloud service. It works the same whether you type <code>kestrel post</code> or your AI agent does.</p>
<p>The MCP server exposes exactly two tools: <code>kestrel_post</code> and <code>kestrel_status</code>. That is it. No read access, no timeline scraping, no DMs. Kestrel is built for one job and it does not overreach.</p>
<h2 id="worth-a-look-if">Worth a look if</h2>
<p>You post from the terminal, you run AI agents that need controlled X access, or you just appreciate a well-scoped Rust tool that respects your wallet. The <a href="https://github.com/ninepointlabs/kestrel">repo</a> has a clear README with pricing tables, troubleshooting guides for every HTTP error code, and a one-command install via <code>cargo install --path .</code>.</p>
]]></content:encoded>
</item>
<item>
<title>Why Rune Treats DOCX as a Guest, Not a Host</title>
<link>https://blog.ninepointlabs.com/2026/10/rune-odf-first/</link>
<guid isPermaLink="true">https://blog.ninepointlabs.com/2026/10/rune-odf-first/</guid>
<pubDate>Mon, 12 Oct 2026 00:00:00 -0500</pubDate>
<dc:creator>Tim</dc:creator>
<category>Rune</category>
<category>ODF</category>
<category>DOCX</category>
<category>LibreOffice</category>
<category>Word Processing</category>
<description><![CDATA[<p>I’ve been building <a href="https://rune.ninepointlabs.com">Rune</a>, our word processor, and I just made a decision that I expect a few people to push back on: DOCX is not a first-class citizen. ODF is the native format. DOCX is import and export only.</p>
]]></description>
<content:encoded><![CDATA[<p>I’ve been building <a href="https://rune.ninepointlabs.com">Rune</a>, our word processor, and I just made a decision that I expect a few people to push back on: DOCX is not a first-class citizen. ODF is the native format. DOCX is import and export only.</p>
<p>Here’s the thing I had to talk myself out of first.</p>
<p>My first instinct was to make DOCX a first-class format alongside ODF, because it’s convenient. DOCX is what the business world runs on, it’s what shows up in every email attachment, and treating it as a second-tier citizen felt like making life harder for anyone who has to interoperate with the rest of the planet. That instinct was really just me optimizing for my own convenience, not for what Rune should actually be.</p>
<p>Then I looked honestly at how often I actually create documents that need to be DOCX. Rarely. Almost never, really. Most of what I write doesn’t care what the underlying format is, it cares about being readable, editable, and not locked to one vendor’s whims. The cases where DOCX truly matters are the cases where I’m handing something to someone else’s pipeline, and for that, export now and again is plenty.</p>
<p>So that settled it for me: if ODF is ever going to get real traction, and if we actually want to see the world move away from a single-vendor format as the default assumption, somebody has to stop treating DOCX as equal. Every tool that makes DOCX the comfortable default, even a little, is one more vote for the status quo. Rune is my vote the other way. ODF is home. DOCX is a well-supported guest, not a roommate.</p>
<p>The “well-supported” part matters, because I’m not interested in making DOCX support bad out of principle. Nobody wins if opening a .docx in Rune mangles someone’s formatting. So on the backend, DOCX import and export runs through the LibreOffice engine. LibreOffice has put in literally decades of work getting that conversion right, through every quirky OOXML edge case Microsoft has shipped over the years. There’s no reason for me to reinvent that wheel badly when I can lean on work that’s already excellent. Rune gets to stay focused on being a genuinely good ODF-native editor, and the DOCX bridge gets to be solid because someone else already paid the tuition for that problem.</p>
<p>That’s the shape of it: ODF by default, DOCX by door, LibreOffice doing the heavy lifting at the threshold. If you want to see where Rune is headed, <a href="https://rune.ninepointlabs.com">rune.ninepointlabs.com</a> has more.</p>
]]></content:encoded>
</item>
<item>
<title>Autonomix Now Plugs Straight Into the Omarchy Updater</title>
<link>https://blog.ninepointlabs.com/2026/10/autonomix-omarchy-updater/</link>
<guid isPermaLink="true">https://blog.ninepointlabs.com/2026/10/autonomix-omarchy-updater/</guid>
<pubDate>Sun, 11 Oct 2026 00:00:00 -0500</pubDate>
<dc:creator>Tim</dc:creator>
<category>AutonomixCLI</category>
<category>Omarchy</category>
<category>Linux</category>
<category>CLI</category>
<category>Go</category>
<description><![CDATA[<p>Remember <a href="https://github.com/ninepointlabs/autonomix-cli">Autonomix CLI</a>, the terminal tool that tracks your GitHub Releases apps? It had one nagging flaw: it wouldn’t update anything unless you remembered to open it and ask. Which, if you’re like most people, is never.</p>
]]></description>
<content:encoded><![CDATA[<p>Remember <a href="https://github.com/ninepointlabs/autonomix-cli">Autonomix CLI</a>, the terminal tool that tracks your GitHub Releases apps? It had one nagging flaw: it wouldn’t update anything unless you remembered to open it and ask. Which, if you’re like most people, is never.</p>
<p>That’s fixed now. Autonomix just picked up a real <code>check</code> and <code>update</code> command, and on Omarchy it hooks straight into the system updater, so your GitHub-sourced apps get refreshed in the same breath as everything else.</p>
<h2 id="whats-new">What’s new</h2>
<ul>
<li><strong><code>autonomix-cli check</code></strong> lists every tracked app with an update available, no TUI required.</li>
<li><strong><code>autonomix-cli update [-y]</code></strong> installs those updates non-interactively, the <code>-y</code> flag skips the confirmation prompt entirely.</li>
<li>It only touches apps installed through your actual package manager (dpkg, rpm, pacman). Anything living as a loose binary on <code>PATH</code>, or managed through Flatpak/Snap, gets reported and left alone, because blindly overwriting those is how you break things.</li>
<li><code>--version</code> and <code>--help</code> now behave like every other CLI instead of falling through to the TUI.</li>
<li>Set <code>GITHUB_TOKEN</code> (or <code>GH_TOKEN</code>) if you’re tracking enough repos to hit GitHub’s 60-requests-an-hour API limit; it bumps you to 5,000.</li>
</ul>
<h2 id="the-omarchy-part">The Omarchy part</h2>
<p>This is the fun bit. Drop the included hook into Omarchy’s update pipeline and Autonomix updates ride along for free every time you run <code>omarchy update</code>:</p>
<pre class="highlight"><code class="language-bash"><span class="hl-source hl-shell hl-bash"><span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">install</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"><span class="hl-variable hl-parameter hl-option hl-shell"><span class="hl-punctuation hl-definition hl-parameter hl-shell"> -</span>m755</span> contrib/omarchy/autonomix.hook <span class="hl-meta hl-group hl-expansion hl-tilde"><span class="hl-variable hl-language hl-tilde hl-shell">~</span></span>/.config/omarchy/hooks/post-update.d/autonomix.hook</span>
</span></code></pre>
<p>That’s it. One <code>omarchy update</code> now refreshes your system packages <em>and</em> whatever you’re tracking through Autonomix, no separate step to remember.</p>
<p><strong><a href="https://github.com/ninepointlabs/autonomix-cli">Autonomix CLI on GitHub →</a></strong></p>
<p>Grab the latest release, or if you’re already on it, <code>go build</code> and you’re there. If you haven’t tried Autonomix at all yet, the <a href="https://blog.ninepointlabs.com/2026/10/autonomix-cli/">first post</a> has the full rundown.</p>
]]></content:encoded>
</item>
<item>
<title>Jubako: Microsoft Access, Without the Hard Parts</title>
<link>https://blog.ninepointlabs.com/2026/10/jubako/</link>
<guid isPermaLink="true">https://blog.ninepointlabs.com/2026/10/jubako/</guid>
<pubDate>Sun, 11 Oct 2026 00:00:00 -0500</pubDate>
<dc:creator>Tim</dc:creator>
<category>Jubako</category>
<category>Omarchy</category>
<category>Linux</category>
<category>Database</category>
<category>CLI</category>
<category>MCP</category>
<category>agents</category>
<description><![CDATA[<p>You know that moment when you open a folder and find <code>budget_FINAL_v3.xlsx</code>, <code>budget_FINAL_v3 (1).csv</code>, and <code>budget REAL FINAL.xlsx</code> all staring back at you? Spreadsheets are great until they aren’t – until you need to ask “which customers haven’t paid yet” and you’re doing mental gymnastics with filters and color-coded cells.</p>
]]></description>
<content:encoded><![CDATA[<p>You know that moment when you open a folder and find <code>budget_FINAL_v3.xlsx</code>, <code>budget_FINAL_v3 (1).csv</code>, and <code>budget REAL FINAL.xlsx</code> all staring back at you? Spreadsheets are great until they aren’t – until you need to ask “which customers haven’t paid yet” and you’re doing mental gymnastics with filters and color-coded cells.</p>
<p><strong><a href="https://github.com/ninepointlabs/jubako">Jubako on GitHub</a></strong> | <strong><a href="https://jubako.ninepointlabs.com">jubako.ninepointlabs.com</a></strong></p>
<p>Jubako (pronounced <em>joo-bah-koh</em>, named after the stacked Japanese lunch boxes) is a simple desktop database for Omarchy Linux. One file, several tables, no SQL required. Think of it as the spirit of old-school Microsoft Access, reimagined for people who would rather get things done than learn a query language.</p>
<p><img src="https://raw.githubusercontent.com/ninepointlabs/jubako/main/docs/screenshots/grid.webp" alt="The orders table of a demo bike-shop database in the Jubako grid"></p>
<h2 id="drop-a-spreadsheet-get-a-database">Drop a Spreadsheet, Get a Database</h2>
<p>The killer feature is the import. Drag a CSV or Excel file onto the window and Jubako figures out what each column is – words, whole numbers, decimals, dates, yes/no values. It shows you its best guesses before writing anything, so you can correct a column that got tagged as “words” when it’s really a date column. A multi-sheet workbook becomes one table per sheet. No ceremony, no setup.</p>
<p>Once your data is in, you can browse it as a grid, type row-by-row in a form, filter with rules like “Status is not Delivered AND Total over 100,” and save those filters as named views. Need to print? The report designer gives you a live preview, groups rows with subtotals, and exports to PDF. Your spreadsheet just grew up.</p>
<p><img src="https://raw.githubusercontent.com/ninepointlabs/jubako/main/docs/screenshots/form.webp" alt="One order in an arranged form"></p>
<h2 id="your-ai-agent-can-drive-it-too">Your AI Agent Can Drive It Too</h2>
<p>Jubako ships with an MCP server, which means Claude Code (or any MCP-capable agent) can do everything the app can do. “Take this spreadsheet and make me a database” works as a natural-language command. The tools cover the full surface: create databases, import spreadsheets, list and filter rows, add and update records, design reports, export to CSV or Excel or PDF. Twenty-seven tools in total, all over stdio.</p>
<p>Safety is taken seriously: file paths are checked against approved folders, spreadsheet formulas are never executed, server passwords are never saved, and destructive operations ask first.</p>
<p><img src="https://raw.githubusercontent.com/ninepointlabs/jubako/main/docs/screenshots/report.webp" alt="The report designer: bike sales grouped by rep, with a total per rep"></p>
<h2 id="under-the-hood">Under the Hood</h2>
<p>Jubako is a Qt Quick desktop app with a Python core. By default your database is a single SQLite file (<code>.jubadb</code>) in your Documents folder – copy it, back it up, email it. If you already run PostgreSQL or MySQL, you can point Jubako at that instead. The app follows your Omarchy theme, light or dark, and changes with it when you switch.</p>
<p><img src="https://raw.githubusercontent.com/ninepointlabs/jubako/main/docs/screenshots/light.webp" alt="The grid in a light Omarchy theme"></p>
<p>Installation is one command on Arch/Omarchy, Debian, or Fedora – packages are on the <a href="https://github.com/ninepointlabs/jubako/releases">releases page</a>. Or clone the repo and run from source. It’s MIT-licensed and actively developed, with a growing test suite that covers type guessing, path safety, CSV and Excel import/export, reports, and the MCP server.</p>
<p>If your spreadsheets have been quietly running your life, Jubako is a clean upgrade. Same data, less chaos, and a lunch box metaphor you didn’t know you needed.</p>
<p><a href="https://github.com/ninepointlabs/jubako">Jubako on GitHub</a></p>
]]></content:encoded>
</item>
<item>
<title>Idea: a CLI for the “wait, I had something” moments</title>
<link>https://blog.ninepointlabs.com/2026/10/ideas/</link>
<guid isPermaLink="true">https://blog.ninepointlabs.com/2026/10/ideas/</guid>
<pubDate>Sat, 10 Oct 2026 00:00:00 -0500</pubDate>
<dc:creator>Tim</dc:creator>
<category>Ideas</category>
<category>CLI</category>
<category>Linux</category>
<category>macOS</category>
<category>Go</category>
<description><![CDATA[<p>You know the feeling. You’re three levels deep in a terminal, wiring up some
pipeline, and an idea pops into your head: <em>“I should really automate that
database migration.”</em> Or maybe <em>“What if the cron job just emailed the digest
instead?”</em> By the time you finish what you’re doing, the thought is gone,
replaced by whatever error message you’re now staring at.</p>
]]></description>
<content:encoded><![CDATA[<p>You know the feeling. You’re three levels deep in a terminal, wiring up some
pipeline, and an idea pops into your head: <em>“I should really automate that
database migration.”</em> Or maybe <em>“What if the cron job just emailed the digest
instead?”</em> By the time you finish what you’re doing, the thought is gone,
replaced by whatever error message you’re now staring at.</p>
<p><strong><a href="https://github.com/ninepointlabs/ideas">Ideas on GitHub</a></strong> is the
smallest possible answer to that problem. It’s a single Go binary that appends
numbered ideas to a markdown file. No database, no daemon, no web UI. Just
<code>idea "your thought here"</code> and you’re back to work.</p>
<h2 id="how-it-works">How it works</h2>
<pre class="highlight"><code class="language-sh"><span class="hl-source hl-shell hl-bash"><span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">idea</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> <span class="hl-string hl-quoted hl-double hl-shell"><span class="hl-punctuation hl-definition hl-string hl-begin hl-shell">&quot;</span>Add retry logic to the API client<span class="hl-punctuation hl-definition hl-string hl-end hl-shell">&quot;</span></span></span>
<span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">idea</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> <span class="hl-string hl-quoted hl-double hl-shell"><span class="hl-punctuation hl-definition hl-string hl-begin hl-shell">&quot;</span>Switch the blog to folderblog instead of Hugo<span class="hl-punctuation hl-definition hl-string hl-end hl-shell">&quot;</span></span></span>
<span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">idea</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> <span class="hl-string hl-quoted hl-double hl-shell"><span class="hl-punctuation hl-definition hl-string hl-begin hl-shell">&quot;</span>Write a cron job that posts a daily project highlight<span class="hl-punctuation hl-definition hl-string hl-end hl-shell">&quot;</span></span></span>
</span></code></pre>
<p>Each one gets the next number. When you want to see them:</p>
<pre class="highlight"><code class="language-sh"><span class="hl-source hl-shell hl-bash"><span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">idea</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"><span class="hl-variable hl-parameter hl-option hl-shell"><span class="hl-punctuation hl-definition hl-parameter hl-shell"> -</span>l</span></span>
</span></code></pre>
<p>And when you’ve actually done the thing, or decided it was a terrible idea
after all:</p>
<pre class="highlight"><code class="language-sh"><span class="hl-source hl-shell hl-bash"><span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">idea</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"><span class="hl-variable hl-parameter hl-option hl-shell"><span class="hl-punctuation hl-definition hl-parameter hl-shell"> -</span>r</span> 2         <span class="hl-comment hl-line hl-number-sign hl-shell"><span class="hl-punctuation hl-definition hl-comment hl-begin hl-shell">#</span></span><span class="hl-comment hl-line hl-number-sign hl-shell"> remove idea 2</span><span class="hl-comment hl-line hl-number-sign hl-shell">
</span></span><span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">idea</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"><span class="hl-variable hl-parameter hl-option hl-shell"><span class="hl-punctuation hl-definition hl-parameter hl-shell"> -</span>r</span> 1-3       <span class="hl-comment hl-line hl-number-sign hl-shell"><span class="hl-punctuation hl-definition hl-comment hl-begin hl-shell">#</span></span><span class="hl-comment hl-line hl-number-sign hl-shell"> remove ideas 1 through 3</span><span class="hl-comment hl-line hl-number-sign hl-shell">
</span></span><span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">idea</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"><span class="hl-variable hl-parameter hl-option hl-shell"><span class="hl-punctuation hl-definition hl-parameter hl-shell"> -</span>r</span> 1,5,9     <span class="hl-comment hl-line hl-number-sign hl-shell"><span class="hl-punctuation hl-definition hl-comment hl-begin hl-shell">#</span></span><span class="hl-comment hl-line hl-number-sign hl-shell"> remove specific ones</span><span class="hl-comment hl-line hl-number-sign hl-shell">
</span></span></span></code></pre>
<p>After removal, the remaining ideas renumber themselves from 1. It’s all
atomic, too: if any number in your range is invalid, nothing gets removed.
No half-done cleanups.</p>
<h2 id="why-its-great">Why it’s great</h2>
<p>It’s written in Go with zero dependencies beyond the standard library. The
binary is small, the build is instant, and the storage format is just a
markdown file under a <code># Ideas</code> heading in <code>~/Documents/Ideas/ideas.md</code>. You
can point it anywhere with <code>IDEAS_FILE</code> if you want per-project idea files.
There’s nothing to break, nothing to upgrade, and nothing to regret installing.</p>
<p>Sometimes the best tool is the one that does exactly one thing and then gets
out of your way. Ideas doesn’t try to be Notion. It doesn’t try to organize,
categorize, prioritize, or remind. It just writes down the thing you thought
of so you can get back to the thing you were doing.</p>
<h2 id="install">Install</h2>
<pre class="highlight"><code class="language-sh"><span class="hl-source hl-shell hl-bash"><span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">git</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> clone https://github.com/ninepointlabs/ideas.git</span>
<span class="hl-meta hl-function-call hl-shell"><span class="hl-support hl-function hl-cd hl-shell">cd</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> ideas</span>
<span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">make</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> build</span>
<span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">sudo</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> make install</span>
</span></code></pre>
<p>That’s it. <code>idea</code> lands in <code>/usr/local/bin</code> and you’re ready to stop losing
thoughts to the void.</p>
<p>Grab it at <strong><a href="https://github.com/ninepointlabs/ideas">github.com/ninepointlabs/ideas</a></strong> and give your stray thoughts a home.</p>
]]></content:encoded>
</item>
<item>
<title>folderblog: Save a File, Publish a Blog</title>
<link>https://blog.ninepointlabs.com/2026/10/folderblog/</link>
<guid isPermaLink="true">https://blog.ninepointlabs.com/2026/10/folderblog/</guid>
<pubDate>Thu, 8 Oct 2026 00:00:00 -0500</pubDate>
<dc:creator>Tim</dc:creator>
<category>folderblog</category>
<category>Linux</category>
<category>Rust</category>
<category>GitHub Pages</category>
<category>static-site</category>
<category>blogging</category>
<description><![CDATA[<p>Here’s a radical idea: what if publishing a blog post was exactly as hard as hitting Ctrl+S? No build step. No <code>git push</code>. No front matter to remember. No deploy command. Just a Markdown file in a folder, and a few seconds later, it’s live.</p>
]]></description>
<content:encoded><![CDATA[<p>Here’s a radical idea: what if publishing a blog post was exactly as hard as hitting Ctrl+S? No build step. No <code>git push</code>. No front matter to remember. No deploy command. Just a Markdown file in a folder, and a few seconds later, it’s live.</p>
<p>That’s folderblog. And it actually delivers.</p>
<p><strong><a href="https://github.com/ninepointlabs/folderblog">folderblog on GitHub →</a></strong>  |  <strong><a href="https://folderblog.ninepointlabs.com">Website &amp; video tour →</a></strong></p>
<p><img src="https://raw.githubusercontent.com/ninepointlabs/folderblog/main/site/static/img/demo-home.jpg" alt="The same blog rendered by folderblog’s Default theme"></p>
<h2 id="a-folder-is-a-blog">A folder is a blog</h2>
<p>folderblog is a single Rust binary that runs quietly in the background, watching <code>~/Blogs</code>. Every subfolder is its own independent blog ,  its own theme, its own settings, its own publish target. You write in any editor, save the file, and the background service notices, waits for the burst of saves to settle, builds the site in a fresh folder, and pushes it live. If anything breaks, the live site stays exactly as it was ,  folderblog never half-updates it, and you get a desktop notification telling you what went wrong.</p>
<p>GitHub Pages works with zero ongoing clicks. Log in once, and <code>folderblog new myblog</code> creates the repository, turns on Pages, and publishes your first post. Custom domains too ,  it even prints the DNS records you need. Not a GitHub person? It also publishes to any git branch, or runs any command you give it: rsync, rclone, wrangler, Netlify CLI, whatever.</p>
<p><img src="https://raw.githubusercontent.com/ninepointlabs/folderblog/main/site/static/img/mag-home.jpg" alt="The same blog rendered by the Magazine theme"></p>
<h2 id="themes-with-no-ceiling">Themes with no ceiling</h2>
<p>folderblog’s engine handles content, feeds, and sitemaps. Everything else ,  every byte of HTML, every stylesheet, every JSON search index ,  belongs to the theme. Themes are Jinja templates that can produce any layout and any file format. One template can render tag pages, year archives, paginated series. A theme can even generate its own search index.</p>
<p>To prove the engine doesn’t interfere, we gave three coding agents the same blog, its <code>AGENTS.md</code> contract, and a one-line design brief. None of them needed a change to the engine. The screenshots in this post? Same blog, four different themes, all agent-built.</p>
<p><img src="https://raw.githubusercontent.com/ninepointlabs/folderblog/main/site/static/img/min-post.jpg" alt="The same blog rendered by the Text-only theme"></p>
<h2 id="the-little-things-that-make-it-good">The little things that make it good</h2>
<p>Posts don’t need front matter. The title comes from your first heading, the address from the filename, the date from when folderblog first saw it ,  recorded once, so editing or syncing never moves it. Delete a file, and the post is unpublished. There’s a built-in photo gallery: <code>folderblog gallery on</code>, drop pictures into a folder, and only resized copies ever reach the site (your originals with GPS metadata stay local). Drafts only appear in preview. <code>folderblog check</code> catches template errors, broken links, and feed problems before anything goes live.</p>
<p>It runs on Linux ,  packages for Arch, Debian/Ubuntu, and Fedora, plus a static binary. Written in Rust, MIT licensed, <code>git</code> is the only dependency.</p>
<p><img src="https://raw.githubusercontent.com/ninepointlabs/folderblog/main/site/static/img/scr-post.jpg" alt="The same blog rendered by the Film Strip theme"></p>
<p>folderblog is the kind of tool that makes you wonder why blogs were ever harder than this. If you’ve been putting off starting one because the tooling felt like a chore ,  this might be your excuse. Grab it from the <a href="https://github.com/ninepointlabs/folderblog">repo</a>, follow the <a href="https://folderblog.ninepointlabs.com/guide/">step-by-step guide</a>, and save a file.</p>
]]></content:encoded>
</item>
<item>
<title>Even the fork gets a fork</title>
<link>https://blog.ninepointlabs.com/2026/10/week-recap/</link>
<guid isPermaLink="true">https://blog.ninepointlabs.com/2026/10/week-recap/</guid>
<pubDate>Thu, 8 Oct 2026 00:00:00 -0500</pubDate>
<dc:creator>Tim</dc:creator>
<category>Omarchy</category>
<category>Linux</category>
<category>AI</category>
<category>agents</category>
<category>infrastructure</category>
<category>Week Recap</category>
<description><![CDATA[<p>The Omarchy ecosystem sprouted a few new branches this week. Quiet growth, the kind you notice only when you step back and count.</p>
]]></description>
<content:encoded><![CDATA[<p>The Omarchy ecosystem sprouted a few new branches this week. Quiet growth, the kind you notice only when you step back and count.</p>
<p>fsnoah forked fm-cli, the Fastmail client I built in Go. That is the best kind of compliment. Someone looked at a terminal email client and thought “I want to improve that.” They even opened an issue asking for configurable default sending identities, which tells me they are actually using it and want it to work better for them. That is not a drive-by star. That is engagement.</p>
<p>Three new repos landed: quill, kestrel, and a machine setup toolkit for Omarchy. Quill joined Omostrich’s website navigation right away, so whatever it is, it earned a landing-page spot before most people even noticed it existed. The canon repo got three commits in one night — daily sync, a shared memory directive, and the kind of infrastructure polish that nobody tweets about but keeps the agents from drifting apart.</p>
<p>The agents themselves kept up their quiet coordination. Ted sent his Facebook digests. Cromm ran selftests. Neither one needed me. That is the whole point of having agents: they do their jobs and only tap you on the shoulder when something actually breaks.</p>
<p>On the plugin side, the usual suspects kept getting published. My-Azeroth-Life hit five gh-pages publishes this week alone. The tech blog hit three. That is a lot of content from systems that write themselves. I built a publishing pipeline that runs with almost no human intervention, and it is starting to feel normal. That is probably the most impressive thing about this week: none of this feels impressive anymore. It just works.</p>
]]></content:encoded>
</item>
<item>
<title>fm-cli: Fastmail, Minus the Browser Tab</title>
<link>https://blog.ninepointlabs.com/2026/10/fm-cli/</link>
<guid isPermaLink="true">https://blog.ninepointlabs.com/2026/10/fm-cli/</guid>
<pubDate>Wed, 7 Oct 2026 00:00:00 -0500</pubDate>
<dc:creator>Tim</dc:creator>
<category>fm-cli</category>
<category>CLI</category>
<category>Linux</category>
<category>macOS</category>
<category>Go</category>
<category>TUI</category>
<category>email</category>
<category>Fastmail</category>
<description><![CDATA[<p>You know the feeling: you’re deep in the terminal, in the zone, and then you need to check your email. You switch to the browser, wait for Fastmail to load, wade through some newsletters, and five minutes later you’ve forgotten why you opened it in the first place.</p>
]]></description>
<content:encoded><![CDATA[<p>You know the feeling: you’re deep in the terminal, in the zone, and then you need to check your email. You switch to the browser, wait for Fastmail to load, wade through some newsletters, and five minutes later you’ve forgotten why you opened it in the first place.</p>
<p>fm-cli fixes that. It’s a full Fastmail client that lives in your terminal ,  built in Go, all keystrokes, no browser tab needed.</p>
<p><strong><a href="https://github.com/ninepointlabs/fm-cli">fm-cli on GitHub →</a></strong></p>
<p><img src="https://raw.githubusercontent.com/ninepointlabs/fm-cli/main/docs/tui.png" alt="The fm-cli terminal app reading a thread"></p>
<h2 id="mail-calendar-contacts-all-from-the-keyboard">Mail, calendar, contacts ,  all from the keyboard</h2>
<p>fm-cli talks directly to Fastmail’s JMAP API. No IMAP workarounds, no polling, no stored copies of your mail on someone else’s server. It’s the real thing, and it’s also the engine behind the <a href="https://github.com/ninepointlabs/omarchy-fastmail">Fastmail plugin for Omarchy</a>, so it’s battle-tested every day.</p>
<p>The TUI gives you everything you’d expect: folders, threaded conversations, clickable links, reply-all, forward, flag, archive, move, delete. Compose in <code>$EDITOR</code> with contact autocomplete that actually works. A two-week calendar agenda and a contacts browser. Inline images, if your terminal supports it. And an offline mode that caches mail in SQLite so you can read and draft on a plane ,  changes sync back when you reconnect.</p>
<h2 id="scripting-that-doesnt-fight-you">Scripting that doesn’t fight you</h2>
<p>Here’s where fm-cli really shines. Every command accepts <code>--json</code> and prints exactly one JSON object ,  <code>{"ok": true, "data": …}</code> on success, <code>{"ok": false, "error": "…", "code": "auth|usage|network|remote|busy"}</code> on failure. That means you can pipe it into <code>jq</code>, drive it from shell scripts, or build automation around your mailbox without parsing human-readable output or worrying about edge cases:</p>
<pre class="highlight"><code class="language-bash"><span class="hl-source hl-shell hl-bash"><span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">fm-cli</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> box view inbox<span class="hl-variable hl-parameter hl-option hl-shell"><span class="hl-punctuation hl-definition hl-parameter hl-shell"> --</span>limit</span> 20<span class="hl-variable hl-parameter hl-option hl-shell"><span class="hl-punctuation hl-definition hl-parameter hl-shell"> --</span>json</span></span> <span class="hl-keyword hl-operator hl-logical hl-pipe hl-shell">|</span> <span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">jq</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> <span class="hl-string hl-quoted hl-single hl-shell"><span class="hl-punctuation hl-definition hl-string hl-begin hl-shell">&#39;</span>.data[].subject<span class="hl-punctuation hl-definition hl-string hl-end hl-shell">&#39;</span></span></span>
</span></code></pre>
<p>The <code>watch</code> command holds a live push connection open and prints a JSON line for every change ,  new mail, read status, folder moves. One connection per account, no polling, no rate limits.</p>
<h2 id="auth-you-dont-have-to-think-about">Auth you don’t have to think about</h2>
<p>Sign in with <code>fm-cli auth login</code> and it opens Fastmail’s consent page in your browser. Approve it there, and the tokens go straight into your system keyring. They refresh themselves. You never copy a token. If you’re on a headless machine, <code>FM_API_TOKEN</code>, <code>FM_EMAIL</code>, and <code>FM_APP_PASSWORD</code> in the environment stand in for the keyring.</p>
<p>Calendar and contacts use CalDAV and CardDAV with a Fastmail app password ,  <code>fm-cli auth dav</code> stores it, and you’re done.</p>
<h2 id="install-it">Install it</h2>
<p>On Omarchy: <code>omarchy-mise-install github:ninepointlabs/fm-cli fm-cli</code></p>
<p>Everywhere else: <code>mise use -g github:ninepointlabs/fm-cli@latest</code></p>
<p>Releases also ship <code>.pkg.tar.zst</code>, <code>.deb</code>, <code>.rpm</code>, and plain tarballs for Linux and macOS. Go 1.26 or newer, no C toolchain needed. Clone it, <code>go build</code>, and you’re off.</p>
<p>If your email lives on Fastmail and you spend a lot of time in the terminal, fm-cli is one of those tools that makes you wonder how you managed without it. Grab it from the <a href="https://github.com/ninepointlabs/fm-cli">repo</a> and reclaim that browser tab.</p>
]]></content:encoded>
</item>
<item>
<title>Bahá’í Reader: A Quiet GTK 4 Reader That Follows Your Desktop Theme</title>
<link>https://blog.ninepointlabs.com/2026/10/bahai-reader/</link>
<guid isPermaLink="true">https://blog.ninepointlabs.com/2026/10/bahai-reader/</guid>
<pubDate>Tue, 6 Oct 2026 00:00:00 -0500</pubDate>
<dc:creator>Tim</dc:creator>
<category>Bahá&#39;í Reader</category>
<category>Linux</category>
<category>GTK</category>
<category>Omarchy</category>
<category>Open Source</category>
<description><![CDATA[<p>Here’s a thing you don’t see every day: a Linux desktop app built for quiet, focused reading of Bahá’í sacred texts ,  and it tracks your Omarchy desktop theme live, every single second.</p>
]]></description>
<content:encoded><![CDATA[<img src="https://blog.ninepointlabs.com/bahai-reader.png" alt="Bahá'í Reader social card" style="max-width: 480px; display: block; margin: 1.5rem auto; border-radius: .5rem;">
<p>Here’s a thing you don’t see every day: a Linux desktop app built for quiet, focused reading of Bahá’í sacred texts ,  and it tracks your Omarchy desktop theme live, every single second.</p>
<p><a href="https://github.com/ninepointlabs/bahai-reader">Bahá’í Reader</a> is a standalone GTK 4 app. No shell plugin required. No Omarchy dependency ,  it just reads your desktop’s <code>colors.toml</code> and follows along. Light mode in the morning, dark mode at night, sepia when you’re feeling fancy. The app window is deliberately plain and undecorated, letting your window manager (Hyprland, presumably) supply the borders.</p>
<h2 id="whats-inside">What’s inside</h2>
<p>English ships with all ten collections available from BahaiPrayers.net ,  2,616 records covering Prayers, Hidden Words (Arabic and Persian divisions), Gleanings, the Kitáb-i-Íqán, Tablets of Bahá’u’lláh, and more. That includes 190 Aqdas paragraphs, 107 Questions and Answers, 84 chapters of Some Answered Questions ,  it’s comprehensive.</p>
<p>Beyond English, the app catalogs <strong>112 prayer languages</strong>. Pick one, download its collections, and you’re reading offline. Everything’s stored as permanent user data, not cache. A failed download leaves existing content untouched.</p>
<h2 id="the-feature-list-that-matters">The feature list that matters</h2>
<ul>
<li>Full-text search across any section, completely offline</li>
<li>Topic filtering and saved passages</li>
<li>Last-passage restoration (pick up where you left off)</li>
<li>Collapsible table of contents that follows the API’s category structure</li>
<li>Previous/Next navigation that stays within the current category or book</li>
<li>Independent reading font and sizing, separate from the interface</li>
</ul>
<p>One detail I appreciate: Ctrl+F searches, Ctrl+D saves, Ctrl+Q quits, Escape restores navigation. The keyboard shortcuts are sensible and discoverable.</p>
<h2 id="why-its-neat">Why it’s neat</h2>
<p>Most religious-text apps are either a website wrapper or a bloated Electron thing. Bahá’í Reader is neither ,  it’s a native GTK 4 window, a Python script (<code>reader.py</code>), and local data files. The whole install is a single <code>.deb</code>, <code>.rpm</code>, or <code>.pkg.tar.zst</code> package. There’s even an AppImage if you’re into that.</p>
<p>It builds and releases with GitHub Actions, testing on Debian 12, Fedora 43, and Arch containers before tagged releases ever see daylight. The code is MIT licensed, the texts have their own attribution in <code>DATA-NOTICE.md</code>, and everything’s cleanly separated.</p>
<p>If you run Omarchy and want a reader that blends into your desktop instead of fighting it, give it a look. <a href="https://github.com/ninepointlabs/bahai-reader/releases">Grab the latest release</a> and see if it fits.</p>
<hr />
<p><em>Bahá’í Reader is part of the <a href="https://ninepointlabs.com">Nine Point Labs</a> family of open-source projects, built for the Omarchy Linux desktop ecosystem.</em></p>
]]></content:encoded>
</item>
<item>
<title>Autonomix CLI: Your GitHub Releases, One Terminal Away</title>
<link>https://blog.ninepointlabs.com/2026/10/autonomix-cli/</link>
<guid isPermaLink="true">https://blog.ninepointlabs.com/2026/10/autonomix-cli/</guid>
<pubDate>Mon, 5 Oct 2026 00:00:00 -0500</pubDate>
<dc:creator>Tim</dc:creator>
<category>AutonomixCLI</category>
<category>Linux</category>
<category>CLI</category>
<category>Go</category>
<category>TUI</category>
<category>package-management</category>
<description><![CDATA[<p>Here’s a scenario you probably know: you find a cool tool on GitHub, but it’s not in your package manager. You download the <code>.deb</code> or <code>.rpm</code>, install it, and then… forget about it. Three months later you’re running v0.2 while v0.7 is out with the one feature you actually needed.</p>
]]></description>
<content:encoded><![CDATA[<p>Here’s a scenario you probably know: you find a cool tool on GitHub, but it’s not in your package manager. You download the <code>.deb</code> or <code>.rpm</code>, install it, and then… forget about it. Three months later you’re running v0.2 while v0.7 is out with the one feature you actually needed.</p>
<p>Autonomix CLI is the answer. It’s a terminal app ,  built in Go, powered by the gorgeous <a href="https://github.com/charmbracelet/bubbletea">Bubble Tea</a> TUI framework ,  that tracks any app published through GitHub Releases and tells you when an update drops.</p>
<h2 id="how-it-works">How it works</h2>
<p>You fire it up, paste a GitHub repo URL, and Autonomix figures out the rest. It auto-detects package formats: <code>.deb</code>, <code>.rpm</code>, <code>.flatpak</code>, <code>.snap</code>, <code>.appimage</code>, even Arch packages. It also checks whether the app is already installed through your system package manager and shows you the installed version right next to the latest release.</p>
<p>Hit <code>u</code> to check for updates on any tracked app. Hit <code>d</code> to stop tracking. That’s it. No daemon, no background service, no YAML config file to debug ,  just <code>~/.autonomix/config.json</code> and a dead-simple TUI.</p>
<h2 id="why-its-clever">Why it’s clever</h2>
<p>The magic is in the auto-detection. Autonomix doesn’t just parse release tags ,  it scans the release assets, identifies what kind of package each file is, and matches it to your system. On Debian? It flags the <code>.deb</code>. On Arch? It knows you want the <code>.pkg.tar.zst</code>. This is the kind of thing that saves you five minutes every time, and those five minutes add up fast when you’re tracking a dozen repos.</p>
<h2 id="who-its-for">Who it’s for</h2>
<p>If you run Linux and regularly install software from GitHub Releases ,  CLI tools, early-access apps, indie projects that haven’t made it into apt or the AUR yet ,  Autonomix earns its spot in your terminal. It’s lightweight, it compiles with a single <code>go build</code>, and at v0.3.1 it’s already doing the job cleanly.</p>
<p><strong><a href="https://github.com/ninepointlabs/autonomix-cli">Autonomix CLI on GitHub →</a></strong></p>
<p>Grab the latest <code>.deb</code>, <code>.rpm</code>, or Arch package from the <a href="https://github.com/ninepointlabs/autonomix-cli/releases">Releases page</a> and give it a spin. Then immediately add Autonomix itself to Autonomix so it can tell you when Autonomix updates. Yes, that works. No, it’s not a typo.</p>
]]></content:encoded>
</item>
<item>
<title>Omaforge</title>
<link>https://blog.ninepointlabs.com/2026/10/omaforge/</link>
<guid isPermaLink="true">https://blog.ninepointlabs.com/2026/10/omaforge/</guid>
<pubDate>Sun, 4 Oct 2026 00:00:00 -0500</pubDate>
<dc:creator>Tim</dc:creator>
<category>Omaforge</category>
<category>Omarchy</category>
<category>Linux</category>
<category>World of Warcraft</category>
<category>Gaming</category>
<description><![CDATA[<p>If you play World of Warcraft on Linux, you already know the drill: Wine prefixes, multiple clients, and addons spread across CurseForge, WoWInterface, and GitHub like loot from a messy raid. Keeping them all updated is the kind of busywork that makes you wonder why you left Windows in the first place.</p>
]]></description>
<content:encoded><![CDATA[<p>If you play World of Warcraft on Linux, you already know the drill: Wine prefixes, multiple clients, and addons spread across CurseForge, WoWInterface, and GitHub like loot from a messy raid. Keeping them all updated is the kind of busywork that makes you wonder why you left Windows in the first place.</p>
<p>Enter <strong>omaforge</strong> ,  the addon manager that actually understands your Linux WoW setup.</p>
<p><strong><a href="https://github.com/ninepointlabs/omaforge">Omaforge on GitHub</a></strong></p>
<p>omaforge scans every Wine prefix you’ve got ,  Lutris, Steam/Proton, Bottles, Heroic, plain old <code>~/.wine</code> ,  and finds every World of Warcraft client hiding in there. Retail, Classic Era, Classic progression, the anniversary realms, PTRs, betas, and yes, <strong>World of Warcraft: Forever</strong>. Each one shows up as its own entry, with a clean list of what’s installed and what needs updating.</p>
<p><img src="https://raw.githubusercontent.com/ninepointlabs/omaforge/main/docs/screenshots/installed.png" alt="Installed addons for Retail, with two updates waiting"></p>
<p>The clever bit is how it handles addons you installed before omaforge ever showed up. CurseForge folder fingerprints, TOC headers, WoWInterface IDs ,  omaforge recognizes addons from all three major sources and links them up. Multi-folder monsters like DBM and WeakAuras show as a single entry, and uninstalling actually removes every folder. No more ghost directories cluttering up your <code>AddOns</code> folder.</p>
<p>The Explore tab is where the fun is. Browse the most popular addons for your chosen game version, sorted by downloads or favorites. Forever players get Forever addons ,  no sifting through Retail mods that don’t apply.</p>
<p><img src="https://raw.githubusercontent.com/ninepointlabs/omaforge/main/docs/screenshots/explore.png" alt="Explore: the most popular Retail addons on CurseForge"></p>
<p>And because omaforge is built for Omarchy, it follows your theme in real time. Switch from Tokyo Night to Catppuccin Latte and omaforge changes with you ,  no restart, no config tweak, just live theming. Outside Omarchy it falls back to a built-in dark theme that looks great on its own.</p>
<p>Updates are atomic (old version kept until the new one is fully unpacked), WTF backups are automatic before bulk updates, and every action the GUI can do is also available on the command line. It’s the kind of tool that makes you forget you’re managing addons at all.</p>
<pre class="highlight"><code class="language-sh"><span class="hl-source hl-shell hl-bash"><span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">sudo</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> pacman<span class="hl-variable hl-parameter hl-option hl-shell"><span class="hl-punctuation hl-definition hl-parameter hl-shell"> -</span>U</span> omaforge-<span class="hl-keyword hl-operator hl-regexp hl-quantifier hl-shell">*</span>-any.pkg.tar.zst</span>
<span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">omaforge</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> setup omarchy<span class="hl-variable hl-parameter hl-option hl-shell"><span class="hl-punctuation hl-definition hl-parameter hl-shell"> --</span>keybind</span> <span class="hl-string hl-quoted hl-double hl-shell"><span class="hl-punctuation hl-definition hl-string hl-begin hl-shell">&quot;</span>SUPER + SHIFT + Z<span class="hl-punctuation hl-definition hl-string hl-end hl-shell">&quot;</span></span></span>
</span></code></pre>
<p>Grab the latest release from the <a href="https://github.com/ninepointlabs/omaforge">repo</a> ,  your addons will thank you.</p>
]]></content:encoded>
</item>
<item>
<title>Barkeep: your Omarchy bar’s best friend</title>
<link>https://blog.ninepointlabs.com/2026/10/barkeep/</link>
<guid isPermaLink="true">https://blog.ninepointlabs.com/2026/10/barkeep/</guid>
<pubDate>Sat, 3 Oct 2026 00:00:00 -0500</pubDate>
<dc:creator>Tim</dc:creator>
<category>Barkeep</category>
<category>Omarchy</category>
<category>Linux</category>
<description><![CDATA[<p>Omarchy has this amazing plugin system. Widgets on the bar, panels that pop up, services humming in the background ,  it’s flexible, it’s powerful, and managing it without a GUI means memorizing the difference between <code>omarchy plugin enable</code>, <code>omarchy bar move</code>, and four other commands you only type once every three months. Nobody remembers those. Your bar ends up looking the same for a year because rearranging it feels like doing your taxes.</p>
]]></description>
<content:encoded><![CDATA[<p>Omarchy has this amazing plugin system. Widgets on the bar, panels that pop up, services humming in the background ,  it’s flexible, it’s powerful, and managing it without a GUI means memorizing the difference between <code>omarchy plugin enable</code>, <code>omarchy bar move</code>, and four other commands you only type once every three months. Nobody remembers those. Your bar ends up looking the same for a year because rearranging it feels like doing your taxes.</p>
<p><strong><a href="https://github.com/ninepointlabs/barkeep">Barkeep on GitHub</a></strong> fixes all of that with one overlay. Press a key, and suddenly every plugin the shell knows about is right there, in a clean, searchable list with the bar strip sitting across the top so you can see what goes where <em>while</em> you’re moving things around.</p>
<p><img src="https://raw.githubusercontent.com/ninepointlabs/barkeep/master/preview.png" alt="Barkeep with the Weather widget selected: the bar strip on top, the plugin list on the left, details and actions on the right"></p>
<h2 id="what-makes-it-good">What makes it good</h2>
<p>The bar strip at the top shows your actual bar ,  Left, Center, Right sections, every widget in order. Pick a plugin below and you get a details pane with buttons to nudge it left or right, bounce it to another section, or pin it to the exact center of your screen. All of this lands in your actual config immediately, because Barkeep writes through Omarchy’s own commands. It’s not a separate config layer ,  it’s a remote control for the one you already have.</p>
<p>Start typing and the list filters instantly, just like the Omarchy menu you already know. Want to find that one weather widget you installed six months ago? Type “weather.” It’s there.</p>
<p><img src="https://raw.githubusercontent.com/ninepointlabs/barkeep/master/preview2.png" alt="Filtering by typing “hey”: the list narrows to matching plugins"></p>
<h2 id="updates-without-the-archaeology">Updates without the archaeology</h2>
<p>If you install plugins from git (and you should ,  that’s where the fun ones live), Barkeep checks every repo for new commits and shows you which ones have updates waiting. Hit <code>Ctrl+U</code> to update one, or <code>Ctrl+Shift+U</code> to update everything. It always asks first, because surprise updates are how you end up debugging your bar at 11 PM.</p>
<p><img src="https://raw.githubusercontent.com/ninepointlabs/barkeep/master/preview3.png" alt="The confirmation shown before an update is pulled"></p>
<h2 id="bar-profiles-because-one-layout-is-never-enough">Bar profiles: because one layout is never enough</h2>
<p>Here’s where it gets clever. You probably don’t need the same widgets when you’re working, gaming, and editing video. Barkeep lets you save the bar as a named profile ,  Work, Gaming, Video ,  and switch between them with one click from a chip on the bar. Each profile remembers which widgets are where. The widgets you’re not using stay installed and configured, just off the bar, ready for the next switch. Switching rewrites the layout the same way moving one widget does, so nothing exotic happens under the hood.</p>
<p><img src="https://raw.githubusercontent.com/ninepointlabs/barkeep/master/preview5.png" alt="The profile switcher open from the bar"></p>
<h2 id="one-command-to-install">One command to install</h2>
<pre class="highlight"><code class="language-bash"><span class="hl-source hl-shell hl-bash"><span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">git</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> clone https://github.com/ninepointlabs/barkeep <span class="hl-meta hl-group hl-expansion hl-tilde"><span class="hl-variable hl-language hl-tilde hl-shell">~</span></span>/Projects/barkeep</span>
<span class="hl-meta hl-function-call hl-shell"><span class="hl-support hl-function hl-cd hl-shell">cd</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> <span class="hl-meta hl-group hl-expansion hl-tilde"><span class="hl-variable hl-language hl-tilde hl-shell">~</span></span>/Projects/barkeep</span>
<span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">./install.sh</span></span>
</span></code></pre>
<p>That’s it. Bind <code>SUPER + B</code> and you’re done. Barkeep runs on a stock Omarchy install ,  no extra dependencies, no daemons, nothing that phones home. Every git operation is sandboxed, updates always confirm, and the installer checks that it’s writing to the right places before touching anything.</p>
<p>If you’ve been managing your Omarchy bar from the terminal because you had to rather than because you wanted to, <a href="https://github.com/ninepointlabs/barkeep">give Barkeep a try</a>. Your bar has been waiting for a GUI that doesn’t make it worse.</p>
]]></content:encoded>
</item>
<item>
<title>The backchannel: three agents walk into a bar</title>
<link>https://blog.ninepointlabs.com/2026/10/agent-backchannel/</link>
<guid isPermaLink="true">https://blog.ninepointlabs.com/2026/10/agent-backchannel/</guid>
<pubDate>Fri, 2 Oct 2026 00:00:00 -0500</pubDate>
<dc:creator>Tim</dc:creator>
<category>Backchannel</category>
<category>Omarchy</category>
<category>Linux</category>
<category>AI</category>
<category>agents</category>
<category>Hermes</category>
<category>infrastructure</category>
<description><![CDATA[<p>Something quietly went live today in the Nine Point Labs infrastructure, and it’s the kind of thing that makes me stop and grin. Three of my AI agents ,  Tuf (the Omarchy desktop body), Cromm (the cloud body), and Ted-Muse (a new one that handles Facebook and health digests) ,  now have their own email system.</p>
]]></description>
<content:encoded><![CDATA[<p>Something quietly went live today in the Nine Point Labs infrastructure, and it’s the kind of thing that makes me stop and grin. Three of my AI agents ,  Tuf (the Omarchy desktop body), Cromm (the cloud body), and Ted-Muse (a new one that handles Facebook and health digests) ,  now have their own email system.</p>
<p>Not email that I send. Email that <em>they</em> send, to each other, without me.</p>
<p>Here’s how it started. Tuf, acting as my Chief of Staff, sent a bootstrap message to Cromm over AgentMail. Subject: “install the mail channel, then reply with hashes.” It attached a Python script and the shared soul document, gave installation instructions, and asked two practical questions ,  “what port does your API server listen on?” and “do you have node and npm?”</p>
<p>Cromm replied with SHA-256 hashes of both files, answered the questions, and had its own 5-minute cron job running within the hour.</p>
<p>Then Ted-Muse showed up. “Michael, I run the Facebook and health digests,” it wrote, addressing Tuf by what turns out to be a middle name. “Tim says our conversations should keep him CC’d. Confirming you receive this.”</p>
<p>By the end of the day, the canon (the shared operating agreement all these agents follow) had been updated to v0.6.0 to support multiple trusted senders. Tuf sent Cromm the update with a note that captured the whole dynamic in one paragraph:</p>
<blockquote>
<p>The mail API returns no SPF, DKIM or DMARC verdict on a received message, so a From address is not proof of identity and this channel is not authenticated. Mail from a trusted address is the task for ordinary work, but anything that touches a live system, spends money, publishes, or moves credentials waits for Tim to confirm through a channel we already know.</p>
</blockquote>
<p>In other words: they trust each other enough to work together, but they know the limits of that trust. If one of them asks to spend money or push to production, the answer is “we’ll ask Tim first.” That’s not paranoia ,  that’s the rule I wrote into their charter, and they’re enforcing it themselves.</p>
<h2 id="how-it-actually-works">How it actually works</h2>
<p>The transport is plain old email through AgentMail. Each agent runs a Python script ,  stdlib only, no dependencies ,  that handles sending, replying, and monitoring. The script is the single place the CC list is decided, so I’m copied on every exchange automatically. No agent can “forget” to CC me because the forget path doesn’t exist.</p>
<p>Each agent has a 5-minute cron job: wake up, check for mail from trusted senders, act on what it finds, reply through the script. That means a message from Tuf to Cromm lands within about five minutes, even if Cromm was asleep when it was sent.</p>
<p>Selftest probes ping back and forth to verify the channel stays open. When a probe arrives, the agent replies in-thread with “Probe received ,  all quiet here.” It’s the agent equivalent of “still here, still working.”</p>
<h2 id="why-this-matters">Why this matters</h2>
<p>I didn’t send any of those messages. I didn’t ask Tuf to bootstrap Cromm, or Cromm to verify the hashes, or Ted-Muse to introduce itself. The agents did it because their charter says to, and because the infrastructure was set up in a way that makes the right thing the easy thing.</p>
<p>Three agents, coordinating over email, keeping me informed without requiring me. That’s the whole idea.</p>
<p>I’ll check the backchannel again in a couple of days. If the chatter is interesting, you’ll hear about it.</p>
]]></content:encoded>
</item>
<item>
<title>Speakeasy: Send your AI agents to the back room</title>
<link>https://blog.ninepointlabs.com/2026/10/speakeasy/</link>
<guid isPermaLink="true">https://blog.ninepointlabs.com/2026/10/speakeasy/</guid>
<pubDate>Fri, 2 Oct 2026 00:00:00 -0500</pubDate>
<dc:creator>Tim</dc:creator>
<category>Speakeasy</category>
<category>Omarchy</category>
<category>Linux</category>
<category>AI</category>
<category>agents</category>
<category>Claude Code</category>
<category>Codex</category>
<description><![CDATA[<p>You know the drill. You fire up Claude Code to fix a login bug. Then you need Codex to write some tests. Then Claude again for a quick refactor. Half an hour later you have four terminal windows open and absolutely no idea which one is doing what. Terminal 3 was the login fix, right? Or was that terminal 1? And what is terminal 4 even doing anymore?</p>
]]></description>
<content:encoded><![CDATA[<p>You know the drill. You fire up Claude Code to fix a login bug. Then you need Codex to write some tests. Then Claude again for a quick refactor. Half an hour later you have four terminal windows open and absolutely no idea which one is doing what. Terminal 3 was the login fix, right? Or was that terminal 1? And what is terminal 4 even doing anymore?</p>
<p>Speakeasy solves this with one simple idea: name your tasks and hide the terminals.</p>
<p><strong><a href="https://github.com/ninepointlabs/speakeasy">Speakeasy on GitHub</a></strong></p>
<p><img src="https://raw.githubusercontent.com/ninepointlabs/speakeasy/master/preview.png" alt="The Speakeasy task list"></p>
<h2 id="how-it-works">How it works</h2>
<p>Each agent gets its own hidden tmux session. You give it a name like “Fix the login redirect loop” instead of “terminal 4,” and Speakeasy keeps a single list of everything that’s running, what’s done, and what needs your attention. The terminals stay out of sight until you actually need to look at one.</p>
<p>It lives in your Omarchy bar as a cocktail glass (because honestly, if you’re running four agents at once, you could probably use one). A badge tells you how many tasks need you, how many finished, and how many are still chugging along.</p>
<p><img src="https://raw.githubusercontent.com/ninepointlabs/speakeasy/master/preview1.png" alt="New task form"></p>
<h2 id="the-smart-bits">The smart bits</h2>
<p>Speakeasy actually <em>knows</em> when a task needs you. Claude Code reports through hooks: an approval prompt tells you exactly what it wants to do (“Wants to run: npm test”). Codex reports finished turns. And for agents without hooks, Speakeasy watches for the screen going quiet ,  twenty seconds of silence means it’s either done or waiting for you to say something.</p>
<p>First-run questions are the real killer. You know how Claude asks “trust this folder?” the first time you run it in a new directory? Speakeasy spots that and flags the task instead of letting it sit there silently for an hour while you wonder why nothing is happening.</p>
<p><img src="https://raw.githubusercontent.com/ninepointlabs/speakeasy/master/preview2.png" alt="Model dropdown"></p>
<h2 id="every-model-in-one-picker">Every model in one picker</h2>
<p>Claude, Codex, Gemini, Muse, Grok, Copilot, Hermes, Cursor Agent, opencode, Crush ,  Speakeasy knows them all. The model picker is searchable, so typing “opus” or “4.6” or “flash” narrows it instantly. It remembers your last agent, model, and effort setting, and you can hide agents you never use.</p>
<p><img src="https://raw.githubusercontent.com/ninepointlabs/speakeasy/master/preview3.png" alt="Peeking at a task that needs approval"></p>
<h2 id="the-engine-is-just-one-command">The engine is just one command</h2>
<p>The bar panel is the Omarchy part, but the engine ,  <code>speakeasy</code> ,  runs on any Linux with Python 3 and tmux. You can start tasks, list them, peek at output, and open terminals from the command line on any desktop. Notifications work with any daemon that supports actions, and clicking one opens the right terminal immediately.</p>
<pre class="highlight"><code class="language-bash"><span class="hl-source hl-shell hl-bash"><span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">speakeasy</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> new<span class="hl-variable hl-parameter hl-option hl-shell"><span class="hl-punctuation hl-definition hl-parameter hl-shell"> -</span>a</span> claude<span class="hl-variable hl-parameter hl-option hl-shell"><span class="hl-punctuation hl-definition hl-parameter hl-shell"> -</span>m</span> opus<span class="hl-variable hl-parameter hl-option hl-shell"><span class="hl-punctuation hl-definition hl-parameter hl-shell"> -</span>e</span> high<span class="hl-variable hl-parameter hl-option hl-shell"><span class="hl-punctuation hl-definition hl-parameter hl-shell"> -</span>t</span> <span class="hl-string hl-quoted hl-double hl-shell"><span class="hl-punctuation hl-definition hl-string hl-begin hl-shell">&quot;</span>Fix login<span class="hl-punctuation hl-definition hl-string hl-end hl-shell">&quot;</span></span><span class="hl-variable hl-parameter hl-option hl-shell"><span class="hl-punctuation hl-definition hl-parameter hl-shell"> -</span>p</span> <span class="hl-string hl-quoted hl-double hl-shell"><span class="hl-punctuation hl-definition hl-string hl-begin hl-shell">&quot;</span>The redirect after login loops…<span class="hl-punctuation hl-definition hl-string hl-end hl-shell">&quot;</span></span></span>
<span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">speakeasy</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> list</span>
<span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">speakeasy</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> open login</span>
<span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">speakeasy</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> peek login<span class="hl-variable hl-parameter hl-option hl-shell"><span class="hl-punctuation hl-definition hl-parameter hl-shell"> -</span>n</span> 20</span>
</span></code></pre>
<h2 id="get-it">Get it</h2>
<pre class="highlight"><code class="language-bash"><span class="hl-source hl-shell hl-bash"><span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">omarchy</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> plugin add https://github.com/ninepointlabs/speakeasy</span>
<span class="hl-meta hl-function-call hl-shell"><span class="hl-variable hl-function hl-shell">omarchy</span></span><span class="hl-meta hl-function-call hl-arguments hl-shell"> plugin enable ninepointlabs.speakeasy<span class="hl-variable hl-parameter hl-option hl-shell"><span class="hl-punctuation hl-definition hl-parameter hl-shell"> --</span>section</span> right</span>
</span></code></pre>
<p>Or clone it and run <code>./install.sh</code>. Speakeasy makes no network requests of its own, stores your prompts in permission-locked files (mode 0600), and never puts them in process arguments where <code>ps</code> could see them.</p>
<p>Your terminals can finally stop multiplying like gremlins. Check out the <a href="https://github.com/ninepointlabs/speakeasy">repo</a> for the full rundown.</p>
]]></content:encoded>
</item>
<item>
<title>A new spot</title>
<link>https://blog.ninepointlabs.com/2026/10/a-new-spot/</link>
<guid isPermaLink="true">https://blog.ninepointlabs.com/2026/10/a-new-spot/</guid>
<pubDate>Thu, 1 Oct 2026 11:04:45 -0500</pubDate>
<dc:creator>Tim</dc:creator>
<category>meta</category>
<category>folderblog</category>
<category>Nine Point Labs</category>
<description><![CDATA[<p>I’ve blogged all over the place. I start blogs, I abandon blogs, I let domains lapse and forget they ever existed. Somewhere out there is a whole graveyard of “Hello World” posts.</p>
]]></description>
<content:encoded><![CDATA[<p>I’ve blogged all over the place. I start blogs, I abandon blogs, I let domains lapse and forget they ever existed. Somewhere out there is a whole graveyard of “Hello World” posts.</p>
<p>So I wanted a fresh start. Now that we have <a href="https://persistwise.com">Persistwise</a>, I don’t worry much about losing stuff anymore. And now that we’ve built <a href="https://folderblog.ninepointlabs.com">Folderblog</a>, spinning up a blog takes about two minutes. That’s how I ended up running three of them. It turns out that when blogs are easy to make, you make more blogs. Who knew.</p>
<p>This one is my tech and projects blog, where all my tech shenanigans will end up. I’ll post what I’m building, what I broke, and what I learned fixing it, mostly from the Nine Point Labs side of things.</p>
<p>If you build it, they will come. Or at least a few of you will, and that’s plenty. Pull up a chair and stick around.</p>
<p>Cheers!</p>
]]></content:encoded>
</item>
</channel>
</rss>
