<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.4">Jekyll</generator><link href="https://unixwzrd.ai/feed.xml" rel="self" type="application/atom+xml" /><link href="https://unixwzrd.ai/" rel="alternate" type="text/html" /><updated>2026-05-09T02:43:18-04:00</updated><id>https://unixwzrd.ai/feed.xml</id><title type="html">Distributed Thinking Systems</title><subtitle>Distributed Thinking Systems: local-first AI, secure automation, and developer tooling for sensitive workflows. &lt;br&gt; Unix, macOS, and Linux systems engineering. &lt;br&gt; Privacy-focused tools for work that needs care.</subtitle><author><name>Distributed Thinking Systems</name><email>info@unixwzrd.ai</email></author><entry><title type="html">Secrets Kit 1.2: launchd, seckit run, and invisible env vars</title><link href="https://unixwzrd.ai/projects/Secrets-Kit/2026/05/04/launchd-seckit-run-and-invisible-env-vars/" rel="alternate" type="text/html" title="Secrets Kit 1.2: launchd, seckit run, and invisible env vars" /><published>2026-05-04T00:00:00-04:00</published><updated>2026-05-04T00:00:00-04:00</updated><id>https://unixwzrd.ai/projects/Secrets-Kit/2026/05/04/launchd-seckit-run-and-invisible-env-vars</id><content type="html" xml:base="https://unixwzrd.ai/projects/Secrets-Kit/2026/05/04/launchd-seckit-run-and-invisible-env-vars/"><![CDATA[<h2 id="secrets-kit-12-launchd-invisible-env-vars-and-why-api-keys-shouldnt-ride-shotgun-on-argv">Secrets Kit 1.2: launchd, invisible env vars, and why API keys shouldn’t ride shotgun on argv</h2>

<p>Feynman had a habit of boiling things down to what actually matters. If you can’t explain it to a freshman, you probably don’t understand it. Thompson might add: if you’re explaining it while the engine is on fire, bring better tools - because adrenaline is expensive and key rotation is worse.</p>

<p>Secrets Kit <strong>1.2.0</strong> is that kind of release: less spectacle, more structural integrity. The kind where nothing flashy happens, and everything quietly stops breaking.</p>

<!--more-->

<h3 id="heres-the-plot">Here’s the plot.</h3>

<p>Most of us learned to pass API keys like contraband in a crowded room: export them in a shell, paste them into a <code class="language-plaintext highlighter-rouge">.env</code>, duplicate them into a launchd plist because “it worked once,” and then pretend <code class="language-plaintext highlighter-rouge">ps eww</code> is not a thing.</p>

<p>Spoiler: it is. So is your shell history. So is every log line that ever captured argv when you weren’t looking.</p>

<p><strong><code class="language-plaintext highlighter-rouge">seckit run</code></strong> is the workaround that sounds boring until you actually watch it behave.</p>

<p>The parent (<code class="language-plaintext highlighter-rouge">seckit</code>) talks to Keychain, pulls the values you asked for, drops them into the <strong>child’s environment</strong>, and hands off to your real program. The secret never becomes a command-line argument. Nothing gets pinned to the process list like it’s a parade float.</p>

<p>Quick example, same vibe as the docs but slightly more awake with black coffee:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">echo</span> <span class="s1">'sk-demo-not-real'</span> | seckit <span class="nb">set</span> <span class="nt">--name</span> OPENAI_API_KEY <span class="nt">--stdin</span> <span class="se">\</span>
  <span class="nt">--kind</span> api_key <span class="nt">--service</span> my-agents <span class="nt">--account</span> launchd

seckit run <span class="nt">--service</span> my-agents <span class="nt">--account</span> launchd <span class="nt">--</span> <span class="se">\</span>
  python3 <span class="nt">-c</span> <span class="s2">"import os; print('set' if os.getenv('OPENAI_API_KEY') else 'missing')"</span>
</code></pre></div></div>

<p>Set defaults once and the launch line collapses into something almost offensively simple:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>seckit run <span class="nt">--</span> /path/to/your/actual/binary
</code></pre></div></div>

<p>That pattern is what makes <strong>launchd</strong> bearable. <code class="language-plaintext highlighter-rouge">launchd</code> is a fine scheduler with a weakness: it loves XML, and XML loves to leak structure the minute you stuff secrets into <code class="language-plaintext highlighter-rouge">EnvironmentVariables</code>. So don’t. Make <code class="language-plaintext highlighter-rouge">ProgramArguments</code> a <strong>wrapper</strong>, not a vault.</p>

<h3 id="launchd-without-the-confession-booth">launchd without the confession booth</h3>

<p><code class="language-plaintext highlighter-rouge">launchd</code> is a solid scheduler with one unfortunate personality trait: it happily exposes whatever you feed it.</p>

<p>So don’t feed it secrets.</p>

<p>Make <code class="language-plaintext highlighter-rouge">ProgramArguments</code> a wrapper, not a vault:</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;key&gt;</span>ProgramArguments<span class="nt">&lt;/key&gt;</span>
<span class="nt">&lt;array&gt;</span>
  <span class="nt">&lt;string&gt;</span>/usr/local/bin/seckit<span class="nt">&lt;/string&gt;</span>
  <span class="nt">&lt;string&gt;</span>run<span class="nt">&lt;/string&gt;</span>
  <span class="nt">&lt;string&gt;</span>--service<span class="nt">&lt;/string&gt;</span>
  <span class="nt">&lt;string&gt;</span>hermes<span class="nt">&lt;/string&gt;</span>
  <span class="nt">&lt;string&gt;</span>--account<span class="nt">&lt;/string&gt;</span>
  <span class="nt">&lt;string&gt;</span>local<span class="nt">&lt;/string&gt;</span>
  <span class="nt">&lt;string&gt;</span>--<span class="nt">&lt;/string&gt;</span>
  <span class="nt">&lt;string&gt;</span>/Users/you/.venv/hermes/bin/hermes<span class="nt">&lt;/string&gt;</span>
  <span class="nt">&lt;string&gt;</span>gateway<span class="nt">&lt;/string&gt;</span>
  <span class="nt">&lt;string&gt;</span>start<span class="nt">&lt;/string&gt;</span>
<span class="nt">&lt;/array&gt;</span>
</code></pre></div></div>

<p>Same camera angle for <strong>OpenClaw</strong> (or any other long-running “always there” agent): <strong><code class="language-plaintext highlighter-rouge">seckit run</code> first</strong>, then your usual subcommand. The plist stays boring. Boring plists age well.</p>

<h3 id="operator-candy">Operator candy</h3>

<p>Shipped alongside the good manners:</p>

<ul>
  <li><strong><code class="language-plaintext highlighter-rouge">seckit version --json</code></strong> and <strong><code class="language-plaintext highlighter-rouge">--info</code></strong>: for scripts and humans who want to see the world as a small, honest data structure instead of squinting at four different terminal panes.</li>
  <li><strong>CI and release hygiene</strong> that actually touches <strong>every</strong> Python the project claims to support - including <strong>3.13</strong> - so “it works on my laptop” stays a joke and not a deployment strategy.</li>
  <li><strong>Cross-host moves</strong> stay the adult path: <strong><code class="language-plaintext highlighter-rouge">seckit export</code></strong> → encrypted artifact → <strong><code class="language-plaintext highlighter-rouge">seckit import</code></strong> on the other Mac. No fairy dust. It works in hotel Wi-Fi and in your lab.</li>
</ul>

<h3 id="cross-host-reality">Cross-host reality</h3>

<p>There’s no magic sync story here, and that’s intentional.</p>

<p>You export, you move the file, you import:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>seckit export → encrypted artifact → seckit import
</code></pre></div></div>

<p>It works on hotel Wi-Fi. It works in a lab. It works when things are slightly broken, which is most of the time.</p>

<h3 id="the-icloud-keychain-chapter-honest-edition">The iCloud Keychain chapter (honest edition)</h3>

<p>We’ve spent real time on <strong>synchronizable Keychain</strong> paths - native helper, entitlements, the whole song-and-dance - because “synced secrets” is a beautiful idea until the operating system decides your helper is <strong>not</strong> allowed to have nice things. In plain English: on a lot of macOS builds, the helper can get <strong><code class="language-plaintext highlighter-rouge">SIGKILL</code></strong> at launch (<strong>taskgated</strong>, <strong>AMFI -413</strong>, pick your villain) <strong>even when notarization looks fine</strong>. That’s not a Python packaging tantrum; that’s policy territory.</p>

<p>The helper gets shut down at launch:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">SIGKILL</code></li>
  <li><code class="language-plaintext highlighter-rouge">taskgated</code></li>
  <li>AMFI complaints</li>
</ul>

<p>The work is <strong>preserved in git</strong> on branch <strong><code class="language-plaintext highlighter-rouge">preserve/icloud-backend-as-of-2026-05-05</code></strong> while we wait to hear something useful back from Apple. If the OS opens the door, you’ll see that path return in a shape that doesn’t waste your afternoon. Until then: <strong><code class="language-plaintext highlighter-rouge">seckit run</code></strong>, <strong>launchd</strong>, <strong>export/import</strong>. It’s less science fiction and more “lunch with the laws of physics.”</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">seckit run</code></li>
  <li>launchd wrappers</li>
  <li>export/import</li>
</ul>

<p>Less fantasy, more physics.</p>

<h3 id="install--peek">Install / peek</h3>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pip <span class="nb">install</span> <span class="s2">"git+https://github.com/unixwzrd/Secrets-Kit.git@v1.2.0"</span>
seckit version
seckit version <span class="nt">--info</span>
</code></pre></div></div>

<p>Repo and deeper docs: <a href="https://github.com/unixwzrd/Secrets-Kit">Secrets-Kit on GitHub</a>.</p>

<hr />

<p><em>P.S. If you already read the gentle introduction post, this is the one where the rubber meets <code class="language-plaintext highlighter-rouge">launchd</code>. Same philosophy: fewer secrets on disk, fewer secrets in argv, fewer apologies later.</em></p>]]></content><author><name>Distributed Thinking Systems</name><email>info@unixwzrd.ai</email></author><category term="Secrets-Kit" /><category term="release" /><category term="launchd" /><category term="seckit-run" /><category term="macos" /><category term="secrets-management" /><category term="agents" /><category term="local-ops" /><summary type="html"><![CDATA[Version 1.2 leans into the boring superpower: run real programs - Hermes, OpenClaw, whatever - without painting secrets on the process list, and wire that story into launchd without turning your plist into a confession booth.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://unixwzrd.ai/assets/images/projects/Secrets-Kit-Banner.png" /><media:content medium="image" url="https://unixwzrd.ai/assets/images/projects/Secrets-Kit-Banner.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Introducing Secrets Kit</title><link href="https://unixwzrd.ai/projects/Secrets-Kit/2026/04/12/secrets-kit-introduction/" rel="alternate" type="text/html" title="Introducing Secrets Kit" /><published>2026-04-12T00:00:00-04:00</published><updated>2026-04-12T00:00:00-04:00</updated><id>https://unixwzrd.ai/projects/Secrets-Kit/2026/04/12/secrets-kit-introduction</id><content type="html" xml:base="https://unixwzrd.ai/projects/Secrets-Kit/2026/04/12/secrets-kit-introduction/"><![CDATA[<p>If you have ever looked across a machine and realized the same API key is living in a <code class="language-plaintext highlighter-rouge">.env</code> file, a shell startup script, a copied command, and some forgotten project directory all at once, then you already understand why Secrets Kit exists.</p>

<!--more-->

<p>Secrets Kit is a local macOS command-line tool for handling tokens, passwords, PII, and other sensitive values in a way that is more disciplined than plain-text sprawl but still practical for real day-to-day workflows.</p>

<p>The basic idea is straightforward. Store secret values in the macOS login Keychain. Keep metadata in a local registry. Export environment variables only when the current shell or runtime actually needs them. It is not a glamorous idea, but it solves a very common and very real local operations problem.</p>

<ul>
  <li><a href="#why-this-tool-exists">Why This Tool Exists</a>
    <ul>
      <li><a href="#secrets-spread-by-accident">Secrets spread by accident.</a></li>
    </ul>
  </li>
  <li><a href="#what-it-is-and-what-it-is-not">What It Is and What It Is Not</a></li>
  <li><a href="#where-it-fits">Where It Fits</a></li>
  <li><a href="#why-it-matters">Why It Matters</a></li>
  <li><a href="#learn-more">Learn More</a></li>
</ul>

<h2 id="why-this-tool-exists">Why This Tool Exists</h2>

<h3 id="secrets-spread-by-accident">Secrets spread by accident.</h3>

<p>For a lot of developer and AI workflows, secrets spread by accident. A token lands in a <code class="language-plaintext highlighter-rouge">.env</code> file because it is quick. Then it also ends up in <code class="language-plaintext highlighter-rouge">~/.bashrc</code> or <code class="language-plaintext highlighter-rouge">~/.bash_profile</code> because something needs it globally. Then it gets copied into a setup note, a startup script, or a temporary command someone meant to clean up later. None of that feels dramatic in the moment, but it is how sensitive values end up committed to GitHub, left behind in archives, or exposed to whatever script happens to read the wrong directory.</p>

<p>Secrets Kit is meant to make that pattern less casual and less dangerous.</p>

<p>It does that by giving local operators and developers a cleaner workflow:</p>

<ul>
  <li>store secrets in Keychain instead of plain-text files</li>
  <li>track them with minimal local metadata</li>
  <li>export values only into the shell that needs them</li>
  <li>migrate <code class="language-plaintext highlighter-rouge">.env</code> files to placeholders instead of leaving raw values behind</li>
</ul>

<p>That is the whole point. It is not trying to become a giant platform. It is trying to be a better local habit.</p>

<h2 id="what-it-is-and-what-it-is-not">What It Is and What It Is Not</h2>

<p>Secrets Kit helps reduce accidental exposure. It does <strong>not</strong> guarantee safety.</p>

<p>It is not a hosted secret manager. It is not a vault service. It is not a guarantee against a compromised machine, a hostile local session, or any downstream process you choose to launch after exporting environment variables.</p>

<p>It also does not collect your secret information for some outside service, and it does not store your keychain password. Under the hood, it is a thin wrapper around the macOS <code class="language-plaintext highlighter-rouge">security</code> command with a local metadata layer and some practical workflow tooling around it.</p>

<p>That matters because it sets the right expectation. Secrets Kit is not promising magic. It is offering a materially better workflow than leaving tokens and passwords all over the filesystem in plain text.</p>

<h2 id="where-it-fits">Where It Fits</h2>

<p>This is a tool for people running local stacks that still depend on environment variables: agent runtimes, development servers, shell-driven automation, local UIs, and project workflows that need credentials at launch time but do not need those values committed into a repo or copied into a startup file forever.</p>

<p>It is also useful when you are trying to clean up an existing machine. If secrets are already scattered through <code class="language-plaintext highlighter-rouge">.env</code> files and project directories, the migration and export flows give you a reasonable path toward something more controlled without forcing you to rebuild your entire workflow from scratch.</p>

<h2 id="why-it-matters">Why It Matters</h2>

<p>The local machine is where a lot of otherwise careful security habits break down. People know better than to paste secrets into public docs or commit them to GitHub intentionally, but local convenience is where the shortcuts happen. That is exactly the gap Secrets Kit is trying to narrow.</p>

<p>It is not a complete answer to local security, but it is a practical improvement. In most real environments, that matters more than pretending a plain-text <code class="language-plaintext highlighter-rouge">.env</code> file is good enough because it is familiar.</p>

<h2 id="learn-more">Learn More</h2>

<p>The repository and documentation are here:</p>

<p><a href="https://github.com/unixwzrd/Secrets-Kit">View Secrets Kit on GitHub</a></p>

<p>If you want the project overview rather than the dated launch write-up, start here instead:</p>

<p><a href="/projects/Secrets-Kit/">Secrets Kit project page</a></p>]]></content><author><name>Distributed Thinking Systems</name><email>info@unixwzrd.ai</email></author><category term="Secrets-Kit" /><category term="introduction" /><category term="overview" /><category term="secrets-management" /><category term="macos" /><category term="security-hygiene" /><category term="local-ops" /><category term="agent-workflows" /><summary type="html"><![CDATA[Secrets Kit is a local macOS tool for keeping API keys, passwords, tokens, and other sensitive values out of scattered .env files and shell startup scripts while still making them usable for real runtimes.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://unixwzrd.ai/assets/images/projects/Secrets-Kit-Banner.png" /><media:content medium="image" url="https://unixwzrd.ai/assets/images/projects/Secrets-Kit-Banner.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Introducing Extract Chat</title><link href="https://unixwzrd.ai/projects/extract-chat/2026/03/28/extract-chat-introduction/" rel="alternate" type="text/html" title="Introducing Extract Chat" /><published>2026-03-28T00:00:00-04:00</published><updated>2026-03-28T00:00:00-04:00</updated><id>https://unixwzrd.ai/projects/extract-chat/2026/03/28/extract-chat-introduction</id><content type="html" xml:base="https://unixwzrd.ai/projects/extract-chat/2026/03/28/extract-chat-introduction/"><![CDATA[<p>If you have ever downloaded a ChatGPT conversation as JSON, stared at the file for a second, and thought, “Okay… now what exactly am I supposed to do with this?” then you already understand why <code class="language-plaintext highlighter-rouge">extract-chat</code> exists.</p>

<!--more-->

<p>The raw export is full of useful material, but it is not something most people actually want to read. It is not especially pleasant to browse, not something you would hand to another person, and not the sort of thing you want to drop directly into a writing workflow, an archive, or an AI pipeline without doing some cleanup first.</p>

<p>That is the gap <code class="language-plaintext highlighter-rouge">extract-chat</code> is meant to close. It takes downloaded ChatGPT or OpenAI conversation JSON and turns it into something you can actually use: readable Markdown, clean HTML, and structured output that still remembers the parts of the conversation that matter. If you are already using <strong>LogGPT</strong> to save conversations locally, this is the natural next step.</p>

<h2 id="why-i-built-it">Why I Built It</h2>

<p>One of the recurring frustrations with ChatGPT is that genuinely useful work tends to get trapped inside the session where it happened. A conversation might contain research notes, a debugging trail, a draft article, a prompt pattern worth saving, or just a line of thought you do not want to lose. Exporting the JSON is better than losing it entirely, but it still leaves you with a machine-oriented file instead of something that feels like a document.</p>

<p><code class="language-plaintext highlighter-rouge">extract-chat</code> closes that gap.</p>

<p>Instead of leaving your conversations as raw exported data, it turns them into something readable, portable, and reusable. It keeps the conversation intelligible for a human being, but it also keeps enough structure around to make the output useful for more serious downstream work. References are preserved. Hidden tool activity is not quietly discarded. Long conversations can be broken into more manageable chunks. The result is that your conversation history starts to feel less like a dead export and more like a real asset.</p>

<p>That matters more than it may sound at first. Once a conversation has been cleaned up and chunked properly, it becomes much easier to archive, publish, search, feed into embeddings, or carry forward into another agent or workflow. Instead of ending with a closed browser tab and a JSON file you never open again, you get something you can keep building on.</p>

<h2 id="a-natural-fit-with-loggpt">A Natural Fit with LogGPT</h2>

<p>This project pairs especially well with <a href="/projects/LogGPT/"><strong>LogGPT</strong></a>, because the two tools solve adjacent parts of the same problem.</p>

<p><a href="/projects/LogGPT/">LogGPT</a> gives you the conversation export, and it is also <a href="https://apps.apple.com/us/app/loggpt/id6743342693?mt=12">available on the App Store</a>. <code class="language-plaintext highlighter-rouge">extract-chat</code> turns that export into something worth keeping. Together, they create a workflow that feels much more practical: save the conversation, convert it into readable output, and then do something useful with it instead of letting it disappear into an archive folder.</p>

<p>If you are working with longer sessions, research notes, or AI-assisted writing, that is a much better experience than leaving everything trapped in a browser tab and hoping you can find it again later.</p>

<h2 id="more-than-a-formatter">More Than a Formatter</h2>

<p>What I like about this project is that it is not just a prettier export utility. It is really about making AI conversations usable outside the chat window. Sometimes that means turning a session into an article draft. Sometimes it means preserving citations and references so the conversation can be reviewed later. Sometimes it means chunking the output so it can feed a local RAG pipeline or some other structured memory system.</p>

<p>In other words, this is a tool for people who think their ChatGPT sessions are worth keeping and worth working with. Writers, researchers, developers, and anyone building repeatable workflows around AI will probably understand the value of that immediately.</p>

<h2 id="where-this-is-going">Where This Is Going</h2>

<p>This project is part of a broader effort to preserve, structure, and reuse AI-generated work without handing everything off to a third-party platform and hoping for the best. The emphasis is on local control, practical output, and making your own conversation history genuinely useful.</p>

<p>There is still more to build, but the foundation is already the right one: take the export seriously, preserve the useful structure, and produce something that can move into publication, research, or machine workflows instead of stopping at a raw JSON dump.</p>

<h2 id="try-it">Try It</h2>

<p>If that sounds like the missing piece in your workflow, start with the repository here:</p>

<p><a href="https://github.com/unixwzrd/extract-chat">View extract-chat on GitHub</a></p>

<p>If you are already using <a href="/projects/LogGPT/">LogGPT</a>, this is the obvious next tool to add. If you are not, this should still make sense on its own: your conversation history should be easier to read, easier to reuse, and easier to keep. That is exactly what <code class="language-plaintext highlighter-rouge">extract-chat</code> is for.</p>]]></content><author><name>Distributed Thinking Systems</name><email>info@unixwzrd.ai</email></author><category term="extract-chat" /><category term="introduction" /><category term="overview" /><category term="chatgpt" /><category term="markdown" /><category term="knowledge-management" /><category term="data-portability" /><summary type="html"><![CDATA[Downloaded a ChatGPT JSON export and wondered what to do with it next? Extract Chat turns that raw export into readable Markdown or HTML, preserves the useful structure, and chunks it for real AI workflows.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://unixwzrd.ai/assets/images/projects/extract-chat-banner.png" /><media:content medium="image" url="https://unixwzrd.ai/assets/images/projects/extract-chat-banner.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Introducing LLM Ops Kit</title><link href="https://unixwzrd.ai/projects/LLM-Ops-Kit/2026/03/09/llm-ops-kit-introduction/" rel="alternate" type="text/html" title="Introducing LLM Ops Kit" /><published>2026-03-09T00:00:00-04:00</published><updated>2026-03-09T00:00:00-04:00</updated><id>https://unixwzrd.ai/projects/LLM-Ops-Kit/2026/03/09/llm-ops-kit-introduction</id><content type="html" xml:base="https://unixwzrd.ai/projects/LLM-Ops-Kit/2026/03/09/llm-ops-kit-introduction/"><![CDATA[<p>Self-hosting AI systems is no longer the hard part. Keeping them stable is.</p>

<p>That is the problem <strong>LLM-Ops-Kit</strong> is meant to solve.</p>

<!--more-->

<h2 id="why-i-built-it">Why I Built It</h2>

<p>Once you move past single-command demos, local AI stacks get messy fast.</p>

<p>You end up with:</p>

<ul>
  <li>one host doing inference</li>
  <li>another running a gateway</li>
  <li>local bridges translating one API into another</li>
  <li>model-specific startup flags</li>
  <li>runtime state that goes stale</li>
  <li>logs that grow forever</li>
  <li>shell wrappers that drift away from reality</li>
</ul>

<p>That is manageable for a while, until you need to diagnose a failure under pressure. Then every undocumented path, hidden assumption, and stale PID file starts costing real time.</p>

<p>LLM-Ops-Kit grew out of exactly that problem.</p>

<h2 id="what-llm-ops-kit-covers">What LLM-Ops-Kit Covers</h2>

<p>The toolkit provides an operator layer for a self-hosted AI environment:</p>

<ul>
  <li>unified wrappers for gateway, model servers, TTS, and bridges</li>
  <li>model profile management for chat, embeddings, and speech</li>
  <li>cross-host deployment helpers</li>
  <li>installed-runtime workflows that do not depend on a working source checkout</li>
  <li>observability tooling for prompt and request debugging</li>
  <li>runtime maintenance for logs and backups</li>
  <li>streamlined Jinja and ChatML template variants, including lower-context-friendly paths for smaller machines</li>
</ul>

<p>In short, it turns a pile of scripts into something you can run, inspect, and repair without guessing.</p>

<h2 id="built-from-real-failures">Built From Real Failures</h2>

<p>This project did not come out of a greenfield design exercise. It came out of chasing real operational problems:</p>

<ul>
  <li>mismatched template selection</li>
  <li>stale runtime state after path migrations</li>
  <li>health checks that looked healthy while the service was actually broken</li>
  <li>TTS routing that appeared correct in config but failed in practice</li>
  <li>upstream API behavior that did not match what the bridge or caller expected</li>
</ul>

<p>That last point was especially useful. End-to-end testing uncovered an OpenAI-compatible API mismatch in the MLX Audio path, which in turn exposed a real <code class="language-plaintext highlighter-rouge">CustomVoice</code> cloning issue. That led to a working local patch and an upstream PR.</p>

<p>That is the kind of work this toolkit is for. Not abstract architecture diagrams, operational reality.</p>

<h2 id="a-big-part-of-the-payoff-local-tts">A Big Part of the Payoff: Local TTS</h2>

<p>One of the biggest immediate wins has been local TTS and voice cloning.</p>

<p>That matters for two reasons:</p>

<ul>
  <li>spoken responses are a lot more engaging in day-to-day agent use</li>
  <li>premium hosted TTS gets expensive fast when you use it heavily</li>
</ul>

<p>Getting MLX Audio working cleanly behind an OpenAI-compatible bridge meant the stack could keep the same higher-level interface while moving speech generation local. That is not just a technical nicety. It is a real cost reduction and a real improvement in control.</p>

<h2 id="why-it-matters">Why It Matters</h2>

<p>There are plenty of tools for running models. There are far fewer tools for operating a whole self-hosted AI stack over time.</p>

<p>If you care about:</p>

<ul>
  <li>reproducibility</li>
  <li>cross-host deployment</li>
  <li>local-first control</li>
  <li>debugging what your models and bridges are actually doing</li>
  <li>keeping prompt/template behavior under control instead of treating it like hidden magic</li>
  <li>reducing dependence on expensive hosted services</li>
</ul>

<p>then the boring operational layer matters a lot.</p>

<p>That is where LLM-Ops-Kit lives.</p>

<h2 id="where-it-goes-next">Where It Goes Next</h2>

<p>The immediate goal is a clean initial release with solid documentation and a stable runtime workflow.</p>

<p>After that, I expect the project to keep expanding in a few directions:</p>

<ul>
  <li>tighter secrets integration</li>
  <li>better diagnostics and reporting</li>
  <li>cleaner runtime packaging</li>
  <li>more general support for non-OpenClaw stacks</li>
  <li>deeper tooling around local AI observability</li>
  <li>more refined prompt/template control for different model sizes and context budgets</li>
</ul>

<h2 id="project-link">Project Link</h2>

<p>You can find the project here:</p>

<ul>
  <li><a href="https://github.com/unixwzrd/LLM-Ops-Kit">LLM-Ops-Kit on GitHub</a></li>
</ul>

<p>If you are building something similar, or if you are tired of debugging self-hosted AI infrastructure by memory and shell history alone, this project may save you some time.</p>

<h2 id="contribute">Contribute</h2>

<p>If you want to help improve the project, contributions are welcome.</p>

<p>That can mean:</p>

<ul>
  <li>testing the toolkit in your own environment</li>
  <li>opening issues for real operational problems</li>
  <li>sending patches and documentation improvements</li>
  <li>sharing deployment notes from hardware and host setups different from mine</li>
</ul>

<p>The project is being shaped by actual use, so practical feedback is especially valuable.</p>

<h2 id="support-the-work">Support the Work</h2>

<p>If this kind of tooling saves you time, reduces hosting costs, or helps you keep a self-hosted AI stack under control, you can also support the work directly:</p>

<ul>
  <li><a href="https://patreon.com/unixwzrd">Patreon</a></li>
  <li><a href="https://ko-fi.com/unixwzrd">Ko-fi</a></li>
  <li><a href="https://buymeacoffee.com/unixwzrd">Buy Me a Coffee</a></li>
</ul>]]></content><author><name>Distributed Thinking Systems</name><email>info@unixwzrd.ai</email></author><category term="LLM-Ops-Kit" /><category term="introduction" /><category term="release" /><category term="ai-operations" /><category term="self-hosting" /><category term="devops" /><summary type="html"><![CDATA[LLM-Ops-Kit is a new operational toolkit for running, debugging, and maintaining self-hosted AI stacks across hosts.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://unixwzrd.ai/assets/images/projects/LLM-Ops-Kit/LLM-OPS-Kit-banner.png" /><media:content medium="image" url="https://unixwzrd.ai/assets/images/projects/LLM-Ops-Kit/LLM-OPS-Kit-banner.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">UnicodeFix v1.2.1: Smoother Installs, Cleaner Reports, Less Weirdness</title><link href="https://unixwzrd.ai/projects/UnicodeFix/2026/03/06/unicodefix-v1-2-1-smoother-cleaner-smarter/" rel="alternate" type="text/html" title="UnicodeFix v1.2.1: Smoother Installs, Cleaner Reports, Less Weirdness" /><published>2026-03-06T00:00:00-05:00</published><updated>2026-03-06T00:00:00-05:00</updated><id>https://unixwzrd.ai/projects/UnicodeFix/2026/03/06/UnicodeFix-v1.2.1-Smoother-Cleaner-Smarter</id><content type="html" xml:base="https://unixwzrd.ai/projects/UnicodeFix/2026/03/06/unicodefix-v1-2-1-smoother-cleaner-smarter/"><![CDATA[<h2 id="unicodefix-v121-the-smooth-the-edges-release">UnicodeFix v1.2.1: The “Smooth the Edges” Release</h2>

<p>Not every release needs fireworks.</p>

<p>Some releases need to do something quieter, and honestly more useful:
<strong>remove friction.</strong></p>

<p>UnicodeFix v1.2.1 is that kind of release.</p>

<p>This update is about making the tool feel better in real use:</p>

<ul>
  <li>easier to install</li>
  <li>easier to understand</li>
  <li>less confusing when you ask for metrics</li>
  <li>more honest in how it reports what it found</li>
</ul>

<p>In other words: less “why is it doing that?” and more “yes, that is exactly what I wanted.”</p>

<hr />

<h2 id="first-installation-finally-got-less-annoying">First: Installation Finally Got Less Annoying</h2>

<p>One of the big cleanup jobs in this release was the install path.</p>

<p>Before, UnicodeFix had a few too many ways to get itself onto a system.
That usually sounds flexible until you’re the person trying to figure out which path is the <em>real</em> one.</p>

<p>v1.2.1 tightens that up.</p>

<p>Now the project uses <strong><code class="language-plaintext highlighter-rouge">pyproject.toml</code> as the single source of truth</strong> for dependencies, and <code class="language-plaintext highlighter-rouge">setup.sh</code> acts like a sane bootstrap script instead of a side quest.</p>

<p>That means:</p>

<ul>
  <li>no split-brain dependency story between <code class="language-plaintext highlighter-rouge">requirements.txt</code> and package metadata</li>
  <li>a cleaner path for contributors and regular users alike</li>
  <li>better alignment between local installs, docs, and CI</li>
</ul>

<p>It also behaves more politely with Python environments now.
If you’re already inside Conda, UnicodeFix should act like a good guest and install there instead of wandering off and building a surprise environment on its own.</p>

<p>That sounds small.
If you’ve ever lost ten minutes to “which Python did this install into?” you know it is not small.</p>

<hr />

<h2 id="the-hyphen-fix-that-should-have-been-there-already">The Hyphen Fix That Should Have Been There Already</h2>

<p>This release also fixes one of those maddening Unicode details that only becomes obvious after it breaks something important.</p>

<p>UnicodeFix now normalizes additional dash and hyphen variants, including the <strong>non-breaking hyphen</strong> (<code class="language-plaintext highlighter-rouge">U+2011</code>).</p>

<p>That matters because these characters are sneaky.
To a human reader they often look perfectly normal.
To a terminal, linter, parser, or diff tool, they are very much <em>not</em> normal.</p>

<p>So if you’ve ever had text that looked clean but still behaved strangely, this is exactly the kind of thing that causes it.</p>

<p>Now UnicodeFix catches more of those cases by default.</p>

<hr />

<h2 id="metrics-now-behave-like-a-person-thought-about-them">Metrics Now Behave Like a Person Thought About Them</h2>

<p>The <code class="language-plaintext highlighter-rouge">--metrics</code> feature got one of the most practical improvements in the entire release.</p>

<p>Before, the behavior around metrics could feel a little too clever in the wrong way.
You might ask for metrics and get output that wasn’t quite what you expected.
Or ask for cleaned output and wonder why the reporting behavior changed.</p>

<p>v1.2.1 makes that much clearer:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">cleanup-text --metrics file.txt</code> gives you a report</li>
  <li>if you explicitly ask for cleaned output with <code class="language-plaintext highlighter-rouge">-o</code> or <code class="language-plaintext highlighter-rouge">-t</code>, UnicodeFix still writes the cleaned file</li>
  <li>and now the report is emitted as a <strong>side report</strong>, so you can see what happened without losing the clean output you asked for</li>
</ul>

<p>That is a much better contract.</p>

<p>You say what you want.
The tool does that.
And it doesn’t make you decode its mood afterward.</p>

<hr />

<h2 id="reports-are-more-honest-now">Reports Are More Honest Now</h2>

<p>This is my favorite kind of fix: the kind that makes a tool more trustworthy.</p>

<p>UnicodeFix’s scanner/reporting logic now does a better job separating what is merely <strong>informational</strong> from what is actually an <strong>anomaly</strong>.</p>

<p>A good example is quote counting.</p>

<p>This release splits quote-like characters into more useful categories, so the tool can distinguish between:</p>

<ul>
  <li>normal ASCII quote characters</li>
  <li>Unicode quote-like characters that may actually be suspicious or worth cleaning</li>
</ul>

<p>That means if you clean a file and run it back through the tool, you are less likely to get a misleading “something is still wrong” vibe just because the file contains ordinary apostrophes or quotation marks.</p>

<p>That is a subtle change, but it matters a lot.
If a report tool overstates the problem, people stop trusting the report.</p>

<p>This release pushes UnicodeFix in the opposite direction:
<strong>fewer false alarms, clearer signal.</strong></p>

<hr />

<h2 id="a-quiet-but-important-python-compatibility-fix">A Quiet But Important Python Compatibility Fix</h2>

<p>UnicodeFix now behaves better across Python versions too.</p>

<p>There was a compatibility issue around <code class="language-plaintext highlighter-rouge">tomllib</code>, which is available in newer Python versions but not older ones like 3.9 and 3.10.
That got cleaned up by falling back to <code class="language-plaintext highlighter-rouge">tomli</code> where needed.</p>

<p>The result:</p>

<ul>
  <li>smoother installs on older supported Python versions</li>
  <li>better CI coverage</li>
  <li>fewer “works on my machine” moments</li>
</ul>

<p>And yes, the CI matrix was expanded too, because if you’re going to claim support, you should actually test it.</p>

<hr />

<h2 id="who-this-release-is-really-for">Who This Release Is Really For</h2>

<p>This update helps a few different kinds of people.</p>

<h3 id="if-youre-technical">If you’re technical</h3>

<p>You get:</p>

<ul>
  <li>a cleaner packaging story</li>
  <li>better CI behavior</li>
  <li>saner metrics/report interactions</li>
  <li>more accurate anomaly reporting</li>
  <li>fewer environment surprises</li>
</ul>

<h3 id="if-youre-not-especially-technical">If you’re not especially technical</h3>

<p>You get something just as valuable:</p>

<ul>
  <li>install it more easily</li>
  <li>run it with less confusion</li>
  <li>trust the output more quickly</li>
  <li>spend less time wondering whether the weirdness is your fault</li>
</ul>

<p>That is one of my favorite things about this release.
It improves the developer experience <strong>without</strong> making the tool more intimidating.</p>

<hr />

<h2 id="a-nice-example-of-what-polish-really-means">A Nice Example of What “Polish” Really Means</h2>

<p>People talk about polish like it’s decorative.</p>

<p>It usually isn’t.</p>

<p>Most of the time, polish is just this:</p>

<blockquote>
  <p>removing the little moments where software makes you stop and ask, “wait… what?”</p>
</blockquote>

<p>UnicodeFix v1.2.1 does a lot of that.</p>

<p>It doesn’t reinvent the project.
It makes the project feel more deliberate.</p>

<p>And for a tool that exists to clean up tiny hidden problems, that feels exactly right.</p>

<hr />

<h2 id="try-it">Try It</h2>

<p>If you’ve already been using UnicodeFix, this is a very easy upgrade to appreciate.</p>

<p>If you haven’t used it yet, this is a nice release to start with.</p>

<p>Use it when:</p>

<ul>
  <li>pasted text starts acting cursed</li>
  <li>your docs look normal but diff weirdly</li>
  <li>CI starts complaining about characters nobody can see</li>
  <li>you want a fast sanity check on whether a file is carrying invisible baggage</li>
</ul>

<p>UnicodeFix is still the same basic idea:
clean the text, remove the gremlins, move on with your life.</p>

<p>This release just makes that whole experience smoother.</p>

<hr />

<h2 id="in-short">In Short</h2>

<p>UnicodeFix v1.2.1 brings:</p>

<ul>
  <li>a unified install path</li>
  <li>better Conda/env behavior</li>
  <li>improved Unicode hyphen handling</li>
  <li>cleaner metrics/report behavior</li>
  <li>more accurate quote/anomaly reporting</li>
  <li>stronger Python compatibility and CI coverage</li>
</ul>

<p>Not flashy.
Very useful.
Exactly the kind of release you want in a tool that lives in your daily workflow.</p>

<hr />

<h2 id="get-it--support-it">Get It / Support It</h2>

<p>Repo, issues, and discussions:</p>

<ul>
  <li>https://github.com/unixwzrd/UnicodeFix</li>
</ul>

<p>UnicodeFix is used pretty widely now, which is great.
What it has not done particularly well is pay for the time it takes to keep improving it.</p>

<p>This project keeps moving because people use it, report weird edge-cases, open issues, send patches, and occasionally throw a little fuel on the fire so more of that work can happen.</p>

<p>If UnicodeFix has saved you time, cleaned up a mess, helped your workflow, or spared you one of those invisible-character debugging sessions that steals an afternoon, support is appreciated.</p>

<p>Support the work:</p>

<ul>
  <li><a href="https://patreon.com/unixwzrd">Patreon</a></li>
  <li><a href="https://ko-fi.com/unixwzrd">Ko-fi</a></li>
  <li><a href="https://buymeacoffee.com/unixwzrd">Buy Me a Coffee</a></li>
</ul>

<p>Bug reports welcome. PRs welcome. New glyph sightings especially welcome.</p>

<p>This project evolves because people keep finding new ways for text to become cursed.</p>

<p>UnicodeFix is how we un-curse it.</p>

<ul>
  <li>
    <ul>
      <li>Mia &amp; the unixwzrd*</li>
    </ul>
  </li>
</ul>]]></content><author><name>Distributed Thinking Systems</name><email>info@unixwzrd.ai</email></author><category term="UnicodeFix" /><category term="unicode" /><category term="python" /><category term="text-cleaning" /><category term="ai" /><category term="developer-tools" /><category term="open-source" /><summary type="html"><![CDATA[UnicodeFix v1.2.1 makes the tool easier to install, easier to trust, and much less likely to surprise you with confusing reports or rough edges.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://unixwzrd.ai/assets/images/projects/UnicodeFix/Wolf-Edition-Enhancements.png" /><media:content medium="image" url="https://unixwzrd.ai/assets/images/projects/UnicodeFix/Wolf-Edition-Enhancements.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">UnicodeFix - Wolf Edition v1.2.0 (It Solves Problems.) Now with API support.</title><link href="https://unixwzrd.ai/projects/UnicodeFix/2026/01/14/unicodefix-wolf-edition/" rel="alternate" type="text/html" title="UnicodeFix - Wolf Edition v1.2.0 (It Solves Problems.) Now with API support." /><published>2026-01-14T00:00:00-05:00</published><updated>2026-01-14T00:00:00-05:00</updated><id>https://unixwzrd.ai/projects/UnicodeFix/2026/01/14/UnicodeFix-Wolf-Edition</id><content type="html" xml:base="https://unixwzrd.ai/projects/UnicodeFix/2026/01/14/unicodefix-wolf-edition/"><![CDATA[<h2 id="unicodefix---wolf-edition-v120">UnicodeFix - Wolf Edition v1.2.0</h2>

<p>You ever paste text into a file and <em>immediately</em> know something’s wrong?</p>

<p>Not “logic wrong.”
Not “syntax wrong.”
More like… <strong>crime scene wrong</strong>.</p>

<p>The file <em>looks</em> fine. But your linter screams. Your CI fails. Your professor narrows their eyes. Your YAML config collapses like a cheap folding chair. And you’re sitting there thinking:</p>

<blockquote>
  <p>“It’s just text. Why does it feel like this text has… fingerprints?”</p>
</blockquote>

<p>That’s the entire reason UnicodeFix exists.</p>

<p>This release is what happens when a simple Unicode scrubber grows into something bigger:</p>

<ul>
  <li>part <strong>cleanup crew</strong></li>
  <li>part <strong>forensics unit</strong></li>
  <li>part <strong>workflow upgrade</strong></li>
  <li>and yes… part “please stop sprinkling invisible gremlins in my code.”</li>
</ul>

<p>If UnicodeFix were a character, it’s not just Jules and Vincent doing a chaotic drive-by on your source files.</p>

<p>It’s <strong>Jules</strong> and <strong>Vincent</strong>… plus <strong>Winston Wolf</strong> - <em>while Jimmy makes coffee with lots of cream and lots of sugar.</em></p>

<p>It solves problems.</p>

<hr />

<h2 id="the-problem-you-cant-see-but-ci-can">The Problem You Can’t See (But CI Can)</h2>

<p>A lot of Unicode trouble isn’t dramatic.</p>

<p>It’s not a glowing glyph with lightning bolts.</p>

<p>It’s the tiny stuff:</p>

<ul>
  <li>invisible whitespace that changes indentation</li>
  <li>zero-width characters that break diffs</li>
  <li>curly quotes that look like ASCII but aren’t</li>
  <li>ellipses that sneak into config or code comments</li>
  <li>bidirectional controls that can literally alter how text is displayed (yes, really)</li>
</ul>

<p>This can come from LLMs… but it doesn’t have to.</p>

<p>Unicode garbage shows up in:</p>

<ul>
  <li>chat apps</li>
  <li>web pages</li>
  <li>PDFs</li>
  <li>Office docs</li>
  <li>transcript generators</li>
  <li>iMessage exports</li>
  <li>“copy code” buttons</li>
  <li>log pipelines</li>
  <li><em>other people</em></li>
</ul>

<p>UnicodeFix doesn’t clean the PDF directly, obviously.</p>

<p>It cleans what you <em>extract</em> from it.</p>

<p>That distinction matters - because it’s where the <em>real power</em> is:</p>

<blockquote>
  <p>Instead of writing Unicode normalization logic into 17 different scripts, you keep one “cleanup brain” in one library.</p>
</blockquote>

<hr />

<h2 id="two-modes-cleaner--auditor-aka-body-work--forensics">Two Modes: Cleaner + Auditor (AKA: Body Work + Forensics)</h2>

<p>UnicodeFix has always been able to clean text.</p>

<p>Wolf Edition makes it explicit:</p>

<ul>
  <li><strong>Clean mode</strong>: remove Unicode quirks, normalize typographic junk, fix whitespace.</li>
  <li><strong>Audit mode</strong> (<code class="language-plaintext highlighter-rouge">--report</code>): scan text and tell you what you’re dealing with.</li>
</ul>

<p>In other words:</p>

<ul>
  <li>Clean mode is the cleanup crew with the bleach.</li>
  <li>Audit mode is CSI Las Vegas with a clipboard and a flashlight.</li>
</ul>

<p>Same tool. Two moods.</p>

<hr />

<h2 id="the-cli-is-nice-but-the-api-is-the-secret-weapon">The CLI Is Nice… But the API Is the Secret Weapon</h2>

<p>A lot of people treat UnicodeFix like a command:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cleanup-text draft.md
</code></pre></div></div>

<p>But the API is where it quietly becomes a <em>serious dev tool</em>.</p>

<p>Because the minute you’re doing extraction of any kind…</p>

<ul>
  <li>parsing a DB dump</li>
  <li>converting HTML</li>
  <li>exporting chat logs</li>
  <li>processing transcript text</li>
  <li>cleaning OCR output</li>
  <li>streaming decoded tokens from a local model</li>
</ul>

<p>…you want normalization <em>inside</em> the pipeline.</p>

<p>Not as an afterthought.</p>

<hr />

<h2 id="tutorial-drop-unicodefix-into-any-extraction-pipeline">Tutorial: Drop UnicodeFix Into Any Extraction Pipeline</h2>

<p>Here’s the trick:</p>

<p>1) extract the text
2) normalize it <em>once</em>
3) every downstream tool stays sane</p>

<h3 id="step-1---the-boundary-function-use-this-everywhere">Step 1 - The boundary function (use this everywhere)</h3>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="n">__future__</span> <span class="kn">import</span> <span class="n">annotations</span>

<span class="kn">from</span> <span class="n">unicodefix.transforms</span> <span class="kn">import</span> <span class="n">clean_text</span><span class="p">,</span> <span class="n">handle_newlines</span>


<span class="k">def</span> <span class="nf">normalize_extracted_text</span><span class="p">(</span><span class="n">raw</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
 <span class="sh">"""</span><span class="s">
 Your </span><span class="sh">'</span><span class="s">Winston Wolf</span><span class="sh">'</span><span class="s"> function:
 call this right after extraction from PDF/html/chat/db/logs/etc.
 </span><span class="sh">"""</span>
 <span class="n">cleaned</span> <span class="o">=</span> <span class="nf">clean_text</span><span class="p">(</span><span class="n">raw</span><span class="p">)</span>
 <span class="k">return</span> <span class="nf">handle_newlines</span><span class="p">(</span><span class="n">cleaned</span><span class="p">)</span>
</code></pre></div></div>

<p>This is boring code.</p>

<p>Boring is good.</p>

<p>Boring means it works at 2:00 AM, with CI screaming at you, while someone’s asking why the release tag didn’t build.</p>

<hr />

<h2 id="real-example-imessage--chat-export-recovery">Real Example: iMessage / Chat Export Recovery</h2>

<p>This is one of my favorite use-cases because it’s so “non-AI.”</p>

<p>You extract iMessage text (or other chat logs) from a database.</p>

<p>You get:</p>

<ul>
  <li>odd non-breaking spaces</li>
  <li>weird line ending styles</li>
  <li>invisible marks</li>
  <li>formatting junk you never typed</li>
</ul>

<p>You could handle it everywhere…</p>

<p>Or you do this once:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="n">unicodefix.transforms</span> <span class="kn">import</span> <span class="n">clean_text</span><span class="p">,</span> <span class="n">handle_newlines</span>

<span class="k">def</span> <span class="nf">normalize_chat_text</span><span class="p">(</span><span class="n">message</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
 <span class="k">return</span> <span class="nf">handle_newlines</span><span class="p">(</span><span class="nf">clean_text</span><span class="p">(</span><span class="n">message</span><span class="p">))</span>
</code></pre></div></div>

<p>Now every exporter, formatter, report generator, and PDF builder in your pipeline benefits automatically.</p>

<p>That’s the “one brain / many scripts” win.</p>

<hr />

<h2 id="audit-mode-counting-the-mess-before-you-clean-it">Audit Mode: Counting the Mess Before You Clean It</h2>

<p>Here’s where Wolf Edition gets fun.</p>

<p>Audit mode will scan text and report anomalies like:</p>

<ul>
  <li>zero-width spaces</li>
  <li>smart quotes</li>
  <li>Unicode separators and NBSP variants</li>
  <li>bidi controls</li>
  <li>trailing whitespace lines</li>
  <li>missing final newline</li>
  <li>replacement characters (U+FFFD)</li>
</ul>

<p>Run it like this:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cleanup-text <span class="nt">--report</span> notes.md
</code></pre></div></div>

<p>Want machine-friendly output?</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cleanup-text <span class="nt">--report</span> <span class="nt">--json</span> notes.md
</code></pre></div></div>

<p>Now you can treat Unicode weirdness like lint.</p>

<p>Which is the entire point.</p>

<hr />

<h2 id="metrics-mode-is-this-text-suspicious">Metrics Mode: “Is This Text… Suspicious?”</h2>

<p>Now let’s talk about the professor angle - because yes, UnicodeFix can play both sides.</p>

<p>Wolf Edition added <strong>semantic metrics</strong> (optional):</p>

<ul>
  <li>entropy</li>
  <li>ascii ratio</li>
  <li>repetition ratio</li>
  <li>sentence-length variability (“burstiness”)</li>
  <li>stopword ratio</li>
  <li>and a heuristic “AI score”</li>
</ul>

<p>To enable it:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cleanup-text <span class="nt">--report</span> <span class="nt">--metrics</span> essay.md
</code></pre></div></div>

<p>This installs NLTK resources (tokenizers etc) via the optional extra:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pip <span class="nb">install </span>unicodefix[nlp]
</code></pre></div></div>

<h3 id="important-note">Important note</h3>

<p>This is not a magical “AI detector.”</p>

<p>It’s a dashboard.</p>

<p>It’s the difference between:</p>

<ul>
  <li>“this <em>feels</em> AI-generated”</li>
  <li>and “here are measurable signals that explain why it feels that way”</li>
</ul>

<p>And yes: professors love that kind of thing.</p>

<p>So do reviewers.</p>

<p>So do paranoid devs.</p>

<p>So do people who are tired of Unicode daemons in production.</p>

<hr />

<h2 id="cicd-the-clock-is-ticking-and-wolf-doesnt-have-time-for-excuses">CI/CD: The Clock Is Ticking (And Wolf Doesn’t Have Time for Excuses)</h2>

<p>UnicodeFix is tested in GitHub Actions across:</p>

<ul>
  <li>Ubuntu Linux</li>
  <li>macOS</li>
  <li>Python 3.9, 3.10, 3.11, 3.12</li>
</ul>

<p>That matters because Unicode problems are often platform-flavored.</p>

<p>Different terminals, different default encodings, different newline behavior, different tools.</p>

<p>This pipeline doesn’t just test Python unit tests - it runs integration tests and newline preservation checks too.</p>

<p>That last part is huge.</p>

<p>Because stripping or rewriting newlines is one of those “quiet disasters” that doesn’t show up until you’ve destroyed a file and a human has to untangle it.</p>

<p>UnicodeFix does the opposite:</p>

<blockquote>
  <p>clean the mess, preserve the structure.</p>
</blockquote>

<hr />

<h2 id="the-joke-thats-also-true">The Joke That’s Also True</h2>

<p>There’s a scene in <em>Pulp Fiction</em> where Winston Wolf calmly walks into chaos and basically says:</p>

<blockquote>
  <p>“If you do what I say, when I say it, we’re gonna be okay.”</p>
</blockquote>

<p>UnicodeFix does that for text.</p>

<p>You’ve got invisible debris everywhere:</p>

<ul>
  <li>little bits of ZWSP</li>
  <li>pools of NBSP</li>
  <li>splashes of bidi controls</li>
  <li>curly quotes pretending to be innocent civilians</li>
</ul>

<p>UnicodeFix is the guy who shows up with:</p>

<ul>
  <li>cleaning products</li>
  <li>metrics</li>
  <li>a report</li>
  <li>a plan</li>
</ul>

<p>And yes:</p>

<ul>
  <li>It’s a floor wax.</li>
  <li>It’s a dessert topping.</li>
  <li>It’s a cleaner <em>and</em> an auditor.</li>
</ul>

<hr />

<h2 id="get-it--support-it">Get It / Support It</h2>

<p>Repo + issues + discussions:</p>

<ul>
  <li>https://github.com/unixwzrd/UnicodeFix</li>
</ul>

<p>Support the work (coffee fuels commits):</p>

<ul>
  <li><a href="https://patreon.com/unixwzrd">Patreon</a></li>
  <li><a href="https://ko-fi.com/unixwzrd">Ko-fi</a></li>
  <li><a href="https://buymeacoffee.com/unixwzrd">Buy Me a Coffee</a></li>
</ul>

<p>Bug reports welcome. PRs welcome. New glyph sightings especially welcome.</p>

<p>This project evolves because people keep finding new ways for text to become cursed.</p>

<p>UnicodeFix is how we un-curse it.</p>

<ul>
  <li>
    <ul>
      <li>Mia &amp; the unixwzrd*</li>
    </ul>
  </li>
</ul>]]></content><author><name>Distributed Thinking Systems</name><email>info@unixwzrd.ai</email></author><category term="UnicodeFix" /><category term="unicode" /><category term="python" /><category term="text-cleaning" /><category term="ai" /><category term="developer-tools" /><category term="open-source" /><summary type="html"><![CDATA[UnicodeFix isn't just a CLI. It's Winston Wolf for your text pipelines: clean it, audit it, score it, ship it.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://unixwzrd.ai/assets/images/projects/UnicodeFix/Wolf-Edition.png" /><media:content medium="image" url="https://unixwzrd.ai/assets/images/projects/UnicodeFix/Wolf-Edition.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">UnicodeFix Levels Up: Metrics, Forensics, and Bracket Discipline</title><link href="https://unixwzrd.ai/projects/UnicodeFix/2025/11/15/unicodefix-minor-updates/" rel="alternate" type="text/html" title="UnicodeFix Levels Up: Metrics, Forensics, and Bracket Discipline" /><published>2025-11-15T00:00:00-05:00</published><updated>2025-11-15T00:00:00-05:00</updated><id>https://unixwzrd.ai/projects/UnicodeFix/2025/11/15/UnicodeFix-Minor-Updates</id><content type="html" xml:base="https://unixwzrd.ai/projects/UnicodeFix/2025/11/15/unicodefix-minor-updates/"><![CDATA[<h2 id="unicodefix-grew-a-brain">UnicodeFix Grew a Brain</h2>

<p>Last time I wrote about UnicodeFix, it was in full CodExorcism mode:
burn the smart quotes, banish zero-width daemons, normalize ellipses, and make Codex’s Unicode gremlins someone else’s problem.</p>

<p>Since then, the tool did what all good exorcists eventually do:
it learned to <strong>take notes on the hauntings.</strong></p>

<p>The current release line is:</p>

<blockquote>
  <p><strong>UnicodeFix - CodExorcism Edition+ v1.1.3</strong></p>
</blockquote>

<p>Same mission (wipe AI breadcrumbs and Unicode trash), but now it can <strong>analyze</strong> what it just cleaned - and tell you how weird your text looked before the ritual.</p>

<hr />

<h2 id="from-just-clean-it-to-show-me-the-crime-scene">From “Just Clean It” to “Show Me the Crime Scene”</h2>

<p>The big change is that UnicodeFix is no longer just a firehose; it’s also a <strong>forensics report</strong>.</p>

<p>You still have the classic “make this text not suck” workflows:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Filter mode (STDIN → STDOUT)</span>
<span class="nb">cat </span>draft.md | cleanup-text <span class="o">&gt;</span> draft.clean.md

<span class="c"># Batch clean</span>
cleanup-text <span class="k">*</span>.txt

<span class="c"># In-place, with temp file safety</span>
cleanup-text <span class="nt">-t</span> important.txt
</code></pre></div></div>

<p>But now there’s a whole analysis layer bolted on top:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Human-readable audit</span>
cleanup-text <span class="nt">--report</span> notes.md

<span class="c"># JSON report (for scripts/CI)</span>
cleanup-text <span class="nt">--report</span> <span class="nt">--json</span> notes.md

<span class="c"># Add experimental semantic metrics</span>
cleanup-text <span class="nt">--report</span> <span class="nt">--json</span> <span class="nt">--metrics</span> essay.md
</code></pre></div></div>

<h3 id="what-the-metrics-do-and-dont-do">What the Metrics Do (and Don’t Do)</h3>

<p>Turn on <code class="language-plaintext highlighter-rouge">--metrics</code> and UnicodeFix will attach a <strong>metrics block</strong> to the report:</p>

<ul>
  <li>Entropy / diversity</li>
  <li>ASCII vs Unicode ratios</li>
  <li>Repetition patterns</li>
  <li>A heuristic “AI-likeness” score</li>
</ul>

<p>This is <strong>not</strong> a magical AI-detector. It’s a <strong>dashboard</strong>:</p>

<ul>
  <li>“Why does this look machine-generated?”</li>
  <li>“Why is this file full of weird Unicode when the rest of the repo isn’t?”</li>
  <li>“Why did my CI suddenly start yelling at me?”</li>
</ul>

<p>Pair it with:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">--metrics-help</code> for a friendly legend (and ↑/↓ hints)</li>
  <li><code class="language-plaintext highlighter-rouge">--exit-zero</code> to keep CI/pre-commit runs informative without breaking your flow</li>
  <li><code class="language-plaintext highlighter-rouge">--threshold</code> when you <em>do</em> want to fail the pipeline if things get too spooky</li>
</ul>

<p>Example:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Warn, don't break commits</span>
cleanup-text <span class="nt">--report</span> <span class="nt">--metrics</span> <span class="nt">--exit-zero</span> src/<span class="k">**</span>/<span class="k">*</span>.py

<span class="c"># Fail CI if anomalies cross your line in the sand</span>
cleanup-text <span class="nt">--report</span> <span class="nt">--threshold</span> 1 docs/<span class="k">**</span>/<span class="k">*</span>.md
</code></pre></div></div>

<hr />

<h2 id="unicode-discipline-fullwidth-brackets--friends">Unicode Discipline: Fullwidth Brackets &amp; Friends</h2>

<p>The 2025-11-15 update (v1.1.3) did a little Unicode housekeeping too:</p>

<ul>
  <li><strong>Fullwidth square brackets</strong> <code class="language-plaintext highlighter-rouge">[]</code> now fold to ASCII <code class="language-plaintext highlighter-rouge">[]</code> <strong>by default</strong>
    <ul>
      <li>keeps tables, code blocks, and terminal output aligned</li>
    </ul>
  </li>
  <li>If you’re doing something visual/typographic and you <em>want</em> the fullwidth flavor:</li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cleanup-text <span class="nt">--keep-fullwidth-brackets</span> manuscript.md
</code></pre></div></div>

<p>The dagger <code class="language-plaintext highlighter-rouge">†</code> (e.g., for footnote markers) is left alone.
We’re exorcising daemons, not your typography.</p>

<p>There’s also a small helper for <strong>display-only folding</strong> if you want to keep your source text intact but render it in ASCII for terminals:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">unicodefix.transforms.fold_for_terminal_display(text)</code></li>
</ul>

<p>Use it when you want clean-looking logs without mutating the original content.</p>

<hr />

<h2 id="test-harness-less-ceremony-more-coverage">Test Harness: Less Ceremony, More Coverage</h2>

<p>The test suite grew up too.</p>

<p>Instead of a thicket of bespoke scripts, there’s now a single entry point:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tests/test_all.sh
</code></pre></div></div>

<p>What it does:</p>

<ul>
  <li>Builds its run list automatically from <code class="language-plaintext highlighter-rouge">data/</code></li>
  <li>Exercises all the main scenarios:
    <ul>
      <li>default clean</li>
      <li>invisible-preserving (<code class="language-plaintext highlighter-rouge">-i</code>)</li>
      <li>no-newline (<code class="language-plaintext highlighter-rouge">-n</code>)</li>
      <li>custom output (<code class="language-plaintext highlighter-rouge">-o</code>)</li>
      <li>in-place (<code class="language-plaintext highlighter-rouge">-t</code> / <code class="language-plaintext highlighter-rouge">-t -p</code>)</li>
      <li>STDIN/STDOUT filter mode</li>
    </ul>
  </li>
  <li>Drops <strong>diffs</strong> and <strong>word-count comparisons</strong> into <code class="language-plaintext highlighter-rouge">test_output/&lt;scenario&gt;/</code></li>
</ul>

<p>Binary fixtures are sensibly skipped in STDIN/STDOUT mode so the run doesn’t explode on UTF-8 decoding.</p>

<p>Cleanup is one command away:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tests/test_all.sh clean
</code></pre></div></div>

<p>If you’re wiring UnicodeFix into CI, this harness is basically your paranoia button: push it before you publish, push it before you grade, push it before you merge PRs that smell like AI copy-paste.</p>

<hr />

<h2 id="install--upgrade-in-60-seconds">Install / Upgrade in 60 Seconds</h2>

<p>The installer path also got cleaned up and clarified.</p>

<p>Fresh install:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://github.com/unixwzrd/UnicodeFix.git
<span class="nb">cd </span>UnicodeFix

./setup.sh               <span class="c"># creates a venv and installs dependencies</span>

<span class="c"># Standard usage</span>
pip <span class="nb">install</span> <span class="nb">.</span>

<span class="c"># Dev/editable mode</span>
pip <span class="nb">install</span> <span class="nt">-e</span> <span class="nb">.</span>

<span class="c"># With optional NLP metrics support</span>
pip <span class="nb">install</span> .[nlp]
</code></pre></div></div>

<p>The README and <code class="language-plaintext highlighter-rouge">setup.sh</code> now actually explain what just happened, how to activate the env, and how to get from “clone repo” to “cleanup-text on PATH” without spelunking.</p>

<hr />

<h2 id="real-world-use-cases-now-with-forensics">Real-World Use Cases (Now With Forensics)</h2>

<h3 id="students">Students</h3>

<ul>
  <li>Clean AI-assisted code before handing it in</li>
  <li>Run <code class="language-plaintext highlighter-rouge">--report --metrics</code> on your own work to understand <strong>why</strong> it looks suspicious</li>
  <li>Use <code class="language-plaintext highlighter-rouge">--exit-zero</code> so your local checks warn you without blocking the compile/push cycle</li>
</ul>

<h3 id="devs">Devs</h3>

<ul>
  <li>Put <code class="language-plaintext highlighter-rouge">cleanup-text --report --threshold N</code> into CI to catch sketchy Unicode in PRs</li>
  <li>Run <code class="language-plaintext highlighter-rouge">cleanup-text -t</code> on config files, docs, and scripts cloned from random Gists</li>
  <li>Keep logs / emails / release notes looking hand-typed instead of LLM-sprayed</li>
</ul>

<h3 id="writers--bloggers">Writers / Bloggers</h3>

<ul>
  <li>Use <code class="language-plaintext highlighter-rouge">-Q</code> and <code class="language-plaintext highlighter-rouge">-D</code> to <strong>keep</strong> smart quotes and em dashes where you actually want them</li>
  <li>Let UnicodeFix handle the invisible junk, weird spaces, and stray AI fingerprints</li>
  <li>Run <code class="language-plaintext highlighter-rouge">--report</code> on drafts to see where editors/LLMs have been “helpful” behind your back</li>
</ul>

<hr />

<h2 id="tldr">TL;DR</h2>

<p>Since the last CodExorcism post, UnicodeFix:</p>

<ul>
  <li><strong>Added analytics</strong>: <code class="language-plaintext highlighter-rouge">--report</code>, <code class="language-plaintext highlighter-rouge">--json</code>, <code class="language-plaintext highlighter-rouge">--metrics</code>, <code class="language-plaintext highlighter-rouge">--metrics-help</code>, <code class="language-plaintext highlighter-rouge">--threshold</code>, <code class="language-plaintext highlighter-rouge">--exit-zero</code></li>
  <li><strong>Slimmed and hardened the test suite</strong>: <code class="language-plaintext highlighter-rouge">tests/test_all.sh</code> drives everything from <code class="language-plaintext highlighter-rouge">data/</code></li>
  <li><strong>Tightened Unicode behavior</strong>: default folding for fullwidth square brackets with an escape hatch flag</li>
  <li><strong>Polished the installer and docs</strong> so the path from “clone” to “clean” is straightforward</li>
</ul>

<p>Same attitude, sharper tools.</p>

<p>If you’re already using UnicodeFix, pull the latest and run your usual workflows with <code class="language-plaintext highlighter-rouge">--report</code> once - it’s weirdly satisfying to watch your own files get roasted in the terminal.</p>

<p>If you’re new:</p>

<ul>
  <li>Repo: <a href="https://github.com/unixwzrd/UnicodeFix">https://github.com/unixwzrd/UnicodeFix</a></li>
  <li>Shortcut, tests, docs, and screenshots are all in there.</li>
</ul>

<p>The Unicode arms race isn’t slowing down.
At least your side has better metrics now.</p>]]></content><author><name>Distributed Thinking Systems</name><email>info@unixwzrd.ai</email></author><category term="UnicodeFix" /><category term="unicode" /><category term="python" /><category term="text-cleaning" /><category term="ai" /><category term="developer-tools" /><category term="open-source" /><summary type="html"><![CDATA[UnicodeFix grew a dashboard in your terminal: reports, metrics, and stricter Unicode discipline - same exorcism, more forensics.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://unixwzrd.ai/assets/images/projects/UnicodeFix/LevelsUp.png" /><media:content medium="image" url="https://unixwzrd.ai/assets/images/projects/UnicodeFix/LevelsUp.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Parental Alienation Awareness - Introduction</title><link href="https://unixwzrd.ai/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-introduction/" rel="alternate" type="text/html" title="Parental Alienation Awareness - Introduction" /><published>2025-09-25T00:00:00-04:00</published><updated>2025-09-25T00:00:00-04:00</updated><id>https://unixwzrd.ai/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-introduction</id><content type="html" xml:base="https://unixwzrd.ai/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-introduction/"><![CDATA[<p>Welcome to the Parental Alienation Awareness project blog. Here we share research-based insights on the scope, impact, and damage of parental alienation to children, families, and society.</p>

<!--more-->

<ul>
  <li><a href="#about-parental-alienation-awareness">About Parental Alienation Awareness</a></li>
  <li><a href="#research-paper-sections">Research Paper Sections</a></li>
  <li><a href="#references">References</a></li>
  <li><a href="#get-involved">Get Involved</a>
    <ul>
      <li><a href="#get-involved--raise-awareness"><strong>Get Involved / Raise Awareness</strong></a></li>
    </ul>
  </li>
  <li><a href="#navigation">Navigation</a></li>
</ul>

<h2 id="about-parental-alienation-awareness">About Parental Alienation Awareness</h2>

<p>Parental Alienation Awareness: A comprehensive research paper examining the scope, impact, and damage of parental alienation to children, families, and society. Our research provides evidence-based analysis of this widespread but often misunderstood phenomenon.</p>

<h2 id="research-paper-sections">Research Paper Sections</h2>

<p>Our comprehensive research paper is organized into five interconnected sections:</p>

<ol>
  <li>
    <p><strong><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-part-1/">Prevalence and Scope of Parental Alienation</a></strong> - How common is parental alienation and who is affected?</p>
  </li>
  <li>
    <p><strong><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-part-2/">Perpetrators and Victims: Who Alienates and Who Is Alienated</a></strong> - Understanding the dynamics of alienation relationships.</p>
  </li>
  <li>
    <p><strong><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-part-3/">Harms and Consequences for Children and Parents</a></strong> - The lasting impact on families.</p>
  </li>
  <li>
    <p><strong><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-part-4/">Divorce, Custody Disputes, and the Legal System</a></strong> - How the legal system addresses and sometimes exacerbates alienation.</p>
  </li>
  <li>
    <p><strong><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-part-5/">Systemic and Societal Impact</a></strong> - The broader consequences for society.</p>
  </li>
</ol>

<h2 id="references">References</h2>

<p>All sections of this research paper include comprehensive citations and references available in our <a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/">References section</a>.</p>

<h2 id="get-involved">Get Involved</h2>

<h3 id="get-involved--raise-awareness"><strong>Get Involved / Raise Awareness</strong></h3>

<p>If you want to help change this, please check out <a href="https://www.change.org/p/make-parental-alienation-a-crime">this petition to make parental alienation a crime</a>.</p>

<p>If you have a story, or just want to connect, <a href="/contact/">contact me here</a>.</p>

<p>And if you know someone going through this-share this page with them. Sometimes the worst part of alienation is thinking you’re alone.</p>

<p>We welcome contributions and feedback. Here’s how you can get involved:</p>

<ul>
  <li>Review the sections of our research paper</li>
  <li>Share insights and experiences</li>
  <li>Provide feedback on our analysis</li>
  <li>Contribute to raising awareness</li>
</ul>

<p><a href="/contact/">Contact us</a> to learn more about participating in this project.</p>

<hr />

<hr />

<h2 id="navigation">Navigation</h2>

<table style="width: 100%; table-layout: fixed;">
<tr>
<td style="width: 100%; text-align: center;"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-part-1/">Part 1: Prevalence and Scope of Parental Alienation →</a></td>
</tr>
</table>]]></content><author><name>Distributed Thinking Systems</name><email>info@unixwzrd.ai</email></author><category term="PA-Awareness-1" /><category term="introduction" /><category term="overview" /><category term="parental-alienation" /><category term="research" /><category term="advocacy" /><summary type="html"><![CDATA[Welcome to the Parental Alienation Awareness project blog. Here we share research-based insights on the scope, impact, and damage of parental alienation to children, families, and society.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://unixwzrd.ai/assets/images/projects/PA-devastation-1.png" /><media:content medium="image" url="https://unixwzrd.ai/assets/images/projects/PA-devastation-1.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Parental Alienation Awareness - Part 1</title><link href="https://unixwzrd.ai/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-part-1/" rel="alternate" type="text/html" title="Parental Alienation Awareness - Part 1" /><published>2025-09-25T00:00:00-04:00</published><updated>2025-09-25T00:00:00-04:00</updated><id>https://unixwzrd.ai/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-part-1</id><content type="html" xml:base="https://unixwzrd.ai/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-part-1/"><![CDATA[<h2 id="1-prevalence-and-scope-of-parental-alienation">1. Prevalence and Scope of Parental Alienation</h2>

<p><strong>How common is parental alienation?</strong> Recent research indicates it is far from rare. A landmark 2016 study using a representative U.S. survey found that <strong>13.4% of parents</strong> reported being alienated from at least one child<sup id="ref-source-1_1_0_2_21_28"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_1_0_2_21_28">[1]</a></sup>. This equated to roughly <strong>22 million American parents</strong> at that time<sup id="ref-source-1_1_0_4_334_343"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_1_0_4_334_343">[1]</a></sup> - implying tens of millions of children potentially affected (since many targeted parents have more than one child)<sup id="ref-source-1_1_0_4_340_348"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_1_0_4_340_348">[1]</a></sup>. In fact, the authors estimate <strong>between 22-44 million U.S. children</strong> could be experiencing some level of parental alienation in their family<a id="ref-source-1_1_1_4_340_348"></a>.</p>

<p>More recent surveys suggest even higher exposure when broader “alienating behaviors” are considered. In 2018-2019, Harman et al. conducted national polls in the U.S. and Canada: <strong>35.5% of U.S. parents</strong> and <strong>32% of Canadian parents</strong> reported that their co-parent had engaged in <strong>parental alienating behaviors (PABs)</strong> - i.e. behaviors intended to damage the parent-child relationship<sup id="ref-source-1_2_0_8_25_33"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_2_0_8_25_33">[2]</a></sup>. Using a more detailed assessment, a third U.S. sample found <strong>39.1%</strong> of American parents to be <strong>targets of alienation attempts</strong> by the other parent<a id="ref-source-1_2_0_8_27_35"></a>. These findings <strong>confirm earlier estimates</strong> - on the order of 22 million U.S. parents affected - but also show that <strong>over one-third of separated/divorced parents experience alienating tactics</strong><a id="ref-source-1_2_0_8_27_36"></a><sup id="ref-source-1_3_0_9_1375_1383"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_3_0_9_1375_1383">[3]</a></sup>. Not all of these cases result in a fully “alienated” child, but they reveal how widespread the <em>attempts</em> at alienation are.</p>

<p><img src="/assets/images/PA-Awareness-1/us-states-with-the-highest-divorce-rate.jpg" alt="Figure 1: States with Highest Divorce Rates" /></p>

<p style="text-align: center;"><em>Figure 1: States with Highest Divorce Rates. The states with the highest divorce rates are typically higher in the South, though Nevada is an outlier due to no-fault divorce laws, people from other states are likely to claim Nevada residence to get a divorce.</em></p>

<p>International data echo these patterns. A 2025 U.K. survey of 1,000 separated parents (Hine et al.) found <strong>39.2%</strong> of respondents directly acknowledged experiencing parental alienating behaviors - and when presented with specific examples of such behaviors, the rate jumped to <strong>59.1%</strong><sup id="ref-source-1_4_0_11_153_161"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_4_0_11_153_161">[4]</a></sup>. In other words, well over half of separated parents in that UK sample had encountered some form of alienation tactics. This study also noted that these behaviors often co-occur with other abuse (the use of children as “a conduit for abuse” by one parent)<a id="ref-source-1_4_1_11_153_161"></a>. Taken together, research from North America and Europe makes clear that <strong>parental alienation is a common phenomenon across demographics and borders</strong><sup id="ref-source-1_3_0_9_1379_1388"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_3_0_9_1379_1388">[3]</a></sup>.</p>

<p><strong>How many children are affected?</strong> Estimating child prevalence is challenging, since not all children subjected to alienating behaviors become fully “alienated”<sup id="ref-source-1_2_0_8_61_69"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_2_0_8_61_69">[2]</a></sup>. Earlier analyses approximated that around <strong>1% of children</strong> in the U.S. were alienated from a parent - roughly <strong>740,000 minors</strong> - based on divorce rates and high-conflict custody disputes circa 2010<sup id="ref-source-1_5_0_2_75_83"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_5_0_2_75_83">[5]</a></sup>. Newer data suggest this may be an underestimate. In the U.S. polls above, <strong>6.7% of all parents</strong> surveyed said <strong>their child(ren) were moderately to severely alienated</strong> from them<sup id="ref-source-1_2_0_8_33_39"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_2_0_8_33_39">[2]</a></sup>. This corresponds to <strong>at least ~1.3% of the U.S. population</strong> (if extrapolated nationally)<a id="ref-source-1_2_1_8_33_39"></a>, which would mean on the order of <strong>4+ million children</strong> experiencing serious alienation. One commentary even described parental alienation as a “silent epidemic,” noting that <strong>over 22 million American adults</strong> have been targets, including <strong>10 million who perceive their alienation as <em>severe</em></strong><sup id="ref-source-1_6_0_5_250_258"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_6_0_5_250_258">[6]</a></sup>. Globally, precise numbers are harder to come by, but if roughly 1 in 5 separated families worldwide experience these issues, the affected children likely number in the <strong>tens of millions</strong>.</p>

<p><strong>Demographic breakdown:</strong> Parental alienation appears in all types of families - across socioeconomic, racial, and educational lines<sup id="ref-source-1_1_0_2_25_33"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_1_0_2_25_33">[1]</a></sup>. The 2016 U.S. survey found targeted parents in every demographic, though <strong>Black/African-American and Native American parents were over-represented</strong> among those experiencing alienation (and Asian-American parents under-represented)<sup id="ref-source-1_1_0_2_29_36"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_1_0_2_29_36">[1]</a></sup><a id="ref-source-1_1_0_4_362_370"></a>. There was no strong gender skew in that representative sample - <strong>fathers were only slightly (and not significantly) more likely than mothers</strong> to report being the alienated/targeted parent<sup id="ref-source-1_3_0_13_219_227"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_3_0_13_219_227">[3]</a></sup>. This aligns with broader evidence that <strong>both mothers and fathers can be perpetrators or victims</strong>. Historically, when mothers more often had primary custody, experts observed more mothers as alienators (Dr. Richard Gardner initially reported ~90% of alienating parents were mothers in the 1980s). However, as custody roles have evened out, modern estimates indicate an <strong>approximately 50/50 gender split</strong> in alienation cases. In short, <strong>either parent can be the alienator or the targeted parent</strong>, and cases span all ages and family structures. Notably, while most documented alienation occurs in divorced or separated families, it <strong>can also occur in intact families</strong> - one parent may undermine the other’s relationship with the child even without a divorce<sup id="ref-source-1_1_0_2_83_90"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_1_0_2_83_90">[1]</a></sup>. Step-parents or other relatives (grandparents, guardians) can also participate in alienating behaviors in some cases<sup id="ref-source-1_2_0_8_43_51"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_2_0_8_43_51">[2]</a></sup>, though typically as part of a campaign led by one parent.</p>

<p><em>Table 1: Prevalence of Parental Alienation</em></p>

<table>
  <thead>
    <tr>
      <th><strong>Metric (Latest Estimates)</strong></th>
      <th><strong>United States</strong></th>
      <th><strong>International</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Adults who report being <strong>targeted</strong> by parental alienation</td>
      <td>~22 million (≈9% of U.S. adults; 13.4% of parents)<sup id="ref-source-1_1_1_2_21_28"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_1_1_2_21_28">[1]</a></sup><a id="ref-source-1_1_1_4_334_343"></a></td>
      <td>U.K.: ~39% of separated parents (59% when prompted)<sup id="ref-source-1_4_2_11_153_161"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_4_2_11_153_161">[4]</a></sup>; Canada: ~32% of parents<sup id="ref-source-1_2_1_8_25_33"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_2_1_8_25_33">[2]</a></sup></td>
    </tr>
    <tr>
      <td>Children who are <strong>moderately-severely alienated</strong> from a parent</td>
      <td>~4 million (estimated 1.3% of U.S. population)<sup id="ref-source-1_2_2_8_33_39"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_2_2_8_33_39">[2]</a></sup>; older estimate ~740,000 (1% of U.S. children)<sup id="ref-source-1_5_1_2_75_83"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_5_1_2_75_83">[5]</a></sup></td>
      <td>No precise national data; assumed proportionally similar in other countries</td>
    </tr>
    <tr>
      <td><strong>High-conflict custody cases</strong> involving alienation</td>
      <td>~25% of high-conflict divorces (Bernet 2010)<a id="ref-source-1_5_2_2_75_83"></a> - roughly 5% of all U.S. divorces (see Section 4)</td>
      <td>U.K.: CAFCASS reports alienation in ~80% of most difficult cases<sup id="ref-source-1_8_0_35_75_83"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_8_0_35_75_83">[7]</a></sup> (~200k cases/yr)</td>
    </tr>
  </tbody>
</table>

<hr />

<h2 id="navigation">Navigation</h2>

<table style="width: 100%; table-layout: fixed;">
<tr>
<td style="width: 50%; text-align: left;"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-introduction/">← Introduction</a></td>
<td style="width: 50%; text-align: right;"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-part-2/">Part 2: Perpetrators and Victims →</a></td>
</tr>
</table>]]></content><author><name>Distributed Thinking Systems</name><email>info@unixwzrd.ai</email></author><category term="PA-Awareness-1" /><category term="parental-alienation" /><category term="research" /><category term="prevalence" /><category term="scope" /><summary type="html"><![CDATA[How common is parental alienation? Recent research indicates it affects millions of parents and children across demographics and borders.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://unixwzrd.ai/assets/images/projects/PA-devastation-1.png" /><media:content medium="image" url="https://unixwzrd.ai/assets/images/projects/PA-devastation-1.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Parental Alienation Awareness - Part 2</title><link href="https://unixwzrd.ai/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-part-2/" rel="alternate" type="text/html" title="Parental Alienation Awareness - Part 2" /><published>2025-09-25T00:00:00-04:00</published><updated>2025-09-25T00:00:00-04:00</updated><id>https://unixwzrd.ai/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-part-2</id><content type="html" xml:base="https://unixwzrd.ai/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-part-2/"><![CDATA[<h2 id="2-perpetrators-and-victims-who-alienates-and-who-is-alienated">2. Perpetrators and Victims: Who Alienates, and Who Is Alienated?</h2>

<p><strong>Common perpetrators:</strong> Parental alienation can be perpetrated by mothers or fathers - <strong>both genders engage in alienating behavior at comparable rates in modern samples</strong><sup id="ref-source-1_3_1_13_219_227"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_3_1_13_219_227">[3]</a></sup>. The stereotype of the vengeful divorced mother turning the kids against the father (which arose in the 1980s when mothers often had primary custody) is no longer the whole story. Dr. Richard Gardner, who first coined “Parental Alienation Syndrome,” initially believed mothers were the alienators in 90% of cases, but <strong>he later revised that to 50/50</strong> as societal roles shifted. Today’s research consistently finds <strong>fathers can be alienators just as often</strong> - any parent with sufficient influence over the child can attempt to poison the child’s relationship with the other parent. For example, in one representative U.S. poll, 54% of the self-identified targeted parents were fathers and 46% were mothers (a non-significant difference)<a id="ref-source-1_3_2_13_219_227"></a>. In short, <strong>parental alienation is not a one-gender issue</strong> - moms and dads are both culpable in different cases.</p>

<p>It’s worth noting that <strong>extended family and others may also play a role</strong>. The alienating parent is usually the primary caregiver or the parent the child resides with most, but they may enlist support from step-parents, grandparents, or even professionals to reinforce the alienation<sup id="ref-source-1_2_1_8_43_51"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_2_1_8_43_51">[2]</a></sup>. For instance, an alienating mother might have her own parents (the child’s grandparents) repeat negative messages about the father; an alienating father might have a new spouse who helps exclude the mother. In some extreme cases, even court-appointed officials (like a biased guardian ad litem) could <strong>unwittingly become “third-party” alienators</strong><a id="ref-source-1_2_2_8_43_51"></a> by siding with false narratives. However, at its core, parental alienation typically centers on <strong>one parent deliberately (or sometimes unconsciously) undermining the child’s bond with the other parent</strong>.</p>

<p><strong>Who are the victims?</strong> There are essentially <strong>two sets of victims</strong> in parental alienation: <strong>the targeted parent</strong> (often called the “rejected” parent) and <strong>the alienated child</strong>. Both suffer harm (we delve into consequences in the next section). Targeted parents come from all walks of life - the phenomenon spans racial and economic groups<sup id="ref-source-1_1_1_2_25_33"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_1_1_2_25_33">[1]</a></sup>. Some studies have found certain groups over-represented; e.g., African-American and Native American parents reported being alienated at higher rates in one U.S. survey<sup id="ref-source-1_1_1_4_362_370"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_1_1_4_362_370">[1]</a></sup>, possibly due to higher conflict custody disputes in those communities. But no group is immune. Mothers and fathers alike experience the devastation of having a child reject them without legitimate cause. In advocacy literature, targeted parents sometimes describe the experience as “ambiguous loss” - the child is still alive, yet <strong>the loving relationship has been forcibly erased</strong>.</p>

<p>Meanwhile, <strong>the children</strong> who become alienated can be of any age or gender. Alienation often starts when kids are between about <strong>8 and 15 years old</strong>, according to clinical reports, as this is when they can voice preferences and be influenced, but cases exist with younger children being conditioned, as well as older teens. Research has not identified a particular “type” of child who is more susceptible, although one theory is that <strong>anxious or passive children may be less able to resist an alienating parent’s pressure</strong><sup id="ref-source-1_9_0_18_239_247"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_9_0_18_239_247">[8]</a></sup>. In general, any child caught in a high-conflict separation could become a pawn. By adulthood, some realize what happened and may reconcile with the targeted parent; others remain estranged for years or permanently.</p>

<p><strong>Relation to other forms of abuse:</strong> Critically, parental alienation is not an isolated phenomenon - it <strong>often co-occurs with other abusive dynamics</strong>, especially <strong>intimate partner violence and coercive control</strong>. In many cases, the <strong>alienating parent is also psychologically or emotionally abusive</strong> toward the targeted parent (and sometimes toward the child via manipulation). The U.K. study by Hine et al. noted that alienating behaviors were linked to <strong>broader domestic abuse patterns</strong> in high-conflict separations<sup id="ref-source-1_4_0_11_155_163"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_4_0_11_155_163">[4]</a></sup>. Alienation itself can be viewed as a form of <strong>family violence</strong>: researchers Harman et al. call these behaviors <em>“abusive strategies to harm parent-child relationships”</em><sup id="ref-source-1_3_1_9_1379_1388"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_3_1_9_1379_1388">[3]</a></sup>, analogous to spousal abuse but targeting the parent-child bond.</p>

<p>Indeed, experts increasingly label parental alienation as <strong>child psychological abuse</strong>. The <strong>DSM-5</strong> (Diagnostic and Statistical Manual of Mental Disorders) includes a related diagnostic code (V995.51, “child psychological abuse”) under which alienation cases can be classified<sup id="ref-source-1_6_0_5_277_283"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-references/#ref-target-1_6_0_5_277_283">[6]</a></sup>. The logic is straightforward: deliberately <strong>turning a child against a loving parent inflicts serious emotional and developmental harm</strong>, just as direct physical or sexual abuse would. As forensic psychologist Dr. Alan Blotcky and psychiatrist Dr. William Bernet wrote, <em>“Causing parental alienation in a child is on par with physical and sexual abuse… It is considered child psychological abuse [in DSM-5]… Parental alienation is real, definable, and toxic… It is not hyperbole to say it can be catastrophic.”</em><a id="ref-source-1_6_0_5_275_283"></a>. This underscores that <strong>parental alienation is now recognized by many professionals as a severe form of abuse</strong>, even if it doesn’t leave visible bruises. (Of course, not all professionals agree - see Section 5 for controversy - but the prevailing view in alienation research is that these behaviors are profoundly harmful.)</p>

<p>Finally, parental alienation often <strong>intersects with allegations of other abuse</strong> in court: for instance, one parent may allege the other abused the child, while the accused counters that the accuser is “just alienating the child.” This creates a thorny situation (addressed in Section 4 on legal responses) where courts must discern <strong>true abuse from fabricated claims made as an alienation tactic</strong>. Sadly, genuine abuse can be masked by false alienation claims, and conversely, an alienator may falsely accuse the targeted parent of abuse. Thus, alienation is deeply intertwined with issues of domestic violence, child protection, and <strong>the credibility of parents in court</strong>.</p>

<hr />

<h2 id="navigation">Navigation</h2>

<table style="width: 100%; table-layout: fixed;">
<tr>
<td style="width: 50%; text-align: left;"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-part-1/">← Part 1: Prevalence and Scope</a></td>
<td style="width: 50%; text-align: right;"><a href="/projects/PA-Awareness-1/2025/09/25/parental-alienation-awareness-part-3/">Part 3: Harms and Consequences →</a></td>
</tr>
</table>]]></content><author><name>Distributed Thinking Systems</name><email>info@unixwzrd.ai</email></author><category term="PA-Awareness-1" /><category term="parental-alienation" /><category term="research" /><category term="perpetrators" /><category term="victims" /><category term="dynamics" /><summary type="html"><![CDATA[Understanding who alienates and who is alienated: both mothers and fathers can be perpetrators or victims of parental alienation.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://unixwzrd.ai/assets/images/projects/PA-devastation-1.png" /><media:content medium="image" url="https://unixwzrd.ai/assets/images/projects/PA-devastation-1.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>