NixOS and Actually Portable Executables

Posted on January 15, 2025 by Jack Kelly
Tags: nix, cosmopolitan, coding

I’ve been very impressed by the Cosmopolitan Libc project and the αcτµαlly pδrταblε εxεcµταblε file format that makes it all possible. Building a crazy polyglot binary that works on two architectures and half-a-dozen operating systems is one thing, but Mozilla’s Llamafile project showed that APEs were more than just a cool hack: it’s stunning that I just download a reasonably smart LLM to my computer, chmod +x it, and begin a conversation. LLM use-cases aside, single-file dependency-free programs that work basically anywhere are just a great thing to be able to stick on a USB stick.

But APEs have been a little finicky for me. I run NixOS as my primary operating system, and sometimes an APE will refuse to launch, or I’ll need to pass --assimilate to it and permanently turn it into an x86-64 Linux binary before it’ll work.

The Cosmopolitan project, of course, has a couple of answers ready. One is to install a system-wide APE loader separate from any one binary and register it with binfmt_misc; the other is to patch the kernel so it can natively detect APEs. I don’t want to wait for a full kernel compile each time I need to update, so until the patch lands in mainline binfmt_misc is the way to go.

I have set up a Nix Flake at https://git.sr.ht/~jack/cosmo.nix to hold my experiments joining the Nix and Cosmopolitan universes. For now, it has convenient NixOS options to register the APE loader with binfmt_misc:`

{
  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11";

    # Import cosmo.nix and plumb our nixpkgs rev through it
    cosmo-nix = {
      url = "sourcehut:~jack/cosmo.nix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = inputs@{ nixpkgs }: {
    nixosConfigurations.myMachine = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        # Include the cosmo.nix module...
        inputs.cosmo-nix.nixosModules.default

        # ...and register the ape-loader with binfmt_misc
        { programs.ape-loader.binfmt = true; }

        # Your other NixOS config here.
      ];
    }
  }
}

Not bad for an evening’s hacking! I hope to take it further at some point in the future: I’d like to build the loader itself from a known bootstrap path rather than fetching a binary, and I’d especially love to be able to do the same with Cosmopolitan Libc and cosmocc. I’m a big fan of bootstrappable builds, and reliable building of ultraportable binaries from a documented bootstrap path would be an incredibly cool achievement. I currently get so much useful stuff out of nix develop — all my build dependencies, pre-commit hooks, useful CI targets, and more — and I have projects in mind where I want Cosmopolitan Libc to be a “tier 1” platform. Nix-based access to a cosmocc toolchain and all cosmocc-built build dependencies would make that so much easier.

A Dictionary of Single-Letter Variable Names

Posted on October 12, 2024 by Jack Kelly
Tags: haskell, coding

Haskell’s expressive type system means that type signatures can carry a lot of information. Haskell’s polymorphism means that you sometimes write functions that work across an enormous range of types, and are left wondering “what do I actually call my variables?”. It is often the case that there’s nothing to say beyond “this variable is a Functor”, or “this variable is a monadic action”, and so a single-letter variable name is appropriate. An unofficial and largely undocumented convention has emerged around these variable names, and so I wanted to write them all down in one place.

It should go without saying that single-letter variable names are not always the answer. Like point-free style, it sometimes obscures more than it helps and people get carried away with it. But when you have a highly polymorphic function and no good words to use, choosing the right letter can convey a surprising amount of meaning.

This dictionary is not and cannot be exhaustive. Variable naming often relies on context to convey information, and shorter variable names should only be used when they make sense in context. That context could be:

With the warnings out of the way, the dictionary is after the jump. The bulk of the dictionary documents type variables, where overly long variable names can blow out complicated type signatures. Important value-level variable names are also documented, and are explicitly labelled as such.

Read more...

Travel Tip: USB-C Desktop Chargers

Posted on October 6, 2024 by Jack Kelly
Tags: travel

I have travelled a lot this year, and after yet another trip where I lugged too many things around, I’ve been thinking about ways to cut back. The classic guide for this is onebag.com, which covers a very interesting mix of techniques and some carefully-chosen lightweight gear that will take you to the farthest corners of the map. Perma-nomad Vitalik Buterin has his own take on living out of a 40L backpack; one of his key points is to run everything you can off of USB-C. The benefits should be obvious: you cut down the number of charging cables you need to carry and your power bank can recharge any of your devices. While I’m a bit of a luddite, I can see a lot of people travelling with at least a laptop and phone, and possibly also a tablet, earbuds, and/or a smartwatch, all of which need power.

Vitalik’s guide mentions a USB-C “wall wart” charger that he uses to power his stuff. I disagree with this choice, at least for international travel: I think you want a desktop USB-C charger that takes an IEC C7 (“figure 8”) cable.

I’m not aware of any good articles that spell out the “desktop charger + replaceable cable” trick and how to actually find a suitable one, so a full explanation, research procedure, and some tentative recommendations are spelled out in laborious detail after the jump.

Read more...

I'm Funding Ladybird Because I Can't Fund Firefox

Posted on July 6, 2024 by Jack Kelly
Tags: rants, web

I’ve been meaning to write this one for a while, but the announcement of the Ladybird Browser Initiative makes now a particularly good time.

TL;DR: Chrome is eating the web. I have wanted to help fund a serious alternative browser for quite some time, and while Firefox remains the largest potential alternative, Mozilla has never let me. Since I can’t fund Firefox, I’m going to show there’s money in user-funded web browsers by funding Ladybird instead. You should too.

Read more...

Why `streaming` Is My Favourite Haskell Streaming Library

Posted on April 13, 2024 by Jack Kelly
Tags: coding, haskell

It’s really easy to misuse lazy I/O (e.g., hGetContents) in nontrivial Haskell programs. You can accidentally close a Handle before the computation which reads from it has been forced, and it’s hard to predict exactly when data will be produced or consumed by IO actions. Streaming libraries in Haskell avoid these problems by explicitly interleaving the yielding of data and execution of effects, as well as helping control the memory usage of a program by limiting the amount of data “in flight”.

A number of veteran Haskellers have built streaming libraries, and off the top of my head I’m aware of conduit, io-streams, iteratee, machines, pipes, streaming, and streamly. Of those, I think conduit, pipes, streaming, and streamly are the most commonly used ones today. It can be hard to know which library to choose when there’s so many options, so here is my heuristic:

  1. If you’re doing simple streaming (e.g., from a network connection straight into a file), use whatever your library uses (usually conduit); or
  2. If you’re doing anything more complicated, or you’re doing greenfield work, use streaming.

I’ll explain why after the jump.

Read more...
All Posts | RSS | Atom
Copyright © 2025 Jack Kelly
Site generated by Hakyll (source)