Help us shape the future of Go! Take the 2026 Go Developer Survey

bashy

module
v0.23.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 18, 2026 License: BSD-3-Clause

README

bashy — a pure-Go Bash 5.3 drop-in

bashy is a single static binary that runs Bash scripts and interactive sessions. It is written entirely in Go (no CGo, no system Bash required) and is a drop-in replacement for bash 5.3 — same command-line flags, same script semantics, same $BASH_VERSION — that passes GNU Bash's own 5.3 test suite (every runnable fixture; see Status below).

It is built on the qiangli/sh fork of mvdan.cc/sh, which carries the Bash 5.3 interpreter work. bashy is the user-facing shell; sh is the library.

Status: bashy passes 100% of GNU Bash's own 5.3 test suite — every measured fixture (86/86: 0 failing, 0 skipped) on Linux and macOS (see docs/TODO.md). That includes job control, coprocesses, signal traps, and locale-aware (non-UTF-8) globbing — features the early goroutine-based runner couldn't do, now implemented.

Known limitations: arithmetic uses the native int width, so 64-bit values on 32-bit builds (GOARCH=386) truncate (a 64-bit-int migration is tracked); and Windows builds and runs but its full test-suite run is still being verified. As in Bash itself (jobs.c vs nojobs.c), OS-level job control is a Unix feature.

POSIX conformance campaign identity

Bashy's licensed Open Group campaign uses VSC-PCTS2016 version 3.1 with the VSC 5.4.1 framework/documentation, configured in the suite's POSIX08 profile (VSC_POSIX_VERSION=200809) with the XSI/X/Open profile disabled (VSC_XOPEN_VERSION=0). The formal certification target for that suite is the 1003.1-2016 Shell and Utilities Product Standard.

That wording is deliberate. IEEE Std 1003.1-2017 is a later publication in the same POSIX.1-2008 / Issue 7 lineage, but it is not the Product Standard name for which VSC-PCTS2016 is authorized. Do not describe this campaign as a “VSC-PCTS2017” or “1003.1-2017 certification” run.

Running the suite provides conformance evidence; it does not by itself make Bashy POSIX certified. Certification and use of an Open Group mark require a separate submission and approval. Current runs are diagnostic campaigns used to find and fix failures before an uninterrupted formal run. See docs/conformance-statement.md for claim scope and docs/vsc-pcts-run-status.md for the public-safe measured status.

Shell regression gates

Shell development has two complementary regression gates:

  1. make test-bash-parallel runs the public GNU Bash 5.3 compatibility corpus locally. Its current denominator is 86 fixtures and the required result is 86/86.
  2. On the licensed native VSC host, make test-bash-system ARM=<unique-name> in the sibling vsc-pcts-harness-kit runs all 493 POSIX shell TPs against bin/bash, with Bashy's pure-Go command applets excluded from PATH.

The 493-TP arm is relatively inexpensive and is required for release candidates and changes to parsing, expansion, execution, jobs, signals, traps, builtins, redirections, or locale-sensitive shell behavior. It cannot run in ordinary public CI because VSC-PCTS is licensed. After that isolation gate passes, make test-bash in the harness restores the Bashy Go applets and checks shell integration before the larger command-and-utility campaign.

For concurrent agent work, use the isolated test-lane contract in docs/isolated-test-lanes.md. It maps weave/worktree ownership to distinct OCI containers and results, supports multiple simultaneous instances of the same suite or POSIX profile, documents the swappable Ubuntu base, and gives status/cleanup commands.

Product sequence and Bash++ activation

Bashy ships two binaries carrying three named substrates: Classic → Bash++ → Yoke. Classic is the compatible standalone shell (bash) together with the pure-Go userland; Bash++ is the opt-in language extension and the bridge upward; Yoke is the agentic framework. The bash binary is Classic alone; bashy carries all three.

Invocation Bash++ default Agentic default
bash with .sh, .bash, or no extension off unavailable
bash with .bpp, without an explicit selector off unavailable
bashy, regardless of extension on on

Use --bashpp (canonical) or --bash++ to opt in and --no-bashpp to opt out. BASHY_BASHPP=1|0 supplies the environment default; set -o bashpp and set +o bashpp change the mode for subsequently parsed input. Bashy's agentic surface is independently controlled by --agentic / --no-agentic and BASHY_AGENTIC=1|0.

Precedence is explicit CLI → environment → .bpp extension → binary default. Because extended grammar must be selected before a file is parsed, an in-file set -o bashpp cannot enable new syntax retroactively in an already-parsed file. Use a flag, environment setting, Bashy's .bpp convention, or #!/usr/bin/env -S bash --bashpp for initial selection.

Startup POSIX mode suppresses Bash++ grammar on both front doors, including --bashpp, its --bash++ alias, and BASHY_BASHPP=1. bashy --posix retains POSIX parsing and runtime semantics while disabling Bash++ defaults and explicit requests. The standalone bash --posix --bashpp combination retains the Sprint 114 compatibility profile: Bash++ and POSIX differences are both off, matching the selector-off, POSIX-off invocation. Ordinary bash --posix, including an explicit --no-bashpp, retains POSIX mode. The resolver still records the winning selector tier and whether it was explicit; that provenance does not mean extended grammar is enabled.

The bare agentic modifier permits explicitly implemented LLM assistance in Bash++ functions, methods and script blocks. See the runnable agentic action example for the same action as a typed callable, shell script, executable tool and native embedding. A function or a dag target can carry a contract — @require / @ensure / @guard, Require: / Ensure: / Effects: — judged as shell checks at the process boundary.

Why

  • No dependencies. One binary. No bash, no shared libraries, no package manager. Drop it on any host (including minimal containers and Windows) and run your scripts.
  • Cross-platform. The same shell semantics on Linux and macOS (verified against Bash's test suite); Windows builds and runs, with full verification in progress.
  • Embeddable lineage. The engine underneath (mvdan.cc/sh) is a mature, widely-used Go shell library, so behaviour is well-tested and hackable.

Install

Download a release binary

Grab the archive for your platform from the Releases page and put bashy on your PATH:

Platform Asset
Linux x86-64 bashy-linux-amd64.tar.gz
Linux arm64 bashy-linux-arm64.tar.gz
macOS Intel bashy-darwin-amd64.tar.gz
macOS Apple Silicon bashy-darwin-arm64.tar.gz
Windows x86-64 bashy-windows-amd64.zip
Windows arm64 bashy-windows-arm64.zip
# Linux/macOS example
tar -xzf bashy-linux-amd64.tar.gz
sudo install bashy /usr/local/bin/bashy
bashy --version
With Go

go install github.com/qiangli/bashy@latest is not supported: the module resolves its engine and siblings through flat replace ../<sibling> directives, which go install refuses. Use a release archive above, or build from source below.

From source

bashy rebuilds itself using only an installed bashy. Every command below is run through bashy, so the same five lines work on Linux, macOS and Windows: bashy git fetches the sources, bashy scripts/bootstrap-siblings.sh checks out the sibling modules at the exact SHAs in .sibling-pins, and bashy dag build compiles both binaries through bashy go, which downloads and verifies its own pinned Go toolchain into bashy's cache the first time.

bashy git clone https://github.com/qiangli/bashy
cd bashy
bashy scripts/bootstrap-siblings.sh
bashy dag build            # -> bin/bash and bin/bashy (bin/*.exe on Windows)
bashy dag install          # optional: install into $DHNT_BIN_DIR (~/.local/bin)

What the host must provide, per platform:

git Go C compiler
Windows none — bashy git downloads a pinned, checksum-verified MinGit none — bashy go provisions it not used
macOS the system git (Xcode Command Line Tools: xcode-select --install) none — bashy go provisions it optional
Linux the distribution's git none — bashy go provisions it optional

The C compiler is optional on Linux and macOS: with cc on PATH the build also compiles the native pre-Go signal launcher (bin/bashy + bin/bashy.real); without one it says so and ships the plain Go binaries — the same form the release archives ship. bashy git on Linux and macOS deliberately uses the platform git rather than downloading one.

A checkout that has no installed bashy yet can bootstrap from the repo-local launcher instead (Linux/macOS; it needs a host go):

./bashy dag build
./bashy dag install

The traditional host-tool path also works when git, go and make are already installed:

git clone https://github.com/qiangli/bashy
cd bashy
./scripts/bootstrap-siblings.sh    # clones each sibling next door at its pinned SHA
make build                         # -> bin/bash and bin/bashy

A reusable Linux OCI base is also available. It preserves the required native launcher plus .real payload and uses a minimal Ubuntu/glibc runtime; see docs/bashy-oci-base.md for build, smoke, and derived image policy. It is the foundation for a future Bash/POSIX + canonical Go coreutils + O3 + verified-toolchain base, not yet an Ubuntu/Alpine parity claim.

Real-repository DAG examples live under examples/dag/. The Go front doors for GitHub CLI, Hugo, and Caddy use ~~~go as go to import the unchanged checkout, build its CLI, and launch that output; make smoke-dag-go provisions pinned checkouts into bashy's user cache and gates the installed product. The gh smoke also runs a checkout-owned helper through an embedded ~~~sh dialect island, with no host-shell dependency.

Usage

bashy script.sh arg1 arg2      # run a script
bashy -c 'echo "$BASH_VERSION"'# run a command string
bashy                          # interactive shell
echo 'echo hi' | bashy         # read a script from stdin
Supported flags

bashy accepts the common Bash invocation flags:

Flag Meaning
-c <string> run <string> as a command
-i force interactive mode
-l, --login act as a login shell
--posix POSIX mode
--norc do not read ~/.bashyrc
--noprofile do not read profile files
--rcfile, --init-file <f> use <f> as the interactive startup file
-o <opt> enable a set option (e.g. errexit, xtrace)
-O <opt> enable a shopt option
--pretty-print pretty-print the parsed input
--version print version and exit
Shell mode selection

Invoked as bash or bashy, the shell starts in GNU Bash 5.3-compatible mode. Invoked with basename sh, it starts in POSIX sh mode. POSIX mode can also be requested with --posix, -o posix, SHELLOPTS=posix, or by the presence of POSIXLY_CORRECT/POSIX_PEDANTIC (including empty values). Command-line -o/+o posix is last-wins unless one of the environment or sh startup conditions forces POSIX mode, matching GNU Bash 5.3.

The complete contract, including strict sh semantics and certification wiring, is documented in Shell mode selection.

Startup files: interactive shells read ~/.bashyrc (or --rcfile); login shells read /etc/profile and ~/.bashy_profile; $BASH_ENV is honoured for non-interactive shells.

Compatibility notes

bashy is a pure-Go runner: subshells are goroutines rather than fork(), and process substitutions use real named pipes. Job control (jobs/fg/bg/kill %n/suspend with stopped-state tracking), coprocesses, and signal traps are implemented and pass Bash's test suite on Unix. Mirroring Bash's own design (jobs.c on Unix, nojobs.c elsewhere), the OS-level job-control machinery is Unix-only; on other platforms it degrades exactly as a no-job-control Bash does.

Two known gaps: arithmetic currently uses the native int width (64-bit on 64-bit platforms), so very large values on 32-bit builds truncate — a tracked int64 migration; and the Windows test-suite run is still being verified. Everything else — parameter expansion, arrays and associative arrays, namerefs, [[ ]], arithmetic, here documents, brace/tilde/glob expansion (locale-aware, including non-UTF-8 charsets such as Big5/Shift-JIS), traps, printf, read, prompt escapes — matches Bash 5.3 and is verified against Bash's own test suite.

Development

See CLAUDE.md for the development workflow and docs/ for the compliance roadmap and per-fixture analyses. The compliance suite is driven by make test-bash (requires a local external/bash-5.3 symlink into a Bash source tree — see CLAUDE.md).

License

BSD 3-Clause (inherited from mvdan.cc/sh). See LICENSE.

Directories

Path Synopsis
cmd
bash command
Command bash is the pure GNU Bash 5.3 drop-in: the sh engine and CLI only, with no AgentOS surface.
Command bash is the pure GNU Bash 5.3 drop-in: the sh engine and CLI only, with no AgentOS surface.
bashy command
Command bashy is the AgentOS system shell: the same shell core as `bash`, plus the coreutils pure-Go userland, the `yc` code-intel verbs, and the front-door subcommands (`bashy weave …`, `bashy podman …`).
Command bashy is the AgentOS system shell: the same shell core as `bash`, plus the coreutils pure-Go userland, the `yc` code-intel verbs, and the front-door subcommands (`bashy weave …`, `bashy podman …`).
Package dhnt defines the portable, Argo-independent dhnt.pipeline/v1 and dhnt.run/v1 data contracts used by Bashy workers and evidence gates.
Package dhnt defines the portable, Argo-independent dhnt.pipeline/v1 and dhnt.run/v1 data contracts used by Bashy workers and evidence gates.
internal
agentos
The space-time advisor: a non-intrusive supervisor that, ONLY when a command fails, adds a context-aware hint explaining that the failure is determined by the agent's ambient resource environment ("space") — filesystem/disk, current working directory, CPU/memory, or network/locality — and what to do instead.
The space-time advisor: a non-intrusive supervisor that, ONLY when a command fails, adds a context-aware hint explaining that the failure is determined by the agent's ambient resource environment ("space") — filesystem/disk, current working directory, CPU/memory, or network/locality — and what to do instead.
agentos/activity
Package activity is the shared activity-event contract for Bashy subsystems: one compact envelope, one interest-routing matrix, and one delivery path onto the EXISTING durable notification and wake primitives.
Package activity is the shared activity-event contract for Bashy subsystems: one compact envelope, one interest-routing matrix, and one delivery path onto the EXISTING durable notification and wake primitives.
agentos/session
Package session implements the warm `bashy serve` process: a persistent, local, explicitly-started listener that runs `bashy -c "…"` commands inside one already-initialized process, so an agent that fires thousands of shell invocations pays the process- and package-init tax once instead of per call.
Package session implements the warm `bashy serve` process: a persistent, local, explicitly-started listener that runs `bashy -c "…"` commands inside one already-initialized process, so an agent that fires thousands of shell invocations pays the process- and package-init tax once instead of per call.
cli
bashy is a Bash 5.3 compatible shell built on top of interp.
bashy is a Bash 5.3 compatible shell built on top of interp.
pkg
harnessrunner
Package harnessrunner implements the effect-safe command boundary used by a YAML harness.
Package harnessrunner implements the effect-safe command boundary used by a YAML harness.
runner
Package runner exposes Bashy's in-process AgentOS shell for embedding.
Package runner exposes Bashy's in-process AgentOS shell for embedding.
Package skills embeds the tier-2 workspace skills shipped with the bashy binary, so a skill resolves from any cwd WITHOUT the source tree present — the skill content is compiled into `bashy`, not read from this repo.
Package skills embeds the tier-2 workspace skills shipped with the bashy binary, so a skill resolves from any cwd WITHOUT the source tree present — the skill content is compiled into `bashy`, not read from this repo.
tools
agentic-example command
Command agentic-example embeds Bash++ with one example-only native tool.
Command agentic-example embeds Bash++ with one example-only native tool.
bash53aggregate command
bash53fixtures command
bash53fixtures ensures the public GNU Bash 5.3 fixture tree is available in bashy's verified user cache and linked into a source checkout.
bash53fixtures ensures the public GNU Bash 5.3 fixture tree is available in bashy's verified user cache and linked into a source checkout.
bash53suite command
installbashy command
Command installbashy installs a freshly built bash/bashy pair without leaving an older bashy earlier on PATH.
Command installbashy installs a freshly built bash/bashy pair without leaving an older bashy earlier on PATH.
yashsuite command
ztst command
ztst is a shell-agnostic runner for zsh's .ztst test-file format (Test/*.ztst in the zsh source tree), used by scripts/zsh-scoreboard.sh to score bashy — and any reference shell — on zsh's own regression suite.
ztst is a shell-agnostic runner for zsh's .ztst test-file format (Test/*.ztst in the zsh source tree), used by scripts/zsh-scoreboard.sh to score bashy — and any reference shell — on zsh's own regression suite.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL