Contributing
This page covers the repository structure, build process, and release workflow. For the full contributing guide, see CONTRIBUTING.md on GitHub.
Repository structure
The repo is a committed Go workspace plus a pnpm workspace.
- Root module (
./) -- publicgbashpackage, CLI (cmd/gbash/), internal runtime, and core commands contrib/-- optional modules (awk,htmltomarkdown,jq,sqlite3,yq,extras,nodejs) kept separate to avoid pulling optional dependencies into the core import graphexamples/-- standalone example projects (separate Go module)packages/-- publishable JavaScript packages, including@ewhauser/gbash-wasmwebsite/-- documentation site
Key internal packages:
| Package | Purpose |
|---|---|
internal/runtime | Session lifecycle, execution, budget enforcement |
internal/shell | Project-owned shell AST parsing, expansion, and execution |
commands | Built-in command implementations |
fs | Filesystem interface and backends (memory, overlay) |
policy | Path checks, command allowlists, limits |
network | HTTP client with allowlist enforcement |
trace | Structured execution event recording |
Building and testing
make build # build all Go modules
make test # run tests across all modules
make lint # run lintersFor JavaScript workspace dependencies:
pnpm install --frozen-lockfileTo preview the website locally with the latest published compatibility data:
make website-devModule versioning
The repo uses go.work for local development with 9 modules (root + 8 children):
. contrib/awk contrib/extras
contrib/htmltomarkdown contrib/jq contrib/nodejs
contrib/sqlite3 contrib/yq examples
Published versions are coordinated. The root module uses plain tags such as vX.Y.Z; contrib modules use nested-module tags such as contrib/jq/vX.Y.Z. Child modules maintain real version requirements in go.mod plus local replace directives for development.
To prepare a coordinated release across all modules:
make fix-modules MODULE_VERSION=vX.Y.ZThis updates nested module requirements, refreshes local replaces, updates the npm package version, and runs go mod tidy in each child module.
Release process
Releases are driven by GitHub Actions:
- Run
make releaseor dispatch the Prepare Release workflow - Review and merge the generated
release/vX.Y.ZPR intomain - The Publish Release workflow creates root and contrib tags, publishes the GitHub release with
gbashandgbash-extrasarchives plus a shared checksum file
The prepare step derives the next version by incrementing the patch number of the latest root v* tag.
Benchmarks
Run comparison benchmarks locally:
make bench-compare
make bench-compare JSON_OUT=bench-compare.json # JSON output
make bench-fs
make bench-fs BENCH_FS_JSON_OUT=/tmp/filesystem-bench.jsonThe benchmark compares five runtimes: native gbash, GNU bash, gbash-extras, gbash-node-wasm (WASM in Node.js), and just-bash (npm).
Some scenarios require optional commands such as jq. Those scenarios keep the full
runtime table on the website, but unsupported runtimes are shown as skipped with a
reason instead of being counted as failures.
GNU compatibility testing
Evaluate skew between gbash commands and GNU coreutils using the compatibility harness:
make gnu-test
make gnu-test GNU_UTILS="printf pwd" # test specific utilitiesThe harness runs inside a Docker container. By default it pulls a published compat image from GitHub Container Registry, falling back to a local build if unavailable.