zy is a shell. It is the program you type commands into. You already know one shell: bash. zy runs your bash scripts unchanged.
Beyond that, zy is a prompt, a fuzzy picker, a frecency jumper, a file manager, and a structured-data pipeline. All built into one binary. One config file. One apt remove if you change your mind.
This page is a first day with zy. Try it, install it, meet the prompt, explore your files, shape the prompt, then take it with you. The deeper engineering sits at the end, marked optional.

Try it in five minutes
You do not need to install anything to look around. zy runs in a throwaway container.
Drop into a real zy session inside a container that deletes itself on exit:
docker run --rm -it ghcr.io/iskandarputra/zyshell:latestType exit when you are done. The container removes itself.
Your first session
Once you are at the prompt, three commands map the whole tool. Run them in order.
help
See every command. A three-pane browser opens over all 533 builtins. Filter as you type.
explore
Browse your files. A full file manager opens inside the shell. Arrow keys to move.
customize
Style the prompt. Pick a theme and a pill shape with a live preview.
A few more worth typing while you are in there.
Jump anywhere
Type zi. Recent directories, grouped by recency. Filter and press Enter to jump.
Treat output as data
Try ls | where size > 1mb | first 5. Real records, not text.
Fetch from the web
Try http get https://api.github.com. The JSON comes back as a table.
Install it for real
When you want to keep zy, install the Debian package from the GitHub Releases page.
Download the .deb
Open the Releases page and grab the latest zy_*_amd64.deb. Shipped builds are amd64.
Install with apt
Run sudo apt install ./zy_*_amd64.deb. apt pulls the runtime libraries for you.
Follow the wizard
A short setup wizard runs in the same terminal. Press Enter to take each default.
There is one .deb. zy is not statically linked, so apt resolves what it needs at install: sqlite3, pcre2, openssl, expat, libarchive. Installing recommends git and suggests chafa, poppler-utils, ffmpeg, ghostscript, ripgrep, and neovim. zy runs fine without all of them. Missing pieces degrade gracefully.
The first-run wizard
Right after install, a setup wizard runs. It asks at most six things. Each step is skipped when there is nothing to do, so most people see two or three.
Import a previous backup
Only if a backup tarball is found. Restores your old setup.
Install a Nerd Font
Only if none is detected. The prompt uses pill glyphs from a Nerd Font.
Install Neovim
nvim is missing. Installs it for you.Enable rich previews
Offers to install whichever of chafa, poppler-utils, ffmpeg, or ghostscript are missing,
for image, PDF, video, and PostScript thumbnails in explore.
Set zy as your login shell
chsh for your user. Not as root.Launch zy now
The prompt draws pill caps from a Nerd Font. Without one you see boxes. Let the wizard install a Nerd Font, point your terminal at it, and the pills render.
Your first prompt
The banner is the version, build-stamped down to the minute. Below it is the prompt. Type a command and it runs. Scripts you wrote for bash run unchanged.
The POSIX surface is fully present. Pipes, redirections, globs, command substitution, parameter expansion, functions, jobs, history. The bash and zsh conveniences are here too. BASH_REMATCH, FUNCNAME, trap DEBUG, mapfile, the kill ring, !! and ^old^new^, bind, shopt.
echo ${var:-default} ${#var} ${var//old/new} ${var:0:5} # parameter expansion
cmd > out.txt 2>&1 # redirections
ls **/*.c # recursive globTo see what zy can do, type help. A three-pane browser opens. Categories on the left, commands in the middle, full docs on the right. Type to filter, Tab to switch panes, y to copy a name, Esc to leave. The same text prints at the prompt with help <cmd>.

Explore your files
Type explore. A file manager opens inside the shell. No helper binary on your $PATH.
It is three-pane Miller columns. The left sidebar holds bookmarks, pinned folders, and mounted disks, each with a usage chip, plus a frecency list of where you go often. The middle column is the focused directory. The right column is a live preview.

The preview is real. Syntax-highlighted code, sixel or kitty images, and PDF, PostScript, or video thumbnails when the tools are present. Text fallback otherwise.
Keys worth knowing
- , cycles the detail columns.
- I opens a file-info card: owner, perms, recursive size, times, binary architecture, SHA-256.
- s opens a sort picker. Listings already sort naturally, so
img2lands beforeimg10. - / filters the directory with fuzzy matching. The cursor is remembered per directory.
- L greps the whole tree into a results pane. Hits group by file with a
line:colgutter. Scope with chips likeext:c path:src !path:vendor TODO. Enter opens a hit at its line in$EDITOR. - Ctrl + R is a regex bulk-rename with a live before/after preview. PCRE2
s/pat/repl/flags,$1backrefs,/gand/i, a{n}counter. Staging is collision-safe.
- c compresses the selection to
.zip. C makes a.tar.zst. x extracts. - P pins the current directory to the sidebar.
- H on a file opens it as a standalone HTML page in your browser.
- \ inside the file viewer opens an in-terminal diff. Syntax-highlighted, n and N jump changes, w wraps.
Press H on a file and it opens as a real HTML page in your browser. A full render through the bundled exporter, not a recolor.

If the file has uncommitted changes, that page becomes a side-by-side diff against the version on disk. What did I change, without leaving the file manager.

Every explore key is remappable through an [explore.keys] table in ~/.zy/config.toml.
Jump where you live — zi
Type zi for the directory jumper. Recent directories, grouped Today, Yesterday, This week, Older, with a Bookmarks tab pinned in front. Type to filter, Tab or 1 through 5 to switch tabs, Enter to jump. The store is shared with z, so the prompt feeds it automatically.

The Bookmarks tab holds destinations you starred. They bypass the time-decay scoring, so they always render first.

Shape the prompt
Type customize. Pick a theme, a pill shape, which pills show, how long directories truncate. The right pane previews every choice live. Each change writes through to ~/.zy/config.toml, and the next prompt renders with it. No restart, no source.

Past the 22 named cap shapes, the Mix & Match tab pairs a left cap and a right cap from the full glyph set. The sample pill updates as you move.

The prompt is one TOML file with hot reload. 39 themes ship in the binary, light variants and editor classics included. GitHub, Nord, Tokyo Night, Rosé Pine, Catppuccin, Dracula, Solarized, Gruvbox, and more. Over 100 modules cover languages, cloud and version-control context, and system signals. Slow modules render on background workers, so a noisy git repo never holds the prompt back.
Switching theme also retints the terminal. zy speaks the OSC sequences that GNOME Terminal, Konsole, Kitty, Alacritty, and Ghostty already listen to. New windows open in the new palette.
Take it with you
Your whole setup is portable in one command.
migrate export # timestamped tarball of ~/.zy/, ~/.zyrc, history, policy
migrate import ~/zy_migrate_<timestamp>.tar.gzTheme, palette overrides, pinned pill shapes, custom modules, bookmarks, frecency database, and history restore verbatim on a new machine. The same flow doubles as a backup.
That is a working first day. Install, explore, jump, style, and move your setup. The rest of this page is for the curious. A beginner can stop here.
The stack you would have built
A productive terminal usually means a shell plus a dozen tools, a plugin manager, and a dotfiles repo to keep them in sync. zy ships the equivalent in one binary, wired together from the first prompt.
| Instead of installing | zy gives you |
|---|---|
| starship + a font script | A TOML prompt with 39 themes, 22 pill shapes, 100+ modules, hot reload, and a customize wizard |
| fzf | A built-in fzf with the 'exact / ^prefix / suffix$ / !negate grammar, plus multi-select |
| zoxide | z and zi over one frecency store, shared with explore and the help TUI |
| yazi, ranger, lf | explore — Miller columns, sixel and kitty preview, archive browsing in place |
| jq, yq | from-json, to-yaml, get, where, sort-by against any supported format |
| ripgrep | fff-grep, in-process with no fork per query, so warm repeat searches stay fast |
| sqlite3 | query-db, stor-open, stor-create, schema over an in-memory SQLite store |
| nushell | Typed pipelines with a vocabulary you already know |
| bat | Syntax-highlighted preview in explore and the fff-preview helper |
| curl, httpie | http get / post / put / patch / delete / head, HTTPS included |
| A task runner | task, reading [task-name] sections from a .zytasks file with depends-based ordering |
| Plugin managers (zinit, antigen) | Nothing. There is nothing to install on top of the binary |
| A dotfiles repo | One ~/.zy/config.toml and a one-command migrate export |
For the curious — how it is built
Data, not strings
Most shells treat output as a wall of text. zy treats it as data.
Pipelines move records, tables, lists, durations, file sizes, and dates between commands in a typed, in-process form. No serialization tax, no awk gymnastics, no fragile column counting.
# Strings out, data in. Reads like Nushell, runs in zy.
ls | where size > 1mb | sort-by modified | first 5
# Group files by extension, count each group, show the four largest.
ls | group-by extension | each { |g| { ext: $g.0, count: ($g.1 | length) } } | sort-by count --reverse | first 4
# Edit a JSON config in place. No jq, no temp file.
open package.json | upsert version "2.0.0" | save package.json
# Pull JSON from any endpoint and treat it as a table.
http get https://api.github.com/repos/iskandarputra/zyshell/releases | get tag_name | first 5When every stage is a builtin, the chain runs in-process and passes typed values between stages. The moment an external command joins, zy falls back to a POSIX pipe with serialization at the boundary.
Seventeen value types. Sixty-plus filter and transform commands. zy reads JSON, CSV, TSV, INI, TOML, YAML, XML, Markdown, NUON, and SSV. It writes JSON, CSV, TSV, TOML, YAML, XML, HTML, Markdown, NUON, and plain text. It decodes PNG, JPEG, GIF, and BMP.
▶The seventeen ZyValue types
null, bool, int, float, string, list, record, table, filesize, duration, datetime, binary, glob, cell-path, closure, range, error. Stored as a C tagged union.
The build and the layers
zy is a single C binary in gnu17, built -Wall -Wextra -Werror -O3 -g -flto. No readline, no libedit, no yacc. The parser is handwritten recursive descent, for direct control over shell corner cases and precise diagnostics.
The source is organized strictly by dependency direction. Nine numbered layers, low-level primitives at the bottom, terminal UI at the top. Parser and runtime changes stay contained. UI and module work stays fast.
The signature design choice: policy and audit live inside the execution path, not beside it. Every command is parsed, policy-checked, executed, and recorded in one loop. Consistent by construction, not by convention.
Trust and accountability
For a shell that sits between people and shared infrastructure, zy ships two governance primitives with no external tooling.
A policy engine loads /etc/zy/policy.conf, through --policy at launch or the policy builtin. An administrator expresses rules there about which commands run in which contexts.
An audit ledger records every execution, with cwd, exit status, and duration, into a SHA-256 hash chain. Inspect it, export it, or verify the chain.
Day to day they stay out of the way. On the day you need the record, it is already there.
By the numbers
Every figure below is produced from the source tree, not a marketing slide.
| Format coverage (read) | JSON, CSV, TSV, INI, TOML, YAML, XML, Markdown, NUON, SSV |
| Format coverage (write) | JSON, CSV, TSV, TOML, YAML, XML, HTML, Markdown, NUON, plain text |
| Terminals with explicit integration | 9 (Alacritty, Ghostty, GNOME Terminal, Kitty, Konsole, Ptyxis, Tilix, XFCE Terminal, xterm) |
| Architecture shipped | amd64 (builds from source on arm64) |
| Vendored libraries | 2 (tomlc99, stb_image) |
| External runtime dependencies | apt resolves them at install |
Public repository state
The public GitHub repository is the release channel. Binaries ship there. The source tree lives in a private development repo for now. This page documents the architecture and engineering decisions while the source stays closed.
Acknowledgments
zy stands on the work of others. It borrows ideas, not code. Every surface is an original C implementation.
| Influence | What zy learned from it |
|---|---|
| Bash / Zsh | The POSIX scripting model and the conveniences (trap, mapfile, kill ring, completion ergonomics) |
| Nushell | The structured-data pipeline model and a shared command vocabulary |
| Starship | The TOML-driven, hot-reloading, module-shaped prompt |
| Yazi | The file-manager experience explore aspires to |
| fzf | The fuzzy-picker grammar and flag shape |
| zoxide / z.lua | The frecency idea behind z and zi |
zy contains no source code from any project above. Inspiration is reproduced through original implementation only, which is what keeps zy MIT.
Why it is here
For my portfolio, zy is end-to-end systems engineering in one artifact. A language frontend and runtime. Low-level memory and ownership discipline. Interactive terminal UX. Operational security designed into the execution path. Complete systems, not isolated components.
Get zy
Releases and the .deb, on GitHub
Public repository
github.com/iskandarputra/zyshell — release channel
Command reference
Every builtin, searchable