<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
  <title>Gioser Journal</title>
  <link>https://gioser.net/en/blog/</link>
  <atom:link href="https://gioser.net/en/blog/feed.xml" rel="self" type="application/rss+xml"/>
  <description>What gets built in the workshop, told with the numbers in plain sight.</description>
  <language>en</language>
  <lastBuildDate>Sat, 24 Oct 2026 09:00:00 -0500</lastBuildDate>
  <item>
    <title>Your WordPress, without WordPress: the same site to the pixel, with its store, without a single line of PHP</title>
    <link>https://gioser.net/en/blog/your-wordpress-without-wordpress/</link>
    <guid isPermaLink="true">https://gioser.net/en/blog/your-wordpress-without-wordpress/</guid>
    <pubDate>Sat, 24 Oct 2026 09:00:00 -0500</pubDate>
    <dc:creator>Gioser Editorial</dc:creator>
    <category>tawasuyu · Making</category>
    <description>qhatu absorbs a WordPress site with one command and leaves it identical to the pixel, with no PHP, no database and no plugins, and if it sells with WooCommerce it brings the store too: on a client&#39;s real site, 9 of 9 WordPress programs answered anyone and on the copy none does; building each page went from about 825 to about 135 milliseconds; no old address is lost; and it is still edited in place, with signed history and rollback.</description>
    <enclosure url="https://gioser.net/blog/medios/qhatu-wordpress-portada.jpg" type="image/jpeg" length="86164"/>
    <content:encoded><![CDATA[<p class="lede">Every time someone opens a page of a WordPress site, a program starts on the server: it reads the database, loads the theme, wakes up every plugin, builds the HTML and sends it. The same thing, over and over, for text that changes once a month. And all the while, that program leaves the doors it is administered through open to the whole internet. This article tells how <strong>qhatu</strong> —tawasuyu's content manager— takes a real WordPress site whole, leaves it <strong>identical to the pixel</strong>, brings its WooCommerce store along, and strips away everything that could be attacked.</p>

<figure class="foto">
  <img src="https://gioser.net/blog/medios/qhatu-wordpress-portada.jpg" alt="Chart: on the left, WordPress with 9 of 9 programs answering anyone, with the list of their addresses —wp-login.php, wp-admin, xmlrpc.php, wp-json, the user list, author=1, readme.html, install.php, wp-cron.php—; on the right, qhatu and saywa with 0 of 9, 0 different pixels out of 3,278,400, 825 to 135 milliseconds and zero PHP" width="1600" height="900" loading="eager">
  <figcaption>Measured on October 24, 2026 on a client's real site and its copy.</figcaption>
</figure>

<h2>The site that is built on every visit</h2>

<p>WordPress is the most common way to have a site, and for good reasons: it installs in an afternoon, there is a theme for everything, and a builder like Elementor lets you design without writing code. The price is paid later, in installments. Every plugin is someone else's code running with <em>all</em> of the site's permissions; every postponed update is a door; and the database, the login and the API stay listening around the clock, even if one person edits the site twice a month.</p>

<p>The site all this was tested on belongs to a real client: a retreat center built with WordPress, the WoodMart theme and Elementor Pro, with 64 pages, a gallery, a blog and two contact forms. An ordinary site, of the kind there are millions of. The request was simple: <strong>keep it exactly the same, and keep it easy to edit</strong>.</p>

<h2>One command</h2>

<p>What was done by hand on the first day —downloading the rendered site, cleaning what WordPress adds to every file name, re-pointing the forms— is now a verb:</p>

<pre><code>qhatu absorb https://the-site.com/ folder</code></pre>

<p>It reads the sitemaps WordPress publishes, downloads every page and everything it needs —stylesheets, scripts, images in all their sizes, fonts, icons—, and leaves every reference pointing to the local copy. It does not download what is not content: the cart, the admin panel, the feeds, the searches. If part of the site is only assembled by JavaScript in the browser, with <code>--render</code> each page first goes through a headless Chrome and is saved already assembled. On the client's site:</p>

<div class="tabla" role="region" aria-label="The absorption of the real site" tabindex="0">
<table>
  <thead><tr><th scope="col">what</th><th scope="col">measured</th></tr></thead>
  <tbody>
    <tr><td>pages</td><td class="propio">64</td></tr>
    <tr><td>resources (stylesheets, scripts, images, fonts)</td><td class="propio">448, 45 MB</td></tr>
    <tr><td>time, with a courtesy pause between requests</td><td class="propio">6 minutes</td></tr>
    <tr><td>broken references in the copy</td><td class="propio">0</td></tr>
  </tbody>
</table>
</div>

<p>And it does not have to be WordPress: the same verb took a Joomla site, a Squarespace demo that builds everything with JavaScript, and the first website in history, CERN's, with zero broken references in all three.</p>

<h2>Identical to the pixel, with a control arm</h2>

<p>"Exactly the same" can be measured. The same page of the original and of the copy was opened in Chrome, at 1366 by 2400 pixels, and the two screenshots were compared point by point. On the home page and on a blog post, <strong>0 different pixels out of 3,278,400</strong>. For that zero to mean something, the test has a control arm: each screenshot has 216,987 distinct colors, so it is not comparing two blank pages.</p>

<p>And honesty includes what did not come out zero. On a third page, 1,785 different pixels showed up in the menu strip. Before blaming the copy, the original was compared <em>with itself</em>, twice: it gave 1,642 and 0. It is the page itself, which does not paint the same way twice in a row.</p>

<h2>No old link breaks</h2>

<p>A site with years has links with years: on Facebook, in emails, on other blogs. WordPress answers addresses nobody typed by hand —<code>/?p=123</code>, <code>/2023/05/a-post/</code>, the categories, the feed— and a move that loses them leaves a trail of 404 errors. qhatu builds a table with all of them, and the server checks it before the files. Against the live site: <strong>143 old addresses, none of them a 404</strong> —55 that are still a page and 88 that the table takes to their new place—. And an invented one still gives a 404, which is what has to happen.</p>

<h2>Nothing to hack</h2>

<p>A WordPress scanner always starts the same way: it asks for the addresses every WordPress has. That same question was asked of both sites, in passive mode —only read requests to public addresses, without trying a single password—:</p>

<div class="tabla" role="region" aria-label="What each site answers" tabindex="0">
<table>
  <thead><tr><th scope="col">address</th><th scope="col">what it is</th><th scope="col">WordPress</th><th scope="col">copy</th></tr></thead>
  <tbody>
    <tr><td><code>/wp-login.php</code></td><td>the login door</td><td>answers</td><td class="propio">404</td></tr>
    <tr><td><code>/wp-admin/</code></td><td>the panel</td><td>answers</td><td class="propio">404</td></tr>
    <tr><td><code>/xmlrpc.php</code></td><td>the classic door for batch brute force</td><td>answers</td><td class="propio">404</td></tr>
    <tr><td><code>/wp-json/</code></td><td>the API</td><td>answers</td><td class="propio">404</td></tr>
    <tr><td><code>/wp-json/wp/v2/users</code></td><td>the list of who can log in</td><td>answers, with 3 names</td><td class="propio">404</td></tr>
    <tr><td><code>/?author=1</code></td><td>the first author's username</td><td>tells it</td><td class="propio">no</td></tr>
    <tr><td><code>/readme.html</code></td><td>the exact version</td><td>answers</td><td class="propio">404</td></tr>
    <tr><td><code>/wp-admin/install.php</code></td><td>the installer</td><td>answers</td><td class="propio">404</td></tr>
    <tr><td><code>/wp-cron.php</code></td><td>tasks anyone can trigger</td><td>answers</td><td class="propio">404</td></tr>
  </tbody>
</table>
</div>

<p><strong>Nine out of nine against zero out of nine.</strong> On top of that, the original announced in its own code the exact version of WordPress and of two of its plugins: exactly what an attacker looks for to cross against a list of known flaws. It is not that the copy has those doors better locked: <strong>it does not have them</strong>. There is no PHP to execute, no database to query, no users to guess.</p>

<p>Measuring this turned up a detail worth telling. The copy still said "WordPress" in an invisible tag of the HTML, inherited from the original: a scanner read it and announced a WordPress that no longer existed. The absorber now removes it.</p>

<p>And the contact forms, which in WordPress are one more plugin? On the copy they are handled by a <strong>WebAssembly function</strong> that runs on the server with declared capabilities: it can store what arrives, read the clock and send the notice by email, and nothing else. It cannot read the disk; what it did not ask for does not exist for it. The messages are read in the panel, and download as a spreadsheet. The search magnifier the copy can add to its menu is another function like that: it reads an index published along with the site, and there is no search server to attack.</p>

<h2>And if it also sells</h2>

<p>Many WordPress sites are also a store, with WooCommerce. A store is not a set of pages: it is a catalog with prices, variants and stock, and a checkout. So it is not copied as HTML: with <code>--as-content</code>, qhatu reads the catalog through the same public API WooCommerce's own cart uses, and every product goes into qhatu's own store with its name, its exact price, its currency, its images and one variant per combination —size, color—, with the sold-out one marked as sold out. The price never goes through a number with a decimal point: it is stored in cents, and at checkout the server recalculates it against the published catalog, so nobody pays whatever they like by sending another number.</p>

<p>It was tested against a real WooCommerce, with the sample products WooCommerce itself ships with: <strong>16 products and 7 variants</strong> came in, and an instrument that compares the original store against the copy, product by product and variant by variant, came out <strong>identical</strong>. Its control arm: after absorbing, a price was changed and a variant sold out on the original, and the instrument named exactly those two differences. Each product's reviews come with it, at the foot of its page. And with a WordPress application password —the kind WordPress itself lets you create for this— comes how many units are left of each product and each variant too: the server counts down what is sold. Then a purchase was made: a hoodie, into the cart, paid with PayPal in its test environment, and the store came back saying the order was paid, with PayPal's capture recorded on the server side.</p>

<p>That store is online, to look at and to buy with play money: <a href="https://tienda.gioser.net/">tienda.gioser.net</a>.</p>

<p>And it does not look like two sites stuck together. What qhatu builds —the products, the list, the cart, the blog posts— goes inside the original site's header, menu, footer, colors and fonts. Measured: the header of a page that came from the original and that of a product built by qhatu give <strong>0 different pixels</strong>. The phone menu opens on the copy even with the original WordPress already turned off, and it no longer offers "Checkout" or "My account", which do not exist on the copy.</p>

<h2>Faster, and measured without cheating</h2>

<p>Five pages, five cold loads on each side —a fresh browser per load, no cache—, alternating original and copy so that a bad streak on the network does not fall entirely on one side. The medians:</p>

<div class="tabla" role="region" aria-label="Measured speed, original against copy" tabindex="0">
<table>
  <thead><tr><th scope="col">page</th><th scope="col">first byte</th><th scope="col">largest paint</th><th scope="col">full load</th></tr></thead>
  <tbody>
    <tr><td>home</td><td>2.5&nbsp;s&nbsp;→ <strong>0.9&nbsp;s</strong></td><td>6.1&nbsp;s&nbsp;→ <strong>4.9&nbsp;s</strong></td><td>9.9&nbsp;s&nbsp;→ <strong>5.9&nbsp;s</strong></td></tr>
    <tr><td>service page</td><td>1.9&nbsp;s&nbsp;→ <strong>0.8&nbsp;s</strong></td><td>6.5&nbsp;s&nbsp;→ <strong>3.8&nbsp;s</strong></td><td>14.9&nbsp;s&nbsp;→ <strong>5.4&nbsp;s</strong></td></tr>
    <tr><td>long page with gallery</td><td>2.3&nbsp;s&nbsp;→ <strong>0.9&nbsp;s</strong></td><td>11.7&nbsp;s&nbsp;→ <strong>6.3&nbsp;s</strong></td><td>22.3&nbsp;s&nbsp;→ <strong>7.9&nbsp;s</strong></td></tr>
    <tr><td>blog listing</td><td>2.4&nbsp;s&nbsp;→ <strong>0.7&nbsp;s</strong></td><td>4.5&nbsp;s&nbsp;→ <strong>4.1&nbsp;s</strong></td><td>5.1&nbsp;s&nbsp;→ 5.3&nbsp;s</td></tr>
    <tr><td>a post</td><td>2.3&nbsp;s&nbsp;→ <strong>0.8&nbsp;s</strong></td><td>5.9&nbsp;s&nbsp;→ <strong>2.5&nbsp;s</strong></td><td>7.0&nbsp;s&nbsp;→ <strong>5.2&nbsp;s</strong></td></tr>
  </tbody>
</table>
</div>

<p>The bytes that travel are practically the same: it is the same page. What changes is the server. And there is a caveat an honest article has to make: the two sites are on different servers, in different places, and the copy was closer to where it was measured from. So the network was separated from the software. Opening the connection costs 392 milliseconds to the original and 179 to the copy; that is distance, not code. Subtracting one round trip on each side, what remains is the work of building the page:</p>

<figure class="foto">
  <svg viewBox="0 0 640 132" width="100%" role="img" aria-label="Bar chart: building a page costs WordPress about 825 milliseconds and saywa about 135, close to six times less.">
    <text x="0" y="22" style="font:500 14px var(--sans);fill:var(--tinta)">WordPress: ~825 ms per page</text>
    <rect x="0" y="32" width="610" height="22" rx="4" style="fill:var(--tinta-tenue)"/>
    <text x="0" y="90" style="font:500 14px var(--sans);fill:var(--tinta)">saywa: ~135 ms per page</text>
    <rect x="0" y="100" width="100" height="22" rx="4" style="fill:var(--acento)"/>
  </svg>
  <figcaption>The server's work, with network distance subtracted. Measured with curl, five requests on each side.</figcaption>
</figure>

<p>And on a phone there is something more. When publishing, qhatu prepares every large image in several widths and the browser picks the one it needs: on the client's home page, seen at 390 pixels wide, <strong>72% fewer image bytes</strong> are downloaded, without moving a pixel on a desktop screen.</p>

<h2>And it is still edited, in place</h2>

<p>A static copy that cannot be touched would be a museum. qhatu's is edited from a panel that lives at its own address —nothing on the public site links to it—, on the page itself, just as it looks:</p>

<figure class="foto">
  <img src="https://gioser.net/blog/medios/qhatu-editor-y-resultado.jpg" alt="Screenshot: on the left, the qhatu panel with an article open —date, cover image and the body with its bar for bold, italics, headings, lists, quotes, links and images, and the Save button—; on the right, the same article published on the gioser blog, with its illustration and the heading «Qué es tawasuyu»" width="1600" height="705" loading="lazy">
  <figcaption>The qhatu panel and what it publishes, side by side: on the left you write, on the right is the article as a reader sees it. It is this very blog, which qhatu also builds.</figcaption>
</figure>

<ul>
  <li><strong>Click on a text and type.</strong> A bar offers bold, italics, links, lists, headings and quotes, and the colors are <em>the site's own</em>, not just any picker. Pasting from Word or Google Docs keeps the formatting and throws away the junk.</li>
  <li><strong>Click on an image and replace it.</strong> Choosing several at once adds photos to a gallery: each extra one duplicates the item and puts its own in.</li>
  <li><strong>Duplicate, move and delete</strong> any block: a card, a section, a list item. And a new page is a copy of another, at whatever address you want.</li>
  <li><strong>The site's palette and fonts on the side.</strong> The colors the page uses, counted; change one and see it instantly, and a button applies it to the eighty-odd stylesheets Elementor left behind. Fonts change the same way. If a text stops being readable on its background, the panel says so with the contrast measurement in hand.</li>
  <li><strong>Publishing is a signed act.</strong> Saving changes the folder; publishing turns the site into a new, signed version that the server serves whole or not at all. The history says what changed between any two versions, page by page. Going back to the previous one is a button, and it leaves the folder as it was too.</li>
</ul>

<p>And what the original built with Elementor no longer stays as HTML that can only be touched in place: with <code>--as-content</code> it comes in as qhatu blocks —heroes, columns, carousels, FAQs— that are edited with the block editor and painted with the site's theme. On the client's site, two of its Elementor pages came in as <strong>22 and 12 blocks</strong>, five heroes with their background photo and three carousels of ten to twelve photos, without a single widget left without an equivalent and without one image that failed to download.</p>

<p>All of that runs on <strong>saywa</strong>, tawasuyu's web server. On the machine where this site lives, saywa and the project's own forge have already replaced four programs: the web server, the git forge, the proxy and the PHP interpreter. Someone wrote both pieces from scratch, in Rust, with a rule that repeats across the whole project: what was not measured is not claimed.</p>

<aside class="ficha" aria-labelledby="ficha-qhatu">
  <h2 id="ficha-qhatu">We measured it</h2>
  <dl>
    <div><dt>WordPress programs that answer, original / copy</dt><dd>9 / 0</dd></div>
    <div><dt>Different pixels on the home page</dt><dd>0 of 3,278,400</dd></div>
    <div><dt>Pages and resources absorbed</dt><dd>64 and 448</dd></div>
    <div><dt>Broken references in the copy</dt><dd>0</dd></div>
    <div><dt>Old addresses that still arrive</dt><dd>143 of 143</dd></div>
    <div><dt>Building a page, WordPress / saywa</dt><dd>~825 / ~135 ms</dd></div>
    <div><dt>Image bytes on a phone</dt><dd>−72%</dd></div>
    <div><dt>Test WooCommerce store, original against copy</dt><dd>identical (16 products, 7 variants)</dd></div>
    <div><dt>Header of an original page / a qhatu page</dt><dd>0 different pixels</dd></div>
    <div><dt>qhatu: pieces, lines of Rust with their tests, tests</dt><dd>8 · 23,517 · 185</dd></div>
    <div><dt>saywa: pieces, lines of Rust with their tests, tests</dt><dd>13 · 21,510 · 221</dd></div>
  </dl>
  <p>Measurements from October 24, 2026, from a laptop, on a client's site and its copy; the store, the old addresses, the images and the Elementor blocks, on October 28; counts over the tawasuyu repository on October 28.</p>
</aside>

<h2>What it does not do yet</h2>

<ul>
  <li><strong>Charging real money has not been tested.</strong> The store charges with PayPal, and end to end it was tested in PayPal's test environment; with a real account, not yet.</li>
  <li><strong>From WooCommerce the catalog and its reviews come, not the history.</strong> Past orders, customers, coupons and shipping and tax rules stay in WordPress.</li>
  <li><strong>Rendering is slow.</strong> With <code>--render</code> the client's site took about 30 minutes instead of 6: Chrome loads every page in full.</li>
  <li><strong>There are reader accounts, members-only pages and a newsletter, but no paid membership.</strong></li>
  <li><strong>The speed numbers are from one day and one place.</strong> That is why the network separation is there: it is the part that does not depend on where it is measured from.</li>
</ul>

<h2>How to try it</h2>

<p>The store in this article is at <a href="https://tienda.gioser.net/">tienda.gioser.net</a>, and its panel is open: at <a href="https://tienda.gioser.net/_/">tienda.gioser.net/_/</a> anyone can get in with «Try it as an author» and edit it at will; their changes are wiped after 24 hours. The same qhatu builds this journal and the <a href="https://manual.tawasuyu.net/">tawasuyu manual</a>, and with one more line in its configuration it becomes a <a href="https://wiki.gioser.net/">wiki</a>: links by title, each page's signed history, and two people editing the same page at once without overwriting each other. To have the same on your own machine, a freshly created VPS is enough: <code>qhatu server install --domain the-site.com</code> leaves the server, the panel and the certificate running —measured on Debian 13 and Fedora 44, with a test certificate authority: the home page answers over HTTPS seven seconds after having access to the machine— and <code>qhatu absorb</code> brings the WordPress over. qhatu lives in the tawasuyu repository —<a href="https://git.tawasuyu.net/tawasuyu/tawasuyu">git.tawasuyu.net</a>, on its own server— under <code>02_ruway/qhatu</code>, and saywa under <code>03_ukupacha/saywa</code>. The instruments of this article —exposure, speed, pixels and the store comparison— are in <code>scripts/qhatu-careo/</code>: anyone can run them against their own WordPress and against its copy, and compare.</p>
]]></content:encoded>
  </item>
  <item>
    <title>Arje: the init that remembers — your whole system as a signed commit</title>
    <link>https://gioser.net/en/blog/arje-the-init-that-remembers/</link>
    <guid isPermaLink="true">https://gioser.net/en/blog/arje-the-init-that-remembers/</guid>
    <pubDate>Fri, 23 Oct 2026 09:00:00 -0500</pubDate>
    <dc:creator>Gioser Editorial</dc:creator>
    <category>tawasuyu · Root</category>
    <description>Arje, tawasuyu&#39;s init written in Rust, replaces systemd: boot as a graph of typed capabilities, the whole system as a signed commit —with log, diff, bisect, blame and autopsy—, jails derived from the unit instead of configured, and the resurrection of a complete machine over the wire, with no server in between.</description>
    <enclosure url="https://gioser.net/blog/medios/arje-portada.jpg" type="image/jpeg" length="452078"/>
    <content:encoded><![CDATA[<p class="lede">You press the power button. Before your desktop, your files or your network exist, the kernel launches <strong>a single program</strong> and hands it the machine: the <em>init</em>, process number 1. Everything that will run that day descends from it, and if it dies, the whole system dies with it. On almost every Linux in the world that program is <strong>systemd</strong>. On tawasuyu machines it is <strong>arje</strong> —from the Greek <em>ἀρχή</em>: origin, principle—, and this article tells what it does differently, with the numbers in plain sight.</p>

<figure class="foto">
  <img src="https://gioser.net/blog/medios/arje-portada.jpg" alt="Illustration: a person in an Andean poncho watches a valley at dawn from a crag; a chakana shines in the sky, the boot chain floats at the center —UEFI, kernel, graph, chakana, session— and on the right a column of glowing commits rises from the valley's servers" width="1600" height="900" loading="eager">
  <figcaption>Illustration: the boot as a chain of acts, and the system as a column of commits rising from the machines in the valley.</figcaption>
</figure>

<h2>The program that runs before all others</h2>

<p>An init does, at minimum, three things: it starts services in the right order, adopts orphaned processes, and brings back whatever falls over. Sounds small. It isn't: it is the only process that can never fail —if process 1 dies, the kernel panics and the screen freezes— and the only one that watches every other process be born and die. Whoever writes the init decides how your computer boots, what runs with which permissions, and what happens when something goes wrong.</p>

<p>That is why it matters who writes it. And why it is worth looking at who writes it today.</p>

<h2>systemd: how the boot process got an owner</h2>

<p>systemd was born in 2010 inside Red Hat to solve real problems: shell-script inits were slow, fragile and supervised nothing. Let's say it without caricature: <strong>it won because what came before was worse</strong>. But it won in a particular way: by absorbing. What began as an init today includes the session manager (logind), the log manager (journald, with its own binary format), the network manager (networkd), DNS (resolved), time, users (homed), partitions (repart), containers (nspawn), a boot loader and a dozen more pieces. No major distribution can remove one piece without breaking the rest: Debian adopted it after one of the harshest votes in its history, and GNOME simply does not fully start without its interfaces.</p>

<p>That is corporate software in the exact sense of the term: it was born to solve one company's problems, grew by absorbing what nobody asked it to absorb, and reached a point where <strong>opting out is no longer a practical option</strong>. Its creator works at Microsoft today; the project is governed by Red Hat/IBM's calendar. No conspiracy theory is needed: it is enough to note that the piece deciding how almost every Linux on the planet boots has a roadmap, and you are not the one writing it.</p>

<p>And there is a technical argument, colder than the political one. systemd's process 1 parses text configuration files, speaks D-Bus, and carries an enormous surface of C code on its back. In the tawasuyu project that is condensed into a six-word doctrine: <em>"a parser in the init is a bomb."</em> Everything process 1 does beyond the minimum is attack surface in the one process that cannot die.</p>

<figure class="foto">
  <svg viewBox="0 0 640 150" width="100%" role="img" aria-label="Bar chart: systemd's C code adds up to 1,175,757 lines; all of arje measures 48,171 lines of Rust, about 4 percent.">
    <text x="0" y="22" style="font:500 14px var(--sans);fill:var(--tinta)">systemd (C and headers)</text>
    <rect x="0" y="32" width="610" height="22" rx="4" style="fill:var(--tinta-tenue)"/>
    <text x="604" y="48" text-anchor="end" style="font:500 13px var(--mono);fill:var(--fondo)">1,175,757 lines</text>
    <text x="0" y="92" style="font:500 14px var(--sans);fill:var(--tinta)">arje (31 crates, Rust)</text>
    <rect x="0" y="102" width="25" height="22" rx="4" style="fill:var(--acento)"/>
    <text x="27" y="118" style="font:500 13px var(--mono);fill:var(--tinta)">48,171 lines — 4 %</text>
  </svg>
  <figcaption>Size at the same scale. arje: counted on the tawasuyu repository on October 22, 2026 (31 crates, 504 tests). systemd: .c and .h files of its public repository on October 23, 2026 (commit 154df43); with hardware data, translations and documentation the whole repository adds up to 2.48 million. Both bars are counted the same way: physical lines, tests and comments included. The small bar is not modesty: it is the thesis — what process 1 does not carry cannot crash on it.</figcaption>
</figure>

<h2>Arje, in one sentence</h2>

<p>Arje covers everything from "you pressed POWER" to "the system is up": its own UEFI boot loader, process 1, supervision, isolation, and compatibility with the old world. And it speaks another language, because it thinks differently:</p>

<div class="tabla" role="region" aria-label="Vocabulary: what systemd says and what arje says" tabindex="0">
<table>
  <thead><tr><th scope="col">systemd says</th><th scope="col">arje says</th><th scope="col">the difference</th></tr></thead>
  <tbody>
    <tr><td>unit / service</td><td><span class="pieza">Ente</span>, described by a <span class="pieza">Card</span></td><td>the unit is not an <code>.ini</code> file: it is a typed object, validated at compile time</td></tr>
    <tr><td>PID 1 (<code>systemd</code>)</td><td><span class="pieza">arje-zero</span>, "Ente #0"</td><td>minimal on purpose: never service logic inside process 1</td></tr>
    <tr><td>default target + <code>enable</code> symlinks</td><td>the <span class="pieza">Seed</span></td><td>what boots is a tree declared in one object, not a table of links scattered across the disk</td></tr>
    <tr><td>the set of active units</td><td>the <span class="pieza">fractal</span></td><td>a living graph of Entes, with typed events</td></tr>
    <tr><td>D-Bus as the control plane</td><td><span class="pieza">arje-bus</span></td><td>its own socket; the caller's identity is injected by the kernel and cannot be forged</td></tr>
    <tr><td>sandboxing via directives</td><td>the Card's <span class="pieza">soma</span></td><td>namespaces, cgroups, limits and jails declared in the same object that describes the process</td></tr>
  </tbody>
</table>
</div>

<h2>Five decisions that change everything</h2>

<p><strong>1 — The unit is a type, not a text file.</strong> A Card is a serialized Rust structure: there is no syntax parser in process 1, there is compile-time validation. A misspelled field is not a warning in a log nobody reads: it is an error before the binary even exists.</p>

<p><strong>2 — Dependencies are capabilities, not names.</strong> systemd says "I need <code>nginx.service</code>"; arje says "I need <em>whoever provides</em> this capability." Who provides it is interchangeable, and boot order <strong>is not declared: it is computed</strong> — a topological sort over the capability graph that detects cycles and discards the unsatisfiable before launching anything.</p>

<p><strong>3 — There is no <code>enable</code> or <code>disable</code>: there is a Seed.</strong> What starts your machine is the <code>genesis</code> tree of a single signable object. Changing the boot means editing that object — not creating symlinks nobody later remembers the reason for.</p>

<p><strong>4 — The control bus is authenticated by the kernel.</strong> Every privileged request (kill an Ente, freeze, change quotas) arrives with the caller's identity injected by the kernel via <code>SO_PEERCRED</code> — impossible to forge — plus one key verb: <code>RunCard</code> incarnates a new process <em>with the caller's permissions</em>, never the init's. Privilege escalation over the bus is impossible <strong>by construction</strong>, not by policy.</p>

<p><strong>5 — The supervisor is sovereign.</strong> In systemd, <code>systemctl stop</code> always wins. In arje, if the Card says "this is supervised," an external stop is merely a signal, and the supervisor decides whether the Ente comes back. Truly stopping something supervised requires removing it from the graph — which is exactly what an attacker with a shell <em>cannot</em> do.</p>

<h2>The boot you can see: six acts became three</h2>

<p>The most honest test of an init is not a benchmark: it is watching the screen from the moment you press the button. Seen that way, a typical Linux boot is a succession of flickers — firmware logo, console text, black screen, splash, another black screen, login. Watching a real arje boot with that eye revealed <strong>four extra acts</strong> (a colored square that was a forgotten placeholder, a menu that blinked every second, console text leaking over the graphics, a second redundant menu). The sequence that remains is three acts, with no black frame in between:</p>

<ol class="bucle">
  <li><span>loader</span>Arje's own UEFI graph menu: the bootable systems drawn as a graph, with a gradient and the animated chakana. Choosing here takes effect — it is <em>before</em> the kernel.</li>
  <li><span>splash</span>The native chakana, drawn by arje-splash straight to the framebuffer, reusing the video mode the loader left behind. No Plymouth.</li>
  <li><span>greeter</span>The compositor picks up the very same chakana from the splash and dissolves it over the graphical login. Between the two there is not a single black frame.</li>
</ol>

<figure class="video">
  <video src="https://gioser.net/blog/medios/arje-arranque.mp4" poster="https://gioser.net/blog/medios/arje-arranque-poster.jpg" width="1600" height="900" autoplay muted loop playsinline preload="metadata" aria-label="Footage of a laptop screen: arje's graph menu with three Linux kernels, the text «entregando el control» (handing over control), the splash chakana on a gray background, and the chakana dissolving over the login with a city of glowing lines"></video>
  <figcaption>Seventeen seconds in real time, filmed with a phone on the everyday laptop on October 23, 2026: the graph menu, «entregando el control» (handing over control), the splash chakana and the login. No editing beyond the crop.</figcaption>
</figure>


<p>That "not a single black frame" cost a hunt measured in milliseconds. The graphics engine's instrumentation showed that most of the gap between splash and desktop was <strong>turning the panel off and back on</strong> — about 1,063 ms of the 1,500 ms total. The cure was to never let go of the panel: the splash keeps its image on screen until the compositor is ready for the handoff.</p>

<p>The last seam showed up when filming the screen in slow motion: between the splash chakana and the desktop one there were still 381 ms of a lit panel with nothing drawn. The kernel log pointed at the culprit —the compositor first presented a plain frame, left over from an earlier handoff— and now its first frame is already the chakana. With a second monitor plugged in there is a blackout: to light it, the graphics driver has to change the display clock, and that turns the panel off for an instant. Nobody can avoid it, but you can choose what is shown: the loader detects the other screen and fades to the shared background in time, so the blackout falls between two identical backgrounds instead of cutting the menu.</p>

<figure class="foto">
  <svg viewBox="0 0 640 140" width="100%" role="img" aria-label="Bar chart: the visible boot gap dropped from 1,500 to 389 milliseconds.">
    <text x="0" y="20" style="font:500 14px var(--sans);fill:var(--tinta)">visible splash → desktop gap, before</text>
    <rect x="0" y="30" width="610" height="22" rx="4" style="fill:var(--tinta-tenue)"/>
    <text x="604" y="46" text-anchor="end" style="font:500 13px var(--mono);fill:var(--fondo)">≈ 1,500 ms</text>
    <text x="0" y="88" style="font:500 14px var(--sans);fill:var(--tinta)">after the handoff that keeps the panel on</text>
    <rect x="0" y="98" width="158" height="22" rx="4" style="fill:var(--acento)"/>
    <text x="166" y="114" style="font:500 13px var(--mono);fill:var(--tinta)">389 ms</text>
  </svg>
  <figcaption>Measured on a laptop with Intel Iris Xe graphics, profiling the compositor's first frame. The dominant cause (~1,063 ms) was the eDP panel's off-and-on cycle; arje-splash no longer releases it. Since October 23 not even that remainder is visible: the splash chakana stays on screen until the compositor's first frame, which already carries it.</figcaption>
</figure>

<p>And the graph menu installs with a safety net designed for machines nobody is watching: it does not set the firmware's boot order —irreversible on a headless machine— but the one-shot <code>BootNext</code>, which the firmware erases upon use and a guardian re-arms on every healthy boot. A broken loader consumes its one attempt and the machine falls back to the usual boot on its own. <strong>One reset, no rescue.</strong></p>

<h2>The machine is a soul; the hardware, a body</h2>

<p>Up to here, arje is a better init. What follows is another category of thing, and it comes from one sentence in the project's plan: <em>"the machine is a soul; the hardware is a body."</em> The soul is the signed Seed, plus the history of its states, plus a content-addressed store where every binary lives under the hash of its own bytes. Four consequences, all four working:</p>

<div class="caminos">
  <section>
    <h3>Lineage</h3>
    <p>Every change to the system —a new service, a permission that moved— is a signed commit in a fork-proof chain. <code>arjectl log</code> and <code>arjectl diff</code> answer what changed and when; the diff is semantic and names the permissions that moved.</p>
    <p class="medida">Booting is checking out: the machine starts the chosen commit. Zero-byte rollback — the old state is already whole in the store.</p>
  </section>
  <section>
    <h3>Bodies</h3>
    <p>A new piece of hardware rises by requesting over the network the blocks of a soul's latest commit. No server, no cloud: over raw Ethernet, verifying every block against its hash.</p>
    <p class="medida">Certified end to end: node B, holding only the hashes, resurrected node A's soul over the wire and booted it as process 1.</p>
  </section>
  <section>
    <h3>Jail</h3>
    <p>A process's confinement is derived from its signed Card, not configured separately: the paths it declares become a kernel boundary (Landlock), and its permissions, a syscall filter (seccomp).</p>
    <p class="medida">Without a signed grant, maximum jail. The kernel returns "denied" to anything undeclared — verified with the syscall in hand.</p>
  </section>
  <section>
    <h3>Forensics</h3>
    <p>Every boot leaves a signed, chained black box. If the machine died mid-boot, the next boot explains it on its own, in your language.</p>
    <p class="medida"><code>arjectl autopsy</code>: "the previous boot was NOT clean — ente=mirada, step=greeter." And <code>arjectl blame</code> gives the commit that last touched the culprit.</p>
  </section>
</div>

<figure class="foto">
  <svg viewBox="0 0 640 250" width="100%" role="img" aria-label="Lineage diagram: four chained, signed commits; a fork from another session is reconciled by structural merge; the chosen commit is booted with arjectl checkout — booting is checking out.">
    <defs>
      <marker id="fl-t" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" style="fill:var(--tinta-tenue)"/></marker>
      <marker id="fl-a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" style="fill:var(--acento)"/></marker>
    </defs>
    <!-- main chain -->
    <line x1="60" y1="90" x2="180" y2="90" style="stroke:var(--tinta-tenue);stroke-width:2"/>
    <line x1="200" y1="90" x2="320" y2="90" style="stroke:var(--tinta-tenue);stroke-width:2"/>
    <line x1="340" y1="90" x2="460" y2="90" style="stroke:var(--tinta-tenue);stroke-width:2"/>
    <!-- fork from another session, reconciled -->
    <line x1="198" y1="83" x2="293" y2="45" style="stroke:var(--tinta-tenue);stroke-width:2"/>
    <line x1="308" y1="44" x2="456" y2="79" style="stroke:var(--tinta-tenue);stroke-width:2" marker-end="url(#fl-t)"/>
    <circle cx="300" cy="38" r="8" style="fill:var(--superficie);stroke:var(--tinta-tenue);stroke-width:2"/>
    <text x="300" y="18" text-anchor="middle" style="font:500 11px var(--mono);fill:var(--tinta-tenue)">another session</text>
    <text x="400" y="49" text-anchor="middle" style="font:500 11px var(--mono);fill:var(--tinta-tenue)">structural merge</text>
    <!-- commits -->
    <circle cx="50" cy="90" r="10" style="fill:var(--superficie);stroke:var(--tinta-tenue);stroke-width:2"/>
    <circle cx="190" cy="90" r="10" style="fill:var(--superficie);stroke:var(--tinta-tenue);stroke-width:2"/>
    <circle cx="330" cy="90" r="10" style="fill:var(--acento-suave);stroke:var(--acento);stroke-width:2.5"/>
    <circle cx="470" cy="90" r="10" style="fill:var(--superficie);stroke:var(--tinta);stroke-width:2"/>
    <text x="50" y="120" text-anchor="middle" style="font:500 11px var(--mono);fill:var(--tinta-suave)">genesis</text>
    <text x="190" y="120" text-anchor="middle" style="font:500 11px var(--mono);fill:var(--tinta-suave)">⚠ net: none → full</text>
    <text x="330" y="70" text-anchor="middle" style="font:500 11px var(--mono);fill:var(--acento)">chosen</text>
    <text x="470" y="120" text-anchor="middle" style="font:500 11px var(--mono);fill:var(--tinta-suave)">− card minga-host</text>
    <text x="488" y="86" style="font:500 11px var(--mono);fill:var(--tinta-tenue)">tip</text>
    <!-- checkout → boot -->
    <line x1="330" y1="102" x2="330" y2="144" style="stroke:var(--acento);stroke-width:2" marker-end="url(#fl-a)"/>
    <text x="318" y="141" text-anchor="end" style="font:500 11px var(--mono);fill:var(--acento)">arjectl checkout</text>
    <rect x="215" y="150" width="230" height="52" rx="6" style="fill:var(--superficie);stroke:var(--acento);stroke-width:1.5"/>
    <text x="330" y="171" text-anchor="middle" style="font:500 13px var(--mono);fill:var(--acento)">boot = checkout</text>
    <text x="330" y="190" text-anchor="middle" style="font:400 12px var(--sans);fill:var(--tinta)">the machine boots the chosen commit</text>
    <!-- legends -->
    <text x="0" y="234" style="font:500 11px var(--mono);fill:var(--tinta-tenue)">signed commits — Ed25519 over BLAKE3</text>
    <text x="640" y="234" text-anchor="end" style="font:500 11px var(--mono);fill:var(--tinta-tenue)">arjectl log · diff · bisect · blame · autopsy</text>
  </svg>
  <figcaption>The soul's lineage: every state of the system is a signed commit; what diverges in another session is reconciled by structural merge, and booting is checking out. Here, a rollback: the tip deleted a card, and the machine boots the previous commit — zero bytes moved, because that state already lives whole in the store.</figcaption>
</figure>

<p>The full package sounds like version control, and it is: <code>log</code>, <code>diff</code>, <code>checkout</code>, <code>blame</code>, and even <code>bisect</code> — a regression planted in a hundred-commit history is found in seven steps, just like in git, but over your operating system. For those who know NixOS: this is not that. There is no new language and no evaluation — the state <em>is</em> the Seed plus the store, which already existed. What NixOS does not have and this does: the history is <strong>signed and non-repudiable</strong>, the diff is <strong>semantic</strong> (objects, not text), and two diverging states <strong>merge structurally</strong>.</p>

<p>This was not born from a thought experiment. One day in September, a unit placed by hand in a server's Seed <strong>disappeared</strong>: the Seed regenerates from the live system, and regenerating overwrote. Without history, an overwritten state leaves no trace — it was noticed by accident. With lineage, that lost unit would have been one line of diff: <code>− card minga-host</code>. The init that remembers exists because the init that forgets had already cost real money.</p>

<h2>Trust is signed, not assumed</h2>

<p>Before incarnating the critical pieces of the boot, arje <strong>attests</strong> them: each binary's BLAKE3 hash is checked against Ed25519-signed grants, anchored to a root key that lives outside the Seed — so rewriting the Seed is not enough to smuggle in a foreign binary. The same signature covers the three routes by which a Seed can be born (installer, packager, absorption), with a single implementation: the manifest is identical whichever way it comes out. And since the store addresses by content, the same hash that signs the attestation is the name by which a peer can request that binary over the network and <strong>reproduce the exact system</strong>.</p>

<h2>Your programs never notice</h2>

<p>The obvious objection: "all desktop software already assumes systemd." It is true, and arje answers it with an explicit compatibility layer — not pretending to be systemd, but serving its interfaces as an <strong>edge</strong>, with the real logic on the other side:</p>

<div class="tabla" role="region" aria-label="The systemd compatibility layer" tabindex="0">
<table>
  <thead><tr><th scope="col">what the software expects</th><th scope="col">what arje serves it</th></tr></thead>
  <tbody>
    <tr><td><code>org.freedesktop.login1</code> (logind)</td><td>a D-Bus shim with real sessions, seats, inhibitors and video-master handoff — the desktop manages power and display as always</td></tr>
    <tr><td><code>libsystemd</code> / <code>libelogind</code> (the C ABI linked by mutter, polkit, gcr)</td><td>its own <code>libelogind.so</code> of 28 functions and a single dependency, verified against the real libsystemd</td></tr>
    <tr><td><code>org.freedesktop.systemd1</code>, system and user</td><td>every Ente appears as a "unit"; gnome-session starts its services with real PIDs</td></tr>
    <tr><td>journald, <code>journalctl</code></td><td>every message persists to the store by hash; <code>journalctl -o export</code> emits systemd's format, re-importable with the old tools</td></tr>
    <tr><td><code>sd_notify</code>, tmpfiles, binfmt, timers, hostnamed, localed, timedated, resolved, machined, polkit…</td><td>20 edge binaries, one per interface, with the parsing shared and tested in one place</td></tr>
    <tr><td><code>systemctl</code>, <code>loginctl</code>, <code>journalctl</code> in your fingers</td><td>the same <code>arjectl</code> binary under another name; and if systemd is the live init, it forwards to the real one instead of lying</td></tr>
  </tbody>
</table>
</div>

<p>The bar for that layer was the most demanding software there is on the matter: <strong>GNOME 50 starts and paints the complete desktop under arje</strong> — gnome-shell, its session services, ibus and portals, verified in a Fedora VM with the screenshot to prove it. KDE, which does not depend on <code>systemd --user</code>, worked earlier. And to migrate an existing machine there is <code>arje-absorb</code>: it reads the configuration of whatever init is there (sysvinit, runit, dinit, OpenRC) in read-only mode —it destroys nothing— and produces a Seed. On the first absorbed server, 11 of the 20 wrapped services ended up promoted to properly supervised daemons.</p>

<h2>Measured on metal, not on slides</h2>

<p>The project has a rule: what was not measured on a real machine is not claimed. This table is arje's state where it hurts most:</p>

<div class="tabla" role="region" aria-label="Arje measured on real machines" tabindex="0">
<table>
  <thead><tr><th scope="col">where</th><th scope="col">what was measured</th></tr></thead>
  <tbody>
    <tr><td>daily-use laptop</td><td class="propio">boots every day through its own UEFI graph menu; arje-zero as process 1 with the full desktop on top (DRM compositor, panels, audio), whole workdays of uptime; real suspend measured at 5.9 s; shutdown and reboot over the bus with their reason recorded</td></tr>
    <tr><td>production server</td><td class="propio">a 26-Ente Seed sustaining SSH, the web server and the public git; the ordered shutdown brings the whole tree down in cascade, leaves first</td></tr>
    <tr><td>FreeBSD 14.5</td><td class="propio"><code>ps -p 1</code> answers <code>arje-zero</code> — it did not delegate: it IS the init, its mechanisms rewritten over kqueue, jails and devd. The shutdown witness is the hypervisor, which sees the machine "off"; the reboot witness, the kernel's boot clock</td></tr>
    <tr><td>two nodes over raw Ethernet</td><td class="propio">the full resurrection: node B requests A's soul blocks over the wire, verifies them against their hashes, and boots that system as process 1</td></tr>
    <tr><td>hard watchdog</td><td class="propio">a hardware watchdog is petted from process 1's main loop via <code>/dev/watchdog</code>: if the init hangs, the kernel reboots instead of leaving the machine dead</td></tr>
  </tbody>
</table>
</div>

<p>And the honesty of the method includes counting the punches. The most instructive one was not arje's: on a server with a classic init, <code>reboot</code> did <strong>nothing</strong> — no error, no message. The tool wrote eight bytes into a control file no process had open, and exited successfully. <em>The worst way to fail.</em> Arje had its own (a process-1 deadlock a code comment already warned about; 2,466 zombies from a signal mask <code>execve</code> does not restore), and each one ended up turned into a test and a line in these tables. No init is innocent; the difference is whether its deaths leave an autopsy.</p>

<h2>What arje has that systemd doesn't</h2>

<div class="tabla" role="region" aria-label="Arje capabilities with no systemd equivalent" tabindex="0">
<table>
  <thead><tr><th scope="col">capability</th><th scope="col">what it means</th></tr></thead>
  <tbody>
    <tr><td class="propio">boot attestation</td><td>Ed25519 signatures over each critical binary's hash, with an external sovereign anchor that beats a rewritten Seed</td></tr>
    <tr><td class="propio">the system as a commit</td><td><code>log</code> · <code>diff</code> · <code>checkout</code> · <code>bisect</code> · <code>blame</code> over the operating system's state; zero-byte rollback</td></tr>
    <tr><td class="propio">boot black box</td><td>every boot leaves its signed flight record; <code>arjectl autopsy</code> explains the boot that died, in three languages</td></tr>
    <tr><td class="propio">resurrection over the wire</td><td>a new body rises by requesting the soul's blocks over raw Ethernet, no TCP/IP and no server</td></tr>
    <tr><td class="propio">re-floor</td><td>if a capability's provider falls, its dependents are not discarded: they are parked and re-erected on their own, in topological order, when it returns</td></tr>
    <tr><td class="propio">escalation impossible by construction</td><td>bus identity is injected by the kernel; incarnating something new inherits the caller's permissions, never the init's</td></tr>
    <tr><td class="propio">hash-chained audit</td><td>who requested what —spawns, kills, power, quotas— anchored to the content store, queryable</td></tr>
    <tr><td class="propio">rules with a reasoner</td><td>a declarative brain ("if this process exceeds 80 % CPU for 30 s, lower its weight") that crystallizes rules from observed patterns, with its own audit</td></tr>
  </tbody>
</table>
</div>

<h2>What it decides not to do</h2>

<p>The other half of the design is the list of what arje <strong>refuses</strong>, with the reasons written down, because an init that absorbs everything already exists and is the problem. There is no <code>enable</code>/<code>disable</code> (the Seed <em>is</em> the model), no drop-ins and no hot reload of units (immutable after boot: less surface, more reasonability), no user manager or partition manager or container engine inside the init (those belong to other pieces of the suite), no heuristic memory killer (there are limits and rules with explicit policy, not a heuristic deciding for you). Every "no" is documented with its why — and that may be the biggest cultural difference with the software it came to replace.</p>

<aside class="ficha" aria-labelledby="ficha-arje">
  <h2 id="ficha-arje">We measured it</h2>
  <dl>
    <div><dt>Lines of Rust, whole domain</dt><dd>48,171</dd></div>
    <div><dt>Software pieces (crates)</dt><dd>31</dd></div>
    <div><dt>Tests in the domain</dt><dd>504</dd></div>
    <div><dt>systemd compatibility binaries</dt><dd>20</dd></div>
    <div><dt>sd-login C-ABI functions served</dt><dd>28</dd></div>
    <div><dt>Black frames between splash and desktop</dt><dd>none (it used to be 1.5 s)</dd></div>
    <div><dt>Entes in the production server's Seed</dt><dd>26</dd></div>
    <div><dt>Suspend measured on metal</dt><dd>5.9 s</dd></div>
    <div><dt>Regression found by <code>bisect</code> in 100 commits</dt><dd>≤ 7 steps</dd></div>
  </dl>
  <p>Counts taken on the tawasuyu repository on October 22, 2026 and on the server on the 23rd; the metal measurements, on the machines and dates the text names.</p>
</aside>

<h2>Not yet</h2>

<ul>
  <li><strong>A second monitor still flickers.</strong> Booting with an external monitor plugged in turns the panel off for an instant —that is the hardware, and the loader masks it by fading to the background—; and plugging it in with the session open currently costs four flickers where one would do.</li>
  <li><strong>The flicker-free handoff from splash to desktop is certified on Intel graphics.</strong> AMD and the new <code>xe</code> driver are not yet verified; proprietary NVIDIA is explicitly out of the seamless path.</li>
  <li><strong>The compatibility logind models a single session.</strong> Virtual-terminal switching, multi-session, idle and lid are half-served; it is the gap that hurts most on the desktop, and the plan names it as such.</li>
  <li><strong>There is no declarative networking and no udev rules.</strong> arje ships a minimal network bring-up and translates hardware events into capabilities; a complex network topology is solved today with the usual tools.</li>
  <li><strong>Lineage does not version your data.</strong> It versions the system — the Seed, the units, the binaries; promising "time travel for everything" would be lying, and the plan says so in those words.</li>
  <li><strong>Attestation starts in warn mode.</strong> Flipping it to strict is an operator ceremony —generating their root key and anchoring it—, deliberately manual: rolling out attestation must never leave a machine unable to boot.</li>
  <li><strong>On FreeBSD, arje is the init, but parity is not total:</strong> the resource limits that on Linux are cgroups degrade there with a notice, and named pieces remain to be written.</li>
</ul>

<h2>How to see it</h2>

<p>Arje lives in the root region of the tawasuyu repository —<a href="https://git.tawasuyu.net/tawasuyu/tawasuyu">git.tawasuyu.net</a>, on a self-hosted server— under <code>03_ukupacha/arje</code>, and also as its own repository that builds on its own: <a href="https://git.tawasuyu.net/tawasuyu/arje">git.tawasuyu.net/tawasuyu/arje</a>. The migration document, <code>DE-SYSTEMD-A-ARJE.md</code>, maps verb by verb what you know from systemd to what arje does differently; the plans and their measurements sit right beside it, with dates and numbers, published as they came out.</p>
]]></content:encoded>
  </item>
  <item>
    <title>Tawasuyu: a sovereign system end to end, built on the Andean chakana</title>
    <link>https://gioser.net/en/blog/tawasuyu-sovereign-computer/</link>
    <guid isPermaLink="true">https://gioser.net/en/blog/tawasuyu-sovereign-computer/</guid>
    <pubDate>Fri, 16 Oct 2026 09:00:00 -0500</pubDate>
    <dc:creator>Gioser Editorial</dc:creator>
    <category>tawasuyu · Sovereignty</category>
    <description>tawasuyu, the Rust software suite that seeks sovereignty in every layer of the computer —from the operating system to identity— and is laid out like the chakana: four regions, a bridge at the centre and applications that are Andean institutions written as software.</description>
    <enclosure url="https://gioser.net/blog/medios/tawasuyu-escritorio.jpg" type="image/jpeg" length="100132"/>
    <content:encoded><![CDATA[<p class="lede">You turn on your computer and, before you see anything, others have already decided for you: what boots, who draws the screen, which engine opens web pages, where your files live and who can shut down the account that says who you are. <strong>tawasuyu</strong> was born from an uncomfortable question: <em>what would it take for every one of those layers to be yours?</em> The answer takes more than twelve hundred pieces of software. And its blueprint doesn’t come from Silicon Valley: it comes from the Andes.</p>

<figure class="foto">
  <img src="https://gioser.net/blog/medios/tawasuyu-andes.jpg" alt="Two stone crosses on an Andean summit at dawn: on the left takana’s, made of ochre bricks; on the right tawasuyu’s chakana, in rainbow colours with a hole of light at its centre" width="1600" height="900" loading="eager">
  <figcaption>Illustration: the marks of takana and tawasuyu carved in stone before a snow-capped peak.</figcaption>
</figure>

<h2>What tawasuyu is</h2>

<p>tawasuyu is a vertical software suite written in Rust. Among its pieces there is an <strong>operating system</strong> that boots straight on the hardware, with no Linux underneath; its own <strong>graphics engine</strong>, Llimphi; a <strong>desktop</strong> with its window manager; a <strong>web browser</strong> with its own engine, without Chromium or WebKit; a <strong>writing</strong> environment where the same text lives in several languages and tones; an <strong>ERP</strong>, an <strong>astronomy</strong> engine, <strong>mail</strong>, <strong>music</strong>, <strong>video</strong> and a <strong>medical record</strong>.</p>

<p>The odd part isn’t the quantity. It’s that none of it rents its foundations: everything rests on the same format, the same identity and the same engine that draws, and none of them has an owner other than you.</p>

<h2>Sovereignty, layer by layer</h2>

<p>The word has been worn thin by speeches, so it’s worth bringing it down to something that can be checked. On an ordinary computer, every layer has an owner who isn’t the person using it. In tawasuyu, each one has a piece of its own that replaces it:</p>

<div class="tabla" role="region" aria-label="Who rules each layer, and what tawasuyu puts in its place" tabindex="0">
<table>
  <thead><tr><th scope="col">Layer</th><th scope="col">Who usually rules</th><th scope="col">In tawasuyu</th></tr></thead>
  <tbody>
    <tr><td>Booting</td><td>someone else’s kernel and system</td><td><span class="pieza">wawa</span>, an operating system of its own, and <span class="pieza">arje</span>, the first process (init)</td></tr>
    <tr><td>The pixel</td><td>Qt, GTK, Flutter or a hidden browser</td><td><span class="pieza">Llimphi</span>, a graphics engine that draws every button in the suite</td></tr>
    <tr><td>The web</td><td>Chromium or WebKit, almost always</td><td><span class="pieza">puriy</span>, a browser with its own JavaScript engine</td></tr>
    <tr><td>Who you are</td><td>an account a third party gives you and can take away</td><td><span class="pieza">agora</span>: your identity is a key you generate yourself, on your own machine</td></tr>
    <tr><td>Your files</td><td>a central index that can be seized or censored</td><td>every file is named by its content: the name is the proof it wasn’t altered</td></tr>
    <tr><td>The network</td><td>servers in the middle</td><td>peer-to-peer connections; the system of its own also speaks a network protocol of its own</td></tr>
    <tr><td>The history of the code</td><td>a third-party platform</td><td><span class="pieza">minga</span>, a version control system of its own, and the code on the author’s own server</td></tr>
    <tr><td>Foreign formats</td><td>the vendor’s program</td><td>46 declared bridges —PDF, Excel, Word, Photoshop, torrent…— that read and write without getting into the core</td></tr>
  </tbody>
</table>
</div>

<p>And the rule behind the table is a single one: <strong>what comes from outside enters through a bridge, never into the centre</strong>. A PDF opens, a spreadsheet gets imported, a website gets visited; but inside, everything works in the native format, and if tomorrow the maker of that format disappears, what is yours stays readable.</p>

<h2>Survival doesn’t belong to the individual alone</h2>

<p>So far, this could be the dream of someone who wants to lock themselves inside their machine. But individual sovereignty has a well-known limit: one person alone doesn’t sustain a road, a record or a decision. And that is where the project looks to the Andes.</p>

<p>For thousands of years, Andean peoples sustained roads that crossed a continent and terraces that still yield harvests, without money or alphabetic writing. What sustained them wasn’t a technical device but a way of organizing: <em>ayni</em>, exact and measurable reciprocity; <em>minka</em>, voluntary work for the common good; and the <em>ayllu</em>, <strong>the sovereign community as the unit</strong>, instead of the isolated individual.</p>

<p>tawasuyu translates that idea into cryptography. A file named by its content has no central index anyone can seize. An identity that is a key doesn’t need a master registry to authorize it or cancel it. And a community that decides by a <strong>signature threshold</strong> —so many of its members have to agree— doesn’t depend on who owns the server. It’s the same premise, written this time in Rust.</p>

<h2>Four regions, one cycle</h2>

<p>The name is the blueprint. <em>Tawa</em> is four in Quechua and <em>suyu</em> is region: tawasuyu means <strong>four regions</strong>. The whole repository is split in four, and each part corresponds to a phase of what happens to information: it is perceived, known, acted upon and sustained.</p>

<div class="tabla" role="region" aria-label="The four regions of tawasuyu" tabindex="0">
<table>
  <thead><tr><th scope="col">Region</th><th scope="col">Phase</th><th scope="col">What lives there</th></tr></thead>
  <tbody>
    <tr><td><span class="pieza">00_unanchay</span></td><td class="propio">Perceive</td><td>What picks up signals: the browser, notes, language, writing, news comparison.</td></tr>
    <tr><td><span class="pieza">01_yachay</span></td><td class="propio">Know</td><td>What models and computes: astronomy, simulation, physics, the ERP, the medical record, claim verification.</td></tr>
    <tr><td><span class="pieza">02_ruway</span></td><td class="propio">Do</td><td>What acts: the graphics engine, the desktop, the terminal, music, video, mail, games.</td></tr>
    <tr><td><span class="pieza">03_ukupacha</span></td><td class="propio">Root</td><td>What holds everything up: the operating system, booting, identity, the network.</td></tr>
  </tbody>
</table>
</div>

<p><em>Yachay</em> is knowing and <em>ruway</em> is doing. <em>Unanchay</em> is related to the signal and to noticing it. <em>Uku pacha</em> is, in the Andean worldview, the inner world, the one below: the place of roots. It’s no accident that sovereignty starts there: whoever doesn’t own the root owns nothing of what grows on top of it.</p>

<p>And it isn’t an administrative division. Moving a program to another region <strong>changes what it is</strong>. tawasuyu has two programs that work with news: <em>watuy</em> harvests claims and puts them side by side, and lives in <em>perceive</em>; <em>iniy</em> (in Quechua, to believe) verifies them, and lives in <em>know</em>. Collecting a claim isn’t taking it as true, and the code doesn’t let the two be confused.</p>

<h2>The chakana: everything goes through the bridge</h2>
<figure class="foto">
  <img src="https://gioser.net/blog/medios/tawasuyu-escritorio.jpg" alt="The tawasuyu desktop: the colourful chakana with its circular hole at the centre of the screen, crossed by two axes of light; on the left the workspaces and applications, on the right the workshop panel with the list of compiled programs" width="1600" height="900" loading="lazy">
  <figcaption>The tawasuyu desktop as it looks today on the author’s machine: the chakana at the centre, and the suite’s panels on either side.</figcaption>
</figure>

<p>The logo is a chakana, the Andean stepped cross with a circular hole in its centre. It has been carved in stone since Chavín and Tiwanaku, and it still appears in textiles someone weaves today. Its name comes from <em>chaka</em>, <strong>bridge</strong>.</p>

<p>In tawasuyu the chakana isn’t an ornament: it’s the diagram. The four regions are its four arms, and at the centre is the bridge. The rule it draws is strict: <strong>nothing communicates by skipping ahead; everything goes through the middle</strong>. It’s the same rule as foreign formats, seen from above: whatever crosses, crosses at a declared place, where it can be looked at.</p>

<h2>Apps woven together like an ayllu</h2>

<p>tawasuyu’s applications aren’t conceived as standalone programs. The project’s documentation says it in one line: they are <strong>Andean institutions written as software</strong>. And almost all of them do the same thing to a different institution: they remove the middleman.</p>

<div class="tabla" role="region" aria-label="Andean institutions and what they do in tawasuyu" tabindex="0">
<table>
  <thead><tr><th scope="col">Name</th><th scope="col">The tradition</th><th scope="col">In tawasuyu</th></tr></thead>
  <tbody>
    <tr><td><span class="pieza">ayni</span></td><td>reciprocity: what I give you today comes back when it’s my turn</td><td>credit among acquaintances, interest-free, with no bank or server</td></tr>
    <tr><td><span class="pieza">mit'a</span></td><td>work in shifts for the common good</td><td>attested community work turns into reciprocal credit</td></tr>
    <tr><td><span class="pieza">minga</span></td><td>everyone’s voluntary communal work</td><td>peer-to-peer collaboration and its own version control</td></tr>
    <tr><td><span class="pieza">tantanakuy</span></td><td>to gather</td><td>the assembly: call, quorum, vote and signed minutes, with no platform hosting it</td></tr>
    <tr><td><span class="pieza">khipu</span></td><td>the knotted cords that kept memory</td><td>notes that reinforce each other, or fade, kept on your own machine</td></tr>
    <tr><td><span class="pieza">siqi</span></td><td>the lines that joined each place to the centre</td><td>automations: every rule is a piece of data that can be signed</td></tr>
    <tr><td><span class="pieza">tampu</span></td><td>the storehouses along the road</td><td>a community’s shared objects</td></tr>
    <tr><td><span class="pieza">chasqui</span></td><td>the relay messenger</td><td>the one that carries data from one program to another</td></tr>
  </tbody>
</table>
</div>

<p>And they are woven together as in an ayllu: work recorded in <em>tampu</em> becomes credit in <em>ayni</em>, the <em>tantanakuy</em> assembly signs its minutes as a community, and those minutes go into a public record. None of those steps needs to ask a company for permission.</p>

<h2>Agora and the seal of the ayllu</h2>

<p>That idea has its own place in <strong>agora</strong>, the plaza of identity. A community has its <strong>constitution</strong> and its own <strong>seal</strong>, which is only stamped when the members it set itself have signed. The person is sovereign and the community can sign as one, without anyone signing on someone else’s behalf. Agora deserves an article of its own, and it will get one.</p>

<h2>A tribute</h2>

<p>When the conquest banned the assemblies and persecuted the language, the Andean way of organizing was not lost: Quechua is still spoken and the stepped cross is still woven. In its own way, it is the longest proof of sovereignty there is: what a community sustains outlives whoever tried to take it away.</p>

<p>tawasuyu is a <strong>tribute to that architecture</strong>. It isn’t a flag: Quechua is the language of many peoples and crosses borders, and the project speaks on behalf of none of them. It learns from them. It takes the idea that resisted the longest —that what endures isn’t what an owner keeps on their server, but what a community sustains— and writes it in the place where today it’s decided who rules: software.</p>

<aside class="ficha" aria-labelledby="ficha-tawasuyu">
  <h2 id="ficha-tawasuyu">What we measured</h2>
  <dl>
    <div><dt>Software pieces (crates) in the workspace</dt><dd>1,210</dd></div>
    <div><dt>Domain folders: perceive · know · do · root</dt><dd>7 · 11 · 37 · 8</dd></div>
    <div><dt>Shared core folders</dt><dd>104</dd></div>
    <div><dt>Bridges to foreign formats</dt><dd>46</dd></div>
    <div><dt>Application families</dt><dd>4</dd></div>
    <div><dt>Language</dt><dd>Rust</dd></div>
  </dl>
  <p>Count taken on the repository on October 16, 2026. The operating system of its own is built separately and isn’t included in the number of pieces.</p>
</aside>

<h2>What isn’t there yet</h2>

<ul>
  <li><strong>The operating system of its own doesn’t replace Linux in daily use yet.</strong> Today tawasuyu’s desktop runs on a Linux kernel and its drivers; the root of its own exists and boots, but it doesn’t carry everything yet.</li>
  <li><strong>The browser of its own doesn’t open the whole web yet.</strong> Its JavaScript engine passes 13.1% of the language’s official test suite (Test262), and the browser 22.1% of the web platform subtests (WPT) already run against it. It grows every week, and the numbers are published as they come out.</li>
  <li><strong>The hardware isn’t sovereign.</strong> The processor, the graphics card and their firmware still belong to whoever made them. tawasuyu starts where the silicon ends.</li>
  <li><strong>The names take some getting used to.</strong> A newcomer doesn’t know what <em>nakui</em> or <em>kamachiq</em> is without reading its description, and the Quechua on some screens hasn’t been reviewed by a speaker yet. Reviews are welcome.</li>
</ul>

<h2>How to see it</h2>

<p>The code is at <a href="https://git.tawasuyu.net/tawasuyu/tawasuyu">git.tawasuyu.net</a> —on a server of its own, not on someone else’s platform— and the full map, at <a href="https://tawasuyu.net">tawasuyu.net</a>. To check what this article says, just open the root of the repository: the four regions are the first thing you see.</p>
]]></content:encoded>
  </item>
  <item>
    <title>Qt, GTK, Flutter, Electron? No: a graphics engine from scratch, entirely in Rust</title>
    <link>https://gioser.net/en/blog/llimphi-graphics-engine-from-scratch/</link>
    <guid isPermaLink="true">https://gioser.net/en/blog/llimphi-graphics-engine-from-scratch/</guid>
    <pubDate>Mon, 12 Oct 2026 19:00:00 -0500</pubDate>
    <dc:creator>Gioser Editorial</dc:creator>
    <category>tawasuyu · Llimphi</category>
    <description>Llimphi, tawasuyu’s graphics engine written in Rust: why it doesn’t use Qt, GTK or Flutter, how it paints along four different paths and what was measured.</description>
    <enclosure url="https://gioser.net/blog/medios/llimphi-portada.jpg" type="image/jpeg" length="42477"/>
    <content:encoded><![CDATA[<p class="lede">Every time you open an application, something has to draw every button, every letter and every window on your screen, dozens of times per second. That something is a graphics engine, and almost nobody builds their own: most of the world’s software is painted with Qt, GTK, Flutter or Electron. Tawasuyu, the software suite with Quechua names being written in the Gioser workshop, chose not to borrow one.</p>

<p>Its engine is called <strong>Llimphi</strong>, which in Quechua means <em>color</em>, <em>shine</em>, <em>pigment</em>. It draws the whole suite: the desktop, the editor, the video player, the control panels and the interface of the project’s own operating system. Today <strong>276 pieces of the suite</strong> are painted with Llimphi.</p>

<figure class="video">
  <video src="https://gioser.net/blog/medios/llimphi-showreel.mp4" poster="https://gioser.net/blog/medios/llimphi-poster.jpg" width="1600" height="900" autoplay muted loop playsinline preload="metadata" aria-label="A terminal where llimphi is typed turns into a glass text field; on sending it, controls unfold, the page slides into the cosmos sky, into a first-person corridor that ends at a fountain, and through the water into a flight over an infinite voxel world under a snowy peak, where a little figure celebrates while a hand writes llimphi"></video>
  <figcaption>Fifteen and a half seconds of Llimphi. Everything on screen is drawn by the engine, frame by frame: the controls, the cosmos sky, the supay corridor, the infinite voxel world and the hand.</figcaption>
</figure>

<h2>Why not use one that already exists</h2>

<p>Until May 2026, tawasuyu was drawn with GPUI, the engine behind the Zed editor. On May 26 it was removed entirely, and not on a whim: the project has its own operating system, <em>wawa</em>, which boots straight on the hardware, with no Linux underneath. No existing engine knows how to draw there.</p>

<p>Qt, GTK and Flutter take a conventional operating system for granted, with its window manager, its installed fonts and its memory management. Llimphi was designed from day one to paint both in a desktop window and in the video memory of a kernel that has just powered on. That requirement forced it to be written from scratch.</p>

<h2>What “from scratch” means</h2>

<p>It is worth being precise, because it is the question every programmer asks. Llimphi did not reinvent every piece. Just as Flutter relies on Skia and GTK on Cairo, Llimphi uses four free projects from the Rust community for the most specialized jobs. Everything else is its own: the way an application describes its screen, how it reacts to each click, the components and the paths that lead to the pixels.</p>

<div class="tabla" role="region" aria-label="What is its own and what comes from the community" tabindex="0">
<table>
  <thead><tr><th scope="col">Job</th><th scope="col">Who does it</th></tr></thead>
  <tbody>
    <tr><td>Talking to the graphics card</td><td><span class="pieza">wgpu</span> · community</td></tr>
    <tr><td>Drawing curves and fills with antialiasing</td><td><span class="pieza">vello</span> · community</td></tr>
    <tr><td>Working out where each box goes (flexbox and grid)</td><td><span class="pieza">taffy</span> · community</td></tr>
    <tr><td>Shaping text: Arabic, Chinese, emoji, ligatures</td><td><span class="pieza">parley</span> · community</td></tr>
    <tr><td>The life cycle of each application</td><td class="propio">Llimphi</td></tr>
    <tr><td>Components, themes, animation, accessibility</td><td class="propio">Llimphi</td></tr>
    <tr><td>Painting without a graphics card, inside the kernel</td><td class="propio">Llimphi</td></tr>
    <tr><td>Isolating an application and painting its drawing from outside</td><td class="propio">Llimphi</td></tr>
  </tbody>
</table>
</div>

<p>The four community pieces are written in Rust too. That is why the headline says “entirely in Rust”, and stands by it.</p>

<h2>How a Llimphi application thinks</h2>

<p>Llimphi follows the Elm architecture, named after a language known for applications that almost never crash. The idea is simple: the application does not modify the screen, it describes it. Every time something happens, the engine goes through six steps:</p>

<ol class="bucle">
  <li><span>input</span>A click, a key or a gesture arrives.</li>
  <li><span>update</span>The application computes its new state.</li>
  <li><span>view</span>It describes how it should look in that state.</li>
  <li><span>layout</span>The engine works out the position of each box.</li>
  <li><span>raster</span>It turns that description into pixels.</li>
  <li><span>present</span>It shows the finished frame.</li>
</ol>

<p>Since nothing touches the screen directly, no two parts of the program fight over the same button. It is the same reason this style became popular on the web with React, except here it runs natively, with no browser in between.</p>

<h2>One brush, four paths to your screen</h2>

<p>The most unusual part of Llimphi is that the same drawing can reach the screen by completely different paths, depending on where the application runs. “Looks about the same” was not good enough: each path was put side by side with the others and the pixels were counted.</p>

<div class="caminos">
  <section>
    <h3>With a graphics card</h3>
    <p>The everyday path on the desktop.</p>
    <p class="medida">It is the reference everything else is measured against.</p>
  </section>
  <section>
    <h3>CPU only</h3>
    <p>The one the wawa kernel uses, since it has no video driver.</p>
    <p class="medida">Fills and layers identical bit for bit. Accented text may differ, because the kernel only ships three fonts.</p>
  </section>
  <section>
    <h3>By message</h3>
    <p>An isolated application doesn’t touch the screen: it sends its drawing as a message and the system paints it on its behalf.</p>
    <p class="medida">0 pixels of difference across the four test scenes.</p>
  </section>
  <section>
    <h3>For phones</h3>
    <p>A path that works on mobile graphics chips without general-purpose compute, such as the Mali-G57.</p>
    <p class="medida">No pixel differs by more than 1/255 out of 19,200.</p>
  </section>
</div>

<p>The “by message” path coming out with zero difference has a practical consequence: an application can live locked away, with no permission at all to touch the screen, and still look exactly the same. Security that costs nothing in appearance.</p>

<h2>What it already ships</h2>

<ul class="trae">
  <li><strong>Close to eighty components</strong>: buttons, tables, text editors with multiple cursors, node graphs, panel splitters, calendars and more.</li>
  <li><strong>Eleven modules</strong> that combine components into complete application pieces.</li>
  <li><strong>Real text</strong>: right-to-left writing, Chinese characters, emoji, ligatures and input methods for Asian languages.</li>
  <li><strong>Accessibility</strong>: every element can declare what it is and what it is called, and the tests query it the way a screen reader would.</li>
  <li><strong>Image-based tests</strong>: a screen is compared with its approved version, and any unexpected change makes the test fail.</li>
  <li><strong>A 3D voxel engine</strong> that mounts inside the same interface, as just another component.</li>
</ul>

<aside class="ficha" aria-labelledby="ficha-titulo">
  <h2 id="ficha-titulo">We measured it</h2>
  <dl>
    <div><dt>Software pieces (crates)</dt><dd>150</dd></div>
    <div><dt>Lines of Rust, with examples and tests</dt><dd>239,173</dd></div>
    <div><dt>Tawasuyu pieces that draw with Llimphi</dt><dd>276</dd></div>
    <div><dt>Ready-to-use components</dt><dd>79</dd></div>
    <div><dt>Difference between painting directly and by message</dt><dd>0 px</dd></div>
    <div><dt>License</dt><dd>MIT or Apache-2.0</dd></div>
  </dl>
  <p>Counted on the repository on October 12, 2026.</p>
</aside>

<h2>What it doesn’t do yet</h2>

<p>An engine that promises too much loses the trust of whoever tries it, so it is worth saying what is missing too:</p>

<ul>
  <li>The phone path has been tested on real hardware, but <strong>no published application uses it yet</strong>. The current Android builds take another path that doesn’t work on every chip.</li>
  <li>Outside its three built-in fonts, text may look different in the kernel and on the desktop. The cause is known: with no operating system underneath, there is nowhere to get more fonts from.</li>
  <li>Part of Llimphi is already published on <a href="https://crates.io/crates/llimphi">crates.io</a>, Rust’s official registry, but the release is incomplete and some recent pieces haven’t been uploaded yet.</li>
</ul>

<h2>How to try it</h2>

<p>For Rust programmers, the way in is a single package:</p>

<pre><code>cargo add llimphi</code></pre>

<p>The package bundles the core, the themes and the 3D engine. For the rest, the best demonstration is tawasuyu itself: every window in the suite is a Llimphi application.</p>
]]></content:encoded>
  </item>
</channel>
</rss>
