Bashkit Compatibility Scorecard#
Feature parity tracking for bash and common tools
See also:
- API Documentation - Full API reference
- Custom Builtins Guide - Extending Bashkit with custom commands
- Threat Model - Security considerations
Legend: ✅ Implemented | ⚠️ Partial | ❌ Not implemented | N/A Security exclusion
POSIX Shell Compliance#
Bashkit provides substantial compliance with IEEE Std 1003.1-2024 (POSIX.1-2024) Shell Command Language. See knowledge/operations/limitations.md for detailed compliance status.
| POSIX Category | Status |
|---|---|
| Reserved Words (16) | Full compliance |
| Special Parameters (8) | Full compliance |
| Special Built-ins (15) | 14/15 implemented |
| Word Expansions | Substantial compliance |
| Redirections | Full compliance |
| Compound Commands | Full compliance |
Security Exclusions: exec is intentionally not implemented
for sandbox security reasons. See the compliance spec for details.
Quick Status#
| Group | Count |
|---|---|
| Always-on builtins | 142 |
Feature-gated builtins (jq, git, ssh/scp/sftp, python/python3, sqlite/sqlite3, ts/typescript/node/deno/bun) |
14 |
| Total | 156 |
Builtins Reference#
Implemented#
| Builtin | Flags/Features | Notes |
|---|---|---|
echo |
-n, -e, -E |
Basic escape sequences |
printf |
%s, %d, %u, %x, %o, %f, width/precision |
GNU-style integer precision; repeats format for multiple args |
cat |
(none) | Concatenate files/stdin |
true |
- | Exit 0 |
false |
- | Exit 1 |
exit |
[N] |
Exit with code |
cd |
[dir] |
Change directory |
pwd |
- | Print working directory |
test |
-f, -d, -e, -z, -n, -eq, -ne, -lt, -gt, -le, -ge |
Conditionals |
[ |
(same as test) | Alias for test |
export |
VAR=value |
Export variables |
read |
VAR, -r, -a, -d, -n, -p, -s, -t |
Read a record; without -r backslashes escape and \<newline> continues; status 1 at end of input |
set |
-e, +e, positional |
Set options and positional params |
unset |
VAR |
Unset variable |
shift |
[N] |
Shift positional params |
local |
VAR=value |
Local variables |
source |
file [args] |
Source script; loads functions/variables, PATH search, positional params |
. |
file [args] |
Alias for source |
/path/to/script.sh |
[args] |
Execute script by absolute/relative path (call frame; a #! naming a registered builtin such as python3 or awk -f runs that builtin, other shebangs are stripped) |
$PATH search |
cmd [args] |
Search $PATH dirs for executable scripts (after builtins) |
break |
[N] |
Break from loop |
continue |
[N] |
Continue loop |
return |
[N] |
Return from function |
: |
- | POSIX null utility (no-op) |
eval |
command... |
POSIX construct and execute command |
readonly |
VAR[=value], -p |
POSIX mark variable read-only |
times |
- | POSIX display process times |
grep |
-G/-E/-F/-P, -e, -f, -i/-y, --no-ignore-case, -v, -w, -x, -c, -l, -L, -o, -q, -s, -m, -n, -b, -H/-h, --label, -T, -Z, -z, -a, -I, --binary-files, -A/-B/-C/-NUM, --group-separator, --no-group-separator, -r/-R, -d, -D, --include/--exclude/--exclude-from/--exclude-dir; long-option prefixes |
GNU grep 3.11 output; BRE/ERE leftmost-longest, back-references; recursive ancestor loops skipped with a warning, files scanned under shared resource budgets |
rg |
-i/-S/-s, -n/-N, --column, -b/--byte-offset, --vimgrep, basic --json, --stats, --null, -c, --count-matches, --include-zero, -l, --files-with-matches, --files-without-match, --files, -F, -w, -x, -a/--text, --binary, -m, -M/--max-columns, --max-columns-preview, --max-depth, -A, -B, -C, separator flags, --heading/--no-heading, --sort/--sortr, --path-separator, -g/--glob, --ignore-file, .ignore/.gitignore, --no-ignore*, --require-git/--no-require-git, -u/--unrestricted, --messages/--no-messages, -t/--type, -T/--type-not, --type-add, --type-clear, --type-list, --hidden/--no-hidden, -o, -q, -e, -f, -E/--encoding (auto, none, UTF-8, UTF-16LE/BE), -r, --passthru, --trim, -H/-I, --no-config, --line-buffered, --block-buffered, --mmap/--no-mmap, -P/--pcre2, --no-pcre2, --engine, --auto-hybrid-regex, --no-auto-hybrid-regex, --help, --version |
Recursive ripgrep-style search |
sed |
s///[gpiImMN w], y, d, D, p, P, n, N, q[N], Q[N], =, l[N], z, F, a, i, c, r, R, w, W, h/H/g/G/x, b/t/T/:label, {}, #/#n; addresses N, $, /re/[IM], \cREc, first~step, a,b, a,+N, a,~N, 0,/re/, !; options -n -e -f -i[SUF] -E/-r -s -z -l N -u -- and long forms |
Stream editing; one stream across operands unless -s/-i |
awk (also gawk, mawk, nawk) |
'{print}', -F, -v, loops, arrays, increment, ternary |
Text processing |
jq |
.field, .[n], pipes, file args, -r, -c, -n, -s, -S, -e, -j, -f/--from-file, --tab, --arg, --argjson, -V, combined flags |
JSON processing |
sleep |
N, N.N |
Pause execution (max 60s) |
head |
-n N, -N |
First N lines (default 10) |
tail |
-n N, -N |
Last N lines (default 10) |
basename |
NAME [SUFFIX] |
Strip directory from path |
dirname |
NAME |
Strip last path component |
mkdir |
-p |
Create directories |
rm |
-rf |
Remove files/directories |
cp |
-r |
Copy files |
mv |
- | Move/rename files |
touch |
-c, -d/--date, -r/--reference, -t, -a/-m |
Create files, set modification time |
chmod |
MODE |
Change permissions (octal only) |
wc |
-l, -w, -c |
Count lines/words/bytes |
sort |
-r, -n, -u |
Sort lines |
uniq |
-c, -d, -u |
Filter duplicate lines |
cut |
-d DELIM, -f FIELDS |
Extract fields |
tr |
-d, character ranges |
Translate/delete chars |
date |
+FORMAT, -u, -R, -I, -r, -d/--date (relative, weekday, compound, epoch, ISO date-times with optional seconds and zone) |
Display/format date with sandboxed IANA timezone support |
wait |
[-n] [-p VAR] [-f] [ID...] (PID or %jobspec) |
Wait for background jobs |
jobs |
-l, -p |
List running background jobs |
ps |
-f, aux, -o, -p |
Virtual process list (shell + jobs) |
pgrep/pkill |
-f, -l, -a, -c, -x, -SIGNAL |
Match jobs by command |
disown, fg, bg |
[JOBSPEC] |
fg waits; bg is a no-op (jobs already run) |
uuidgen |
-r |
Random (v4) UUID from the OS CSPRNG |
openssl |
rand [-hex|-base64] [-out FILE] NUM |
Only rand; other subcommands fail with Invalid command |
make |
-f, -C, -n, -k, -q, -s, -i, -B, -e, -j (sequential), VAR=value |
GNU make subset; recipes run in the sandbox shell; no built-in implicit rules, $(eval) or vpath (L-MAKE-001..003) |
curl |
-s, -o, -X, -d/--data, --data-raw, --data-binary, --data-urlencode, -G/--get, -H, -I, -f, -L, -w, --compressed, -u, -A, -e, -v, -m |
HTTP client (requires http_client feature) |
wget |
-q, -O, --spider, --header, -U, --post-data, -t |
Download files (requires http_client feature) |
time |
[-p] [-f FORMAT] [-o FILE] [-a] [-v] [--] PIPELINE |
Reserved-word timing; elapsed/status/Bashkit counters are truthful, host CPU/RSS fields say unavailable |
timeout |
DURATION COMMAND |
Run with time limit (stub) |
ls |
-l, -a, -h, -1, -R, -t, -F, -C, -d, -b, -N, -Q, --quoting-style (not locale/clocale) |
List directory contents |
find |
GNU expression grammar (( ), !, -a, -o, ,), -H/-L/-P, -name/-iname, -path/-ipath, -regex/-iregex/-regextype, -type/-xtype, -size, -empty, -mtime/-mmin/-newer/-newerXY, -perm, -user/-group/-uid/-gid, -maxdepth/-mindepth/-depth, -print/-print0/-printf, -exec/-execdir (; and +), -delete, -prune, -quit |
Search for files (gaps: L-FIND-001) |
rmdir |
-p |
Remove empty directories |
xargs |
-I, -n, -d |
Build commands from stdin |
tee |
-a |
Write to files and stdout |
watch |
INTERVAL COMMAND |
Execute periodically (virtual mode) |
file |
(none) | Detect file type via magic bytes |
less |
(none) | View file (behaves like cat in virtual mode) |
stat |
-c FORMAT |
Display file metadata |
tar |
-c, -x, -t, -v, -f, -z/--gzip, -j/--bzip2, -C, -O, -P/--absolute-names, -T/--files-from, --strip-components, --exclude, -- |
Archive operations; auto-detects gzip/bzip2 while reading |
gzip |
-d, -k, -f |
Compress files |
gunzip |
-k, -f |
Decompress files |
bzip2 |
-c, -d, -z, -k, -f |
Compress or decompress bzip2 streams/files |
bunzip2 |
-c, -k, -f |
Decompress bzip2 streams/files |
bzcat |
Decompress bzip2 streams/files to stdout | |
env |
-i, -u, -C, -0, [VAR=val], CMD [ARGS] |
Print environment or run a command in a modified one |
printenv |
[VAR] |
Print environment variables |
history |
(none) | Command history (limited in virtual mode) |
hostname |
(none) | Display virtual hostname |
uname |
-a, -s, -n, -r, -v, -m, -o |
System info |
whoami |
(none) | Display virtual username |
id |
-u, -g, -n |
User/group IDs |
nl |
-b, -n, -s, -i, -v, -w |
Number lines of files |
paste |
-d, -s |
Merge lines of files |
column |
-t, -s, -o |
Columnate lists |
comm |
-1, -2, -3 |
Compare two sorted files |
diff |
-u, -q/--brief |
Compare files line by line |
strings |
-n, -t, -a |
Find printable strings in binary data |
od |
-A, -t, -N, -j |
Octal/hex dump |
xxd |
-l, -s, -c, -g, -p |
Hex dump |
hexdump |
-C, -n, -s |
Display file in hex+ASCII |
time reports#
time wraps a shell pipeline, so groups, functions, redirects, nested shells,
and pipeline status behave as shell syntax rather than utility arguments. -p
uses the POSIX layout. -f supports elapsed seconds (%e), elapsed
hours/minutes/seconds (%E), exit status (%x), literal percent (%%), and
Bashkit counters (%{commands}, %{loops}, %{work_units}). GNU host-process
fields such as %U, %S, %P, and %M return unavailable; Bashkit never
attributes the embedding process’s CPU or memory to a wrapped command.
-v reports the same available data with labels. -o FILE atomically replaces
the report file in the VFS; -a -o FILE appends. Wrapped stdout and stderr are
unchanged. Hardened profiles expose elapsed time in 100 ms lower-bound buckets.
date timezone contract#
date defaults to UTC when the shell environment has no TZ; it never reads
the host process timezone. A valid IANA identifier or alias in TZ (for example
America/Chicago, Etc/GMT+6, or UTC) controls display and the interpretation
of timezone-naive -d values. Explicit input offsets and Z identify an instant
independently of TZ; the output is then rendered in the selected zone. -u
always renders UTC while naive input still uses the selected sandbox zone.
IANA transition rules apply at DST boundaries. Nonexistent local wall times
fail; repeated wall times choose the earlier instant deterministically. Empty,
invalid, POSIX-rule, and path-style TZ values fail closed to UTC. Formats use
Chrono’s validated strftime implementation, plus GNU %N, %3N, %6N, and
%9N fractional-second forms.
Recently Added#
| Builtin | Flags / Arguments | Notes |
|---|---|---|
ln |
-s, -f |
Create links |
chown |
OWNER[:GROUP] FILE |
Change ownership (virtual) |
kill |
-l, -s SIG, -n NUM, -SIG, PID/%job |
Terminate background jobs (exit 128+signal); stop/continue signals are ignored |
trap |
COMMAND SIGNAL..., -p, -l |
Signal/event handlers |
type |
NAME... |
Describe command type |
which |
NAME... |
Locate a command |
command |
-v, NAME... |
Run or identify commands |
hash |
(none) | No-op in sandboxed env |
declare/typeset |
-i, -r, -x, -a, -p, -n, -l, -u |
Variable attributes |
let |
EXPR... |
Evaluate arithmetic |
getopts |
OPTSTRING NAME |
Parse positional parameters |
caller |
[FRAME] |
Display call stack frame |
mapfile |
-n, -O, -s, -t, -d |
Read lines into array |
readarray |
-n, -O, -s, -t, -d |
Alias for mapfile |
shopt |
-s, -u, -q, -p, -o |
Shell options; -o acts on set -o names |
seq |
[FIRST [INCR]] LAST |
Print number sequence |
tac |
(none) | Reverse file lines |
rev |
(none) | Reverse characters per line |
yes |
[STRING] |
Output repeated string |
expr |
EXPRESSION |
Evaluate expressions |
mktemp |
-d, -p, -t |
Create temporary files |
realpath |
PATH |
Resolve path |
pushd/popd/dirs |
standard flags | Directory stack |
arch |
(none) | Virtual machine name (x86_64) |
sum |
-r, -s |
BSD and System V checksums, GNU output format |
shasum |
-a 1/224/256/384/512 |
Perl shasum front end over the sha*sum builtins |
egrep/fgrep |
grep flags |
grep -E / grep -F |
link/unlink |
FILE1 FILE2 / FILE |
Single-file link (a symlink, L-FS-001) and remove |
chgrp |
GROUP FILE... |
Change group (virtual, like chown) |
nohup/nice |
COMMAND..., nice -n N |
Run the command; no signal or priority effect in a sandbox |
flock |
FILE CMD, FILE -c CMD, -n FD |
Creates the lock file and runs the command; locks are uncontended in one session |
getconf |
NAME, -a |
POSIX config values, consistent with nproc and /proc/meminfo |
tty |
-s |
“not a tty” unless the embedder sets tty(0, true), like [ -t 0 ] |
sync/hostid |
(none) | No-op / fixed virtual host id |
groups/logname |
[USER] |
Virtual user only |
users/who |
(none) | Empty: no login sessions |
uptime |
-p, -s |
Derived from the virtual clock |
free |
-b, -k, -m, -g, -h, -t |
Fixed virtual memory, consistent with /proc/meminfo |
Not Implemented#
| Builtin | Priority | Status |
|---|---|---|
exec |
N/A | Security: intentionally excluded |
Shell Syntax#
Operators#
| Operator | Status | Example | Notes |
|---|---|---|---|
| |
✅ | cmd1 | cmd2 |
Pipeline; each stage is a subshell, shopt -s lastpipe keeps the last stage in the shell |
&& |
✅ | cmd1 && cmd2 |
AND list |
|| |
✅ | cmd1 || cmd2 |
OR list |
; |
✅ | cmd1; cmd2 |
Sequential |
& |
⚠️ | cmd & |
Parsed, async pending |
! |
✅ | ! cmd |
Negate exit code |
Redirections#
| Redirect | Status | Example | Notes |
|---|---|---|---|
> |
✅ | cmd > file |
Output to file |
>> |
✅ | cmd >> file |
Append to file |
< |
✅ | cmd < file |
Input from file |
<<< |
✅ | cmd <<< "string" |
Here-string |
<<EOF |
✅ | Heredoc | Multi-line input; unquoted bodies expand $, $( ), backticks and \$/\`/\\ escapes |
2> |
✅ | cmd 2> file |
Stderr redirect |
2>&1 |
✅ | cmd 2>&1 |
Stderr to stdout |
&> |
✅ | cmd &> file |
Both to file |
N>/N>> (N≥3) |
✅ | { cmd >&3; } 3>file |
Opens fd N only; stdout untouched |
Control Flow#
| Feature | Status | Example |
|---|---|---|
if/elif/else/fi |
✅ | if cmd; then ...; fi |
for/do/done |
✅ | for i in a b c; do ...; done |
while/do/done |
✅ | while cmd; do ...; done |
until/do/done |
✅ | until cmd; do ...; done |
case/esac |
✅ | case $x in pat) ...;; esac |
{ ... } |
✅ | Brace group |
( ... ) |
✅ | Subshell |
function name { } |
✅ | Function definition |
name() { } |
✅ | Function definition |
Expansions#
Variable Expansion#
| Syntax | Status | Example | Description |
|---|---|---|---|
$var |
✅ | $HOME |
Simple expansion |
${var} |
✅ | ${HOME} |
Braced expansion |
${var:-default} |
✅ | ${X:-fallback} |
Use default if unset/empty |
${var:=default} |
✅ | ${X:=value} |
Assign default if unset/empty |
${var:+alt} |
✅ | ${X:+yes} |
Use alt if set |
${var:?error} |
✅ | ${X:?missing} |
Error if unset/empty |
${#var} |
✅ | ${#str} |
Length of value |
${var#pat} |
✅ | ${f#*.} |
Remove shortest prefix |
${var##pat} |
✅ | ${f##*/} |
Remove longest prefix |
${var%pat} |
✅ | ${f%.*} |
Remove shortest suffix |
${var%%pat} |
✅ | ${f%%/*} |
Remove longest suffix |
${var/pat/repl} |
✅ | ${s/foo/bar} |
Substitute first match |
${var//pat/repl} |
✅ | ${s//o/0} |
Substitute all matches |
${var^} |
✅ | ${s^} |
Uppercase first |
${var^^} |
✅ | ${s^^} |
Uppercase all |
${var,} |
✅ | ${s,} |
Lowercase first |
${var,,} |
✅ | ${s,,} |
Lowercase all |
${var^^pat} |
✅ | ${s^^[aeiou]} |
Case change only for characters matching pat (also ^, ,, ,,) |
${var@op} |
✅ | ${s@Q} |
Transform: Q quote, E escapes, U/u/L case, A assignment, a attributes |
${arr[@]op} |
✅ | ${a[@]/x/y}, ${a[@]^^}, ${a[@]@Q} |
Pattern, case and transform operators apply per element (also ${a[i]op}, $@, $*) |
Prefix Environment Assignments#
| Syntax | Status | Example | Description |
|---|---|---|---|
VAR=val cmd |
✅ | TOKEN=abc printenv TOKEN |
Temporary env for command |
| Multiple prefix | ✅ | A=1 B=2 cmd |
Multiple vars in one command |
| No persist | ✅ | X=1 cmd; echo $X |
Var not set after command |
| Assignment-only | ✅ | X=1 (no cmd) |
Persists in shell variables |
Command Substitution#
| Syntax | Status | Example |
|---|---|---|
$(cmd) |
✅ | x=$(pwd) |
`cmd` |
✅ | Backticks, including after quoted word segments; unquoted output splits and globs |
Arithmetic#
| Syntax | Status | Example |
|---|---|---|
$((expr)) |
✅ | $((1+2)) |
+, -, *, /, % |
✅ | Basic ops |
==, !=, <, >, <=, >= |
✅ | Comparisons |
&, | |
✅ | Bitwise |
&&, || |
✅ | Logical operators |
? : |
✅ | Ternary |
=, +=, etc. |
✅ | Assignment operators |
Other Expansions#
| Syntax | Status | Example | Description |
|---|---|---|---|
*, ? |
✅ | *.txt |
Glob patterns |
[abc] |
✅ | [0-9] |
Bracket globs |
{a,b,c} |
✅ | {1..5} |
Brace expansion |
~ |
✅ | ~/file, ~+, ~- |
Tilde expansion: HOME, PWD, OLDPWD |
<(cmd) |
✅ | diff <(a) <(b) |
Process substitution |
Special Variables#
| Variable | Status | Description |
|---|---|---|
$? |
✅ | Last exit code |
$# |
✅ | Number of positional params |
$@ |
✅ | All positional params (separate) |
$* |
✅ | All positional params (joined) |
$0 |
✅ | Script/function name |
$1-$9 |
✅ | Positional parameters |
$! |
✅ | Last background job ID (POSIX) |
$$ |
✅ | Current PID |
$- |
✅ | Current option flags (POSIX) |
$_ |
❌ | Last argument |
$RANDOM |
✅ | Random number (0-32767) |
$SRANDOM |
✅ | 32-bit random number from the OS CSPRNG (bash 5.1); assignment ignored |
$SECONDS |
✅ | Whole seconds since the shell (the Bash instance) started; SECONDS=N restarts the count from N |
$LINENO |
✅ | Current line number |
Arrays#
| Feature | Status | Example |
|---|---|---|
| Declaration | ✅ | arr=(a b c) |
| Index access | ✅ | ${arr[0]} |
All elements @ |
✅ | ${arr[@]} (separate args) |
All elements * |
✅ | ${arr[*]} (single arg when quoted) |
| Array length | ✅ | ${#arr[@]} |
| Element length | ✅ | ${#arr[0]} |
| Append | ✅ | arr+=(d e) |
| Slice | ✅ | ${arr[@]:1:2} |
| Indices | ✅ | ${!arr[@]} |
| Associative | ✅ | declare -A |
Test Operators#
File Tests#
| Operator | Status | Description |
|---|---|---|
-e file |
✅ | Exists |
-f file |
✅ | Is regular file |
-d file |
✅ | Is directory |
-s file |
✅ | Size > 0 |
-r file |
✅ | Is readable (exists in virtual fs) |
-w file |
✅ | Is writable (exists in virtual fs) |
-x file |
✅ | Is executable (mode & 0o111) |
-L file |
✅ | Is symlink |
String Tests#
| Operator | Status | Description |
|---|---|---|
-z str |
✅ | Is empty |
-n str |
✅ | Is non-empty |
str1 = str2 |
✅ | Equal |
str1 != str2 |
✅ | Not equal |
str1 < str2 |
✅ | Less than |
str1 > str2 |
✅ | Greater than |
Numeric Tests#
| Operator | Status | Description |
|---|---|---|
-eq |
✅ | Equal |
-ne |
✅ | Not equal |
-lt |
✅ | Less than |
-gt |
✅ | Greater than |
-le |
✅ | Less or equal |
-ge |
✅ | Greater or equal |
Resource Limits#
Default limits (configurable):
| Resource | Default | Notes |
|---|---|---|
| Commands | 10,000 | Per execution |
| Loop iterations | 10,000 | Per loop |
| Total loop iterations | 1,000,000 | Per execution |
| Function depth | 100 | Recursion limit |
| Output size | 1MiB each | Separate stdout and stderr caps |
| Parser timeout | 5s | Prevents infinite parse |
| Parser operations | 100,000 | Fuel-based limit |
| Input size | 10MB | Max script size |
| AST depth | 100 | Nesting limit |
Filesystem#
| Feature | Status | Notes |
|---|---|---|
| Virtual filesystem | ✅ | InMemoryFs, OverlayFs, MountableFs |
| Real filesystem | ❌ | Virtual by default |
| Symlinks | ✅ | Followed in the VFS (40-link cap); .. resolves lexically |
| Permissions | ✅ | Metadata stored, not enforced |
/dev/null |
✅ | Interpreter-level handling (cannot be bypassed) |
/dev/zero |
✅ | 1 MiB of zeros per read |
/etc, /proc |
⚠️ | Synthetic, read-only (os-release, passwd, cpuinfo, …); rootfs(false) disables |
/bin, /usr/bin |
✅ | Stub per builtin; which/type report paths, running a stub runs the builtin |
Network#
| Feature | Status | Notes |
|---|---|---|
| HTTP client | ✅ | Full implementation with security mitigations |
| URL allowlist | ✅ | Default-deny whitelist security model |
curl builtin |
✅ | Full HTTP client; ordered data variants, @file, and -G query aggregation included |
wget builtin |
✅ | Full downloader with -q, -O, --spider, --header, -U, --post-data, -t |
| Response limits | ✅ | 10MB max response size, 30s timeout |
| Redirect security | ✅ | Redirects require explicit -L and allowlist check |
| Raw sockets | ❌ | Not planned |
Network Configuration#
use bashkit::{Bash, NetworkAllowlist};
// Enable network with URL allowlist
let bash = Bash::builder()
.network(NetworkAllowlist::new()
.allow("https://api.example.com")
.allow("https://cdn.example.com/assets"))
.build();
See knowledge/security/threat-model.md for HTTP security details.
Running Tests#
# All tests
cargo test --all-features
# Spec tests only
cargo test --test spec_tests
# Compare with real bash
cargo test --test spec_tests -- bash_comparison_tests --ignored
Roadmap#
Completed#
-
sleepbuiltin -
head/tailbuiltins - File operation builtins (
mkdir,rm,cp,mv,touch,chmod) -
wcbuiltin - Text processing (
sort,uniq,cut,tr) - Text structure (
nl,paste,column) - File comparison (
diff,comm) - Byte inspection (
strings,od,xxd,hexdump) -
basename/dirnamebuiltins -
datebuiltin - Background execution (
&,wait) - jobs run concurrently on the session’s task (no stop/continue) - Network (
curl,wget) - full HTTP implementation with security mitigations -
timeoutbuiltin - stub, requires interpreter-level integration - Process substitution (
<(cmd),>(cmd)) - Here string edge cases tested
-
set -e(errexit) - exit on command failure - Tilde expansion (~) - expands to $HOME
- Special variables ($$, $RANDOM, $LINENO)
- File test operators (-r, -w, -x, -L)
- Stderr redirections (2>, 2>&1, &>)
- Arithmetic logical operators (&&, ||)
- Brace expansion ({a,b,c}, {1..5})
- String comparison operators (< >) in test
- Array indices
${!arr[@]} -
/dev/nullsupport (interpreter-level, cannot be bypassed by custom fs)
Known LLM Compatibility Gaps (Resolved)#
Identified from eval analysis, all items now implemented:
High Impact (commonly generated by LLMs):
-
chmod +xsymbolic mode,apply_symbolic_mode()in fileops.rs -
sedampersand (&) in replacement, PR #196 - AWK
printf %x/%o/%cformat specifiers, hex/octal output - AWK
match()andgensub()functions, text extraction -
sed\nliteral newline in replacement, line splitting
Medium Impact:
- AWK power operators (
^,**), math scripts - AWK
exitstatement with code, error handling - AWK negation
!$1, filtering empty fields -
sedgrouped commands{cmd1;cmd2}, PR #227 -
sedbranch/label (b/t/:label), branching support - AWK
ORSvariable, custom output formatting - AWK
getline, multi-file processing
Low Impact:
-
sed0~2step addressing, even/odd line processing -
sedQquiet quit command -
sed0,/pattern/first match addressing -
sedGNU rewrite, issue #2427: literal$in the replacement, BRE/ERE translation shared bys///and address regexes, stateful range addresses, single-stream multi-file input, preserved missing final newline,s///Ng, they = l n N P D T z F r R w Wcommands,#comments and#n, atomic mode-preserving-i, and full getopt-style option parsing - AWK
$0modification with field re-splitting - AWK regex field separators (
-F' +',FS = "[,;]") and regexsplit()separators
Not Planned#
- Interactive features (history, job control UI)
- Process spawning (virtual environment)
- Raw filesystem access
See Also#
- knowledge/operations/limitations.md - Intentional gaps and partial features
- Bashkit knowledge - Persistent design and engineering knowledge