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

bashy

module
v0.28.0 Latest Latest
Warning

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

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

README

bashy — a pure-Go Bash 5.3 that speaks Bash#

release tour

bashy is one static binary — no CGo, no system bash — that is a drop-in Bash 5.3 on Linux, macOS and Windows: same flags, same script semantics, same $BASH_VERSION, and it passes GNU Bash's own 5.3 test suite (every runnable fixture, 86/86). With --bashsharp the same binary speaks Bash#: the bash you already know, Go where you need types, any fenced language where you need a library, and agentic where you need a model — with contracts so a model's output is judged, never trusted.

Alpha (0.x). Bash 5.3 compatibility is stable; the Bash# dialect may still change before 1.0 through RFCs. Every number this project states names its corpus: docs/claims.md.

Ten minutes

# macOS (Apple Silicon)
curl -fsSLO https://github.com/qiangli/bashy/releases/latest/download/bashy-darwin-arm64.tar.gz
tar -xzf bashy-darwin-arm64.tar.gz && sudo install bashy /usr/local/bin/bashy
bashy --version

Then take the tour — 27 small programs with pinned transcripts and one script that runs them all on your machine, also written as a procedure your coding agent can drive: bashsharp/tour. The ten-minute version is in this repo: examples/quickstart/.

@guard(effects: "read")
@require('test -n "$1"')
@ensure('test "$1" != lie')
agentic function summarize() { ... }

agentic {
    summarize ok        # exit 0
    summarize ""        # exit 3 — precondition failed; the body never ran
    summarize yield     # exit 6 — "I need input": a yield, not a made-up answer
}

The interpreter never calls a model. agentic marks the one place a program may hand work to one, and the contracts around it are ordinary shell commands, run deterministically.

What you get

  • A Bash 5.3 you can ship anywhere. One binary per platform; job control, coprocesses, signal traps, locale-aware globbing — verified against Bash's own suite on Linux and macOS. Invoked as sh, or with --posix, it is a POSIX shell: 493/493 on the licensed VSC shell arm, 99 %+ on yash's POSIX suite (bash 5.3 itself scores 96 % there).
  • The pure-Go userland with it. ls, sed, awk, grep, find, sort, tar, jq, git, make, … as applets, so the same script means the same thing on Windows.
  • Bash# with the flag on: typed Go in shell text, fenced Python / TypeScript / Rust / C / C++ / Go islands, decorators, keyword arguments, enums, deep readonly, contracts and agentic. Off with --no-bashsharp or --posix, where none of it exists.
  • The islands bring their own toolchains. A fence never resolves its tool from your PATH: bashy provisions what it uses — Go 1.27.1, zig cc for C/C++, a uv-managed CPython, Node + typescript, a rustup toolchain — downloaded from the vendor once, checksum-verified against a pin in this repo, cached — so the same program means the same thing on every machine. bashy check --prepare SCRIPT... pays that download ahead of time; BASHPP_PYTHON, BASHPP_GO, BASHPP_CC, … name a program explicitly.
  • It rebuilds itself. bashy git clone, bashy scripts/bootstrap-siblings.sh, bashy dag build — on Windows with no git, no Go and no C compiler on the host (see From source).
  • A tool that knows its caller is an agent. bashy check for static checks, bashy dag for dependency-ordered tasks in Markdown, bashy awd for "run this there", registered commands, and the agentic yield status a harness can act on.

Built on the qiangli/sh fork of mvdan.cc/sh by Daniel Martí — the engine is his; the Bash 5.3 conformance work and the Bash# dialect are carried in the fork. Campaign identity, regression gates and the product sequence: docs/internal/campaign-and-gates.md.

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 ~/.local/bin ($DHNT_BIN_DIR to change)

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
Containers — the offline image

Bashy is all you need. With nothing but the release download — no git, go, podman or docker on the host — build the image and run your script with no network:

bashy self image
bashy podman run --rm --network=none -v "$PWD:/work" -w /work localhost/bashy:<ver>-linux-<arch> --bashsharp ./script.bsh

bashy self image fetches the release's static bashy-scratch-linux-<arch> artifact (checksum-verified) and builds a FROM scratch image around it through bashy podman — the engine bashy provisions for itself from the pinned upstream releases (a complete static podman on Linux; the machine client plus gvproxy/vfkit on macOS; the client on Windows, where the machine runs on WSL2 — every edition). The image is bashy as it is: Bash 5.3, --posix, Bash#, the builtin coreutils, dag/weave/check/transpile. What is and is not in it, per command, is the measured matrix in docs/airgap-image.md. From a checkout, bashy dag build-image images the candidate instead of a published artifact.

A minimal Linux container base (Ubuntu/glibc, launcher + payload) is described in docs/bashy-oci-base.md.

Real-repository examples driven by bashy dag — one dag.md each for GitHub CLI, Hugo, Caddy, curl, git, FFmpeg, tesseract, llama.cpp, CMake, uv, Codex, Bun, OpenCode, OpenClaw, Hermes Agent and more, calling their Go, Python, TypeScript, Rust and C/C++ code as fenced islands — live under examples/dag/.

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 some interactive job-control behavior remains incomplete. The final Sprint 253 production gate measured the Bash 5.3 fixtures at 86/86 on Windows and Linux (run 35812307698), and the Sprint 257 timezone follow-up measured 86/86 on two native Windows builds, native macOS, and Ubuntu 24.04 test droplets. These are fixture results, not a claim of full Bash compatibility; see the umbrella's docs/sprint-253-delivery-evidence.md. 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 Bash 5.3 suite is driven by make test-bash (serial; needs a controlling terminal; make test-bash-fixtures fetches the pinned fixture tree). The language, its roadmap and RFCs live in bashsharp/bashsharp.

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 …`).
sh command
Command sh is the pure POSIX shell used by the shell conformance gate.
Command sh is the pure POSIX shell used by the shell conformance gate.
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
elfaudit command
Command elfaudit verifies the structural contract of Bashy's Cloudbox ELF.
Command elfaudit verifies the structural contract of Bashy's Cloudbox ELF.
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.
windowswslocale command
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