Strands Shell reimplements a curated subset of POSIX and coreutils in Rust, targeting the operations agents reach for most rather than a complete toolset. This page is the reference for what is supported and where behavior diverges from GNU or BSD: missing flags, unsupported features, and known gaps.
The shell is Bourne-compatible, with pipes, loops, functions, and subshells. The commands group into text processing, file contents, file management, path and system utilities, networking, JSON, search, and scripting.
These notes apply across commands:
- Regex uses the Rust
regex crate. Backreferences and lookaround are unavailable, so grep -P is unsupported and GNU BRE escapes are not translated.
jq is backed by jaq, a jq subset.
- Unsupported flags are rejected, not ignored. Idioms such as
cp -p, set -o pipefail, or ln -sf produce an error rather than silently doing the wrong thing.
- Multiple file arguments are not uniformly supported.
cut and uniq read only the first file; head and tail return a hard error; cat, sort, and wc handle multiple files correctly.
- Malformed numeric input passes silently.
test, [, and arithmetic $(( )) treat non-numeric or empty operands as 0 without an error.
- Stdin under
strands-shell -c is not connected to commands (bad fd 0). Use an in-shell pipe instead.
| Command | Notable gaps |
|---|
grep | No -P, backreferences, lookaround, or -f. -o on empty-matching patterns emits blank lines. |
sed | No branching (b, t, :label) or multiline (N, D, P); no -f. s///N replaces the wrong match; range c emits per line. |
tr | Missing [:punct:], [:cntrl:], and [c*n] repeats. -c two-set translate uses the wrong replacement character. |
cut | No -b or --complement. Reads only the first file when given several. |
sort | No -c, -o, -V, or -h (-h prints help instead). Keyed-tie order is non-deterministic. Loads all input into memory. |
uniq | No -w or -D. Reads only the first file when given several. |
wc | No -m (char count) or -L. Counts are correct; column padding differs from coreutils. |
| Command | Notable gaps |
|---|
cat | No -b, -s, -A, -e, or -t; no - stdin operand. |
head | No -c, negative -n, or head -5 shorthand. Multiple files produce a hard error (no ==> headers). |
tail | No -c, -f or -F follow, or shorthand. Multiple files produce a hard error. |
tee | No -i. Standard usage (stdout plus files, -a) is supported. |
| Command | Notable gaps |
|---|
cp | -r works, including nested directories; no -p, -a, -f, or -i. cp f f silently succeeds. |
mv | Rename, move, and cross-mount operations work; no -f, -i, -n, or -v. |
rm | -r, -f, and symlink non-follow behave correctly; no -d or -i. |
mkdir | No -m. An invalid-option path returns exit 0. |
rmdir | No -p. |
touch | File creation and timestamp update only; no -t, -d, -c, or -r (cannot set a specific time). |
ln | -s only; hard links are refused by design; no -f, so ln -sf fails. |
chmod | Full support. Octal and symbolic modes; no -R. |
| Command | Notable gaps |
|---|
ls | -l omits owner, group, and link count; -a omits . and ... No -t, -S, -d, -F, or -h. Output is always single-column. |
basename | No -a or -s. basename / and "" diverge from coreutils. |
dirname | Single operand only. A trailing slash is mishandled (/usr/lib/ becomes /usr/lib). |
readlink | Plain read only; no -f, -e, or -m canonicalization. |
mktemp | No -u or -t. |
date | %s is not expanded; unknown specifiers pass through literally; no -d or -r. UTC only. |
env | Print-only. env VAR=v cmd, -i, and -u are unsupported; use the shell-prefix form instead. |
echo | Expands escapes by default; -e and -E are printed literally (escape expansion cannot be disabled). |
pwd | Full support, including -L and -P. |
sleep | No unit suffixes (0.1s). Respects the shell timeout. |
true, false | Full support. |
| Command | Notable gaps |
|---|
curl | GET, POST, JSON, headers, auth, redirects, and -w are supported. No --max-time, --connect-timeout, or --retry (risk of an indefinite hang); no -I, -F, -A, -G, or cookie jar. SSRF and credential controls are enforced. |
The SSRF guard and credential injection on curl are security features, covered in the security model. They are not optional and cannot be disabled per command.
| Command | Notable gaps |
|---|
jq (jaq) | Broad filter coverage. A missing nested key throws an error, which breaks the .a.b // default pattern; no --arg, --argjson, or -S; inputs and setpath are absent. |
| Command | Notable gaps |
|---|
find | -name, -type, -maxdepth, -exec, and -print0 are supported. No -delete, -size, -mtime, -prune, or -regex. Children are sorted alphabetically, not in readdir order. |
xargs | Space-separated -n, -I, -0, and -d are supported; attached forms (-n1, -I{}) and -t, -r, -L, -P are not. Implicitly behaves as -r. |
| Command | Notable gaps |
|---|
lua | Full support. Sandboxed Lua 5.4 with VFS-backed io and os. Metatables are disabled (setmetatable removed); no os.date or debug. No wall-clock timeout under a bare -c. |
Reach for lua when shell syntax gets awkward: multi-step transforms, structured data manipulation, or logic that would otherwise sprawl across a chain of pipes.
| Builtin | Notable gaps |
|---|
test, [ | No [[ ]]. Non-numeric or empty operands are treated as 0 (succeeds rather than erroring). |
printf | No floating-point (%f, %e, %g print literally); %d does not parse 0x or octal prefixes. |
read | No -a, -n, or -d; a prefix IFS= is ignored; -r is effectively always on. |
set | No -o, so set -o pipefail fails; only e, u, and x are supported. |
trap | EXIT works; numeric signals (trap ... 0) are ignored; -p and -l are no-ops. |
alias | Can be defined and listed, but aliases are never expanded during execution. |
readonly | Enforced, but a violation returns exit 0; no -p. |
local | Works within functions; silently succeeds when used outside a function. |
type | No -t or -a. |
cd | No CDPATH; -P and -L are not parsed. |
getopts, export, unset, shift, umask, hash, wait, : | Full support. |
Arithmetic $(( )) handles precedence, bitwise operators, the ternary, hex, and octal correctly. Malformed input returns a wrong result with exit 0 ($((2 3)) yields 2, $((1/0)) yields 0). Post-increment x++ and x-- return the value without updating the variable.
| Feature | Supported |
|---|
| Pipelines and lists | |, &&, ||, ; |
| Redirections | >, >>, <, 2>, &>, here-docs << |
| Conditionals | if, elif, else, case |
| Loops | for, while, until |
| Functions | definitions, local variables, return |
| Grouping | command groups { }, subshells ( ) |
| Expansion | variables (${VAR:-default}, ${VAR%pat}, ${#VAR}), command substitution (`cmd`, $(cmd)), arithmetic $(( )), globs |
| Quoting | single, double |
| Jobs | background & |
| Scripts | . script.sh, source |