I've been working on wisp, a Linux shell that uses Lua 5.4 for scripting and config instead of inventing another shell grammar.
The core idea is simple: any global function you define in ~/.config/wisp/init.lua becomes a shell command. No alias syntax, no config DSL -- just Lua.
function ll(input)
return sh("ls -la")
end
function g(input, pattern)
return sh("grep " .. pattern)
end
Then use them like any command: wisp> ll | g "wisp"
Why Lua?
Every shell invents its own scripting language. Bash has its own grammar, fish has its own, zsh has its own. They all have different syntax for aliases, functions, conditionals, and loops.
Lua is already a real programming language with closures, tables, loops, and a standard library. It's the most embedded scripting language on the planet. Why invent another one?
Structured Pipeline Data
The other thing that's different: native pipeline stages (user-defined functions and builtins) pass Lua tables between each other in-process. No fork, no serialization.
function nums(input)
return { {n = 3}, {n = 1}, {n = 2} }
end
function sorted(input)
table.sort(input, function(a, b) return a.n < b.n end)
return input
end
wisp> nums | sorted passes the table directly from nums to sorted without forking or text parsing. Only when a pipeline hits an external command (grep, wc, anything on $PATH) does wisp fork and serialize to bytes.
What's in v2
- Full job control: fg, bg, kill, disown, wait
- Globbing, brace expansion
- ${VAR:-default} expansion
- 2>&1 redirect
- Tab completion for commands, filenames, Lua functions
- Levenshtein command-not-found suggestions
- Script mode:
./wisp -f script.luaor#!/usr/bin/env wisp - Builtins: cd, exit, export, command, jobs, fg, bg, kill, disown, wait, echo, source, pwd, type
Stats
- Binary: 195K (stripped: 168K)
- Source: ~2,300 lines C++17
- Dependencies: Lua 5.4, vendored linenoise
- Startup: 1.5ms
What it can't do (yet)
No array syntax, no [[ ]] tests, no ${!prefix*} expansions. Not a bash replacement for scripts -- focused on interactive use.
GitHub: https://github.com/Hinikaa/wisp
Top comments (2)
I particularly appreciate how you've leveraged Lua's strengths to create a more seamless and expressive shell experience, such as using Lua tables to pass data between pipeline stages, which eliminates the need for forking and serialization. The example with the
numsandsortedfunctions demonstrates this beautifully, showcasing how wisp can handle structured data in a more efficient and intuitive way. How do you envision the community contributing to the development of wisp, especially in terms of adding support for features like array syntax or more advanced testing constructs?Thanks! The nums | sorted pipeline was the moment I knew this wasn't just a toy -- passing actual data structures between stages instead of parsing text at every fork just makes sense for anything beyond ls | grep.
For community contributions, the honest answer is: I'm not sure yet. The codebase is small enough (~2,300 lines) that I can hold the whole thing in my head, which is both a strength and a constraint. I don't want to open it up to PRs that I can't review properly.
That said, the areas where outside help would actually be useful:
Testing on different systems. I've only tested on x86-64 Linux with g++ and Lua 5.4. If someone wants to try it on ARM, musl, or with clang, that's real value.
Edge cases in the parser/executor. The shell has basic job control, redirects, and expansion, but there are definitely quoting/escaping edge cases that only show up when someone actually uses it as their daily shell.
Init.lua libraries. The real power is in what people build in init.lua -- utility functions, pipeline stages, prompt customizations. That's where community contributions could be most useful without touching the C++ core.
As for array syntax or advanced testing constructs -- I'm deliberately keeping v2 simple. Arrays in a shell are a design rabbit hole (indexed vs associative, slicing syntax, iteration). I'd rather get the fundamentals right than chase feature parity with bash.
If someone wants to fork it and add those things, the license allows it. But for the main repo, I'm taking it slow.