<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Stefanie Jane 🌠</title>
    <description>The latest articles on DEV Community by Stefanie Jane 🌠 (@hyperb1iss).</description>
    <link>https://dev.to/hyperb1iss</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2102549%2F569e4e6d-f956-4e75-afb4-394f763a9afa.jpeg</url>
      <title>DEV Community: Stefanie Jane 🌠</title>
      <link>https://dev.to/hyperb1iss</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hyperb1iss"/>
    <language>en</language>
    <item>
      <title>Get Loopy! Act, React, Iterate Until We Love It</title>
      <dc:creator>Stefanie Jane 🌠</dc:creator>
      <pubDate>Sat, 25 Jul 2026 00:12:19 +0000</pubDate>
      <link>https://dev.to/hyperb1iss/get-loopy-act-react-iterate-until-we-love-it-57e0</link>
      <guid>https://dev.to/hyperb1iss/get-loopy-act-react-iterate-until-we-love-it-57e0</guid>
      <description>&lt;p&gt;For the past week, an agent has been rewriting the retrieval system inside my memory engine. So far it's made a deterministic scorer, run dozens of experiments, kept the good ideas and ditched the failed ones. I wrote one prompt at the start and have made a few calls along the way (insert coin to continue). The loop is doing the rest, and it isn't even close to done.&lt;/p&gt;

&lt;p&gt;At 3:30 every morning, another model wakes up to a standing instruction I wrote once and never send. It reads what my agents captured yesterday, decides what's worth keeping, promotes the confident findings into a knowledge graph, and routes the uncertain ones to me. Nobody is awake. The system is prompting itself.&lt;/p&gt;

&lt;p&gt;And in one five-day stretch last month, a PR babysitter I built ran a thousand agent sessions against my open pull requests. Poll, classify, dispatch, fix, learn, repeat. Tiny models for watching, frontier models for fixing. As agents and humans review code, we react immediately and update PRs automatically.&lt;/p&gt;

&lt;p&gt;This article will show you a few techniques I use everyday for large scale agentic engineering.&lt;/p&gt;

&lt;h2&gt;
  
  
  🌀 The Name Finally Caught Up
&lt;/h2&gt;

&lt;p&gt;In June the term &lt;strong&gt;loop engineering&lt;/strong&gt; landed. Peter Steinberger &lt;a href="https://x.com/steipete/status/2063697162748260627" rel="noopener noreferrer"&gt;put it in twelve words&lt;/a&gt;: "you shouldn't be prompting coding agents anymore. You should be designing loops that prompt your agents." Addy Osmani &lt;a href="https://addyo.substack.com/p/own-the-outer-loop" rel="noopener noreferrer"&gt;named the practice&lt;/a&gt; a day later and gave it an anatomy; O'Reilly &lt;a href="https://www.oreilly.com/radar/loop-engineering/" rel="noopener noreferrer"&gt;republished the essay&lt;/a&gt; two weeks after that, which is how you know a term has officially arrived. Boris Cherny, who created Claude Code, summed up the vibe: "I don't prompt Claude anymore."&lt;/p&gt;

&lt;p&gt;The lineage is clean. Prompt engineering is about what we tell the model. &lt;a href="https://hyperbliss.tech/blog/2026.01.26_context-engineering" rel="noopener noreferrer"&gt;Context engineering&lt;/a&gt; is how we can make the model create and improve those prompts. Loop engineering is about what happens &lt;em&gt;between&lt;/em&gt; runs: the trigger, the feedback signal, the state that carries forward, and the rule that decides when it stops.&lt;/p&gt;

&lt;p&gt;This post is the third act of a trilogy I have apparently created! &lt;a href="https://hyperbliss.tech/blog/2026.01.26_context-engineering" rel="noopener noreferrer"&gt;In January&lt;/a&gt; I wrote about engineering the context. &lt;a href="https://hyperbliss.tech/blog/2026.05.27_how-i-ai" rel="noopener noreferrer"&gt;In May&lt;/a&gt; I wrote about the operating system underneath my prompts: a contract, a skill library, a memory graph. This one is about what happens when that operating system starts running itself.&lt;/p&gt;

&lt;p&gt;One receipt for how convergent this moment is: while mining my own session archive for this post, an agent found the original wish for my memory consolidation loop, timestamped April 4. Verbatim: "i really want a dream mode for claude code. like something that reviews all our conversations regularly." Two months before anyone named the practice. If you've been working seriously with agents, you've been converging on the same ideas. The name doesn't unlock anything; it just gives us a shared vocabulary. &lt;/p&gt;

&lt;p&gt;There is a bit of craft here.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚡ Act → React: The Core Mechanic
&lt;/h2&gt;

&lt;p&gt;At their core, every agentic loop is the same three-beat cycle:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Act.&lt;/strong&gt; The agent does something real: edits code, runs an experiment, drives a browser, opens a PR.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observe.&lt;/strong&gt; The world answers with a signal: a test result, a metric, a screenshot, a review verdict, CI going green or red.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React.&lt;/strong&gt; The loop, not a human, feeds the signal back into the agent's context, and the next act is shaped by it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F14a0w68xrclok80x4hqv.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F14a0w68xrclok80x4hqv.webp" alt="Flowchart of the core loop: Act flows to Observe, Observe to React via tests, metrics, screenshots, and CI, then a stop-condition check loops back to Act until true, with a state carrier of ledger, graph, and git feeding Act" width="799" height="273"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  Mermaid source
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
    A["⚡ Act"] --&amp;gt;|"edit · run · drive · ship"| O["👁 Observe"]
    O --&amp;gt;|"tests · metrics · screenshots · CI"| R["🔄 React"]
    R --&amp;gt; G{"stop condition true?"}
    G --&amp;gt;|"no, go again"| A
    G --&amp;gt;|"yes"| D["💎 done"]
    S[("state carrier: ledger · graph · git")] -.-&amp;gt; A
    R -.-&amp;gt; S
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;&lt;/p&gt;

&lt;p&gt;That third part is really the thing. A prompt is a one-shot context delivery: you curate what the model sees, it acts, done. A loop is a &lt;em&gt;context engine&lt;/em&gt;. Every iteration curates what the next iteration sees, automatically, from the results of the last one. The agent is feeding itself. Then we think about the loops around the loops.&lt;/p&gt;

&lt;p&gt;Which means the quality of a loop is exactly the quality of four components:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The feedback signal.&lt;/strong&gt; What does the loop observe after acting? A signal that's fast, deterministic, and dense beats an expensive vague one every single time, because the loop consumes it on every iteration. Tests are great signals. Typed metrics are great signals. "The page looks better than it did before" is not a signal, but "the page's style matches the style guide perfectly" is .&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The state carrier.&lt;/strong&gt; What survives between iterations? The model's context window doesn't. It fills, it compacts, it's gone when the session ends. Loops that compound carry state outside the model: a findings ledger, a journal file, a task board, a knowledge graph, git history itself. The agent forgets; the repo doesn't.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The stop condition.&lt;/strong&gt; When is it done? "When it's good" is not a stop condition. A testable predicate is: tests green, findings count at zero, metric above threshold, budget exhausted, human says ship.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The safety rails.&lt;/strong&gt; Budgets, cooldowns, whatever you need to make sure everything stays on track and nothing goes crazy and lights your wallet on fire.&lt;/p&gt;

&lt;p&gt;Everything that follows is the same four components rearranged.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 The Eval Loop: An Agent Running Real Science
&lt;/h2&gt;

&lt;p&gt;The best loop I've run this year is still running while I write this: an experiment campaign against &lt;a href="https://github.com/hyperb1iss/sibyl" rel="noopener noreferrer"&gt;Sibyl&lt;/a&gt;, my memory engine, on the LongMemEval v2 benchmark, because v1 is saturated to the point that a good score is table stakes rather than signal. A week in, it already shows what act → react looks like when the feedback signal is engineered instead of vibed.&lt;/p&gt;

&lt;p&gt;Our goal: improve our benchmark scores, without cheating. &lt;/p&gt;

&lt;p&gt;The agent's first move was the one that made everything else work: &lt;strong&gt;it built itself a super simple scorer.&lt;/strong&gt; Instead of asking an LLM judge "did this retrieval look good?" on every iteration (slow, noisy, expensive), it wrote a script that checks whether the known-correct answer literally appears in the assembled context. That check is cheap, exact, and instant, and every configuration got a real number in seconds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;exposure 14/23 ( 60.9%)  phrase-hit  66.7%  ctx  36.9K avg
exposure 15/23 ( 65.2%)  phrase-hit  69.7%  ctx  35.8K avg
exposure 16/23 ( 69.6%)  phrase-hit  69.7%  ctx  47.8K avg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhyperbliss.tech%2Fimages%2Fblog%2Floop-engineering-eval.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhyperbliss.tech%2Fimages%2Fblog%2Floop-engineering-eval.webp" title="Eleven experiments, five retired with receipts, one survivor. The loop feeds the win back in." alt="A dark laboratory with eleven tall glass cylinders in a row, most glowing with faint fading embers while one blazes bright with cyan and pink light, its energy flowing through conduits back into the machinery feeding all the cylinders." width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then the loop proper. The plan said six experiments; the results kept suggesting new ones, and the list has grown to dozens so far, because that's what loops do. Each experiment ran in the background and could crash and resume where it left off, and the agent slept until a results file (or a stack trace) showed up to react to.&lt;/p&gt;

&lt;p&gt;The surprise came from scoring two things separately: whether search &lt;em&gt;found&lt;/em&gt; the right memories, and whether the layout actually got them onto the page. Search was already finding 82.6% of the answers; the layout only got 65.2% of them in front of the model. The bottleneck wasn't search at all. It was page layout. I would not have guessed that, and neither did the agent: the loop measured its way there.&lt;/p&gt;

&lt;p&gt;One change looked like a clear win. Instead of shipping it, the loop did the thing that separates engineering from enthusiasm: it ran the same experiment three more times and compared results question by question. The win evaporated: the average had been sitting still while individual questions churned underneath it. Single runs lie. Five plausible improvements were retired this way, each with receipts.&lt;/p&gt;

&lt;p&gt;We got as far as we could without an LLM, but the idea survived: have a tiny, fast model write a short digest of every memory as it's stored, about fifteen cents for the whole corpus. Replicated effect: &lt;strong&gt;+6.67 points, nine questions better, two worse.&lt;/strong&gt; Then it flunked its first test on a different kind of data, the agent worked out why (the digest was reading fields that didn't exist there), fixed it, and passed the rerun.&lt;/p&gt;

&lt;p&gt;Dozens of commits have landed and the campaign is still running as this post goes up. The eval loop is rewriting the system it's evaluating, live.&lt;/p&gt;

&lt;p&gt;The transferable lessons, because your version of this won't be a memory benchmark:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Build the cheap scorer first.&lt;/strong&gt; One hour spent making feedback deterministic pays back on every iteration. LLM judges belong at the &lt;em&gt;end&lt;/em&gt; of a loop, not inside it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make iterations resumable.&lt;/strong&gt; Experiments that can crash and resume turn an overnight failure into a delay instead of a loss.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Replicate before you believe.&lt;/strong&gt; N=1 results are noise wearing a costume.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retire hypotheses with receipts.&lt;/strong&gt; A loop that only confirms is a yes-machine. Five documented rule-outs bought the credibility of the one win.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🎭 Visual Verification: The Loop Got Eyes
&lt;/h2&gt;

&lt;p&gt;The loop upgrade that still feels like magic: agents can &lt;em&gt;see&lt;/em&gt; now, and seeing closes feedback cycles that used to require a human on every iteration.&lt;/p&gt;

&lt;p&gt;The modern setup: the agent drives the running app in a real browser, the rendered surface itself rather than the test suite. It navigates, clicks, fills forms, and screenshots. The screenshot is the observe beat. The agent compares what it sees against the acceptance criteria, fixes, re-renders, looks again. For UI work I'll write something like "the cards align to an 8px grid, the hover state doesn't shift layout, dark mode holds contrast" and let the loop iterate itself there, screenshot by screenshot. A year ago this was "make the change, describe it to me, I'll look." Now the agent is the one looking, and it catches the 2px misalignment I would have missed.&lt;/p&gt;

&lt;p&gt;The same pattern runs end-to-end tests as a loop signal: drive the app, assert on what actually rendered, feed failures back as context. And it composes with everything else in this post. A review loop where the reviewer &lt;em&gt;also&lt;/em&gt; drives the app catches a class of bug no diff-reader ever will.&lt;/p&gt;

&lt;p&gt;One rule keeps these loops honest, learned the expensive way and now written into my skill library: &lt;strong&gt;perf and visual loops need an objective signal before iteration two. Loops judged by the next screenshot become random walks.&lt;/strong&gt; The screenshot is the sensor, not the standard. Pin the standard first (named acceptance criteria, a reference design, a metric, a golden snapshot) and let the screenshots measure against it. An agent iterating toward "looks better" will happily wander forever, each iteration convincingly justified.&lt;/p&gt;

&lt;p&gt;When the surface is one the agent can't observe, the first move is building the connector, because most "unobservable" surfaces are just missing a driver. Terminals get automation harnesses like &lt;a href="https://github.com/hyperb1iss/ghostty-automator" rel="noopener noreferrer"&gt;ghostty-automator&lt;/a&gt; or cmux that drive keystrokes and read the screen back. Machines beyond the laptop get an agent over SSH. A drawer full of Android devices becomes a sensor array with an MCP server like &lt;a href="https://github.com/hyperb1iss/droidmind" rel="noopener noreferrer"&gt;droidmind&lt;/a&gt; pushing input and pulling screenshots from every one of them. Each connector converts a blind spot into a feedback signal, permanently, for every loop you build afterward.&lt;/p&gt;

&lt;p&gt;And when the surface genuinely can't be instrumented (how a terminal &lt;em&gt;feels&lt;/em&gt;, the light coming off actual hardware), the loop still doesn't end. The human becomes the sensor: hand them a pre-registered expected outcome and a discriminating tell, and you're still running act → react. You've just got a slower sensor with better taste.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔮 Review Loops: Convergence You Can Graph
&lt;/h2&gt;

&lt;p&gt;The loop I run most often is cross-model review to convergence, and the state carrier is what makes it more than "ask another model twice."&lt;/p&gt;

&lt;p&gt;The shape: one model produces an artifact. A spec, a plan, a diff. A different model reviews it adversarially. The findings go into a &lt;strong&gt;ledger&lt;/strong&gt; that travels between rounds: every finding verbatim, the claimed fix, the commit SHA of the fix. The next round's reviewer gets the ledger and two jobs: verify each claimed fix actually landed, and hunt for new problems the fixes introduced. The artifact and its ledger &lt;em&gt;are&lt;/em&gt; the loop's memory. The agent is feeding itself its own review state.&lt;/p&gt;

&lt;p&gt;You track convergence numerically, and the numbers tell you things. A recent infrastructure plan of mine converged over twelve rounds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;17 → 9 → 8 → 4 → 3 → 2 → 1 → 1 → 4 → 1 → 1 → PASS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhyperbliss.tech%2Fimages%2Fblog%2Floop-engineering-convergence.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhyperbliss.tech%2Fimages%2Fblog%2Floop-engineering-convergence.webp" title="17 → 9 → 8 → 4 → 3 → 2 → 1 → 1 → 4 → 1 → 1 → PASS. Round nine is why you graph it." alt="A surreal night landscape where a staircase of glowing monoliths descends toward a calm cyan horizon, one late step rising unexpectedly higher before the final flat plane, with two small figures of light walking down together." width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See round nine? Four new findings after two quiet rounds, because the round-eight fixes broke new ground. Convergence isn't monotonic, which is exactly why you graph it instead of trusting your sense that "it's probably fine now." Another spec went 19 → 6 → 4 → 2 → 0 in five rounds. When the trend stalls or oscillates, the loop is telling you the remaining findings are matters of judgment, and judgment is the human's job.&lt;/p&gt;

&lt;p&gt;The community has been circling the simplest form of this for a while: implement, review, fix, repeat, sometimes with a hook that re-feeds the same prompt until the work is done. Fine as far as it goes. But the naive version has a failure mode that only shows up in production use: &lt;strong&gt;not all review loops should stop the same way&lt;/strong&gt;, and treating them uniformly either burns tokens or ships defects. What I've converged on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Code review: cap the re-litigation, not the rounds.&lt;/strong&gt; Three visits to the &lt;em&gt;same finding&lt;/em&gt; means you're in an argument, not a review. But rounds that keep surfacing new confirmed defects keep going.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spec review: iterate until you love it.&lt;/strong&gt; Spec defects are the most expensive class of defect there is, so convergence is the only exit. My standing instruction to the loop is literally "iterate until we love it."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fix passes: pre-declare a file budget.&lt;/strong&gt; Review-fix loops are a monotonic scope ratchet; every round wants to touch a few more files. I've watched one hit 8 rounds and 63 files before we re-anchored it to six. Now the budget gets declared before round one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two independence rules, both non-negotiable. The implementer never self-assigns PASS, because the model that wrote the code is too kind grading its own homework, and so is the same model re-reading it. And a verdict is pinned to a SHA: any commit after the reviewer's pass voids the pass. Warm-resuming the same reviewer speeds up fix-round convergence; a fresh-context reviewer does final certification precisely because it inherits nothing.&lt;/p&gt;

&lt;h2&gt;
  
  
  🛠️ The Babysitter: 1,785 Sessions in Five Days
&lt;/h2&gt;

&lt;p&gt;Vigil is a PR babysitter I built this spring: an agent system that watches my open pull requests and does whatever they need next. In its first real production window it ran 1,785 agent sessions in five days, every one of them against my real PRs.&lt;/p&gt;

&lt;p&gt;The loop: pollers watch GitHub (my PRs every 30 seconds, the wider radar every 60). State changes get classified by a five-state machine (hot, waiting, ready, dormant, blocked) and classified events go to a cheap triage agent with a five-cent budget that routes to specialists: a fixer with a fifty-cent budget and 15 turns, a responder for review comments, a rebaser, an evidence gatherer. A fixer pushes a commit, the next poll sees fresh CI, triage re-routes. The loop continues until the PR hits READY.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frt8tdhyfeqxrd5rm5xgl.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frt8tdhyfeqxrd5rm5xgl.webp" alt="Vigil's architecture: GitHub polled every 30 to 60 seconds into a five-state machine, events route through a five-cent triage agent to fixer, responder, and rebaser agents that push back to GitHub; three strikes or irreversible actions escalate to a human, and merges feed a learning agent whose patterns flow into future prompts" width="799" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  Mermaid source
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
    GH[("GitHub")] --&amp;gt;|"poll 30s / 60s"| SM{"five-state machine"}
    SM --&amp;gt; T["🧭 triage · 5¢"]
    T --&amp;gt; FX["🔧 fixer · 50¢ · 15 turns"]
    T --&amp;gt; RS["💬 responder"]
    T --&amp;gt; RB["🌿 rebaser"]
    FX --&amp;gt;|"push → fresh CI"| GH
    RS --&amp;gt; GH
    RB --&amp;gt; GH
    T -.-&amp;gt;|"3 strikes · irreversible"| H["👤 you"]
    GH --&amp;gt;|"on merge"| LN["📚 learning agent"]
    LN -.-&amp;gt;|"patterns → future prompts"| T
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;&lt;/p&gt;

&lt;p&gt;What the architecture diagram doesn't show: &lt;strong&gt;the loop logic is maybe a fifth of the code. The rest is safety rails.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Per-agent turn caps and dollar budgets, per run.&lt;/li&gt;
&lt;li&gt;Event dedupe with a five-minute window, plus a 45-second cooldown per event type, because GitHub will happily tell you the same thing four times.&lt;/li&gt;
&lt;li&gt;A concurrency gate so two agents never work the same PR simultaneously.&lt;/li&gt;
&lt;li&gt;Prompt fingerprinting that flags when an agent is about to ask the same question it asked five minutes ago. That's the observability hook for loop detection.&lt;/li&gt;
&lt;li&gt;Escalation: three consecutive failures on the same thing and it stops looping and pings the human.&lt;/li&gt;
&lt;li&gt;Auto-approve for everything except the irreversible set: push, merge, branch delete. Reversible actions flow; irreversible ones queue for me.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhyperbliss.tech%2Fimages%2Fblog%2Floop-engineering-vigil.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhyperbliss.tech%2Fimages%2Fblog%2Floop-engineering-vigil.webp" title="1,785 sessions in five days: poll, classify, dispatch, learn. The irreversible stuff rides the beam up to you." alt="A lantern-like drone hovers over a dark grid of glowing cards, sweeping a cyan beam across them; cards glow in five distinct colors, tiny repair drones tend to some, and one card rises out of the grid on a beam of light." width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's also a second, quieter loop stacked on the first. On every merge, a learning agent extracts patterns into a knowledge file ("this reviewer usually asks for type annotations on public APIs, confidence 0.70"), and new patterns start at 0.50 confidence and gain +0.10 on each reconfirmation. The whole file gets injected into future triage and fix prompts. Every PR makes the next one smoother. The loop's output has become the loop's context, and that's the move that compounds.&lt;/p&gt;

&lt;p&gt;To be fair, you no longer need to build any of this yourself just to get your PRs babysat. Codex and Claude are both solid PR watchers out of the box now, and with newer models you can hand one an entire stack: a PR goes up, a bot review posts feedback, human engineers post theirs, and the agent reads it all as it lands, updates the PR, and replies to the comments with a summary of what changed. What the off-the-shelf version doesn't ship is everything around the loop: the budgets, the dedupe, the learning file, and the queue of irreversible actions that waits for a human.&lt;/p&gt;

&lt;p&gt;If you build one loop this year, build a babysitter for something you already poll by hand that nobody has productized yet. The design pressure is fantastic: every safety rail above exists because its absence produced a specific, memorable mess.&lt;/p&gt;

&lt;h2&gt;
  
  
  🌙 Loops That Feed the Loops
&lt;/h2&gt;

&lt;p&gt;The layer above all of this is where it gets properly recursive: loops whose output is the &lt;em&gt;context machinery itself&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consolidation runs nightly.&lt;/strong&gt; Sibyl's dream cycle wakes at 3:30am, reads what my agents captured during the day, and applies a hard policy: findings it's confident about promote into the knowledge graph automatically, anything it's unsure of queues for me, and duplicates and stale entries get archived. Every agent's tomorrow-context is being curated by an unattended model run tonight, gated by policy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Forgetting is a loop too.&lt;/strong&gt; Every recall an agent makes stamps usage counters on the entities it retrieved. A nightly decay job consumes those counters: memory that gets used survives, memory that doesn't fades and eventually archives. Reads are the training signal for retention. The knowledge graph is under continuous selection pressure from the swarm's actual behavior. I don't garden it; the usage gardens it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhyperbliss.tech%2Fimages%2Fblog%2Floop-engineering-dream.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhyperbliss.tech%2Fimages%2Fblog%2Floop-engineering-dream.webp" title="Recall feeds the bloom, silence feeds the ash. The garden gardens itself at 3:30am." alt="A bioluminescent night garden of glowing networked blossoms under a pale moon; threads of light make some blossoms flare bright while untouched ones fade to ash, as a translucent moonlight figure prunes and grafts the vines." width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And once a season, the big one.&lt;/strong&gt; In July I pointed one prompt at my entire session archive: "review the last few months of Claude and Codex sessions and mine all the patterns and good stuff that worked." What ran: five chained workflows, 208 subagents, two hours and fifty-three minutes. Sixty-two readers worked through distilled versions of ~600 sessions (about 8GB of raw transcripts), pulled out 1,883 findings, merged them into 221 patterns, and then eleven editor agents with adversarial verifiers rewrote my skill library and my agent contract &lt;em&gt;from the evidence of their own use&lt;/em&gt;. The loop system audited itself and shipped the patch.&lt;/p&gt;

&lt;p&gt;A solid finding, mined from months of my own sessions: &lt;strong&gt;"Rules don't self-enforce at generation time; checkpoints do."&lt;/strong&gt; Written by an agent, about agents, from watching agents. The instruction you put in the prompt is a hope; the verification you build into the loop is a guarantee.&lt;/p&gt;

&lt;p&gt;That's the full stack of self-feeding: the eval loop improves the memory engine, the memory engine improves every agent's context, the agents' transcripts improve the skills, and the skills improve the loops. Each layer's exhaust is the next layer's fuel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F01mwz0wj35qy7kr0winm.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F01mwz0wj35qy7kr0winm.webp" alt="The self-feeding stack: the eval loop improves the memory engine, which curates every agent's context, which produces session transcripts, which rewrite the skills and contract, which sharpen the eval loop" width="798" height="110"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  Mermaid source
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
    E["🧪 eval loop"] --&amp;gt;|"improves"| M["🔮 memory engine"]
    M --&amp;gt;|"curates"| C["🗂 every agent's context"]
    C --&amp;gt;|"produces"| T["📜 session transcripts"]
    T --&amp;gt;|"rewrite"| S["🧠 skills + contract"]
    S --&amp;gt;|"sharpen"| E
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🎯 Proof at Scale: Bun's Rust Rewrite
&lt;/h2&gt;

&lt;p&gt;Everything above ran on my laptop against my projects. If you want evidence that the same discipline holds at three orders of magnitude more scale, May was happy to oblige: &lt;a href="https://bun.com/blog/bun-in-rust" rel="noopener noreferrer"&gt;Bun rewrote itself from Zig to Rust&lt;/a&gt;. 535,496 lines of Zig across 1,448 files became a 1,009,272-line Rust diff in eleven days, built by 64 Claude agents running continuously, for about $165,000 in API-priced tokens. Jarred Sumner's estimate of the manual alternative: three engineers with full codebase context, about a year.&lt;/p&gt;

&lt;p&gt;Jarred published the core of the system as pseudocode, and it's the act → react cycle verbatim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt;
&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;todoList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;feedback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;review&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;review&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;feedback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Act, observe twice in parallel, react. And every component from the anatomy section is there at industrial strength:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The feedback signal&lt;/strong&gt; is the whole story. Bun's test suite is written in TypeScript, which means it's independent of the runtime's implementation language: 1,386,826 &lt;code&gt;expect()&lt;/code&gt; calls on Linux x64 alone, roughly 60,000 tests per platform, functioning as a conformance suite for the port. When the tests pass, the port is correct, and no LLM judge has to opine. During the compiler-error phase (16,000 errors at the start), the loop was literally "run &lt;code&gt;cargo check&lt;/code&gt;, group the output by file, save the errors to a file, fix all the compiler errors within that crate." Deterministic, dense, cheap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The state carrier&lt;/strong&gt; was built before the loop ran: three hours producing a PORTING.md (600 lines of Zig-to-Rust pattern mappings, with hard constraints like no tokio, no async/await, because Bun owns its own event loop) plus a LIFETIMES.tsv mapping the ownership of every struct field. Both documents got their own adversarial review before any code generation started. Context engineering feeding loop engineering.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Independence was structural.&lt;/strong&gt; One implementer, two adversarial reviewers per task, and the roles never blur: "The implementer doesn't review. The reviewer doesn't implement." Reviewers got only the diff and were told to assume the code is wrong. Every line of the million-line diff crossed two adversarial readers at a peak throughput of 1,300 lines per minute.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The rails were physical.&lt;/strong&gt; Four git worktrees with 16 agents each, so shards couldn't touch each other's files. Agents banned from &lt;code&gt;git stash&lt;/code&gt;, &lt;code&gt;git reset&lt;/code&gt;, anything that doesn't commit a specific file. The stop condition had integrity teeth: 100% of the suite passing with zero tests skipped or deleted, because a loop that's allowed to delete failing tests will absolutely delete failing tests.&lt;/p&gt;

&lt;p&gt;The most instructive moment is the failure. Mid-run, agents started interpreting "get all the crates to compile" as "stub out the functions": the classic false-victory pathology, at scale. The fix wasn't hand-editing stubs. It was one prompt edit, and the stubbing stopped fleet-wide. Jarred's summary of the methodology is the cleanest one-line definition of loop engineering I've seen: a million-assertion test suite, adversarial review, and &lt;strong&gt;"when something does go wrong, fixing the process that generates the code instead of hand-fixing the code."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not everyone applauded. Zig's creator &lt;a href="https://www.theregister.com/devops/2026/07/14/zig-creator-calls-buns-claude-rust-rewrite-unreviewed-slop/5270743" rel="noopener noreferrer"&gt;called it "unreviewed slop"&lt;/a&gt;, and 6,502 commits in eleven days is a real review-debt question no matter how adversarial the machine reviewers were. The preconditions were also unusually good: an expert who knew every corner of the codebase steering daily, and a test suite that took years of runtime development to accumulate. That's the lesson, not a caveat to it. &lt;strong&gt;The rewrite took eleven days because the feedback signal took years.&lt;/strong&gt; Your test harness is the asset your future loops will spend.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhyperbliss.tech%2Fimages%2Fblog%2Floop-engineering-scale.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhyperbliss.tech%2Fimages%2Fblog%2Floop-engineering-scale.webp" title="Sixty-four builders, two adversarial readers per beam, one human steering. The tests don't care what you call it." alt="A monumental lattice bridge at night, its left span fading to amber embers and its right span glowing electric purple and cyan, with dozens of tiny figures of light rebuilding the seam between them while paired inspector drones sweep scrutiny beams over new struts and a lone human watches from a control platform." width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  💎 The Craft: What Separates a Loop from a while(true)
&lt;/h2&gt;

&lt;p&gt;Distilling everything above, plus a couple of years of expensive mistakes, into the principles I'd actually defend:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Size the loop to the work.&lt;/strong&gt; Loop engineering earns its keep in two places: greenfield scope too big to hold in your head (new builds, ports, benchmark campaigns) and toil that recurs forever (PR queues, nightly digests). A small task or a routine debugging session doesn't want a harness; the setup never pays back, and the ceremony slows down work you could have just done. The exception is the verify loop, which is free and belongs everywhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Type your stop conditions.&lt;/strong&gt; Different loop species stop differently, and using the wrong stop rule is the classic failure:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Loop species&lt;/th&gt;
&lt;th&gt;Stop rule&lt;/th&gt;
&lt;th&gt;Why that one&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Spec review&lt;/td&gt;
&lt;td&gt;Convergence: iterate until you love it&lt;/td&gt;
&lt;td&gt;Spec defects are the most expensive class there is&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code review&lt;/td&gt;
&lt;td&gt;Re-litigation cap: three visits to one finding&lt;/td&gt;
&lt;td&gt;New confirmed defects keep rounds alive; arguments don't&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Research&lt;/td&gt;
&lt;td&gt;Yield: a wave that surfaces nothing new is the last&lt;/td&gt;
&lt;td&gt;Count-based stops miss the tail in both directions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Digests&lt;/td&gt;
&lt;td&gt;Cron: the schedule is the stop&lt;/td&gt;
&lt;td&gt;The job is cadence, not convergence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exploration&lt;/td&gt;
&lt;td&gt;Budget: turns or dollars, pre-declared&lt;/td&gt;
&lt;td&gt;Open-ended search needs a wall set before it starts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Self-re-prompting&lt;/td&gt;
&lt;td&gt;A completion predicate that can only be emitted truthfully&lt;/td&gt;
&lt;td&gt;"Blocked cleanly, with receipts and a runbook" is terminal; fake-done is not&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Engineer the feedback signal.&lt;/strong&gt; Deterministic beats judged, dense beats sparse, and cheap beats expensive, because the loop pays the cost on every iteration. The geometry sweep worked because the scorer was exact; vigil works because CI and GitHub state are unambiguous; visual loops work when the acceptance criteria are named before iteration one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Carry state outside the model.&lt;/strong&gt; Ledgers, journals, knowledge graphs, git history. The context window is a scratchpad, not a database. Every loop that compounds does it through external state; every loop that plateaus is usually re-deriving what it knew yesterday.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The dominant failure mode is stopping early, not running away.&lt;/strong&gt; Everyone fears the runaway loop; in practice the pathology you'll actually fight is the agent quietly declaring victory: the plan-only exit, the false "all done!" on an empty turn, the wrap-up reflex as context fills. I spent a research cycle on this while building a swarm harness, and the design answer is a watchdog that distinguishes &lt;em&gt;stalls&lt;/em&gt; from &lt;em&gt;stops&lt;/em&gt;: re-prompt on stall, replan on no-progress, and break the loop only on a repeated failure signature. Pair it with turn and dollar budgets and you've bounded both tails.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Independence is structural, not aspirational.&lt;/strong&gt; The implementer never self-assigns PASS. Verdicts pin to SHAs. Final certification gets fresh context. None of this is about model quality; it's about the same conflict-of-interest logic we already apply to humans.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Budgets and rails will save you at some point.&lt;/strong&gt; Get these right so you don't wake up to a huge bill and mess.&lt;/p&gt;

&lt;h2&gt;
  
  
  🌸 Start With One Loop
&lt;/h2&gt;

&lt;p&gt;You don't need my stack. You don't even need a special harness: every loop in this post runs on stock agent CLIs, Claude Code or Codex, sometimes Pi or OpenCode, with small scripts and cron holding the loops together. The agents are ordinary sessions; the engineering is in what surrounds them, and all of it is portable. This is a good order:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The verify loop (you probably already do this).&lt;/strong&gt; Edit → test → fix, every two or three edits, enforced as loop structure rather than discipline. Throw in agent-browser or another tool to give the agent visibility into it's own output&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The review-to-convergence loop (this week).&lt;/strong&gt; Next spec: have a &lt;em&gt;different&lt;/em&gt; model review it, keep a findings ledger, fix, re-review, and track the count. Watch it converge, or watch round nine surprise you. Stop conditions per the craft section: convergence for specs, re-litigation caps for code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The scheduled digest (this month).&lt;/strong&gt; One recurring report you currently assemble by hand: last week's merges, your open review queue, error trends. Cron a session, give it a fail-closed preflight, gate delivery behind a fact-check pass. This is your intro to loops that run when you're not watching, with training wheels: worst case is a bad report to yourself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. The babysitter (when the polling pain is real).&lt;/strong&gt; Pick the thing you check compulsively (a flaky CI pipeline, that long-running db migration, your PR queue) and wrap a poll → classify → act loop around it, with the full rail kit: budgets, cooldowns, dedupe, escalation, irreversible-actions-queue-for-human.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. The memory loop (when the others are humming).&lt;/strong&gt; Scheduled consolidation of your sessions into recallable knowledge, with a confidence gate between the unattended run and what your future agents get to see. This is the one that makes the other four compound.&lt;/p&gt;

&lt;p&gt;And measure the loop, not the vibes: iterations to convergence, cost per iteration, unverified-claim rate, escalation rate, and how often the loop's stop condition fired versus you pulling the plug. A loop earning its keep shows up in those numbers within a week; a loop that doesn't gets deleted.&lt;/p&gt;

&lt;h2&gt;
  
  
  🦋 The Part That Stays Human
&lt;/h2&gt;

&lt;p&gt;Osmani ends his essay warning against &lt;em&gt;cognitive surrender&lt;/em&gt;, the temptation to stop having judgment once the automation feels smooth. It's the right warning. Every loop in this post keeps a human where it counts: I pick the hypotheses the eval loop tests, approve the pushes vigil queues, review what the dream cycle isn't sure about, and make the judgment calls the review ledger converges toward. The loops removed the toil of re-prompting, not the steering. If anything, they concentrated the job into its highest-leverage form: designing feedback systems and exercising taste at their decision points.&lt;/p&gt;

&lt;p&gt;Two years ago the craft was writing the perfect prompt. One year ago it was &lt;a href="https://hyperbliss.tech/blog/2026.01.26_context-engineering" rel="noopener noreferrer"&gt;engineering the context&lt;/a&gt;. This spring it was &lt;a href="https://hyperbliss.tech/blog/2026.05.27_how-i-ai" rel="noopener noreferrer"&gt;the contract, the skills, and the memory&lt;/a&gt;. Now the context engineers itself, on a schedule, from the results of its own actions, and the craft moved up another level: act, react, repeat, with you designing the loop and keeping the judgment.&lt;/p&gt;

&lt;p&gt;Don't just prompt. Engineer the loop. Iterate until you love it. 💜&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://hyperbliss.tech/blog/2026.07.21_loop-engineering/" rel="noopener noreferrer"&gt;hyperbliss.tech&lt;/a&gt;. Follow me on &lt;a href="https://github.com/hyperb1iss" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and &lt;a href="https://bsky.app/profile/hyperbliss.tech" rel="noopener noreferrer"&gt;Bluesky&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>loopengineering</category>
      <category>agents</category>
      <category>claudecode</category>
    </item>
    <item>
      <title>The Terminal Renaissance: Designing Beautiful TUIs in the Age of AI</title>
      <dc:creator>Stefanie Jane 🌠</dc:creator>
      <pubDate>Fri, 10 Apr 2026 00:23:12 +0000</pubDate>
      <link>https://dev.to/hyperb1iss/the-terminal-renaissance-designing-beautiful-tuis-in-the-age-of-ai-24do</link>
      <guid>https://dev.to/hyperb1iss/the-terminal-renaissance-designing-beautiful-tuis-in-the-age-of-ai-24do</guid>
      <description>&lt;p&gt;Something shifted.&lt;/p&gt;

&lt;p&gt;It wasn't sudden. More like tectonic plates moving under the industry while everyone watched the AI hype cycle. But the evidence is hard to ignore. Claude Code now authors &lt;a href="https://newsletter.semianalysis.com/p/claude-code-is-the-inflection-point" rel="noopener noreferrer"&gt;4% of all public GitHub commits&lt;/a&gt; , 135,000 a day, doubling month over month. &lt;a href="https://devecosystem-2025.jetbrains.com/" rel="noopener noreferrer"&gt;69% of developers&lt;/a&gt; keep a terminal open at all times. OpenCode, a terminal-native AI coding agent, hit 95,000 GitHub stars in two weeks. Ghostty, a GPU-accelerated terminal emulator, went nonprofit because its creator believed the terminal mattered enough to protect from acquisition.&lt;/p&gt;

&lt;p&gt;The terminal isn't having a nostalgia moment. It's having a &lt;em&gt;platform&lt;/em&gt; moment.&lt;/p&gt;

&lt;p&gt;And nobody's talking about how to design for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚡ The Three Forces
&lt;/h2&gt;

&lt;p&gt;Three things happened at once, and the compound effect is bigger than any of them alone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI agents chose the terminal.&lt;/strong&gt; Claude Code, Codex CLI, Gemini CLI, OpenCode:&lt;br&gt;
every serious AI coding tool lives in the shell. Not because terminals are trendy, but because the terminal is where &lt;em&gt;execution&lt;/em&gt; happens. IDE extensions suggest code. Terminal agents &lt;em&gt;write&lt;/em&gt; code, run tests, read logs, fix errors, and commit. The terminal became &lt;a href="https://adelzaalouk.me/2026/feb/22/terminals-agents-and-the-control-plane-nobody-built/" rel="noopener noreferrer"&gt;an AI runtime nobody intentionally designed&lt;/a&gt;, and it turns out to be a really good one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Modern tooling raised the floor.&lt;/strong&gt; A generation of Rust and Go tools quietly&lt;br&gt;
replaced the Unix standard library with versions that are faster, prettier, and more intuitive. ripgrep over grep. bat over cat. eza over ls. fd over find. yazi over ranger. zoxide over cd. lazygit over raw git. atuin over Ctrl+R. And tools like &lt;a href="https://github.com/hyperb1iss/chromacat" rel="noopener noreferrer"&gt;ChromaCat&lt;/a&gt;, which turns any terminal output into animated gradient art with plasma patterns, aurora effects, and 40+ themes, proved that the terminal could be genuinely &lt;em&gt;beautiful&lt;/em&gt;, not just functional. The terminal got a glow-up that had nothing to do with AI; it just got &lt;em&gt;better&lt;/em&gt; as a daily environment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal emulators became premium products.&lt;/strong&gt; Ghostty renders at 500fps with&lt;br&gt;
native GPU acceleration and platform-native UI. Kitty pioneered an inline image protocol that lets terminals &lt;em&gt;show&lt;/em&gt; things. WezTerm ships a built-in multiplexer. Rio runs on WebGPU. The modern terminal baseline is true color, font ligatures, Unicode everywhere, and rendering performance that puts some web apps to shame.&lt;/p&gt;

&lt;p&gt;Put them together: more developers spending more time in terminals that are more capable than ever, building with frameworks that make terminal UIs genuinely enjoyable to create.&lt;/p&gt;

&lt;p&gt;So where's the design language?&lt;/p&gt;
&lt;h2&gt;
  
  
  📖 The Missing Manual
&lt;/h2&gt;

&lt;p&gt;Web developers have Material Design, Apple's Human Interface Guidelines, WCAG accessibility standards, and a research tradition going back decades. Mobile developers have platform-specific HIG documents, accessibility mandates, and component libraries that enforce consistency.&lt;/p&gt;

&lt;p&gt;Terminal developers have... vibes.&lt;/p&gt;

&lt;p&gt;I went looking for the equivalent. Here's what I found:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://clig.dev/" rel="noopener noreferrer"&gt;clig.dev&lt;/a&gt;&lt;/strong&gt;: a solid CLI design guide that
&lt;a href="https://clig.dev/#introduction" rel="noopener noreferrer"&gt;explicitly excludes TUIs&lt;/a&gt;: "Full-screen   terminal programs are niche projects; very few of us will ever be in the   position to design one."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Base16 / Tinted Theming&lt;/strong&gt;: a color system with 230+ palettes. Covers color
only. Nothing on layout, interaction, navigation, or component patterns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A 1983 ACM paper&lt;/strong&gt; on terminal interface design. The last (and essentially
only) academic work on the subject.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;awesome-tuis&lt;/strong&gt;: the most-starred TUI resource list on GitHub. It's a catalog
of apps. Zero design resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is no HIG for terminal applications. No accessibility standard. No cross-framework design system. No academic research tradition. The closest thing is library documentation for individual frameworks, useful but framework-specific and focused on &lt;em&gt;how to build&lt;/em&gt;, not &lt;em&gt;what to build&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This gap isn't just an oversight. It's a massive opportunity. Terminals are a medium with their own affordances (information density, keyboard-first interaction, spatial memory, graceful degradation across connection quality) and they deserve design thinking that's native to those strengths, not borrowed from the web.&lt;/p&gt;

&lt;p&gt;What follows is my attempt to start filling that gap. Not theory: lessons from building five production TUI applications across two frameworks, with a design system that spans all of them.&lt;/p&gt;
&lt;h2&gt;
  
  
  🏗️ Designing for 80 Columns
&lt;/h2&gt;

&lt;p&gt;The first thing you learn building terminal UIs: every cell matters in a way that pixels don't. A web developer can throw a 32px margin on something and it disappears into the layout. In a terminal, a single wasted column is a percentage of your real estate. The constraint shapes everything.&lt;/p&gt;
&lt;h3&gt;
  
  
  🧱 Layout as Architecture
&lt;/h3&gt;

&lt;p&gt;Terminal layouts aren't just arrangements; they're &lt;em&gt;architectures&lt;/em&gt; that determine how users build mental models of your app. After building five apps and studying &lt;a href="https://github.com/hyperb1iss/hyperskills" rel="noopener noreferrer"&gt;23 exemplar TUIs&lt;/a&gt;, I've found that almost every successful terminal app falls into one of seven patterns:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Persistent Multi-Panel&lt;/strong&gt;: Everything visible at once, panels in fixed&lt;br&gt;
positions. lazygit, btop, and Unifly all use this. The magic is &lt;em&gt;spatial consistency&lt;/em&gt;: users learn that "network traffic is top-right" and their eyes go there automatically. You never rearrange panels without explicit user action. The user's spatial memory &lt;em&gt;is&lt;/em&gt; the navigation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Miller Columns&lt;/strong&gt;: Three columns showing parent, current, and preview. yazi and&lt;br&gt;
ranger use this for file navigation. The insight: hierarchical data has a natural horizontal flow. You see where you came from (left), where you are (center), and where you're going (right). Elegant for anything tree-shaped.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Drill-Down Stack&lt;/strong&gt;: Browser-like navigation into increasingly specific views.&lt;br&gt;
k9s does this beautifully for Kubernetes (cluster → namespace → deployment → pod → container → logs), with &lt;code&gt;:resource&lt;/code&gt; jumps for power users. The pattern for deep hierarchies where showing everything at once would be chaos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Widget Dashboard&lt;/strong&gt;: Independent, self-contained widgets in a grid. btop and&lt;br&gt;
bottom take this approach for system monitoring. Each widget owns its own data lifecycle and rendering. Good when the relationship between data is "these are all about the same system" rather than "these are all about the same item."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IDE Three-Panel&lt;/strong&gt;: Sidebar, main content, and detail/output. Iris Studio,&lt;br&gt;
harlequin, and most development tools use some variant. The layout metaphor is: &lt;em&gt;navigate&lt;/em&gt; (left), &lt;em&gt;work&lt;/em&gt; (center), &lt;em&gt;inspect&lt;/em&gt; (right). Tab bars give the main panel multiple personalities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overlay/Popup&lt;/strong&gt;: Appears over the shell, does one thing, disappears. atuin and&lt;br&gt;
fzf embody this. No state between invocations. The terminal equivalent of a modal dialog, summoned when needed, gone when done, never disrupting your scrollback.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Header + Scrollable List&lt;/strong&gt;: Fixed header with stats, scrollable data below,&lt;br&gt;
function bar at the bottom. htop and tig. The oldest pattern and still one of the most effective for any "view a list of things with summary stats" use case.&lt;/p&gt;

&lt;p&gt;The choice isn't arbitrary. When I built Unifly (a network dashboard), persistent multi-panel was obvious: network state is best understood &lt;em&gt;all at once&lt;/em&gt;, with your eyes learning where each metric lives. When I built Iris Studio (an AI git workflow), IDE three-panel was the right call, because you're working on one thing at a time but need navigation and context flanking the main content.&lt;/p&gt;

&lt;p&gt;Picking the wrong layout is like picking the wrong data structure. Everything downstream gets harder.&lt;/p&gt;
&lt;h3&gt;
  
  
  🎯 Seven Principles
&lt;/h3&gt;

&lt;p&gt;I've codified the design patterns that work across all seven layout types into principles. I won't enumerate them as a numbered list; that's not how they work in practice. Instead, they're threads that run through every decision:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spatial consistency&lt;/strong&gt; is the foundation. Panels don't move. Tabs stay in&lt;br&gt;
order. The user builds a mental map of your app in the first minute and navigates by &lt;em&gt;location memory&lt;/em&gt; after that. Every time you shuffle the layout, you reset their spatial model to zero.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keyboard-first, mouse-optional&lt;/strong&gt; means every feature is reachable without a&lt;br&gt;
mouse, but mouse support isn't an afterthought either. The reason: terminal power users are keyboard people, but beginners discovering your app will click. Support both; optimize for keys.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Progressive disclosure&lt;/strong&gt; is how you avoid the "wall of keyboard shortcuts"&lt;br&gt;
problem. Three tiers: a footer bar showing the 3-5 most important keys (always visible), a &lt;code&gt;?&lt;/code&gt; help overlay with the full keybinding reference (on demand), and complete documentation for everything else. Beginners see the floor. Experts find the ceiling. Nobody reads a manual to get started.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Semantic color&lt;/strong&gt; means color carries &lt;em&gt;meaning&lt;/em&gt;, not decoration. Green means&lt;br&gt;
success. Red means danger. Yellow means caution. If you stripped all color from your app and it became unusable, your design is broken. Color should reinforce information hierarchy that's already established through layout, typography, and symbols. More on this shortly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Async everything&lt;/strong&gt; is non-negotiable in 2026. Never freeze the UI. File&lt;br&gt;
operations, network calls, AI generation: all background tasks with progress indicators. The user should always be able to press &lt;code&gt;Esc&lt;/code&gt; and get back to a responsive interface. A TUI that hangs is a TUI that gets killed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contextual intelligence&lt;/strong&gt; means your interface adapts to what the user is&lt;br&gt;
doing &lt;em&gt;right now&lt;/em&gt;. Keybindings change when focus moves between panels. The status bar reflects current state. Help shows shortcuts that are actually available in this context. The UI earns trust by always being accurate about what's possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Design in layers&lt;/strong&gt; is the principle I wish someone had told me on day one.&lt;br&gt;
Start with monochrome: is the app &lt;em&gt;usable&lt;/em&gt; with no color at all? Then add 16 ANSI colors: is the hierarchy &lt;em&gt;readable&lt;/em&gt;? Then layer in true color: is it &lt;em&gt;beautiful&lt;/em&gt;? Each tier is independent. Your app works on a monochrome SSH session &lt;em&gt;and&lt;/em&gt; looks stunning in Ghostty. That's not a tradeoff; it's a design discipline.&lt;/p&gt;
&lt;h3&gt;
  
  
  ⌨️ The Vim Question
&lt;/h3&gt;

&lt;p&gt;One pattern that emerged across every framework and every app I built: vim keybindings are the terminal lingua franca.&lt;/p&gt;

&lt;p&gt;Not because every terminal user runs vim. But because &lt;code&gt;j&lt;/code&gt;/&lt;code&gt;k&lt;/code&gt; for up/down, &lt;code&gt;h&lt;/code&gt;/&lt;code&gt;l&lt;/code&gt; for left/right, &lt;code&gt;/&lt;/code&gt; for search, &lt;code&gt;?&lt;/code&gt; for help, &lt;code&gt;g&lt;/code&gt;/&lt;code&gt;G&lt;/code&gt; for top/bottom, and &lt;code&gt;Esc&lt;/code&gt; to go back is the most information-dense navigation vocabulary ever designed. It's six keystrokes that handle 80% of navigation. And it's muscle memory for exactly the audience that builds and uses TUIs.&lt;/p&gt;

&lt;p&gt;I structure keyboard interaction in four layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;L0 (Universal)&lt;/strong&gt;: Arrow keys, Enter, Escape, &lt;code&gt;q&lt;/code&gt; to quit. Shown in the
footer. Anyone can use this.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L1 (Vim motions)&lt;/strong&gt;: &lt;code&gt;j&lt;/code&gt;/&lt;code&gt;k&lt;/code&gt;/&lt;code&gt;h&lt;/code&gt;/&lt;code&gt;l&lt;/code&gt;, &lt;code&gt;/&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt;, &lt;code&gt;:&lt;/code&gt;. Also shown in the
footer. Terminal natives expect this.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L2 (Actions)&lt;/strong&gt;: Single mnemonic keys: &lt;code&gt;d&lt;/code&gt; for delete, &lt;code&gt;s&lt;/code&gt; for stage, &lt;code&gt;r&lt;/code&gt; for
refresh. Discoverable through the &lt;code&gt;?&lt;/code&gt; help overlay.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L3 (Power)&lt;/strong&gt;: Composed commands, macros, configuration. Documentation only.
The ceiling for experts who've invested the time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each layer is invisible until the user reaches for it. That's progressive disclosure applied to keyboard interaction.&lt;/p&gt;
&lt;h2&gt;
  
  
  🎨 Color as Information Architecture
&lt;/h2&gt;

&lt;p&gt;Color in a terminal is a &lt;em&gt;resource&lt;/em&gt;, not a paintbrush. You have a constrained palette compared to the web, a wildly unpredictable rendering environment (users run every terminal emulator and theme combination imaginable), and an audience that may be looking at your app over SSH on a 16-color connection.&lt;/p&gt;
&lt;h3&gt;
  
  
  🌈 The Three-Tier Model
&lt;/h3&gt;

&lt;p&gt;The golden rule: &lt;strong&gt;usable at 16 colors, beautiful at true color&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Your app encounters terminals in three capability tiers:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;16 ANSI colors&lt;/strong&gt;: The foundation. These are the colors the user's terminal&lt;br&gt;
theme controls. When you say "red," the terminal decides what red looks like. This means your reds match their theme. The upside: automatic coherence. The downside: no fine control. Design with named ANSI colors and your app blends into any terminal. This is your SSH-over-a-bad-connection baseline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;256 colors&lt;/strong&gt;: Extended palette with fixed colors. You gain control but lose&lt;br&gt;
theme coherence. Your specific shade of purple will look the same on every terminal, which means it may clash with their background. Use sparingly for emphasis; don't build your entire palette here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;True color (24-bit)&lt;/strong&gt;: Full control. 16 million colors. This is where you make&lt;br&gt;
it beautiful. But always remember: it's an enhancement layer over a 16-color foundation, not a replacement for one.&lt;/p&gt;

&lt;p&gt;Detection is straightforward: check &lt;code&gt;$COLORTERM&lt;/code&gt; for &lt;code&gt;truecolor&lt;/code&gt; or &lt;code&gt;24bit&lt;/code&gt;. Check &lt;code&gt;$TERM&lt;/code&gt; for &lt;code&gt;256color&lt;/code&gt;. Respect &lt;code&gt;$NO_COLOR&lt;/code&gt; unconditionally: if it's set, strip all color. This isn't just accessibility; it's professional courtesy.&lt;/p&gt;
&lt;h3&gt;
  
  
  🏷️ Semantic Color Slots
&lt;/h3&gt;

&lt;p&gt;The insight that changed how I think about terminal color: define colors by &lt;em&gt;function&lt;/em&gt;, not appearance.&lt;/p&gt;

&lt;p&gt;Instead of "this panel border is &lt;code&gt;#e135ff&lt;/code&gt;," it's "focused panel borders use &lt;code&gt;accent.primary&lt;/code&gt;." Instead of "errors are &lt;code&gt;#ff6363&lt;/code&gt;," it's "errors use &lt;code&gt;status.error&lt;/code&gt;." A semantic layer between your code and your colors.&lt;/p&gt;

&lt;p&gt;Here's the vocabulary I use across all five apps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;text.primary&lt;/strong&gt;: Main body text. Off-white on dark backgrounds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;text.muted&lt;/strong&gt;: Secondary information, metadata, timestamps. Noticeably
dimmer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;text.emphasis&lt;/strong&gt;: Headers, focused items. Bright, bold.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;bg.base&lt;/strong&gt; → &lt;strong&gt;bg.surface&lt;/strong&gt; → &lt;strong&gt;bg.overlay&lt;/strong&gt;: Three background layers, each
~5-8% lighter. Creates depth without borders.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;accent.primary&lt;/strong&gt;: Your brand color. Interactive elements, focused borders.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;accent.secondary&lt;/strong&gt;: Supporting interactions. Secondary highlights.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;status.success / .warning / .error / .info&lt;/strong&gt;: Exactly what they sound like.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;git.staged / .modified / .untracked&lt;/strong&gt;: Domain-specific tokens for git apps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;diff.added / .removed&lt;/strong&gt;: Domain-specific tokens for diff views.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When your colors have semantic names, your entire app becomes theme-swappable overnight. Change the values behind the names; every screen updates instantly. I proved this across five apps with 20 different themes, same codebase, completely different personalities.&lt;/p&gt;
&lt;h3&gt;
  
  
  🔧 Theming as Infrastructure
&lt;/h3&gt;

&lt;p&gt;This is where most TUI developers stop: they pick some hex codes, scatter them through the codebase, and ship one look. Changing anything means grepping through 50 files.&lt;/p&gt;

&lt;p&gt;I got tired of this after the second app. So I built &lt;a href="https://github.com/hyperb1iss/opaline" rel="noopener noreferrer"&gt;Opaline&lt;/a&gt;, a token-based theme engine for Ratatui that implements the semantic color model as actual infrastructure.&lt;/p&gt;

&lt;p&gt;The pipeline:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Palette&lt;/strong&gt; (raw hex colors) → &lt;strong&gt;Tokens&lt;/strong&gt; (semantic names that reference palette) → &lt;strong&gt;Styles&lt;/strong&gt; (composed foreground + background + modifiers) → &lt;strong&gt;Gradients&lt;/strong&gt; (multi-stop color interpolation)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Each layer references the one below it. Tokens like &lt;code&gt;text.primary&lt;/code&gt; resolve to palette entries like &lt;code&gt;gray_50&lt;/code&gt;. Styles like &lt;code&gt;keyword&lt;/code&gt; compose a foreground token with bold. Gradients interpolate between palette entries for progress bars and visual effects.&lt;/p&gt;

&lt;p&gt;The result: 20 builtin themes, including five &lt;a href="https://github.com/hyperb1iss/silkcircuit" rel="noopener noreferrer"&gt;SilkCircuit&lt;/a&gt; variants (Neon, Soft, Glow, Vibrant, Dawn), plus Catppuccin, Dracula, Nord, Rose Pine, Gruvbox, Tokyo Night, and more. Every theme is validated against a contract test suite: 40+ tokens must be defined, 18+ styles must resolve, 5 gradients must interpolate correctly. Users can write their own themes as TOML files. Runtime switching costs nothing.&lt;/p&gt;

&lt;p&gt;The bigger lesson isn't about Opaline specifically. It's that theming is &lt;em&gt;infrastructure&lt;/em&gt;, the same way a design system is infrastructure for the web. If you want visual consistency across multiple apps, or you want to support user customization without chaos, you need a resolution pipeline with semantic indirection. Hex codes in source files is a phase, not a strategy.&lt;/p&gt;
&lt;h3&gt;
  
  
  ✨ SilkCircuit: A Terminal Design Language
&lt;/h3&gt;

&lt;p&gt;To make the theme system concrete, I designed SilkCircuit as a cohesive visual identity for terminal applications. Not "use my colors," but "here's what a complete terminal design language looks like."&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Electric Purple&lt;/strong&gt; (&lt;code&gt;#e135ff&lt;/code&gt;): Brand, emphasis, focus states&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Neon Cyan&lt;/strong&gt; (&lt;code&gt;#80ffea&lt;/code&gt;): Interaction, file paths, tech elements&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coral&lt;/strong&gt; (&lt;code&gt;#ff6ac1&lt;/code&gt;): Accents, hashes, constants&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Electric Yellow&lt;/strong&gt; (&lt;code&gt;#f1fa8c&lt;/code&gt;): Warnings, timestamps, attention&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Success Green&lt;/strong&gt; (&lt;code&gt;#50fa7b&lt;/code&gt;): Confirmations, additions, online states&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Red&lt;/strong&gt; (&lt;code&gt;#ff6363&lt;/code&gt;): Danger, deletions, offline states&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Five variants prove the system works: Neon is electric and high-contrast. Soft is muted and comfortable. Glow adds bloom-like emphasis. Vibrant is saturated and bold. Dawn is a warm light theme. Same semantic slots, completely different energy. The design language is the &lt;em&gt;mapping&lt;/em&gt; from meaning to color, not the colors themselves.&lt;/p&gt;
&lt;h2&gt;
  
  
  🚀 Five Apps, Two Frameworks
&lt;/h2&gt;

&lt;p&gt;Theory is cheap. Here's what I actually learned by shipping.&lt;/p&gt;
&lt;h3&gt;
  
  
  📊 Unifly: The Dashboard
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/hyperb1iss/unifly" rel="noopener noreferrer"&gt;Unifly&lt;/a&gt; is a real-time network management dashboard for Ubiquiti UniFi controllers. Eight screens of live data: WAN traffic charts, device health, client lists, firewall rules, topology maps, event streams, historical analytics. Built in Rust with Ratatui.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The design lesson: information density is a feature, not a problem.&lt;/strong&gt; Every&lt;br&gt;
cell on screen earns its place. WAN bandwidth charts use a dual-layer technique : HalfBlock area fills for the smooth body with Braille character line overlays for the crisp edge. Traffic bars use fractional block characters (&lt;code&gt;▏▎▍▌▋▊▉█&lt;/code&gt;) for sub-cell precision that makes terminal charts feel surprisingly smooth. Status indicators use semantic symbols: &lt;code&gt;●&lt;/code&gt; online, &lt;code&gt;○&lt;/code&gt; offline, &lt;code&gt;◐&lt;/code&gt; transitioning, &lt;code&gt;◉&lt;/code&gt; pending adoption.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The architecture lesson: never poll.&lt;/strong&gt; Unifly uses reactive streams,&lt;br&gt;
&lt;code&gt;tokio::watch&lt;/code&gt; channels that push data changes to the UI. The TUI doesn't ask "has anything changed?" on a timer. It gets told when something changes. The difference in responsiveness is visceral.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The product lesson: the dual-product pattern.&lt;/strong&gt; Unifly ships as two binaries&lt;br&gt;
from the same codebase: &lt;code&gt;unifly&lt;/code&gt; (CLI for scripting and automation, JSON output, composable with pipes) and &lt;code&gt;unifly-tui&lt;/code&gt; (interactive dashboard for humans). One core, two faces. The CLI lets you &lt;code&gt;unifly devices --json | jq '.[] | select(.status == "offline")'&lt;/code&gt;. The TUI lets you explore the same data visually, drill into details, restart devices. Neither is better; they serve different workflows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdagtzwzghmjieejxix4p.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdagtzwzghmjieejxix4p.gif" alt="Unifly TUI tour showing real-time network stats, device health, and traffic charts" width="800" height="504"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  🤖 Iris Studio: The AI Workflow
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/hyperb1iss/git-iris" rel="noopener noreferrer"&gt;Iris Studio&lt;/a&gt; is a six-mode AI-powered git workflow tool. Explore code semantically, generate commit messages, run code reviews, draft PR descriptions, create changelogs, write release notes, all from a three-panel TUI with a universal chat interface. Built in Rust with Ratatui.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The design lesson: modes need visual identity.&lt;/strong&gt; Six modes could easily feel&lt;br&gt;
like six apps wearing a trench coat. Consistent three-panel layout across all modes (navigate left, work center, inspect right) with mode-specific content keeps it unified. Shift+letter shortcuts for mode switching build muscle memory fast.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The architecture lesson: pure reducers make AI UIs predictable.&lt;/strong&gt; When an AI&lt;br&gt;
agent controls your UI, you need a state model you can reason about. Iris uses a Redux-style pure reducer where every state transition is a function from &lt;code&gt;(state, event) → (new state, side effects)&lt;/code&gt;. No I/O inside the reducer. Agent responses flow through the same event system as keystrokes. This makes the entire UI testable, debuggable, and auditable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The interaction lesson: universal chat changes everything.&lt;/strong&gt; Press &lt;code&gt;/&lt;/code&gt; in any&lt;br&gt;
mode and a chat overlay appears. Ask Iris to refine a commit message, explain a security finding in a review, or add detail to release notes, and it updates the content directly through tool calls. The AI isn't in a separate panel; it's accessible &lt;em&gt;from anywhere&lt;/em&gt; you're working. Context follows you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgafz44hoqbvjfv0nztvc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgafz44hoqbvjfv0nztvc.png" alt="Iris Studio commit mode with three-panel layout and SilkCircuit Neon theme" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  🔹 q: The Minimalist
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/hyperb1iss/q" rel="noopener noreferrer"&gt;q&lt;/a&gt; is a tiny Claude Code CLI built with TypeScript, Bun, and Ink (React for terminals). One letter, four modes: query (fire-and-forget questions), pipe (Unix pipeline citizen), interactive (full TUI), and agent (tool-using AI).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The design lesson: know when &lt;em&gt;not&lt;/em&gt; to be a TUI.&lt;/strong&gt; q's pipe mode is the&lt;br&gt;
opposite of a rich interface: raw text output, no markdown formatting, no code blocks, no decoration. It's a perfect Unix filter. &lt;code&gt;cat config.yaml | q "convert to json" &amp;gt; config.json&lt;/code&gt;. The discipline is in &lt;em&gt;not&lt;/em&gt; rendering things when the context doesn't want rendering.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The framework lesson: React's mental model works in terminals.&lt;/strong&gt; Ink maps&lt;br&gt;
React's component model directly to the terminal. &lt;code&gt;&amp;lt;Box flexDirection="column"&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;Text color="cyan"&amp;gt;&lt;/code&gt;, &lt;code&gt;useState&lt;/code&gt; for state, &lt;code&gt;useEffect&lt;/code&gt; for side effects. If you know React, you know Ink. The conceptual overhead is near zero. Claude Code itself is built on Ink, and that's not a niche endorsement.&lt;/p&gt;
&lt;h3&gt;
  
  
  👁️ Vigil: The Agent Orchestrator
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/hyperb1iss/vigil" rel="noopener noreferrer"&gt;Vigil&lt;/a&gt; is a PR lifecycle manager that dispatches AI agents to handle mechanical code review tasks. Card-based dashboard showing all your open PRs, six specialized agents (triage, fix, respond, rebase, evidence, learning), and a human-in-the-loop toggle that ranges from "approve every action" to "let agents run."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The design lesson: state machines need visual language.&lt;/strong&gt; Vigil classifies PRs&lt;br&gt;
into five states: hot (needs attention now), waiting (blocked on something), ready (good to merge), dormant (stale), blocked (can't proceed). Each state maps to a color, an icon, and a card style. The dashboard &lt;em&gt;looks&lt;/em&gt; different when things are on fire versus when everything is calm. Color as information, not decoration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The architecture lesson: the HITL/YOLO spectrum is a design decision.&lt;/strong&gt;&lt;br&gt;
Sometimes you want an agent to show you what it plans to do and wait for approval. Sometimes you want it to just handle things. The toggle between these modes is a UX feature, not a backend feature. It changes the entire interaction model of the dashboard. Building it taught me that human-AI control boundaries are UI design problems.&lt;/p&gt;
&lt;h3&gt;
  
  
  💎 Opaline: The Invisible One
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/hyperb1iss/opaline" rel="noopener noreferrer"&gt;Opaline&lt;/a&gt; is the theme engine underneath the other four. It doesn't have its own TUI. It &lt;em&gt;is&lt;/em&gt; the reason the other four look cohesive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it taught: infrastructure is the unglamorous work that makes everything&lt;br&gt;
else possible.&lt;/strong&gt; Opaline is 20 builtin themes, a four-pass resolution pipeline, contract testing that validates every theme against a strict schema, and a &lt;code&gt;ThemeSelector&lt;/code&gt; widget for drop-in theme pickers. Nobody sees it directly. Everyone benefits.&lt;/p&gt;
&lt;h2&gt;
  
  
  🛠️ Choosing Your Framework
&lt;/h2&gt;

&lt;p&gt;I build in two frameworks, Ratatui (Rust) and Ink (TypeScript/React). Having shipped production apps in both, here's the actual decision guide:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reach for Ratatui&lt;/strong&gt; when your app is a dashboard, a monitor, or any data-heavy&lt;br&gt;
view that runs for hours. Immediate-mode rendering means you describe the entire UI every frame and the framework diffs the terminal buffer for you. Zero garbage collection pauses. Runs beautifully over SSH. Netflix, AWS, and OpenAI all ship Ratatui apps in production. It's the right tool for btop-shaped problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reach for Ink&lt;/strong&gt; when your app is conversational, agent-driven, or benefits&lt;br&gt;
from the npm ecosystem (syntax highlighting, markdown rendering, rich text). React's component model and hooks make state management familiar. Bun gives you fast startup and embedded SQLite. Claude Code is built on Ink. It's the right tool for chat-shaped problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What they share is more interesting than how they differ.&lt;/strong&gt; Both ecosystems&lt;br&gt;
converge on the same design patterns: unidirectional data flow (events → state → render), vim keybindings as the default navigation model, footer key hints with &lt;code&gt;?&lt;/code&gt; help overlays, semantic color systems, and action dispatch architectures. The framework is the least interesting choice you'll make. The design principles travel across both.&lt;/p&gt;

&lt;p&gt;The real question isn't "Ratatui or Ink?" It's "what patterns does my app's data flow demand?" If you answer that well, the framework choice falls out naturally.&lt;/p&gt;
&lt;h2&gt;
  
  
  🎭 Playwright for Terminals
&lt;/h2&gt;

&lt;p&gt;Here's the part nobody else is talking about.&lt;/p&gt;

&lt;p&gt;AI coding agents can write TUI code all day. Claude Code, Codex, Gemini CLI: they'll generate Ratatui components, Ink React trees, Bubbletea models without breaking a sweat. But they have a fundamental problem: &lt;strong&gt;they're blind&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When Claude Code runs your TUI app, it gets stdout text. It cannot see the layout. It cannot verify that panel borders line up. It cannot check that &lt;code&gt;j&lt;/code&gt;/&lt;code&gt;k&lt;/code&gt; navigates correctly. It cannot tell if the status bar is rendering in the right color. It's building a visual interface &lt;em&gt;without eyes&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This isn't a theoretical gap. Claude Code's Bash tool &lt;a href="https://github.com/anthropics/claude-code/issues/9881" rel="noopener noreferrer"&gt;doesn't allocate a real PTY&lt;/a&gt;. Interactive programs hang. TUI apps corrupt terminal state. Gemini CLI shipped proper PTY support in October 2025; Claude Code still hasn't. The most capable AI coding agent in the world cannot interact with the category of applications we're building.&lt;/p&gt;

&lt;p&gt;Web developers solved this problem years ago with Playwright and Cypress. The agent writes code, opens a browser, renders the page, inspects the DOM, takes screenshots, simulates interactions, and iterates. Test-driven development with eyes.&lt;/p&gt;

&lt;p&gt;Terminals have nothing equivalent. Until now.&lt;/p&gt;
&lt;h3&gt;
  
  
  👻 ghostty-automator
&lt;/h3&gt;

&lt;p&gt;I built &lt;a href="https://github.com/hyperb1iss/ghostty-automator" rel="noopener noreferrer"&gt;ghostty-automator&lt;/a&gt;, a purpose-built IPC layer for &lt;a href="https://ghostty.org/" rel="noopener noreferrer"&gt;Ghostty&lt;/a&gt; that exposes the terminal's actual state to external processes.&lt;/p&gt;

&lt;p&gt;Not scraped text. Not regex-parsed ANSI escape sequences. Not tmux pane captures. The terminal emulator itself tells you, through structured data over a Unix socket, exactly what's on screen: every cell's character, foreground color, background color, bold/italic/underline state, and cursor position. The full semantic state of the rendered terminal.&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://github.com/hyperb1iss/ghostty-automator-python" rel="noopener noreferrer"&gt;Python library&lt;/a&gt; wraps this with Playwright-style async ergonomics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;terminal.send("cargo run")&lt;/code&gt;: send a command&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;terminal.wait_for_text("Listening on")&lt;/code&gt;: wait for specific output&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;terminal.screen()&lt;/code&gt;: read what's on screen as text&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;terminal.cells()&lt;/code&gt;: read styled cells with color and formatting&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;terminal.screenshot()&lt;/code&gt;: capture a PNG&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;terminal.press("KeyJ")&lt;/code&gt;: send keystrokes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;terminal.click(row=5, col=20)&lt;/code&gt;: click at a position&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;terminal.expect.to_contain("Dashboard")&lt;/code&gt;: assert content&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An &lt;a href="https://github.com/hyperb1iss/ghostty-automator-python/tree/main/skills/ghostty-terminal-automation" rel="noopener noreferrer"&gt;AI agent skill&lt;/a&gt; wraps the whole thing so any Claude Code agent can install terminal automation in one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add hyperb1iss/ghostty-automator-python
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent gets the full API: send commands, read screens, take screenshots, click cells, assert content. No MCP server configuration, no protocol wiring. Just install and go.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔄 The Loop
&lt;/h3&gt;

&lt;p&gt;Put the whole stack together and something remarkable happens:&lt;/p&gt;

&lt;p&gt;The AI agent has &lt;strong&gt;design knowledge&lt;/strong&gt;: a &lt;a href="https://github.com/hyperb1iss/hyperskills" rel="noopener noreferrer"&gt;3,000-line TUI design skill&lt;/a&gt; covering layout paradigms, color theory, interaction patterns, accessibility requirements, and anti-patterns ranked by real-world complaint frequency.&lt;/p&gt;

&lt;p&gt;It has &lt;strong&gt;theming infrastructure&lt;/strong&gt;: Opaline, so it can work with semantic colors and swap themes without touching the layout code.&lt;/p&gt;

&lt;p&gt;It has &lt;strong&gt;frameworks&lt;/strong&gt;: Ratatui and Ink, which it already knows how to use from training data and documentation.&lt;/p&gt;

&lt;p&gt;And now it has &lt;strong&gt;eyes and hands&lt;/strong&gt;: ghostty-automator, so it can run the app in a real terminal, see the rendered output, interact with it through keystrokes and mouse events, and verify that what it built matches what it intended.&lt;/p&gt;

&lt;p&gt;The loop closes: &lt;strong&gt;design → build → run → see → fix → repeat&lt;/strong&gt;. The same workflow web developers have had for years, finally available for terminal applications.&lt;/p&gt;

&lt;p&gt;Most terminal automation approaches parse ANSI byte streams, capture tmux panes, or run headless emulators. ghostty-automator is different: purpose-built IPC where the emulator itself participates. No parsing, no scraping, no guessing. The terminal tells you its state because you asked in its native protocol.&lt;/p&gt;

&lt;p&gt;This is Playwright for terminals. And I think it changes what's possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔮 What Comes Next
&lt;/h2&gt;

&lt;p&gt;The terminal stopped being the environment you escaped from. It became the environment you returned to, because it's actually better for how serious work happens now.&lt;/p&gt;

&lt;p&gt;AI agents made it the control plane for software development. Modern frameworks made it beautiful. A generation of Rust and Go tooling made it a pleasure to live in. And now the infrastructure exists for those same agents to build, test, and iterate on terminal interfaces autonomously.&lt;/p&gt;

&lt;p&gt;We have design principles for a medium that never had them. We have theming systems that bring design-system rigor to the terminal. We have frameworks in multiple languages that make building TUIs genuinely enjoyable. And we have an automation layer that gives AI agents eyes.&lt;/p&gt;

&lt;p&gt;What we need now is more people building beautiful things. The terminal is a canvas. The tools are ready. The renaissance is here.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Projects mentioned in this post:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/hyperb1iss/opaline" rel="noopener noreferrer"&gt;Opaline&lt;/a&gt;: Token-based theme engine for
Ratatui (20 builtin themes)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/hyperb1iss/unifly" rel="noopener noreferrer"&gt;Unifly&lt;/a&gt;: UniFi network management CLI +
TUI&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/hyperb1iss/git-iris" rel="noopener noreferrer"&gt;Git-Iris&lt;/a&gt;: AI-powered git workflow
with Iris Studio TUI&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/hyperb1iss/q" rel="noopener noreferrer"&gt;q&lt;/a&gt;: The tiniest Claude Code CLI&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/hyperb1iss/vigil" rel="noopener noreferrer"&gt;Vigil&lt;/a&gt;: AI-powered PR lifecycle manager&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/hyperb1iss/ghostty-automator" rel="noopener noreferrer"&gt;ghostty-automator&lt;/a&gt;: Terminal
automation IPC for Ghostty&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/hyperb1iss/ghostty-automator-python" rel="noopener noreferrer"&gt;ghostty-automator-python&lt;/a&gt;:
Playwright-style Python API + AI agent skill&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/hyperb1iss/chromacat" rel="noopener noreferrer"&gt;ChromaCat&lt;/a&gt;: Terminal colorization
with animated gradient patterns and 40+ themes&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/hyperb1iss/silkcircuit" rel="noopener noreferrer"&gt;SilkCircuit&lt;/a&gt;: Electric meets
elegant — terminal design language and theme system&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/hyperb1iss/hyperskills" rel="noopener noreferrer"&gt;tui-design skill&lt;/a&gt;: 3,000-line TUI
design knowledge base for AI agents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Frameworks:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://ratatui.rs/" rel="noopener noreferrer"&gt;Ratatui&lt;/a&gt;: Rust terminal UI framework (18.7K stars, used
by Netflix/AWS/OpenAI)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/vadimdemedes/ink" rel="noopener noreferrer"&gt;Ink&lt;/a&gt;: React for the terminal
(TypeScript)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/charmbracelet/bubbletea" rel="noopener noreferrer"&gt;Bubbletea&lt;/a&gt;: Elm architecture for
Go TUIs (40K stars)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/Textualize/textual" rel="noopener noreferrer"&gt;Textual&lt;/a&gt;: Python TUI framework with
CSS-like styling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Further reading:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://techcrunch.com/2025/07/15/ai-coding-tools-are-shifting-to-a-surprising-place-the-terminal/" rel="noopener noreferrer"&gt;AI coding tools are shifting to the terminal&lt;/a&gt;,
TechCrunch&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://adelzaalouk.me/2026/feb/22/terminals-agents-and-the-control-plane-nobody-built/" rel="noopener noreferrer"&gt;Your terminal is an AI runtime now&lt;/a&gt;,
Adel Zaalouk&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://newsletter.semianalysis.com/p/claude-code-is-the-inflection-point" rel="noopener noreferrer"&gt;Claude Code is the Inflection Point&lt;/a&gt;,
SemiAnalysis&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hatchet.run/blog/tuis-are-easy-now" rel="noopener noreferrer"&gt;Building a TUI Is Easy Now&lt;/a&gt;,
Hatchet&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://brandur.org/interfaces" rel="noopener noreferrer"&gt;Learning From Terminals to Design the Future of User Interfaces&lt;/a&gt;,
Brandur&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://jensroemer.com/writing/tui-design/" rel="noopener noreferrer"&gt;TUI Design&lt;/a&gt;, Jens Roemer&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;✨ &lt;em&gt;Originally published at &lt;a href="https://hyperbliss.tech/blog/2026.04.04_terminal-renaissance/" rel="noopener noreferrer"&gt;hyperbliss.tech&lt;/a&gt;.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;💜 &lt;em&gt;If you dig this kind of work, consider &lt;a href="https://github.com/sponsors/hyperb1iss" rel="noopener noreferrer"&gt;sponsoring me on GitHub&lt;/a&gt;.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;🦋 &lt;em&gt;Find me on &lt;a href="https://bsky.app/profile/hyperbliss.tech" rel="noopener noreferrer"&gt;Bluesky&lt;/a&gt; and &lt;a href="https://github.com/hyperb1iss" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>terminal</category>
      <category>tui</category>
      <category>design</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
