This is a significant release, containing several months of work and more than 200 merged PRs. It includes a broad set of new features, bug fixes, and quality improvements, most notably a myriad of bash compatibility fixes that materially raise the bar on which real-world scripts and interactive sessions brush can handle.
Some key highlights:
A meaningful step forward in bash compatibility. Major bash language features are now implemented or substantially expanded, e.g.: set -e, set -u, pipefail, failglob, the ERR trap, coprocesses, and a great deal more.
Improved robustness across edge cases. Closed pipes, broken stdout, unusual file-descriptor states, non-UTF8 history files, and platform corner cases are now handled gracefully. A systematic audit also removed an entire class of avoidable failure modes.
Broader platform support. Using brush as a login shell on macOS is now supported, Windows path handling is overhauled, FreeBSD, Android and 32-bit targets build cleanly again, and wasm32-wasip2 is now exercised in CI.
A more capable interactive shell. Optional TOML config, zsh-style preexec/precmd hooks, experimental terminal integration, expanded readline-macro support, and many completion improvements.
API improvements and foundations for what's next. Scaffolding for a winnow-based parser, a generic Shell<Extensions> for embedders, an opt-in bundled-coreutils build, and serde features for both AST and shell state. This work has required breaking changes to API surface, mostly to brush-core. Some changes were also made to brush-parser's API but we expect migration for parser-only consumers to be straightforward and relatively minimal. Please reach out to us if you encounter challenges in this area.
A heartfelt thank-you to everyone who filed issues, reproduced bugs on unusual platforms, and contributed code over the last several months 🙏. A significant percentage of the work below is in direct response to community reports.
✅ bash compatibility
This release expands brush's coverage of widely-used bash language features. Among the most commonly-relied-on additions:
set -e (errexit) and pipefail (#852) are implemented with bash-faithful semantics, including the long list of exemptions bash has accumulated over the years. See the compatibility reference for the current status of supported set options.
set -u (nounset) (#774, #1007) now actually errors on unset variable references, including the subtle interaction with ${#arr[i]}.
failglob (#1011) treats no-match globs as an error.
The ERR trap (#1020) is implemented, complementing the EXIT trap work from the previous release. As a corollary, EXIT traps now also fire correctly under -c (#1080).
A new --noglob/-f command-line flag (#1091), proper -- option-terminator handling for -c (#1076), and an exit code of 2 for unknown command-line options (#1050).
Heads up: because set -e, set -u, pipefail, and failglob previously had limited effect in brush, scripts that ran cleanly under v0.3.0 may now exit with errors that bash would also have produced. This is the intended behavior. If you see a divergence from bash, please file an issue.
Beyond the headline options, this release lands a long list of more focused compatibility fixes. Many are small, but in aggregate they account for the bulk of the change list. Highlights worth calling out:
Arithmetic got serious attention: high-radix literals (#1019), faithful overflow/underflow (#1017), legacy $[expr] syntax (#1004), the missing |= and ^= assignment operators (#911), array indices inside array indices (#910), arithmetic-for parsing/eval fixes (#1018), and infinite-recursion detection (#1021).
Heredocs are substantially more robust inside command substitutions and quoted contexts (#1014, #1055, #1056, #1067).
Pattern and extglob correctness work covers escaped parens (#960), backslash preservation (#963), pattern character-set escaping (#824), brace-sequence step direction (#1025), and the nullglob + quoted-empty-string interaction (#1035).
Builtins matured across the board: caller was added (#812), read is now much closer to feature-complete (#914), mapfile -O works (#558), getopts got OPTERR semantics (#1048) and short-option fixes (#827), compgen -A picked up binding, command, and reserved-word completion (#814, #1027, #1047), printf %q quotes empty strings as '' (#1026), and the rules for shadowing special builtins with functions are now correct (#922).
Variables and prompts:BASH_ARGC/BASH_ARGV (#1013) and $_ (#1030) are populated; OSTYPE is set on macOS (#1097); prompts handle \l, \[/\], and $? correctly (#913, #909, #798); and $- correctly reflects -c (#767).
If you've previously hit a bash-compatibility issue with brush, there's a decent chance it's resolved here. If not, please open an issue!
Robustness improvements
v0.4.0 also includes a substantial amount of plumbing work that won't show up in our feature lists but contributed to raising our quality. A big thanks to contributors who put these (and others) together:
A systematic unwrap() audit (#921) hardened brush against a class of unusual-input edge cases.
Closed stdout and stderr are now handled gracefully; this is important when brush is on the producing side of a | head pipeline (#873, #875).
File-descriptor failures (e.g., dup failures from clone) are now reported cleanly rather than aborting (#1051).
Path search now finds executables reachable via symlinks (#991, #992), broadening the set of environments where commands resolve as expected.
History import tolerates non-UTF8 and otherwise unusual entries (#878).
Regex-cache contention under concurrent use is reduced (#1043), with additional allocation-reduction work in brace expansion and other hot paths (#884, #886, #936, #940).
Broader platform support
We aim for portability and this release advances that goal on several fronts:
macOS: using brush as your login shell is now supported, thanks to a fix for a startup hang in that scenario (#1095). If you'd like to set brush as your chsh target on a Mac, please give it a try.
Windows: broad path-handling improvements (#1075), proper /dev/null emulation (#1044, #1104), and CI now exercises the Windows test suite (#1083) to keep the platform on solid footing. Windows support remains in an experimental state, but it has matured meaningfully this cycle. If you've tried brush on Windows previously, this is a good time to revisit, and we'd appreciate hearing how it goes.
WebAssembly:split_paths is now safe under WASM (#1064), and basic wasm32-wasip2 smoke tests run in CI (#1098).
Interactive shell improvements
The interactive experience picked up several things that interactive-shell users have requested:
TOML configuration file for brush-shell: an opt-in alternative to shell-script-based configuration for brush-specific shell-level settings (#895). See the configuration reference for the file format, location, and available settings. Experimental.
preexec / precmd hooks in the style of zsh: useful for prompt frameworks, timing, integration tools (#652). Enable via the [experimental] zsh-hooks setting documented in the configuration reference. Experimental.
Shell/terminal integration: semantic prompt and command marking that modern terminals can use to enable command navigation, exit-status display, and similar features (#872). Enable via the [experimental] terminal-shell-integration setting in the configuration reference. Experimental.
Readline macros: initial support (#880) plus follow-up to handle more macro forms found in real inputrc files (#967). Many additional fixes to improve compatibility with shell extension tools like starship, atuin, fzf, and others.
Hint-acceptance key bindings are now exposed (#802).
A bag of completion fixes that mostly fall under "things you'd never notice unless they were broken": filenames with spaces and special characters now escape correctly (#870); shell variables get a sensible default fallback completion (#954); . and .. are offered (#887); mark-directories is honored (#817); COMP_KEY/COMP_TYPE are populated for completion functions (#1008); COMP_WORDBREAKS default matches bash (#828); word tokenizing during completion was corrected (#816); and deduplication of completions is deferred to the presentation layer so functions see the full list (#1012).
Profile/rc loading is now deferred until the input backend is attached (#879), which matters for rc files that probe terminal capabilities at startup.
For embedders and crate consumers
The brush crates are published to crates.io, and several of the changes in this release are aimed at people building on top of brush-core, brush-parser, et al. The most important ones:
Shell is now generic over a ShellExtensions type parameter (#941). This is the scaffolding that lets embedders extend brush with custom builtins, custom variable behavior, and other hooks without forking. Existing code that names Shell directly will need to either pick a concrete extension type or thread the generic through; a default extension type is provided for the common case. We plan to continue building on this for better low-overhead, static inspection and extension of brush-core behaviors.
Shell fields are now private (#900) and shell.rs was split into shell/*.rs (#945). Callers using the public re-exports and accessor/builder methods are unaffected; callers reaching into private state will need to migrate.
serde features are now available on both brush-parser (#783) and brush-core (#831) for AST and shell-state serialization. This makes a number of new use cases viable, e.g.: memoizing initialization, snapshotting shell state.
PEG parser reorganization (#899) along with scaffolding for a future winnow-based parser (#974). The PEG parser remains the production parser; the winnow work is groundwork for a faster, more diagnosable replacement in a future release.
brush-parser:ParsingNearToken was renamed to ParsingNear (#1022).
fuzz-testing Cargo feature was renamed to arbitrary (#844) to better reflect what it actually gates.
Build/test/validate scripting moved to cargo xtask subcommands (#898); see cargo xtask --help.
Experimental work to keep an eye on
A few items in this release are intentionally marked experimental; they are usable today, but the shape of the API or UX may evolve based on feedback (hint: we want your feedback!):
Bundled coreutils builtins behind a feature flag (#1031). Opt in at build time to ship a single binary that resolves common utilities (ls, cat, etc.) internally, useful for container/embedded scenarios where a coreutils package isn't available, or for platforms like Windows that don't typically offer these utilities. See the experimental features reference.
Full shell-state serialization via the experimental save builtin (#835): primarily a debugging and tooling aid today, but a building block for future features. See the experimental features reference.
The TOML config, preexec/precmd, and terminal-integration features mentioned above are all in the experimental bucket. The experimental features reference covers how to enable each one. Try them and tell us what feels off.
Application-level breaking changes
If you're a script author or interactive user (rather than an embedder), these are the changes most likely to be visible to you:
Stricter set -e / set -u / pipefail / failglob enforcement. These options had limited effect in v0.3.0; they now behave like bash. Scripts that previously ran without surfacing errors may need updates.
readonly now operates on global scope (#1003), matching bash. Code that depended on the prior local behavior will observe a difference.
Reserved words are rejected as function names (#978).
Unknown command-line options exit with code 2 (#1050), matching bash.
Profile/rc loading happens after input backend attach (#879). Visible only to rc files that probed for terminal capabilities at startup.
🙏 Acknowledgments
Releases like this one don't happen without the people who file thoughtful issues, reproduce bugs on platforms the maintainers don't have access to, and send code. Thank you to everyone who contributed to this release! Whether your name appears below or you helped via an issue, a discussion, or a reproducing test case we value and count on your contribution.
Special thanks go to the contributors whose work shows up in many of the bullet points above:
@lu-zero - has been the driving force behind a multi-release effort to modernize brush's parser and improve bash compatibility from the ground up. The work landing in this release is laying the groundwork for substantially more significant parser, diagnostics, and compatibility improvements in upcoming release: enriched ASTs, source-location tracking, parser reorganization, and the early scaffolding for a winnow-based parser. Thank you for the sustained, foundational contributions.
@Elsie19 - focused, high-quality bash-compat fixes spread across builtins, expansion, and corner cases.
@oech3 - ongoing edge-case testing, exit-code validation, and bug finding.
@StudioLE - surgical heredoc / tokenizer fixes that resolved a cluster of long-standing parser bugs.
@takeshiD and @xtqqczze - repeated, well-targeted contributions across the codebase.
And thank you to everyone else who authored or co-authored a commit in this release:
This is a major release, containing architectural improvements and compatibility-focused features and fixes. A big thanks to all of the contributors over the last few months, including issue filers, question-askers, and code contributors 🙏.
Based on user-filed issues (thank you!), targeted work went into improving compatibility with popular tools like fzf and neofetch.
Additionally, a significant amount of work went into refactoring and improving usability of the public API surface within the crate-based libraries that make up brush's core. These come with breaking changes for programmatic clients, but we're confident they will come with significant benefit.
The following summary covers the most notable changes and the full change details are below.
✅ Features and Improvements
Builtins
The fc builtin received its initial implementation!
bind implementation received support for binding key sequences to readline functions (e.g., "\C-a":beginning-of-line).
trap now fully implements the EXIT trap.
Standard variables
Basic support for use of BASH_XTRACEFD was added. A new command-line parameter to brush (--inherit-fd) enables allow-listing inherited file descriptors for use within the shell.
Control flow
Support for an undocumented C-like syntax for arithmetic for loops has been implemented for improved compatibility.
🪳 Notable bug fixes
Fixes for quote handling of \' in double-quoted word contexts.
Targeted fixes to history importing make it more robust against non-UTF8 compatible text.
Fixes for parsing of here-documents in quoted command substitutions.
Fixes for nuanced quote removal in parameter expressions with replacements (e.g., "${var:+'x'}").
Fixes for command substitution expansions resulting in spawning processes with large volumes of output (e.g., $(emit-a-lot-of-text)).
Updates to the open file table made by commandless exec (e.g., exec 2>/dev/null) are now reflected immediately, even when in a loop context.
🚧 API Changes
Changes in this section pertain to programmatic clients of the brush-core, brush-parser, and brush-interactive crates. They do not apply to application-level shell users.
brush-builtins
All shell builtins have been moved into a new dedicated brush-builtins crate. With this move, significant refactoring was done to ensure that these builtins are all implementable using public APIs exposed by brush-core. In doing so, this also significantly advanced the richness of the latter APIs.
Important
Programmatic clients of the brush-core crate will find that a constructed Shell is not automatically populated with the usual set of builtins. New optional APIs exist in the brush-builtins crate to retrieve default builtins and in brush-core to register them with a Shell instance.
Parsing and AST
As an important step on our journey to evolve brush's parsers, @lu_zero has made contributions that start enriching our parsed Abstract Syntax Trees (ASTs) with links back to the source text. As part of this work, a new SourceLocation trait was introduced and implemented for many AST node types. Work will continue in the coming releases.
API Ergonomics
To improve ergonomics, we've introduce builder-based construction utilities to key structures like brush_core::Shell. We will continue to expand on this adoption over time to simplify the work of constructing these values.
Note that the signature of Shell::new() has changed and may require adjustment in callers.
Error handling
As preparatory work for future improvements, we've overhauled the core error types and execution result types in brush-core:
Error has been renamed to ErrorKind, with a new wrapping Error struct type that can carry additional context. This will be used in the future for improved diagnostics.
Clients of brush-core can now provide their own custom error formatter to render a displayable string from an Error value. This will be used by some of our frontends for fancier diagnostics in the future. It also decouples error formatting from writing.
Multiple overlapping result types across the core interpreter, command utilities, and builtins have been consolidated into a coherent set of ExecutionResult, ExecutionExitCode, and ExecutionControlFlow types. Along the way a handful of bugs for edge cases were identified and resolved as part of the streamlining.
Details
build(deps): bump the github-actions group with 6 updates by @dependabot[bot] in #669
build(deps): bump procfs from 0.17.0 to 0.18.0 in the cargo group across 1 directory by @dependabot[bot] in #671
build(deps): bump the github-actions group with 5 updates by @dependabot[bot] in #675
This release contains several bug fixes to improve compatibility with bash, as well as some feature work focused on command history. We are now also publishing more complete license notices along with the binaries we release on GitHub.
Notable features and fixes:
Implemented history builtin! This has been in the works for a while, but we saw it reach stability during this release cycle.
Resolved a handful of issues discovered by users trying to run Arch's makepkg script under brush, including some missing functionality in brace expansion and arithmetic expression parsing. (Thanks to @theoparis for finding and reporting these!)
Resolved panics occurring with strings containing multi-byte characters. (Thanks to @colindean for catching and root-causing these!)
Adds support for (<"$file") special-case supported by bash.
Notable installation improvements:
brush is now installable via homebrew! (Thanks to @colindean for updating our readme with instructions.)
brush is installable (more officially) from Arch! (Thanks to @roland-5 for readme updates on that.)
🗒️ Details
fix(ci): correct CD workflow run name by @reubeno in #603
build(deps): bump the github-actions group with 3 updates by @dependabot[bot] in #605
Arch Linux - update installation instruction by @roland-5 in #604
fix: prepare tests to run against bash-5.3 by @reubeno in #610
build(deps): bump the github-actions group across 1 directory with 4 updates by @dependabot[bot] in #611
build(deps): bump the cargo group across 1 directory with 5 updates by @dependabot[bot] in #609
build(deps): bump the cargo group with 3 updates by @dependabot[bot] in #612
build(deps): bump the cargo group with 2 updates by @dependabot[bot] in #613
build(deps): bump the github-actions group with 3 updates by @dependabot[bot] in #617
build(deps): bump tokio from 1.46.1 to 1.47.0 in the cargo group by @dependabot[bot] in #616
build(deps): bump the cargo group with 2 updates by @dependabot[bot] in #619
build(deps): bump the github-actions group with 2 updates by @dependabot[bot] in #620
build(deps): bump the cargo group with 2 updates by @dependabot[bot] in #621
feat(history): implement history builtin by @reubeno in #599
This release includes a targeted change to the project's default compiler flags (see #600 for details). Prior to this change, release builds defaulted to optimizing for the build host's hardware platform; while useful for individuals, this is problematic for users who plan to use the built binaries on a different system.
Notable features and fixes:
Fixed "illegal instruction" issue sometimes seen when building brush on one system and running on another. (Thanks to @kachick for diagnosing and fixing this!)
Added support for +o/-o on the brush command line.
Corrected behavior of positional parameter shadowing with source/. builtin.
Notable API improvements:
Ergonomics improvements to Shell::invoke_function, ShellValue construction, and a few other places. (Thanks to @Elsie19 for contributions here!)
🗒️ Details
chore: suppress cognitive complexity errors (for now) by @reubeno in #583
fix(dot): only shadow args when provided to source by @reubeno in #582
docs: README.md installation updates by @reubeno in #580
ci: fix dry-run PR trigger on CD workflow by @reubeno in #584
chore: update dependencies + deny policy by @reubeno in #586
tests: tag test binary dependencies by @reubeno in #585
tests: add test cases for open issues by @reubeno in #587
This release included a batch of compatibility fixes, ergonomics improvements to the API surfaces of brush-core and brush-parser crates, and some targeted performance improvements.
Notable features:
Add BRUSH_VERSION variable to distinguish versions of brush from the version of bash it targets compatibility with. (Thanks to @kachick for proposing and implementing this one.)
API adjustments to script parsing in brush-core for ergonomics. (Thanks to @hwittenborn for contributing this.)
Initial (non-translating) support for gettext quoted strings. (Thanks to @Elsie19 for identifying this gap and merging in an initial implementation.)
Overhaul of printf builtin using the uucore crate from the Rust coreutils project.
Added support for >&-, >&N-, and other bash-extended redirection forms.
Highlighted fixes:
Correct handling of escape sequences in ANSI-C strings.
Handle here documents terminated by EOF (Thanks to @mati865 for reporting this.)
Fix behavior of brush when commands are piped to stdin. (Thanks to @andychu for catching and reporting this.)
Other shout-outs:
Big shout-out to @andychu for onboarding brush to the Oils project's cross-shell compatibility testing! More discussion of this can be found here.
🗒️ Details
fix(typeset): mark typeset as a declaration builtin by @reubeno in #517
fix(tokenizer): correctly treat $( (...) ) as a cmd substitution by @reubeno in #521
feat(AndOrList): add iteration abilities by @Elsie19 in #512
build(deps): bump the cargo group with 3 updates by @dependabot in #522
fix(backquote): correct backslash handling by @reubeno in #524
fix(test): reuse -ef, -nt, -ot support by @reubeno in #525
fix(vars): ensure effective GID is first in GROUPS by @reubeno in #526
fix(arithmetic): permit space after unary operator by @reubeno in #527
feat(vars): implement correct updating for -u/-c/-l vars by @reubeno in #529
ci: hash-pin actions + explicitly constrain token needs by @reubeno in #532
feat(env): introduce brush specific variable by @kachick in #531
ci: clean up ci report workflow by @reubeno in #533
ci: enable checks against workflow yaml by @reubeno in #534
ci: fix pedantic warnings from newer zizmor release by @reubeno in #535
feat: enable cargo-binstall to work with brush by @reubeno in #536
test: work-in-progress script to run bash test suite by @reubeno in #537
build(deps): bump pprof from 0.14.0 to 0.15.0 in the cargo group by @dependabot in #542
ci: run cd workflow in dry-run mode on PR by @reubeno in #543
build(deps): bump the github-actions group with 2 updates by @dependabot in #541
test(parser): enable serde::Serialize on AST et al. for test targets by @reubeno in #544
Since our last release we've seen an influx of interest, thanks in part to getting posted to Hacker News and elsewhere. Welcome all! We appreciate your interest, questions, filed issues, and support 😄
This release focuses on a wave of fixes to address some of the user feedback we've received, as well as some targeted features that had been on our backlog for quite some time.
Some select highlights:
Ergonomic improvements to the brush-core exported API surface for applications embedding brush. (Particular thanks to @Elsie19 and other contributors on this).
Support for logical/physical options (-L, -P) to cd, pwd, et al. (This builds on the work that @39555 started several months back; thanks for your patience until we were able to get to it!)
Significant improvements to the mapfile/readarray builtin. (Thanks to @Elsie19 on overhauling mapfile's core input loop.)
Initial implementation of the ulimit builtin. (Thanks to @lu-zero for getting it from unimplemented to something reasonable.)
Initial implementation of bind -x support, used by many shell extensions and users' .bashrc files; there's more to do, but this covers a long asked-for feature request from the community.
There's plenty more bug fixes and changes -- as usual, the full details are below. And a big shout-out to our new contributors as well as contributors who dove in deeper this cycle! 🙏
🗒️ Details
fix: correct release tag check in cd pipeline by @reubeno in #443
feat(apply_unary_predicate_to_str): implement -R operand by @Elsie19 in #439
feat(Shell): add methods to add environmental variables and builtins by @Elsie19 in #447
ref(Shell): turn &Path parameters into AsRef<Path> by @Elsie19 in #448
build(deps): bump taiki-e/upload-rust-binary-action from 1.24.0 to 1.25.0 in the github-actions group by @dependabot in #450
fix(prompt): support PROMPT_COMMAND arrays by @reubeno in #451
fix(trap): handle '-' unregistration syntax by @reubeno in #452
test(extended-tests): explicitly set modified date on test files by @reubeno in #453
chore: upgrade dependencies: reedline, nix, clap, thiserror, etc. by @reubeno in #456
chore: enable (and fix) current checks across all workspace crates by @reubeno in #457
feat: implement {cd,pwd} -{L,P} by @reubeno in #458
build(deps): bump the cargo group with 3 updates by @dependabot in #461
build(deps): bump the github-actions group with 2 updates by @dependabot in #460
fix(complete): fixes + tests for "declare -r" by @reubeno in #462
fix: enable unnameable_types lint and mitigate errors by @reubeno in #459
fix(builtin): fix issues with 'builtin' invoking declaration builtins by @reubeno in #466
fix(declare): turn down volume on non-existent functions by @reubeno in #467
fix(expansion): allow negative subscripts with indexed arrays + slices by @reubeno in #468
chore: better log + connect unimpl functionality with GH issues by @reubeno in #476
chore: separate release and bench profiles by @reubeno in #477
test: add compat test for $_ (not yet passing) by @reubeno in #480
Another release with a sizable number of targeted fixes for posted issues, performance tweaks, and a couple of smaller features. The most noticeable feature may be the introduction of "dynamic variables" into the shell implementation, which allowed us to add quick support for standard special variables like $SHELLOPTS, $BASHOPTS, et al.
What's Changed
build(deps): bump the cargo group across 1 directory with 4 updates by @dependabot in #320
fix(builtins): skip unenumerable vars in set builtin by @reubeno in #322
test(perf): update tokenizer/parser benchmarks by @reubeno in #321
fix(patterns): fix incorrect parse of char ranges by @reubeno in #323
chore: remove unneeded string cloning for arithmetic eval by @reubeno in #324
feat(continue): implement continue n for n >= 2 by @reubeno in #326
fix(completion): improve basic backend completion output by @reubeno in #327
This is a sizable release, incorporating a large number of bug-fixes and performance improvements, as well as some targeted features to close compatibility gaps. Notably this includes brace expansion, support for additional shopt/set options, support for the time special keyword, and support for multiple additional builtin commands.
What's Changed
fix: stop incorrectly parsing assignment as function def by @reubeno in #273
fix: assorted non-fatal clippy warnings by @reubeno in #274
fix: multiple issues blocking docker cmd completion by @reubeno in #275
fix: correct handling of multi-byte chars in highlighter by @reubeno in #277
feat(prompts): enable PS0, custom right-side prompts, more by @reubeno in #278
feat(set): implement nullglob option by @reubeno in #279
fix: improve substring ops with multi-byte chars by @reubeno in #280
fix: better handle escape chars in pattern bracket exprs by @reubeno in #281
feat(set): implement nocaseglob + nocasematch options by @reubeno in #282
build(deps): bump the cargo group with 3 updates by @dependabot in #285
build(deps): bump the cargo group with 4 updates by @dependabot in #289
feat(completion): progress toward passing bash-completion test suite by @reubeno in #288
feat: implement brace expansion by @reubeno in #290
feat(options): implement noclobber option (a.k.a. -C) by @reubeno in #291
build(deps): bump the cargo group with 3 updates by @dependabot in #294
chore: pin workflows to specific ubuntu versions by @reubeno in #293
chore: update reedline + Cargo.lock by @reubeno in #296
build(deps): bump anyhow from 1.0.94 to 1.0.95 in the cargo group by @dependabot in #297
fix: implement date and time in prompts by @reubeno in #298
build(deps): bump the cargo group with 2 updates by @dependabot in #299
fix(completion): handle -o {default,dirnames,plusdirs} by @reubeno in #300
perf: cache parsing for arithmetic expressions by @reubeno in #301
build(deps): bump the cargo group with 2 updates by @dependabot in #304
fix(jobs): only report job status when job control option is enabled by @reubeno in #306
feat(builtins): implement more of kill builtin by @reubeno in #305
perf: remove setup operations from microbenchmarks by @reubeno in #307
feat(builtins): implement times builtin by @reubeno in #309
feat(non-posix): implement time keyword by @reubeno in #310
feat(builtins): implement suspend by @reubeno in #311