àṣẹ (pronounced roughly “ah‑sheh”) is a small Unix-style interactive shell written in Rust.
It’s designed to feel familiar if you live in bash/zsh, but with a compact, readable implementation that’s easy to explore and hack on.
-
Interactive shell
- Colorful prompt showing the shell name and current directory.
- Shows the current Git branch when you’re in a Git repo (or a child directory).
- Multi-line input for unclosed quotes.
-
Builtins
cd– change directory (cd,cd ~,cd /path).pwd– print the current directory.echo– print arguments.exit [CODE]– exit the shell with an optional status.type NAME...– tell you whether a name is a builtin or which executable it resolves to.history [N]– list recent commands (optionally lastN), with redirect support.
-
External commands
- Resolves executables via
PATH, just like a typical Unix shell. - You can run
ls,grep,git, etc. as usual.
- Resolves executables via
-
Redirection
>/1>– overwrite stdout.>>/1>>– append stdout.2>/2>>– redirect stderr and append stderr.- Redirection targets support
~and$VAR(e.g.> ~/out.txt,2> $LOGFILE).
-
Pipelines
cmd1 | cmd2 | cmd3using OS pipes between external programs.- Last stage honours stdout/stderr redirections.
-
Control operators
;– run commands in sequence, regardless of the previous command’s exit status.&&– run the next command only if the previous one succeeded (exit status 0).||– run the next command only if the previous one failed (exit status ≠ 0).- Splitting respects quotes (e.g.
echo "hello; world"is one command).
-
History
- Up/down arrows navigate previous commands.
historyandhistory Nprint numbered history.- Output can be redirected like any other command.
-
Tab completion
- First word: builtins + executables found in
PATH. cdarguments: filesystem path completion.
- First word: builtins + executables found in
-
Basic expansions
$VAR– environment variable expansion.~/~/...– tilde expansion using$HOME.- Globbing:
*,?,[...]in arguments expand to matching paths.
This is intentionally not a full POSIX shell; it’s a small, usable shell you can read in an afternoon.
The prompt looks like:
àṣẹ [my-project (main)] >
my-projectis the current directory name.(main)is the current Git branch when inside a repo (omitted otherwise).
-
cd [DIR]cdorcd ~→$HOME.cd /tmp,cd relative/pathas you’d expect.
-
pwd- Prints the current working directory.
-
echo ARG...- Writes arguments joined by a space, followed by a newline.
-
exit [CODE]exitexits with status0.exit 1exits with status1, etc.
-
type NAME...- For each
NAME, prints either:NAME is a shell builtin, orNAME is /full/path/to/executable, orNAME: not found.
- For each
-
history [N]historyprints all commands in the in-memory history.history 20prints only the last 20.- Output can be redirected:
history > hist.txt history 50 >> last50.txt
ls | wc -l
ps aux | grep ase | wc -l
cat Cargo.toml | sed -n '1,5p'echo hello > out.txt
echo more >> out.txt
ls not-a-dir 2> errors.logecho one ; echo two
# Prints "one" then "two", always runs both.
mkdir foo && cd foo
# Creates foo, then changes into it only if mkdir succeeded.
false || echo "previous command failed"
# Runs echo only because false exits with non-zero.Homebrew (recommended):
brew install steph-crown/tap/ase-shellShell installer (macOS or Linux):
curl --proto '=https' --tlsv1.2 -LsSf \
https://github.com/steph-crown/ase/releases/download/v0.2.3/ase-shell-installer.sh | shThis downloads the appropriate binary for your platform and puts ase on your PATH.
Shell installer (most distros):
curl --proto '=https' --tlsv1.2 -LsSf \
https://github.com/steph-crown/ase/releases/download/v0.2.3/ase-shell-installer.sh | shAlternatively, grab the tarball for your architecture from the
releases page, unpack it,
and move the ase binary somewhere on your PATH (e.g. /usr/local/bin).
PowerShell installer:
powershell -ExecutionPolicy Bypass -c "irm https://github.com/steph-crown/ase/releases/download/v0.2.3/ase-shell-installer.ps1 | iex"You can also download the .zip or .msi for your architecture from the
releases page and install it manually.
You’ll need a recent Rust toolchain (rustup recommended):
cargo install ase-shellThis installs the ase binary into ~/.cargo/bin. Make sure that directory is on your PATH:
export PATH="$HOME/.cargo/bin:$PATH"Then run:
aseFor a global CLI (if you prefer managing it via npm):
npm install -g ase-shell
asegit clone https://github.com/steph-crown/ase.git
cd ase
cargo build --releaseThe binary will be at:
target/release/aseYou can copy or symlink it somewhere on your PATH, for example:
sudo cp target/release/ase /usr/local/bin/aseThis is not a drop-in replacement for bash/zsh. Notable gaps:
- No job control (
&,jobs,fg,bg,Ctrl+Z). - No shell scripting language (no
if,for,while, functions,$@, etc.). - No here-docs (
<<), here-strings, or advanced redirections (2>&1, arbitrary FDs). - No history expansion (
!!,!123,!foo).
I plan to add some of these in future releases, so watch out for them.
Issues and pull requests are welcome. The codebase is intentionally small and straightforward:
src/main.rs– REPL loop, prompt handling, history wiring.src/lib.rs– crate exports and constants.src/commands.rs–Cmdenum, builtins, external command handling, pipelines.src/commands/parse.rs– token parsing, redirections, expansions.src/commands/targets.rs– stdout/stderr target types and writer helpers.src/repl.rs– Rustyline setup and completion.src/utils.rs– prompt andpwdhelpers.
If you build something cool on top or find rough edges in the UX, feel free to open an issue or PR.
Dual-licensed under either:
- MIT license
- Apache License, Version 2.0
at your option.