Introduction
This book is not complete, so do not expect all chapters to be finished.
wsh
is the WebAssembly-based shell, bringing the
power of Wasm to the everyday programmer! This shell aims to be a comfortable
experience to those familiar with traditional shell languages, but provides a
powerful toolkit for interacting with programs in ways impossible before the
days of WebAssembly.
If you'd like a quick overview of what wsh
allows you to do (and why), see
the GitHub repository. wsh
is compatible
with all major operating systems and architectures.
Sections
A guide for installing and setting up the shell.
A complete and comprehensive look into the features of wsh.
A quick start for people who want to translate their
bash or zsh
skills to wsh
.
A page dedicated to the features that haven't landed in wsh
, but are planned!
Getting Started
To get started with wsh
, install the binary and learn a little bit about the
shell language!
Installing
Since this project is still in infancy (see Project Status), the
best way to install wsh
is through Rust's package manager,
cargo
. In the future, more package
managers, along with pre-built binaries, will be supported.
After installing the binary, you may start it up wsh
:
$ wsh
Welcome to wsh, the WebAssembly shell!
~/code $
wsh
is compatible with all major operating systems and architectures.
Using cargo
wsh
can be installed using cargo
, though crates.io.
This will build the project using Rust. The minimum supported Rust version
(MSRV) is 1.75.0 (you can check with rustc --version
. If you do not have
cargo
, follow the instructions at
this link.
$ cargo install wsh
...
Building from source
First, you can clone the repository, with:
$ git clone https://github.com/dzfrias/wsh
$ cd wsh
Then, you can build the project with cargo
. Make sure that you have version
1.75.0 at least (you can check with rustc --version
). There are no
external (non-Rust) dependencies needed. However, if you'd like to run the
testsuite, make sure to clone the submodules with git submodule update --init
.
$ cargo run --release
...
A Tour of wsh
On a base level, wsh
aims to be similar to
bash and
zsh. Every-day usage will resemble the
aforementioned languages quite a bit. However, wsh
differs a lot in its
programmatic features. wsh
can resemble that
of a modern scripting language, if needed. You'll find that the control flow,
arithmetic, syntax, and semantics are much less arcane than the POSIX standard.
The base usage
To get started, start up wsh
and run the cd
built-in
to move to your home directory.
$ cd
$ echo hi from wsh!
hi from wsh!
$ pwd
/Users/dzfrias
Piping, from POSIX-style shells, remains the same:
$ echo "how many words here?" | wc -w
4
Redirection is also present:
$ echo "put this in a file" > out.txt
$ echo "append this" >> out.txt
$ cat out.txt
put this in a file
append this
Capture the stdout of a command with backticks:
$ cat `echo Cargo.toml`
...
Create an alias with the alias
key word:
$ alias foo = echo I don't want to type this again
$ foo
I don't want to type this again
Hopefully, these tools are enough to get you started using wsh
! See the
POSIX migration chapter for some more differences
between wsh
and traditional shells. You can read a more detailed dive into
running commands in this chapter.
wsh as a scripting language
While a lot of the every-day usage experience will be similar to that of
traditional shells, wsh
has a powerful escape hatch. You can use the .
character to escape to a language akin to a regular scripting language:
$ .x = 10
$ echo .(x + 100 == 110)
true
$ echo .("string" + " concat")
string concat
$ # yes, there's type coersion
$ .(1 + "1")
2
For the full power of language, create a new file, example.wsh
.
echo hello from this script!
.var = 10
while var > 0 do
echo .var
.var = var - 1
end
if var == 0 then
echo BLAST OFF!
else
echo basic math broke in the shell...
end
Run the script with the source
built-in.
$ source example.wsh
hello from this script!
10
9
8
7
6
5
4
3
2
1
BLAST OFF!
You can read more about wsh
's programmatic capabilities in
this chapter.
Using the Shell
This section provides a detailed look into the features currently supported by
wsh
.
Running Commands
Running commands in wsh
is similar to that of other shells, following the
<COMMAND> <ARGS>...
standard.
$ echo "Hello, World!"
Hello, World!
Piping
Piping can be achieved with the |
(pipe) token:
$ echo pipe! | tee out.txt | xargs echo cool
cool pipe!
$ cat out.txt
pipe!
This will pipe stdout, not stderr. The stderr stream can easily be redirected into stdout, if needed:
$ cargo build %| wc -l
1
Note:
%|
inwsh
is equivalent to2>&1
in POSIX shells; see the migration guide for similar discrepencies.
Redirection
You can redirect to different files with the >
and >>
characters. >
will
create (or overwrite) a file and fill it with the received input. >>
is the
same as >
, but will append to the file instead of overwriting it if it
already exists.
$ echo hello > out.txt
$ echo append >> out.txt
$ cat out.txt
hello
append
They can accept any expression on the right hand side (i.e. string concatenation):
$ echo important stuff > .("hi" + ".txt")
Like the regular pipe operator, you can use the %
character to
redirect stderr along with stdout:
$ cargo build %> cargo_out.txt
$ cargo build %>> cargo_out.txt
Note: Unlike POSIX shells, redirect symbols must terminate a pipeline. For example, the parser will not succeed with:
echo hello > out | cat
Output capture
You can use backticks to capture a command result into a string:
$ .x = `cat large_file.txt`
$ .x
...
The above example uses variable assignment.
Status codes
You can get the exit status of any command using the ?
character. This will be
stored as a number.
$ msityped
wsh: command not found: msityped
$ echo .? .(? + 100)
127 227
Programming
Numbers
Strings
Conditions
Loops
Functions
WebAssembly
Sandboxing
Loading
memfs
Linking
Environment
Configuration
Configuration in wsh
is largely done through the .wshrc
file. This file will
be executed on startup! .wshrc
has different locations depending on your
operating system, for example:
Linux | macOS | Windows |
---|---|---|
/home/dzfrias/.wshrc | /Users/dzfrias/.wshrc | C:\Users\dzfrias\.wshrc |
Make sure to replaced dzfrias
with your machine's name. If the file does not
already exist, feel free to just create it at that location! There are three
main things to put in a config file:
Aliases
Aliases allow you to set up custom names for commands
and their arguments. For example, here are two aliases for echo
:
alias foo = echo
alias bar = echo hello world
Now, when in the shell,
$ foo nice
nice
$ bar
hello world
Make sure to restart the shell when a change to the .wshrc
file is made!
Aliases can also represent pipelines:
alias long = echo hello world | wc -w | xargs word count:
$ long
word count: 2
Functions
Functions are much more powerful than aliases, and allow you to create custom commands with arbitrarily complex behavior!
def func : x do
echo hello world
if x > 3 then
echo greater than 3!
else
echo less than or equal to 3!
end
end
This function uses conditionals, and takes in an argument.
$ func 10
hello world
greater than 3!
$ func 1
hello world
less than or equal to 3!
For more details on the nuances of functions in wsh
, see the
Functions chapter.
Note: Functions must be declared at the top level of your program. This, for example, is not allowed by the parser:
if true then def func do echo hi end end
Aliases, however, can be declared conditionally.
Environment variables
You can set environment variables using the export
keyword. This will allow
all spawned subprocesses read the variable.
export HELLO = this is the value
In the shell,
$ echo $HELLO
Built-ins
POSIX Migration
Project Status
This project is not finished yet! Mainly, there are a few POSIX-shell features
that aren't supported in wsh
at this point. There are also many things that
are still under consideration, so do not expect the language to be stable.
Some syntax hasn't been completely decided on yet, but most semantics should
stay the same.
That being said, this project aims to be as polished as possible, so the WebAssembly features and the language implementation should be sound.
Planned Features
Here are some things that are planned, but haven't landed yet:
- Process substitution
- Windows
>>
(append redirection) support - Collection data structures (lists, maps)
- For loops
- Job control
- Signal handling
- Completion scripts
Contributing
If you'd like to help out with implementing any of these features, feel free to fork the repository and send in a PR!