Written in V — MIT Licensed
This tool was developed with the assistance of AI

The hackable
Unix shell

vlsh is an interactive Unix shell written in V — simple, fast, and hackable, with a clean codebase you can read, modify, and extend.

vlsh — ~
  # inline autosuggestion from history
~$ git push origin main
 
  # press → or End to accept
~$ git push origin main
  Everything up-to-date.
 
  # tab completion works after trailing /
~$ cd .config/nvim
 
~$

Everything you need, nothing you don't

vlsh ships with the fundamentals done right, then gets out of your way.

Fast & Compiled

Built with V, vlsh compiles to a lean native binary. Cold start is near-instant — no interpreter overhead on every keystroke.

|

Pipes, Redirection & Chains

Pipelines (|), file redirection (>, >>, <), and 2>&1 when stdout is captured — plus &&, ||, and ;. Glob expansion (*.v, ~/docs/**), tilde expansion, and parameter expansion ($VAR, ${…}) with session IFS for word splitting.

💬

Smart History

Shared history file (~/.vlsh_history, last 5 000 entries), arrow keys, and Ctrl+R search. Bash-style history expansion at the interactive prompt: !!, !$, !n, !-n, !prefix, and !?sub.

Tab Completion

Files and directories; the first word also completes command names from $PATH. After cd , only directories are suggested. Plugins can register custom completions (for example SSH hostnames).

Inline Autosuggestions

Fish-style ghost text appears as you type, sourced from command history. Press or End to accept the suggestion. Includes path validation for cd candidates and a filesystem fallback.

🔌

Plugin System

Install from the official repo with plugins install, plugins search, plugins update, plugins delete, or plugins reinstall. Plugins can add commands, prompt lines, pre/post hooks, output_hook, tab completions, mux_status for the multiplexer bar, and help text surfaced via help.

Built-in Multiplexer

Run mux to split panes (resizable), use the mouse, copy/paste, a status bar, and up to 1 000 lines of scrollback per pane — VT100-friendly so editors like vim and nano work inside panes.

📜

Native .vsh Scripts

Run .vsh V scripts directly without manually compiling them first. Great for automation that needs performance without the ceremony of a full build.

🎨

Theming & Aliases

Configure prompt colors via RGB values in ~/.vlshrc. Manage aliases at runtime or persist them in your config — all without restarting the shell.

POSIX compatibility

vlsh is not POSIX-conformant, but it supports commonly used POSIX shell features — with a documented, tested subset growing over time (see posix-inventory.md on GitHub).

Supported operators

OperatorBehaviour
&&Run next command only on success
||Run next command only on failure
;Run next command unconditionally
<Redirect stdin from a file
>Redirect stdout, overwriting the file
>>Redirect stdout, appending to the file
2>&1Merge stderr into captured stdout when piping or redirecting

Supported builtins

BuiltinDescription
export / unsetSet or remove environment variables
source / .Execute a script in the current shell context
cdChange directory; supports ~, $HOME, and cd -
exitExit the shell with an optional status code
$?Expands to the exit status of the last command

Get up and running

Latest release v1.2.0 — pre-built packages for 64-bit Linux, or build from source. Full instructions: README on GitHub.

shell
# .deb for v1.2.0 (installs to /usr/bin/vlsh; postinst updates /etc/shells)
curl -LO https://github.com/vlshcc/vlsh/releases/download/v1.2.0/vlsh_1.2.0_amd64.deb
sudo dpkg -i vlsh_1.2.0_amd64.deb

# Set as login shell (optional)
chsh -s /usr/bin/vlsh
shell
# RPM for v1.2.0
curl -LO https://github.com/vlshcc/vlsh/releases/download/v1.2.0/vlsh-1.2.0-1.x86_64.rpm
sudo rpm -U vlsh-1.2.0-1.x86_64.rpm
shell
# Standalone 64-bit Linux binary (v1.2.0)
curl -LO https://github.com/vlshcc/vlsh/releases/download/v1.2.0/vlsh_1.2.0_amd64_linux
chmod +x vlsh_1.2.0_amd64_linux
sudo mv vlsh_1.2.0_amd64_linux /usr/local/bin/vlsh

# Approve shell and set as default (optional)
echo /usr/local/bin/vlsh | sudo tee -a /etc/shells
chsh -s /usr/local/bin/vlsh
shell
# Requires V — https://vlang.io
git clone https://github.com/vlshcc/vlsh.git
cd vlsh
v .
./vlsh

# Or install into PATH: sudo make install  (default PREFIX=/usr/local)
# make help — targets; make test — suite; make fuzz — stress parsers

Extend with pure V

Plugins install from the official repository into ~/.vlsh/plugins/<name>/<version>/; vlsh compiles them on startup. The remote catalogue lives at github.com/vlshcc/plugins. Plugins can:

  • 1 Register commands, prompt lines, and help text for the built-in help command
  • 2 Run pre/post hooks and output_hook around every command
  • 3 Provide tab completions and mux_status text for the multiplexer status bar
  • 4 Be searched, installed, updated, removed, or purged and re-fetched with plugins reinstall
~/.vlsh/plugins/myplugin/v1.0.0/myplugin.v
// Plugins implement main() and respond to argument tokens
module main

import os

fn main() {
    arg := if os.args.len > 1 { os.args[1] } else { '' }
    match arg {
        'capabilities' { println('prompt') }
        'prompt' {
            branch := os.execute('git branch --show-current')
            if branch.exit_code == 0 {
                print(' (' + branch.output.trim_space() + ')')
            }
        }
        else {}
    }
}

Plugin management

CommandDescription
plugins listShow all locally installed plugins with their installed version
plugins remoteList plugins in the remote repository with version info and available updates
plugins search <query>Search available plugins by name or description
plugins install <name>Download and install the latest semver version of a plugin
plugins update [name]Update one plugin or all installed plugins to their latest version
plugins reloadRecompile and reload all plugins (run after install or update)
plugins enable / disable <name>Activate or deactivate a plugin without deleting it
plugins enable / disable allActivate or deactivate all plugins at once
plugins delete <name>Remove an installed plugin and its entire directory
plugins reinstall <name>Remove the local copy and install the latest from the remote repository