Inferno Shell
The command language of Bell Labs' Inferno operating system - a tiny rc-inspired shell, rewritten by Roger Peppé at Vita Nuova around 2000, that keeps almost nothing built in and instead loads its programming constructs as modules running on the Dis virtual machine.
Created by Roger Peppé (the modern programmable sh, at Vita Nuova, circa 2000); the original minimal Inferno shell came from the Inferno team at Bell Labs (Sean Dorward, Rob Pike, David Presotto, Dennis Ritchie, Howard Trickey, and Phil Winterbottom created the Inferno system)
The Inferno Shell (invoked as sh) is the command language of Inferno, the distributed operating system created at Bell Labs in the mid-1990s by the team behind Plan 9. On the surface it looks like a compact cousin of Plan 9’s rc: pipelines, flat word lists, `{...} command substitution. Underneath, it is one of the most unusual shells ever shipped: it compiles to bytecode for Inferno’s Dis virtual machine, treats {...} command blocks as first-class values, and keeps almost nothing built in - even if, while, and for live in a loadable module. Its author, Roger Peppé, summarized the design plainly in his paper The Inferno Shell, describing a shell built around “Inferno’s dynamically loaded modules, which it uses for much of the functionality traditionally built in to the shell.”
History and origins
Inferno grew out of Bell Labs’ Computing Science Research Center around 1995, created by Sean Dorward, Rob Pike, David Presotto, Dennis Ritchie, Howard Trickey, and Phil Winterbottom as a compact distributed operating system for networked devices. Its existence was revealed by Ritchie in early 1996, it was presented publicly that year as a competitor to Java’s vision of portable network computing, and Lucent Technologies released Inferno 1.0 commercially in 1997. Everything in Inferno runs on the Dis virtual machine and is written in Limbo, a type-safe, garbage-collected language with channels - and, in keeping with the Divine Comedy naming scheme (Dis, Limbo, the Styx protocol), the shell is no exception.
The shell described on this page is actually the second generation. Inferno’s original sh was a small, deliberately non-programmable command interpreter - a single Limbo source file of a few hundred lines - and Second Edition (1999) supplemented it with mash, a programmable shell by Bruce Ellis. After Lucent’s Inferno Business Unit folded in 2000 and the system passed to Vita Nuova Holdings in York, England, Roger Peppé wrote a new shell that aimed to combine rc’s ergonomics with Inferno’s module system. His paper describing it was online by December 2000, and the shell shipped with Inferno Third Edition in June 2001. The old minimal shell survives in the modern distribution as tiny/sh, a reduced interface for memory-constrained devices - so Fourth Edition Inferno actually carries three shells, with Peppé’s sh as the standard one.
Peppé was candid about the lineage in his Credits: the shell “owes its largest debt to rc,” Tom Duff’s Plan 9 shell, which supplies “almost all of the syntax and most of the semantics”; the grammar came from Byron Rakitzis’s Unix reimplementation of rc; the blocks-as-values idea and the if syntax came from Paul Haahr’s es; and the load command, the "{} syntax, and <> redirection came from Ellis’s mash. When in doubt, he wrote, he copied rc’s behaviour.
Design philosophy: a shell made of modules
The Inferno shell’s defining idea is radical minimalism enforced by the platform. In Inferno, external commands are not executables in the Unix sense - they are Limbo modules compiled to Dis bytecode, loaded from /dis and run inside the same virtual machine. Even echo is an external module. The shell extends this idea inward: only a handful of commands (load, loaded, unload, run, exit, whatis, builtin) are truly built in. Everything else arrives via load, which pulls in Dis modules implementing the shell’s Shellbuiltin interface:
stdsupplies the programming vocabulary:if,while,for,and,or,raise,rescuefor exception handling, and substitution operators like${hd},${tl}, and${split}.expradds arithmetic - the core shell has none.regexprovides regular-expression matching.tklets scripts build graphical interfaces against Inferno’s Tk implementation.file2chanexposes Inferno’s signature trick, letting a shell script serve a synthetic file whose reads and writes are handled by shell code.- Further modules (
arg,string,csv, and others) round out the toolkit.
This design means the shell can be exactly as large as a task requires: nearly bare on an embedded device, or a full scripting environment - Peppé’s paper demonstrates a complete networked chat application written entirely in shell script - on a workstation.
The second pillar is blocks as first-class values. A brace-enclosed command block can appear anywhere a word can; rather than being executed immediately, it is a value that can be stored in variables, passed to commands, and converted to and from strings:
| |
Because control structures are ordinary commands that receive blocks as arguments, the module system and blocks-as-values together give the shell its programmability - the interpreter itself never needed an if statement.
From rc, the shell keeps the familiar machinery: every variable is a flat list of words, $#var counts elements, `{...} substitutes command output, ^ concatenates lists pairwise, and file descriptors can be manipulated with forms like >[1=2]. From mash it takes "{} (substituting a command’s output without tokenizing it) and <> for read-write redirection.
Evolution
The shell has changed little since it stabilized in the early 2000s; its history since then is the history of its host system. Inferno Fourth Edition reached a preliminary public release in 2004 and was released as free software in early 2005 under a dual licensing scheme. In March 2021 the source tree was consolidated under the MIT License. Development today happens quietly in the inferno-os repository on GitHub, where the shell’s grammar still lives in appl/cmd/sh/sh.y and its modules alongside it, and community forks such as the 64-bit inferno64 carry the system onto current hardware.
Current relevance
The Inferno shell is dormant: it evolves only as the Inferno distribution does, and its user base is the small community that still runs Inferno natively or hosted. But it remains genuinely usable. Hosted Inferno runs as a user application on mainstream operating systems - the official documentation lists Linux, FreeBSD, macOS, Solaris, Plan 9, and others, with native ports spanning ARM, PowerPC, SPARC, and x86 - and inside any of those sessions, sh is the working command language, exactly as documented in its still-shipping manual pages.
Why it matters
It answered a question most shells never ask. Where does a shell’s programming language belong? Bourne descendants build it into the interpreter; the Inferno shell moved it into dynamically loaded, type-checked virtual-machine modules. That gave a single shell an honest size gradient from embedded device to development workstation, and it remains one of the few shells whose extension mechanism is the platform’s native module system rather than an afterthought.
It pushed the rc lineage to its logical end. The line from Bourne’s shell through Duff’s rc and Haahr’s es reaches a kind of conclusion in Inferno’s sh: rc’s clean syntax, es’s first-class command blocks, and a module discipline none of its ancestors could offer, all running on a virtual machine inside an operating system where even echo is bytecode.
It shows what “everything is a file” makes possible. With file2chan, a few lines of shell script can serve a file that other programs - anywhere on the network, via the Styx protocol - can open and read. A shell script acting as a file server is a party trick almost nowhere else, and in Inferno it is idiomatic. For anyone studying how far the Plan 9 and Inferno design ideas can be carried, the Inferno shell is a small, readable, and still-runnable exhibit.
Timeline
Notable Uses & Legacy
The Inferno operating system
The shell is Inferno's native command interface and scripting glue: system scripts, interactive sessions in the wm window system, and everyday administration of Inferno's file-based resources all run through sh and its loadable modules
Lucent network products
Lucent built shipping products on Inferno, including the VPN Firewall Brick and the PathStar Access Server, a combined phone and data switch - commercial deployments of the operating system the shell was designed to drive
Bell Labs' Signet firewall
The 1997 Bell Labs Technical Journal paper describes Signet, an Inferno-based firewall that secured Bell Labs Research's own Internet connection - Inferno eating its own dog food inside the lab that created it
Hosted Inferno environments
Because Inferno runs as an ordinary user application under host operating systems including Linux, FreeBSD, macOS, Solaris, Plan 9, and Windows, the shell serves as the working command language inside hosted Inferno sessions used for Limbo development and experimentation
Ports to unusual hardware
Inferno's small footprint has carried it - shell and all - to devices from the Compaq iPaq to the Nintendo DS to the Raspberry Pi, where sh is the interactive face of the system