@jerryan/just-bash 3.5.0 → 3.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/CHANGELOG.md +334 -308
  2. package/LICENSE +201 -201
  3. package/README.md +827 -827
  4. package/dist/agent-sandbox.d.ts +27 -0
  5. package/dist/bin/chunks/{chunk-7WBCA2BB.js → chunk-3DWQCLNP.js} +1 -1
  6. package/dist/bin/chunks/{chunk-QFTZKD5O.js → chunk-6TUILMPB.js} +1 -1
  7. package/dist/bin/chunks/chunk-JHEAT7AR.js +12 -0
  8. package/dist/bin/chunks/{chunk-MF3GVFLC.js → chunk-L345YZ6R.js} +1 -1
  9. package/dist/bin/chunks/chunk-QKJAAJ7J.js +3 -0
  10. package/dist/bin/chunks/chunk-SE7JHGP3.js +9 -0
  11. package/dist/bin/{shell/chunks/chunk-NLU5LALY.js → chunks/chunk-YCOJCFGU.js} +1 -1
  12. package/dist/bin/{shell/chunks/flag-coverage-J2ZHA465.js → chunks/flag-coverage-FYJ2V7J4.js} +1 -1
  13. package/dist/bin/chunks/{js-exec-DJQLXWCS.js → js-exec-5QZZCOR7.js} +7 -7
  14. package/dist/bin/chunks/js-exec-worker.js +155 -33
  15. package/dist/bin/{shell/chunks/python3-JCJHSX4Z.js → chunks/python3-TMFYDQAP.js} +1 -1
  16. package/dist/bin/chunks/{rm-3PLW4O4B.js → rm-NLG5344W.js} +1 -1
  17. package/dist/bin/chunks/{sleep-DVFE2GSF.js → sleep-MOJQBZMY.js} +1 -1
  18. package/dist/bin/{shell/chunks/sqlite3-KP42NNIY.js → chunks/sqlite3-3EUPHVEZ.js} +1 -1
  19. package/dist/bin/chunks/{timeout-YGFHQJKX.js → timeout-RQOWSWYG.js} +1 -1
  20. package/dist/bin/chunks/worker.js +162 -48
  21. package/dist/bin/just-bash.js +307 -307
  22. package/dist/bin/shell/chunks/{chunk-7WBCA2BB.js → chunk-3DWQCLNP.js} +1 -1
  23. package/dist/bin/shell/chunks/{chunk-QFTZKD5O.js → chunk-6TUILMPB.js} +1 -1
  24. package/dist/bin/shell/chunks/chunk-JHEAT7AR.js +12 -0
  25. package/dist/bin/shell/chunks/{chunk-MF3GVFLC.js → chunk-L345YZ6R.js} +1 -1
  26. package/dist/bin/shell/chunks/chunk-QKJAAJ7J.js +3 -0
  27. package/dist/bin/shell/chunks/chunk-SE7JHGP3.js +9 -0
  28. package/dist/bin/{chunks/chunk-NLU5LALY.js → shell/chunks/chunk-YCOJCFGU.js} +1 -1
  29. package/dist/bin/{chunks/flag-coverage-J2ZHA465.js → shell/chunks/flag-coverage-FYJ2V7J4.js} +1 -1
  30. package/dist/bin/shell/chunks/{js-exec-DJQLXWCS.js → js-exec-5QZZCOR7.js} +7 -7
  31. package/dist/bin/{chunks/python3-JCJHSX4Z.js → shell/chunks/python3-TMFYDQAP.js} +1 -1
  32. package/dist/bin/shell/chunks/{rm-3PLW4O4B.js → rm-NLG5344W.js} +1 -1
  33. package/dist/bin/shell/chunks/{sleep-DVFE2GSF.js → sleep-MOJQBZMY.js} +1 -1
  34. package/dist/bin/{chunks/sqlite3-KP42NNIY.js → shell/chunks/sqlite3-3EUPHVEZ.js} +1 -1
  35. package/dist/bin/shell/chunks/{timeout-YGFHQJKX.js → timeout-RQOWSWYG.js} +1 -1
  36. package/dist/bin/shell/shell.js +237 -237
  37. package/dist/bundle/browser.js +240 -240
  38. package/dist/bundle/chunks/{chunk-N3A4JVFJ.js → chunk-6IA4DXG2.js} +1 -1
  39. package/dist/bundle/chunks/chunk-G3IRZ4FN.js +8 -0
  40. package/dist/bundle/chunks/{chunk-24NLAR7R.js → chunk-KEMO3CBM.js} +1 -1
  41. package/dist/bundle/chunks/chunk-PS2RJNZZ.js +2 -0
  42. package/dist/bundle/chunks/{chunk-DMWNBCXJ.js → chunk-TLPMB3FO.js} +1 -1
  43. package/dist/bundle/chunks/chunk-ULXGGWAD.js +11 -0
  44. package/dist/bundle/chunks/{chunk-XV2V56NQ.js → chunk-YFFU74KY.js} +1 -1
  45. package/dist/bundle/chunks/{flag-coverage-DPSAPFXA.js → flag-coverage-XSPWRCVG.js} +1 -1
  46. package/dist/bundle/chunks/{js-exec-XKF2B7C3.js → js-exec-57QMXJG5.js} +7 -7
  47. package/dist/bundle/chunks/js-exec-worker.js +155 -33
  48. package/dist/bundle/chunks/{python3-F5S5TYGS.js → python3-NNONJINM.js} +1 -1
  49. package/dist/bundle/chunks/{rm-JQ4GDKDD.js → rm-R2ZENNSN.js} +1 -1
  50. package/dist/bundle/chunks/{sleep-PPRBTSVR.js → sleep-25QUPVDK.js} +1 -1
  51. package/dist/bundle/chunks/{sqlite3-4EZ4GXVD.js → sqlite3-M4UZPXDO.js} +1 -1
  52. package/dist/bundle/chunks/{timeout-C6WDYPLV.js → timeout-37GM7IIL.js} +1 -1
  53. package/dist/bundle/chunks/worker.js +162 -48
  54. package/dist/bundle/index.cjs +760 -760
  55. package/dist/bundle/index.js +306 -306
  56. package/dist/commands/js-exec/js-exec.d.ts +4 -0
  57. package/dist/commands/worker-bridge/bridge-handler.d.ts +9 -0
  58. package/dist/commands/worker-bridge/protocol.d.ts +17 -0
  59. package/dist/commands/worker-bridge/sync-backend.d.ts +3 -0
  60. package/dist/fs/overlay-fs/apply.d.ts +13 -0
  61. package/dist/fs/overlay-fs/index.d.ts +2 -0
  62. package/dist/fs/overlay-fs/merge.d.ts +24 -0
  63. package/dist/fs/overlay-fs/overlay-fs.d.ts +17 -0
  64. package/dist/fs/overlay-fs/overlay-tree.d.ts +39 -0
  65. package/dist/fs/real-fs-utils.d.ts +15 -0
  66. package/dist/fs/vfs-template.d.ts +51 -0
  67. package/dist/index.d.cts +2 -1
  68. package/dist/index.d.ts +2 -1
  69. package/dist/timers.d.ts +9 -0
  70. package/package.json +32 -33
  71. package/vendor/cpython-emscripten/python.cjs +2 -2
  72. package/dist/bin/chunks/chunk-JQM3DKCH.js +0 -12
  73. package/dist/bin/chunks/chunk-PPVF2N6C.js +0 -3
  74. package/dist/bin/chunks/chunk-YOIFOOGX.js +0 -9
  75. package/dist/bin/shell/chunks/chunk-JQM3DKCH.js +0 -12
  76. package/dist/bin/shell/chunks/chunk-PPVF2N6C.js +0 -3
  77. package/dist/bin/shell/chunks/chunk-YOIFOOGX.js +0 -9
  78. package/dist/bundle/chunks/chunk-LPJEKUCB.js +0 -8
  79. package/dist/bundle/chunks/chunk-WXPNKIIH.js +0 -2
  80. package/dist/bundle/chunks/chunk-YJKHREBZ.js +0 -11
package/CHANGELOG.md CHANGED
@@ -1,308 +1,334 @@
1
- # just-bash
2
-
3
- ## 3.4.2
4
-
5
- ### Patch Changes
6
-
7
- - [#381](https://github.com/vercel-labs/just-bash/pull/381) [`d40a42d`](https://github.com/vercel-labs/just-bash/commit/d40a42d514b22da4ed023635d747c8b3f029a6c5) Thanks [@cramforce](https://github.com/cramforce)! - Include the security and transform declaration trees referenced by the package entrypoints and worker declarations in published packages.
8
-
9
- ## 3.4.1
10
-
11
- ### Patch Changes
12
-
13
- - [#373](https://github.com/vercel-labs/just-bash/pull/373) [`2c1831c`](https://github.com/vercel-labs/just-bash/commit/2c1831cc832d4b09ee4e1823526afb6ccca77942) Thanks [@cramforce](https://github.com/cramforce)! - Prevent defense-in-depth violation reporting from recursively overflowing the call stack in host runtimes that wrap `Date.now()`, honor configured main-thread violation exclusions, include actionable exclusion guidance for configurable violations, and keep constructor-execution protections non-excludable.
14
-
15
- ## 3.4.0
16
-
17
- ### Minor Changes
18
-
19
- - [#303](https://github.com/vercel-labs/just-bash/pull/303) [`c5a2a4a`](https://github.com/vercel-labs/just-bash/commit/c5a2a4a35c7490276befa716acae3fe880c1fe89) Thanks [@boramuyar](https://github.com/boramuyar)! - Provide the shadowed bundled command to custom command overrides through `CommandContext.origCommand`.
20
-
21
- ## 3.3.0
22
-
23
- ### Minor Changes
24
-
25
- - [#291](https://github.com/vercel-labs/just-bash/pull/291) [`47f604a`](https://github.com/vercel-labs/just-bash/commit/47f604a7f1e12730318e4c88c7872a5a35383056) Thanks [@trieloff](https://github.com/trieloff)! - jq: add external-argument flags (`--arg`, `--argjson`, `--rawfile`, `--slurpfile`, `--args`, `--jsonargs`) and the `$ARGS` object (`$ARGS.named` / `$ARGS.positional`), matching real jq 1.7.1 behavior including exit codes, error messages, and prototype-sensitive key handling.
26
-
27
- - [#336](https://github.com/vercel-labs/just-bash/pull/336) [`d97425d`](https://github.com/vercel-labs/just-bash/commit/d97425dff8f51cfd773d22bc009561a09235cd1b) Thanks [@trieloff](https://github.com/trieloff)! - Support user file descriptors (fd >= 3). `exec 3< file`, `N< file` / `N> file` / `N>> file` on any command, `read -u N`, `read <&N`, `>&N`, `N<&M`, and `N<&-` now go through a real descriptor table: a descriptor carries one shared read position, `exec` keeps it open until it is closed, and every other construct — including `done N< file` on a loop — gets it only for the duration of that command.
28
-
29
- - [#331](https://github.com/vercel-labs/just-bash/pull/331) [`6680247`](https://github.com/vercel-labs/just-bash/commit/66802470837cfac3a58a09e00d37b2070387ba7b) Thanks [@trieloff](https://github.com/trieloff)! - Treat a `-` FILE operand in `grep` as standard input, matching GNU. `grep PATTERN -` now reads stdin instead of failing with "No such file or directory", stdin is labelled `(standard input)` in the multi-file prefix and in `-l`/`-L`/`-c` output, repeated `-` operands see the stream drained by the first one, and `-` is exempt from `-r` recursion and `--include`/`--exclude` filtering.
30
-
31
- - [#325](https://github.com/vercel-labs/just-bash/pull/325) [`edc7f2f`](https://github.com/vercel-labs/just-bash/commit/edc7f2fac5337cebd19911c5756b76ed02e52090) Thanks [@trieloff](https://github.com/trieloff)! - Support process substitution `<(cmd)` and `>(cmd)`.
32
-
33
- `<(cmd)` runs `cmd` and substitutes a readable `/dev/fd/N` path backed by an
34
- in-memory file; `>(cmd)` substitutes a writable path whose contents are fed to
35
- `cmd` once the outer command finishes. Descriptors are numbered from 63
36
- downwards like bash and released when the command that opened them completes.
37
- Process substitutions retain their surrounding word context in assignments,
38
- conditionals, regular expressions, and heredoc delimiters. Previously any use
39
- raised `Parse error: Expected redirection target`.
40
-
41
- - [#327](https://github.com/vercel-labs/just-bash/pull/327) [`eaedb5b`](https://github.com/vercel-labs/just-bash/commit/eaedb5bc34cffd2077b88bb1ccc48ea7e0545a48) Thanks [@trieloff](https://github.com/trieloff)! - Add `grep -f FILE` / `--file=FILE` to read patterns from a file (one per line). Patterns from `-f` OR-combine with `-e` patterns and with each other, `-f -` reads patterns from stdin, empty pattern lines match every line, and an empty pattern file selects nothing (exit 1). Newline-separated `PATTERNS` operands are now split into individual patterns, and `-x` groups alternatives correctly (`^(?:a|b)$`).
42
-
43
- ### Patch Changes
44
-
45
- - [#358](https://github.com/vercel-labs/just-bash/pull/358) [`bd1df37`](https://github.com/vercel-labs/just-bash/commit/bd1df37f8ff836355f470e95dcaa004b769d1e61) Thanks [@privatenumber](https://github.com/privatenumber)! - Parse and serialize bare file descriptor variable redirections such as `{output}>output.log` and `{input}<<EOF`. Bare redirects create their target with a command-scoped descriptor, while named command forms keep the allocated descriptor available.
46
-
47
- - [#347](https://github.com/vercel-labs/just-bash/pull/347) [`abb904b`](https://github.com/vercel-labs/just-bash/commit/abb904b1e126d14aa437b05f006df83117f06db3) Thanks [@privatenumber](https://github.com/privatenumber)! - Fix escaped reserved words being parsed as shell syntax. Unquoted escapes now retain their provenance through lexing and word parsing, including when the word is serialized back to Bash.
48
-
49
- - [#332](https://github.com/vercel-labs/just-bash/pull/332) [`4f9bdec`](https://github.com/vercel-labs/just-bash/commit/4f9bdec02edb9eb72511546b759cb7e20bc2e27e) Thanks [@trieloff](https://github.com/trieloff)! - Fix `grep -L` exit status to match GNU grep. The status reports whether a line
50
- was selected, not whether a filename was printed, so `grep -L` now exits 0 when
51
- every file matched (printing nothing) and 1 when no file matched (printing every
52
- name) — previously these were inverted.
53
-
54
- - [#339](https://github.com/vercel-labs/just-bash/pull/339) [`31d247f`](https://github.com/vercel-labs/just-bash/commit/31d247fe3a62f081b4462064da195552ab0a421c) Thanks [@mutewinter](https://github.com/mutewinter)! - network: restore private-range-enforced requests from the bundled build
55
-
56
- Every request made with `denyPrivateRanges` enabled failed with `Network access denied: DNS pinning unavailable for private IP enforcement`, so `curl` could not reach any host at all. The published ESM bundle was affected; source consumers and the CommonJS bundle were not.
57
-
58
- The pinned connection owner reads `Agent` and `fetch` off a dynamic `import("undici")`. Node's resolution of the package exposes those as named exports, but the ESM build inlines undici's CommonJS module into a chunk whose namespace carries it under `default` alone, so `Agent` was `undefined` and the `TypeError` from constructing it was reported as a runtime incapable of pinning.
59
-
60
- The namespace is now normalized before the transport is read off it, which also covers a consumer that bundles just-bash further.
61
-
62
- - [#336](https://github.com/vercel-labs/just-bash/pull/336) [`d97425d`](https://github.com/vercel-labs/just-bash/commit/d97425dff8f51cfd773d22bc009561a09235cd1b) Thanks [@trieloff](https://github.com/trieloff)! - Stop command groups, function bodies and `eval` from rewinding stdin they never replaced, so `{ { read a; }; read b; }` gives `b` the second line instead of replaying the first.
63
-
64
- - [#348](https://github.com/vercel-labs/just-bash/pull/348) [`1a7940d`](https://github.com/vercel-labs/just-bash/commit/1a7940ddf91dec8f69125474a40cef1adebabee9) Thanks [@privatenumber](https://github.com/privatenumber)! - Reject unsupported command-leading reserved words in every parser context instead of discarding them or executing them as simple commands. Unknown command AST nodes now fail explicitly instead of returning a successful result.
65
-
66
- - [#345](https://github.com/vercel-labs/just-bash/pull/345) [`2208a34`](https://github.com/vercel-labs/just-bash/commit/2208a34e27d33a2fce712fbd024875ec60747553) Thanks [@privatenumber](https://github.com/privatenumber)! - Restore command groups and subshells after the process-substitution and stdin-ownership changes were combined without forwarding ownership through inner command dispatch.
67
-
68
- - [#336](https://github.com/vercel-labs/just-bash/pull/336) [`d97425d`](https://github.com/vercel-labs/just-bash/commit/d97425dff8f51cfd773d22bc009561a09235cd1b) Thanks [@trieloff](https://github.com/trieloff)! - Apply output redirections attached to `while` and `until` loops. `while true; do echo x; break; done >/dev/null` no longer leaks its output to the caller, and `> file`, `>>`, `2>`, `2>&1`, `&>` and `>|` now behave on loops the way they already did on `for` and `case`. `until` loops also gained the input-redirection handling `while` loops already had, so `until ! read l; do ...; done < file` reads from the file. A loop now only restores stdin it owns, so reading inside a loop no longer rewinds an enclosing group's read position: `printf 'a\nb\n' | { while read x; do break; done; read y; }` sees `y=b`.
69
-
70
- - [#328](https://github.com/vercel-labs/just-bash/pull/328) [`65dafd5`](https://github.com/vercel-labs/just-bash/commit/65dafd55afbfa7e62642ce485787f7d65fad4961) Thanks [@trieloff](https://github.com/trieloff)! - Stop pipelines from draining the enclosing shell's stdin, so `while read …; do … | …; done < file` runs once per line again.
71
-
72
- - [#349](https://github.com/vercel-labs/just-bash/pull/349) [`be55fec`](https://github.com/vercel-labs/just-bash/commit/be55fec4e23b3f5a42cf8eaeb6939b379f741ae1) Thanks [@privatenumber](https://github.com/privatenumber)! - Process redirections through policy-driven transactions that preserve Bash ordering, descriptor lifetimes, persistent `exec` routes, compound-command stdin, control-flow output routing, and shared read-write descriptor positions without duplicate expansion or opening.
73
-
74
- - [#368](https://github.com/vercel-labs/just-bash/pull/368) [`3ee215c`](https://github.com/vercel-labs/just-bash/commit/3ee215c2ad56c96ce0d88e2813050df9f15afa38) Thanks [@cramforce](https://github.com/cramforce)! - FS sym-link hardening
75
-
76
- - [#338](https://github.com/vercel-labs/just-bash/pull/338) [`19a02c2`](https://github.com/vercel-labs/just-bash/commit/19a02c297d110fde8a8a3376d6956c2c549d128e) Thanks [@mutewinter](https://github.com/mutewinter)! - sqlite3: report failed statements on stderr and exit non-zero without `-bail`
77
-
78
- A statement that failed was written to **stdout** as `Error: ...` and the command still exited `0` unless `-bail` was passed. Real `sqlite3` writes the error to stderr and exits `1` in either mode; `-bail` only decides whether the remaining statements still run.
79
-
80
- Two consequences for callers: `sqlite3 db "SELECT ..." > out.csv` silently wrote the error text into the data file, and `sqlite3 db "..." && next-step` ran `next-step` after the query had failed, so a shell script could not detect a bad query without opting into `-bail` and losing the ability to see later statements.
81
-
82
- Errors now accumulate on stderr in statement order and the exit status is `1` whenever any statement failed. Successful runs are unchanged, `-bail` still stops at the first failure, and the partial stdout produced before a failure is still emitted. Writeback of a partially-successful script is also unchanged.
83
-
84
- - [#360](https://github.com/vercel-labs/just-bash/pull/360) [`1fbde34`](https://github.com/vercel-labs/just-bash/commit/1fbde341d74ff7f933d9cead9a390a6ab65b5df3) Thanks [@privatenumber](https://github.com/privatenumber)! - Preserve whether a here-document ended at its delimiter or at end-of-input. Unterminated final body lines now receive Bash's trailing newline, backslash-newline continuations are removed during expansion, and serialization rejects unterminated documents rather than manufacturing a closing delimiter.
85
-
86
- ## 3.2.0
87
-
88
- ### Minor Changes
89
-
90
- - [#304](https://github.com/vercel-labs/just-bash/pull/304) [`3d39a71`](https://github.com/vercel-labs/just-bash/commit/3d39a714b3751cedc173dffae27933dfe7b8b3b5) Thanks [@subsetpark](https://github.com/subsetpark)! - Add curl `-G`/`--get` query-string data handling and preserve command-line order when repeated `-d`, `--data-raw`, `--data-binary`, and `--data-urlencode` options are mixed, including `@file` forms. Data requests now also set curl's standard `application/x-www-form-urlencoded` content type unless the caller supplies one.
91
-
92
- - [#307](https://github.com/vercel-labs/just-bash/pull/307) [`7c4caed`](https://github.com/vercel-labs/just-bash/commit/7c4caedf02599628f19b243f960d480760f5e476) Thanks [@cramforce](https://github.com/cramforce)! - Harden untrusted execution with shared aggregate budgets, liberal normal and
93
- opt-in hardened limit profiles, request-bound network validation, bounded
94
- archive and worker processing, transactional filesystem and shell state, and
95
- expanded adversarial regression checks.
96
-
97
- Established command declarations and host-extension defaults remain source
98
- compatible. Dispatched callbacks receive a `ResolvedCommandContext` with
99
- required limits; applications can use `createCommandContext({ fs })` for direct
100
- invocation, opt into restricted custom-command execution with `trusted: false`,
101
- and select tighter resource policy with the `hardened` profile. All
102
- host-registration paths keep their established trusted default. The supported
103
- Node.js floor is now declared as `>=20.18.1`.
104
-
105
- ### Patch Changes
106
-
107
- - [#315](https://github.com/vercel-labs/just-bash/pull/315) [`6df692f`](https://github.com/vercel-labs/just-bash/commit/6df692f236ca108c888552a67557998156ac845b) Thanks [@matchai](https://github.com/matchai)! - Treat `--` as the end of options in `grep`.
108
-
109
- ## 3.1.0
110
-
111
- ### Minor Changes
112
-
113
- - [#284](https://github.com/vercel-labs/just-bash/pull/284) [`af2e0f4`](https://github.com/vercel-labs/just-bash/commit/af2e0f4cdeb5417ea59e25140038c239dd8fd92d) Thanks [@arimxyer](https://github.com/arimxyer)! - sandbox: forward capability flags from `SandboxOptions` into the underlying `Bash`
114
-
115
- `Sandbox.create(opts)` previously constructed its internal `Bash` with only a subset
116
- of `BashOptions`, silently dropping the optional capability flags (`python`,
117
- `javascript`, `commands`, `customCommands`, `fetch`). A host that drives just-bash
118
- through the `Sandbox` API (rather than `new Bash(...)`) therefore could not enable
119
- python3, js-exec, a restricted command set, custom commands, or a custom fetch — even
120
- though the runtimes ship in the package.
121
-
122
- `SandboxOptions` now exposes those fields and `Sandbox.create` forwards them into the
123
- `Bash` it builds. Behavior is unchanged when a caller omits them (each falls back to
124
- its existing `BashOptions` default — Python/js-exec stay off, the full command set
125
- stays available). Fixes the root cause behind vercel/eve#431.
126
-
127
- ### Patch Changes
128
-
129
- - [#268](https://github.com/vercel-labs/just-bash/pull/268) [`7a5a0b9`](https://github.com/vercel-labs/just-bash/commit/7a5a0b9ae3bf0524722653cbf4b45e6bc176cf22) Thanks [@trieloff](https://github.com/trieloff)! - jq: allow nested double-quoted strings inside `"\(...)"` string interpolation
130
-
131
- jq string interpolation of the form `"\(...)"` that contained a nested double-quoted string — for example `"\(sub("T.*";""))"` or `"\(ltrimstr("ab"))"` — previously failed with a parse error. The tokenizer terminated the outer string at the first `"` it saw inside the interpolation expression, so the rest of the expression became orphaned tokens.
132
-
133
- The lexer now tracks `\(...)` depth while consuming a string literal and treats nested `"..."` pairs as opaque content while inside an interpolation, restoring them verbatim into the captured interpolation source. `parseStringInterpolation` similarly skips over nested strings when balancing parentheses, so the interpolation expression is captured as a whole and handed to the expression parser intact.
134
-
135
- ## 3.0.3
136
-
137
- ### Patch Changes
138
-
139
- - [#277](https://github.com/vercel-labs/just-bash/pull/277) [`aec5643`](https://github.com/vercel-labs/just-bash/commit/aec56431d7d9b6fcb141bbfe25d26f4931f54f80) Thanks [@mutewinter](https://github.com/mutewinter)! - interpreter: avoid lazy import in variable assignment path that trips defense-in-depth (fixes [#273](https://github.com/vercel-labs/just-bash/issues/273))
140
-
141
- Any non-`export` variable assignment (bare `SECRET=s`, prefixed `SECRET=s cmd`,
142
- or before a custom command) failed with a defense-in-depth security violation
143
- (`dynamic import of Node.js builtin 'node:module' is blocked during script
144
- execution`), while plain commands and `export`-ed assignments passed.
145
-
146
- `processScalarAssignment()` resolved `isArray` via `await import("./expansion.js")`
147
- in two spots. In the bundled `dist`, that dynamic `import()` marks `expansion.js`
148
- as a lazily-linked chunk whose `createRequire` banner imports `node:module`; the
149
- defense layer's ESM `resolve` hook blocks that builtin import when the sandbox is
150
- active and untrusted, so it blocked just-bash's own chunk load. The file already
151
- statically imports from `./expansion.js`, so `isArray` is now pulled from that
152
- static import and the two lazy imports are removed — no lazy `node:module`-bearing
153
- chunk is linked at runtime. No public API change.
154
-
155
- - [#276](https://github.com/vercel-labs/just-bash/pull/276) [`1ec5eec`](https://github.com/vercel-labs/just-bash/commit/1ec5eec0aefd099d23ac9f056df1e6612c81d49b) Thanks [@mutewinter](https://github.com/mutewinter)! - interpreter: preserve leading whitespace in multi-line quoted strings (fixes [#259](https://github.com/vercel-labs/just-bash/issues/259))
156
-
157
- `exec()` runs each script through `normalizeScript()`, which `trimStart()`s
158
- leading indentation from lines so indented template-literal scripts parse. It
159
- was applied line-by-line and stripped the leading whitespace inside multi-line
160
- single- and double-quoted strings too. The visible symptom was `python3 -c
161
- '...'` (and `node -e`, `awk`, etc.) with an indented body failing with
162
- `IndentationError`, while the same code via heredoc or pipe worked.
163
-
164
- `normalizeScript()` is now quote-aware (mirroring the earlier heredoc-aware
165
- fix): it only strips indentation from lines that begin outside any quote, and
166
- preserves lines that begin inside an unterminated single- or double-quoted
167
- string verbatim. This also un-skips four sed spec tests whose indented stdin
168
- was previously being corrupted.
169
-
170
- - [#286](https://github.com/vercel-labs/just-bash/pull/286) [`cb2b583`](https://github.com/vercel-labs/just-bash/commit/cb2b583b3f46e6bb4e6982c4bfe19903ec811a87) Thanks [@privatenumber](https://github.com/privatenumber)! - interpreter: deliver redirected output to each fd's final target (fixes `cmd > file 2>&1` leaking stderr to stdout)
171
-
172
- `applyRedirections()` processed a command's redirection list sequentially over
173
- the result's stdout/stderr strings, moving content at each step. The
174
- duplication operators (`2>&1`, `1>&2`) merged into the live stream regardless
175
- of where the source fd pointed, so the canonical `cmd > file 2>&1` wrote
176
- stdout to the file but leaked stderr onto the caller's stdout — including
177
- "command not found" errors and custom-command stderr. Any wrapper protocol
178
- that parses the enclosing script's stdout (e.g. a runner emitting a JSON
179
- payload after `eval "$CMD" > "$OUT" 2>&1`) saw the leaked stderr corrupt its
180
- stream. Ordering variants were wrong in other ways: `cmd 2>&1 > file` put
181
- stderr in the file instead of on stdout, and `cmd > a > b` wrote content to
182
- `a` instead of `b`.
183
-
184
- The pass now mirrors how bash sets up fds before running the command: each
185
- output redirection only opens/truncates its target and re-points the fd's
186
- sink (file, /dev/null, or a snapshot of the caller-visible stream), and
187
- duplication operators copy the source fd's current sink. Stream content is
188
- delivered once, after the whole list is processed, to each fd's final sink.
189
- This makes `cmd > file 2>&1` send stderr to the file, `cmd 2>&1 > file` keep
190
- stderr on the caller's stdout, `cmd > all 2>&1 2> err` let the later `2> err`
191
- reclaim stderr, and `cmd > a > b` truncate `a` while writing content to `b`.
192
- The `/dev/null`-as-regular-VFS-file behavior for stdout redirects is
193
- preserved.
194
-
195
- ## 3.0.2
196
-
197
- ### Patch Changes
198
-
199
- - [#272](https://github.com/vercel-labs/just-bash/pull/272) [`150a915`](https://github.com/vercel-labs/just-bash/commit/150a915a1d45a2cc7f2b6aec3268f27116c34916) Thanks [@trieloff](https://github.com/trieloff)! - interpreter: fix UTF-8 mojibake when a script interleaves text-output and byte-output statements
200
-
201
- A single `exec()` can interleave text-shaped statements (sed, awk, echo — `ö`
202
- as `U+00F6`) with byte-shaped ones (grep | head, cat — `ö` as bytes
203
- `0xC3 0xB6`). `executeScript` / `executeStatement` concatenated each result's
204
- raw stdout, so the lone high byte from the text half made the combined stream
205
- invalid UTF-8, the output-boundary decoder bailed, and the byte half came back
206
- as Latin-1 mojibake (`Köpenicker` for `Köpenicker`). The same path backs
207
- command substitution, so `echo "你好: $(cat /file)"` was affected too.
208
-
209
- The fix decodes each statement/pipeline result to text via its explicit
210
- `stdoutKind` (`decodedTextFromResult`) before concatenating — no guessing from
211
- string contents, so text whose code units merely look like UTF-8 (`ö`) is
212
- preserved. `tac` (stdin path) and `curl` (response body) now declare
213
- `stdoutKind: "bytes"` on the results that forward raw bytes, so the decode is
214
- driven per output rather than by inspecting characters.
215
-
216
- - [#256](https://github.com/vercel-labs/just-bash/pull/256) [`75d8dfd`](https://github.com/vercel-labs/just-bash/commit/75d8dfd3a322786250e3b0f81b1500c87610acb7) Thanks [@Hazzng](https://github.com/Hazzng)! - js-exec: fix Buffer shim correctness — ascii encode now uses & 0xff (not & 0x7f), consolidate latin1/ascii into shared \_rawEncode, fix Buffer.from(ArrayBuffer, offset, length), throw on invalid byteLength input, clamp negative toString start, throw RangeError for out-of-range write offset
217
-
218
- - [#239](https://github.com/vercel-labs/just-bash/pull/239) [`1369b77`](https://github.com/vercel-labs/just-bash/commit/1369b772fe887694c09ce834d1b0b21aa6420b59) Thanks [@trieloff](https://github.com/trieloff)! - curl: interpret `@file` for `-d`/`--data`, `--data-binary`, and `--data-urlencode`
219
-
220
- Real curl reads file contents when these flags are passed `@filename`:
221
-
222
- - `-d @file` / `--data @file` — read file contents, strip CR/LF.
223
- - `--data-binary @file` — read file contents verbatim (newlines preserved).
224
- - `--data-urlencode @file` — read file, URL-encode the contents.
225
- - `--data-urlencode name@file` — prefix the URL-encoded contents with `name=`.
226
-
227
- just-bash's curl previously passed `@filename` through verbatim as the HTTP body. Posting JSON or any non-trivial payload via `curl --data-binary @payload.json https://…` sent the literal string `@payload.json` instead of the file. The new behavior matches upstream curl; `--data-raw` keeps the documented "no `@` interpretation" semantics.
228
-
229
- - [#262](https://github.com/vercel-labs/just-bash/pull/262) [`4ece258`](https://github.com/vercel-labs/just-bash/commit/4ece2580d8cb707e6c6b7fa22897ea3fdd21739a) Thanks [@chernetsov](https://github.com/chernetsov)! - parser: don't treat quotes inside a heredoc body as shell quotes when finding the end of a command substitution
230
-
231
- A command substitution whose body contained a heredoc with an unbalanced quote in its body — most commonly an apostrophe in literal prose, e.g. `June's` — failed to parse with `bash: syntax error: ... unexpected EOF while looking for matching ')'`:
232
-
233
- ```bash
234
- OUT=$(cat <<'SCRIPT'
235
- June's moon
236
- SCRIPT
237
- )
238
- ```
239
-
240
- Both the lexer's `$(...)` word scanner and the substitution boundary scanner walked into the heredoc body and applied shell quote tracking to it. The `'` in `June's` opened a single-quoted string that never closed, so the closing `)` was swallowed and the scan ran to EOF. In bash a heredoc body is literal text and must be skipped wholesale when locating the substitution boundary.
241
-
242
- Both scanners are now heredoc-aware: when scanning a `$(...)` they recognize `<<` / `<<-` operators (but not the `<<<` here-string), capture the possibly-quoted delimiter, and skip the heredoc body lines literally — without quote or paren tracking — up to the terminator. Multiple heredocs on one line and tab-stripping (`<<-`) are handled. This fixes the common pattern of capturing the output of a connector/CLI invocation that is fed a heredoc script containing apostrophes, backticks, or parentheses.
243
-
244
- The heredoc scan also tracks arithmetic `((...))` nesting so a `<<` left-shift inside `$((...))` (or a nested arithmetic expansion) is not mistaken for a heredoc opener — previously a multi-line arithmetic expansion containing a shift, e.g. `$((\n1 << 2\n))`, had its closing `))` swallowed by spurious body-skipping.
245
-
246
- - [#248](https://github.com/vercel-labs/just-bash/pull/248) [`d64009a`](https://github.com/vercel-labs/just-bash/commit/d64009aef6bc1556e7c84b22ed455863275ea953) Thanks [@Hazzng](https://github.com/Hazzng)! - perf(grep): up to 14.5× speedup via preFilter extensions and matcher reuse.
247
-
248
- Anchored alternation patterns like `^def \|^async def` now extract literal needles (stripping outer `^`/`$`), enabling the `String.indexOf` fast-path. Files with no matching needle are rejected before `split("\n")`, skipping RE2 entirely. `acquireMatcher()` extended to `match()`, `replace()`, `search()`, and `matchAll()` to reduce GC pressure across awk/sed hot-paths.
249
-
250
- - [#261](https://github.com/vercel-labs/just-bash/pull/261) [`c9904de`](https://github.com/vercel-labs/just-bash/commit/c9904dea24ad2aa847749ee6289239c2a2c651fc) Thanks [@chernetsov](https://github.com/chernetsov)! - set: support a bundled `-o`/`+o` long option inside a short-flag cluster (e.g. `set -euo pipefail`)
251
-
252
- The `set` builtin previously rejected `set -euo pipefail` with `bash: set: -o: invalid option`, because it parsed each character after the `-` as an independent short flag and has no `o` short flag. `-o` was only honored as its own token (`set -eu -o pipefail`).
253
-
254
- This is the canonical "bash strict mode" idiom and is extremely common in generated scripts, so the whole script would abort on its first line.
255
-
256
- `set` now matches bash: an `o` inside a cluster consumes the _next word_ as its long-option name, and the remaining characters keep being parsed as short flags. So `set -euo pipefail` is equivalent to `set -e -u -o pipefail`, `set -oe pipefail` enables both `pipefail` and `errexit`, trailing words become positional parameters, and `+`-clusters (`set +euo pipefail`) disable the options. An invalid bundled name (`set -euo bogus`) still reports `invalid option name`, and an `o` with no following argument falls back to the standalone `-o`/`+o` listing.
257
-
258
- ## 3.0.1
259
-
260
- ### Patch Changes
261
-
262
- - [#238](https://github.com/vercel-labs/just-bash/pull/238) [`01a4721`](https://github.com/vercel-labs/just-bash/commit/01a4721324350adea4b035b311f0b60ccdbb65ff) Thanks [@cramforce](https://github.com/cramforce)! - Fix `Dynamic require of "tty" is not supported` crash when invoking commands that transitively load `debug` / `supports-color` (notably `file`) under ESM Node consumers and via the `just-bash` CLI binary.
263
-
264
- The esbuild dynamic-require shim emitted into the ESM Node bundles had no `require` to delegate to at chunk-init under ESM, so any runtime `require("tty")` / `require("os")` from `file-type` → `debug` chain threw. Build banners now provide `createRequire(import.meta.url)` for `build:lib`, `build:cli`, and `build:shell`. CJS and browser bundles are unchanged.
265
-
266
- Fixes [#211](https://github.com/vercel-labs/just-bash/issues/211).
267
-
268
- ## 3.0.0
269
-
270
- ### Major Changes
271
-
272
- - [#233](https://github.com/vercel-labs/just-bash/pull/233) [`7cca738`](https://github.com/vercel-labs/just-bash/commit/7cca73831987e3331160f426b7a66d7217b8cf79) Thanks [@cramforce](https://github.com/cramforce)! - Breaking change for stdin byte/utf8-handling. Will break some custom commands that handle stdin
273
-
274
- ### Minor Changes
275
-
276
- - [#209](https://github.com/vercel-labs/just-bash/pull/209) [`b3bd85e`](https://github.com/vercel-labs/just-bash/commit/b3bd85ed816445e6d148290163a1900f49ebea82) Thanks [@cramforce](https://github.com/cramforce)! - Introducing plumbing for integrating executor and adding a peer package for the implememtation
277
-
278
- - [#233](https://github.com/vercel-labs/just-bash/pull/233) [`7cca738`](https://github.com/vercel-labs/just-bash/commit/7cca73831987e3331160f426b7a66d7217b8cf79) Thanks [@cramforce](https://github.com/cramforce)! - TS-enforced correct handling of utf8 on stdin. Impacts many commands
279
-
280
- ## 2.14.5
281
-
282
- ### Patch Changes
283
-
284
- - [#214](https://github.com/vercel-labs/just-bash/pull/214) [`da58f4f`](https://github.com/vercel-labs/just-bash/commit/da58f4f523c5e9c1c444106a0f2a7777a59fb618) Thanks [@subsetpark](https://github.com/subsetpark)! - jq: accept control characters inside JSON strings
285
-
286
- - [#221](https://github.com/vercel-labs/just-bash/pull/221) [`a835686`](https://github.com/vercel-labs/just-bash/commit/a835686c97f5cac2e5b94bd551d996079a33dfc2) Thanks [@cramforce](https://github.com/cramforce)! - upgrade deps
287
-
288
- - [#218](https://github.com/vercel-labs/just-bash/pull/218) [`13d78b2`](https://github.com/vercel-labs/just-bash/commit/13d78b2876d7ac7b6bc3a6eacfa3937bbb79665f) Thanks [@Hazzng](https://github.com/Hazzng)! - grep: 5-123x faster pattern matching via RE2 matcher reuse and literal pre-filter
289
-
290
- ## 2.14.4
291
-
292
- ### Patch Changes
293
-
294
- - [#206](https://github.com/vercel-labs/just-bash/pull/206) [`6ccc35f`](https://github.com/vercel-labs/just-bash/commit/6ccc35f5a9b5c6f395b145ed2ec7ee71c4862057) Thanks [@subsetpark](https://github.com/subsetpark)! - Fix awk lexer to honor POSIX statement continuation across newlines after `,`,
295
- `{`, `&&`, `||`, `?`, `:`, `do`, `else`, `if`, and `while`. Previously, a
296
- multi-line idiom like `printf "%s=%d\n", \n $1, $2` (comma at end-of-line
297
- followed by indented args on the next line) failed with `Unexpected token:
298
- NEWLINE` because the lexer emitted a NEWLINE token unconditionally. The
299
- lexer now suppresses the NEWLINE when it immediately follows one of the
300
- continuation-allowing tokens, matching POSIX awk.
301
-
302
- - [#212](https://github.com/vercel-labs/just-bash/pull/212) [`733c847`](https://github.com/vercel-labs/just-bash/commit/733c84796e3abbd05a25cf67805bf4b030d0b02d) Thanks [@cramforce](https://github.com/cramforce)! - Bug fixes across network, sqlite3, xan, rg, terminal rendering, and CI
303
-
304
- ## 2.14.3
305
-
306
- ### Patch Changes
307
-
308
- - [#199](https://github.com/vercel-labs/just-bash/pull/199) [`3d11f05`](https://github.com/vercel-labs/just-bash/commit/3d11f05959faa205267a5173b25665c6732fee8b) Thanks [@cramforce](https://github.com/cramforce)! - Internal: convert repository to a pnpm workspace under `packages/just-bash` and adopt Changesets for versioning. No public API changes; `import` paths and the `bin` entries are unchanged.
1
+ # just-bash
2
+
3
+ ## 3.6.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`f49b787`](https://github.com/JerryAZR/just-bash/commit/f49b7878d9f1b613afac0d58f6f67f4c6e180f85) Thanks [@JerryAZR](https://github.com/JerryAZR)! - Fixes since 3.6.0:
8
+
9
+ - **Windows real-dir modes**: real directories no longer report `0o40666` (no execute bits), which made every real-backed directory untraversable for the python worker (`chdir`/`listdir`/`open` EACCES below the overlay root). Modes are normalized to `0o755` on win32.
10
+ - **Abort/timeout preserves stdout**: output accumulated before an abort or execution deadline is no longer silently discarded — the exact partial output a harness needs on timeout.
11
+ - **js-exec worker leak**: the idle-teardown timer was suppressed by defense-in-depth context deactivation, leaking the worker (and its handles) so any process that ran js-exec could never exit naturally.
12
+ - **Torn bridge read on cancel**: a request-level cancel landing mid-op could surface as a garbage `Error code: 0` guest error instead of a clean timeout exit 124 (the intermittent js-exec CI flake class).
13
+ - **8MB file ceiling removed**: files larger than the 8MB bridge buffer are readable and writable in both worker runtimes (python3 and js-exec) via ranged transport.
14
+ - **Errno honesty**: python no longer reports `FileNotFoundError` for existing files when the backend errors (blanket ENOENT replaced by real mapping, numeric bridge error codes preferred over substring matching, `ENOTEMPTY` added end-to-end).
15
+ - **Binary write corruption**: js-exec `writeFile`/`appendFile` no longer writes `Uint8Array` data as comma-joined text; write data accepts exactly string/Buffer/TypedArray/DataView and throws TypeError otherwise.
16
+ - **Constructor guard**: `Bash({ fs, files })` now throws (files were silently ignored with a custom fs).
17
+ - **Concurrency**: `appendFile` and `sync()` no longer lose concurrent writes (copy-up and detach compare-and-swap).
18
+ - **rm -f**: ENOENT suppression anchored to the error-code prefix — a file named `ENOENT-notes` can't smuggle a real failure past `-f`.
19
+ - Plus review hardening: directory mode/mtime restored at apply, non-normalized change-set paths rejected loudly, `RESULT_LENGTH` overflow guard.
20
+
21
+ ## 3.6.0
22
+
23
+ ### Minor Changes
24
+
25
+ - [`942abb1`](https://github.com/JerryAZR/just-bash/commit/942abb1a41b836757d98a7a47c9c85633b0455ad) Thanks [@JerryAZR](https://github.com/JerryAZR)! - `rm -f` now suppresses only ENOENT errors, matching GNU rm: mount-point (EBUSY) and other failures are reported and exit 1 instead of being silently swallowed. Previously `rm -rf` on a mount point or its parent was a silent no-op with exit 0, while the change set correctly showed nothing had been deleted.
26
+
27
+ `AgentSandbox` gains path conversion helpers: `resolveRealPath(realPath)` maps a real host path to `{ mountPoint, overlay, path }` for direct shadow inspection on the overlay, and `toRealPath(vfsPath)` maps a VFS path to its real host path. Both return null for paths outside the mounted overlays.
28
+
29
+ ## 3.4.2
30
+
31
+ ### Patch Changes
32
+
33
+ - [#381](https://github.com/vercel-labs/just-bash/pull/381) [`d40a42d`](https://github.com/vercel-labs/just-bash/commit/d40a42d514b22da4ed023635d747c8b3f029a6c5) Thanks [@cramforce](https://github.com/cramforce)! - Include the security and transform declaration trees referenced by the package entrypoints and worker declarations in published packages.
34
+
35
+ ## 3.4.1
36
+
37
+ ### Patch Changes
38
+
39
+ - [#373](https://github.com/vercel-labs/just-bash/pull/373) [`2c1831c`](https://github.com/vercel-labs/just-bash/commit/2c1831cc832d4b09ee4e1823526afb6ccca77942) Thanks [@cramforce](https://github.com/cramforce)! - Prevent defense-in-depth violation reporting from recursively overflowing the call stack in host runtimes that wrap `Date.now()`, honor configured main-thread violation exclusions, include actionable exclusion guidance for configurable violations, and keep constructor-execution protections non-excludable.
40
+
41
+ ## 3.4.0
42
+
43
+ ### Minor Changes
44
+
45
+ - [#303](https://github.com/vercel-labs/just-bash/pull/303) [`c5a2a4a`](https://github.com/vercel-labs/just-bash/commit/c5a2a4a35c7490276befa716acae3fe880c1fe89) Thanks [@boramuyar](https://github.com/boramuyar)! - Provide the shadowed bundled command to custom command overrides through `CommandContext.origCommand`.
46
+
47
+ ## 3.3.0
48
+
49
+ ### Minor Changes
50
+
51
+ - [#291](https://github.com/vercel-labs/just-bash/pull/291) [`47f604a`](https://github.com/vercel-labs/just-bash/commit/47f604a7f1e12730318e4c88c7872a5a35383056) Thanks [@trieloff](https://github.com/trieloff)! - jq: add external-argument flags (`--arg`, `--argjson`, `--rawfile`, `--slurpfile`, `--args`, `--jsonargs`) and the `$ARGS` object (`$ARGS.named` / `$ARGS.positional`), matching real jq 1.7.1 behavior including exit codes, error messages, and prototype-sensitive key handling.
52
+
53
+ - [#336](https://github.com/vercel-labs/just-bash/pull/336) [`d97425d`](https://github.com/vercel-labs/just-bash/commit/d97425dff8f51cfd773d22bc009561a09235cd1b) Thanks [@trieloff](https://github.com/trieloff)! - Support user file descriptors (fd >= 3). `exec 3< file`, `N< file` / `N> file` / `N>> file` on any command, `read -u N`, `read <&N`, `>&N`, `N<&M`, and `N<&-` now go through a real descriptor table: a descriptor carries one shared read position, `exec` keeps it open until it is closed, and every other construct — including `done N< file` on a loop — gets it only for the duration of that command.
54
+
55
+ - [#331](https://github.com/vercel-labs/just-bash/pull/331) [`6680247`](https://github.com/vercel-labs/just-bash/commit/66802470837cfac3a58a09e00d37b2070387ba7b) Thanks [@trieloff](https://github.com/trieloff)! - Treat a `-` FILE operand in `grep` as standard input, matching GNU. `grep PATTERN -` now reads stdin instead of failing with "No such file or directory", stdin is labelled `(standard input)` in the multi-file prefix and in `-l`/`-L`/`-c` output, repeated `-` operands see the stream drained by the first one, and `-` is exempt from `-r` recursion and `--include`/`--exclude` filtering.
56
+
57
+ - [#325](https://github.com/vercel-labs/just-bash/pull/325) [`edc7f2f`](https://github.com/vercel-labs/just-bash/commit/edc7f2fac5337cebd19911c5756b76ed02e52090) Thanks [@trieloff](https://github.com/trieloff)! - Support process substitution `<(cmd)` and `>(cmd)`.
58
+
59
+ `<(cmd)` runs `cmd` and substitutes a readable `/dev/fd/N` path backed by an
60
+ in-memory file; `>(cmd)` substitutes a writable path whose contents are fed to
61
+ `cmd` once the outer command finishes. Descriptors are numbered from 63
62
+ downwards like bash and released when the command that opened them completes.
63
+ Process substitutions retain their surrounding word context in assignments,
64
+ conditionals, regular expressions, and heredoc delimiters. Previously any use
65
+ raised `Parse error: Expected redirection target`.
66
+
67
+ - [#327](https://github.com/vercel-labs/just-bash/pull/327) [`eaedb5b`](https://github.com/vercel-labs/just-bash/commit/eaedb5bc34cffd2077b88bb1ccc48ea7e0545a48) Thanks [@trieloff](https://github.com/trieloff)! - Add `grep -f FILE` / `--file=FILE` to read patterns from a file (one per line). Patterns from `-f` OR-combine with `-e` patterns and with each other, `-f -` reads patterns from stdin, empty pattern lines match every line, and an empty pattern file selects nothing (exit 1). Newline-separated `PATTERNS` operands are now split into individual patterns, and `-x` groups alternatives correctly (`^(?:a|b)$`).
68
+
69
+ ### Patch Changes
70
+
71
+ - [#358](https://github.com/vercel-labs/just-bash/pull/358) [`bd1df37`](https://github.com/vercel-labs/just-bash/commit/bd1df37f8ff836355f470e95dcaa004b769d1e61) Thanks [@privatenumber](https://github.com/privatenumber)! - Parse and serialize bare file descriptor variable redirections such as `{output}>output.log` and `{input}<<EOF`. Bare redirects create their target with a command-scoped descriptor, while named command forms keep the allocated descriptor available.
72
+
73
+ - [#347](https://github.com/vercel-labs/just-bash/pull/347) [`abb904b`](https://github.com/vercel-labs/just-bash/commit/abb904b1e126d14aa437b05f006df83117f06db3) Thanks [@privatenumber](https://github.com/privatenumber)! - Fix escaped reserved words being parsed as shell syntax. Unquoted escapes now retain their provenance through lexing and word parsing, including when the word is serialized back to Bash.
74
+
75
+ - [#332](https://github.com/vercel-labs/just-bash/pull/332) [`4f9bdec`](https://github.com/vercel-labs/just-bash/commit/4f9bdec02edb9eb72511546b759cb7e20bc2e27e) Thanks [@trieloff](https://github.com/trieloff)! - Fix `grep -L` exit status to match GNU grep. The status reports whether a line
76
+ was selected, not whether a filename was printed, so `grep -L` now exits 0 when
77
+ every file matched (printing nothing) and 1 when no file matched (printing every
78
+ name) — previously these were inverted.
79
+
80
+ - [#339](https://github.com/vercel-labs/just-bash/pull/339) [`31d247f`](https://github.com/vercel-labs/just-bash/commit/31d247fe3a62f081b4462064da195552ab0a421c) Thanks [@mutewinter](https://github.com/mutewinter)! - network: restore private-range-enforced requests from the bundled build
81
+
82
+ Every request made with `denyPrivateRanges` enabled failed with `Network access denied: DNS pinning unavailable for private IP enforcement`, so `curl` could not reach any host at all. The published ESM bundle was affected; source consumers and the CommonJS bundle were not.
83
+
84
+ The pinned connection owner reads `Agent` and `fetch` off a dynamic `import("undici")`. Node's resolution of the package exposes those as named exports, but the ESM build inlines undici's CommonJS module into a chunk whose namespace carries it under `default` alone, so `Agent` was `undefined` and the `TypeError` from constructing it was reported as a runtime incapable of pinning.
85
+
86
+ The namespace is now normalized before the transport is read off it, which also covers a consumer that bundles just-bash further.
87
+
88
+ - [#336](https://github.com/vercel-labs/just-bash/pull/336) [`d97425d`](https://github.com/vercel-labs/just-bash/commit/d97425dff8f51cfd773d22bc009561a09235cd1b) Thanks [@trieloff](https://github.com/trieloff)! - Stop command groups, function bodies and `eval` from rewinding stdin they never replaced, so `{ { read a; }; read b; }` gives `b` the second line instead of replaying the first.
89
+
90
+ - [#348](https://github.com/vercel-labs/just-bash/pull/348) [`1a7940d`](https://github.com/vercel-labs/just-bash/commit/1a7940ddf91dec8f69125474a40cef1adebabee9) Thanks [@privatenumber](https://github.com/privatenumber)! - Reject unsupported command-leading reserved words in every parser context instead of discarding them or executing them as simple commands. Unknown command AST nodes now fail explicitly instead of returning a successful result.
91
+
92
+ - [#345](https://github.com/vercel-labs/just-bash/pull/345) [`2208a34`](https://github.com/vercel-labs/just-bash/commit/2208a34e27d33a2fce712fbd024875ec60747553) Thanks [@privatenumber](https://github.com/privatenumber)! - Restore command groups and subshells after the process-substitution and stdin-ownership changes were combined without forwarding ownership through inner command dispatch.
93
+
94
+ - [#336](https://github.com/vercel-labs/just-bash/pull/336) [`d97425d`](https://github.com/vercel-labs/just-bash/commit/d97425dff8f51cfd773d22bc009561a09235cd1b) Thanks [@trieloff](https://github.com/trieloff)! - Apply output redirections attached to `while` and `until` loops. `while true; do echo x; break; done >/dev/null` no longer leaks its output to the caller, and `> file`, `>>`, `2>`, `2>&1`, `&>` and `>|` now behave on loops the way they already did on `for` and `case`. `until` loops also gained the input-redirection handling `while` loops already had, so `until ! read l; do ...; done < file` reads from the file. A loop now only restores stdin it owns, so reading inside a loop no longer rewinds an enclosing group's read position: `printf 'a\nb\n' | { while read x; do break; done; read y; }` sees `y=b`.
95
+
96
+ - [#328](https://github.com/vercel-labs/just-bash/pull/328) [`65dafd5`](https://github.com/vercel-labs/just-bash/commit/65dafd55afbfa7e62642ce485787f7d65fad4961) Thanks [@trieloff](https://github.com/trieloff)! - Stop pipelines from draining the enclosing shell's stdin, so `while read …; do … | …; done < file` runs once per line again.
97
+
98
+ - [#349](https://github.com/vercel-labs/just-bash/pull/349) [`be55fec`](https://github.com/vercel-labs/just-bash/commit/be55fec4e23b3f5a42cf8eaeb6939b379f741ae1) Thanks [@privatenumber](https://github.com/privatenumber)! - Process redirections through policy-driven transactions that preserve Bash ordering, descriptor lifetimes, persistent `exec` routes, compound-command stdin, control-flow output routing, and shared read-write descriptor positions without duplicate expansion or opening.
99
+
100
+ - [#368](https://github.com/vercel-labs/just-bash/pull/368) [`3ee215c`](https://github.com/vercel-labs/just-bash/commit/3ee215c2ad56c96ce0d88e2813050df9f15afa38) Thanks [@cramforce](https://github.com/cramforce)! - FS sym-link hardening
101
+
102
+ - [#338](https://github.com/vercel-labs/just-bash/pull/338) [`19a02c2`](https://github.com/vercel-labs/just-bash/commit/19a02c297d110fde8a8a3376d6956c2c549d128e) Thanks [@mutewinter](https://github.com/mutewinter)! - sqlite3: report failed statements on stderr and exit non-zero without `-bail`
103
+
104
+ A statement that failed was written to **stdout** as `Error: ...` and the command still exited `0` unless `-bail` was passed. Real `sqlite3` writes the error to stderr and exits `1` in either mode; `-bail` only decides whether the remaining statements still run.
105
+
106
+ Two consequences for callers: `sqlite3 db "SELECT ..." > out.csv` silently wrote the error text into the data file, and `sqlite3 db "..." && next-step` ran `next-step` after the query had failed, so a shell script could not detect a bad query without opting into `-bail` and losing the ability to see later statements.
107
+
108
+ Errors now accumulate on stderr in statement order and the exit status is `1` whenever any statement failed. Successful runs are unchanged, `-bail` still stops at the first failure, and the partial stdout produced before a failure is still emitted. Writeback of a partially-successful script is also unchanged.
109
+
110
+ - [#360](https://github.com/vercel-labs/just-bash/pull/360) [`1fbde34`](https://github.com/vercel-labs/just-bash/commit/1fbde341d74ff7f933d9cead9a390a6ab65b5df3) Thanks [@privatenumber](https://github.com/privatenumber)! - Preserve whether a here-document ended at its delimiter or at end-of-input. Unterminated final body lines now receive Bash's trailing newline, backslash-newline continuations are removed during expansion, and serialization rejects unterminated documents rather than manufacturing a closing delimiter.
111
+
112
+ ## 3.2.0
113
+
114
+ ### Minor Changes
115
+
116
+ - [#304](https://github.com/vercel-labs/just-bash/pull/304) [`3d39a71`](https://github.com/vercel-labs/just-bash/commit/3d39a714b3751cedc173dffae27933dfe7b8b3b5) Thanks [@subsetpark](https://github.com/subsetpark)! - Add curl `-G`/`--get` query-string data handling and preserve command-line order when repeated `-d`, `--data-raw`, `--data-binary`, and `--data-urlencode` options are mixed, including `@file` forms. Data requests now also set curl's standard `application/x-www-form-urlencoded` content type unless the caller supplies one.
117
+
118
+ - [#307](https://github.com/vercel-labs/just-bash/pull/307) [`7c4caed`](https://github.com/vercel-labs/just-bash/commit/7c4caedf02599628f19b243f960d480760f5e476) Thanks [@cramforce](https://github.com/cramforce)! - Harden untrusted execution with shared aggregate budgets, liberal normal and
119
+ opt-in hardened limit profiles, request-bound network validation, bounded
120
+ archive and worker processing, transactional filesystem and shell state, and
121
+ expanded adversarial regression checks.
122
+
123
+ Established command declarations and host-extension defaults remain source
124
+ compatible. Dispatched callbacks receive a `ResolvedCommandContext` with
125
+ required limits; applications can use `createCommandContext({ fs })` for direct
126
+ invocation, opt into restricted custom-command execution with `trusted: false`,
127
+ and select tighter resource policy with the `hardened` profile. All
128
+ host-registration paths keep their established trusted default. The supported
129
+ Node.js floor is now declared as `>=20.18.1`.
130
+
131
+ ### Patch Changes
132
+
133
+ - [#315](https://github.com/vercel-labs/just-bash/pull/315) [`6df692f`](https://github.com/vercel-labs/just-bash/commit/6df692f236ca108c888552a67557998156ac845b) Thanks [@matchai](https://github.com/matchai)! - Treat `--` as the end of options in `grep`.
134
+
135
+ ## 3.1.0
136
+
137
+ ### Minor Changes
138
+
139
+ - [#284](https://github.com/vercel-labs/just-bash/pull/284) [`af2e0f4`](https://github.com/vercel-labs/just-bash/commit/af2e0f4cdeb5417ea59e25140038c239dd8fd92d) Thanks [@arimxyer](https://github.com/arimxyer)! - sandbox: forward capability flags from `SandboxOptions` into the underlying `Bash`
140
+
141
+ `Sandbox.create(opts)` previously constructed its internal `Bash` with only a subset
142
+ of `BashOptions`, silently dropping the optional capability flags (`python`,
143
+ `javascript`, `commands`, `customCommands`, `fetch`). A host that drives just-bash
144
+ through the `Sandbox` API (rather than `new Bash(...)`) therefore could not enable
145
+ python3, js-exec, a restricted command set, custom commands, or a custom fetch — even
146
+ though the runtimes ship in the package.
147
+
148
+ `SandboxOptions` now exposes those fields and `Sandbox.create` forwards them into the
149
+ `Bash` it builds. Behavior is unchanged when a caller omits them (each falls back to
150
+ its existing `BashOptions` default — Python/js-exec stay off, the full command set
151
+ stays available). Fixes the root cause behind vercel/eve#431.
152
+
153
+ ### Patch Changes
154
+
155
+ - [#268](https://github.com/vercel-labs/just-bash/pull/268) [`7a5a0b9`](https://github.com/vercel-labs/just-bash/commit/7a5a0b9ae3bf0524722653cbf4b45e6bc176cf22) Thanks [@trieloff](https://github.com/trieloff)! - jq: allow nested double-quoted strings inside `"\(...)"` string interpolation
156
+
157
+ jq string interpolation of the form `"\(...)"` that contained a nested double-quoted string — for example `"\(sub("T.*";""))"` or `"\(ltrimstr("ab"))"` — previously failed with a parse error. The tokenizer terminated the outer string at the first `"` it saw inside the interpolation expression, so the rest of the expression became orphaned tokens.
158
+
159
+ The lexer now tracks `\(...)` depth while consuming a string literal and treats nested `"..."` pairs as opaque content while inside an interpolation, restoring them verbatim into the captured interpolation source. `parseStringInterpolation` similarly skips over nested strings when balancing parentheses, so the interpolation expression is captured as a whole and handed to the expression parser intact.
160
+
161
+ ## 3.0.3
162
+
163
+ ### Patch Changes
164
+
165
+ - [#277](https://github.com/vercel-labs/just-bash/pull/277) [`aec5643`](https://github.com/vercel-labs/just-bash/commit/aec56431d7d9b6fcb141bbfe25d26f4931f54f80) Thanks [@mutewinter](https://github.com/mutewinter)! - interpreter: avoid lazy import in variable assignment path that trips defense-in-depth (fixes [#273](https://github.com/vercel-labs/just-bash/issues/273))
166
+
167
+ Any non-`export` variable assignment (bare `SECRET=s`, prefixed `SECRET=s cmd`,
168
+ or before a custom command) failed with a defense-in-depth security violation
169
+ (`dynamic import of Node.js builtin 'node:module' is blocked during script
170
+ execution`), while plain commands and `export`-ed assignments passed.
171
+
172
+ `processScalarAssignment()` resolved `isArray` via `await import("./expansion.js")`
173
+ in two spots. In the bundled `dist`, that dynamic `import()` marks `expansion.js`
174
+ as a lazily-linked chunk whose `createRequire` banner imports `node:module`; the
175
+ defense layer's ESM `resolve` hook blocks that builtin import when the sandbox is
176
+ active and untrusted, so it blocked just-bash's own chunk load. The file already
177
+ statically imports from `./expansion.js`, so `isArray` is now pulled from that
178
+ static import and the two lazy imports are removed — no lazy `node:module`-bearing
179
+ chunk is linked at runtime. No public API change.
180
+
181
+ - [#276](https://github.com/vercel-labs/just-bash/pull/276) [`1ec5eec`](https://github.com/vercel-labs/just-bash/commit/1ec5eec0aefd099d23ac9f056df1e6612c81d49b) Thanks [@mutewinter](https://github.com/mutewinter)! - interpreter: preserve leading whitespace in multi-line quoted strings (fixes [#259](https://github.com/vercel-labs/just-bash/issues/259))
182
+
183
+ `exec()` runs each script through `normalizeScript()`, which `trimStart()`s
184
+ leading indentation from lines so indented template-literal scripts parse. It
185
+ was applied line-by-line and stripped the leading whitespace inside multi-line
186
+ single- and double-quoted strings too. The visible symptom was `python3 -c
187
+ '...'` (and `node -e`, `awk`, etc.) with an indented body failing with
188
+ `IndentationError`, while the same code via heredoc or pipe worked.
189
+
190
+ `normalizeScript()` is now quote-aware (mirroring the earlier heredoc-aware
191
+ fix): it only strips indentation from lines that begin outside any quote, and
192
+ preserves lines that begin inside an unterminated single- or double-quoted
193
+ string verbatim. This also un-skips four sed spec tests whose indented stdin
194
+ was previously being corrupted.
195
+
196
+ - [#286](https://github.com/vercel-labs/just-bash/pull/286) [`cb2b583`](https://github.com/vercel-labs/just-bash/commit/cb2b583b3f46e6bb4e6982c4bfe19903ec811a87) Thanks [@privatenumber](https://github.com/privatenumber)! - interpreter: deliver redirected output to each fd's final target (fixes `cmd > file 2>&1` leaking stderr to stdout)
197
+
198
+ `applyRedirections()` processed a command's redirection list sequentially over
199
+ the result's stdout/stderr strings, moving content at each step. The
200
+ duplication operators (`2>&1`, `1>&2`) merged into the live stream regardless
201
+ of where the source fd pointed, so the canonical `cmd > file 2>&1` wrote
202
+ stdout to the file but leaked stderr onto the caller's stdout — including
203
+ "command not found" errors and custom-command stderr. Any wrapper protocol
204
+ that parses the enclosing script's stdout (e.g. a runner emitting a JSON
205
+ payload after `eval "$CMD" > "$OUT" 2>&1`) saw the leaked stderr corrupt its
206
+ stream. Ordering variants were wrong in other ways: `cmd 2>&1 > file` put
207
+ stderr in the file instead of on stdout, and `cmd > a > b` wrote content to
208
+ `a` instead of `b`.
209
+
210
+ The pass now mirrors how bash sets up fds before running the command: each
211
+ output redirection only opens/truncates its target and re-points the fd's
212
+ sink (file, /dev/null, or a snapshot of the caller-visible stream), and
213
+ duplication operators copy the source fd's current sink. Stream content is
214
+ delivered once, after the whole list is processed, to each fd's final sink.
215
+ This makes `cmd > file 2>&1` send stderr to the file, `cmd 2>&1 > file` keep
216
+ stderr on the caller's stdout, `cmd > all 2>&1 2> err` let the later `2> err`
217
+ reclaim stderr, and `cmd > a > b` truncate `a` while writing content to `b`.
218
+ The `/dev/null`-as-regular-VFS-file behavior for stdout redirects is
219
+ preserved.
220
+
221
+ ## 3.0.2
222
+
223
+ ### Patch Changes
224
+
225
+ - [#272](https://github.com/vercel-labs/just-bash/pull/272) [`150a915`](https://github.com/vercel-labs/just-bash/commit/150a915a1d45a2cc7f2b6aec3268f27116c34916) Thanks [@trieloff](https://github.com/trieloff)! - interpreter: fix UTF-8 mojibake when a script interleaves text-output and byte-output statements
226
+
227
+ A single `exec()` can interleave text-shaped statements (sed, awk, echo — `ö`
228
+ as `U+00F6`) with byte-shaped ones (grep | head, cat — `ö` as bytes
229
+ `0xC3 0xB6`). `executeScript` / `executeStatement` concatenated each result's
230
+ raw stdout, so the lone high byte from the text half made the combined stream
231
+ invalid UTF-8, the output-boundary decoder bailed, and the byte half came back
232
+ as Latin-1 mojibake (`Köpenicker` for `Köpenicker`). The same path backs
233
+ command substitution, so `echo "你好: $(cat /file)"` was affected too.
234
+
235
+ The fix decodes each statement/pipeline result to text via its explicit
236
+ `stdoutKind` (`decodedTextFromResult`) before concatenating — no guessing from
237
+ string contents, so text whose code units merely look like UTF-8 (`ö`) is
238
+ preserved. `tac` (stdin path) and `curl` (response body) now declare
239
+ `stdoutKind: "bytes"` on the results that forward raw bytes, so the decode is
240
+ driven per output rather than by inspecting characters.
241
+
242
+ - [#256](https://github.com/vercel-labs/just-bash/pull/256) [`75d8dfd`](https://github.com/vercel-labs/just-bash/commit/75d8dfd3a322786250e3b0f81b1500c87610acb7) Thanks [@Hazzng](https://github.com/Hazzng)! - js-exec: fix Buffer shim correctness — ascii encode now uses & 0xff (not & 0x7f), consolidate latin1/ascii into shared \_rawEncode, fix Buffer.from(ArrayBuffer, offset, length), throw on invalid byteLength input, clamp negative toString start, throw RangeError for out-of-range write offset
243
+
244
+ - [#239](https://github.com/vercel-labs/just-bash/pull/239) [`1369b77`](https://github.com/vercel-labs/just-bash/commit/1369b772fe887694c09ce834d1b0b21aa6420b59) Thanks [@trieloff](https://github.com/trieloff)! - curl: interpret `@file` for `-d`/`--data`, `--data-binary`, and `--data-urlencode`
245
+
246
+ Real curl reads file contents when these flags are passed `@filename`:
247
+
248
+ - `-d @file` / `--data @file` — read file contents, strip CR/LF.
249
+ - `--data-binary @file` — read file contents verbatim (newlines preserved).
250
+ - `--data-urlencode @file` — read file, URL-encode the contents.
251
+ - `--data-urlencode name@file` — prefix the URL-encoded contents with `name=`.
252
+
253
+ just-bash's curl previously passed `@filename` through verbatim as the HTTP body. Posting JSON or any non-trivial payload via `curl --data-binary @payload.json https://…` sent the literal string `@payload.json` instead of the file. The new behavior matches upstream curl; `--data-raw` keeps the documented "no `@` interpretation" semantics.
254
+
255
+ - [#262](https://github.com/vercel-labs/just-bash/pull/262) [`4ece258`](https://github.com/vercel-labs/just-bash/commit/4ece2580d8cb707e6c6b7fa22897ea3fdd21739a) Thanks [@chernetsov](https://github.com/chernetsov)! - parser: don't treat quotes inside a heredoc body as shell quotes when finding the end of a command substitution
256
+
257
+ A command substitution whose body contained a heredoc with an unbalanced quote in its body — most commonly an apostrophe in literal prose, e.g. `June's` — failed to parse with `bash: syntax error: ... unexpected EOF while looking for matching ')'`:
258
+
259
+ ```bash
260
+ OUT=$(cat <<'SCRIPT'
261
+ June's moon
262
+ SCRIPT
263
+ )
264
+ ```
265
+
266
+ Both the lexer's `$(...)` word scanner and the substitution boundary scanner walked into the heredoc body and applied shell quote tracking to it. The `'` in `June's` opened a single-quoted string that never closed, so the closing `)` was swallowed and the scan ran to EOF. In bash a heredoc body is literal text and must be skipped wholesale when locating the substitution boundary.
267
+
268
+ Both scanners are now heredoc-aware: when scanning a `$(...)` they recognize `<<` / `<<-` operators (but not the `<<<` here-string), capture the possibly-quoted delimiter, and skip the heredoc body lines literally — without quote or paren tracking — up to the terminator. Multiple heredocs on one line and tab-stripping (`<<-`) are handled. This fixes the common pattern of capturing the output of a connector/CLI invocation that is fed a heredoc script containing apostrophes, backticks, or parentheses.
269
+
270
+ The heredoc scan also tracks arithmetic `((...))` nesting so a `<<` left-shift inside `$((...))` (or a nested arithmetic expansion) is not mistaken for a heredoc opener — previously a multi-line arithmetic expansion containing a shift, e.g. `$((\n1 << 2\n))`, had its closing `))` swallowed by spurious body-skipping.
271
+
272
+ - [#248](https://github.com/vercel-labs/just-bash/pull/248) [`d64009a`](https://github.com/vercel-labs/just-bash/commit/d64009aef6bc1556e7c84b22ed455863275ea953) Thanks [@Hazzng](https://github.com/Hazzng)! - perf(grep): up to 14.5× speedup via preFilter extensions and matcher reuse.
273
+
274
+ Anchored alternation patterns like `^def \|^async def` now extract literal needles (stripping outer `^`/`$`), enabling the `String.indexOf` fast-path. Files with no matching needle are rejected before `split("\n")`, skipping RE2 entirely. `acquireMatcher()` extended to `match()`, `replace()`, `search()`, and `matchAll()` to reduce GC pressure across awk/sed hot-paths.
275
+
276
+ - [#261](https://github.com/vercel-labs/just-bash/pull/261) [`c9904de`](https://github.com/vercel-labs/just-bash/commit/c9904dea24ad2aa847749ee6289239c2a2c651fc) Thanks [@chernetsov](https://github.com/chernetsov)! - set: support a bundled `-o`/`+o` long option inside a short-flag cluster (e.g. `set -euo pipefail`)
277
+
278
+ The `set` builtin previously rejected `set -euo pipefail` with `bash: set: -o: invalid option`, because it parsed each character after the `-` as an independent short flag and has no `o` short flag. `-o` was only honored as its own token (`set -eu -o pipefail`).
279
+
280
+ This is the canonical "bash strict mode" idiom and is extremely common in generated scripts, so the whole script would abort on its first line.
281
+
282
+ `set` now matches bash: an `o` inside a cluster consumes the _next word_ as its long-option name, and the remaining characters keep being parsed as short flags. So `set -euo pipefail` is equivalent to `set -e -u -o pipefail`, `set -oe pipefail` enables both `pipefail` and `errexit`, trailing words become positional parameters, and `+`-clusters (`set +euo pipefail`) disable the options. An invalid bundled name (`set -euo bogus`) still reports `invalid option name`, and an `o` with no following argument falls back to the standalone `-o`/`+o` listing.
283
+
284
+ ## 3.0.1
285
+
286
+ ### Patch Changes
287
+
288
+ - [#238](https://github.com/vercel-labs/just-bash/pull/238) [`01a4721`](https://github.com/vercel-labs/just-bash/commit/01a4721324350adea4b035b311f0b60ccdbb65ff) Thanks [@cramforce](https://github.com/cramforce)! - Fix `Dynamic require of "tty" is not supported` crash when invoking commands that transitively load `debug` / `supports-color` (notably `file`) under ESM Node consumers and via the `just-bash` CLI binary.
289
+
290
+ The esbuild dynamic-require shim emitted into the ESM Node bundles had no `require` to delegate to at chunk-init under ESM, so any runtime `require("tty")` / `require("os")` from `file-type` → `debug` chain threw. Build banners now provide `createRequire(import.meta.url)` for `build:lib`, `build:cli`, and `build:shell`. CJS and browser bundles are unchanged.
291
+
292
+ Fixes [#211](https://github.com/vercel-labs/just-bash/issues/211).
293
+
294
+ ## 3.0.0
295
+
296
+ ### Major Changes
297
+
298
+ - [#233](https://github.com/vercel-labs/just-bash/pull/233) [`7cca738`](https://github.com/vercel-labs/just-bash/commit/7cca73831987e3331160f426b7a66d7217b8cf79) Thanks [@cramforce](https://github.com/cramforce)! - Breaking change for stdin byte/utf8-handling. Will break some custom commands that handle stdin
299
+
300
+ ### Minor Changes
301
+
302
+ - [#209](https://github.com/vercel-labs/just-bash/pull/209) [`b3bd85e`](https://github.com/vercel-labs/just-bash/commit/b3bd85ed816445e6d148290163a1900f49ebea82) Thanks [@cramforce](https://github.com/cramforce)! - Introducing plumbing for integrating executor and adding a peer package for the implememtation
303
+
304
+ - [#233](https://github.com/vercel-labs/just-bash/pull/233) [`7cca738`](https://github.com/vercel-labs/just-bash/commit/7cca73831987e3331160f426b7a66d7217b8cf79) Thanks [@cramforce](https://github.com/cramforce)! - TS-enforced correct handling of utf8 on stdin. Impacts many commands
305
+
306
+ ## 2.14.5
307
+
308
+ ### Patch Changes
309
+
310
+ - [#214](https://github.com/vercel-labs/just-bash/pull/214) [`da58f4f`](https://github.com/vercel-labs/just-bash/commit/da58f4f523c5e9c1c444106a0f2a7777a59fb618) Thanks [@subsetpark](https://github.com/subsetpark)! - jq: accept control characters inside JSON strings
311
+
312
+ - [#221](https://github.com/vercel-labs/just-bash/pull/221) [`a835686`](https://github.com/vercel-labs/just-bash/commit/a835686c97f5cac2e5b94bd551d996079a33dfc2) Thanks [@cramforce](https://github.com/cramforce)! - upgrade deps
313
+
314
+ - [#218](https://github.com/vercel-labs/just-bash/pull/218) [`13d78b2`](https://github.com/vercel-labs/just-bash/commit/13d78b2876d7ac7b6bc3a6eacfa3937bbb79665f) Thanks [@Hazzng](https://github.com/Hazzng)! - grep: 5-123x faster pattern matching via RE2 matcher reuse and literal pre-filter
315
+
316
+ ## 2.14.4
317
+
318
+ ### Patch Changes
319
+
320
+ - [#206](https://github.com/vercel-labs/just-bash/pull/206) [`6ccc35f`](https://github.com/vercel-labs/just-bash/commit/6ccc35f5a9b5c6f395b145ed2ec7ee71c4862057) Thanks [@subsetpark](https://github.com/subsetpark)! - Fix awk lexer to honor POSIX statement continuation across newlines after `,`,
321
+ `{`, `&&`, `||`, `?`, `:`, `do`, `else`, `if`, and `while`. Previously, a
322
+ multi-line idiom like `printf "%s=%d\n", \n $1, $2` (comma at end-of-line
323
+ followed by indented args on the next line) failed with `Unexpected token:
324
+ NEWLINE` because the lexer emitted a NEWLINE token unconditionally. The
325
+ lexer now suppresses the NEWLINE when it immediately follows one of the
326
+ continuation-allowing tokens, matching POSIX awk.
327
+
328
+ - [#212](https://github.com/vercel-labs/just-bash/pull/212) [`733c847`](https://github.com/vercel-labs/just-bash/commit/733c84796e3abbd05a25cf67805bf4b030d0b02d) Thanks [@cramforce](https://github.com/cramforce)! - Bug fixes across network, sqlite3, xan, rg, terminal rendering, and CI
329
+
330
+ ## 2.14.3
331
+
332
+ ### Patch Changes
333
+
334
+ - [#199](https://github.com/vercel-labs/just-bash/pull/199) [`3d11f05`](https://github.com/vercel-labs/just-bash/commit/3d11f05959faa205267a5173b25665c6732fee8b) Thanks [@cramforce](https://github.com/cramforce)! - Internal: convert repository to a pnpm workspace under `packages/just-bash` and adopt Changesets for versioning. No public API changes; `import` paths and the `bin` entries are unchanged.