$_ shish

shish

A small POSIX-ish shell in C. One file, no stdio, no dialect of its own — and it compiles to WebAssembly.

Get started Run it in your browser GitHub

Three places a 139 KB shell changes the maths

Containers

A distroless image with a shell in it usually means a libc, a loader and a pile of coreutils binaries, just so the entrypoint can run mkdir -p and a for loop.

shish has cat, rm, mkdir, mktemp, ln, chmod, uname and friends compiled in. The entrypoint runs with PATH= empty and nothing else in the image.

Containers →

Agent sandboxes

An AI harness runs thousands of shell commands inside a boundary somebody has to review. bash is 1.4 MB, a startup-file search path, a history file and $BASH_ENV.

shish reads no startup file of its own, writes no history, starts in ~1.3 ms, and -n parses a generated command without running it.

Agent sandboxes →

WebAssembly

184 KB of .wasm: a real shell in a browser tab, a worker, or a WASI runtime — with no process and no container underneath it.

Subshells and command substitution are in-process, so $(...) and ( ... ) work even where fork() does not exist.

Playground →

A shell that does not need a /bin

$ shish -c 'PATH=; mkdir -p a/b; echo hi > a/b/f; cat a/b/f; rm -r a'
hi

Every utility in that line is inside the binary. Nothing is looked up, so nothing can be planted on a PATH — see Builtins for the full set and how to choose it at compile time.

shellsizeneeds coreutils
shish139 KBno (builtins)
dash126 KByes
bash1.4 MByes
busybox (sh + ~400 applets)2.0 MBno

Stripped x86-64 binaries on the same machine, dynamically linked. shish is ~1.05 MB static with every builtin compiled in.

No dialect of its own

shish will never introduce a language construct that is not already in POSIX or in another shell. Everything it accepts beyond the standard — local, source, brace expansion, history expansion — is spelled the way bash, ksh or dash already spells it, and is an option rather than the default.

A script written for shish keeps running under sh. That is the whole point: the small shell is a deployment choice, not a language you have to learn or a lock-in you have to migrate off.

Build it

$ git clone https://github.com/rsenn/shish.git && cd shish
$ cmake -S . -B build/x86_64-linux-gnu
$ cmake --build build/x86_64-linux-gnu -j

Cross-builds for musl, dietlibc, mingw32/64, MSYS, aarch64, Android, Termux, Emscripten and WASI all come from the same tree — see Building.

Status: alpha, and honest about it

shish runs the shell language — pipelines, redirections, functions, case, loops, parameter expansion, arithmetic, job control, traps — and passes 5541 cases of yash's POSIX conformance suite. It also still fails 551, mostly in signal disposition, alias and quoting/parameter expansion.

It is not a drop-in /bin/sh yet: do not point init at it. Every known defect has a repro in BUGS, the work plan is in TODO.md, and every fix ships with a regression test. See Conformance for the numbers behind that.