Shelly
Current version: 0.5.4.
Shelly is a Unix-style shell written in Rust, with a typed scripting language for commands, structured data, and network services. Pipelines carry typed values between Shelly functions and ordinary byte streams between external programs.
Shelly runs on Linux, WSL, and macOS. Its core language features are implemented, and the project is in stabilization before a potential rewrite and cleanup of the prototype's internals.
Install with Cargo
With a Rust toolchain supporting edition 2024 installed:
The Cargo package is named shelly-shell; the installed executable is shelly.
Make sure Cargo's binary directory, normally ~/.cargo/bin, is on your PATH.
The executable includes its standard library, so no separate library installation
is needed. You can select a filesystem library through $SHELLY_STD_PATH;
$SHELLY_STD_FOUND reports the selected location. See the
startup guide
for library selection and profile loading.
Build from source
Use a Rust toolchain supporting edition 2024:
This builds and launches the debug executable. You can also run it directly:
The wiki/ submodule records the documentation revision for this checkout. If you
already cloned the repository, initialize it with:
When developing with Shelly as your login shell, validate release builds in a separate directory so you do not overwrite the executable your sessions depend on:
Run your first script
Save this as hello.shy:
let $name = if $args.count > 0 { $args[0] } else { "world" }
echo "Hello, ${name}!"
Run it with the installed executable or your source build:
Hello, Mira!
For a single command, use -c. For source supplied on stdin, use -s:
|
Running shelly in a terminal starts the interactive REPL. Ctrl+D on an empty
input exits; Ctrl+C interrupts a foreground command or discards the current input.
Use shelly --help for execution options.
A brief look at the language
Commands use familiar space-separated arguments, while variables begin with $.
Functions can declare parameter and return types. Arrays, hashes, structs, enums,
and distinct named types let scripts describe the data they work with.
A pipeline can process structured values directly:
fn sum($args: Number...): Number
{
$args.sum
}
let $result: [Number]
[[1, 1], [2, 2], [3, 3], [4, 4], [5, 5]] | sum $... | $result
echo $result...
2 4 6 8 10
Each inner array becomes one pipeline item. $... spreads that item's values
into arguments to sum, and the final $result collects the returned sums.
External programs still connect through ordinary pipes, such as git diff | less.
Conversion annotations connect text formats such as JSON and CSV to typed stages.
Visual pipeline splits
let one upstream stream feed several independently transformed paths.
The language also includes:
- Integer and Float arithmetic, with Integer-to-Float promotion where required.
- Conditionals, match expressions, ranges, destructuring, and an iterator protocol.
- Closures with live captures, first-class function types, and extension methods.
- Modules with private declarations, public interfaces, and conditional imports.
- Typed errors and cleanup, plus library APIs for files, streams, JSON, and networking.
- An interactive editor with completion, syntax highlighting, history, and prompt widgets.
Shelly has its own language semantics; existing Bash scripts should continue to run with their intended interpreter.
Explore the wiki
The Shelly wiki contains the full language documentation, worked examples, and standard-library guides. Start with:
Shelly is available under the MIT license.