<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator>
  <link href="https://shel.sh/feed.xml" rel="self" type="application/atom+xml" />
  <link href="https://shel.sh/" rel="alternate" type="text/html" />
  <updated>2026-06-30T20:18:20+00:00</updated>
  <id>https://shel.sh/</id>
  <title type="html">sHEL</title>
  <subtitle>All the protection of a turtle without the soft underbelly. Volatile, literal-safe, automation-friendly data substrate.</subtitle>
  <author>
    <name>sHEL Contributors</name>
    <email>clement.keynote-1e@icloud.com</email>
  </author>

  
  <entry>
    <title type="html">adspace: The Redirect Engine That Could</title>
    <link href="https://shel.sh/blog/2025-11-01-adspace/" rel="alternate" type="text/html" />
    <published>2025-11-01T09:00:00+00:00</published>
    <updated>2025-11-01T09:00:00+00:00</updated>
    <id>https://shel.sh/blog/2025-11-01-adspace/</id>
    <author>
      <name>CommanderTurtle</name>
    </author>
    <content type="html" xml:base="https://shel.sh/blog/2025-11-01-adspace/">
      &lt;p&gt;Every project starts with a template. A blank canvas. A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index.html&lt;/code&gt; and a dream. &lt;strong&gt;adspace&lt;/strong&gt; is currently just that — a single template, a timer counting up from 11.20 seconds, and a name: &lt;em&gt;Hillscape Journey&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;But the vision is bigger. Much bigger.&lt;/p&gt;

&lt;h2 id=&quot;what-exists-today&quot;&gt;What Exists Today&lt;/h2&gt;

&lt;p&gt;Right now, adspace is a redirect engine template living at &lt;a href=&quot;https://shel.sh/projects/adspace/templates/1/&quot;&gt;shel.sh/projects/adspace/templates/1&lt;/a&gt;. It shows a scenic hillscape background with a subtle counter. Simple. Peaceful. Deliberately minimal.&lt;/p&gt;

&lt;p&gt;The template system is designed for &lt;strong&gt;interstitial redirects&lt;/strong&gt; — those moments between clicking a link and arriving at the destination where you have, say, 5-15 seconds of the user’s attention. Instead of showing a generic “you will be redirected” message, why not show something beautiful? Something that might make the user actually &lt;em&gt;want&lt;/em&gt; to pause before the redirect completes?&lt;/p&gt;

&lt;h2 id=&quot;where-its-heading&quot;&gt;Where It’s Heading&lt;/h2&gt;

&lt;p&gt;The long-term plan is a &lt;strong&gt;pluggable redirect engine&lt;/strong&gt; with a template marketplace. Creators design interstitial templates (like Hillscape Journey), advertisers bid on redirect slot time, and users get something visually interesting instead of a blank loading screen.&lt;/p&gt;

&lt;p&gt;The architecture I’m imagining:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Template Layer&lt;/strong&gt;: HTML/CSS/JS interstitial designs, each with configurable parameters (background, timer duration, transition animation, optional interactive elements). Think of it as themes for the space between pages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Redirect Layer&lt;/strong&gt;: Fast, tracked URL shortening with analytics — click counts, dwell time on the interstitial, completion rate to final destination.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ad Insertion Layer&lt;/strong&gt;: Optional sponsored content in the interstitial space. The key constraint: it must be as pleasant as the default templates. No flashing banners. No auto-playing audio. Just calmly presented, beautifully designed content that respects the user’s attention.&lt;/p&gt;

&lt;h2 id=&quot;the-philosophy&quot;&gt;The Philosophy&lt;/h2&gt;

&lt;p&gt;Most ad tech is hostile. It interrupts, distracts, and degrades the experience. adspace is an experiment in the opposite: &lt;strong&gt;advertising as ambient art&lt;/strong&gt;. If someone is going to wait 5 seconds for a redirect anyway, that time can be either empty and frustrating, or filled with something worth looking at.&lt;/p&gt;

&lt;p&gt;The Hillscape Journey template embodies this — a gentle landscape, a slow counter, no demands on the user. Just a moment of visual calm before the next page loads.&lt;/p&gt;

&lt;h2 id=&quot;why-this-matters&quot;&gt;Why This Matters&lt;/h2&gt;

&lt;p&gt;Redirect pages are universally hated because they’re universally bad. A blank screen with “please wait.” A spinning loader that gives no indication of progress. Or worst of all, a wall of aggressive ads that make you hunt for the “skip” button.&lt;/p&gt;

&lt;p&gt;adspace proposes: what if the redirect page was the best-designed page in the entire flow? What if people &lt;em&gt;remembered&lt;/em&gt; your redirect page? What if the ad was so well-crafted that users shared screenshots of it?&lt;/p&gt;

&lt;p&gt;That’s the experiment. Currently at template #1, 11.20 seconds, and counting.&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;https://shel.sh/projects/adspace/templates/1/&quot;&gt;View the template&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;https://github.com/CommanderTurtle/CommanderTurtle.github.io/tree/master/projects/adspace&quot;&gt;Project directory&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

    </content>
    
    <category term="side-project" />
    
    <category term="adspace" />
    
    <category term="redirect" />
    
    <category term="templates" />
    
    <category term="future" />
    
    <summary type="html">
      Every project starts with a template. A blank canvas. A index.html and a dream. adspace is currently just that — a single template, a timer counting up from 11.20 seconds, and a name: Hillscape Journey.

    </summary>
  </entry>
  
  <entry>
    <title type="html">macrohard: Not Your Average Macro Extension</title>
    <link href="https://shel.sh/blog/2025-10-15-macrohard/" rel="alternate" type="text/html" />
    <published>2025-10-15T10:00:00+00:00</published>
    <updated>2025-10-15T10:00:00+00:00</updated>
    <id>https://shel.sh/blog/2025-10-15-macrohard/</id>
    <author>
      <name>CommanderTurtle</name>
    </author>
    <content type="html" xml:base="https://shel.sh/blog/2025-10-15-macrohard/">
      &lt;p&gt;Task scheduling and macro automation on Windows has a reputation. The built-in Task Scheduler is powerful but opaque. AutoHotkey is flexible but its scripting language shows its age. Commercial tools are either enterprise-expensive or consumer-limited. And none of them give you a visual node editor where you can wire together IF/THEN/ELSE logic by dragging connections between blocks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;macrohard&lt;/strong&gt; does. It’s a complete rewrite and extension of Tasket++ with a ComfyUI-style node editor, checkpoint-based flow control, and a typed HTTP trigger daemon — turning repetitive desktop tasks into visual, composable workflows.&lt;/p&gt;

&lt;h2 id=&quot;what-it-is&quot;&gt;What It Is&lt;/h2&gt;

&lt;p&gt;macrohard is a Visual Workflow Automation Platform for Tasket++. It extends &lt;a href=&quot;https://github.com/AmirHammouteneEI/ScheduledPasteAndKeys&quot;&gt;Amir Hammoutene’s ScheduledPasteAndKeys&lt;/a&gt; (tested against v1.8) with three integrated components:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Component&lt;/th&gt;
      &lt;th&gt;Stack&lt;/th&gt;
      &lt;th&gt;Purpose&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Daemon&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;C++&lt;/td&gt;
      &lt;td&gt;HTTP-triggered task execution engine&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Workflow Editor&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;React + React Flow&lt;/td&gt;
      &lt;td&gt;Visual node-based workflow design&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;PI Agent&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;TypeScript&lt;/td&gt;
      &lt;td&gt;LLM-integrated automation agent&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;the-architecture&quot;&gt;The Architecture&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;+---------------+     HTTP      +-----------------------+
| Android/Tasker| &amp;lt;-----------&amp;gt; |  tasket-httpd.exe     |
| Home Assistant|   port 7777   |  (C++ daemon)         |
| curl/any      |               |  - TaskExecutor*      |
|               |               |  - TaskRegistry       |
|               |               |  - cpp-httplib        |
+---------------+               +----------+------------+
                                           |
                                           | loads .scht
                                           v
                                +-----------------------+
                                |  Tasket++ Engine      |
                                |  (PasteAction,        |
                                |   KeysSequenceAction, |
                                |   SystemCommands,     |
                                |   CursorMovements,    |
                                |   RunningOtherTask)   |
                                +-----------------------+

+---------------+     HTTP      +-----------------------+
| Browser       | &amp;lt;-----------&amp;gt; |  Workflow Editor      |
| localhost:3000|               |  (React + React Flow) |
|               |               |  - Node editor        |
|               |               |  - Checkpoint editor  |
|               |               |  - Macro library      |
|               |               |  - Inline grid edit   |
|               |               |  - Copy/paste/delete  |
+---------------+               +----------+------------+
                                           |
                                           | JSON workflow
                                           v
                                +-----------------------+
                                |  PI Agent Extension   |
                                |  (@pi-extensions/     |
                                |   pi-tasket-http)     |
                                +-----------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;the-c-daemon&quot;&gt;The C++ Daemon&lt;/h2&gt;

&lt;p&gt;The daemon replaces Tasket++’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TaskThread&lt;/code&gt; with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TaskExecutor&lt;/code&gt; class (avoids the private &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;copyActionsList()&lt;/code&gt; API). It uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cpp-httplib&lt;/code&gt; for HTTP serving and listens on port 7777 by default. Any HTTP client can trigger tasks — curl, Home Assistant, Tasker on Android, or the Workflow Editor itself.&lt;/p&gt;

&lt;p&gt;The daemon loads &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.scht&lt;/code&gt; macro files from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;saved_tasks/&lt;/code&gt;, maintains a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TaskRegistry&lt;/code&gt; of available entrypoints, and executes tasks through the Tasket++ engine. Actions include: paste operations, key sequences, system commands, cursor movements, and running other tasks as subroutines.&lt;/p&gt;

&lt;h2 id=&quot;the-workflow-editor&quot;&gt;The Workflow Editor&lt;/h2&gt;

&lt;p&gt;Built with React and React Flow, the editor provides a ComfyUI-inspired canvas where workflows are graphs, not scripts. Five custom node types:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;EntrypointNode&lt;/strong&gt; — Inline value editing (string, bool, float)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;DataGridNode&lt;/strong&gt; — Inline 3×3 cell editing for tabular data&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;CheckpointNode&lt;/strong&gt; — IF/THEN/ELSE branching logic&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;MacroNode&lt;/strong&gt; — References saved &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.scht&lt;/code&gt; macro files&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;OutputNode&lt;/strong&gt; — Terminal actions and result capture&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The checkpoint system is the killer feature. Traditional macro tools run linearly. macrohard’s checkpoints let you branch: &lt;em&gt;IF&lt;/em&gt; window title contains “Error”, &lt;em&gt;THEN&lt;/em&gt; click dismiss, &lt;em&gt;ELSE&lt;/em&gt; proceed. The graph traversal engine in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;workflowEngine.ts&lt;/code&gt; handles the full execution flow with cycle detection and subgraph isolation.&lt;/p&gt;

&lt;p&gt;Keyboard shortcuts, copy/paste/delete, and a macro library with drag-and-drop placement make the editor feel like a native application. Zustand manages state with a full undo/redo stack.&lt;/p&gt;

&lt;h2 id=&quot;the-pi-agent&quot;&gt;The PI Agent&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@pi-extensions/pi-tasket-http&lt;/code&gt; TypeScript package provides 6 PI (Programmable Intelligence) tool registrations that let an LLM agent interact with the macrohard system. The agent can: list available tasks, trigger execution, read grid data, modify entrypoints, and query execution status — all through typed HTTP calls to the daemon.&lt;/p&gt;

&lt;p&gt;This means you can tell an LLM “run my morning setup routine” and it will: query the available tasks, find &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;morning-setup.scht&lt;/code&gt;, trigger it via HTTP, and report back what happened.&lt;/p&gt;

&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;/h2&gt;

&lt;p&gt;One PowerShell command as Administrator:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;clone&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;https://github.com/CommanderTurtle/macrohard&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;macrohard&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Also clone the original Tasket++ source (required for daemon build)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;clone&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;https://github.com/AmirHammouteneEI/ScheduledPasteAndKeys.git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;original&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Apply the one-line patch&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;daemon\patches\Task.h.patch&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;original\&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;original&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Task.h.patch&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Install everything&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;\install.ps1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-QtPath&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;C:\Qt\6.9.3\mingw_64&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Prerequisites: Qt 6.9.3 (MinGW or MSVC), CMake 3.16+, bun.&lt;/p&gt;

&lt;p&gt;Run everything with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.\run.ps1&lt;/code&gt; — starts both the daemon and workflow editor. Or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.\run.ps1 daemon&lt;/code&gt; for daemon-only.&lt;/p&gt;

&lt;h2 id=&quot;repository-layout&quot;&gt;Repository Layout&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;macrohard/
├── README.md
├── install.ps1              # One-click Windows installer
├── run.ps1                  # Runtime launcher
├── .tasketconfig.json       # Generated config
│
├── original/                # Tasket++ source (patched)
│
├── daemon/                  # C++ HTTP daemon
│   ├── CMakeLists.txt
│   ├── patches/Task.h.patch
│   ├── include/             # Headers
│   ├── src/                 # C++ sources
│   ├── saved_tasks/         # .scht macro files
│   └── test/                # Python API validation (63 tests)
│
├── workflows/               # React workflow editor
│   └── src/
│       ├── types/workflow.ts
│       ├── engine/checkpoint.ts
│       ├── engine/workflowEngine.ts
│       ├── stores/workflowStore.ts
│       └── components/nodes/
│
├── pi-extension/            # PI Agent
│   └── src/
│       ├── client/tasket-client.ts
│       ├── tools/tasket-http.ts
│       └── skills/
│
└── docs/
    ├── INSTALL.md
    ├── API.md
    ├── PI_AGENT.md
    └── ARCHITECTURE.md
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;64% C++, 29.8% TypeScript, 2.4% PowerShell. GPL-3.0 licensed.&lt;/p&gt;

&lt;p&gt;macrohard turns the tedious into the visual. If ComfyUI made ML model pipelines tangible, macrohard does the same for desktop automation.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/CommanderTurtle/macrohard&quot;&gt;github.com/CommanderTurtle/macrohard&lt;/a&gt;&lt;/p&gt;

    </content>
    
    <category term="project" />
    
    <category term="automation" />
    
    <category term="macros" />
    
    <category term="tasket" />
    
    <category term="cpp" />
    
    <category term="react" />
    
    <category term="typescript" />
    
    <summary type="html">
      Task scheduling and macro automation on Windows has a reputation. The built-in Task Scheduler is powerful but opaque. AutoHotkey is flexible but its scripting language shows its age. Commercial tools are either enterprise-expensive or consumer-limited. And none of them give you a visual node editor where you can wire together...
    </summary>
  </entry>
  
  <entry>
    <title type="html">Deep Dive: sHEL&apos;s Schema System</title>
    <link href="https://shel.sh/blog/2025-09-01-shel-schema-deep-dive/" rel="alternate" type="text/html" />
    <published>2025-09-01T14:00:00+00:00</published>
    <updated>2025-09-01T14:00:00+00:00</updated>
    <id>https://shel.sh/blog/2025-09-01-shel-schema-deep-dive/</id>
    <author>
      <name>sHEL Team</name>
    </author>
    <content type="html" xml:base="https://shel.sh/blog/2025-09-01-shel-schema-deep-dive/">
      &lt;p&gt;One of sHEL’s most powerful features is its schema system. In this post, we’ll explore how sHEL schemas work and why they’re different from traditional approaches.&lt;/p&gt;

&lt;h2 id=&quot;schema-as-contract&quot;&gt;Schema as Contract&lt;/h2&gt;

&lt;p&gt;In sHEL, a schema isn’t just validation — it’s a &lt;strong&gt;contract&lt;/strong&gt; between producer and consumer. When you define a schema, you’re specifying:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The exact structure of the data&lt;/li&gt;
  &lt;li&gt;Literal constraints (no injection possible)&lt;/li&gt;
  &lt;li&gt;Transformation rules&lt;/li&gt;
  &lt;li&gt;Pipeline compatibility&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;defining-schemas&quot;&gt;Defining Schemas&lt;/h2&gt;

&lt;p&gt;sHEL schemas are written in sHEL’s own schema definition language:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-shel&quot;&gt;schema User {
  id: uuid,
  name: literal&amp;lt;string&amp;gt;,
  email: literal&amp;lt;string&amp;gt;,
  role: enum(&quot;admin&quot;, &quot;user&quot;, &quot;guest&quot;),
  created_at: timestamp
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;literal&amp;lt;&amp;gt;&lt;/code&gt; wrapper — this is the key. Any data passing through this schema is guaranteed to be treated as a literal value, never as executable code.&lt;/p&gt;

&lt;h2 id=&quot;validation-pipeline&quot;&gt;Validation Pipeline&lt;/h2&gt;

&lt;p&gt;Schemas integrate directly into pipelines:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Validate incoming data against schema&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;users.json | shel validate &lt;span class=&quot;nt&quot;&gt;--schema&lt;/span&gt; User | shel transform &lt;span class=&quot;nt&quot;&gt;--to&lt;/span&gt; csv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If validation fails, sHEL provides detailed error messages with line numbers and context.&lt;/p&gt;

&lt;h2 id=&quot;performance&quot;&gt;Performance&lt;/h2&gt;

&lt;p&gt;Schema validation in sHEL is fast. Really fast. Our benchmarks show:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Dataset Size&lt;/th&gt;
      &lt;th&gt;Validation Time&lt;/th&gt;
      &lt;th&gt;Memory Usage&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;1K records&lt;/td&gt;
      &lt;td&gt;0.3ms&lt;/td&gt;
      &lt;td&gt;2MB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;100K records&lt;/td&gt;
      &lt;td&gt;12ms&lt;/td&gt;
      &lt;td&gt;8MB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;10M records&lt;/td&gt;
      &lt;td&gt;890ms&lt;/td&gt;
      &lt;td&gt;128MB&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;next-steps&quot;&gt;Next Steps&lt;/h2&gt;

&lt;p&gt;Read the &lt;a href=&quot;https://docs.shel.sh/schema-reference/&quot;&gt;full schema documentation&lt;/a&gt; for advanced features like conditional validation, custom types, and schema composition.&lt;/p&gt;

&lt;p&gt;Have questions? Join us on &lt;a href=&quot;https://slack.shel.sh&quot;&gt;Slack&lt;/a&gt; or open a &lt;a href=&quot;https://github.com/CommanderTurtle/docs-pages/discussions&quot;&gt;GitHub discussion&lt;/a&gt;.&lt;/p&gt;

    </content>
    
    <category term="technical" />
    
    <category term="schema" />
    
    <category term="deep-dive" />
    
    <summary type="html">
      One of sHEL’s most powerful features is its schema system. In this post, we’ll explore how sHEL schemas work and why they’re different from traditional approaches.

    </summary>
  </entry>
  
  <entry>
    <title type="html">Introducing sHEL: A New Kind of Data Substrate</title>
    <link href="https://shel.sh/blog/2025-08-15-introducing-shel/" rel="alternate" type="text/html" />
    <published>2025-08-15T09:00:00+00:00</published>
    <updated>2025-08-15T09:00:00+00:00</updated>
    <id>https://shel.sh/blog/2025-08-15-introducing-shel/</id>
    <author>
      <name>sHEL Team</name>
    </author>
    <content type="html" xml:base="https://shel.sh/blog/2025-08-15-introducing-shel/">
      &lt;p&gt;Today we’re excited to introduce &lt;strong&gt;sHEL&lt;/strong&gt; — a volatile, literal-safe, automation-friendly data substrate that brings the reliability of a turtle shell to your data pipelines.&lt;/p&gt;

&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;/h2&gt;

&lt;p&gt;Modern data interchange is fragile. JSON, YAML, TOML — they all suffer from the same fundamental issues:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Injection vulnerabilities&lt;/strong&gt; — unescaped strings open the door to injection attacks&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Parsing ambiguity&lt;/strong&gt; — subtle syntax differences break parsers across implementations&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tooling fragmentation&lt;/strong&gt; — every format needs its own toolchain&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;our-solution&quot;&gt;Our Solution&lt;/h2&gt;

&lt;p&gt;sHEL takes a different approach. Inspired by the Unix philosophy, sHEL treats data as a stream of literal-safe tokens that flow through composable pipelines.&lt;/p&gt;

&lt;h3 id=&quot;key-design-principles&quot;&gt;Key Design Principles&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Literal-Safe by Default&lt;/strong&gt; — Data is always treated as literals. No escaping, no injection.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Volatile Operations&lt;/strong&gt; — Fast, in-memory processing with optional persistence.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Automation-First&lt;/strong&gt; — Structured output designed for machine consumption.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;quick-example&quot;&gt;Quick Example&lt;/h2&gt;

&lt;p&gt;Here’s what sHEL looks like in practice:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Parse a log file and extract structured data&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;app.log | shel parse &lt;span class=&quot;nt&quot;&gt;--format&lt;/span&gt; json | jq &lt;span class=&quot;s1&quot;&gt;&apos;.level == &quot;ERROR&quot;&apos;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# The output is always predictable, always safe&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;timestamp&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;2025-08-15T09:00:00Z&quot;&lt;/span&gt;,
  &lt;span class=&quot;s2&quot;&gt;&quot;level&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;ERROR&quot;&lt;/span&gt;,
  &lt;span class=&quot;s2&quot;&gt;&quot;message&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;Connection timeout&quot;&lt;/span&gt;,
  &lt;span class=&quot;s2&quot;&gt;&quot;literal&quot;&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;whats-next&quot;&gt;What’s Next&lt;/h2&gt;

&lt;p&gt;This is just the beginning. We’re building:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A rich plugin ecosystem&lt;/li&gt;
  &lt;li&gt;IDE integrations&lt;/li&gt;
  &lt;li&gt;Visual pipeline builders&lt;/li&gt;
  &lt;li&gt;Enterprise features&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;https://docs.shel.sh/getting-started/&quot;&gt;Get started today&lt;/a&gt; and let us know what you think!&lt;/p&gt;

    </content>
    
    <category term="announcement" />
    
    <category term="introduction" />
    
    <summary type="html">
      Today we’re excited to introduce sHEL — a volatile, literal-safe, automation-friendly data substrate that brings the reliability of a turtle shell to your data pipelines.

    </summary>
  </entry>
  
  <entry>
    <title type="html">countku: Expert Level Counting</title>
    <link href="https://shel.sh/blog/2025-07-15-countku-side-project/" rel="alternate" type="text/html" />
    <published>2025-07-15T10:00:00+00:00</published>
    <updated>2025-07-15T10:00:00+00:00</updated>
    <id>https://shel.sh/blog/2025-07-15-countku-side-project/</id>
    <author>
      <name>CommanderTurtle</name>
    </author>
    <content type="html" xml:base="https://shel.sh/blog/2025-07-15-countku-side-project/">
      &lt;p&gt;It started with a Discord thread. I was playing with two bots — a counting bot and Haikubot — and wondered: what if counting could be poetry? What if every number you expressed had to fit the rigid 5-7-5 structure of a haiku?&lt;/p&gt;

&lt;p&gt;That question became &lt;strong&gt;countku&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;the-origin&quot;&gt;The Origin&lt;/h2&gt;

&lt;p&gt;I posted the original concept to Reddit (&lt;a href=&quot;https://www.reddit.com/r/haikusbot/comments/1p1aq85/countku_expert_level_counting/&quot;&gt;r/haikusbot&lt;/a&gt;) with a simple challenge: get both the counting bot and Haikubot to validate the same message simultaneously. The screenshot tells the whole story — me typing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;21+1.1-1.1+1-1&lt;/code&gt;, the counting bot accepting it as valid (it evaluates to 22), and Haikubot transcribing it into perfect 5-7-5 form:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Twenty two, plus one&lt;br /&gt;
point one, minus one point one,&lt;br /&gt;
plus one, minus one&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then I pushed further. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1-3.000+1+1+1&lt;/code&gt; — evaluating to 1, the next number in the count — became:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;One minus three point&lt;br /&gt;
zero zero zero, plus&lt;br /&gt;
one, plus one, plus one&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The bots agreed. The game was born.&lt;/p&gt;

&lt;h2 id=&quot;what-countku-actually-is&quot;&gt;What Countku Actually Is&lt;/h2&gt;

&lt;p&gt;Countku is a base-ten number system more convoluted than all prime numbers. The core premise: &lt;strong&gt;express any mathematical result as a haiku&lt;/strong&gt; (5-7-5 syllables) where the math actually evaluates to the intended number.&lt;/p&gt;

&lt;p&gt;It isn’t just wordplay — it’s a genuine constraint system with documented rules:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;5-7-5 syllable structure&lt;/strong&gt; is strictly enforced&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;No cutting words across line breaks&lt;/strong&gt; — “ze-“ on line 1 and “ro” on line 2 is illegal&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Decimal is always “point”&lt;/strong&gt; — proper mathematical English&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Zero variants&lt;/strong&gt;: “zero” (2 syl), “zed” (1 syl), or “oh” (1 syl) — pick one per thread and stick to it&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;“Type shit” and two-syllable memes&lt;/strong&gt; are legal BS words — they pad syllables without affecting the math&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Words must finish at the end of a Ku&lt;/strong&gt; — no “one point zero Oh” cheating that circumvents the memory challenge&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The O’Leary license applies: I don’t intend to monetize it, but if you sell countku or a variation, I ask for 1 satoshi per API call. You can wrap the shaves of pennies in envelopes and mail them to me.&lt;/p&gt;

&lt;h2 id=&quot;the-documentation&quot;&gt;The Documentation&lt;/h2&gt;

&lt;p&gt;What started as a joke grew into a fully documented system. I built out comprehensive docs across three files:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://shel.sh/projects/1.md&quot;&gt;1.md — The Rulebook&lt;/a&gt;&lt;/strong&gt; documents every substring in the countku lexicon with full grammatical metadata — syllable count, whether it’s a base number, scale word, math operator, preposition, or passive/active participle. There are 127 indexed substrings from “one” to “influence,” each with their bit flags for the parsing engine. Five complete data tables cover: the substring database, base glossary (Zero through Highers), full operators matrix (46+ distinct operations), prepositional/auxiliary combinations, and modifier/ordinal definitions including Latin and Greek systematic forms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://shel.sh/projects/2.md&quot;&gt;2.md — The Changelog&lt;/a&gt;&lt;/strong&gt; tracks the engine evolution from v1.0 through v7.4, including the deferred emission engine, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$P_Action&lt;/code&gt; vs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$P_Passiv&lt;/code&gt; prepositional semantics (does “using the power of” wrap the entire expression or just the last term?), logarithm system overhaul, trig parenthesis fixes, and noun operator preposition gating.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://shel.sh/projects/3.md&quot;&gt;3.md — The Engine Reference&lt;/a&gt;&lt;/strong&gt; is the complete technical manual for the JavaScript conversion engine, covering the tokenization pipeline, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;convertTokens()&lt;/code&gt; state machine, the fallover syllable system for automatic 5-7-5 line detection, and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CountkuConverter&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HaikuValidator&lt;/code&gt; class architectures.&lt;/p&gt;

&lt;h2 id=&quot;the-math-engine&quot;&gt;The Math Engine&lt;/h2&gt;

&lt;p&gt;The JavaScript engine converts English word phrases into executable math expressions. Some examples from the docs:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Input&lt;/th&gt;
      &lt;th&gt;Expression&lt;/th&gt;
      &lt;th&gt;Result&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;one plus two&lt;/td&gt;
      &lt;td&gt;1+2&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;the square root of sixteen&lt;/td&gt;
      &lt;td&gt;Math.sqrt(16)&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;five to the sixtieth&lt;/td&gt;
      &lt;td&gt;(5)**60&lt;/td&gt;
      &lt;td&gt;huge&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;the sine of zero plus the log of one and two&lt;/td&gt;
      &lt;td&gt;Math.sin(0)+Math.log(1)+2&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;five plus three using the power of two&lt;/td&gt;
      &lt;td&gt;(5+3)**2&lt;/td&gt;
      &lt;td&gt;64&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;five plus three under the power of two&lt;/td&gt;
      &lt;td&gt;5+(3)**2&lt;/td&gt;
      &lt;td&gt;14&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$P_Action&lt;/code&gt; vs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$P_Passiv&lt;/code&gt; distinction is the clever part. “Using” wraps the entire preceding expression in parentheses before applying the power. “Under” wraps only the immediately preceding term. Same words, different math.&lt;/p&gt;

&lt;h2 id=&quot;sakura-count-ninja--the-game&quot;&gt;Sakura Count Ninja — The Game&lt;/h2&gt;

&lt;p&gt;All of this became &lt;strong&gt;&lt;a href=&quot;https://shel.sh/projects/&quot;&gt;Sakura Count Ninja&lt;/a&gt;&lt;/strong&gt;, a browser-based counting game with four modes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Normal&lt;/strong&gt; — Base 10 JS math expression evaluation&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Hard&lt;/strong&gt; — Base 2, results shown in binary&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;WTF&lt;/strong&gt; — Base 16, results shown in hex&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Countku&lt;/strong&gt; — English word haikus validated for 5-7-5 structure then converted to math&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The game features ninja animations (idle, run, jump), streak tracking, sound effects, and an end-game dashboard. The countku mode runs the full &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HaikuValidator&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CountkuConverter&lt;/code&gt; dual-check system — both the syllable structure AND the math must be valid.&lt;/p&gt;

&lt;h2 id=&quot;the-future-a-js-math-library&quot;&gt;The Future: A JS Math Library&lt;/h2&gt;

&lt;p&gt;The long-term vision is extracting the countku engine into a proper JavaScript math library that &lt;strong&gt;invalidates non-haiku math and forces haiku-safe operations&lt;/strong&gt;. Imagine a math library where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eval(&quot;one plus two&quot;)&lt;/code&gt; works but &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eval(&quot;1 + 2&quot;)&lt;/code&gt; doesn’t — where every computation must pass through the linguistic layer. Where the constraint isn’t a bug, it’s the feature.&lt;/p&gt;

&lt;p&gt;The documentation is already structured like a language specification. The engine handles ordinals, fractions, trigonometry, logarithms, roots, powers, passive/active voice distinctions, and noise-token stripping. Turning that into a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;countku-math&lt;/code&gt; npm package is the natural next step.&lt;/p&gt;

&lt;p&gt;Play the game at &lt;a href=&quot;https://shel.sh/projects/&quot;&gt;shel.sh/projects&lt;/a&gt;. Read the full docs at &lt;a href=&quot;https://shel.sh/projects/1.md&quot;&gt;shel.sh/projects/1.md&lt;/a&gt;, &lt;a href=&quot;https://shel.sh/projects/2.md&quot;&gt;2.md&lt;/a&gt;, and &lt;a href=&quot;https://shel.sh/projects/3.md&quot;&gt;3.md&lt;/a&gt;. And remember: numbers are nature.&lt;/p&gt;

    </content>
    
    <category term="side-project" />
    
    <category term="math" />
    
    <category term="haiku" />
    
    <category term="game" />
    
    <category term="js" />
    
    <summary type="html">
      It started with a Discord thread. I was playing with two bots — a counting bot and Haikubot — and wondered: what if counting could be poetry? What if every number you expressed had to fit the rigid 5-7-5 structure of a haiku?

    </summary>
  </entry>
  
  <entry>
    <title type="html">Turtle Protect: An Independent Shelling Company</title>
    <link href="https://shel.sh/blog/2025-06-20-captcha-side-project/" rel="alternate" type="text/html" />
    <published>2025-06-20T14:00:00+00:00</published>
    <updated>2025-06-20T14:00:00+00:00</updated>
    <id>https://shel.sh/blog/2025-06-20-captcha-side-project/</id>
    <author>
      <name>CommanderTurtle</name>
    </author>
    <content type="html" xml:base="https://shel.sh/blog/2025-06-20-captcha-side-project/">
      &lt;p&gt;Most CAPTCHA solutions ask you to replace your entire page architecture. ReCAPTCHA wants its script in your head, its badge on your footer, and its external API calls on every form submission. hCaptcha isn’t much different. They’re effective but heavy — external dependencies, user tracking, significant page weight, and a UX that treats every visitor as a suspected bot first and a human second.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Turtle Protect&lt;/strong&gt; takes a different approach. It’s a drop-in CAPTCHA overlay — you don’t replace anything. Think of it like adding three ingredients to a recipe you already have.&lt;/p&gt;

&lt;h2 id=&quot;the-philosophy&quot;&gt;The Philosophy&lt;/h2&gt;

&lt;p&gt;The project tagline is &lt;em&gt;“an independent shelling company”&lt;/em&gt; — a play on words that captures the ethos. Independent: no external API calls, no third-party dependencies, no tracking. Shelling: the protective outer layer. Company: it just keeps you company on your existing page, no drama.&lt;/p&gt;

&lt;p&gt;The core insight is that most sites don’t need fortress-level bot protection. They need a sensible gate that keeps out automated abuse without annoying legitimate users or loading external scripts.&lt;/p&gt;

&lt;h2 id=&quot;how-it-works&quot;&gt;How It Works&lt;/h2&gt;

&lt;p&gt;The implementation is intentionally minimal. You add three things to your existing HTML:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;A small JavaScript snippet that loads the overlay&lt;/li&gt;
  &lt;li&gt;A button trigger element (can be your existing submit button)&lt;/li&gt;
  &lt;li&gt;A lightweight CSS file for the overlay styling&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When the user clicks the protected button, an overlay appears with the CAPTCHA challenge. Upon successful completion, the overlay dismisses and the original form submission proceeds normally. The existing page logic doesn’t change — Turtle Protect just intercepts, verifies, and releases.&lt;/p&gt;

&lt;p&gt;The docs show the full integration pattern:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Your existing stuff like title, other CSS --&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;stylesheet&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;turtle-protect.css&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Your existing content --&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Welcome to My Site&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;login-btn&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Login&lt;span class=&quot;nt&quot;&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

  &lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;turtle-protect.js&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;TurtleProtect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;guard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;#login-btn&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;onSuccess&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Your original login logic here&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;the-sickh-captcha&quot;&gt;The “sickh” CAPTCHA&lt;/h2&gt;

&lt;p&gt;The project includes a reference implementation called the &lt;strong&gt;“sickh” CAPTCHA&lt;/strong&gt; (a stylized spelling of “sick” — as in, &lt;em&gt;that’s sick&lt;/em&gt;). It’s an anti-bot button that’s easily placeable anywhere on an existing page. The overlay pattern means it works with vanilla HTML, React, Vue, or any framework — since it operates at the DOM level, your framework doesn’t need to know it exists.&lt;/p&gt;

&lt;p&gt;The full implementation guide with the overlay diagram and step-by-step integration is in the project docs:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Project page&lt;/strong&gt;: &lt;a href=&quot;https://shel.sh/projects/captcha&quot;&gt;shel.sh/projects/captcha&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Documentation&lt;/strong&gt;: &lt;a href=&quot;https://shel.sh/projects/captcha/docs&quot;&gt;shel.sh/projects/captcha/docs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Raw docs&lt;/strong&gt;: &lt;a href=&quot;https://shel.sh/projects/captcha/docs/raw.txt&quot;&gt;shel.sh/projects/captcha/docs/raw.txt&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;why-not-just-use-recaptcha&quot;&gt;Why Not Just Use reCAPTCHA?&lt;/h2&gt;

&lt;p&gt;Three reasons:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Privacy&lt;/strong&gt;: Turtle Protect makes zero external network requests. No Google servers, no tracking cookies, no behavioral profiling. Your users’ interactions stay on your domain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weight&lt;/strong&gt;: The entire library is under 5KB gzipped. reCAPTCHA’s script alone is ~150KB, plus the badge, plus the verification request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Control&lt;/strong&gt;: You own the challenge generation, the validation logic, and the UX. Want to change the challenge type? It’s your code. Want to customize the styling? It’s your CSS. No API keys to manage, no quota limits, no terms-of-service changes.&lt;/p&gt;

&lt;h2 id=&quot;current-status&quot;&gt;Current Status&lt;/h2&gt;

&lt;p&gt;Turtle Protect is functional and documented. The overlay implementation works across modern browsers. The project is actively maintained as a side project — the kind of tool you build because you need it yourself, then share because others probably need it too.&lt;/p&gt;

&lt;p&gt;The captcha philosophy mirrors the broader sHEL approach: literal-safe, dependency-light, and respectful of the user. No external calls. No hidden tracking. Just a simple shell that keeps the bots out and the humans flowing through.&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;https://shel.sh/projects/captcha/docs&quot;&gt;View the docs&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;https://shel.sh/projects/captcha&quot;&gt;See it in action&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

    </content>
    
    <category term="side-project" />
    
    <category term="security" />
    
    <category term="web" />
    
    <category term="captcha" />
    
    <category term="anti-bot" />
    
    <summary type="html">
      Most CAPTCHA solutions ask you to replace your entire page architecture. ReCAPTCHA wants its script in your head, its badge on your footer, and its external API calls on every form submission. hCaptcha isn’t much different. They’re effective but heavy — external dependencies, user tracking, significant page weight, and a...
    </summary>
  </entry>
  
  <entry>
    <title type="html">fsharp-zensical: F# Meets Material for MkDocs</title>
    <link href="https://shel.sh/blog/2025-05-10-fsharp-zensical/" rel="alternate" type="text/html" />
    <published>2025-05-10T09:00:00+00:00</published>
    <updated>2025-05-10T09:00:00+00:00</updated>
    <id>https://shel.sh/blog/2025-05-10-fsharp-zensical/</id>
    <author>
      <name>CommanderTurtle</name>
    </author>
    <content type="html" xml:base="https://shel.sh/blog/2025-05-10-fsharp-zensical/">
      &lt;p&gt;Documentation sites have a familiar shape: Markdown files, a static site generator, some theme customization, and a CI pipeline that builds on push. Most teams reach for MkDocs (with Material), Docusaurus, or Hugo. But what if your docs need to integrate with F# code? What if you want type-safe HTML generation, a Giraffe ViewEngine DSL, and the full Zensical (Material for MkDocs) feature set — admonitions, tabs, Mermaid diagrams — all while keeping the ability to drop raw HTML into the pipeline?&lt;/p&gt;

&lt;p&gt;That’s the question &lt;strong&gt;fsharp-zensical&lt;/strong&gt; answers.&lt;/p&gt;

&lt;h2 id=&quot;what-it-is&quot;&gt;What It Is&lt;/h2&gt;

&lt;p&gt;fsharp-zensical is a complete &lt;strong&gt;F# → GitHub Pages&lt;/strong&gt; workflow using Zensical (Material for MkDocs) with full F# and DSL support. It’s designed as a cross-repo pages orchestrator: each site folder (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main/&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docs/&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;app/&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blog/&lt;/code&gt;) builds locally, and GitHub Actions push artifacts to entirely separate repositories using token-authenticated git. Think of it as a monorepo docs system where each subdomain gets its own repo and its own deployment pipeline.&lt;/p&gt;

&lt;p&gt;The project is a continuation of the original &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fsharp-material&lt;/code&gt; work, restructured for maintainability and expanded with new features.&lt;/p&gt;

&lt;h2 id=&quot;architecture-overview&quot;&gt;Architecture Overview&lt;/h2&gt;

&lt;p&gt;The system is organized around &lt;strong&gt;site folders&lt;/strong&gt;, each representing a distinct documentation property:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Folder&lt;/th&gt;
      &lt;th&gt;Purpose&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main/&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Primary landing page&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docs/&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Technical documentation&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;app/&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Application guides&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blog/&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Blog posts and announcements&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Each folder contains its own F# source files, markdown content, and build configuration. The shared infrastructure lives at the root: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Directory.Build.props&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GenerateConfig.fsx&lt;/code&gt;, and the GitHub Actions workflows in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.github/&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;two-page-types&quot;&gt;Two Page Types&lt;/h2&gt;

&lt;p&gt;The system supports two distinct page construction patterns:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Standalone HTML (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index.fs&lt;/code&gt;)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For pages with complex JavaScript interactivity or heavy F# logic — the page is built entirely with Giraffe ViewEngine DSL:&lt;/p&gt;

&lt;div class=&quot;language-fsharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Blog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;MyPage&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Giraffe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ViewEngine&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;My Page&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;h1&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Hello from F#!&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;script&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;rawText&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&quot;
                console.log(&quot;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Hello&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;);
                &quot;&quot;&quot;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;RenderView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;AsString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;htmlDocument&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;2. F# with Markdown (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;indexmd.fs&lt;/code&gt;)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For documentation-heavy pages that need Zensical features — the F# generates components that get embedded in markdown frontmatter:&lt;/p&gt;

&lt;div class=&quot;language-fsharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Docs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;MyPage&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Giraffe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ViewEngine&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;card&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;card&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;h3&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Welcome&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Type-safe components!&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;RenderView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;AsString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;htmlNode&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&quot;
---
title: My Page
---
# My Page
{card}
!!! tip &quot;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Zensical&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Features&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;
    Admonitions, tabs, Mermaid diagrams all work!
&quot;&quot;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The markdown passes through Zensical (Material for MkDocs), so you get the full feature set: admonitions, code annotation, content tabs, Mermaid diagrams, and the complete visual theme.&lt;/p&gt;

&lt;h2 id=&quot;the-html-to-dsl-converter&quot;&gt;The HTML-to-DSL Converter&lt;/h2&gt;

&lt;p&gt;One of the most practical features is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/throw/&lt;/code&gt; folder. Drop any HTML file in there, push to GitHub, and a workflow automatically:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Parses the HTML element-by-element&lt;/li&gt;
  &lt;li&gt;Generates &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pages/my-page/index.fs&lt;/code&gt; with proper Giraffe ViewEngine DSL&lt;/li&gt;
  &lt;li&gt;Renders the output HTML for deployment&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This means designers can work in raw HTML (or export from Figma, or paste from Tailwind templates), and the system converts it to type-safe F# DSL automatically. For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;script&amp;gt;&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;style&amp;gt;&lt;/code&gt; blocks, the converter uses triple-quoted strings — no escaping needed.&lt;/p&gt;

&lt;p&gt;Input HTML:&lt;/p&gt;
&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;container&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello World&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Welcome to my site&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Output F#:&lt;/p&gt;
&lt;div class=&quot;language-fsharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Views&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Giraffe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ViewEngine&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;container&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;h1&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Hello World&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Welcome to my site&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;shared-modules&quot;&gt;Shared Modules&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/&lt;/code&gt; folder contains reusable components: AST manipulation utilities, tree walking functions, and shared Giraffe view helpers. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blog/&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;documentation/&lt;/code&gt; folders contain the actual content. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pages/&lt;/code&gt; folder holds generated output from the HTML-to-DSL converter.&lt;/p&gt;

&lt;h2 id=&quot;github-actions-pipeline&quot;&gt;GitHub Actions Pipeline&lt;/h2&gt;

&lt;p&gt;The CI/CD setup is token-based. GitHub Actions build each site folder locally, then push the generated output to separate repositories — one per subdomain. This means &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docs.yoursite.com&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blog.yoursite.com&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;app.yoursite.com&lt;/code&gt; can all originate from the same monorepo but deploy independently.&lt;/p&gt;

&lt;h2 id=&quot;why-f-for-documentation&quot;&gt;Why F# for Documentation?&lt;/h2&gt;

&lt;p&gt;The usual objection: “Why not just use plain Markdown?” The answer is type safety and composability. When your documentation includes generated API references, version matrices, or dynamic content pulled from other sources, having a full programming language at your disposal — with compile-time checking — beats template string substitution every time.&lt;/p&gt;

&lt;p&gt;The Giraffe ViewEngine DSL is particularly well-suited for this because it’s just F# functions. No template syntax to learn. No magic string interpolation. Just functions composing functions, with the full power of the F# type system catching errors before they reach production.&lt;/p&gt;

&lt;h2 id=&quot;project-structure&quot;&gt;Project Structure&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;fsharp-zensical/
├── .github/              # CI/CD workflows
├── app/                  # Application docs site
├── blog/                 # Blog site
├── docs/                 # Technical docs site
├── documentation/        # Project documentation
├── main/                 # Landing page
├── pages/                # Generated pages from HTML
├── src/                  # Shared F# modules
├── throw/                # HTML drop zone for conversion
├── Directory.Build.props # MSBuild properties
├── GenerateConfig.fsx    # Config generation script
└── html2giraffe.sln      # Solution file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;98.7% F#, 1.3% HTML. AGPL-3.0 licensed.&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;https://github.com/CommanderTurtle/fsharp-zensical&quot;&gt;View on GitHub&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;https://github.com/CommanderTurtle/fsharp-zensical#documentation&quot;&gt;Documentation&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

    </content>
    
    <category term="project" />
    
    <category term="fsharp" />
    
    <category term="zensical" />
    
    <category term="docs" />
    
    <category term="giraffe" />
    
    <category term="dsl" />
    
    <summary type="html">
      Documentation sites have a familiar shape: Markdown files, a static site generator, some theme customization, and a CI pipeline that builds on push. Most teams reach for MkDocs (with Material), Docusaurus, or Hugo. But what if your docs need to integrate with F# code? What if you want type-safe HTML...
    </summary>
  </entry>
  
  <entry>
    <title type="html">regedited: So I Rewrote the Windows Registry in Rust</title>
    <link href="https://shel.sh/blog/2025-04-01-regedited/" rel="alternate" type="text/html" />
    <published>2025-04-01T11:00:00+00:00</published>
    <updated>2025-04-01T11:00:00+00:00</updated>
    <id>https://shel.sh/blog/2025-04-01-regedited/</id>
    <author>
      <name>CommanderTurtle</name>
    </author>
    <content type="html" xml:base="https://shel.sh/blog/2025-04-01-regedited/">
      &lt;p&gt;It started as a joke. “Why need a DB? You should dangerously grep a million-line markdown file.” That became the repo description, then the design philosophy, then — somehow — an actual Rust project that reimagines the Windows Registry as a memory-mapped, plaintext-parsable database with O(1) section jumps.&lt;/p&gt;

&lt;h2 id=&quot;what-regedited-is&quot;&gt;What regedited Is&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;regedited&lt;/strong&gt; is a fast plaintext parsing database with structured headers, typed hex-word offsets, and O(1) section jumps on multi-GB files. The tagline says it all: &lt;em&gt;dangerously grep a million-line markdown file&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The name itself is a pun — “the registry, edited.” It’s not a registry editor in the traditional sense. It’s a complete rethinking of how structured system configuration data should be stored, parsed, and accessed.&lt;/p&gt;

&lt;h2 id=&quot;the-core-insight&quot;&gt;The Core Insight&lt;/h2&gt;

&lt;p&gt;The inspiration came from the &lt;a href=&quot;https://github.com/huggingface/safetensors&quot;&gt;safetensors&lt;/a&gt; format — specifically its ability to scan, diff, and replace keys in multi-gigabyte files without loading them into RAM. If that works for ML model weights, why not for structured configuration data?&lt;/p&gt;

&lt;p&gt;The approach: memory-map your file and build an index of section headers. A 10GB file with 1,000 sections uses ~200KB of Rust heap — the file lives in OS-managed virtual memory, not your process RAM. The trick is the &lt;strong&gt;hex-word store&lt;/strong&gt;: each section header contains typed line-number pointers that encode both the data type and the byte offset.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Approach&lt;/th&gt;
      &lt;th&gt;10GB File RAM&lt;/th&gt;
      &lt;th&gt;Section Jump&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cat + grep&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;10GB&lt;/td&gt;
      &lt;td&gt;O(n) scan&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Python &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;readlines()&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;10GB&lt;/td&gt;
      &lt;td&gt;O(1) — at a cost&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;regedited&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;~200KB&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;O(1) byte offset&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;architecture&quot;&gt;Architecture&lt;/h2&gt;

&lt;p&gt;The database format uses structured markdown documents with full key-value semantics. Section headers carry typed hex-word offsets — essentially embedded metadata that lets the parser jump directly to any section without scanning. The format is human-readable (it’s markdown), diff-friendly, and version-control compatible — three things the actual Windows Registry hive format is not.&lt;/p&gt;

&lt;p&gt;The Rust codebase is 90.2% Rust, 7.5% Python (for the &lt;a href=&quot;https://github.com/CommanderTurtle/regedited/blob/main/test_compendium.py&quot;&gt;test compendium&lt;/a&gt;), and 2.3% Shell. The project includes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/&lt;/code&gt;&lt;/strong&gt; — Core Rust library with the parser, index builder, and section jumper&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docs/&lt;/code&gt;&lt;/strong&gt; — Format specification and API documentation&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;examples/&lt;/code&gt;&lt;/strong&gt; — Sample databases and usage patterns&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pi/&lt;/code&gt;&lt;/strong&gt; — Platform interface layer&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test_compendium.py&lt;/code&gt;&lt;/strong&gt; — Comprehensive Python test suite&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;why-plaintext&quot;&gt;Why Plaintext?&lt;/h2&gt;

&lt;p&gt;The Windows Registry binary format (hive files) is opaque, fragile, and impossible to version control meaningfully. regedited asks: what if system configuration was just well-structured markdown? Readable in any editor. Diffable in git. Greppable in any Unix tool. And yet — with the hex-word index — as fast as a binary format for random access.&lt;/p&gt;

&lt;p&gt;The structured headers mean you don’t actually need the “dangerous grep” anymore. The index gives you direct jumps. But the grep still works if you want it — that’s the beauty of plaintext.&lt;/p&gt;

&lt;h2 id=&quot;project-status&quot;&gt;Project Status&lt;/h2&gt;

&lt;p&gt;18 commits on main. AGPL-3.0 licensed. The core engine is functional and the test compendium validates parsing correctness across a range of file sizes and section counts. The project continues to evolve — the next frontier is write operations (safe section edits without full file rewrites) and a query language for filtered lookups.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/CommanderTurtle/regedited&quot;&gt;github.com/CommanderTurtle/regedited&lt;/a&gt;&lt;/p&gt;

    </content>
    
    <category term="project" />
    
    <category term="registry" />
    
    <category term="rust" />
    
    <category term="windows" />
    
    <category term="database" />
    
    <category term="plaintext" />
    
    <summary type="html">
      It started as a joke. “Why need a DB? You should dangerously grep a million-line markdown file.” That became the repo description, then the design philosophy, then — somehow — an actual Rust project that reimagines the Windows Registry as a memory-mapped, plaintext-parsable database with O(1) section jumps.

    </summary>
  </entry>
  
  <entry>
    <title type="html">Gemma 4 on Blackwell: A Three-Act Saga of Pain and Glory</title>
    <link href="https://shel.sh/blog/2025-03-15-shel-gemma4-release/" rel="alternate" type="text/html" />
    <published>2025-03-15T16:00:00+00:00</published>
    <updated>2025-03-15T16:00:00+00:00</updated>
    <id>https://shel.sh/blog/2025-03-15-shel-gemma4-release/</id>
    <author>
      <name>CommanderTurtle</name>
    </author>
    <content type="html" xml:base="https://shel.sh/blog/2025-03-15-shel-gemma4-release/">
      &lt;p&gt;Getting Gemma 4 running locally on a 5090 wasn’t supposed to be this hard. NVIDIA’s latest Blackwell architecture, a brand-new MoE model from Google, and a quantization format (NVFP4) designed specifically for the hardware — what could go wrong?&lt;/p&gt;

&lt;p&gt;Everything, it turns out. But the destination was worth every hour.&lt;/p&gt;

&lt;h2 id=&quot;the-model&quot;&gt;The Model&lt;/h2&gt;

&lt;p&gt;The release is &lt;strong&gt;&lt;a href=&quot;https://huggingface.co/sHEL1562/gemma-4-A4B-it-MoE-HERETIC-nvfp4-blackwell&quot;&gt;sHEL Gemma 4 A4B Heretic NVFP4&lt;/a&gt;&lt;/strong&gt; — a pruned-expert, reasoning-optimized Gemma-4 MoE model with full NVFP4 quantization using NVIDIA ModelOpt. Built on the DavidAU heretic base, pruned from 128 to 90 experts, then fully finetuned. It supports thinking mode (with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;|think|&amp;gt;&lt;/code&gt; blocks), instruct mode, tool calling, and full multimodal vision via AEON’s proven methods.&lt;/p&gt;

&lt;p&gt;The specs: 19B parameters (26B pruned), 10B params export size, ~16GB on disk, 256K native context length, served at 64K for throughput. On a 5090 with 32GB VRAM, four parallel 65K context windows at 170 tok/s.&lt;/p&gt;

&lt;h2 id=&quot;act-i-following-allen-kuo-into-the-minefield&quot;&gt;Act I: Following Allen Kuo Into the Minefield&lt;/h2&gt;

&lt;p&gt;I started where anyone should start — Allen Kuo’s three-part Medium saga on getting vLLM running on Blackwell.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://allenkuo.medium.com/vllm-or-ollama-on-blackwell-benchmarks-landmines-and-what-agents-actually-need-5dc539bb28ef&quot;&gt;Part 1: vLLM or Ollama on Blackwell&lt;/a&gt;&lt;/strong&gt; set the stage. Allen laid out the fundamental problem: Blackwell is new, the software stack is raw, and most “it just works” claims are lies. He benchmarked both vLLM and Ollama, found landmines in CUDA version compatibility, driver requirements, and the reality that “FP8 support” doesn’t mean “your model will load.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://allenkuo.medium.com/gemma-4-on-vllm-vs-ollama-benchmarks-on-a-96-gb-blackwell-gpu-804ca4845a21&quot;&gt;Part 2: Gemma 4 on vLLM vs Ollama&lt;/a&gt;&lt;/strong&gt; went deeper. Specific to Gemma 4, Allen documented the MoE routing issues, the context length limitations, the memory footprint surprises. His 96GB Blackwell GPU gave him room I didn’t have — my 5090’s 32GB meant every quantization decision mattered.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://allenkuo.medium.com/finishing-what-we-started-gemma-4-nvfp4-on-vllm-desktop-blackwell-wsl2-b2088c34815a&quot;&gt;Part 3: Finishing What We Started&lt;/a&gt;&lt;/strong&gt; was where things got real. NVFP4 on vLLM, inside WSL2, with manual patching. Allen documented the full reproduction method: ModelOpt calibration, the 15-hour CPU quantization process, manual shard patching for vision tower keys, and the specific environment variables needed to make Blackwell’s Cutlass/FlashInfer/Marlin paths all activate correctly.&lt;/p&gt;

&lt;h2 id=&quot;act-ii-the-wsl2-rabbit-hole&quot;&gt;Act II: The WSL2 Rabbit Hole&lt;/h2&gt;

&lt;p&gt;Following Allen’s guide, I went deep into WSL2. The quantization itself took ~15 hours on a high-end CPU — the model simply doesn’t fit in BF16 on a 5090 alone, so you quantize on CPU using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uv run&lt;/code&gt; inside a vLLM venv. The calibration uses 512 samples at sequence length 4096, batch size 3, with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NVFP4_DEFAULT_CFG&lt;/code&gt; (plain NVFP4, no AWQ).&lt;/p&gt;

&lt;p&gt;Then came the patching nightmare. ModelOpt doesn’t perfectly preserve vision tower + down_proj/up_proj/gate_proj/q_proj/k_proj/v_proj/o_proj keys across shards. I ended up running a sequence of manual patch scripts:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Patches &apos;vision_tower and down_proj&apos; keys&lt;/span&gt;
uv run clean_shards3-2.py
&lt;span class=&quot;c&quot;&gt;# Patches &apos;vision_tower and up_proj&apos; keys&lt;/span&gt;
uv run clean_shards3-2-1.py
&lt;span class=&quot;c&quot;&gt;# ...and so on for every combination&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Each script takes keys from the original &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.safetensors&lt;/code&gt; file and transplants them into the post-ModelOpt shards. When vLLM errors with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AssertionError: Tried to load weights of size torch.Size([2816,576]) to a parameter of size torch.Size([2816,1152])&lt;/code&gt;, you run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scanoffendingkey.py&lt;/code&gt;, find the mismatch, and build a new patch script.&lt;/p&gt;

&lt;p&gt;The final fix was the EOS configuration. Gemma 4 uses internal control tokens (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;|channel&amp;gt;&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;channel|&amp;gt;&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;|think|&amp;gt;&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;|tool_call&amp;gt;&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;tool_call|&amp;gt;&lt;/code&gt;) that can leak into API responses as plaintext spam if not handled. Adding tokens 98, 100, and 101 to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eos_token_id&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;generation_config.json&lt;/code&gt; stops the model from getting stuck in repetition loops.&lt;/p&gt;

&lt;h2 id=&quot;act-iii-windows-native-and-the-breath-of-fresh-air&quot;&gt;Act III: Windows Native and the Breath of Fresh Air&lt;/h2&gt;

&lt;p&gt;After weeks in WSL2, I stumbled on &lt;strong&gt;&lt;a href=&quot;https://github.com/SystemPanic/vllm-windows&quot;&gt;SystemPanic/vllm-windows&lt;/a&gt;&lt;/strong&gt; — the official vLLM Windows port. This changed everything.&lt;/p&gt;

&lt;p&gt;No more WSL2 overhead. No more cross-filesystem path translation. No more &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;export&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$env:&lt;/code&gt;. Just native Windows PowerShell with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uv&lt;/code&gt; venv and the vllm-windows wheel.&lt;/p&gt;

&lt;p&gt;The environment variables for Windows:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;VLLM_TEST_FORCE_FP8_MARLIN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;VLLM_MARLIN_USE_ATOMIC_ADD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;VLLM_ALLOW_LONG_MAX_MODEL_LEN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;TORCH_MATMUL_PRECISION&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;high&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PYTORCH_CUDA_ALLOC_CONF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;expandable_segments:True&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;NVIDIA_FORWARD_COMPAT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The serving command:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vllm&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;serve&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sHEL1562/gemma-4-A4B-it-MoE-HERETIC-nvfp4-blackwell&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;`
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--quantization&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;modelopt&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;`
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--kv-cache-dtype&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fp8_e4m3&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;`
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--max-model-len&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;65536&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;`
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--max-num-seqs&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;`
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--max-num-batched-tokens&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;8192&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;`
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--gpu-memory-utilization&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;0.90&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;`
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--enable-chunked-prefill&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;`
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--enable-prefix-caching&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;`
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--trust-remote-code&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;`
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--enable-auto-tool-choice&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;`
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--tool-call-parser&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gemma4&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;`
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--reasoning-parser&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gemma4&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;One PowerShell window. Four concurrent 65K context streams. 170 tok/s.&lt;/p&gt;

&lt;h2 id=&quot;the-aeon-connection&quot;&gt;The AEON Connection&lt;/h2&gt;

&lt;p&gt;The quantization method follows &lt;strong&gt;&lt;a href=&quot;https://huggingface.co/AEON-7/supergemma4-26b-abliterated-multimodal-nvfp4&quot;&gt;AEON-7’s SuperGemma guidelines&lt;/a&gt;&lt;/strong&gt;. AEON’s work on the “Gemma Problem” — the internal control token leakage, the MoE routing quirks, the calibration strategies for pruned experts — was foundational. The model card explicitly references AEON’s JSON configurations and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clean_shards&lt;/code&gt; patching methodology.&lt;/p&gt;

&lt;p&gt;For anyone reconstructing the ModelOptimizer pipeline: it requires &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;modelopt&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;torch&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;accelerate&lt;/code&gt;, performed in WSL with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uv run&lt;/code&gt;. The reproduction script is included in the model files. Just… expect to wait. And patch. And patch again.&lt;/p&gt;

&lt;h2 id=&quot;life-after-wsl&quot;&gt;Life After WSL&lt;/h2&gt;

&lt;p&gt;The experience fundamentally changed how I work. WSL2 is still there for quantizing and debugging — anything that needs the full Linux build chain. But for actual inference serving? Native Windows vLLM is the way. I followed &lt;a href=&quot;https://www.youtube.com/watch?v=U_K2w-Cee1c&quot;&gt;OneMarcFifty’s WSL productivity guide&lt;/a&gt; for setting up the Kali taskbar, minimal tools, and the hobby-project mindset. The future is a hybrid: WSL for build environments, Windows for runtime.&lt;/p&gt;

&lt;h2 id=&quot;quickstart-for-5090-owners&quot;&gt;Quickstart for 5090 Owners&lt;/h2&gt;

&lt;p&gt;Prerequisites: NVIDIA drivers, CUDA, PowerShell Preview from the Windows Store. No external dependencies.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Test the model is serving&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;curl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;http://localhost:8000/v1/models&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Run inference&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;TEMP&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;\vllm_req_&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-Random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.json&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$json&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;gemma4&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;messages&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@(@{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;user&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@(@{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;text&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;Your prompt here&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})})}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ConvertTo-Json&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Depth&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Compress&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Set-Content&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$tmp&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$json&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;curl.exe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;http://localhost:8000/v1/chat/completions&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Content-Type: application/json&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;@&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$tmp&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Pipe the output through Notepad++ (find+replace `    ` with empty, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\n&lt;/code&gt; with literal newline, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\&quot;&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;&lt;/code&gt;), then paste into Obsidian for clean markdown rendering.&lt;/p&gt;

&lt;p&gt;The model is uncensored, reasoning-optimized, and genuinely excellent at long-form narrative writing. The thinking blocks are unlike anything else — leave them on for complex writing tasks, switch to instruct mode for tool calling.&lt;/p&gt;

&lt;p&gt;Download: &lt;a href=&quot;https://huggingface.co/sHEL1562/gemma-4-A4B-it-MoE-HERETIC-nvfp4-blackwell&quot;&gt;sHEL1562/gemma-4-A4B-it-MoE-HERETIC-nvfp4-blackwell&lt;/a&gt;&lt;/p&gt;

    </content>
    
    <category term="llm" />
    
    <category term="local-ai" />
    
    <category term="windows" />
    
    <category term="gemma" />
    
    <category term="blackwell" />
    
    <category term="vllm" />
    
    <category term="nvfp4" />
    
    <summary type="html">
      Getting Gemma 4 running locally on a 5090 wasn’t supposed to be this hard. NVIDIA’s latest Blackwell architecture, a brand-new MoE model from Google, and a quantization format (NVFP4) designed specifically for the hardware — what could go wrong?

    </summary>
  </entry>
  
</feed>
