Browsher and Namespaces [weekly-2026-w33]
- August 17, 2026
- Patrick Ferris
The work presented constitutes a good bit more than a weeks worth of work. That being said, let's dive in.
Browsher [browsher]
- August 17, 2026
- Patrick Ferris
After a week or two of abstracting the internals of Merry, I finally got a shell running in the browser. You can have a play with it here:
https://patrick.sirref.org/msh
The final hurdle was providing an abstract interface to file handles. Eio, the library that so far has enabled much of the OS abstraction, doesn't have a particularly good cross-platform file descriptor API. Eio_unix does extend sources and sinks with the Unix_fd tag, but there is no Eio.Fd.dup2 that provides a platform-agnostic API for file handle manipulation. Even if it did, a POSIX shell does a fair amount of assuming that your file handles are integers which might prove tricky on Windows.
The shell in the browser completely reuses the logic of Merry. It also links in a browser-aware subpackage of bruit (the OCaml port of linenoise I wrote) and a few, half-baked POSIX utilities I wrote (like ls and cat). But you can at least run something like:
$ echo "hello" > hello.txt
$ ls -la .
$ cat < hello.txt
Being able to, in some sense, run a shell anywhere is actually quite an attractive proposition. Shells, with all of their wonderful footguns, are still a reliable and familiar tool for interacting with a running system. I'm interested in the idea of running shells in more exotic deployments (e.g., unikernels) where it becomes an interface for dynamical reconfiguration or a tool for debugging.
Updates on Eio_mem
- August 17, 2026
- Patrick Ferris
At the heart of browsher is Eio_mem (an in-memory filesystem for Eio). The Eio_mem API now comes with (and exposes) a number of file descriptor operations:
val pipe : Eio.Switch.t -> Fd.t * Fd.t
val dup : sw:Eio.Switch.t -> Fd.t -> Fd.t
val dup2 : sw:Eio.Switch.t -> src:Fd.t -> tgt:Fd.t -> unit
I was happy to see Eio_mem getting some use in Thomas G.'s fork eio-fs where he was able to use it for chaos engineering.
Namespaces [namespace-musings]
- August 17, 2026
- Patrick Ferris
I spent a few days recently trying to come up with some formalism for the notion of names, namespaces and name resolution.
On the surface, it seems bigraphs might be a fruitful approach. The orthogonal treatment of locality and connectivity maps fairly well onto name structure (e.g, Module.X.foo, /foo/bar/hello.txt or foo.example.org) and redirection (e.g., symlinks or CNAMEs). Bigraph reaction rules could then model name resolution. A resolution process can move through the hierarchical name structure and across links at which point you might have some interesting properties to prove or check about a particular namespace system. Additionally, namespaces and resolution mechanism might compose in different ways and this might be worth formalising and comparing.
I didn't get much further than modelling some bits of a filesystem in BigraphER.
# filesystem
ctrl Dir = 0;
atomic ctrl File = 1;
atomic ctrl SymLink = 2;
# Query -- the thing that gets resolved.
atomic ctrl Q = 1;
# Reaction Rules
react resolve_symlink =
Q{x} | SymLink{x, y} --> Q{y} | SymLink{x, y};
# Initial State
big s0 =
Dir.
(SymLink{sym_a, file_a}
|
Q{sym_a}
|
File{file_a}
);
# Bigraphical Reactive System
begin brs
init s0;
rules = [ {resolve_symlink} ];
endResulting in these two transition states.
Bear in mind this was just a quick experiment. The first bigraph shows our query at sym_a and the second bigraph (using the resolve_symlink reduction rule) shows the query at file_a. All of this takes places within Dir. It seems that BigraphER represents the tree structure graphically with black arrows (rather than spatial containment).
Papers
- August 17, 2026
- Patrick Ferris
TODOs
- August 17, 2026
- Patrick Ferris
Over the next week, I hope to finish up a first draft of the aforementioned paper. I also want to publish a backlog of packages I have for OCaml: bruit, ocaml-bibtex, a fresh cut of Graft etc.
Ramblings
- August 17, 2026
- Patrick Ferris
I had some half-formed thoughts lying around in my forest, so I thought I might include those here:
Boilerplate [on-boilerplate]
- August 11, 2026
- Patrick Ferris
The word boilerplate gained popularity as a colloquialism used by newspaper and magazine editors for pre-prepared editorials and stories that were syndicated across the US. In effect, boilerplates were news stamps that could produce identical content.
I have been thinking about the nature of boilerplate code. How is it similar or different to boilerplate in its original meaning.
Distinguishing true boilerplate code from code that feels repetitive or boring to write is, I think, important. Argument parsing falls into this category quite well. Consider the following flag I added to Merry's set built-in.
let all_export =
let doc = "Export all variables, like -o allexport." in
Arg.(value & flag & info [ "a" ] ~docv:"ALLEXPORT" ~doc)
It uses cmdliner to define a new -a flag that will, in effect, make all variable definitions act like the export built-in. LLMs have been praised for their ability to do this specific task in OCaml.
What exactly is boilerplate about this code snippet? It seems to me that there is some sort of ceremony to defining a flag. There is boilerplate in the structure with more meaningful content threaded through. Below, is the example reduced to just the boilerplate replacing the for more meaningful parts with Merlin's typed holes: _.
let all_export =
let doc = _ in
Arg.(value & flag & info [ _ ] ~docv:_ ~doc)
Arguably the use of flag is quite important too as that is where the magic happens if you want an optional argument, or a positional one etc. As a thought experiment, having agents deliver fill-in-the-blanks style code might be quite useful. In a type system that can support holes (e.g. like in OCaml or Hazel) it becomes a more pleasant exercise, but helps keep you in the loop. I, myself, do not use any AI in the code I write; so I admit that I am pretty far from the problem.
The problem I have with this approach is that it is fairly easy to automate in a predictable and easy way! I just added a snippet subcommand to octx, but you could easily wrap this up in whatever your editor of choice is.
$ octx snippet cmdliner-flag let cmdliner_flag = let doc = _ in Arg.(value & flag & info [ _ ] ~docv:_ ~doc)
The more I think on this problem the harder I find good uses for LLMs besides churning out vasts amount of end-to-end code; something I am personally not that interested in doing. It seems to me, to reap the benefits of LLMs, one must relinquish a certain amount of agency; anything less, and you could easily replace its usage with a cheaper, more predictable tool.