zish - A Minimal Shell in Zig#

A POSIX-ish shell written in Zig with GNU Readline and SQLite-backed persistent state.

The Idea#

Your shell environment lives in a single SQLite file (~/.zish.db). History, environment variables, aliases — everything is portable. Copy the file to another machine and pick up right where you left off.

# On machine A
scp ~/.zish.db user@machine-b:~/.zish.db

# On machine B
zish  # all your history, aliases, and env vars are there

Or use a custom database:

zish --db ~/projects/myproject/.zish.db

Features#

  • SQLite-backed persistence: History, environment, aliases, settings
  • Prefix-based history search: Type git then press ↑ to find only git commands
  • Rich history: Every command stored with timestamp, working directory, and exit code
  • Portable environment: export persists to DB, loads on startup
  • Persistent aliases: alias writes to DB, available across sessions
  • Command lists: && and || for conditional execution
  • Command substitution: $(command) captured and expanded inline
  • Glob expansion: *, ?, [...] patterns via POSIX glob(3)
  • Pipes & redirects: |, >, >>, <
  • Variable expansion: $HOME, $USER, $? (last exit code)
  • Exit code indicator: Red ✘ in prompt when last command failed
  • Alias expansion: First word is checked against alias DB
  • SIGINT handling: Ctrl-C won’t kill the shell

Builtins#

CommandDescription
cd [dir]Change directory (~ supported)
pwdPrint working directory
exitExit the shell
export KEY=VALSet & persist environment variable
exportList persisted environment variables
unset KEYRemove environment variable
alias name=commandSet & persist alias
aliasList all aliases
unalias nameRemove alias
historyShow readline history
history search PREFIXSearch DB history by prefix
history statsShow history statistics
query SQLExecute SQL, output as table (default)
query --json SQLExecute SQL, output as JSON
query --csv SQLExecute SQL, output as CSV
dbinfoShow database information
helpShow help

Database Schema#

history     (id, command, cwd, timestamp, exit_code)
environment (key, value)
aliases     (name, command)
settings    (key, value)

The database uses WAL mode for performance and safe concurrent access.

Build#

Prerequisites#

  • Zig >= 0.15.0
  • GNU Readline development headers
  • SQLite3 development headers

Current version provides Linenoise and SQLite Amalgamate compiled statically to improve portability.

Compile & Run#

zig build
./zig-out/bin/zish

Static Linking#

For a fully portable binary, change build.zig:

exe.linkSystemLibrary2("readline", .{ .preferred_link_mode = .static });
exe.linkSystemLibrary2("sqlite3", .{ .preferred_link_mode = .static });

Query Builtin#

Direct SQL access to your shell database with multiple output formats:

# Table format (default)
query SELECT command, exit_code FROM history WHERE cwd LIKE '%/myproject%' LIMIT 5

# JSON output - pipe to jq, store, or send to an API
query --json SELECT key, value FROM environment

# CSV output - import into spreadsheets or other tools
query --csv SELECT command, count(*) as n FROM history GROUP BY command ORDER BY n DESC LIMIT 20

Prefix-based search is built in — no ~/.inputrc needed:

KeyAction
Search backward (prefix match)
Search forward (prefix match)
Ctrl-PSearch backward (prefix match)
Ctrl-NSearch forward (prefix match)

Additionally, history search git searches the SQLite database directly, showing timestamp, exit status, and working directory for each match.

License#

GPL-3.0-or-later