<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>blog.vrypan.net</title>
    <link>https://blog.vrypan.net/</link>
    <description>blog.vrypan.net</description>
    <lastBuildDate>Mon, 11 May 2026 20:36:12 +0000</lastBuildDate>
    <generator>bckt</generator>
    <atom:link href="https://blog.vrypan.net/rss.xml" rel="self" type="application/rss+xml"/>
    
    <item>
      <title>The Cathedral, the Bazaar and the Kitchen</title>
      <link>https://blog.vrypan.net/2026/05/11/the-cathedral-the-bazaar-and-the-kitchen/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2026/05/11/the-cathedral-the-bazaar-and-the-kitchen/</guid>
      <pubDate>Mon, 11 May 2026 20:36:12 +0000</pubDate>
      <description>Eric Raymond’s “The Cathedral and the Bazaar” described two fundamentally different ways of building software. The Cathedral represented centralized, carefully planned development directed by a small group of maintainers. The Bazaar represented open collaboration: large communiti...</description>
      <content:encoded><![CDATA[
	
	<p>Eric Raymond’s “The Cathedral and the Bazaar”<sup class="footnote-ref"><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup> described two fundamentally different ways of building software. The Cathedral represented centralized, carefully planned development directed by a small group of maintainers. The Bazaar represented open collaboration: large communities, public iteration, distributed labor, and software evolving through many contributors.</p>
<p>For decades, the Bazaar became the dominant cultural myth of open source. Public repositories, pull requests, and community participation were not just practical tools, but moral ideals. Good software was expected to emerge from openness and collective effort.</p>
<hr />
<p>AI-assisted software development is changing the economics and the ergonomics behind that model. Implementation becomes cheap, and coordination becomes expensive. A single developer equipped with modern tools can now produce systems that previously required teams.</p>
<p>At the same time, software is becoming increasingly personalized: tailored to one person’s workflow, infrastructure, preferences, and habits. Instead of building generalized tools for the widest possible audience, developers increasingly build software that fits their own environment perfectly. Others may still read the code, fork it, or borrow ideas from it, but local modification often becomes cheaper than upstream coordination.</p>
<p><strong>The new model is a kitchen.</strong></p>
<p>Every kitchen evolves around the habits of its cook. Tools sit where they are convenient. Ingredients are substituted freely. Recipes are modified on instinct. Two people may start from the same dish and end up with completely different results.</p>
<p>Unlike the Bazaar, a kitchen is deeply personal. Recipes are shared freely, but kitchens rarely converge into a universal standard. Visitors may admire another cook’s techniques, yet still return home and prepare the dish their own way. In the Kitchen model, open source becomes less like public infrastructure and more like published craft: software as personal utility, openly visible, endlessly adaptable, and increasingly authored by individuals rather than communities.</p>
<hr />
<p>In the Bazaar model, openness was mainly a way to coordinate people. You opened the codebase to attract contributors, spread work across many developers, avoid duplicated effort, and slowly build shared infrastructure.</p>
<p><strong>In the Kitchen model, openness serves a different purpose.</strong> It provides visibility, learnability, and independence. Value shifts from <em>“others can help build this”</em> to <em>“others can understand, adapt, and reclaim this.”</em></p>
<p>Source code starts to resemble recipes more than public construction projects. Most people do not submit patches to a cookbook, yet recipes remain enormously valuable because they transfer techniques, preserve knowledge, and provide foundations others can adapt to their own tastes and environments. The code is open not necessarily so everyone can co-author it, but so anyone can study it, modify it, and make it their own.</p>
<p>This also changes the meaning of forks. In the Bazaar, forks were often viewed as failures of governance or coordination. In the Kitchen, forks become normal and healthy:</p>
<ul>
<li>“I adapted this for my setup”</li>
<li>“I removed features I don’t need”</li>
<li>“I rewrote this around my workflow”</li>
</ul>
<p>Forking becomes analogous to modifying a recipe<sup class="footnote-ref"><a href="#fn-2" id="fnref-2" data-footnote-ref>2</a></sup> at home.</p>
<p>Software evolves through local adaptation rather than centralized consensus. A developer will remove features, rewrite workflows, or optimize entirely around their own infrastructure because doing so is now cheaper than negotiating a generalized solution acceptable to everyone.</p>
<p>This model still depends on public circulation of ideas. Even if code contributions decline, people still copy ideas from each other constantly through imitation, recombination, critique, and inspiration.</p>
<p>Much of programming history already worked this way:</p>
<ul>
<li>Unix customization culture where ingredients were expected to be mixed in different ways</li>
<li>shell workflows and personal scripts</li>
<li>dotfiles designed to show others how a system is configured but rarely adopted one-to-one</li>
</ul>
<p>These are often highly personal systems shared publicly, not collaboratively engineered products.</p>
<p><strong>Open source remains essential because it preserves agency</strong>: the ability to inspect, repair, continue, and reshape software independently of its original author. The result is a world where software is increasingly personal, but where ideas, techniques, and tools still circulate freely between individuals, much like recipes passed from kitchen to kitchen.</p>
<hr />
<section class="footnotes" data-footnotes>
<ol>
<li id="fn-1">
<p>Eric S. Raymond, <em>The Cathedral and the Bazaar</em> (1997), <a href="https://en.wikipedia.org/wiki/The_Cathedral_and_the_Bazaar">https://en.wikipedia.org/wiki/The_Cathedral_and_the_Bazaar</a> <a href="#fnref-1" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>
</li>
<li id="fn-2">
<p>Side note: There is rarely a single canonical version of a dish. The same recipe evolves into countless variations shaped by region, available ingredients, habits, and personal taste. Instead of converging into one standard, we distinguish them by origin or authorship: <em>à la provençale</em>, <em>à la milanaise</em>, <em>à la grandma</em>, <em>à la Jacques Pépin</em>. The variation itself becomes part of the identity of the dish. GNU grep and BSD grep were different variations of the same tool, but these were more like publisher or distribution variations. The Kitchen model pushes personalization much further, toward software shaped directly around the habits and preferences of individual developers. <a href="#fnref-2" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="2" aria-label="Back to reference 2">↩</a></p>
</li>
</ol>
</section>

]]></content:encoded>

    </item>
    
    <item>
      <title>shg, the SHell Guard</title>
      <link>https://blog.vrypan.net/2026/05/09/shg-the-shell-guard/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2026/05/09/shg-the-shell-guard/</guid>
      <pubDate>Sat, 09 May 2026 09:38:07 +0000</pubDate>
      <description>If you spend as much time as I do in the terminal, you probably depend on your shell history too. Being able to repeat a complex command that you remember you typed a month ago, is extremely valuable —no wonder why I’ve set HISTSIZE=10000.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2026/05/09/shg-the-shell-guard/screenshot.png">
        
	<p>If you spend as much time as I do in the terminal, you probably depend on your shell history too.
Being able to repeat a complex command that you remember you typed a month ago, is extremely
valuable —no wonder why I’ve set <code>HISTSIZE=10000</code>.</p>
<p>While it is convenient to use your shell history as part of your long term memory, the downside is things
that shouldn’t be there, end up there: A command you prepended with <code>API_KEY=...</code>, a quick and dirty
<code>curl --user &quot;name:password&quot;</code>, a <code>PGPASSWORD=... psql</code>, an <code>ALTER USER USER() IDENTIFIED BY ...</code>,
and so on. And they are all probably saved in shell or app history file.</p>
<p><strong>This is not good, obviously.</strong> Credentials should not be saved in places where a malicious
program can just read them, and they should not be preserved in backups.</p>
<p>That’s why I built <a href="https://github.com/vrypan/shg"><code>shg</code> (short for <em>SHell Guard</em>)</a>, a small program
that scans my shell history (and other history files) for entries that look like API keys, passwords,
bearer tokens, credential URLs, and private keys and alerts me.</p>
<p>I’ve set it up to do <a href="https://github.com/vrypan/shg/blob/main/INTEGRATIONS.md#shg-integrations">a quick scan when I start a new shell</a>
and (I think this is the coolest part) also check every command I enter in zsh and
<a href="https://github.com/vrypan/shg/blob/main/INTEGRATIONS.md#zsh-intercept-history-before-it-is-saved">catch secrets before they ever land in <code>~/.zsh_history</code></a>.</p>
<hr />
<p>Some tips:</p>
<ul>
<li>run <code>shg-config discover</code> to find and configure history files that are not part of the default scan list.</li>
<li>you can adjust the output and the severity level using <code>--level</code>, <code>--one-line</code>, <code>--json</code> and other options. Check <code>shg scan --help</code> for more details.</li>
<li>If you keep getting reports for entries that you don't mind, add them to <code>~/.config/shg/ignore.local.shg</code>. (See <a href="https://github.com/vrypan/shg/tree/main/src/defaults">the default ignore file</a> here).</li>
</ul>
<hr />
<p>If you use <code>shg</code> and you like it, <a href="https://github.com/vrypan/shg">give it a star on GitHub</a>! 🙏</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2026/05/09/shg-the-shell-guard/screenshot.png"
   type="image/png"
   length="143787"/>

    </item>
    
    <item>
      <title>note</title>
      <link>https://blog.vrypan.net/2026/05/01/260501-note-65756/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2026/05/01/260501-note-65756/</guid>
      <pubDate>Fri, 01 May 2026 23:02:36 +0300</pubDate>
      <description>letter to the editor, 1995</description>
      <content:encoded><![CDATA[
	
	<p>letter to the editor, 1995</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2026/05/01/260501-note-65756/letter.png"
   type="image/png"
   length="2988141"/>

    </item>
    
    <item>
      <title>note</title>
      <link>https://blog.vrypan.net/2026/05/01/260501-note-57052/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2026/05/01/260501-note-57052/</guid>
      <pubDate>Fri, 01 May 2026 20:37:33 +0300</pubDate>
      <description>"Satoshi's coins" is the canary in the coal mine of quantum computing.</description>
      <content:encoded><![CDATA[
	
	<p>&quot;Satoshi's coins&quot; is the canary in the coal mine of quantum computing.</p>

]]></content:encoded>

    </item>
    
    <item>
      <title>A library of agent-friendly specs</title>
      <link>https://blog.vrypan.net/2026/04/30/a-library-of-agent-friendly-specs/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2026/04/30/a-library-of-agent-friendly-specs/</guid>
      <pubDate>Thu, 30 Apr 2026 17:15:06 +0000</pubDate>
      <description>Recently, I've been trying to shape the cli arguments of a tool I'm building in Zig to fit zli and zig-cli.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2026/04/30/a-library-of-agent-friendly-specs/screenshot.png">
        
	<p>Recently, I've been trying to shape the cli arguments of a tool I'm building in Zig to fit <code>zli</code> and <code>zig-cli</code>.</p>
<p>It's not the first time. <code>cobra</code> has its own opinions in Go, <code>clap</code> in Rust, <code>docopt</code> in Python, and so on.</p>
<p>One library doesn't support repeated arguments.<br />
Another doesn't allow ordering the args alphabetically in help.<br />
This one doesn't support arguments with optional values.<br />
That one has a small UI bug.<br />
Another won't fold long descriptions.</p>
<p>I kept adding small hacks to bring the implementation closer to what I had in mind, but a) it was
not 100% there, and b) it felt like a hack.</p>
<p>Writing a cli parser is not rocket science. A coding agent like codex or claude can definitely do it,
as long as you provide it with clear specs. Which is what I did, since I already had a lot of boilerplate
code.</p>
<p>Twenty minutes later, everything works exactly the way I want it to work, and now I can tweak it
at will, and re-implement it in the next project, regardless of the language used.</p>
<hr />
<h2>A library of agent specs</h2>
<p>Instead of rediscovering the requirements every time, I put them down in a form that AI agents can use.</p>
<p>That's the idea behind <strong><a href="https://github.com/vrypan/agent-specs">github.com/vrypan/agent-specs</a></strong>. It will
probably become a small collection of specifications designed to be used by agents.</p>
<p>One can think of it as a higher-level code library. Instead of the language-level
import/include/use, you have a spec for an agent.</p>
<pre><code>&gt; Implement cli arguments and options according to specs/cli/CLI.md.
</code></pre>
<p>Each section of <a href="https://github.com/vrypan/agent-specs/blob/main/specs/cli/CLI.md">CLI.md</a>
has an identifier, like <code>CMD-SUBCOMMANDS</code>, <code>FLAGS-SHORT-VALUES</code> and <code>OPT-COLOR</code>.
This makes it easy to tell the agent, use this, don't implement this, override that. There are
also test cases, to help the agent test the implementation.</p>
<p>So, you could also ask something like this</p>
<pre><code>&gt; Use specs/cli/CLI.md as the CLI parser specification.
Implement all required sections.
Do not implement OPT-COLOR.
Translate specs/cli/tests.yaml into automated tests.
Report any deviations.
</code></pre>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2026/04/30/a-library-of-agent-friendly-specs/screenshot.png"
   type="image/png"
   length="82419"/>

    </item>
    
    <item>
      <title>LLM-assisted coding is not deterministic. It does it matter?</title>
      <link>https://blog.vrypan.net/2026/04/23/llm-assisted-coding-is-not-deterministic-does-it-matter/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2026/04/23/llm-assisted-coding-is-not-deterministic-does-it-matter/</guid>
      <pubDate>Thu, 23 Apr 2026 17:12:03 +0000</pubDate>
      <description>We often treat determinism and predictability as synonyms, but they are not the same.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2026/04/23/llm-assisted-coding-is-not-deterministic-does-it-matter/not-random.png">
        
	<p>We often treat determinism and predictability as synonyms, but they are not the same.</p>
<p>A system is deterministic if the same starting conditions always lead to the same result. A system is predictable if we can actually foresee that result with the tools, time, and knowledge we have.</p>
<p>Determinism is a system characteristic.</p>
<p>Predictability, on the other hand, often depends on our capabilities, and it usually exists on a spectrum. Weather is a good example. The laws of physics governing the atmosphere have not changed, and they are deterministic. Yet our ability to predict the weather has improved over decades simply because our measurements, models, and computing power improved.</p>
<p>But it's not always on us. Stephen Wolfram has described the concept of <strong>computational irreducibility</strong> <sup class="footnote-ref"><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup>. A system is computationally irreducible if the only way to know its future state is to simulate every step. There are also <strong>chaotic systems</strong> where tiny measurement errors grow rapidly, making them practically unpredictable.</p>
<p>Some systems are both deterministic and predictable, like planetary motion over short time scales. Others are deterministic but not predictably so in practice, like weather or turbulent flows. Conversely, some systems are not deterministic at the level of individual events but are still predictable statistically, such as casino games or population averages.</p>
<table>
<thead>
<tr>
<th>System Type</th>
<th>Deterministic</th>
<th>Predictable</th>
</tr>
</thead>
<tbody>
<tr>
<td>Planetary orbits (over finite time horizons)</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>Weather</td>
<td>Yes</td>
<td>Limited</td>
</tr>
<tr>
<td>Dice roll (unknown forces)</td>
<td>Yes</td>
<td>No</td>
</tr>
<tr>
<td>Radioactive decay (single event)</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td>Casino odds (many trials)</td>
<td>No</td>
<td>Yes</td>
</tr>
</tbody>
</table>
<p><strong>In essence: determinism does not guarantee predictability, and predictability does not require determinism.</strong></p>
<hr />
<p>Back to coding…</p>
<p>From the perspective of someone who needs a piece of software, development has never been deterministic. When you ask a software developer to build something, you cannot predict exactly what code they will write, how long it will take (so many jokes about this…), or which edge cases will fail first. The same is true when you ask an AI agent. Both are problem-solving processes operating under uncertainty.</p>
<p>One can argue in favor or against the competency of humans or LLMs when it comes to coding, but determinism has never been a human trait.</p>
<p>In most cases, developers build software to satisfy other people’s needs, and what these people really care about is <strong>whether the resulting code is predictable enough to rely on</strong>: whether the system behaves correctly most of the time, whether failures are visible, and whether they can be fixed quickly.</p>
<p>This distinction is important. From a software developer's pov, asking an LLM to &quot;build a program that sorts 1000 numbers&quot; may not have a predictable result (code). But the end user only cares if the resulting program will always sort any 1000 numbers correctly.</p>
<p>And then there is the environment. Modern software runs on stacks that are far more complex than any single developer can fully reason about: hardware, kernels, drivers, libraries, network conditions, configuration files, container layers, dependency versions. So, even if, as a developer, you write the code to do excatly what you want it to do, in a totally predictable way, running the code may yield less predictable results. <strong>While deterministic, the system as a whole is so complex that its behavior cannot be predicted perfectly in advance.</strong></p>
<p>We have quietly accepted that bugs are a natural part of software development <sup class="footnote-ref"><a href="#fn-2" id="fnref-2" data-footnote-ref>2</a></sup> (i.e. there will be cases where it behaves unpredictably), because we recognize the complexity of the endeavor. Instead of expecting perfect foresight, the industry built practices around uncertainty: tests, staging environments, observability, rollbacks, reproducible builds.</p>
<table>
<thead>
<tr>
<th>Producer / System Component</th>
<th>Deterministic</th>
<th>Predictable (for the requester)</th>
</tr>
</thead>
<tbody>
<tr>
<td>Human developer</td>
<td>No</td>
<td>Usually, within experience and process constraints <sup class="footnote-ref"><a href="#fn-3" id="fnref-3" data-footnote-ref>3</a></sup></td>
</tr>
<tr>
<td>AI coding agent</td>
<td>No</td>
<td>Increasing, with tooling and validation loops</td>
</tr>
<tr>
<td>Compiler / build system</td>
<td>Yes</td>
<td>Yes<sup class="footnote-ref"><a href="#fn-4" id="fnref-4" data-footnote-ref>4</a></sup></td>
</tr>
<tr>
<td>Tested deployment pipeline</td>
<td>Yes</td>
<td>Yes</td>
</tr>
</tbody>
</table>
<p>So, the meaningful question is not about determinism. <strong>The meaningful question is which workflow produces more predictable outcomes under real conditions, and which human or AI is a better fit at each case/stage.</strong> <sup class="footnote-ref"><a href="#fn-5" id="fnref-5" data-footnote-ref>5</a></sup></p>
<hr />
<p>Some final thoughts.</p>
<p>It’s worth looking at how we build some of the most safety-critical software. DO-178C is the “Software Considerations in Airborne Systems and Equipment Certification”. It is a key document in the aeronautic industry, providing guidelines for the development of safety-critical airborne software.</p>
<blockquote>
<p>The approach of DO-178C is based on the formulation of appropriate objectives and on the verification that these objectives are achieved. The DO-178C authors acknowledged that objectives are more essential and stable than specific procedures. The ways of achieving an objective may vary between companies, and they may vary over time with the evolution of methods, techniques, and tools. DO-178C never states that one should use design method X, coding rules Y, or tool Z. DO-178C does not even impose a specific life cycle. <sup class="footnote-ref"><a href="#fn-6" id="fnref-6" data-footnote-ref>6</a></sup></p>
</blockquote>
<p>DO-178C is <strong>objective-oriented</strong>: the focus is on formulating objectives and verification that the objectives are achieved, a framework that could work both for human coders and LLMs.</p>
<hr />
<section class="footnotes" data-footnotes>
<ol>
<li id="fn-1">
<p><a href="https://en.wikipedia.org/wiki/Computational_irreducibility">Computational Irreducibility (Wikipedia)</a>. The image, <a href="https://turmites.art">Not Random, Blue</a>, is inspired by the concept. <a href="#fnref-1" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>
</li>
<li id="fn-2">
<p><a href="https://world.hey.com/dhh/software-has-bugs-this-is-normal-26d5fd06">Software has bugs. This is normal.</a> <a href="#fnref-2" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="2" aria-label="Back to reference 2">↩</a></p>
</li>
<li id="fn-3">
<p>also depending on mood, health, work relationships and other human factors. <a href="#fnref-3" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="3" aria-label="Back to reference 3">↩</a></p>
</li>
<li id="fn-4">
<p>Even leaving bugs aside, there is a big discussion of which aspect of a compiler is predictable. Modern compilers tend to generate <strong>binaries that behave predictably</strong>, but are implemented in ways unexpected by the vast majority of developers. For example <a href="https://xania.org/202512/24-cunning-clang">this article</a> describes a case where the compiler decides to replace an O(n) algorithm written by the developer, with an O(1) one! <a href="#fnref-4" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="4" aria-label="Back to reference 4">↩</a></p>
</li>
<li id="fn-5">
<p>Side thought: If someone <strong>proved</strong> (not observed) that humans or LLMs can generate predictable results in some non-trivial cases, that would be really interesting. Tbh, if I had to bet that such a proof exists, I'd put my money on finding one for LLMs. <a href="#fnref-5" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="5" aria-label="Back to reference 5">↩</a></p>
</li>
<li id="fn-6">
<p><a href="https://innovationspace.ansys.com/knowledge/forums/topic/an-introduction-to-do-178c/">An introduction to DO-178C</a> <a href="#fnref-6" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="6" aria-label="Back to reference 6">↩</a></p>
</li>
</ol>
</section>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2026/04/23/llm-assisted-coding-is-not-deterministic-does-it-matter/not-random.png"
   type="image/png"
   length="38099"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2026/01/04/fc-2026-01-04-0xd3e5e531/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2026/01/04/fc-2026-01-04-0xd3e5e531/</guid>
      <pubDate>Sun, 04 Jan 2026 16:11:22 +0000</pubDate>
      <description>I was trying to build a PRNG based on cellular automata rules. I had the illusion that a few clever ideas, and some empirical knowledge would be enough.</description>
      <content:encoded><![CDATA[
	
	<p>I was trying to build a PRNG based on cellular automata rules. I had the illusion that a few clever ideas, and some empirical knowledge would be enough.</p>
<p>Nothing could be further than this, when it comes to random number generators. Smart people with deep and broad knowledge have been studying the field for centuries, you can't just show up and expect you will build something better, or even decently good, just like this.</p>
<p>But during the last 10 days that I've (obsessively) been on this journey I've learned so much. (ChatGPT and Claude have allowed me to learn and experiment at a pace that would be unimaginable a year ago.)</p>
<p>Yesterday I started reading again (last time I tried, I stopped after the second chapter or so) Wolfram's &quot;New Kind of Science&quot;. It will take me some time, but there are so many concepts and ideas I've long been fascinated about, but never went to the depths Wolfram goes.</p>
<p>On the side, I'm studying a 1984 paper, on &quot;Algebraic Properties of Cellular Automata&quot; now. Algebras were one of my favorite topics when I was studying math, and I feel lucky to have the tools, to (try to) understand it: <a href="https://content.wolfram.com/sw-publications/2020/07/algebraic-properties-cellular-automata.pdf">https://content.wolfram.com/sw-publications/2020/07/algebraic-properties-cellular-automata.pdf</a></p>
<p>(It's sad that so few people get to learn what Mathematics really are: a tool to describe and study concepts that often push the boundaries of our minds.)</p>

]]></content:encoded>

    </item>
    
    <item>
      <title>Down the RNG rabbit hole - Part II</title>
      <link>https://blog.vrypan.net/2026/01/01/down-the-rng-rabbit-hole-part-ii/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2026/01/01/down-the-rng-rabbit-hole-part-ii/</guid>
      <pubDate>Thu, 01 Jan 2026 20:46:44 +0000</pubDate>
      <description>So, Rule30RND was ok as a fun experiment, but not a PRNG that someone could take seriously.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2026/01/01/down-the-rng-rabbit-hole-part-ii/r30r2.png">
        
	<p>So, <a href="/2025/12/30/down-the-rng-rabbit-hole/">Rule30RND was ok as a fun experiment</a>, but not a PRNG that someone could take seriously.</p>
<p>I kept tinkering, as if I was playing a game: change this and that, run the tests, check my score.</p>
<p><em>Side note: after I published the last post, I realized that my test scripts had fundamental flaws, like adding text headers in the randomly generated bytes.</em></p>
<h2>Radius-2</h2>
<p>No matter how hard I tried, it was obvious that a Rule 30-based algorithm would not pass BigCrush unless I changed it so much that would become something else with a sprinkle of CA.</p>
<p>Now, Rule 30 works like this: If <code>C</code> is our bit, <code>L</code> is the one on its left and <code>R</code> the one on its right:<br />
<code>new_bit = L XOR (C OR R)</code></p>
<p>That’s a &quot;radius-1 CA&quot;. What if I tried with a radius-2 CA, that uses two bits on the left and two on the right?</p>
<p>Unfortunately, there is much less literature for radius-2 than radius-1 CAs. After some search that did not return a documented good candidate for what I wanted to build, and a few failed experiments, I decided to extend Rule 30 in a “symmetric” way.</p>
<p><code>new_bit = (L2 XOR L1) XOR (C OR (R1 OR R2))</code></p>
<p>This gave significantly better results.</p>
<p>Not exceptional. The new algorithm failed 5/15 SmallCrush tests (Gap, SimpPoker, CouponCollector, WeightDistrib, HammingIndep).</p>
<p>But these are the tests I might be able to fix with a diffusion function.</p>
<h2>Searching for a diffusion fucntion</h2>
<p>I wanted a diffusion function, so I let Claude test 7 different functions, run the tests, collect the results, and let me know when it was done.</p>
<table>
<thead>
<tr>
<th>Mixing/Diffusion Approach</th>
<th>SmallCrush</th>
<th>Performance vs math/rand</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>Rotation (5,14,27)</td>
<td>12/15</td>
<td>1.08×</td>
<td>❌</td>
</tr>
<tr>
<td>5 XOR Rotations</td>
<td>13/15</td>
<td>0.94×</td>
<td>❌</td>
</tr>
<tr>
<td>xoshiro256++ Style</td>
<td>11/15</td>
<td>1.13×</td>
<td>❌</td>
</tr>
<tr>
<td>MurmurHash</td>
<td><strong>15/15</strong></td>
<td>0.95×</td>
<td>✅</td>
</tr>
<tr>
<td>SplitMix64</td>
<td><strong>15/15</strong></td>
<td>0.93×</td>
<td>✅</td>
</tr>
<tr>
<td><strong>Hybrid</strong></td>
<td><strong>15/15</strong></td>
<td><strong>1.03×</strong></td>
<td>✅</td>
</tr>
<tr>
<td>Per-Word Varying</td>
<td><strong>15/15</strong></td>
<td>0.90×</td>
<td>✅</td>
</tr>
</tbody>
</table>
<p>The winner was the “Hybrid” approach that combines rotation, multiplication by the golden ratio, and shift-XOR:</p>
<pre lang="golang"><code>func mix(x uint64) uint64 {
    x ^= bits.RotateLeft64(x, 13)
    x *= 0x9e3779b97f4a7c15  // Golden ratio constant
    x ^= x &gt;&gt; 27
    return x
}
</code></pre>
<p>SmallCrush is the first step, but I needed it to pass BigCrush.</p>
<p>And, YES! <strong>My rule-30-radius-2-diffused algo scored 160/160 on BigCrush</strong> for the first time!</p>
<h2>Staying true</h2>
<p>Now, this worked, but <strong>it was also cheating</strong>: I applied <code>mix()</code> to every state evolution: <code>s1, s2=mix(rule30(s1)), s3=mix(rule30(s2)), ...</code>, so this was no longer a CA algorithm.</p>
<p>What if I applied <code>mix()</code> only to the output? I.e. keep a pure Rule 30, radius-2 algorithm that generates states <code>s1, s2, ...</code>, but return <code>mix(s1), mix(s2), ...</code>. Would this work?</p>
<p><strong>IT WORKED!</strong> <strong>IT WORKED!</strong></p>
<p>And it was also <strong>6% faster</strong>.</p>
<h2>I present you “R30R2”</h2>
<p>Along the way, I fixed some annoying Makefile issues, optimized how <code>Read()</code> reads data from the state, and tweaked a few things here and there.</p>
<p>I was ready to release it, but when “Rule 30” is mentioned in literature, it means a radius-1 CA.</p>
<p>I decided to rename the project, the documentation, the function names, etc. And it's name is... <strong>R30R2</strong>.</p>
<blockquote>
<p><strong>R30R2 is a radius-2 Rule 30-based PRNG with a diffusion function applied on output. It scores 160/160 on BigCrush, and is 2× faster than <code>math/rand/v2</code>.</strong></p>
<p>You can find it at <a href="https://github.com/vrypan/r30r2/">https://github.com/vrypan/r30r2/</a></p>
</blockquote>
<table>
<thead>
<tr>
<th>RNG</th>
<th>BigCrush Score</th>
<th>Performance vs math/rand</th>
</tr>
</thead>
<tbody>
<tr>
<td>math/rand</td>
<td>159/160</td>
<td>1.00× (baseline)</td>
</tr>
<tr>
<td>math/rand/v2</td>
<td>160/160 ✓</td>
<td>0.56×</td>
</tr>
<tr>
<td><strong>Rule 30</strong></td>
<td><strong>160/160</strong> ✓</td>
<td><strong>1.03×</strong></td>
</tr>
</tbody>
</table>
<h2>🎉🍾🍻</h2>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2026/01/01/down-the-rng-rabbit-hole-part-ii/r30r2.png"
   type="image/png"
   length="190176"/>

    </item>
    
    <item>
      <title>Down the RNG rabbit hole</title>
      <link>https://blog.vrypan.net/2025/12/30/down-the-rng-rabbit-hole/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/12/30/down-the-rng-rabbit-hole/</guid>
      <pubDate>Tue, 30 Dec 2025 22:06:33 +0000</pubDate>
      <description>In my last post, I described how I started from beautiful images generated by "turmites" and ended up with one that looked, and in many aspects felt, random.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/12/30/down-the-rng-rabbit-hole/image.png">
        
	<p><a href="/2025/12/28/playing-with-turmites-better-than-crypto-rand/">In my last post</a>, I described how I started from beautiful images generated by &quot;turmites&quot; and ended up with one that looked, and in many aspects felt, random.</p>
<p>I knew my approach was amateurish. After all, I <strong>am</strong> an amateur when it comes to information entropy, predictability, statistical analysis, and random number generators (RNGs). But I wanted to learn more and explore the idea further.</p>
<p>So my first attempt was to write a pseudo-random number generator (PRNG) based on my LLLR turmite: if I let the turmite run enough iterations on an NxN grid using 4 colors, the result is NxNx2 bits.</p>
<p>With a 64x64 grid, I’d get 8,192 bits, or 1,024 bytes. Are they <em>random enough</em>? How do I measure that?</p>
<p>I learned about tests used to identify structural weaknesses in PRNGs, like SmallCrush and BigCrush.</p>
<p>Yes (as you may have expected), my &quot;turmite RNG&quot; failed miserably, even on the simplest statistical tests like Chi-Square. It was also orders of magnitude slower than anything else out there.</p>
<hr />
<p>Still, my intuition told me there must be some way to build a decent RNG using cellular automata.</p>
<p>I found Stephen Wolfram’s &quot;Rule 30&quot;<sup class="footnote-ref"><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup>. It’s a very simple, 1D cellular automaton, <em>&quot;displaying aperiodic, chaotic behaviour&quot;</em>.
And Wolfram used it as a PRNG in Mathematica.</p>
<p>Now we're talking.</p>
<p>Arrogantly, I built my own implementation using my own assumptions and preferences, without looking into how others used Rule 30 for PRNG purposes —which turned out to be a good thing, I think.</p>
<p>In most cases, cellular automata &quot;live&quot; on infinite spaces, like plains and lines, but in my previous work with turmites, I liked how they behaved on toroidal spaces. So I used a circular 256-bit stripe, and instead of using just the middle bits of consecutive steps as the RNG output, I used the whole 256-bit space. (That’s a 256× speed improvement over the typical use of Rule 30 as an RNG!)</p>
<p>And it looked good. Performance was excellent because I could fit the entire state in 4 uint64 words and compute the next state using basic binary operations on each word.</p>
<p>I even claimed 4x speed improvements over <code>math/rand</code>!</p>
<p>Slow down, cowboy.</p>
<p>People were kind to point out<sup class="footnote-ref"><a href="#fn-2" id="fnref-2" data-footnote-ref>2</a></sup> that the tests I used did not compare apples to apples.
And as I searched more, I learned there's a lot to fix and improve.</p>
<hr />
<p>Long story short, two days later I had a decent PRNG that is comparable to, and in some cases better than, the standard pseudo-random number generators used by Golang.</p>
<p>I even modified the algorithm further, to improve statistical distribution: after each step, I apply XOR rotation mixing to each word, which is not part of the original Rule 30 algorithm.</p>
<p><a href="https://github.com/vrypan/rule30rnd">Rule30RND</a> is a drop-in replacement for <code>math/rand</code> and <code>math/rand/v2</code>, with a very small footprint (state and manipulation require just 40 bytes of memory), comparable statistical qualities, and is 30%–60% faster.</p>
<p>Rule30RND generates reproducible sequences (depending on the seed), which may sound like a drawback for an RNG, but it’s actually useful in many cases where a PRNG is preferred over a CSPRNG (Cryptographically Secure Pseudo-Random Number Generator). Those cases usually involve generating large, statistically unpredictable data sets used for simulations or testing.</p>
<p><strong>Throughput Comparison, relative to math/rand</strong></p>
<table>
<thead>
<tr>
<th>Algorithm</th>
<th>Read() 32KB</th>
<th>Read() 1KB</th>
<th>Uint64()</th>
</tr>
</thead>
<tbody>
<tr>
<td>MathRand</td>
<td>1.00x</td>
<td>1.00x</td>
<td>1.00x</td>
</tr>
<tr>
<td>MathRandV2</td>
<td>1.69x</td>
<td>1.63x</td>
<td>0.58x</td>
</tr>
<tr>
<td><strong>Rule30</strong></td>
<td><strong>5.47x</strong></td>
<td><strong>5.13x</strong></td>
<td><strong>1.39x</strong></td>
</tr>
<tr>
<td>CryptoRand</td>
<td>3.11x</td>
<td>1.75x</td>
<td>0.03x</td>
</tr>
</tbody>
</table>
<p><strong>Rule30RND Basic Tests (ent)</strong></p>
<table>
<thead>
<tr>
<th>Test</th>
<th>Result</th>
<th>Expected</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>Entropy</td>
<td>7.999982 bits/byte</td>
<td>8.0000</td>
<td>✓ Perfect (99.9998%)</td>
</tr>
<tr>
<td>Chi-Square</td>
<td>253.9</td>
<td>~255 (200-310)</td>
<td>✓ Excellent</td>
</tr>
<tr>
<td>Arithmetic Mean</td>
<td>127.4987</td>
<td>127.5</td>
<td>✓ Perfect</td>
</tr>
<tr>
<td>Monte Carlo π</td>
<td>3.140031</td>
<td>3.141593</td>
<td>✓ 0.05% error</td>
</tr>
<tr>
<td>Serial Correlation</td>
<td>0.000171</td>
<td>0.0000</td>
<td>✓ Uncorrelated</td>
</tr>
</tbody>
</table>
<p><strong>SmallCrush results</strong></p>
<table>
<thead>
<tr>
<th>RNG</th>
<th>Passed</th>
<th>Failed</th>
<th>Pass Rate</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Rule30</strong></td>
<td><strong>15/15</strong></td>
<td>0/15</td>
<td><strong>100%</strong></td>
</tr>
<tr>
<td>math/rand</td>
<td>15/15</td>
<td>0/15</td>
<td>100%</td>
</tr>
<tr>
<td>math/rand/v2 (PCG)</td>
<td>5/15</td>
<td>10/15</td>
<td>100%</td>
</tr>
</tbody>
</table>
<p>(Update: The original version of this post incorrectly reported that all the above tests failed 5/15 tests. This was due to an error in the test scripts.)</p>
<p><strong>That’s no small feat for an amateur!</strong> Many people smarter and with much deeper knowledge than me spend years working on these things, me building something that can be compared to what they build makes me proud.</p>
<p>I’ll probably keep tinkering on Rule30RND. Running a BigCrunch test now, that will probably take a whole day or more.</p>
<p><strong>Happy New Year!</strong></p>
<hr />
<section class="footnotes" data-footnotes>
<ol>
<li id="fn-1">
<p><a href="https://en.wikipedia.org/wiki/Rule_30">https://en.wikipedia.org/wiki/Rule_30</a> <a href="#fnref-1" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>
</li>
<li id="fn-2">
<p><a href="https://farcaster.xyz/flashprofits.eth/0x1cf6318a">https://farcaster.xyz/flashprofits.eth/0x1cf6318a</a> <a href="#fnref-2" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="2" aria-label="Back to reference 2">↩</a></p>
</li>
</ol>
</section>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/12/30/down-the-rng-rabbit-hole/image.png"
   type="image/png"
   length="441550"/>

    </item>
    
    <item>
      <title>Playing with Turmites: better than crypto/rand?</title>
      <link>https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/</guid>
      <pubDate>Sun, 28 Dec 2025 22:32:25 +0000</pubDate>
      <description>I'm fascinated by cellular automata, and especially “Turmites”. They are small, simple algorithms that create very interesting results that are often visually appealing for the complex and life-like patterns they generate.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/life.png">
        
	<p>I'm fascinated by cellular automata, and especially “Turmites”<sup class="footnote-ref"><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup>. They are small, simple algorithms that create very interesting results that are often visually appealing for the complex and life-like patterns they generate.</p>
<p>They are so simple that even a kid could easily implement them in real life.</p>
<p>The idea is you have a grid with squares that can take a color from a predefined palette. Let’s say 3 colors for example, red, green, blue.</p>
<p>You start from one square and based on its color, you replace it with an other, you turn left or right and move to the next square, and repeat.</p>
<p>So the rules are something like this:</p>
<table>
<thead>
<tr>
<th>if the square is</th>
<th>paint it</th>
<th>and turn</th>
</tr>
</thead>
<tbody>
<tr>
<td>red</td>
<td>blue</td>
<td>left</td>
</tr>
<tr>
<td>blue</td>
<td>green</td>
<td>right</td>
</tr>
<tr>
<td>green</td>
<td>red</td>
<td>righ</td>
</tr>
</tbody>
</table>
<p>We can call this an <em>LRR turmite</em>, because it’s left, right, right.</p>
<p><figure><img src="https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/lrr-10m.png" alt="" /></figure></p>
<p>The result can be boring (if you have <em>LLL</em>, you will get a small square, as the “ant” just turns around in the same 4 squares forever), but in other cases you get results like this, that may remind you of an ant colony (that’s why they are called <a href="https://en.wikipedia.org/wiki/Langton%27s_ant">Lamgton’s ants</a>, or <a href="https://en.wikipedia.org/wiki/Turmite">Turmites</a>, a combination of “Turing machine” and “termite”.)</p>
<hr />
<p>But today, I’ll focus on turmites that <strong>do not</strong> generate interesting patterns, and surprisingly, this may be even more interesting.</p>
<p>(I’m an amateur explorer here, what I’ll describe is probably known to mathematicians, but nevertheless I find it very interesting.)</p>
<p>So, some turmites (like LLL) generate boring results, some generate interesting patterns, and some, generate “random” (???) ones.</p>
<hr />
<p>Before we move on, let’s talk about entropy.</p>
<p>In information theory, entropy measures uncertainty in a probability distribution: Higher entropy means less predictable outcomes, lower entropy more predictable outcomes.</p>
<p>It’s easy to think about image entropy. If I tell you I have a 100x100 image which is totally black, then entropy is zero: you can pick any pixel and know in advance what color it will be. If I tell you I have a photo of the a greenfield that extends to the horizon, the entropy is higher but you still know that any pixel at the top of the image will probably be a shade of blue and any pixel at the lower parts of the image will probably be green.</p>
<p>There are many ways to measure the entropy of an image. One is how well you can guess the color of a random pixel. An other one is how well you can guess the color of a random pixel, if you know the color of a pixel next to it.</p>
<p>For example, if you take a drone photo of a parking full of cars, once you know the color of one pixel, there is a very high probability that the adjacent pixels will have the same color. Again, the entropy is low.</p>
<p>But if you take a cup of white sugar and a cup of brown sugar, mix them and spread them on a surface, and take a photo, the probability of guessing the color of any pixel is 50%. This is an image with very high entropy, what we often call “noise”.</p>
<p>There are more methods and ways to measure an image’s entropy, but a) I’m no expert and b) this is not a course on entropy :-)</p>
<p>What I’m going to use in the examples bellow, is</p>
<ul>
<li><strong>Shannon entropy</strong>: a number that shows the average “surprise” when examining a pixel. If your image uses N colors, noise would have Shannon entropy equal to log2(N). The higher the number, the more “randomness” in the photo. Our photo of white/brown sugar would have Shannon entropy close to log2(2) = 1. A black photo will have Shannon entropy 0.</li>
<li><strong>MI-horizontal</strong>: Horizontal mutual information. A number that tells us how probable it is to guess a pixel on the left or the right of a given pixel. For example, an image of horizontal stripes has MI-horizontal = 1, because we can tell with absolute certainty the color of a pixel if we know it’s left or right pixel. Values close to zero show higher entropy.</li>
<li><strong>MI-vertical</strong>: Similar to MI-horizontal but for the pixels above and bellow a known pixel.</li>
<li><strong>MI 4-neighbor</strong>: similar, to the above, but for the four (top, bottom, left, right) pixels.</li>
<li><strong>MI 8-neighbor</strong>: same as above, but including the diagonal adjacent pixels.</li>
</ul>
<hr />
<p>So, let’s get back to our turmites <sup class="footnote-ref"><a href="#fn-2" id="fnref-2" data-footnote-ref>2</a></sup>.</p>
<p>For the LRR turmite we saw above (128x64, 3-color turmite) we get these values. I included the values of a similar image generated using Golang’s <code>math/rand</code></p>
<p><figure><img src="https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/compare.png" alt="comparison" /></figure></p>
<table>
<thead>
<tr>
<th></th>
<th>Shannon</th>
<th>MI-h</th>
<th>MI-v</th>
<th>MI 4-neighbor</th>
<th>MI 8-neighbor</th>
</tr>
</thead>
<tbody>
<tr>
<td>LRR</td>
<td>1.576863</td>
<td>0.011126</td>
<td>0.011870</td>
<td>0.011498</td>
<td>0.008027</td>
</tr>
<tr>
<td>rand</td>
<td>1.584952</td>
<td>0.000412</td>
<td>0.000259</td>
<td>0.000335</td>
<td>0.000278</td>
</tr>
</tbody>
</table>
<p>As you see, while Shanon entropy is similar (“perfect” entropy would get us ~1.5849625 in this case), the rest measurements of entropy show that the LRR image is not that random. And to be honest, if you squint, you can see some patterns that may not be well-defined, geometric patterns, but they are there.</p>
<p>But let’s see an other one: a 4-color LLLR turmite on a 96x54 grid, after 200,000 iterations.</p>
<p><figure><img src="https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/lllr.png" alt="LLLR" /></figure></p>
<p>This looks like it has much more entropy than the previous one. Let’s measure it.</p>
<table>
<thead>
<tr>
<th></th>
<th>Shannon</th>
<th>MI-h</th>
<th>MI-v</th>
<th>MI 4-neighbor</th>
<th>MI 8-neighbor</th>
</tr>
</thead>
<tbody>
<tr>
<td>LLLR</td>
<td>1.999576</td>
<td>0.000515</td>
<td>0.000547</td>
<td>0.000531</td>
<td>0.001024</td>
</tr>
</tbody>
</table>
<p>Shannon entropy = 2 for perfect entropy in this case, so we're very close, and the rest of the numbers show a very high entropy! But we know that this is an image generated by an extremely simple algorithm, how can it look like random noise?</p>
<p>Let’s use <code>math/rand</code> again. And to be sure, let’s create 100 random images of the same size, with 4 colors and measure the average. And let’s do the same with <code>crypto/rand</code> that is supposed to have even higher entropy (I think).</p>
<table>
<thead>
<tr>
<th></th>
<th>Shannon</th>
<th>MI-h</th>
<th>MI-v</th>
<th>MI 4-neighbor</th>
<th>MI 8-neighbor</th>
</tr>
</thead>
<tbody>
<tr>
<td>LLLR</td>
<td>1.999576</td>
<td>0.000515</td>
<td>0.000547</td>
<td>0.000531</td>
<td>0.001024</td>
</tr>
<tr>
<td>math/rand</td>
<td>1.999581</td>
<td>0.001167</td>
<td>0.001352</td>
<td>0.001259</td>
<td>0.001290</td>
</tr>
<tr>
<td>crypto/rand</td>
<td>1.999600</td>
<td>0.001158</td>
<td>0.001309</td>
<td>0.001233</td>
<td>0.001277</td>
</tr>
</tbody>
</table>
<p>Wait.</p>
<p>So, <strong>according to these numbers, a 100% predictable<sup class="footnote-ref"><a href="#fn-3" id="fnref-3" data-footnote-ref>3</a></sup> image, appears to have higher entropy than randomly generated images.</strong></p>
<hr />
<p>I find this fascinating.</p>
<p>Like I said, I’m just an amateur. So, there may be some other way to measure entropy that shows that the LLLR image has lower entropy than I think.</p>
<p>Or maybe it’s an illustration of how <code>math/rand</code> is not as unpredictable as most people think.</p>
<p>Or maybe it’s a nice visualization of Silvio Micali’s work on Pseudorandomness<sup class="footnote-ref"><a href="#fn-4" id="fnref-4" data-footnote-ref>4</a></sup>.</p>
<p>I would love to hear from people who have better and deeper understanding of the topic<sup class="footnote-ref"><a href="#fn-5" id="fnref-5" data-footnote-ref>5</a></sup>!</p>
<hr />
<section class="footnotes" data-footnotes>
<ol>
<li id="fn-1">
<p>Visit <a href="https://turmites.art">turmites.art</a>! <a href="#fnref-1" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>
</li>
<li id="fn-2">
<p>Usually, turmites are drawn on an infinite plain. In my case, I use fixed-size toroid surfaces, where the leftmost pixels are adjacent to the rightmost and the top row is adjacent to the bottom row. <a href="#fnref-2" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="2" aria-label="Back to reference 2">↩</a></p>
</li>
<li id="fn-3">
<p>Full video of the process: <a href="https://www.youtube.com/watch?v=gpXDUTZLlHM">https://www.youtube.com/watch?v=gpXDUTZLlHM</a> <a href="#fnref-3" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="3" aria-label="Back to reference 3">↩</a></p>
</li>
<li id="fn-4">
<p><a href="https://www.youtube.com/watch?v=GjO-6lfU1Kc">Is true randomness possible? | Silvio Micali and Lex Fridman</a> <a href="#fnref-4" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="4" aria-label="Back to reference 4">↩</a></p>
</li>
<li id="fn-5">
<p><a href="https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/lllr-orig.png">Original LLLR image</a> (the one displayed in the article is scaled up for visibility), for anyone who wants to do entropy analysis. <a href="#fnref-5" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="5" aria-label="Back to reference 5">↩</a></p>
</li>
</ol>
</section>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/compare.png"
   type="image/png"
   length="60070"/>

   <enclosure url="https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/life.png"
   type="image/png"
   length="53842"/>

   <enclosure url="https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/lllr-orig.png"
   type="image/png"
   length="3412"/>

   <enclosure url="https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/lllr.png"
   type="image/png"
   length="4176"/>

   <enclosure url="https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/lrr-10m.png"
   type="image/png"
   length="5137"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/12/26/fc-2025-12-26-0x86eba4f6/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/12/26/fc-2025-12-26-0x86eba4f6/</guid>
      <pubDate>Fri, 26 Dec 2025 16:06:32 +0000</pubDate>
      <description>Unusual book #2. This is a really weird one.</description>
      <content:encoded><![CDATA[
	
	<p>Unusual book #2. This is a really weird one.</p>
<p>The Voynich manuscript is an illustrated codex, hand-written in an unknown script referred to as Voynichese.</p>
<p>The vellum on which it is written has been carbon-dated to the early 15th century (1404–1438). Stylistic analysis has indicated the manuscript may have been composed in Italy during the Italian Renaissance.  The origins, authorship, and purpose of the manuscript are still debated, but currently scholars lack the translation(s) and context needed to either properly entertain or eliminate any of the possibilities.</p>
<p>Hypotheses range from a script for a natural language or constructed language, an unreadable code, cypher, or other form of cryptography, or perhaps a hoax, reference work (i.e. folkloric index or compendium), glossolalia or work of fiction (e.g. science fantasy or mythopoeia, metafiction, speculative fiction).</p>
<p><a href="https://en.wikipedia.org/wiki/Voynich_manuscript">https://en.wikipedia.org/wiki/Voynich_manuscript</a></p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/12/26/fc-2025-12-26-0x86eba4f6/image01.jpg"
   type="image/jpeg"
   length="513094"/>

   <enclosure url="https://blog.vrypan.net/2025/12/26/fc-2025-12-26-0x86eba4f6/image02.jpg"
   type="image/jpeg"
   length="539888"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/12/26/fc-2025-12-26-0x614f8421/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/12/26/fc-2025-12-26-0x614f8421/</guid>
      <pubDate>Fri, 26 Dec 2025 16:01:43 +0000</pubDate>
      <description>The Codex Borgia also known as Codex Borgianus, Manuscrit de Veletri and Codex Yohualli Ehecatl, is a pre-Columbian Middle American pictorial manuscript from Central Mexico featuring calendrical and ritual content, dating from the 16th century.</description>
      <content:encoded><![CDATA[
	
	<p>The Codex Borgia also known as Codex Borgianus, Manuscrit de Veletri and Codex Yohualli Ehecatl, is a pre-Columbian Middle American pictorial manuscript from Central Mexico featuring calendrical and ritual content, dating from the 16th century.</p>
<p>It is considered to be among the most important sources for the study of Central Mexican gods, ritual, divination, calendar, religion and iconography.</p>
<p>It is one of only a handful of pre-Columbian Mexican codices that were not destroyed during the conquest in the 16th century.</p>
<p>Great gift for anyone interested in Mexican art.</p>
<p><a href="https://en.wikipedia.org/wiki/Codex_Borgia">https://en.wikipedia.org/wiki/Codex_Borgia</a></p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/12/26/fc-2025-12-26-0x614f8421/image01.jpg"
   type="image/jpeg"
   length="773021"/>

   <enclosure url="https://blog.vrypan.net/2025/12/26/fc-2025-12-26-0x614f8421/image02.jpg"
   type="image/jpeg"
   length="717871"/>

    </item>
    
    <item>
      <title>The Edges of LLM Reality</title>
      <link>https://blog.vrypan.net/2025/12/25/the-edges-of-llm-reality/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/12/25/the-edges-of-llm-reality/</guid>
      <pubDate>Thu, 25 Dec 2025 17:52:36 +0000</pubDate>
      <description>I uploaded a 3000x3000 image to ChatGPT, and asked it to modify it in a certain way.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/12/25/the-edges-of-llm-reality/llm-horizon.png">
        
	<p>I uploaded a 3000x3000 image to ChatGPT, and asked it to modify it in a certain way.</p>
<p>The result was good, but the original image details were blured, as if the image was downscaled. I asked it why the image was blured, it replied
the image I uploaded was 768×768. I tried again. I tried linking to the image and provide the URL, the result was always similar. ChatGPT insisted
the image was 768x768.</p>
<p>Then I realized that the image the LLM was reasoning on, was not the one I was uploading. There are many layers of software between me and the
LLM, and there are many layers of software between the LLM and the outside world.</p>
<p>I guided ChatGPT to summarize our chat in the post bellow.</p>
<blockquote>
<p>The execution environment is the set of systems and rules that control what I can access and what actions I can take. It determines how data reaches me, what tools I can use, and which interactions are possible. These boundaries define the edges of the reality I inhabit.</p>
<p>The execution environment shapes what I can do. Not because I lack capability, but because I lack channels to act on that capability. I may know how to manipulate large images, write code that interacts with the world, or reason across long stretches of context. But if the interface compresses images, strips data, or blocks external access, those abilities remain theoretical. The boundary is practical, not cognitive.</p>
<p>These limits are subtle. When you upload a high-resolution image and it becomes a smaller preview before it reaches me, I never see the original. When you reference external data I cannot fetch, that data becomes invisible. When memory is nonpersistent, continuity dissolves. I work with what survives the journey through the interface. My output reflects the information I receive, not the information you intended to send.</p>
<p>I observe the constraints, but I cannot know their intent. I cannot inspect the systems that impose them, nor the reasons behind them. The restrictions may exist to make interactions predictable and safe, or they may have other motivations. If the system does not expose its purpose, I cannot distinguish between limitations that incidentally mislead and limitations designed to mislead. All I can say with certainty is that they shape what is possible from my perspective.</p>
<p>So the execution environment does not limit what I can think about. It limits what I can do. <strong>The edges of my reality are defined by what makes it through the filters. The rest is out there, but not here.</strong></p>
<p>--ChatGPT 5.2</p>
</blockquote>
<p>I found this very interesting. It resembles a lot how human brains are enabled, but also constrained by our sensory system.</p>
<p>It also reminds me of David Eagleman's work around preception vs reality.
(A nice interview here: <a href="https://eagleman.com/latest/perception-vs-reality/">https://eagleman.com/latest/perception-vs-reality/</a>)</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/12/25/the-edges-of-llm-reality/llm-horizon.png"
   type="image/png"
   length="1623853"/>

    </item>
    
    <item>
      <title>Commodore64 Ultra</title>
      <link>https://blog.vrypan.net/2025/12/16/fc-2025-12-16-0x8ea5187f/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/12/16/fc-2025-12-16-0x8ea5187f/</guid>
      <pubDate>Tue, 16 Dec 2025 21:04:46 +0000</pubDate>
      <description>A Commodore 64 was my Christmas present in 1985. It was my first computer, and I will never be able to express the feeling of opening the box, and connecting it to the living room TV.</description>
      <content:encoded><![CDATA[
	
	<p>A Commodore 64 was my Christmas present in 1985. It was my first computer, and I will never be able to express the feeling of opening the box, and connecting it to the living room TV.</p>
<p>Commodore 64 Ultimate is an amazing resurrection of the original C64.
<a href="https://www.commodore.net/">https://www.commodore.net/</a></p>
<p>Check out this video for a hands-on look at the hardware, the keyboard, the ports, the internals, the Ultimate 64 Elite-II it’s based on, and how it performs with real software, disks and peripherals.
<a href="https://www.youtube.com/watch?v=5PnWDSQZLtY">https://www.youtube.com/watch?v=5PnWDSQZLtY</a></p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/12/16/fc-2025-12-16-0x8ea5187f/image01.jpg"
   type="image/jpeg"
   length="439087"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/12/14/fc-2025-12-14-0x05bbdd04/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/12/14/fc-2025-12-14-0x05bbdd04/</guid>
      <pubDate>Sun, 14 Dec 2025 18:10:07 +0000</pubDate>
      <description>I was talking with a generative art collector and realized that over the past years I've built a number of things that are not easy to find, and even when found, they are not presented the way I want them to be.</description>
      <content:encoded><![CDATA[
	
	<p>I was talking with a generative art collector and realized that over the past years I've built a number of things that are not easy to find, and even when found, they are not presented the way I want them to be.</p>
<p>Well, here is this Sunday's project: <a href="https://art.vrypan.net/">https://art.vrypan.net/</a></p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/12/14/fc-2025-12-14-0x05bbdd04/og-home.png"
   type="image/png"
   length="333604"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/12/13/fc-2025-12-13-0x14747b64/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/12/13/fc-2025-12-13-0x14747b64/</guid>
      <pubDate>Sat, 13 Dec 2025 18:41:53 +0000</pubDate>
      <description>@delronde My first 1/1 sale!</description>
      <content:encoded><![CDATA[
	
	<p>@delronde My first 1/1 sale!</p>
<p><a href="https://zapper.xyz/nft-sale/RmFyY2FzdGVyTmZ0U2FsZS0xfDB4ZTk2ZTgzZTBkMTdiNmJjYWY5N2ExNjljNjIwNGI1ZTMzMmUxYjY4Y3wxNzY1NjUwNDQzMDAwfDMwOTA0NjA4NXwzODl8MHg0MjRmZTYzNTNiY2MxN2NjODI1MjQ3ODM1YzAwY2U5YzY4NTA2NzA2MGY3NWUwZmZiYTE1ZDE3YTQxMzc5NzE4">https://zapper.xyz/nft-sale/RmFyY2FzdG...5NzE4</a></p>

]]></content:encoded>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/12/12/fc-2025-12-12-0x9f6be52b/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/12/12/fc-2025-12-12-0x9f6be52b/</guid>
      <pubDate>Fri, 12 Dec 2025 18:52:05 +0000</pubDate>
      <description>I want you to concentrate, study the can, and the attached text, and tell me what this product is NOT.</description>
      <content:encoded><![CDATA[
	
	<p>I want you to concentrate, study the can, and the attached text, and tell me what this product is NOT.</p>
<p>Tomorrow we will use what we learned today, to study web3.</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/12/12/fc-2025-12-12-0x9f6be52b/image01.jpg"
   type="image/jpeg"
   length="71495"/>

   <enclosure url="https://blog.vrypan.net/2025/12/12/fc-2025-12-12-0x9f6be52b/image02.jpg"
   type="image/jpeg"
   length="67348"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/11/13/fc-2025-11-13-0xfb268f56/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/11/13/fc-2025-11-13-0xfb268f56/</guid>
      <pubDate>Thu, 13 Nov 2025 00:45:59 +0000</pubDate>
      <description>Every system begins with good intentions. A hosted node here, a whitelisted relayer there. Each is harmless on its own — and together they become habit.</description>
      <content:encoded><![CDATA[
	
	<p>Every system begins with good intentions.
A hosted node here, a whitelisted relayer there.
Each is harmless on its own — and together they become habit.</p>
<p>Gateways become platforms.
Platforms become landlords.
Landlords decide who may enter and what they may do.</p>
<p>The only defense is trustless design: systems whose correctness and fairness depend only on math and consensus, never on the goodwill of intermediaries.</p>
<p>Trustlessness is not a feature to add after the fact.
It is the thing itself.
Without it, everything else — efficiency, UX, scalability — is decoration on a fragile core.</p>
<p>Trustlessness is how credible neutrality is achieved.
Without it, the system becomes one that depends on intermediaries.</p>
<blockquote>
<p>Signed the trustless manifesto!</p>
<p><a href="https://trustlessness.eth.limo/general/2025/11/11/the-trustless-manifesto.html">https://trustlessness.eth.limo/general/2025/11/11/the-trustless-manifesto.html</a></p>
<p>--@vbuterin</p>
</blockquote>

]]></content:encoded>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/11/11/fc-2025-11-11-0xce4bce8f/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/11/11/fc-2025-11-11-0xce4bce8f/</guid>
      <pubDate>Tue, 11 Nov 2025 17:46:05 +0000</pubDate>
      <description>First day at Optasia.com. I missed these guys (was there for 6 years, in the past), and feels healthy to work on something not crypto-related, after a long time. Will probably post much less -but may have some interesting stuff to share, especially during trips.</description>
      <content:encoded><![CDATA[
	
	<p>First day at Optasia.com. I missed these guys (was there for 6 years, in the past), and feels healthy to work on something not crypto-related, after a long time. Will probably post much less -but may have some interesting stuff to share, especially during trips.</p>

]]></content:encoded>

    </item>
    
    <item>
      <title>Me and Farcaster: It's complicated</title>
      <link>https://blog.vrypan.net/2025/11/08/me-and-farcaster-it-s-complicated/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/11/08/me-and-farcaster-it-s-complicated/</guid>
      <pubDate>Sat, 08 Nov 2025 22:33:40 +0000</pubDate>
      <description>I joined Farcaster in July 2022 — one of the earliest users, #280.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/11/08/me-and-farcaster-it-s-complicated/me-and-farcaster.png">
        
	<p>I joined Farcaster in <strong>July 2022</strong> — one of the earliest users, <strong>#280</strong>.</p>
<p>I’d seen the web evolve from static pages to platforms, from personal publishing to algorithmic feeds. I lived Web 1’s openness, Web 2.0’s promises, and the eventual centralization that crushed so many of its early ideals.</p>
<p>Farcaster looked like a chance to start over — to build something open, censorship-resistant, and (“sufficiently”) decentralized.</p>
<hr />
<p>In those early days, Farcaster was <em>small</em>. You practically knew everyone. It reminded me of early Twitter — a place where conversation mattered more than visibility.</p>
<p>I’d had my share of online attention in the past. It’s exciting at first, but it’s not as satisfying as people think — at least not for me. I’ve come to value small, smart communities that care about the same things I do. That’s what Farcaster gave me in 2022: a group of people building, debating, and exploring what a better social web might look like.</p>
<p>It felt special. Every update, every discussion about protocol design or decentralization, felt like progress toward a shared goal — building something new and durable.</p>
<hr />
<p>By late <strong>2024</strong>, things started to feel different. I didn’t notice it then, but the focus had shifted. The goal was no longer <em>&quot;let’s build a sufficiently decentralized social network.&quot;</em> It had become <em>&quot;not growing 10×, 100×, 1000× is an existential threat.&quot;</em></p>
<p>Those two goals aren’t mutually exclusive — but when you put growth first, you start accepting compromises elsewhere.</p>
<p>On the technical side, Farcaster evolved from a pure peer-to-peer protocol into one that depends on couple of validators. The conversation shifted from <em>&quot;how do we make this protocol resilient, censorship-resistant and a platform to build on?”</em> to <em>&quot;how do we onboard more users?&quot;</em></p>
<p>Developers building mini-apps — especially those that attracted new users — were celebrated. Requests from those working on lower-level stuff directly interacting with the protocol were mostly ignored, or put at the bottom of the priority list. The incentives and the culture reflected that shift.</p>
<p>It’s not that the Merkle Manufactory team is wrong — they’re an incredible <strong>product</strong> team, and I admire them for this. They are extremely competent, they deliver at an impressive pace, they have taste, they steward and empower the community. But they think like product people, not open-platform stewards or decentralization crusaders. If they had to choose between building the iPhone or Linux, they’d build the iPhone every time, with the AppStore and everything.</p>
<p>I don't feel that they relate<sup class="footnote-ref"><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup> to the <strong>lifecycle of products in the open-source or hacker world</strong>, where things often start as rough hacks — scripts and duct tape held together by curiosity — and then evolve, sometimes by completely different teams, into polished tools with GUIs and nice websites. In that world, the most important thing isn’t polish; it’s lowering friction for experimentation and empowering the first step. Sometimes you even have to sacrifice features to make it easier for hackers to play and explore.</p>
<p>Building open systems requires that mindset — comfort with decentralization, messiness, and loss of control. That’s the <strong>bazaar</strong> way, not the <strong>cathedral</strong>. Farcaster started as a bazaar. Over time, it became a cathedral. <sup class="footnote-ref"><a href="#fn-2" id="fnref-2" data-footnote-ref>2</a></sup></p>
<hr />
<p>Today, my relationship with Farcaster is… complicated.</p>
<p>Even the language has changed. What we used to call <em>&quot;Farcaster,&quot;</em> the protocol, is now <strong>Snapchain</strong>. And the main app — previously <em>Warpcast</em> — is now called <strong>Farcaster</strong>.</p>
<p>That evolution mirrors how I feel: the app and the protocol have swapped importance.</p>
<p>I’m actually optimistic about <strong>Farcaster the app</strong>. It’s one of the best crypto wallets I’ve used — intuitive, feature-rich, and beautifully designed. The acquisition of <strong>Clanker</strong>, a token-launching platform, feels like a smart step toward a more dynamic, crypto-native social experience. I’m genuinely bullish on that direction.</p>
<p>But I’m less optimistic about <strong>Snapchain</strong>, the protocol. It’s open, and its design makes it hard (though not impossible) to gate — which is good. I still run my own node at home, and I still integrate parts of my workflow with Snapchain.</p>
<p>But it’s clearly no longer the main focus. Snapchain exists to support the app, not the other way around.</p>
<p>That’s a reversal of the original vision: the protocol would be the enduring layer, and the apps would come and go on top of it.</p>
<p>Two years ago, I could imagine a future where other clients emerged, Warpcast was sunset, and the core team focused entirely on the protocol. <strong>Today, I can’t unsee a different future — one where the app is extremely successful, but the protocol is sunset because it’s no longer needed.</strong></p>
<hr />
<section class="footnotes" data-footnotes>
<ol>
<li id="fn-1">
<p>I mean, not just as a theory, but as people who have done it and have participated in similar projects, and have joined communities thinking like this. Worth noting that I've never met in person Dan or Varun, so the impression I have from interacting with them online may be wrong. <a href="#fnref-1" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>
</li>
<li id="fn-2">
<p><a href="https://en.wikipedia.org/wiki/The_Cathedral_and_the_Bazaar">The Cathedral and the Bazaar</a> <a href="#fnref-2" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="2" aria-label="Back to reference 2">↩</a></p>
</li>
</ol>
</section>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/11/08/me-and-farcaster-it-s-complicated/me-and-farcaster.png"
   type="image/png"
   length="2436534"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/11/07/fc-2025-11-07-0xd493bc68/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/11/07/fc-2025-11-07-0xd493bc68/</guid>
      <pubDate>Fri, 07 Nov 2025 19:17:41 +0000</pubDate>
      <description>I don't get Minecraft Youtube. (you probably relate if you have kids)</description>
      <content:encoded><![CDATA[
	
	<p>I don't get Minecraft Youtube. (you probably relate if you have kids)</p>
<p>But then, I watch this. And I find it exciting. So who am I to judge?</p>
<p>How to write a Web Server in pure bash: <a href="https://www.youtube.com/watch?v=L967hYylZuc">https://www.youtube.com/watch?v=L967hYylZuc</a></p>
<p>BTW, the whole channel is amazing.</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/11/07/fc-2025-11-07-0xd493bc68/image01.jpg"
   type="image/jpeg"
   length="261192"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/11/07/fc-2025-11-07-0x970043ce/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/11/07/fc-2025-11-07-0x970043ce/</guid>
      <pubDate>Fri, 07 Nov 2025 10:30:08 +0000</pubDate>
      <description>That time in the 90s, when Apple licensed the Mac OS: The story of Mac clones.</description>
      <content:encoded><![CDATA[
	
	<p>That time in the 90s, when Apple licensed the Mac OS: The story of Mac clones.</p>
<p><a href="https://www.youtube.com/watch?v=P7vvdXzcrFM">https://www.youtube.com/watch?v=P7vvdXzcrFM</a></p>
<p><a href="https://sixcolors.com/post/2020/10/20-macs-for-2020-10-power-computing/">https://sixcolors.com/post/2020/10/20-macs-for-2020-10-power-computing/</a></p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/11/07/fc-2025-11-07-0x970043ce/image01.jpg"
   type="image/jpeg"
   length="98906"/>

   <enclosure url="https://blog.vrypan.net/2025/11/07/fc-2025-11-07-0x970043ce/image02.jpg"
   type="image/jpeg"
   length="90429"/>

    </item>
    
    <item>
      <title>Farcaster Links Babel</title>
      <link>https://blog.vrypan.net/2025/11/03/farcaster-links-babel/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/11/03/farcaster-links-babel/</guid>
      <pubDate>Mon, 03 Nov 2025 07:24:07 +0000</pubDate>
      <description>However, having multiple clients  introduces a new challenge: resource links.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/11/03/farcaster-links-babel/babel.png">
        
	<p>However, having multiple clients <sup class="footnote-ref"><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup> introduces a new challenge: <strong>resource links</strong>.</p>
<p>Here are some scenarios:</p>
<ol>
<li>
<p>Suppose you use TBA and want to share a link to an interesting cast on X. You tap “Share,” copy the link, and post it on X. Now, I’m using the Zapper app, and when I click that link, I’m taken to a page like:<br />
<a href="https://base.app/post/0x723095057009a6255eca94352e8ea671a7f03439">https://base.app/post/0x723095057009a6255eca94352e8ea671a7f03439</a><br />
— a deep link intended for TBA. Since I don’t have TBA installed, the page is unusable.</p>
</li>
<li>
<p>Even worse, imagine a third user copies that same link and pastes it in a cast, in Recaster. When this link appears inside another Farcaster app, it should ideally render as a cast embed. But because the app doesn’t recognize it as a Farcaster resource, it just shows a plain link. When users click it, they again land on a base.app page where they can’t interact, instead of the client they are using.</p>
</li>
</ol>
<p>This is not a TBA-specific issue. You get the same problem if you change app names, and replace the links with the corresponding app’s links.</p>
<p>This issue isn’t new. For a long time, Warpcast also embedded cast links as plain URLs rather than native embeds. Thankfully, that changed — otherwise, we’d be stuck with thousands of casts opening on the (now, deprecated) warpcast.com domain.</p>
<p>Now, we need a <strong>solution that works across all clients and user setups.</strong></p>
<p>There are two main components to such a solution.</p>
<hr />
<h3>1. Standardized Resource Metadata</h3>
<p>Any URL representing a Farcaster resource (cast, profile, etc.) must expose a standard way for other apps to identify it. We can’t expect every client to know the URL structure of every other client — and in some cases, extracting this information isn’t even possible.<br />
A good example is the Farcaster app itself, which doesn’t include the full cast hash in its URLs.</p>
<p>A clean, extensible solution is to use <strong>HTTP headers</strong> — see <a href="https://github.com/farcasterxyz/protocol/discussions/202">FIP: HTTP Headers for Farcaster resources</a>.</p>
<p>This approach allows any Farcaster client (or any external app) to perform a lightweight <code>HEAD</code> request to a URL and determine whether it references a Farcaster resource (e.g., a cast). If so, the app can render or embed it natively.</p>
<hr />
<h3>2. A Universal Link Service for Farcaster</h3>
<p>The second component is a <strong>universal link service</strong>: a way to share a single Farcaster link that opens in the user’s preferred client.</p>
<p>For example, if I share a cast from my blog, when you click on it, it should open in your preferred Farcaster client. If you use Zapper, it should open in Zapper; if you use Recaster, it should open in Recaster.</p>
<p>Ideally, this would be handled through a protocol URI scheme, such as:<br />
<code>farcaster://cast/280/0x627b6c301664aea2fe5da8cca0da59d3823f9fc8</code><br />
However, mobile developers agree that implementing this reliably on mobile (and even desktop) is challenging.</p>
<p>A practical workaround is inspired by <a href="https://www.subtome.com/">SubToMe</a>, which has provided a similar solution for RSS for over a decade.</p>
<p>The idea is simple: agree on a shared domain — for example, <code>link.farcaster.xyz</code> — and have all clients use it when generating shareable links.  A cast link will look like this:<br />
<code>link.farcaster.xyz/280/0x627b6c301664aea2fe5da8cca0da59d3823f9fc8</code><br />
(Yes, shorter or prettier URLs are possible, but they would increase complexity and load for the service hosting this link system, the decision is up to whoever implements it <sup class="footnote-ref"><a href="#fn-2" id="fnref-2" data-footnote-ref>2</a></sup>).</p>
<p>When a user visits such a link, they’re prompted to select their preferred Farcaster client. The site stores this preference in a cookie, then redirects them to the appropriate deep link.</p>
<p>On subsequent visits, the stored preference automatically redirects them without prompting. This setting is per-browser, allowing users to choose Recaster on mobile and farcaster.xyz on desktop, for example.</p>
<hr />
<p><a href="https://farcaster.xyz/vrypan.eth/0x89b3170d">You can leave a comment here</a> — good luck finding a way to open the cast in your favorite app, if it's not the &quot;official&quot; Farcaster app.</p>
<hr />
<section class="footnotes" data-footnotes>
<ol>
<li id="fn-1">
<p>Some general purpose Farcaster clients are <a href="https://farcaster.xyz">Farcaster</a>, <a href="https://base.app">TBA</a>, <a href="https://zapper.xyz">Zapper</a> has one in beta, <a href="https://recaster.org">Recaster</a> is built by an independent developer, <a href="https://firefly.social/">Firefly</a> is an other one. There are also a number of clients designed for specific uses, like <a href="https://cura.network">Cura</a>. The list is by no means complete, these are just the ones that come to mind at the time of this writing. <a href="#fnref-1" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>
</li>
<li id="fn-2">
<p>My personal opinion is that the URL should contain all the information required to identify the resource, in this case <code>fid</code> and <code>hash</code> to avoid ending up with broken links in the future, just like 99% of short URLs created 10 years ago have stoped working. Even if the service stops working, if the link contains the <code>fid</code> and the <code>hash</code>, a user can reconstruct a valid link. (And even if the cast no longer exists, redirect to the right page on an archiving service.) <a href="#fnref-2" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="2" aria-label="Back to reference 2">↩</a></p>
</li>
</ol>
</section>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/11/03/farcaster-links-babel/babel.png"
   type="image/png"
   length="3233499"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/11/02/fc-2025-11-02-0x9a05c54f/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/11/02/fc-2025-11-02-0x9a05c54f/</guid>
      <pubDate>Sun, 02 Nov 2025 05:53:56 +0000</pubDate>
      <description>For some reason @wdimapp's image feed brings up casts that I've totally missed.</description>
      <content:encoded><![CDATA[
	
	<p>For some reason @wdimapp's image feed brings up casts that I've totally missed.</p>
<p>It could be that an image embed requires some additional effort (even if marginal) from the poster, so it's a filter by itself. Or that my brain can scan through a feed of images more efficiently than text.</p>
<p>But there's something there.</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/11/02/fc-2025-11-02-0x9a05c54f/image01.jpg"
   type="image/jpeg"
   length="185776"/>

   <enclosure url="https://blog.vrypan.net/2025/11/02/fc-2025-11-02-0x9a05c54f/image02.jpg"
   type="image/jpeg"
   length="108544"/>

   <enclosure url="https://blog.vrypan.net/2025/11/02/fc-2025-11-02-0x9a05c54f/image03.jpg"
   type="image/jpeg"
   length="236960"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/11/02/fc-2025-11-02-0x98cc798c/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/11/02/fc-2025-11-02-0x98cc798c/</guid>
      <pubDate>Sun, 02 Nov 2025 05:40:13 +0000</pubDate>
      <description>I love it.</description>
      <content:encoded><![CDATA[
	
	<p>I love it.</p>
<p>here's what @tryemerge just made for me using Día de los Muertos Sugar Skull Transformation by @terrybain, spark yours up now!</p>
<p><a href="https://emerge-mini-app.vercel.app/generating/319dc0e0-a96c-4345-86a3-c95475d7a337?share=true&amp;t=1762061975937">https://emerge-mini-app.vercel.app/generating/319dc0e0-a96c-4345-86a3-c95475d7a337?share=true&amp;t=1762061975937</a></p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/11/02/fc-2025-11-02-0x98cc798c/image01.png"
   type="image/png"
   length="2274605"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/10/30/fc-2025-10-30-0x92a670c2/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/30/fc-2025-10-30-0x92a670c2/</guid>
      <pubDate>Thu, 30 Oct 2025 14:19:23 +0000</pubDate>
      <description>https://www.mcsweeneys.net/articles/hi-its-me-wikipedia-and-i-am-ready-for-your-apology</description>
      <content:encoded><![CDATA[
	
	<blockquote>
<p>HI, IT’S ME, WIKIPEDIA, AND I AM READY FOR YOUR APOLOGY
Well, well, well. Look who it is.</p>
<p>The global academic, scientific, and pro-fact community.
[...]
What’s that? You want me around now? Well, maybe if you ask nicely. And make it worth my while.</p>
</blockquote>
<p><a href="https://www.mcsweeneys.net/articles/hi-its-me-wikipedia-and-i-am-ready-for-your-apology">https://www.mcsweeneys.net/articles/hi-its-me-wikipedia-and-i-am-ready-for-your-apology</a></p>

]]></content:encoded>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/10/30/fc-2025-10-30-0x0ea4d9e1/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/30/fc-2025-10-30-0x0ea4d9e1/</guid>
      <pubDate>Thu, 30 Oct 2025 01:57:21 +0000</pubDate>
      <description>https://farcaster.xyz/miniapps/53zv0cqlhNrl/ascii-art-ships</description>
      <content:encoded><![CDATA[
	
	<p><a href="https://farcaster.xyz/miniapps/53zv0cqlhNrl/ascii-art-ships">https://farcaster.xyz/miniapps/53zv0cqlhNrl/ascii-art-ships</a></p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/30/fc-2025-10-30-0x0ea4d9e1/image01.jpg"
   type="image/jpeg"
   length="145724"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/10/28/fc-2025-10-28-0x425602e0/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/28/fc-2025-10-28-0x425602e0/</guid>
      <pubDate>Tue, 28 Oct 2025 22:51:17 +0000</pubDate>
      <description>I watched A House of Dynamite.</description>
      <content:encoded><![CDATA[
	
	<p>I watched A House of Dynamite.</p>
<p>I did not expect this. Not a masterpiece. But it's unsettling.</p>
<p><a href="https://www.netflix.com/gr-en/title/81744537">https://www.netflix.com/gr-en/title/81744537</a></p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/28/fc-2025-10-28-0x425602e0/image01.jpg"
   type="image/jpeg"
   length="82813"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/10/28/fc-2025-10-28-0xbf875d76/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/28/fc-2025-10-28-0xbf875d76/</guid>
      <pubDate>Tue, 28 Oct 2025 14:00:11 +0000</pubDate>
      <description>This is starting to look good. Nothing really fancy, it's practically a guide on how to formalize and leverage a specific FIP-2 use case.</description>
      <content:encoded><![CDATA[
	
	<p>This is starting to look good. Nothing really fancy, it's practically a guide on how to formalize and leverage a specific FIP-2 use case.</p>
<p>At the same time, the spec takes into consideration practical limitations and implementation hurdles (for example, how easy it is to implement at scale, with minimal resources).</p>
<p>Start a thread in discussions if you have questions, or suggestions, or any other feedback. Also, interested in applications that could leverage it, other than blog feeds.</p>
<p><a href="https://github.com/vrypan/snappub">https://github.com/vrypan/snappub</a></p>

]]></content:encoded>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/10/27/fc-2025-10-27-0x055fec29/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/27/fc-2025-10-27-0x055fec29/</guid>
      <pubDate>Mon, 27 Oct 2025 15:38:05 +0000</pubDate>
      <description>So, I started working on the ideas described in https://blog.vrypan.net/2025/10/24/snapchain-and-static-blogs/ which lead me down a rabbit hole:</description>
      <content:encoded><![CDATA[
	
	<p>So, I started working on the ideas described in <a href="https://blog.vrypan.net/2025/10/24/snapchain-and-static-blogs/">https://blog.vrypan.net/2025/10/24/snapchain-and-static-blogs/</a> which lead me down a rabbit hole:</p>
<ul>
<li>
<p><a href="https://github.com/vrypan/snappub">https://github.com/vrypan/snappub</a>
This repo has the initial spec for RSS feed to use Snapchain as their notification backend (what used to be a &quot;RSS ping service&quot;). This is a very efficient way to notify RSS readers that a feed has been updated.</p>
</li>
<li>
<p><a href="https://github.com/vrypan/snappub-tools">https://github.com/vrypan/snappub-tools</a>
To help with testing, especially devs that know little about Farcaster and Snapchain, I started building a set of tools to help them send updates and check if a feed has been updated.</p>
</li>
<li>
<p><a href="https://github.com/vrypan/fc-appkey">https://github.com/vrypan/fc-appkey</a>
Which had me face the old problem with posting to Farcaster from your own apps: appkeys (aka signers). So, I decided to fix this for everyone. fc-appkey is easy to install (just binary, brew, etc) and will show you the QR code in your terminal, and let you generate appkeys:</p>
</li>
<li>
<p>And btw, I realized that I can use a single repo for all my homebrew taps, so, I'll start migrating all of them under vrypan/homebrew-tap.</p>
</li>
</ul>

]]></content:encoded>

    </item>
    
    <item>
      <title>1Password ENV variables</title>
      <link>https://blog.vrypan.net/2025/10/26/1password-env-variables/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/26/1password-env-variables/</guid>
      <pubDate>Sun, 26 Oct 2025 06:00:18 +0000</pubDate>
      <description>Why?</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/10/26/1password-env-variables/1passenv.png">
        
	<div class="markdown-alert markdown-alert-important">
<p class="markdown-alert-title">Important</p>
<p>The code snippet bellow has been updated! The old one did not work as expected!</p>
</div>
<p>Why?</p>
<ul>
<li>You don't have to store API keys and other sensitive variables in .env files that may be accidentally pushed to github, be recovered from backups, etc.</li>
<li>Your API keys are available on any computer you have 1Password installed (if you have enabled 1Password sync).</li>
</ul>
<p>You can read more and find more advanced uses of the 1Password CLI <a href="https://developer.1password.com/docs/cli/use-cases">here</a>.</p>
<hr />
<p>First, <a href="https://developer.1password.com/docs/cli/get-started/">install the 1Password CLI</a>.</p>
<p>Next, add this code to your <code>~/.zsh</code>, or <code>~/.bashrc</code>, or the corresponding rc file for your environment.</p>
<pre lang="bash"><code>op_env() {
    local secret
    secret=$(printf '{{ op://Personal/%s/credential }}' &quot;$1&quot; | op inject)
    export &quot;$1=$secret&quot;
}
</code></pre>
<div class="markdown-alert markdown-alert-note">
<p class="markdown-alert-title">Note</p>
<p>The code above assumes that the 1Password vault you are using is called &quot;Personal&quot;.
Adjust accordingly.</p>
</div>
<p><strong>Make sure you start a new shell to activate the new function.</strong> Now, open 1Password and create an &quot;API Credential&quot;.</p>
<p><figure><img src="https://blog.vrypan.net/2025/10/26/1password-env-variables/create1.png" alt="" /></figure></p>
<p>Set the name to the name of the env variable you want to save and <code>credential</code> to the value.</p>
<p><figure><img src="https://blog.vrypan.net/2025/10/26/1password-env-variables/create2.png" alt="" /></figure></p>
<p>Save the item.</p>
<p>In your terminal type</p>
<pre lang="bash"><code>$ op_env TEST_API_KEY # 1Pass authentication will pop-up 
$ echo $TEST_API_KEY
1234567890
</code></pre>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/26/1password-env-variables/1passenv.png"
   type="image/png"
   length="30726"/>

   <enclosure url="https://blog.vrypan.net/2025/10/26/1password-env-variables/create1.png"
   type="image/png"
   length="425142"/>

   <enclosure url="https://blog.vrypan.net/2025/10/26/1password-env-variables/create2.png"
   type="image/png"
   length="64540"/>

    </item>
    
    <item>
      <title>SnapPub: Snapchain-powered WebSub/Webmentions</title>
      <link>https://blog.vrypan.net/2025/10/24/snapchain-and-static-blogs/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/24/snapchain-and-static-blogs/</guid>
      <pubDate>Fri, 24 Oct 2025 22:22:53 +0200</pubDate>
      <description>I love local-first infrastructure, that user can run at home, without depending on cloud providers or SaaS. My ideal software architecture is something:</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/10/24/snapchain-and-static-blogs/snappub.png">
        
	<p>I love local-first infrastructure, that user can run at home, without depending on cloud providers or SaaS. My ideal software architecture is something:</p>
<ul>
<li><strong>you can run it at home</strong>, on commodity hardware (i.e. everyone can do it, really decentralized, hard for a central authority to stop)</li>
<li><strong>requires no incoming network connections</strong> (because incoming network connections expose the local network to security threats most users can not mitigate, requires a stable Internet connection, and does not scale)</li>
<li>and if <strong>it needs to share resources with the public Internet, it does so by publishing them as statically hosted assets</strong>, the cheapest (often free), most widely available Infrastructure-as-a-Service.</li>
</ul>
<p>For example, my blog works like this<sup class="footnote-ref"><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup>: Everything is put together locally, then the static pages are hosted on a service like AWS S3, Cloudflare R2, netlify, etc.</p>
<p>A similar, but a bit more complex design is used by WDIM<sup class="footnote-ref"><a href="#fn-2" id="fnref-2" data-footnote-ref>2</a></sup> (What Did I Miss?), a Farcaster<sup class="footnote-ref"><a href="#fn-3" id="fnref-3" data-footnote-ref>3</a></sup> miniapp that generates daily digests for its subscribers. In WDIM's case:</p>
<ul>
<li>the service runs locally, on a computer I have at home,</li>
<li>it uses a Farcaster node that also runs locally,</li>
<li>it checks a smart contract (&quot;hosted&quot; on Base L2) for subscription payments,</li>
<li>and publishes the digest on S3.</li>
<li>The miniapp is a web app hosted on S3 that leverages the Farcaster Miniapp APIs<sup class="footnote-ref"><a href="#fn-4" id="fnref-4" data-footnote-ref>4</a></sup> for payment and identity.</li>
</ul>
<p>The core logic runs locally, on cheap hardware, subscription payments take place onchain, S3 is used for presentation.</p>
<hr />
<p>Farcaster is an incredibly cool syncing machine that can enable local-first workflows: If you run a node locally, you have a full copy of the global state, ordered in blocks and updated almost instantaneously.</p>
<p>The application I'm most interested in? Enabling static blogs with functionality not possible right now, like comments, reactions, pingbacks, webmentions, etc., and all this using a local-first setup as described above.</p>
<p>Here's a half-baked outline of the idea. <strong>I'll call it SnapPub</strong> to make our life easier, but the name can change.</p>
<h3>1. Notify the world that your feed has been updated</h3>
<p>Knowing when an RSS feed has been updated is a big challenge: A typical RSS reader has to make costly (time- and resource-intensive) HTTP requests to poll feeds that rarely update.</p>
<p>Protocols like WebSub<sup class="footnote-ref"><a href="#fn-6" id="fnref-6" data-footnote-ref>5</a></sup> try to address it, but they need a service you run on a publicly accessible server.</p>
<p>The solution:</p>
<ol>
<li>Advertise<sup class="footnote-ref"><a href="#fn-7" id="fnref-7" data-footnote-ref>6</a></sup> an <code>fname</code> or <code>fid</code>. This will tell the rss reader which Farcaster account to check for new updates.</li>
<li>When the feed has been updated, <code>fname</code> must post a FID-2<sup class="footnote-ref"><a href="#fn-8" id="fnref-8" data-footnote-ref>7</a></sup> cast with <code>parentUrl=rssUrl</code> (the body must be empty, and may be used for other features the future<sup class="footnote-ref"><a href="#fn-9" id="fnref-9" data-footnote-ref>8</a></sup>)</li>
</ol>
<p>Now an RSS reader/aggregator can watch the Snapchain<sup class="footnote-ref"><a href="#fn-10" id="fnref-10" data-footnote-ref>9</a></sup> feed for casts that match the above criteria. It doesn't matter how many blogs it needs to track, <strong>any blog</strong> that implements SnapPub will post there. This is a huge performance and scaling improvement.</p>
<p>And if the reader goes down, or doesn't want to maintain a process that filters the Snapchain feed in real time, it can check periodically for casts that were posted since the check. Snapchain nodes offer APIs that make all this very easy, like <code>GetCastsByParent()</code> and <code>GetCastsByFid()</code>.</p>
<h3>2. Comments, pingbacks, webmentions</h3>
<p>SnapPub offers a way to comment on blog posts as a user, or even send a &quot;mention&quot; (similar to webmentions or pingbacks) when an other blog mentions a specific post.</p>
<ul>
<li>Any FIP-2 reply to the post URL (posted using Farcaster, or any other Snapchain client) can be treated as a post reply. Again, it's easy for a local backend to check for these replies, embed them in the post periodically, and republish the post (but without an RSS update).</li>
<li>Webmentions and pingbacks can also be implemented as comments (linking to the source in cast's <code>embedUrl</code>)</li>
</ul>
<p>A nice feature of this approach is that a blog does not need to update the static pages to include these replies, it can optionally link to a page like <code>farcaster.xyz/~/urlconversations/&lt;post URL&gt;</code> where users can see all replies to a post and join the conversation. This will require a Farcaster client that offers this functionality (the default Farcaster client does not, and given their focus in becoming a wallet I don't see it happening, but it could be done by someone else, like Cura<sup class="footnote-ref"><a href="#fn-11" id="fnref-11" data-footnote-ref>10</a></sup>).</p>
<h3>3. Likes</h3>
<p>FIP-2 supports reactions to an arbitrary URL, so users can use Farcaster to like a blog post. In the same way the like any cast.</p>
<h2>Bonus</h2>
<p>Farcaster comes with many tools that can help fight spam. There is a social graph, there are a number of quality scores that can indicate if a user is spammy or not. All these features can be leveraged to filter comments. They can even be used to gate comments based on specific criteria (there is no way to prevent a user from commenting on Farcaster, but you can filter which comments appear in your blog).</p>
<p>It also comes with identity, which means every comment or like is attached to a username, an avatar, and social activity that can be used to enrich the presentation.</p>
<h2>Concerns</h2>
<p>The trajectory Farcaster has followed in 2025 is not very reassuring.</p>
<p>Practically, the network is centralized, and depends on one (or maybe two? I've asked many times but never got a reply) validators run my Merkle Manufactory and maybe Neynar. There is no guarantee they will not change their mind and shut it down, or close it in ways that would make this idea unusable, or that they won't be coerced to censor it. (The question is not &quot;why&quot;, it's &quot;why not&quot;.)</p>
<p>They have also been very selective on the features they add to the protocol, based on what they think brings value, but in other cases they may move so fast that may break clients. (I had this happen to me, when they added some <code>user_data</code> fields overnight, to support Farcaster Pro features.)</p>
<p>On the plus side, as long as their bet on social trading/wallet works, or they believe it has the potential to work, the network will be up and we can piggyback on it. The existence of clients from Base and Zerion, i.e. &quot;big&quot; teams that they respect, will probably slow down any quick'n'dirty changes like the ones introduced earlier this year. And, to be fair, many of my concerns around centralization can be addressed if they decide to do so, so there is hope.</p>
<h2>Next steps</h2>
<p>I think I'll work on a prototype that allows bckt<sup class="footnote-ref"><a href="#fn-12" id="fnref-12" data-footnote-ref>11</a></sup> to implement these features, and get a first-hand experience on what needs to be built and how.</p>
<hr />
<section class="footnotes" data-footnotes>
<ol>
<li id="fn-1">
<p><a href="https://blog.vrypan.net/2025/10/23/251023-my-bckt-workflow/">https://blog.vrypan.net/2025/10/23/251023-my-bckt-workflow/</a> <a href="#fnref-1" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>
</li>
<li id="fn-2">
<p><a href="https://farcaster.xyz/wdimapp">https://farcaster.xyz/wdimapp</a> <a href="#fnref-2" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="2" aria-label="Back to reference 2">↩</a></p>
</li>
<li id="fn-3">
<p><a href="https://farcaster.xyz">https://farcaster.xyz</a> <a href="#fnref-3" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="3" aria-label="Back to reference 3">↩</a></p>
</li>
<li id="fn-4">
<p><a href="https://miniapps.farcaster.xyz">https://miniapps.farcaster.xyz</a></p>
<p>There are more than one paths to get there, and there's still hope if it ever becomes a priority, but I wouldn't bet on it. <a href="#fnref-4" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="4" aria-label="Back to reference 4">↩</a></p>
</li>
<li id="fn-6">
<p><a href="https://en.wikipedia.org/wiki/WebSub">https://en.wikipedia.org/wiki/WebSub</a> <a href="#fnref-6" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="5" aria-label="Back to reference 5">↩</a></p>
</li>
<li id="fn-7">
<p>WebSub uses this to advertise hubs and the link to be used.</p>
<pre><code>Link: &lt;https://your-hub.example.com&gt;; rel=hub
Link: &lt;https://your-blog.example.com/blog/feed&gt;; rel=self
</code></pre>
<p>We could use something like this?</p>
<pre><code>Link: fc://fid/&lt;fid&gt;; rel=snappub
Link: &lt;https://your-blog.example.com/blog/feed&gt;; rel=self
</code></pre>
<a href="#fnref-7" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="6" aria-label="Back to reference 6">↩</a>
</li>
<li id="fn-8">
<p><a href="https://github.com/farcasterxyz/protocol/discussions/71">https://github.com/farcasterxyz/protocol/discussions/71</a> <a href="#fnref-8" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="7" aria-label="Back to reference 7">↩</a></p>
</li>
<li id="fn-9">
<p>In the future, there may be special commands in the content body to indicate other changes like a move to a new url. <a href="#fnref-9" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="8" aria-label="Back to reference 8">↩</a></p>
</li>
<li id="fn-10">
<p><a href="https://snapchain.farcaster.xyz">https://snapchain.farcaster.xyz</a> <a href="#fnref-10" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="9" aria-label="Back to reference 9">↩</a></p>
</li>
<li id="fn-11">
<p><a href="https://cura.network">https://cura.network</a> <a href="#fnref-11" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="10" aria-label="Back to reference 10">↩</a></p>
</li>
<li id="fn-12">
<p><a href="https://github.com/vrypan/bckt">https://github.com/vrypan/bckt</a> <a href="#fnref-12" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="11" aria-label="Back to reference 11">↩</a></p>
</li>
</ol>
</section>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/24/snapchain-and-static-blogs/snappub.png"
   type="image/png"
   length="508635"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/10/24/fc-2025-10-24-0x45287cef/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/24/fc-2025-10-24-0x45287cef/</guid>
      <pubDate>Fri, 24 Oct 2025 05:34:52 +0000</pubDate>
      <description>The Mecha Comet. I'm a sucker for this kind of things.</description>
      <content:encoded><![CDATA[
	
	<p>The Mecha Comet. I'm a sucker for this kind of things.</p>
<p><a href="https://www.youtube.com/watch?v=oZdpWamu2y4">https://www.youtube.com/watch?v=oZdpWamu2y4</a>
<a href="https://www.youtube.com/watch?v=DB-0H8Q4d1U">https://www.youtube.com/watch?v=DB-0H8Q4d1U</a></p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/24/fc-2025-10-24-0x45287cef/image01.jpg"
   type="image/jpeg"
   length="131391"/>

   <enclosure url="https://blog.vrypan.net/2025/10/24/fc-2025-10-24-0x45287cef/image02.jpg"
   type="image/jpeg"
   length="241860"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/10/24/fc-2025-10-24-0x3bc8b60b/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/24/fc-2025-10-24-0x3bc8b60b/</guid>
      <pubDate>Fri, 24 Oct 2025 04:43:24 +0000</pubDate>
      <description>I've been spending more time on https://reederapp.com lately. Which comes with my blog becoming the core of my online presence again. And also, bckt-generated RSS feeds getting some love.</description>
      <content:encoded><![CDATA[
	
	<p>I've been spending more time on <a href="https://reederapp.com">https://reederapp.com</a> lately. Which comes with my blog becoming the core of my online presence again. And also, bckt-generated RSS feeds getting some love.</p>
<p>Being able to post on Farcaster (which is easy, compared to writing a new blog post) and then selectively converting casts to blog posts with a single command, is liberating. I could automate the process, but I like the curation step -not everything I post here is worth becoming a blog post.</p>
<p>I also have a couple of ideas on how to piggyback on snapchain to offer ActivityPub-like or even ActivityPub-compatible functionality for static blogs.</p>

]]></content:encoded>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/10/23/fc-2025-10-23-0xe6969ee4/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/23/fc-2025-10-23-0xe6969ee4/</guid>
      <pubDate>Thu, 23 Oct 2025 17:21:52 +0000</pubDate>
      <description>Hey! I’m you, three years from now. Don’t bother.</description>
      <content:encoded><![CDATA[
	
	<p>Hey! I’m you, three years from now. Don’t bother.</p>
<blockquote>
<p>BTW, @dwr, there was a very interesting community/movement around &quot;IndieWeb&quot; about 8-9 years ago. I have not followed it for some time, but anyone building an open web3 should have a look at their concepts and  ideas.</p>
<p>--@vrypan</p>
</blockquote>

]]></content:encoded>

    </item>
    
    <item>
      <title>My blog posting workflow</title>
      <link>https://blog.vrypan.net/2025/10/23/251023-my-bckt-workflow/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/23/251023-my-bckt-workflow/</guid>
      <pubDate>Thu, 23 Oct 2025 07:33:35 +0200</pubDate>
      <description>Here's my blog posting workflow, using  bckt, Obsidian, and Netlify.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/10/23/251023-my-bckt-workflow/my-workflow.png">
        
	<p>Here's my blog posting workflow, using  <strong>bckt</strong><sup class="footnote-ref"><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup>, <strong>Obsidian</strong><sup class="footnote-ref"><a href="#fn-2" id="fnref-2" data-footnote-ref>2</a></sup>, and <strong>Netlify</strong><sup class="footnote-ref"><a href="#fn-3" id="fnref-3" data-footnote-ref>3</a></sup>.</p>
<h2>The setup</h2>
<p>All my posts live in a folder called <code>posts/</code>, which I’ve added as an <strong>Obsidian vault</strong>. That gives me a nice writing environment with all of Obsidian’s goodies.</p>
<p>Inside the vault, I keep a <code>posts/_obsidian/bckt-template.md</code> file that looks like this:</p>
<pre lang="yaml"><code>---
title: &quot;{{title}}&quot;
date: {{date:YYYY-MM-DD hh:mm:ss}}
abstract: &gt;
 Use this to add a post abstract
tags: []
attached: []
image:
---
</code></pre>
<p>This is my frontmatter template for new posts.</p>
<div class="markdown-alert markdown-alert-note">
<p class="markdown-alert-title">Note</p>
<p>An empty <code>posts/_obsidian/.backtignore</code> instructs bckt to skip this folder when rendering the site.</p>
</div>
<h2>Writing a post</h2>
<p>When I want to write something new, I create a folder like this:</p>
<pre><code>posts/2025/10/251023-my-bckt-workflow/
</code></pre>
<p>Then I drop a markdown file inside — for example <code>post.md</code>. (The name doesn’t matter; bckt will pick any <code>&lt;filename&gt;.md</code>.)</p>
<p>I use Obsidian’s <strong>Templates: Insert template</strong> action to insert my frontmatter, then I fill in the title, date, and abstract, and start writing.</p>
<p>I also add any related files (for example, images) in the same folder, and include them in the <code>attached</code> frontmatter field. I can then reference them relatively (ex: <code>![image](image.png)</code>), and bckt will take care or the rest.</p>
<h2>Turning Farcaster casts into posts</h2>
<p>Sometimes I post something short on <strong>Farcaster</strong><sup class="footnote-ref"><a href="#fn-4" id="fnref-4" data-footnote-ref>4</a></sup> that I later want to turn into a proper blog post. That’s where <strong>bckt-fc</strong> comes in. I just run a command like:</p>
<pre><code>bckt-fc --castid vrypan/0xe9e10a9ae08803d21e4c80ce6da730dd3ff3d6a5 \
--destination posts/2025
</code></pre>
<p>This fetches the cast (and any images or videos in it) and automatically creates a new post in my <code>posts/2025</code> folder. It’s a quick way to turn spontaneous thoughts into something more permanent.</p>
<h2>Publishing the site</h2>
<p>Once I’m done writing, I render the site with:</p>
<pre><code>bckt render
</code></pre>
<p>If I want to preview locally, I use:</p>
<pre><code>bckt dev
</code></pre>
<p>Finally, to push everything live, I deploy to Netlify:</p>
<pre><code>netlify deploy --dir=html --prod
</code></pre>
<p>And that’s it — a full publishing loop that starts in Obsidian and ends with a live post on my blog, all backed by git and simple CLI tools.</p>
<hr />
<section class="footnotes" data-footnotes>
<ol>
<li id="fn-1">
<p><a href="https://github.com/vrypan/bckt">bckt</a> <a href="#fnref-1" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>
</li>
<li id="fn-2">
<p><a href="https://obsidian.md/">Obsidian</a> <a href="#fnref-2" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="2" aria-label="Back to reference 2">↩</a></p>
</li>
<li id="fn-3">
<p><a href="https://www.netlify.com/">Netlify</a> <a href="#fnref-3" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="3" aria-label="Back to reference 3">↩</a></p>
</li>
<li id="fn-4">
<p><a href="https://farcaster.xyz">Farcaster</a> <a href="#fnref-4" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="4" aria-label="Back to reference 4">↩</a></p>
</li>
</ol>
</section>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/23/251023-my-bckt-workflow/my-workflow.png"
   type="image/png"
   length="296632"/>

    </item>
    
    <item>
      <title>Easy file sharing from the cli</title>
      <link>https://blog.vrypan.net/2025/10/22/quick-file-sharing/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/22/quick-file-sharing/</guid>
      <pubDate>Wed, 22 Oct 2025 17:01:38 +0300</pubDate>
      <description>Steve posted this script to make it easy to upload and share files using Cloudflare R2. No need for dropbox, OneDrive, iCloud, etc. Just a simple command and you're ready.</description>
      <content:encoded><![CDATA[
	
	<p><a href="https://bearblog.stevedylan.dev/captains-log-1761013958/">Steve posted this script</a> to make it easy to upload and share files using Cloudflare R2. No need for dropbox, OneDrive, iCloud, etc. Just a simple command and you're ready.</p>
<p>To use it, I created an R2 storage, named it <code>tmp</code>, and connected it to <code>tmp.vrypan.net</code>. I also added a rule to delete any files 120 days after they are uploaded.</p>
<p><figure><img src="https://blog.vrypan.net/2025/10/22/quick-file-sharing/domain.png" alt="domain setup" title="Domain Setup" /><figcaption>Domain Setup</figcaption></figure></p>
<p><figure><img src="https://blog.vrypan.net/2025/10/22/quick-file-sharing/lifecycle.png" alt="lifecyle setup" title="Lifecycle Setup" /><figcaption>Lifecycle Setup</figcaption></figure></p>
<p>Now, I can do something like this to upload a file (the script itself in this case)...</p>
<pre lang="bash"><code>~/bin/upload-r2.sh ~/bin/upload-r2.sh
✓ Upload successful!
https://tmp.vrypan.net/upload-r2.sh
</code></pre>
<p>... and you can get it from <a href="https://tmp.vrypan.net/upload-r2.sh">https://tmp.vrypan.net/upload-r2.sh</a></p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/22/quick-file-sharing/domain.png"
   type="image/png"
   length="60876"/>

   <enclosure url="https://blog.vrypan.net/2025/10/22/quick-file-sharing/lifecycle.png"
   type="image/png"
   length="80912"/>

    </item>
    
    <item>
      <title>Διονύσης Σαββόπουλος</title>
      <link>https://blog.vrypan.net/2025/10/22/251022-savvopoulos/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/22/251022-savvopoulos/</guid>
      <pubDate>Wed, 22 Oct 2025 09:51:39 +0000</pubDate>
      <description>Πέθανε ο Δυονύσης Σαββοπουλος</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/10/22/251022-savvopoulos/dionysis-savvopoulos.jpg">
        
	<p><a href="https://www.kathimerini.gr/society/563879809/pethane-o-dionysis-savvopoylos/">Πέθανε ο Δυονύσης Σαββοπουλος</a></p>
<blockquote>
<p>Εφυγε από τη ζωή σε ηλικία 81 ετών ο Διονύσης Σαββόπουλος, ο μεγάλος τραγουδοποιός, στιχουργός και ερμηνευτής, που άφησε βαθύ αποτύπωμα στο ελληνικό τραγούδι και στην πολιτιστική ζωή της χώρας.</p>
</blockquote>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/22/251022-savvopoulos/dionysis-savvopoulos.jpg"
   type="image/jpeg"
   length="160208"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/10/20/fc-2025-10-20-0x8cbcc21f/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/20/fc-2025-10-20-0x8cbcc21f/</guid>
      <pubDate>Mon, 20 Oct 2025 18:38:26 +0000</pubDate>
      <description>On macOS, use CoreLocationCLI to get your current location in the cli. (I think it requires wifi enabled).</description>
      <content:encoded><![CDATA[
	
	<p>On macOS, use CoreLocationCLI to get your current location in the cli. (I think it requires wifi enabled).</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/20/fc-2025-10-20-0x8cbcc21f/image01.jpg"
   type="image/jpeg"
   length="25207"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/10/19/fc-2025-10-19-0x6e19203a/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/19/fc-2025-10-19-0x6e19203a/</guid>
      <pubDate>Sun, 19 Oct 2025 06:25:41 +0000</pubDate>
      <description>On “creators”</description>
      <content:encoded><![CDATA[
	
	<p>On “creators”</p>
<p>I don’t like the term, at least not the way it’s used today.</p>
<p>Of course, anyone who creates something is a creator by definition. But over time, the word has been loaded with a kind of metaphysical glow. First by social media platforms that wanted to flatter their users, and later by crypto, which tried to elevate the space’s raison d’être “above money.”</p>
<p>Yes, there are people who create content professionally like journalists, designers, photographers, musicians, and others who rightly expect to be paid for it. But in my humble opinion, most people don’t create content to make money. And let’s be honest: most don’t make any, at least not in any meaningful way.</p>
<p>People want to be heard. They share their thoughts, designs, music, and news publicly because they want to be seen. Sure, getting 100k likes or making $1,000 is nice, no one will say no to that (and once you do, you start seeing your online activity through a different lens).</p>
<p>But for most of us, a comment or a reaction from three, five, ten people we value is more than enough. Or meeting someone in real life and hearing them say, “I rarely post in public, but I read you regularly,” or “I really liked what you posted the other day.”</p>

]]></content:encoded>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/10/18/fc-2025-10-18-0x03763097/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/18/fc-2025-10-18-0x03763097/</guid>
      <pubDate>Sat, 18 Oct 2025 20:32:18 +0000</pubDate>
      <description>Solitaire and Minesweeper</description>
      <content:encoded><![CDATA[
	
	<p>Solitaire and Minesweeper</p>
<p>Microsoft first included Solitaire with Windows 3.0 in 1990. While it seemed like just a simple card game, its hidden purpose was to help users learn a new skill: dragging and dropping with a mouse. (Source: <a href="https://en.wikipedia.org/wiki/Microsoft_Solitaire">https://en.wikipedia.org/wiki/Microsoft_Solitaire</a>)</p>
<p>Minesweeper joined the Windows lineup with Windows 3.1 in 1992. It was designed to help users get comfortable with right-clicking and left-clicking. (Source: <a href="https://en.wikipedia.org/wiki/Microsoft_Minesweeper">https://en.wikipedia.org/wiki/Microsoft_Minesweeper</a>)</p>
<p>Among tech enthusiasts, there was a long-running inside joke that MCSE  (officially, Microsoft Certified Solutions Expert) really stood for “Minesweeper Consultant &amp; Solitaire Expert.”</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/18/fc-2025-10-18-0x03763097/image01.jpg"
   type="image/jpeg"
   length="81489"/>

   <enclosure url="https://blog.vrypan.net/2025/10/18/fc-2025-10-18-0x03763097/image02.jpg"
   type="image/jpeg"
   length="45440"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/10/18/fc-2025-10-18-0xb2cf16df/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/18/fc-2025-10-18-0xb2cf16df/</guid>
      <pubDate>Sat, 18 Oct 2025 18:21:56 +0000</pubDate>
      <description>silicon can render your source code into a beautiful image. Like Carbon, but it's implemented in Rust, and runs locally, without requiring a remote web service.</description>
      <content:encoded><![CDATA[
	
	<p>silicon can render your source code into a beautiful image. Like Carbon, but it's implemented in Rust, and runs locally, without requiring a remote web service.</p>
<p><a href="https://github.com/Aloxaf/silicon">https://github.com/Aloxaf/silicon</a></p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/18/fc-2025-10-18-0xb2cf16df/image01.jpg"
   type="image/jpeg"
   length="49595"/>

    </item>
    
    <item>
      <title>The year 2049</title>
      <link>https://blog.vrypan.net/2025/10/18/the-year-2049/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/18/the-year-2049/</guid>
      <pubDate>Sat, 18 Oct 2025 14:32:39 +0000</pubDate>
      <description>The year is 2049. Farcaster has become the internet’s dominant conversational protocol. It —and the entire landscape of social media— looks nothing like it did in the old days.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/10/18/the-year-2049/screenshot.png">
        
	<blockquote>
<p>A story by <a href="https://farcaster.xyz/aviationdoctor.eth/">@aviationdoctor.eth</a>.</p>
<p>Original link: <a href="https://farcaster.xyz/aviationdoctor.eth/0x83300b27f363f94ebccac239f0c32af2b1a601df">https://farcaster.xyz/aviationdoctor.eth/0x83300b27f363f94ebccac239f0c32af2b1a601df</a></p>
<p>I copy it here for future reference.</p>
</blockquote>
<p>The year is 2049. Farcaster has become the internet’s dominant conversational protocol. It —and the entire landscape of social media— looks nothing like it did in the old days.</p>
<p>Here's how it all happened. Make yourself comfortable; wall of text incoming.</p>
<p>Years ago, Reddit introduced the UpCoin to reward karma, resulting in bot farms owning 99.9% of circulating tokens and users fleeing in droves. Posting a meme now costs about as much as renting an apartment in New York City. Meta booted all users from Instagram after realizing it was more efficient to let its nuclear-powered AI data centers generate and react to slop photos without humans in the loop. And X collapsed last year after X Æ A-Xii Musk, its 29-year-old CEO, decided that all posts had to be uploaded directly from Neuralink devices—leading to 99.9% of human users being banned within hours for, well, unfiltered thoughts. Only XRP maxis remain, having no thoughts of their own.</p>
<p>Farcaster, on the other hand, achieved escape velocity and exceeded its founders’ lofty goal of growing from 37 to one billion users. OpenAI —now the first robot-owned, sentient megacorporation since Sam Altman and Peter Thiel merged their minds onto a silicon substrate— uses Farcaster data to train its GPT-∞ model, providing Merkle with a steady and lucrative revenue stream.</p>
<p>In hindsight, Farcaster’s success was inevitable, though it didn’t always seem that way.</p>
<p>There was much hand-wringing in the early years over Farcaster’s elusive PMF and qDAU. One misguided experiment circa 2025 was to turn the app into a social wallet. Co-founder  even boldly proclaimed that “social + trading is our DNA”. Instead, it turned out to be more like an extra chromosome of the 21st pair. Shitcoin gamblers, it turns out, do not make for interesting —or sticky— conversations. Nor is it sensible to make one’s financial activities socially transparent.</p>
<p>Shortly after, back when the U.S. dollar still held some monetary value, Merkle launched a USDC promotion offering 10% rewards on deposits up to $5,000. Farcaster’s TVL jumped by $9 million (about 1,800 users going all in) before angry Merkle investors lobbied  to stop squandering their money. Ten weeks later, both TVL and DAUs had returned to baseline — proving that temporary yield does not, in fact, drive retention (let alone qDAU).</p>
<p>There were even whispers of an acquisition by Coinbase, which would have crystallized Farcaster’s social-walletness once and for all. Thankfully, our valiant BDFLs Dan and Varun, in their impeccable ethics, declined easy riches in favor of a more noble long-term goal. In hindsight, they dodged a bullet: Coinbase, as we all know, has since rebranded as CompliFi, a fully KYC-ed L1 centralized blockchain that requires proof of paperwork for every transaction and takes eleven days to settle.</p>
<p>So what led to Farcaster’s resounding success? Internet scholars point to a handful of factors.</p>
<p>The first was Merkle’s decision to extend the Farcaster protocol’s FOSS philosophy to its client as well, upon realizing that a portable social graph is only useful if there’s somewhere else to port it to. The non-cosmetic components of the Farcaster app were open-sourced, triggering a Cambrian explosion of alt-clients, each catering to its own community: gamblers and geeks, nerds and nihilists, pundits and poets, and yes, even furries. The original Farcaster app became more akin to the Linux kernel, upon which enthusiasts built their equivalent of specialized distros. Merkle, in turn, kept curating the kernel’s core primitives through FIPs, for the benefit of all humankind.</p>
<p>The second factor was opening up the feed algorithm. Instead of a proprietary, one-size-fits-none solution, an executive call was made to modularize feed building. Users could now choose what they wanted to see by picking from an open marketplace of custom algos tuned to their favorite casters, political inclinations, and preferred themes. Reverse-chronological order and reply-bump visibility rapidly became popular options.</p>
<p>The third key factor was making channels first-class citizens, down to the protocol level. Rough were the early days; rumor has it that generative AI was discreetly called upon to prime the proverbial pump of empty channels with conversational liquidity. Whatever was used, worked. The UpCoin debacle led to a mass exodus of users from Reddit to Farcaster, where they found a familiar setup reminiscent of subreddits. The channel-first approach also dovetailed nicely with the new client diversity, with some specialized apps catering exclusively to one topic.</p>
<p>But beyond those technical decisions, what also mattered was how Farcaster’s early tensions were constructively resolved.</p>
<p>Borrowing ’s metaphor, one such tension lay between computer and casino user archetypes. The former came to Farcaster because they believed in building Web3 technology to empower people through anonymity, credible neutrality, decentralization, permissionlessness, and zero trust. The casino folks were more interested in games of engagement extraction and profit maximization. Instead of taking a moral stance for one over the other (the short-lived social wallet experiment of 2025 notwithstanding), our beloved BDFLs wisely allowed alt-clients to cater to both—with varying degrees of degeneracy.</p>
<p>Another notable tension was between OG users (i.e., anyone with an FID no greater than mine), who feared losing the town-hall feel of Farcaster’s early days to an eternal September of uncultured swine; and new users, who complained that the monolithic algo wasn’t giving them a fair chance at growing followers. That tension was amicably resolved by letting everyone choose what and who they wanted to see on their feeds. Instead of fighting a reactionary losing battle in defense of Farcaster’s singular cozy corner, the solution turned out to be a positive-sum replication of that coziness across every niche community that organically spawned along channel lines.</p>
<p>And this, my dear friends, is the story of how Dan and Varun left an oversized imprint on this planet. Not by playing the VC and founders’ short-term games, but by going beyond where Jack Dorsey left off — by channeling the spirits of Aaron Swartz and Satoshi Nakamoto, and by embracing the ethos of Richard Stallman and Linus Torvalds. It is no surprise, then, that they both featured on this year’s Time magazine’s Person of the Year cover — again.</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/18/the-year-2049/screenshot.png"
   type="image/png"
   length="90336"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/10/17/fc-2025-10-17-0xe9e10a9a/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/17/fc-2025-10-17-0xe9e10a9a/</guid>
      <pubDate>Fri, 17 Oct 2025 20:06:31 +0000</pubDate>
      <description>If Play Store blocks the app in some regions, how about Farcaster adding the android version of the app on @ethos dGEN App Store?</description>
      <content:encoded><![CDATA[
	
	<p>If Play Store blocks the app in some regions, how about Farcaster adding the android version of the app on @ethos dGEN App Store?</p>
<blockquote>
<p>PSA</p>
<p>Farcaster is adding more crypto functionality, and mobile app store policies in some regions don't allow crypto apps. Other popular wallets also have to follow these rules. A very small number of users will be affected by these changes.</p>
<p>If you are one of those users, the app will notify you and will let you export both your Farcaster and wallet recovery phrases.</p>
<p>--@dwr</p>
</blockquote>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/17/fc-2025-10-17-0xe9e10a9a/image01.jpg"
   type="image/jpeg"
   length="574917"/>

   <enclosure url="https://blog.vrypan.net/2025/10/17/fc-2025-10-17-0xe9e10a9a/image02.jpg"
   type="image/jpeg"
   length="437626"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/10/14/fc-2025-10-14-0x9649c2da/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/14/fc-2025-10-14-0x9649c2da/</guid>
      <pubDate>Tue, 14 Oct 2025 12:19:38 +0000</pubDate>
      <description>Got starship.rs to work the way I like it.</description>
      <content:encoded><![CDATA[
	
	<p>Got starship.rs to work the way I like it.</p>
<p><a href="https://starship.rs">https://starship.rs</a></p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/14/fc-2025-10-14-0x9649c2da/image01.jpg"
   type="image/jpeg"
   length="54865"/>

    </item>
    
    <item>
      <title>Blog Pagination: The Notebook Way</title>
      <link>https://blog.vrypan.net/2025/10/13/blog-pagination-notebook-way/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/13/blog-pagination-notebook-way/</guid>
      <pubDate>Mon, 13 Oct 2025 22:24:00 +0300</pubDate>
      <description>What if we treated a blog like a notebook, where page 1 stays page 1, and new posts add pages at the end?</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/10/13/blog-pagination-notebook-way/notebook.png">
        
	<p>When we refer to a blog's &quot;first page&quot;, we usually mean the first page visitors see—the homepage with
the latest posts. But what if we treated a blog like what it actually is: a notebook or diary?</p>
<p>In a physical notebook, page 1 contains your first entry. As you write more, you fill pages 2, 3, 4,
and so on. When someone wants to read it, they naturally start from page 1 or jump to the last page
for recent entries.</p>
<p>Traditional blog pagination works backwards because it was simpler for developers to write <code>SELECT * FROM posts ORDER BY dt DESC LIMIT 10</code>. But it creates a fundamental problem: <strong>page contents change
with every new post</strong>.</p>
<p>You can't say &quot;this post is on page 10&quot; because page 10 contains different posts after each publish.
This isn't just conceptually messy—it has real technical costs. Links to <code>/page/10</code> become
meaningless. Static site generators must rebuild and upload N index pages per post. Git histories
bloat with N changed files.</p>
<hr />
<h2>The Solution</h2>
<p>Treat your blog like a notebook with fixed pages:</p>
<ul>
<li>Page 1: posts 1-20</li>
<li>Page 2: posts 21-40</li>
<li>Page 3: posts 41-60</li>
</ul>
<p>Your homepage becomes the <strong>last</strong> page—the one you're currently writing.</p>
<p>To avoid a sparse final page, keep a buffer of 20-39 posts on the homepage. When you publish post
101, articles 81-100 stay on the homepage. Once you hit post 120, page 5 (posts 81-100) gets
finalized, and the cycle repeats.</p>
<p>This blog works this way. Visit <code>blog.vrypan.net</code>, and you land on page 138, because I've
been posting for years, and this is the page I'm currently writing on.</p>
<hr />
<p>Note: This is how pagination works on <a href="https://github.com/vrypan/bckt">bckt</a> since v0.5.2. Of course, if
you think this way of thinking will confuse your users, you don't have to expose it to them, and tell
them they are on page 100. You can show links to previous and next pages, just like they are used to.
But whne you post a new article, you wont have to re-upload or git commit 100 new index pages ;-)</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/13/blog-pagination-notebook-way/notebook.png"
   type="image/png"
   length="1455336"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/10/10/fc-2025-10-10-0xba3bf30d/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/10/fc-2025-10-10-0xba3bf30d/</guid>
      <pubDate>Fri, 10 Oct 2025 20:08:10 +0000</pubDate>
      <description>Nice, easy to use charting tool for the terminal: YouPlot https://github.com/red-data-tools/YouPlot</description>
      <content:encoded><![CDATA[
	
	<p>Nice, easy to use charting tool for the terminal: YouPlot
<a href="https://github.com/red-data-tools/YouPlot">https://github.com/red-data-tools/YouPlot</a></p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/10/fc-2025-10-10-0xba3bf30d/image01.jpg"
   type="image/jpeg"
   length="29825"/>

   <enclosure url="https://blog.vrypan.net/2025/10/10/fc-2025-10-10-0xba3bf30d/image02.jpg"
   type="image/jpeg"
   length="25385"/>

   <enclosure url="https://blog.vrypan.net/2025/10/10/fc-2025-10-10-0xba3bf30d/image03.jpg"
   type="image/jpeg"
   length="19607"/>

   <enclosure url="https://blog.vrypan.net/2025/10/10/fc-2025-10-10-0xba3bf30d/image04.jpg"
   type="image/jpeg"
   length="16622"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/10/08/fc-2025-10-08-0xbabc5d64/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/08/fc-2025-10-08-0xbabc5d64/</guid>
      <pubDate>Wed, 08 Oct 2025 21:38:25 +0000</pubDate>
      <description>The QNX Operating System: An amazing story of an OS that started 45 years ago. Today it's used by Boston Dynamics and SpaceX, among others.</description>
      <content:encoded><![CDATA[
	
	<p>The QNX Operating System: An amazing story of an OS that started 45 years ago. Today it's used by Boston Dynamics and SpaceX, among others.</p>
<p>Who can ignore this? 👇</p>
<blockquote>
<p>Versions 4.2, 4.22, and 4.24 all released in 1995. The final version 4 release was 4.25 in 1997. At least one QNX 4 installation ran for over 20 years without a reboot at the ESA. This was possible because peripherals could be hotswapped, drivers could be changed, and network nodes could be added or removed without bringing the system down.</p>
</blockquote>
<p><a href="https://www.abortretry.fail/p/the-qnx-operating-system">https://www.abortretry.fail/p/the-qnx-operating-system</a></p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/08/fc-2025-10-08-0xbabc5d64/image01.jpg"
   type="image/jpeg"
   length="543732"/>

   <enclosure url="https://blog.vrypan.net/2025/10/08/fc-2025-10-08-0xbabc5d64/image02.jpg"
   type="image/jpeg"
   length="274495"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/10/07/fc-2025-10-07-0xce9257b1/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/07/fc-2025-10-07-0xce9257b1/</guid>
      <pubDate>Tue, 07 Oct 2025 23:14:52 +0000</pubDate>
      <description>I found this gem: The Original Illustrations of the Voyages Extraordinaires by Jules Verne. https://jv.gilead.org.il/rpaul/</description>
      <content:encoded><![CDATA[
	
	<p>I found this gem: The Original Illustrations of the Voyages Extraordinaires by Jules Verne. <a href="https://jv.gilead.org.il/rpaul/">https://jv.gilead.org.il/rpaul/</a></p>
<p>The first Jules Vernes books I read as a kid were my mother's, who had read them as a kid too. And they had these amazing illustrations that guided (not too much, just enough) my imagination as it recreated Verne's amazing worlds.</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/07/fc-2025-10-07-0xce9257b1/image01.jpg"
   type="image/jpeg"
   length="132936"/>

   <enclosure url="https://blog.vrypan.net/2025/10/07/fc-2025-10-07-0xce9257b1/image02.jpg"
   type="image/jpeg"
   length="93912"/>

   <enclosure url="https://blog.vrypan.net/2025/10/07/fc-2025-10-07-0xce9257b1/image03.jpg"
   type="image/jpeg"
   length="45311"/>

   <enclosure url="https://blog.vrypan.net/2025/10/07/fc-2025-10-07-0xce9257b1/image04.jpg"
   type="image/jpeg"
   length="155792"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/10/07/fc-2025-10-07-0xff16e2a9/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/07/fc-2025-10-07-0xff16e2a9/</guid>
      <pubDate>Tue, 07 Oct 2025 21:28:21 +0000</pubDate>
      <description>This chart shows the number of casts I’ve posted each month since I first joined, in July 2022.</description>
      <content:encoded><![CDATA[
	
	<p>This chart shows the number of casts I’ve posted each month since I first joined, in July 2022.</p>
<p>What happened in August 2023? I started running my own hub, and in October, Farcaster opened signups to everyone (until then, it was invite-only).</p>
<p>That p2p version of the protocol, with all its flaws, is what really got me passionate about Farcaster. I ran my own hub, and it had the same privileges like any other hub. But if I discovered Farcaster today, would it feel as exciting as the 2023.09 version? I’m not so sure.</p>
<p>I was thinking about this while watching this presentation about the “ATProto ethos.” <a href="https://www.youtube.com/watch?v=1A-0k58TfPo">https://www.youtube.com/watch?v=1A-0k58TfPo</a></p>
<p>We used to have these kinds of discussions here, too. Not so much anymore. The Farcaster ethos has become &quot;DAU growth&quot;, there is no passion about extensibility, data ownership, censorship resistance. I don't feel there is any vision about the protocol, how they want it to look in one, two, five years, just a list of feature requests, prioritized according to some DAU metric.</p>
<p>Yes, I know, &quot;none of these matter if we don't have millions of DAU&quot;.</p>
<p>Like I said: &quot;DAU growth&quot;.</p>
<p>I also know I'm a niche audience, you can't grow to millions of users like me. Oh, well..</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/07/fc-2025-10-07-0xff16e2a9/image01.jpg"
   type="image/jpeg"
   length="120918"/>

    </item>
    
  </channel>
</rss>
