Changelog

View Source

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

0.4.0 (2026-09-28)

⚠ BREAKING CHANGES

  • JustBash.Fs and JustBash.Fs.InMemoryFs are replaced by JustBash.FS / JustBash.FS.Memory with vfs-shaped returns ({:ok, payload, fs} on reads, %VFS.Error{} on failure, %VFS.Stat{} from stat). Bash-level script behavior is unchanged.

Features

  • add JustBash.CLI for namespaced subcommand tools (#39) (2761adf)
  • add put_context/3 and get_context/3 accessors (#41) (2c6e6b7)
  • cli: address consumer feedback from issue #38 (#43) (7d84244)
  • replace the filesystem layer with the vfs library (#44) (1da1db8)

Bug Fixes

  • /dev/null exists as a filesystem node so operands agree with redirects (#78) (#93) (8619ada)
  • a CLI flag rejects unknown spec keys and accepts extra long spellings (#71) (83af599)
  • a command whose redirect fails does not run at all (#60) (025673c)
  • a flag a command does not implement is an error, not a filename (#72) (9aab27a)
  • a trailing slash on a destination requires a directory instead of overwriting the file it names (#75) (5de39ef)
  • awk's empty for(;;) condition is true, matching gawk (#87) (ca5c918)
  • bound ${v//pat/rep} so global replace cannot OOM (#97) (f2beeb9)
  • bound value size so doubling cannot blow past max_wall_ms (#85) (55c0f50), closes #77
  • cp into a directory, and make cp -r actually copy (#57) (7d73837)
  • date implements %F and -I instead of emitting them literally (#63) (274e86b)
  • date rejects unknown arguments instead of returning today at exit 0 (#66) (fd2bb2c)
  • empty path operands are ENOENT, not the current directory (#95) (2e73917)
  • exec/2 returns a shell result instead of raising, and always terminates (#73) (3b9be0d)
  • find and jq honour -- as end-of-options (#90) (#98) (0077d63)
  • grep BRE alternation, missing-path exit code, and flag-level did-you-mean (#84) (3d2c625)
  • head default line count no longer emits a trailing blank line (#91) (1bcda6b)
  • honour -- as end-of-options for file-operand commands (#89) (b5477c3)
  • mkdir and rm report backend errors instead of crashing the exec (#48) (dffd5dd)
  • printf %b support and no-progress guard against format-recycle hangs (#50) (56c74b8)
  • replace retired earmark runtime dependency with mdex (#55) (ce86847), closes #54
  • shasum -c and sha256sum -c read checksums from stdin (#88) (cdddddc)
  • Special table owns readdir merge and write-redirect paths (#99) (05a26b2)
  • tac does not invent a newline on an unterminated last record (#92) (6c92a44)
  • writing through a regular file is ENOTDIR, not unreachable state (#56) (1633cdc)

Miscellaneous Chores

0.3.0 (2026-04-14)

Features

  • add context option to justbash struct for custom commands (#34) (8824fd9)
  • add xxd/od, curl flags, grep -P, awk crash guard (#32) (4afdb3b)
  • add production resource limits and execution stats (#28) (9c7a36d)
  • add missing command flags, stdin support, and bash comparison fixtures (#31) (67de3b0)
  • replace NimbleParsec lexer with hand-written state machine (#30) (bc05d36)
  • add telemetry instrumentation for script execution (#29) (b8cac23)

Bug Fixes

  • jq parser failing to resolve builtin function names to atoms (144cbe8)

0.2.0 (2026-03-23)

Features

  • add 12 new evals covering uncovered commands and shell features (2c21f75)
  • add custom command eval with KV store (840ba00)
  • add eval system and fix 5 bugs exposed by LLM agent evals (39e4637)
  • expand evals to 28 tasks and fix 8 additional bugs (5ba37c5)
  • major expansion - 15 new commands, jq overhaul, test infrastructure (a5efb73)
  • test infrastructure, new commands, jq overhaul (13749d2)

Bug Fixes

  • 8 AWK bugs, jq -e exit status, declare -A keys, printf redirect parsing (cb57e64)
  • capture bash state between exec calls in README example (09b2039)
  • correct GitHub URLs in CHANGELOG (a4cf791)
  • correct GitHub URLs in CHANGELOG (5b29c7e)
  • heredoc in compound commands, assoc array subscripts, which/type builtins, jq @tsv (99aab44)
  • implement AWK field assignment ($N = value) with $0 reconstruction (e760cad)
  • read IFS splitting, wc/head/tail multi-file, and improve eval robustness (7d96af7)
  • remove deprecated package-name from release-please workflow (d1d7ab7)
  • tests: use variable instead of module attribute for spec tests (#18) (f583911)

Unreleased

Added

  • mix bash_fixtures.gen printf enumerates a printf conversion × flag/width/precision matrix (printf_matrix) — #70 item 2
  • mix bash_fixtures.gen test enumerates a test/[ operator × revealing-shape matrix (test_matrix) — #70 item 2
  • mix bash_fixtures.gen varop enumerates a ${var op word} parameter-expansion matrix (varop_matrix) — #70 item 2
  • mix bash_fixtures.gen flags enumerates a Registry-wide unknown-flag probe (flags_matrix) — #70 item 2
  • mix bash_fixtures.gen seto enumerates the POSIX/bash set -o/+o name alphabet (seto_matrix) — #70 item 2

Bug Fixes

  • ${v//pat/rep} / ${v/pat/rep} refuse before allocating a result that would exceed :max_value_bytes (#86)
  • empty-string path operands are ENOENT, not the current directory (#79)
  • honour -- as end-of-options for file-operand commands (#83)
  • find and jq honour -- as end-of-options: find -- -foo is a path, jq -- . is the filter (#90)
  • head default line count no longer emits a trailing blank line (#80)
  • tac no longer invents a newline on an unterminated last record (#82)
  • /dev/null exists as a filesystem node, so operands agree with redirects (#78)
  • FS.readdir/2 only uniq-sorts directories that contribute special children, and write redirects to /dev/./null skip the file-size cap (#94)

0.1.0 - 2026-01-11

Added

  • Initial release
  • In-memory virtual filesystem (JustBash.Fs.InMemoryFs)
  • Bash lexer and recursive descent parser
  • Variable expansion: $VAR, ${VAR}, ${VAR:-default}, ${VAR:=default}, ${VAR:+alt}, ${#VAR}, ${VAR:start:len}, ${VAR#pattern}, ${VAR%pattern}, ${VAR/old/new}, ${VAR^^}, ${VAR,,}
  • Command substitution: $(cmd) and backticks
  • Arithmetic expansion: $((expr)) with full operator support including **, ?:, hex, binary
  • Control flow: if/elif/else/fi, for x in ...; do; done, while/until, case/esac
  • Logical operators: &&, ||, ! with short-circuit evaluation
  • Pipes with stdin/stdout flow
  • Redirections: >, >>, 2>, &>, <, <<<, heredocs
  • Brace expansion: {a,b,c}, {1..5}, {a..z}
  • Arrays: arr=(...), ${arr[0]}, ${arr[@]}, ${#arr[@]}
  • Functions with local variables
  • Extended test command: [[ ]] with regex support

Commands

File operations:

  • cat, ls, cp, mv, rm, mkdir, touch, ln
  • find, stat, du, tree, file, readlink

Text processing:

  • grep, sed, awk (full implementations)
  • sort, uniq, head, tail, wc, cut, tr
  • rev, tac, nl, fold, paste, comm, diff, expand

Data tools:

  • jq (comprehensive JSON processor)
  • curl (HTTP client with network allowlists)
  • markdown / md (Markdown to HTML)
  • base64, md5sum

Shell builtins:

  • echo, printf, pwd, cd, export, unset
  • test, [, [[, true, false, :
  • set (shell options: -e, -u, -o pipefail)
  • source, ., read, exit, return
  • local, declare, typeset
  • break, continue, shift, getopts, trap

Utilities:

  • seq, date, sleep, basename, dirname
  • which, env, printenv, hostname
  • xargs, tee