<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: minerobber</title>
    <description>The latest articles on DEV Community by minerobber (@minerobber9000).</description>
    <link>https://dev.to/minerobber9000</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F273346%2F5f36e0cd-dd58-4dc3-9b86-c7b050315c89.png</url>
      <title>DEV Community: minerobber</title>
      <link>https://dev.to/minerobber9000</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/minerobber9000"/>
    <language>en</language>
    <item>
      <title>How I made a barebones Gemini client for the Mini Micro</title>
      <dc:creator>minerobber</dc:creator>
      <pubDate>Fri, 23 Oct 2026 19:35:03 +0000</pubDate>
      <link>https://dev.to/minerobber9000/how-i-made-a-barebones-gemini-client-for-the-mini-micro-2h3p</link>
      <guid>https://dev.to/minerobber9000/how-i-made-a-barebones-gemini-client-for-the-mini-micro-2h3p</guid>
      <description>&lt;p&gt;I recently read Joe Strout's article on &lt;a href="https://dev.to/joestrout/a-multiplayer-network-starter-for-mini-micro-3kpa"&gt;a multiplayer network starter for Mini Micro&lt;/a&gt;, and it reminded me of a project I finished up last month, so I figured I'd write that project up, in a similar style to my last dev.to article on &lt;a href="https://dev.to/minerobber9000/porting-miniscript-to-cosmopolitan-libc-4jp3"&gt;porting MiniScript to Cosmopolitan Libc&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part the First: "What does the title mean?"
&lt;/h2&gt;

&lt;p&gt;To make the couple paragraphs I spent on MiniScript in my last article into one shorter one, MiniScript was invented by Joe Strout in 2016 and released in 2017 as a new beginner language for teaching kids how to code. MiniScript's language reference fits on &lt;a href="https://miniscript.org/files/MiniScript-QuickRef.pdf" rel="noopener noreferrer"&gt;one side of a sheet of US Letter paper&lt;/a&gt; and &lt;a href="https://miniscript.org/files/MiniMicro-CheatSheet.pdf" rel="noopener noreferrer"&gt;the reference for Mini Micro&lt;/a&gt;, the "killer app" of MiniScript so to speak, only takes 3 more pages (the last page of that PDF being the one-pager for MiniScript itself).&lt;/p&gt;

&lt;p&gt;Gemini, on the other hand, &lt;a href="https://geminiprotocol.net/" rel="noopener noreferrer"&gt;describes itself as follows&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Gemini is a new internet technology supporting an electronic library of interconnected text documents. That's not a new idea, but it's not old fashioned either. It's timeless, and deserves tools which treat it as a first class concept, not a vestigial corner case. Gemini isn't about innovation or disruption, it's about providing some respite for those who feel the internet has been disrupted enough already. We're not out to change the world or destroy other technologies. We are out to build a lightweight online space where documents are just documents, in the interests of every reader's privacy, attention and bandwidth.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A request in Gemini is a URL followed by a CRLF--nothing more, nothing less. A response is a 2-digit status code, a "meta" line, and then the response body. It's a very simple protocol by design; there are no ways to track someone unless they want to be tracked--Gemini uses TLS client certificates for cases where you'd &lt;em&gt;want&lt;/em&gt; to have an account-like system--and no ways to add such a system without breaking compatibility with older clients.&lt;/p&gt;

&lt;p&gt;A simple programming language, and a simple network protocol... seems like a match made in heaven!&lt;/p&gt;

&lt;h2&gt;
  
  
  Part the Second: "What did you accomplish?"
&lt;/h2&gt;

&lt;p&gt;Using a &lt;a href="https://github.com/MineRobber9000/geminimicro/blob/trunk/proxy/proxy.py" rel="noopener noreferrer"&gt;simple proxy server&lt;/a&gt; alongside a &lt;a href="https://github.com/MineRobber9000/geminimicro/tree/trunk/minimicro" rel="noopener noreferrer"&gt;client running in Mini Micro&lt;/a&gt;, you can browse Gemini space using your Mini Micro. There &lt;em&gt;are&lt;/em&gt; some limitations (only gemtext and images are properly displayed, there's no client certificate support nor server certificate pinning), but enough is implemented for a quick browse of basic Geminispace.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part the Third: "How did you do it?"
&lt;/h2&gt;

&lt;p&gt;When you type in a Gemini URL or follow a link, Mini Micro runs &lt;code&gt;startup.ms&lt;/code&gt;-- the same file Mini Micro would naturally run on boot. This runs a small code snippet which requests the URL from the proxy server you run alongside it and then dispatches to another script which handles the specific response (displaying the response for &lt;code&gt;20&lt;/code&gt;, or showing error screens for &lt;code&gt;4x&lt;/code&gt;, &lt;code&gt;5x&lt;/code&gt;, or &lt;code&gt;6x&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Part the Third and a Half: "Why use a proxy server?"
&lt;/h3&gt;

&lt;p&gt;The Gemini protocol is, as I said above, a simple protocol. It runs on raw sockets encrypted with TLS. Unfortunately, Mini Micro doesn't provide support for raw sockets, let alone wrapping them with TLS.&lt;/p&gt;

&lt;p&gt;What Mini Micro &lt;em&gt;does&lt;/em&gt; support is synchronous HTTP requests. So the fix is simple: write a simple Python script to take HTTP requests and convert them to Gemini.&lt;/p&gt;

&lt;p&gt;The proxy, implemented in less than 100 lines of code, parses the gemini URL from the HTTP request path, makes the Gemini request, and then returns to Mini Micro a binary blob containing the canonical URL, the Gemini header line (status and meta), and the body of the response.&lt;/p&gt;

&lt;p&gt;The reason we have to return a binary blob with all of this data is because Mini Micro's HTTP support is admittedly quite limited. All it supports is retrieving some resource from a remote server, and all you get back in your program is either the resource (interpreted as Mini Micro sees fit), or &lt;code&gt;null&lt;/code&gt;, if there was some error communicating between Mini Micro and the server. As such, the proxy returns the binary blob, which Mini Micro interprets as a &lt;code&gt;RawData&lt;/code&gt;, an object specifically made for manipulating binary data, and we can parse the separate fields from it ourselves.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part the Third and Two Thirds: "But what about the &lt;code&gt;chrome://&lt;/code&gt; URL in the cover image?"
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;chrome://&lt;/code&gt; pages don't actually trigger a request on the proxy; instead, they run a small MiniScript function, which either returns a local file (in the case of &lt;code&gt;chrome://homepage/*&lt;/code&gt;) or does some extra logic  internally (in the case of &lt;code&gt;chrome://bookmarks/*&lt;/code&gt;). This lets the internal logic stay the same; the same &lt;code&gt;utils.request&lt;/code&gt; function gets called whether you're passing a Gemini URL or a &lt;code&gt;chrome://&lt;/code&gt; URL, and the response from that function gets handled in the same way.&lt;/p&gt;

&lt;p&gt;This also has the secondary benefit of not immediately dropping a new user into an error screen if they aren't running the proxy, since the homepage is implemented as a &lt;code&gt;chrome://&lt;/code&gt; URL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part the Fourth: "Why is it interesting or useful?"
&lt;/h2&gt;

&lt;p&gt;To be honest, in the grand scheme of things, it probably isn't. MiniScript is pretty niche, and so is Gemini. But for the handful of people who like both--like myself--it's neat to be able to combine them.&lt;/p&gt;

</description>
      <category>minimicro</category>
      <category>miniscript</category>
    </item>
    <item>
      <title>Porting MiniScript to Cosmopolitan Libc</title>
      <dc:creator>minerobber</dc:creator>
      <pubDate>Tue, 23 Sep 2025 01:12:53 +0000</pubDate>
      <link>https://dev.to/minerobber9000/porting-miniscript-to-cosmopolitan-libc-4jp3</link>
      <guid>https://dev.to/minerobber9000/porting-miniscript-to-cosmopolitan-libc-4jp3</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;There is a &lt;em&gt;lot&lt;/em&gt; to be written up. Starting with "wtf is cosmopolitan?" &lt;strong&gt;If you leave this now as it is, it will be essentially wasted effort (except for any enjoyment you got out of doing it) — I barely understand what you did, how you did it, and the implications of it, and nobody else is going to get even that far.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
It may seem trivial to you, because you already understand all that. 99.9999% of people don't.&lt;br&gt;&lt;br&gt;
It doesn't need to be complicated. &lt;strong&gt;Just explain (1) a little background, (2) what you accomplished, (3) how you did it, and (4) why it is interesting/useful.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Then somebody else can come along and appreciate what you've done! 💪&lt;br&gt;&lt;br&gt;
~ &lt;em&gt;Joe Strout, August 27, 2025 (bold emphasis mine)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Alright!&lt;/p&gt;

&lt;h2&gt;
  
  
  Part the First: "a little background"
&lt;/h2&gt;

&lt;p&gt;Firstly, what is MiniScript, and who is Joe Strout? MiniScript is a programming language that was created in 2016 (first released in 2017) by Joe Strout as an alternative to other programming languages that were/are typically used to teach kids how to program. As the &lt;a href="https://miniscript.org/" rel="noopener noreferrer"&gt;MiniScript homepage&lt;/a&gt; states:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is the home page for &lt;strong&gt;MiniScript&lt;/strong&gt;, a clean, simple language for embedding or learning to program.&lt;/p&gt;

&lt;p&gt;MiniScript is &lt;em&gt;modern&lt;/em&gt;, &lt;em&gt;elegant&lt;/em&gt;, &lt;em&gt;easy to learn&lt;/em&gt;, and &lt;em&gt;easy to embed&lt;/em&gt; in your own C# or C++ projects. (And elsewhere — there are unofficial ports to TypeScript, Kotlin, and more.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;My favorite thing about MiniScript is that a decently full-featured summary of the entire language &lt;a href="https://miniscript.org/files/MiniScript-QuickRef.pdf" rel="noopener noreferrer"&gt;fits on one side of a sheet of letter paper&lt;/a&gt;. The cheat sheet for Mini Micro, a self-described "neo-retro virtual computer" based around MiniScript, only takes &lt;a href="https://miniscript.org/files/MiniMicro-CheatSheet.pdf" rel="noopener noreferrer"&gt;3 more pages of letter paper&lt;/a&gt; to cover pretty much every API that it has (except the ones implemented in MiniScript, which you can read the code of yourself; the fourth page in that PDF, fittingly, is the one-page cheat sheet for the language itself).&lt;/p&gt;

&lt;p&gt;Secondly, as Joe put it, "wtf is cosmopolitan?" In the words of creator Justine Tunney:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://justine.lol/cosmopolitan/index.html" rel="noopener noreferrer"&gt;Cosmopolitan Libc&lt;/a&gt; makes C/C++ a build-once run-anywhere language, like Java, except it doesn't need an interpreter or virtual machine. Instead, it reconfigures stock GCC and Clang to output a POSIX-approved polyglot format that runs natively on Linux + Mac + Windows + FreeBSD + OpenBSD 7.3 + NetBSD + BIOS with the best possible performance and the tiniest footprint imaginable.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In layman's terms, Cosmopolitan takes normal C or C++ code and compiles it into a special file. Windows sees it as a normal .EXE file, the other operating systems see it as a shell script (which does some magic to extract the code into a format the operating system in question understands), and in addition to all of that, it's also a .ZIP file, which contains all of the files it needs to be truly portable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part the Second: "what you accomplished"
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/MineRobber9000/files/raw/refs/heads/master/miniscript.com" rel="noopener noreferrer"&gt;This&lt;/a&gt; is the MiniScript C++ command-line interpreter (SHA256 hash: &lt;code&gt;bd802c2be2320739691920f13974f6a5dc950fade387ded8b15b8374e9aa95eb&lt;/code&gt;). You can run it on your computer (your antivirus might complain, and/or you may need to do some tricks to make it work if you're on a Mac, but by and large it should Just Work). It contains all of the libraries that "come with" the command-line interpreter (&lt;code&gt;dateTime&lt;/code&gt;, &lt;code&gt;grfon&lt;/code&gt;, &lt;code&gt;importUtil&lt;/code&gt;, &lt;code&gt;json&lt;/code&gt;, &lt;code&gt;listUtil&lt;/code&gt;, &lt;code&gt;mapUtil&lt;/code&gt;, &lt;code&gt;mathUtil&lt;/code&gt;, &lt;code&gt;matrixUtil&lt;/code&gt;, &lt;code&gt;qa&lt;/code&gt;, &lt;code&gt;stringUtil&lt;/code&gt;, &lt;code&gt;tsv&lt;/code&gt;, and &lt;code&gt;vt&lt;/code&gt;) inside the executable (this is where the .ZIP file part above comes in handy).&lt;/p&gt;

&lt;p&gt;If you write a script with it and want to share that script as a self-contained executable in its own right, the steps are simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Copy &lt;code&gt;miniscript.com&lt;/code&gt; and rename the copy to something like &lt;code&gt;MyAwesomeProgram.com&lt;/code&gt; or whatever you want (it only really needs a file extension if you're on Windows).&lt;/li&gt;
&lt;li&gt;Change the file extension of &lt;code&gt;MyAwesomeProgram.com&lt;/code&gt; to &lt;code&gt;.zip&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Copy your script (and any libraries you &lt;code&gt;import&lt;/code&gt;ed) into the &lt;code&gt;.zip&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Write a &lt;code&gt;.args&lt;/code&gt; file containing the filename of your script preceded by &lt;code&gt;/zip/&lt;/code&gt; (so &lt;code&gt;MyAwesomeProgram.ms&lt;/code&gt; would be put in there as &lt;code&gt;/zip/MyAwesomeProgram.ms&lt;/code&gt;), and place that in the &lt;code&gt;.zip&lt;/code&gt; file as well.&lt;/li&gt;
&lt;li&gt;Finally, change the file extension back to &lt;code&gt;.com&lt;/code&gt; (or remove it if you don't need it).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, when you run &lt;code&gt;MyAwesomeProgram.com&lt;/code&gt;, it should run your script!&lt;/p&gt;

&lt;h2&gt;
  
  
  Part the Third: "how you did it"
&lt;/h2&gt;

&lt;p&gt;Well, first, compiling a cmake project like MiniScript using Cosmopolitan's "cosmocc" compiler has been done before; I personally followed (and suggest following to anyone doing something similar) &lt;a href="https://jcbhmr.com/2024/07/22/cosmocc-cmake/" rel="noopener noreferrer"&gt;these instructions&lt;/a&gt; by Jacob Hummer. I &lt;em&gt;did&lt;/em&gt; have to modify MiniScript's &lt;code&gt;whereami.c&lt;/code&gt; to properly handle Cosmopolitan as a platform, but that was &lt;a href="https://github.com/MineRobber9000/miniscript/commit/555f9b6" rel="noopener noreferrer"&gt;really easy&lt;/a&gt; and basically amounted to making a WAI-shaped wrapper for the Cosmopolitan function &lt;code&gt;GetProgramExecutableName&lt;/code&gt; (after I was told that function existed). Doing just that is enough to get a functional, if odd, MiniScript install; it says it's running on Linux, for some reason, and it's missing a lot of features common to Cosmopolitan projects, like support for &lt;code&gt;.args&lt;/code&gt;, use of storing files in the ZIP, etc.&lt;/p&gt;

&lt;p&gt;Luckily, these features are somewhat easy to add. In the case of "it says it's a command line interpreter for Linux", Linux is just what it defaults to if it doesn't think it's running on something else, so correctly reporting ourselves as a Cosmopolitan interpreter is as easy as just adding a case for &lt;code&gt;__COSMOPOLITAN__&lt;/code&gt;. Storing files in the .ZIP portion of the executable ("ZipFS" in Cosmopolitan parlance) is automatically supported by the runtime, so we just need to tell MiniScript to go look there; in &lt;a href="https://github.com/JoeStrout/miniscript/commit/af47ff875cd60f537669fa8c7ab8c0ee7bf58d40#diff-f6afe422271be6ba637a3e14d46eb91028c5a5c12dc159c1a47a5556fc98540cR20-R26" rel="noopener noreferrer"&gt;my actual implementation&lt;/a&gt; I moved the definition of the default import path into &lt;code&gt;ShellIntrinsics.h&lt;/code&gt;, so I could add &lt;code&gt;/zip/lib&lt;/code&gt; to the end if and only if we were compiling for Cosmopolitan. As for &lt;code&gt;.args&lt;/code&gt;, the function in Cosmopolitan that implements this is called &lt;code&gt;cosmo_args&lt;/code&gt;, so it's just a matter of calling that before we do anything with arguments. I did a little fancy stuff so that &lt;code&gt;argv&lt;/code&gt; could be defined as &lt;code&gt;const&lt;/code&gt; when not compiling for Cosmopolitan (no reason not to, and that's what it was before I got to the code), but not be defined as &lt;code&gt;const&lt;/code&gt; when we were compiling for Cosmopolitan (since &lt;code&gt;cosmo_args&lt;/code&gt;, by definition, modifies &lt;code&gt;argv&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Part the Fourth: "why it is interesting/useful"
&lt;/h2&gt;

&lt;p&gt;With this finished, MiniScript joins the ranks of programming languages like Janet, Lua(JIT), Perl, PHP, Python, and Tcl in having been ported to Cosmopolitan. The idea of being able to package everything you need to write command-line MiniScript programs into a single file--and then package that program as a single-file click-it-and-run executable of its own--well...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnmjdqmq2d78xk9whr08z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnmjdqmq2d78xk9whr08z.png" alt="" width="790" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>miniscript</category>
    </item>
  </channel>
</rss>
