bashkit

Bashkit Compatibility Scorecard#

Feature parity tracking for bash and common tools

See also:

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 CategoryStatus
Reserved Words (16)Full compliance
Special Parameters (8)Full compliance
Special Built-ins (15)14/15 implemented
Word ExpansionsSubstantial compliance
RedirectionsFull compliance
Compound CommandsFull compliance

Security Exclusions: exec is intentionally not implemented for sandbox security reasons. See the compliance spec for details.

Quick Status#

GroupCount
Always-on builtins142
Feature-gated builtins (jq, git, ssh/scp/sftp, python/python3, sqlite/sqlite3, ts/typescript/node/deno/bun)14
Total156

Builtins Reference#

Implemented#

BuiltinFlags/FeaturesNotes
echo-n, -e, -EBasic escape sequences
printf%s, %d, %u, %x, %o, %f, width/precisionGNU-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, -geConditionals
[(same as test)Alias for test
exportVAR=valueExport variables
readVARRead line into variable
set-e, +e, positionalSet options and positional params
unsetVARUnset variable
shift[N]Shift positional params
localVAR=valueLocal variables
sourcefile [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 (shebang stripped, call frame)
$PATH searchcmd [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)
evalcommand...POSIX construct and execute command
readonlyVAR[=value], -pPOSIX mark variable read-only
times-POSIX display process times
grep-i, -v, -c, -n, -E, -qPattern matching
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, --versionRecursive ripgrep-style search
seds///[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 formsStream editing; one stream across operands unless -s/-i
awk'{print}', -F, -v, loops, arrays, increment, ternaryText processing
jq.field, .[n], pipes, file args, -r, -c, -n, -s, -S, -e, -j, --tab, --arg, --argjson, -V, combined flagsJSON processing
sleepN, N.NPause execution (max 60s)
head-n N, -NFirst N lines (default 10)
tail-n N, -NLast N lines (default 10)
basenameNAME [SUFFIX]Strip directory from path
dirnameNAMEStrip last path component
mkdir-pCreate directories
rm-rfRemove files/directories
cp-rCopy files
mv-Move/rename files
touch-Create empty files
chmodMODEChange permissions (octal only)
wc-l, -w, -cCount lines/words/bytes
sort-r, -n, -uSort lines
uniq-c, -d, -uFilter duplicate lines
cut-d DELIM, -f FIELDSExtract fields
tr-d, character rangesTranslate/delete chars
date+FORMAT, -u, -R, -I, -r, -d/--date (relative, compound, epoch)Display/format date with sandboxed IANA timezone support
wait[JOB_ID...]Wait for background jobs
curl-s, -o, -X, -d/--data, --data-raw, --data-binary, --data-urlencode, -G/--get, -H, -I, -f, -L, -w, --compressed, -u, -A, -e, -v, -mHTTP client (requires http_client feature)
wget-q, -O, --spider, --header, -U, --post-data, -tDownload files (requires http_client feature)
time[-p] [-f FORMAT] [-o FILE] [-a] [-v] [--] PIPELINEReserved-word timing; elapsed/status/Bashkit counters are truthful, host CPU/RSS fields say unavailable
timeoutDURATION COMMANDRun with time limit (stub)
ls-l, -a, -h, -1, -R, -t, -F, -C, -dList directory contents
find-name, -type, -maxdepth, -printSearch for files
rmdir-pRemove empty directories
xargs-I, -n, -dBuild commands from stdin
tee-aWrite to files and stdout
watchINTERVAL COMMANDExecute periodically (virtual mode)
file(none)Detect file type via magic bytes
less(none)View file (behaves like cat in virtual mode)
stat-c FORMATDisplay file metadata
tar-c, -x, -t, -v, -f, -z/--gzip, -j/--bzip2Archive operations; auto-detects gzip/bzip2 while reading
gzip-d, -k, -fCompress files
gunzip-k, -fDecompress files
bzip2-c, -d, -z, -k, -fCompress or decompress bzip2 streams/files
bunzip2-c, -k, -fDecompress bzip2 streams/files
bzcatDecompress bzip2 streams/files to stdout
env[VAR=val]Print/modify environment
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, -oSystem info
whoami(none)Display virtual username
id-u, -g, -nUser/group IDs
nl-b, -n, -s, -i, -v, -wNumber lines of files
paste-d, -sMerge lines of files
column-t, -s, -oColumnate lists
comm-1, -2, -3Compare two sorted files
diff-u, -q/--briefCompare files line by line
strings-n, -t, -aFind printable strings in binary data
od-A, -t, -N, -jOctal/hex dump
xxd-l, -s, -c, -g, -pHex dump
hexdump-C, -n, -sDisplay 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#

BuiltinFlags / ArgumentsNotes
ln-s, -fCreate links
chownOWNER[:GROUP] FILEChange ownership (virtual)
kill-SIGNAL PIDSend signals (virtual)
trapCOMMAND SIGNAL..., -p, -lSignal/event handlers
typeNAME...Describe command type
whichNAME...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, -uVariable attributes
letEXPR...Evaluate arithmetic
getoptsOPTSTRING NAMEParse positional parameters
caller[FRAME]Display call stack frame
mapfile-n, -O, -s, -t, -dRead lines into array
readarray-n, -O, -s, -t, -dAlias for mapfile
shopt-s, -u, -qShell options
seq[FIRST [INCR]] LASTPrint number sequence
tac(none)Reverse file lines
rev(none)Reverse characters per line
yes[STRING]Output repeated string
exprEXPRESSIONEvaluate expressions
mktemp-d, -p, -tCreate temporary files
realpathPATHResolve path
pushd/popd/dirsstandard flagsDirectory stack

Not Implemented#

BuiltinPriorityStatus
execN/ASecurity: intentionally excluded

Shell Syntax#

Operators#

OperatorStatusExampleNotes
|✅cmd1 | cmd2Pipeline
&&✅cmd1 && cmd2AND list
||✅cmd1 || cmd2OR list
;✅cmd1; cmd2Sequential
&⚠️cmd &Parsed, async pending
!✅! cmdNegate exit code

Redirections#

RedirectStatusExampleNotes
>✅cmd > fileOutput to file
>>✅cmd >> fileAppend to file
<✅cmd < fileInput from file
<<<✅cmd <<< "string"Here-string
<<EOF✅HeredocMulti-line input
2>✅cmd 2> fileStderr redirect
2>&1✅cmd 2>&1Stderr to stdout
&>✅cmd &> fileBoth to file

Control Flow#

FeatureStatusExample
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#

SyntaxStatusExampleDescription
$var✅$HOMESimple 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

Prefix Environment Assignments#

SyntaxStatusExampleDescription
VAR=val cmd✅TOKEN=abc printenv TOKENTemporary env for command
Multiple prefix✅A=1 B=2 cmdMultiple vars in one command
No persist✅X=1 cmd; echo $XVar not set after command
Assignment-only✅X=1 (no cmd)Persists in shell variables

Command Substitution#

SyntaxStatusExample
$(cmd)✅x=$(pwd)
`cmd`✅Backticks (deprecated but supported)

Arithmetic#

SyntaxStatusExample
$((expr))✅$((1+2))
+, -, *, /, %✅Basic ops
==, !=, <, >, <=, >=✅Comparisons
&, |✅Bitwise
&&, ||✅Logical operators
? :✅Ternary
=, +=, etc.✅Assignment operators

Other Expansions#

SyntaxStatusExampleDescription
*, ?✅*.txtGlob patterns
[abc]✅[0-9]Bracket globs
{a,b,c}✅{1..5}Brace expansion
~✅~/fileTilde expansion
<(cmd)✅diff <(a) <(b)Process substitution

Special Variables#

VariableStatusDescription
$?✅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)
$LINENO✅Current line number

Arrays#

FeatureStatusExample
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#

OperatorStatusDescription
-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#

OperatorStatusDescription
-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#

OperatorStatusDescription
-eq✅Equal
-ne✅Not equal
-lt✅Less than
-gt✅Greater than
-le✅Less or equal
-ge✅Greater or equal

Resource Limits#

Default limits (configurable):

ResourceDefaultNotes
Commands10,000Per execution
Loop iterations10,000Per loop
Total loop iterations1,000,000Per execution
Function depth100Recursion limit
Output size1MiB eachSeparate stdout and stderr caps
Parser timeout5sPrevents infinite parse
Parser operations100,000Fuel-based limit
Input size10MBMax script size
AST depth100Nesting limit

Filesystem#

FeatureStatusNotes
Virtual filesystem✅InMemoryFs, OverlayFs, MountableFs
Real filesystem❌Virtual by default
Symlinks✅Stored but not followed
Permissions✅Metadata stored, not enforced
/dev/null✅Interpreter-level handling (cannot be bypassed)

Network#

FeatureStatusNotes
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#

  • sleep builtin
  • head/tail builtins
  • File operation builtins (mkdir, rm, cp, mv, touch, chmod)
  • wc builtin
  • Text processing (sort, uniq, cut, tr)
  • Text structure (nl, paste, column)
  • File comparison (diff, comm)
  • Byte inspection (strings, od, xxd, hexdump)
  • basename/dirname builtins
  • date builtin
  • Background execution (&, wait) - parsed, runs synchronously
  • Network (curl, wget) - full HTTP implementation with security mitigations
  • timeout builtin - 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/null support (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 +x symbolic mode, apply_symbolic_mode() in fileops.rs
  • sed ampersand (&) in replacement, PR #196
  • AWK printf %x/%o/%c format specifiers, hex/octal output
  • AWK match() and gensub() functions, text extraction
  • sed \n literal newline in replacement, line splitting

Medium Impact:

  • AWK power operators (^, **), math scripts
  • AWK exit statement with code, error handling
  • AWK negation !$1, filtering empty fields
  • sed grouped commands {cmd1;cmd2}, PR #227
  • sed branch/label (b/t/:label), branching support
  • AWK ORS variable, custom output formatting
  • AWK getline, multi-file processing

Low Impact:

  • sed 0~2 step addressing, even/odd line processing
  • sed Q quiet quit command
  • sed 0,/pattern/ first match addressing
  • sed GNU rewrite, issue #2427: literal $ in the replacement, BRE/ERE translation shared by s/// and address regexes, stateful range addresses, single-stream multi-file input, preserved missing final newline, s///Ng, the y = l n N P D T z F r R w W commands, # comments and #n, atomic mode-preserving -i, and full getopt-style option parsing
  • AWK $0 modification with field re-splitting

Not Planned#

  • Interactive features (history, job control UI)
  • Process spawning (virtual environment)
  • Raw filesystem access

See Also#