AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
Bash commands for PowerShell — real flags, real output, typed objects underneath. 67 commands, 775 tests, cross-platform.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Real bash commands on Windows. No WSL, Git Bash, or Cygwin required.
PsBash transpiles bash to PowerShell — rm -rf, ls -la, grep -r, sort -k3 all work natively. Every command returns typed .NET objects while producing bash-identical text output. Includes a standalone shell binary that AI coding agents (Claude Code, OpenCode, GitHub Copilot) can use as a drop-in bash replacement.
As a standalone shell binary (no .NET runtime required):README 전문 보기 ↗Real bash commands on Windows. No WSL, Git Bash, or Cygwin required.
PsBash transpiles bash to PowerShell — rm -rf, ls -la, grep -r, sort -k3 all work natively. Every command returns typed .NET objects while producing bash-identical text output. Includes a standalone shell binary that AI coding agents (Claude Code, OpenCode, GitHub Copilot) can use as a drop-in bash replacement.
As a PowerShell module:
Install-Module PsBash
As a standalone shell binary (no .NET runtime required):
# Windows
iwr https://raw.githubusercontent.com/standardbeagle/ps-bash/main/install.ps1 | iex
# Linux / macOS
curl -fsSL https://raw.githubusercontent.com/standardbeagle/ps-bash/main/install.sh | bash
On Windows, -InstallDir must be empty or marked as a PsBash package by this installer.
Move an older unmarked installation aside before upgrading. Upgrades retain the old
package in a unique .previous-* directory; existing backups are preserved.
PowerShell ships aliases for ls, cat, sort, rm — but they're lies. rm -rf fails. ls -la fails. sort -k3 -rn fails. They're Get-ChildItem, Get-Content, and Sort-Object wearing a disguise, rejecting every bash flag you throw at them.
PsBash makes the flags work — and goes further. Every command returns typed .NET objects while producing bash-identical text output.
# Before: string parsing
PS> Get-Process | Format-Table -Auto | Out-String | ForEach-Object { $_ -split "`n" } |
>> Where-Object { $_ -match 'pwsh' }
# Good luck extracting CPU from that
# After: typed objects through the entire pipeline
PS> $top = ps aux | sort -k3 -rn | head 5
PS> $top[0].ProcessName # pwsh
PS> $top[0].CPU # 12.4 (decimal, not a string)
PS> $top[0].PID # 1847 (integer, not a substring)
PS> $top | Where-Object { $_.CPU -gt 5.0 } | ForEach-Object { Stop-Process $_.PID -WhatIf }
PS> ls -la | grep '.ps1' | sort -k5 -h
-rw-r--r-- 1 beagle wheel 4521 Apr 2 00:57 PsBash.psd1
-rw-r--r-- 1 beagle wheel 89234 Apr 2 09:46 PsBash.Tests.ps1
-rw-r--r-- 1 beagle wheel 141234 Apr 2 09:46 PsBash.psm1
# grep matched the TEXT, but passed through the TYPED OBJECTS:
PS> $files = ls -la | grep '.ps1' | sort -k5 -h
PS> $files[0].GetType().Name # PSCustomObject (LsEntry)
PS> $files.Name # PsBash.psd1, PsBash.Tests.ps1, PsBash.psm1
PS> $files.SizeBytes | Measure-Object -Sum | Select -Expand Sum
234989
PS> echo '{"db":"postgres","port":5432}' | jq '.db'
"postgres"
PS> cat app.log | grep ERROR | awk '{print $1, $3}' | sort | uniq -c | sort -rn | head 5
47 2024-01-15 DatabaseError
23 2024-01-15 TimeoutError
12 2024-01-15 AuthError
PS> find . -name '*.log' -mtime +7 | xargs rm -f # actually works on Windows
PsBash can be used as a PowerShell module or a standalone shell. They share the same 77 bash commands and typed object pipeline.
Install-Module PsBash
ls -la | grep '.cs' | sort -k5 -h # typed objects through the pipeline
$procs = ps aux | sort -k3 -rn | head 5 # .PID, .CPU are real .NET types
Best for: scripts, VS Code terminal, CI/CD, mixing bash with PowerShell cmdlets.
# Launch as your shell
ps-bash
# Inside: bash aliases, .psbashrc, colored prompt, external tools
ll # alias: ls -al
cd ~/projects && git status # cd + external git
claude # full interactive AI session
Best for: Windows Terminal, AI coding agents (Claude Code, OpenCode), replacing WSL/Git Bash.
→ See the full Shell Guide for setup, configuration, mixing bash + PowerShell, and limitations.
Install the PsBash module, which bundles the binary cmdlets. PowerShell 7.4 or later is required:
Install-Module PsBash
Import-Module PsBash
Quickstart:
# Run bash through the separately installed shell executable
ps-bash -c 'ls -la | grep .ps1'
# Source a bash script into the current PowerShell session
Invoke-BashSource ./my-script.sh
# Test if a bash command is valid syntax
Test-BashSyntax 'echo hello | wc -l'
→ See the Shell Guide for details on dynamic-env tools and advanced usage.
Invoke-BashEval is experimental and excluded from default builds. Format-Styled and
Show-Styled require an optional Strata build dependency and are absent from builds
without it. The shell, source and syntax commands above do not require those features.
The shell currently refuses set -u/set -o nounset and set -C/set -o noclobber
because their protections are not implemented. Unsupported launcher flags also exit 2;
use ps-bash -c 'set -e; ...' for errexit rather than a launcher -e flag.
Other unsupported set options and mixed option forms also fail explicitly. Use
separate set commands for supported options and set -- ... for positional parameters.
Ps-bash works as a drop-in bash replacement for AI coding agents on Windows. Agents invoke ps-bash -c "command" and it transpiles bash to PowerShell transparently.
Agent runs can opt into compact output mode with --compact-output or
PSBASH_COMPACT_OUTPUT=1. The launcher normalizes the setting and passes it to
the host/output layer as PSBASH_COMPACT_OUTPUT=1; without either setting,
behavior is unchanged. An explicit CLI flag wins over the environment, so
--no-compact-output disables compaction for a single invocation even when the
environment variable is set. --caveman and --wenyan are accepted aliases for
the same opt-in mode.
When enabled, ps-bash keeps command identity, exit code, timeout status, stream labels, stderr presence, file/line diagnostics, and useful tail context while collapsing repeated lines and verbose progress/listing noise.
Use compact mode for agent and CI log capture where token volume matters. Leave it off when you need exact byte-for-byte stdout/stderr, full progress logs, or human-facing interactive output.
ps-bash --compact-output -c "dotnet test"
$env:PSBASH_COMPACT_OUTPUT = '1'
ps-bash -c "git status"
ps-bash --no-compact-output -c "git status"
Claude Code only accepts a Windows shell whose file is named bash.exe (or
sh.exe); it silently falls back to Git Bash for any other name. So give it
ps-bash under that name — a copy of ps-bash.exe placed in the same folder
(it keeps loading ps-bash.dll beside it). install-local.ps1 creates it for you:
Copy-Item $env:USERPROFILE\.local\bin\ps-bash.exe $env:USERPROFILE\.local\bin\bash.exe
Then in ~/.claude/settings.json, and restart Claude Code (it picks its shell at startup):
{
"env": {
"CLAUDE_CODE_GIT_BASH_PATH": "C:\\Users\\you\\.local\\bin\\bash.exe",
"PSBASH_UNIX_PATHS": "1"
}
}
Verify from a new session: echo $BASH_VERSION in the Bash tool prints
0.x.0(1)-release (ps-bash), not 4.4.x/5.x (Git Bash).
$env:SHELL = 'C:\Users\you\.local\bin\ps-bash.exe'
opencode
In VS Code settings.json:
{
"terminal.integrated.profiles.windows": {
"ps-bash": {
"path": "C:\\Users\\you\\.local\\bin\\ps-bash.exe"
}
},
"terminal.integrated.defaultProfile.windows": "ps-bash"
}
| Agent | Config Method | Setting |
|---|---|---|
| Claude Code | settings.json env (restart after) | CLAUDE_CODE_GIT_BASH_PATH=C:\path\to\bash.exe (a copy of ps-bash.exe, same folder) |
| OpenCode | $SHELL environment variable | $env:SHELL = 'C:\path\to\ps-bash.exe' |
| GitHub Copilot | VS Code terminal profile | terminal.integrated.defaultProfile.windows |
| Gemini CLI | Not configurable (hardcoded shell) | Run inside ps-bash interactive shell |
See docs/agent-setup.md for detailed per-agent configuration, Docker setup, and troubleshooting.
| PsBash | Git Bash | Cygwin | WSL | Crescendo | |
|---|---|---|---|---|---|
| Install | Install-Module | Git for Windows | 50+ packages | Hyper-V/WSL2 | Per-command XML |
| Footprint | 340 KB, 3 files | ~300 MB (MSYS2 runtime) | ~1-4 GB | ~1-15 GB (full distro) | Module + your wrappers |
rm -rf works | Yes | Yes | Yes | Yes | If you configure it |
| Typed objects | Always | Never (strings) | Never (strings) | Never (strings) | If configured |
| Object pipeline | Types survive grep | sort | head | Strings only | Strings only | Strings only | Varies |
| PowerShell integration | Native — objects flow into cmdlets | Separate shell | Separate shell | Separate shell | Native |
| Cross-platform | Win/Lin/Mac | Windows only | Windows only | Windows only | Win/Lin/Mac |
| Commands | 77 built-in | ~80 (GNU coreutils) | ~200+ (full GNU) | All of Linux | Define your own |
| jq/awk/sed | Built-in, zero binaries | awk/sed yes, jq no | Yes (install pkg) | Yes (apt install) | Not included |
| PATH conflicts | None (AllScope aliases) | Shadows PowerShell | Shadows PowerShell | Filesystem boundary | None |
| Startup overhead | ~100 ms (module load) | New process per call | New process per call | ~1s (cold), ~200ms (warm) | ~100 ms |
| AI agent shell | Yes (ps-bash -c) | No | No | No | No |
| Interactive mode | Yes (aliases, prompt, external tools) | Yes (full bash) |
| Category | Commands |
|---|---|
| Listing | ls find stat tree du pwd basename dirname realpath dirs |
| Files | cp mv rm mkdir rmdir touch ln |
| Content | cat head tail less tac wc nl rev strings fold expand unexpand split |
| Search | grep rg |
| Text | sed awk cut tr uniq sort column join paste comm diff |
| Pipeline | tee xargs yes |
| Data | jq yq xan |
| System | ps env date hostname whoami which alias time sleep tput pushd popd |
| Shell | shopt type source command unset shift |
| Output | echo printf |
| Encoding | base64 |
Every command supports --help and tab completion for all flags.
| Task | PsBash | Native PowerShell |
|---|---|---|
| List files | ls -la | Get-ChildItem -Force | Format-List |
| Find by name | find . -name '*.ps1' | Get-ChildItem -Recurse -Filter *.ps1 |
| Top 5 CPU | ps aux | sort -k3 -rn | head 5 | Get-Process | Sort-Object CPU -Desc | Select -First 5 |
| Count lines | wc -l file.txt | (Get-Content file.txt).Count |
| Search files | grep -r 'TODO' src/ | Select-String -Path src/* -Pattern TODO -Recurse |
| JSON field | cat f.json | jq '.name' | (Get-Content f.json | ConvertFrom-Json).name |
| Delete tree | rm -rf dist/ | Remove-Item dist/ -Recurse -Force |
| Disk usage | du -sh * | sort -rh | Get-ChildItem | Sort Length -Desc | Select Name,Length |
Both sides give you objects. PsBash just lets you type what you already know.
Every PsBash command returns a PSCustomObject with a .BashText property. The terminal renders BashText (looks like real bash). Your code accesses typed properties.
ls -la
|
Invoke-BashLs
|
[LsEntry] objects
.Name = "README.md"
.SizeBytes = 4521 [int]
.Permissions = "-rw-r--r--" [string]
.Owner = "beagle" [string]
.LastModified = 2024-04-02... [DateTime]
.BashText = "-rw-r--r-- 1 beagle wheel 4521 Apr 2 ..."
Pipeline commands (grep, sort, head, tail, tee) match against BashText but pass through the original typed objects. This is the pipeline bridge — the core architectural pattern.
The standalone ps-bash binary adds a transpiler layer:
bash input → BashLexer → BashParser → PsEmitter → IpcWorker → ps-bash-host/SdkWorker → PowerShell SDK
The parser tokenizes and parses bash into an AST modeled on Oils syntax.asdl. The emitter maps bash commands to Invoke-Bash* functions, forwarding all arguments unchanged. The runtime PowerShell module handles all flag parsing with full bash-compatible behavior.
Invoke-Pester ./tests/PsBash.Tests.ps1
# 857 tests: 561 Core (parser/emitter), 96 Shell (e2e), 200 Module (runtime)
CI runs on Windows, Linux, and macOS via GitHub Actions.
| Feature | Linux/macOS | Windows |
|---|---|---|
| File permissions | Real POSIX (rwxr-xr-x) | Approximated from ACLs |
ps backend | /proc filesystem | .NET System.Diagnostics.Process |
ln -s | Works normally | Requires Developer Mode |
stat | /usr/bin/stat | Pure .NET implementation |
dev.standardbeagle.com/ps-bash — full command reference, object type specs, pipeline cookbook, cross-platform guide.
MIT
Issues and PRs welcome.
| Yes (full bash) |
| Yes (full Linux) |
| No |
md5sumsha1sumsha256sumfile| Archive | gzip gunzip zcat tar |
| Math | seq expr |