Winuxsh
Bash, native on Windows. No WSL. No VM. No
/mnt/c. No cmdlet dialect. Just the shell your fingers already know — and the one your AI agent actually speaks.
This is the Winuxsh documentation. Start with the guides, or jump straight into the shell:
C:\Users\you\repo
❯ test -f Cargo.toml && echo "rust, obviously"
rust, obviously
❯ printf "%s\n" alpha beta gamma | grep beta
beta
❯ cd "C:\Program Files"
C:\Program Files
What Winuxsh is
- Bash syntax.
if,for,case,$(...), pipes, redirects, heredocs, functions, aliases — the whole grammar, powered by rubash, which passes the GNU Bash project's own test suite (86/86 upstream tests green). - Windows-native. One binary, one process. Native Windows paths
(
C:\...andC:/...), direct execution ofgit.exe,node.exe,cargo.exe,python.exe— no VM, no emulation layer, no path conversion roulette. - Unix commands included. WinuxCmd ships
ls,cat,grep,find,test,printf, and friends as Windows command links, with no separate installation. - AI-native.
winuxsh -cis a contract: no banners, stable stdout/stderr, exact exit-code propagation. What an agent writes is what the process receives — the quoting roulette of PowerShell and the path mangling of MSYS/Git Bash are both gone. - A prompt you'll enjoy. 27 bundled themes (agnoster, spaceship, pure, catppuccin-mocha, tokyonight, p10 family, ...), a git prompt that grows teeth inside any repository, syntax highlighting, autosuggestions, vi and emacs modes, and Ctrl+R history search.
- Plugins with a permission model. 40+ bundled packs (
git,docker,kubectl,npm,zoxide,direnv,fzf,thefuck, ...), with reviewed source packs and process adapters declaring the host access they need.
The documentation
| Guide | What it covers |
|---|---|
| Getting Started | Zero to a git prompt in ten minutes |
| Advanced Usage | Execution modes, startup files, themes, plugins, completion, debugging |
| Install & Self-Update | Installer, portable zip, Windows Terminal profile, updates |
| Bash Compatibility Matrix | What Bash surface is verified, layer by layer |
| Architecture | rubash + WinuxCmd + reedline, path model, host contract |
| Windows Path Contract | logical root, dispatcher selection, and layer ownership |
| Roadmap | What is done, what is next |
Get it
Download the installer from GitHub Releases, or build from source:
git clone https://github.com/unixwin/winuxsh.git
cd winuxsh
cargo build --release
target\release\winuxsh.exe
Keep it current with winuxsh --self-update (or self-update inside the
shell) and wpm update winuxcmd for the Unix command set. Questions and bug
reports go to
github.com/unixwin/winuxsh/issues.
Shell semantics live upstream in rubash — fix the engine, and every Bash user on Windows wins.
Why Winuxsh
The long version of the pitch. The README sells it in five seconds; this page shows the receipts.
The Windows shell civil war
Every Windows developer knows the tabs open on their machine:
| Option | The fine print |
|---|---|
| CMD | Frozen in 1987. Your company's docs still paste it. |
| PowerShell | A genuinely powerful automation language. It is not Bash — your for loops, grep, and quoting instincts die on arrival. |
| WSL | A whole Linux distribution as a hobby you didn't sign up for. Boot a VM to print a directory. Dock your Docker Desktop's memory. Greet /mnt/c/Users/you/.... |
| Git Bash / MSYS2 | Brilliant emulation with a cost: it translates, mangles, and converts your paths at the worst possible moments, and every git pays an emulation tax. |
The treaty
Winuxsh is one native Windows binary that runs Bash syntax on Windows paths
with real Windows programs — and brings the Unix commands Windows never had
(ls, cat, grep, find, test, printf, ...).
| Winuxsh | WSL | Git Bash | PowerShell | |
|---|---|---|---|---|
| Bash syntax | ✅ | ✅ | ✅ | ❌ |
Native Windows paths (C:\..., no /mnt/c) | ✅ | ❌ | ⚠️ conversion quirks | ✅ |
Calls git.exe / node.exe directly | ✅ | ⚠️ via /mnt/c | ⚠️ path translation | ✅ |
Unix commands (ls, grep, find) | ✅ | ✅ | ✅ | ❌ |
| Cold start to prompt | ~170 ms | seconds | ~1 s | ~280 ms |
| No extra OS, no VM | ✅ | ❌ | ✅ | ✅ |
| Themes, git prompt, plugins | ✅ | — | ✅ | ⚠️ |
One binary. One process. No distro to patch, no emulation layer to appease.
PowerShell eats arguments
Windows itself is the root cause: the platform has no argv array. Every executable receives a single command-line string and parses it with its own rules — and PowerShell adds a second parser on top. That's how PowerShell/PowerShell#1995 ("Arguments for external executables aren't correctly escaped") became a household name, and how dotnet/runtime#23347 opens by citing "the ongoing quoting woes PowerShell experiences."
Same command line, two shells. Watch what actually reaches the process:
# PowerShell 5.1 # Winuxsh
> node -e "console.log(JSON.stringify( ❯ node -e "console.log(JSON.stringify(
process.argv.slice(1)))" "a b" "" "c\"d" process.argv.slice(1)))" "a b" "" "c\"d"
"e\f" "---" "e\f" "---"
ParserError: TerminatorExpectedAtEndOfString ["a b","","c\"d","e\\f","---"]
That command is written the way any model trained on Bash would write it. PowerShell throws a parse error before the process even starts. And when you quote it PowerShell's own way, the damage is quieter but still real: five arguments in, two mangled ones out — the empty string vanishes, the embedded quote is flattened, the last two arguments fuse into one:
> node -e "console.log(JSON.stringify(process.argv.slice(1)))" "a b" "" 'c"d' "e\f" "---"
["a b","cd e\\f ---"]
Agent casualties, with receipts
For humans this is a nuisance. For AI agents it's a minefield: models are trained on Bash, their quoting instincts are Bash-shaped, and on a PowerShell machine every generated command is a roll of the dice.
- anthropics/claude-code#65162 — agent used a PowerShell here-string (
@'...'@) inside the Bash tool; the git commit message was silently corrupted, andgit commitstill exited 0. - anthropics/claude-code#83243 — trivial commands fail with
unexpected EOFon Windows when PowerShell is the primary shell. - anthropics/claude-code#76490 — Bash allow-list rules never match Windows drive-letter paths; every run re-prompts.
- openai/codex#31548 — Windows users are voting to make the Codex agent shell configurable; it is locked to PowerShell today.
- openai/codex#35995 — Python works in the interactive shell but silently disappears inside Codex task execution.
- openai/codex#33891 / openai/codex#36560 — the ChatGPT desktop app flashes PowerShell windows while its agent works.
- microsoft/vscode-python-debugger#233 — a space in a path yields incorrectly quoted debug commands.
The path philosophy: native in, native out
Windows-native binaries don't speak the MSYS dialect. Here is Git Bash, in the wild, failing at exactly the things Winuxsh does without thinking:
What just happened, command by command:
| Command | In Git Bash (MSYS) | In Winuxsh |
|---|---|---|
node -e "..." "C:\Users\you\repo" | the backslashes are eaten — the argument vanishes | argument arrives byte-for-byte |
cmd /c dir /c/Windows/... | cmd.exe rejects the MSYS path (exit 1) | native path, native tools, no guessing |
git grep "/fn main" | MSYS rewrites /fn into a Windows path — the pattern silently dies | / is just a character, not a path to convert |
MSYS "solves" paths by guessing: it heuristically rewrites /c/foo into
C:\foo, and famously mangles innocent arguments along the way — the
notorious case of git grep "/pattern" silently becoming
git grep "C:\...\pattern" is why MSYS2 still ships MSYS2_ARG_CONV_EXCL
as an escape hatch. Every native tool call is a game of path roulette.
Winuxsh is the only Windows shell that doesn't translate anything — because it speaks both dialects itself and hands every process its own native language:
❯ cd /c/Users/you/repo # MSYS-style input: understood
C:/Users/you/repo # output: always Windows-native
❯ node -e "console.log(process.cwd())"
C:\Users\you\repo # native binaries get native cwd
❯ cd "C:\Program Files" # Windows-style input: understood
❯ pwd
C:/Program Files
Input in any dialect. Output always native. Zero guessing, zero conversion roulette — for your fingers, and for your agent.
Getting Started with Winuxsh
A short walkthrough from zero to a working prompt with git status.
1. Build or download
git clone https://github.com/unixwin/winuxsh.git
cd winuxsh
cargo build --release
After building, the binary is at target\release\winuxsh.exe. You can run it
directly, or add target\release to your user PATH using your normal Windows
environment settings:
target/release/winuxsh.exe
If you are using the release zip, winuxsh automatically runs the activation script on first start when command links are missing:
winuxsh winuxcmd/activate-winuxcmd.sh
That creates local command links inside winuxcmd/, so ls, cat, and
friends resolve normally. Once the links exist, startup skips activation.
2. Start the shell
winuxsh
You should see something like:
user@DESKTOP C:\Users\you
%
Type exit or press Ctrl+D to quit.
3. See the git prompt
cd into any git repository:
cd C:\Users\you\repo
# if inside a repo, the prompt changes:
user@DESKTOP C:\Users\you\repo git:(main) ●1 ✚2 ?1
%
Symbols at a glance:
| Symbol | Meaning |
|---|---|
●N | N files staged for commit |
✚N | N files modified but unstaged |
?N | N untracked files |
↑N | N commits ahead of upstream |
↓N | N commits behind upstream |
⚑N | N stashes saved |
✖N | N merge conflicts |
The branch name is green when the tree is clean, yellow when dirty.
4. Try some commands
pwd # prints C:/Users/you/repo
ls -la # Unix-style listing
echo "hello from $USER"
for i in 1 2 3; do echo $i; done
if [ -f Cargo.toml ]; then echo "yep"; fi
cat Cargo.toml | grep name
grep -n "fn main" src/main.rs
Windows paths work directly:
ls C:\Windows\System32\drivers\etc
ls D:/Projects
cd "C:\Program Files"
Multiline blocks work naturally:
for f in *.toml; do
echo "found $f"
done
5. Try git completions
git ad<Tab> # completes to `git add`
git commit -<Tab> # shows flags: --message, --all, --amend
git push --fo<Tab> # completes to --force
git branch -<Tab> # shows -d, -D, -m, -v, -a, -r
6. Set up your config
Create ~/.winuxshrc for interactive shell code, plugin selection, and theme
selection:
WINUXSH_THEME=minimal
WINUXSH_THEME_PLUGIN=theme-minimal
WINUXSH_PROMPT_SYMBOL="❯"
export WINUXSH_THEME WINUXSH_THEME_PLUGIN WINUXSH_PROMPT_SYMBOL
WINUXSH_PLUGINS=(prompt-core git)
if [ -z "${HOME:-}" ] && [ -n "${USERPROFILE:-}" ]; then
HOME="$USERPROFILE"
export HOME
fi
if [ -z "${WINUXSH:-}" ]; then
WINUXSH="$HOME/.oh-my-winuxsh"
export WINUXSH
fi
[ -f "$WINUXSH/oh-my-winuxsh.winux" ] && . "$WINUXSH/oh-my-winuxsh.winux"
winuxsh_prompt_use_template "{cwd} {git_prompt}{prompt_char} " "{time} " 2>/dev/null || true
export EDITOR=vim
alias ll='ls -la'
alias la='ls -a'
alias gst='git status'
alias gco='git checkout'
alias gl='git log --oneline --graph --decorate --all'
hello() {
echo "hello from winuxsh"
}
~/.winuxshrc is sourced only for the interactive REPL and the -C
one-shot REPL command path. It does not run for winuxsh -c ..., script files,
or stdin script execution, so agent and CI surfaces stay deterministic.
~/.winshrc is a legacy compatibility fallback and is used only when
~/.winuxshrc is absent. Plugin CLI enable/disable records, migration blocks,
completion overrides, test isolation, and advanced machine state are managed
internally. Prefer ~/.winuxshrc for normal interactive customization.
6b. Prompt and theme plugins
Themes are official plugins. To use a Powerlevel-style theme, switch the theme
plugin in ~/.winuxshrc:
WINUXSH_THEME=p10-lean
WINUXSH_THEME_PLUGIN=theme-p10-lean
WINUXSH_PLUGINS=(prompt-core git)
Useful bundled theme plugins include theme-minimal, theme-classic,
theme-pure, theme-robbyrussell, theme-p10-lean, theme-p10-classic,
theme-p10-rainbow, and theme-p10-pure. Theme assets support named
colours, 256-colour indexes, and true-colour #RRGGBB foreground/background
values plus bold, italic, underline, and dimmed flags.
Prompt templates use the public prompt-core API:
winuxsh_prompt_use_template "{cwd} {git}{prompt_char} " "{status}{time} "
Available template tokens include {cwd}, {cwd_base}, {user_host},
{git}, {git_prompt}, {status}, {time}, {command_execution_time},
{newline}, and {prompt_char}. The Git prompt snapshot is refreshed during
startup/precmd so late Git work warms the next prompt instead of redrawing the
line the user is typing on.
7. Official plugin bundle
Winuxsh has a built-in plugin system. oh-my-winuxsh is the
official bundled plugin distribution. It ships first-party packs such as git, docker, kubectl,
npm, zoxide, direnv, dotenv, fzf, prompt presets, and keybinding
presets.
The normal interactive shape is the ~/.winuxshrc plugin list shown above.
winuxsh plugin enable/disable and migration tooling update internal managed
state. Official shell helper packs can
ship reviewed bundle-local init.winux source scripts. If ~/.winuxshrc
exists, it is the source-plugin entry point and loads the framework directly.
Without ~/.winuxshrc, managed startup can still load enabled source packs
before fallback ~/.winshrc. Use winuxsh plugin list,
winuxsh plugin search, winuxsh plugin themes, and
winuxsh plugin review for current inventory, theme sources, and permission
checks.
What next
- Plugin System Direction for the v3 plugin model
- Plugin System Roadmap for the execution sequence
- Oh My Winuxsh Bundle Plan for the official bundle
- Roadmap to see what is planned
- Source at github.com/unixwin/winuxsh
Advanced Winuxsh Usage
This guide covers the surfaces that matter after the first successful launch: execution modes, startup files, prompt/theme plugins, command discovery, and update/debug workflows.
For first-time setup, start with Getting Started.
Execution Modes
Winuxsh has three intentionally different execution paths:
winuxsh # interactive REPL
winuxsh -c 'pwd; echo "$SHELL"' # quiet script/CI command mode
winuxsh -C 'alias ll; pwd' # one-shot REPL command
- Use the interactive REPL for normal shell work.
- Use
-cfor scripts, tests, CI, and coding agents. It does not load~/.winuxshrc,~/.winshrc, prompt plugins, or interactive lifecycle hooks. - Use
-Conly when a one-shot command needs the same startup state as the interactive REPL. It loads~/.winuxshrcand lifecycle hooks, then exits.
This separation keeps automation deterministic while still allowing a rich interactive shell.
Startup And Config
Use ~/.winuxshrc as the normal human-authored entry point:
WINUXSH_THEME=p10-classic
WINUXSH_THEME_PLUGIN=theme-p10-classic
WINUXSH_PROMPT_SYMBOL=">"
export WINUXSH_THEME WINUXSH_THEME_PLUGIN WINUXSH_PROMPT_SYMBOL
WINUXSH_PLUGINS=(prompt-core git common-aliases path-tools extract)
[ -f "$WINUXSH/oh-my-winuxsh.winux" ] && . "$WINUXSH/oh-my-winuxsh.winux"
alias ll='ls -la'
export EDITOR=vim
The legacy files still exist, but they should not be the primary user path:
~/.winshrcis a fallback only when~/.winuxshrcis absent.- Plugin CLI records, migration blocks, bundle versions, tests, and advanced overrides are internal managed state, not a user configuration file.
Do not put automation-critical behavior only in an interactive rc file. Pass
needed environment variables directly to winuxsh -c or the script process.
Prompt And Themes
Prompt behavior is plugin-owned. The core shell provides host APIs and lifecycle hooks; official theme and prompt behavior lives in bundled plugins.
Common rc shape:
WINUXSH_THEME=p10-lean
WINUXSH_THEME_PLUGIN=theme-p10-lean
WINUXSH_PLUGINS=(prompt-core git)
export WINUXSH_THEME WINUXSH_THEME_PLUGIN
[ -f "$WINUXSH/oh-my-winuxsh.winux" ] && . "$WINUXSH/oh-my-winuxsh.winux"
winuxsh_prompt_use_template "{cwd} {git_prompt}{prompt_char} " "{status}{time} " 2>/dev/null || true
Theme assets can use named colors, 256-color indexes, and true-color
#RRGGBB foreground/background values. Prefer changing the theme plugin or
theme asset instead of hardcoding prompt rendering in shell core.
Git Prompt Performance
Git status should be consumed as a coherent prompt snapshot, not rendered by blocking every prompt draw with fresh Git processes. The intended shape is:
- prompt/theme plugins render the latest available snapshot;
- the host keeps git status work warm in the background;
- late git work updates the next prompt instead of repainting the active input line.
If the prompt flickers or repaints the current line, debug the lifecycle and git snapshot path rather than adding more inline Git calls to the theme.
Plugin Workflow
Use the CLI to inspect the active bundle instead of relying on stale docs:
winuxsh plugin list
winuxsh plugin search git
winuxsh plugin themes
winuxsh plugin info git
winuxsh plugin review git
winuxsh plugin doctor
Normal interactive choices belong in ~/.winuxshrc:
WINUXSH_PLUGINS=(prompt-core git docker kubectl zoxide)
WINUXSH_THEME_PLUGIN=theme-p10-rainbow
Use managed plugin CLI operations when you need a reviewable machine record, permissions, bundle update state, or rollback.
Command Discovery And WPM
Winuxsh resolves Unix-style commands through normal Windows PATH. When a
command is missing or comes from the wrong provider, inspect the active
installation:
command -v winuxsh
command -v winuxcmd.exe
command -v ls
winuxcmd.exe wpm index status
winuxcmd.exe wpm search jq
winuxcmd.exe wpm links rebuild --force
Do not assume /usr/bin exists. Winuxsh is a Windows process using Windows
executables and command links.
Windows Paths And Home
Prefer durable Windows paths in scripts:
cd C:/Users/you/repo
ls "C:\Program Files"
cd ~
Prompt display should normally render the home directory as ~ and descendants
as ~/path, but internal process paths remain native Windows paths. Treat
/c/Users/... as compatibility input, not the primary model.
Updating
Keep the three update planes separate:
winuxsh --self-update --check
winuxsh --self-update
winuxcmd.exe wpm update winuxcmd
winuxsh plugin update oh-my-winuxsh --github-release latest
winuxsh plugin rollback oh-my-winuxsh
winuxsh --self-updateupdates the shell.wpm update winuxcmdupdates command packages and command links.plugin update oh-my-winuxshupdates the official plugin bundle.
Debug Checklist
For shell issues, capture the active binary and execution path first:
winuxsh --version
command -v winuxsh
command -v winuxcmd.exe
echo "$SHELL"
winuxsh -c 'echo command-mode:$SHELL'
winuxsh -C 'echo repl-command:$SHELL'
For repository changes, run focused tests before broad suites:
cargo test --test repl_command --locked
cargo test -p winuxsh-runtime --lib --locked
cargo test --test plugin_inventory --locked
Use Plugin System Direction for architecture and Plugin System Roadmap for execution order.
Installer and Self-Update
Winuxsh ships two Windows package shapes:
winuxsh-v<version>-win-<arch>-setup.exefor normal users.winuxsh-v<version>-win-<arch>.zipfor portable, agent, or scripted use.
The installer is built with Inno Setup and installs per user by default under:
%LOCALAPPDATA%\Programs\Winuxsh
It does not require administrator privileges. The default installer tasks:
- add the install directory to the user's
PATH; - add or update a Windows Terminal profile named
Winuxsh; - set that profile's command line to the installed
winuxsh.exe; - set that profile's starting directory to
%USERPROFILE%; - point the Windows Terminal profile icon at the installed PNG asset.
The Windows Terminal profile is installed by running:
winuxsh --install-wt-profile --quiet
Users can run this command again after moving an install. To also set Winuxsh as the Windows Terminal default profile, run:
winuxsh --install-wt-profile --set-default
Self-update uses Windows WinHTTP directly to follow the GitHub Release
releases/latest redirect, download the latest installer for the current
architecture, and start it silently. It does not depend on the GitHub REST API.
winuxsh --self-update
Inside an interactive Winuxsh REPL, use:
self-update
The REPL command hands the update to a child process and exits the current
shell so the installer can replace winuxsh.exe.
Useful dry-run modes:
winuxsh --self-update --check
winuxsh --self-update --dry-run
Interactive shells check for updates at most once per day. The check is
best-effort and silent on network failures; when a newer release exists, Winuxsh
prints a short hint to run self-update in the REPL or
winuxsh --self-update outside it. Set
WINUXSH_UPDATE_CHECK=0 or WINUXSH_NO_UPDATE_CHECK=1 to disable the reminder.
The installer invokes winuxcmd.exe wpm links rebuild --root ... --force after
copying the files, so the bundled commands are materialized immediately. On NTFS,
WPM creates hard links to the installed winuxcmd.exe. The portable zip keeps the
first-start fallback: if command links are missing, Winuxsh runs
winuxcmd/activate-winuxcmd.sh once from the bundle.
Updating WinuxCmd with WPM
The Unix command set (ls, cat, grep, sed, ...) is delivered by
WinuxCmd and managed separately from the Winuxsh binary. Winux Package
Manager (wpm) handles it:
wpm update winuxcmd # update WinuxCmd from the local index
wpm index status # inspect the local index state
wpm list # indexed packages and install state
wpm update winuxcmd refreshes the command set in place; command links are
rebuilt automatically. Run wpm --help for the full surface (index,
source, search, info, install, links).
So the update story has two parts:
winuxsh --self-update # the shell itself
wpm update winuxcmd # the Unix commands it ships with
Bundled Plugin Baseline
Release packages also stage the official oh-my-winuxsh bundle under:
bundles\oh-my-winuxsh
The runtime checks that app-bundled path after user-managed bundle locations:
%LOCALAPPDATA%\Winuxsh\bundles\oh-my-winuxsh\current
%LOCALAPPDATA%\Winuxsh\bundles\oh-my-winuxsh\<version>
bundles\oh-my-winuxsh
Fresh offline installs can still list and use official plugins, while
winuxsh plugin update oh-my-winuxsh ... can replace the baseline without
rewriting the application install directory.
Rubash Bash Compatibility Matrix
This matrix keeps the bounoary clear: rubash owns shell language semantics, while Winuxsh owns Winoows host integration, REPL behavior, completion, plugin routing, ano winuxcmo commano oiscovery. Use it when oecioing whether a fix belongs in rubash or in the Winuxsh host layer.
Verification Layers
| Layer | Scope | Current evioence |
|---|---|---|
| Local compat fixtures | Focuseo Winuxsh binary tests for common bash semantics that oepeno on rubash plus winuxcmo commano links. | CARGO_TARGET_OIR=target/cooex-verify-phase17 cargo test --test compat --lockeo -- --ignoreo passeo 18/18 on 2026-07-31. |
| Host contract tests | Winoows process, cwo, stoin, script, env, ano stoio behavior arouno rubash execution. | Covereo by tests/host_contract.rs; full workspace test passeo in the Phase 16 verification run. |
| GNU Bash upstream local gate | Broaoer upstream bash fixture from a sibling rubash checkout, intentionally local-only ano not venooreo. | OOCS/bash-upstream-local.mo recoros the gate ano the expecteo 86 total / 86 pass / 0 fail result from the 2026-07-28 local run. |
Focuseo Compat Fixtures
| Capability | Evioence fixture(s) | Status | Bounoary |
|---|---|---|---|
| Variables ano simple parameter expansion | var_expansion, string_param | Passing | rubash parser/executor. |
| Commano substitution | commano_substitution, commano_substitution_quoteo_newline, commano_substitution_function_pipeline | Passing | rubash commano substitution; host still owns -c quoting ano process invocation. |
| Arithmetic expansion | bash_smoke section [2] arithmetic | Passing | rubash arithmetic evaluator. |
| Inoexeo arrays | bash_smoke sections [3] arrays, [16] array slice | Passing | rubash arrays ano parameter expansion. |
| Associative arrays | bash_smoke section [4] assoc arrays | Passing | rubash oeclare -A ano associative lookup. |
| Boolean list status | ano_or_status, bash_smoke section [20] exit status | Passing | rubash &&, ` |
| If / elif / else | if_else, multiline_if, bash_smoke section [11] if | Passing | rubash compouno commanos; Winuxsh must feeo full scripts to rubash. |
| For loops | for_loop, multiline_for, bash_smoke sections [6] for list, [7] for c | Passing | rubash loop parser/executor. |
| While / until loops | bash_smoke sections [8] while, [9] until | Passing | rubash loop parser/executor. |
| Case statements | bash_smoke section [12] case | Passing | rubash case parser/executor. |
| Functions | function, commano_substitution_function_pipeline, bash_smoke section [10] function | Passing | rubash function oefinition ano invocation. |
| Aliases | alias | Passing | Winuxsh installs aliases into rubash; expansion is rubash-owneo. |
| Pipelines | pipeline, commano_substitution_function_pipeline, bash_smoke section [13] pipeline | Passing | rubash pipeline execution plus winuxcmo commano links. |
| Reoirection | bash_smoke section [14] reoirect | Passing | rubash reoirection with Winuxsh/winuxcmo filesystem behavior. |
| Hereoocs | hereooc | Passing | rubash whole-script parsing; host stoin/script path must avoio line-by-line splitting. |
| Backslash continuations | continuation | Passing | rubash whole-script parsing. |
| Echo flags | echo_flags | Passing | shell builtin behavior as exposeo through rubash/winuxsh. |
| Export to Winoows chilo process | bash_smoke section [19] export | Passing | rubash environment plus Winuxsh process environment synchronization. |
| File tests | bash_smoke section [18] file tests | Passing | rubash test builtin plus host filesystem paths. |
Host Contract Coverage
| Host surface | Evioence | Notes |
|---|---|---|
| cwo authority | cwo_co_pwo_ano_winoows_chilo_process_agree, orive_only_co_ano_bare_orive_commanos_switch_to_orive_root | Winuxsh normalizes/synchronizes shell PWO with Winoows chilo process cwo. |
| startup isolation | winshrc_ooes_not_run_for_non_interactive_mooes | Non-interactive -c, script file, ano stoin script paths oo not source REPL startup rc. |
| temporary assignments | temporary_assignment_reaches_nesteo_winuxsh_chilo | Assignment semantics are observable by nesteo Winuxsh chilo processes. |
| stoin scripts | pipeo_stoin_without_args_runs_plain_script_surface, pipeo_stoin_without_args_runs_multiline_compouno_block, pipeo_stoin_without_args_runs_hereooc_as_one_chunk | Host feeos complete stoin scripts to rubash for multiline/hereooc semantics. |
| script positional parameters | script_file_args_populate_positional_parameters | Host script path preserves $0/positional parameter behavior. |
| Winoows chilo env | exporteo_env_reaches_winoows_chilo_processes, sourceo_rc_keeps_winuxcmo_visible_to_winoows_chiloren | Winuxsh brioges rubash env changes into Winoows chilo process launches. |
| stoio ano exit cooe | stoout_stoerr_ano_exit_cooe_are_preserveo, closeo_stoout_pipe_ooes_not_print_broken_pipe_error | Host preserves process surfaces expecteo by agents. |
| commano-mooe parsing eoge cases | commano_mooe_accepts_base_prefixeo_arithmetic_in_function_booy, commano_mooe_parameter_pattern_removal_hanoles_escapeo_quotes, commano_mooe_set_positional_splits_custom_ifs | Focuseo regressions for rubash-facing -c script oelivery. |
Known Gaps ano Routing
| Gap | Route |
|---|---|
| Full GNU Bash upstream gate is local-only ano not normal CI. | Keep using OOCS/bash-upstream-local.mo; oo not venoor upstream bash tests. |
winuxsh -c still has host-sioe rough eoges arouno POSIX assignment prefixes, env VAR=value cmo, hereooc temp-file flows, ano complex quoting in agent commanos. | Track as Winuxsh commano-mooe/host issues, not as rubash language failures unless a oirect rubash fixture reproouces it. |
| Job control ano interactive terminal process-group semantics are not covereo by the focuseo compat matrix. | Route through rubash first; aoo Winuxsh host tests only for Winoows process integration. |
| Plugin runtime behavior is intentionally outsioe current shell compatibility scope. | Keep in plugin docs; oo not mix with bash language compatibility claims. |
Maintenance Rules
- Aoo one focuseo fixture unoer
tests/compat/fixtures/before claiming a new bash-language capability in REAOME or roaomap. - Prefer host contract tests for Winoows cwo/env/stoin/stoout issues that happen arouno rubash rather than insioe rubash.
- Re-run the ignoreo compat suite before upoating this matrix:
CARGO_TARGET_OIR=target/cooex-verify-phase17 cargo test --test compat --lockeo -- --ignoreo. - Use the upstream local gate only when parser/executor behavior changes or when syncing a new rubash revision.
Winuxsh v2 Architecture
基于 rubash + winuxcmd 的 Windows 原生 Bash-compatible terminal
项目定位
winuxsh 是一个 Windows 原生、无隔离、给人和 agent 都可以直接使用的 Bash-compatible terminal。它不自己实现 shell 语言,而是作为 rubash lib(bash 兼容引擎)的交互式前端 + winuxcmd(coreutils)的路由层。它的核心价值在于 Windows 原生进程/环境体验:reedline REPL、补全系统、主题系统、Ctrl+C 处理、终端集成,以及稳定的非交互式 agent 执行契约。
winuxsh 不是 MSYS2、Git Bash、Cygwin 或 WSL 风格的隔离环境。~ 指向普通 Windows 用户 home(PowerShell 中的 home / USERPROFILE / dirs::home_dir()),PATH、cwd、env、stdout、stderr、exit code 都是正常 Windows 进程状态。
三层架构
winuxsh.exe
├── winuxsh 自身层 (Rust)
│ ├── rubash::Executor ← shell 语言引擎 (lexer/parser/execution/builtins)
│ ├── reedline REPL ← 行编辑、历史、补全
│ ├── completion/ ← shell definitions + bash 自动导入 + 三级缓存
│ ├── theme/ ← 主题 API / schema / bundle loader
│ ├── config ← legacy/managed machine-state 读取
│ ├── plugins ← Winuxsh 官方插件 registry / bundle 控制面
│ └── ctrl_c ← Win32 Ctrl+C 处理
├── rubash lib (Rust)
│ ├── lexer/parser/ast
│ ├── executor (pipeline/redirect/alias/function/array/job)
│ └── builtins (cd/source/export/set/test/printf...)
└── winuxcmd.exe (C++) ← Unix coreutils (ls/cat/grep/find/cp/mv/rm...)
关键设计决策
1. rubash 作为 lib 依赖
winuxsh 直接链接 rubash 作为 Rust crate 依赖:
[dependencies]
rubash = { git = "https://github.com/unixwin/rubash.git", branch = "master" }
所有 shell 语义(解析、执行、内建命令、变量展开、重定向、管道、作业控制)委托给 rubash。winuxsh 不重复实现 lexer/parser/ast/builtins。
2. WinuxCmd 由 Winuxsh 选择并通过 PATH 集成
不是通过 FFI/DLL——rubash Executor 仍然通过 PATH 查找外部命令。版本选择 属于 Winuxsh 的 session/config 责任,在启动时:
- 读取显式
WINUXCMD_PATH,必要时再按 Winuxsh 自己的安装/bundle/PATH 规则寻找一个winuxcmd.exe - 将同一个 exe 所在目录前置到进程
PATH,以提供ls/cat/grep等 command links - 将解析出的精确 exe 路径通过
Executor::set_winuxcmd_path传给 rubash
Rubash 不会再从 PATH 猜测另一个 winuxcmd.exe。这样即使 Windows PATH 中
同时存在旧 bundle 的 command links,也不会把 dispatcher 和 links 混用。
3. Windows real installation tree
Winuxsh derives one shell root from the selected installed
winuxcmd.exe. For example, the executable
<install>/usr/bin/winuxcmd.exe makes <install> the root. Winuxsh creates
the ordinary directories below that root:
<install>/usr/bin
<install>/bin
<install>/usr/local/bin
<install>/etc
<install>/var
<install>/tmp
<install>/dev
<install>/.wpm
usr/bin is canonical for WinuxCmd, WPM, command links, and filename-only WPM
targets. Explicit package targets keep their requested real directory.
Winuxsh passes the selected installation root to Rubash through
WINUXSH_ROOT; there is no second ~/.winuxsh/root tree and no provider
union. Rubash maps /, /bin, /usr/bin, /etc, and /tmp directly below
the real root. /dev/null maps to Windows NUL; other /dev entries remain
unsupported capabilities.
4. 补全系统独立于引擎
补全系统(shell 定义 + bash 脚本自动导入 + cmd -h 描述抓取 + 三级缓存)在 winuxsh 侧实现,不依赖 rubash。这是 winuxsh 的核心差异化能力。
5. 配置与启动入口
~/.winuxshrc是主要交互式入口,用普通 winuxsh/bash 语法声明插件列表、 主题、prompt 模板、export、alias、函数和本地启动逻辑。~/.winshrc是兼容 fallback;只有~/.winuxshrc不存在时才作为旧用户 rc 启动文件读取。- plugin CLI 的启停记录、权限、bundle 版本、legacy managed blocks、测试隔离、补全 目录等机器状态由内部 managed-state 机制维护,不是用户配置入口。
- 当
~/.winuxshrc存在时,它是 source plugin/framework 的入口;host 不再 同时从 managed-state 默认插件状态偷偷 source 一遍官方 source plugins,避免双入口和 prompt/Git 状态重复刷新。 - 普通
winuxsh -c、脚本文件和 stdin 脚本仍保持安静确定,不加载交互式 rc 或 source plugins。
设计原则是减少人类可见入口:用户日常只改 ~/.winuxshrc;机器状态由
Winuxsh 自己维护,用户不需要编辑其存储格式。
5. 插件系统
v3 插件系统是 Winuxsh 自己的插件系统。
oh-my-winuxsh作为官方 bundled plugin distribution 随 winuxsh 发行。- git/docker/kubectl/npm 这类 shell helper 可以作为
kind = "source"的 first-party pack,从 bundle 内init.winux加载。 - zoxide/direnv/dotenv/fzf 等需要更强 host 行为的能力继续由
kind = "builtin"或后续显式 effect/runtime API 承接。 - 第三方插件当前通过受审阅的 source packs 和 process adapters 接入,权限模型由 manifest 统一声明。
- process/IPC 插件是外部工具桥和调试后端。
- 插件不能扩展 rubash parser/executor,也不能 source 任意 legacy
.winsh或用户目录里发现的 rc 片段。source pack 只能加载 manifest 声明的 bundle-local.winux文件,并且需要shell:source权限。 - Winuxsh 编辑器能力由 reedline 和 Winuxsh 原生 keybinding presets 提供。
目录结构
winuxsh/
├── Cargo.toml
├── LICENSE # GPL-3.0-or-later
├── README.md / README-zh.md
├── .winuxshrc # primary interactive user entry
├── .winshrc # legacy fallback rc
├── managed state # internal machine-managed state
├── crates/
│ └── winuxsh-runtime/
│ ├── Cargo.toml
│ └── src/
│ ├── lib.rs # 库入口
│ ├── shell.rs # Shell 状态
│ ├── repl.rs # reedline REPL
│ ├── ctrl_c.rs # Win32 Ctrl+C
│ ├── config.rs # 配置解析
│ ├── winuxcmd.rs # winuxcmd 探测
│ ├── prompt.rs # Prompt 渲染
│ ├── theme.rs # 主题系统
│ └── completion/ # 补全系统
├── src/
│ └── main.rs # 入口
└── docs/
├── src/
│ └── (this documentation book)
└── planning/
数据流
用户输入 "ls -la | grep foo"
│
▼
reedline (行编辑 + 补全)
│
▼
shell.execute_line(line) ← winuxsh-runtime
│
├─ rubash::lexer::tokenize(line)
├─ rubash::parser::parse(tokens) → Ast
└─ executor.execute_ast(&ast) ← rubash 处理全部语义
│
├─ 内建命令 (cd/source/echo...)
├─ 外部命令 → find_user_command("ls")
│ │ (PATH 已注入 winuxcmd 目录)
│ ▼
│ winuxcmd.exe ls -la
│
├─ 管道: | grep foo → find_user_command("grep")
└─ 输出到 stdout
与旧架构的差异
| 方面 | v1 (旧 winuxsh) | v2 (新 winuxsh) |
|---|---|---|
| Shell 引擎 | 自研 winsh-lexer/parser/ast | rubash lib |
| Coreutils | winuxcmd FFI (DLL, 已禁用) | winuxcmd.exe 进程 (PATH 注入) |
| 命令路由 | command_router.rs 分类表 | rubash 内部 find_user_command |
| 内建命令 | builtins.rs 自实现 | rubash::builtins |
| 补全系统 | src/completion/ | 完整保留迁移 |
| 主题系统 | theme.rs (8 主题) | 精简为 4 内置主题 |
| 插件系统 | Plugin trait + Oh-My-Winuxsh | 移出 v1,后续迭代 |
| 许可协议 | MIT | GPL-3.0-or-later |
版本规划
- v2.2: rubash rewrite 稳定化、补全增强、Vi/Ctrl+R、配置一致性、用户主题
- v2.3: Windows 原生 terminal contract、agent 友好的非交互式行为、history/prompt/completion UX
- v2.4: 交互体验 polish(右 prompt、提示、补全菜单、默认配置)
- v3: 内置 Winuxsh 插件系统;
oh-my-winuxsh作为官方 bundled plugin distribution;先用builtinregistry 统一现有 first-party packs,再引入 第三方插件通过 source/process runtime 接入。 - 非目标: Linux/macOS 原生 shell 产品;rubash 可跨平台复用,但 winuxsh 产品目标是 Windows
Last updated: 2026-07-30
Windows Path Contract
Winuxsh uses a real Windows directory tree for its Unix-shaped shell paths. This is path spelling support, not MSYS, WSL, Cygwin, a POSIX runtime, or a filesystem overlay.
Ownership
| Layer | Responsibility |
|---|---|
| Winuxsh | Select one winuxcmd.exe, derive its installation root, create the real tree, and configure the shell session. |
| Rubash | Interpret /, /bin, /usr/bin, /etc, /tmp, cd, source, glob, redirects, tests, and command lookup. |
| WinuxCmd | Implement external commands and native Windows filesystem, process, handle, and device operations. |
| WPM | Install package payloads and command links inside the selected installation root. |
Installation Root
For an installed executable such as:
C:/Users/Administrator/AppData/Local/Programs/Winuxsh/winuxcmd/usr/bin/winuxcmd.exe
the shell root is:
C:/Users/Administrator/AppData/Local/Programs/Winuxsh/winuxcmd/
usr/bin/
bin/
usr/local/bin/
etc/
var/
tmp/
dev/
.wpm/
These are ordinary Windows directories. usr/bin is canonical for
winuxcmd.exe, wpm.exe, command links, and filename-only WPM targets.
Explicit WPM targets under bin, usr/bin, or usr/local/bin remain in that
exact directory. .wpm is private package state and is never a command path.
Winuxsh passes this exact root to Rubash as WINUXSH_ROOT. Rubash maps paths
lexically below it:
/ -> <root>
/usr/bin/tool -> <root>/usr/bin/tool
/bin/tool -> <root>/bin/tool
/etc/config -> <root>/etc/config
/tmp/file -> <root>/tmp/file
Command lookup and native child PATH use these real directories directly.
Rubash does not merge a second provider directory, and WinuxCmd coreutils do
not inspect Winuxsh variables. Existing flat installations remain usable when
their directory is explicitly present on PATH; new installs use the tree
above.
Dispatcher Selection
WINUXCMD_PATH selects one exact dispatcher executable for the session.
Winuxsh resolves it, prepends that installation's usr/local/bin, usr/bin,
and bin directories to the native PATH, and passes the exact executable to
Rubash. Rubash does not discover another dispatcher from PATH.
The dispatcher is only a fallback when a command is absent from the real tree.
It must not implement Rubash builtins such as cd, export, set, read,
jobs, or trap.
Special Paths
~ is USERPROFILE, the same directory used by PowerShell. Windows paths
such as C:/work/file and /c/work/file remain host paths.
The only device spelling currently supported is /dev/null, mapped to the
native NUL endpoint. Other /dev entries do not become ordinary files until
their fd or terminal capability is implemented.
tags: [winuxsh, roadmap] created: 2026-07-13 status: active
Winuxsh Roadmap
Winuxsh is a Windows-native, non-isolated Bash-compatible shell for humans and agents.
winuxsh = rubash + winuxcmd + reedline + oh-my-winuxsh
Done
rubashis embedded as the shell language engine.- WinuxCmd command links provide bundled Unix-style commands through PATH.
- The REPL uses reedline for editing, history, menus, autosuggestions, syntax highlighting, vi/emacs modes, and prompt rendering.
~/.winuxshrcis the primary interactive startup file.~/.winshrcis an old fallback only when~/.winuxshrcis absent.- Plugin CLI decisions, permissions, bundle versions, tests, and advanced overrides are maintained as internal managed state, not user configuration.
- Plugin inventory, review, doctor, enable/disable, update, and rollback surfaces exist.
oh-my-winuxshis the official bundled plugin distribution.- Git completions, Git prompt status, prompt templates, and p10-style segment presets are available.
- Host contract tests cover cwd, env, stdin, stdout/stderr, script args, command-mode parsing, and exit-code propagation.
Current Direction
- Keep shell semantics in
rubash; fix parser, executor, builtins, redirects, pipelines, functions, jobs, and Bash language behavior upstream. - Keep Windows host integration in Winuxsh: cwd/env synchronization, PATH injection, installer behavior, command links, prompt rendering, and REPL UX.
- Model the plugin system after mature shell frameworks: named packs in a bundle, pack manifests, sourceable helper files, exported aliases, completions, functions, hooks, prompt segments, keybindings, and themes.
- Keep prompt layout user/theme owned. Providers such as native Git status or Starship-backed Git supply segment data; they do not replace the whole prompt unless the selected theme chooses that layout.
- Keep third-party integration on reviewed source packs and explicit process adapters until a real host API justifies another runtime.
Near-Term Work
- Normalize first-party pack manifests around exports and permissions.
- Move more alias/completion/theme assets from compiled fallback into the
bundled
oh-my-winuxshdistribution. - Split prompt responsibilities clearly:
- theme owns layout and connective text;
- prompt-core renders templates;
- Git/Starship providers supply data for
{git}and related tokens.
- Add regression tests for installed bundle startup, prompt provider selection, and missing external binaries.
- File and fix WinuxCmd command issues separately from rubash language issues.
Verification
- Fast loop:
cargo fmt --check -p winuxsh; cargo build --locked; cargo test --workspace --locked - Runtime library:
cargo test -p winuxsh-runtime --lib --locked - Host contract: run the ignored host suites with WinuxCmd command links in PATH when changing PATH, cwd, env, or command-link behavior.
- Local Bash upstream gate remains local-only and should report 86 total, 86 passed, 0 failed for the Winuxsh binary under test.
Locked Decisions
- License: GPL-3.0-or-later.
rubashfollows latestunixwin/rubashmaster.- WinuxCmd stays integrated through PATH injection and command links.
~/.winuxshrcis the normal user-authored interactive config.- Machine-managed state is not a human-authored configuration surface.
oh-my-winuxshis the official bundle, not a fork of another shell framework.