bashkit 0.5.0

Awesomely fast virtual sandbox with bash and file system
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
# Bashkit Compatibility Scorecard

> Feature parity tracking for bash and common tools

**See also:**
- [API Documentation]https://docs.rs/bashkit - Full API reference
- [Custom Builtins Guide]./custom_builtins.md - Extending Bashkit with custom commands
- [Threat Model]./threat-model.md - 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 [specs/implementation-status.md](../specs/implementation-status.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

| Category | Count |
|----------|-------|
| Core & Navigation | 12 |
| Flow Control & Variables | 23 |
| Shell | 7 |
| Text Processing | 20 |
| File Operations & Inspection | 17 |
| Archives & Byte Tools | 6 |
| Utilities & System | 20 |
| Network | 2 |
| Experimental | 3 |
| **Total** | **150** |

---

## Builtins Reference

### Implemented

| Builtin | Flags/Features | Notes |
|---------|----------------|-------|
| `echo` | `-n`, `-e`, `-E` | Basic escape sequences |
| `printf` | `%s`, `%d`, `%x`, `%o`, `%f` | Format specifiers, 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` | Read line into variable |
| `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 (shebang stripped, call frame) |
| `$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` | `-i`, `-v`, `-c`, `-n`, `-E`, `-q` | Pattern matching |
| `sed` | `s///[g]`, `d`, `p`, `q`, `a`, `i`, `c`, `h/H/g/G/x`, `-E`, `-n`, `!` | Stream editing |
| `awk` | `'{print}'`, `-F`, `-v`, loops, arrays, increment, ternary | Text processing |
| `jq` | `.field`, `.[n]`, pipes, file args, `-r`, `-c`, `-n`, `-s`, `-S`, `-e`, `-j`, `--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` | - | Create empty files |
| `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`, `-d`/`--date` (relative, compound, epoch) | Display/format date |
| `wait` | `[JOB_ID...]` | Wait for background jobs |
| `curl` | `-s`, `-o`, `-X`, `-d`, `-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) |
| `timeout` | `DURATION COMMAND` | Run with time limit (stub) |
| `ls` | `-l`, `-a`, `-h`, `-1`, `-R` | List directory contents |
| `find` | `-name`, `-type`, `-maxdepth`, `-print` | Search for files |
| `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` | Archive operations |
| `gzip` | `-d`, `-k`, `-f` | Compress files |
| `gunzip` | `-k`, `-f` | Decompress files |
| `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`, `-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 |

### Recently Added

| Builtin | Flags / Arguments | Notes |
|---------|-------------------|-------|
| `ln` | `-s`, `-f` | Create links |
| `chown` | `OWNER[:GROUP] FILE` | Change ownership (virtual) |
| `kill` | `-SIGNAL PID` | Send signals (virtual) |
| `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` | Shell options |
| `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 |

### Not Implemented

| Builtin | Priority | Status |
|---------|----------|--------|
| `exec` | N/A | Security: intentionally excluded |

---

## Shell Syntax

### Operators

| Operator | Status | Example | Notes |
|----------|--------|---------|-------|
| `\|` || `cmd1 \| cmd2` | Pipeline |
| `&&` || `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 |
| `2>` || `cmd 2> file` | Stderr redirect |
| `2>&1` || `cmd 2>&1` | Stderr to stdout |
| `&>` || `cmd &> file` | Both to file |

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

### 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 (deprecated but supported) |

### 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 |
| `<(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) |
| `$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 | 100,000 | Per loop |
| Function depth | 100 | Recursion limit |
| Output size | 10MB | Total stdout |
| 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 || Stored but not followed |
| Permissions || Metadata stored, not enforced |
| `/dev/null` || Interpreter-level handling (cannot be bypassed) |

---

## Network

| Feature | Status | Notes |
|---------|--------|-------|
| HTTP client || Full implementation with security mitigations |
| URL allowlist || Default-deny whitelist security model |
| `curl` builtin || Full HTTP client with `-s`, `-o`, `-X`, `-d`, `-H`, `-I`, `-f`, `-L`, `-w`, `--compressed`, `-u`, `-A`, `-e`, `-v`, `-m` |
| `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

```rust,ignore
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 [specs/threat-model.md](../specs/threat-model.md) for HTTP security details.

---

## Running Tests

```bash
# 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
- [x] `sleep` builtin
- [x] `head`/`tail` builtins
- [x] File operation builtins (`mkdir`, `rm`, `cp`, `mv`, `touch`, `chmod`)
- [x] `wc` builtin
- [x] Text processing (`sort`, `uniq`, `cut`, `tr`)
- [x] Text structure (`nl`, `paste`, `column`)
- [x] File comparison (`diff`, `comm`)
- [x] Byte inspection (`strings`, `od`, `xxd`, `hexdump`)
- [x] `basename`/`dirname` builtins
- [x] `date` builtin
- [x] Background execution (`&`, `wait`) - parsed, runs synchronously
- [x] Network (`curl`, `wget`) - full HTTP implementation with security mitigations
- [x] `timeout` builtin - stub, requires interpreter-level integration
- [x] Process substitution (`<(cmd)`, `>(cmd)`)
- [x] Here string edge cases tested
- [x] `set -e` (errexit) - exit on command failure
- [x] Tilde expansion (~) - expands to $HOME
- [x] Special variables ($$, $RANDOM, $LINENO)
- [x] File test operators (-r, -w, -x, -L)
- [x] Stderr redirections (2>, 2>&1, &>)
- [x] Arithmetic logical operators (&&, ||)
- [x] Brace expansion ({a,b,c}, {1..5})
- [x] String comparison operators (< >) in test
- [x] Array indices `${!arr[@]}`
- [x] `/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):**
- [x] `chmod +x` symbolic mode — `apply_symbolic_mode()` in fileops.rs
- [x] `sed` ampersand (`&`) in replacement — PR #196
- [x] AWK `printf %x/%o/%c` format specifiers — hex/octal output
- [x] AWK `match()` and `gensub()` functions — text extraction
- [x] `sed` `\n` literal newline in replacement — line splitting

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

**Low Impact:**
- [x] `sed` `0~2` step addressing — even/odd line processing
- [x] `sed` `Q` quiet quit command
- [x] `sed` `0,/pattern/` first match addressing
- [x] AWK `$0` modification with field re-splitting

### Not Planned
- Interactive features (history, job control UI)
- Process spawning (virtual environment)
- Raw filesystem access

---

## See Also

- [specs/implementation-status.md]../../../specs/implementation-status.md - Detailed implementation status
- [specs/]../../../specs/ - Design specifications