shell
Run commands and inspect the filesystem. exec and bash run programs and raise an approval interrupt before doing so. ls, grep, glob, stat, exists, and which are read-only helpers that return results directly.
import { bash } from "std::shell"
node main() {
const result = bash("ls -la") with approve
print(result.stdout)
}Types
ExecResult
What a shell command produced. Exported so std::safeBash can declare the same return type on both its paths — a fast-path result and a real bash() result have to be the same shape by construction, not by coincidence.
/** What a shell command produced. Exported so `std::safeBash` can declare the
* same return type on both its paths — a fast-path result and a real
* `bash()` result have to be the same shape by construction, not by
* coincidence. */
export type ExecResult = {
stdout: string;
stderr: string;
exitCode: number
}(source)
Effects
std::exec
@always(command, subcommand)
effect std::exec {
command: string;
args: string[];
subcommand: string;
cwd: string;
timeout: number;
stdin: string
}(source)
std::bash
@always(command, cwd)
effect std::bash {
command: string;
cwd: string;
timeout: number;
stdin: string
}(source)
std::ls
@alwaysUnder(dir)
effect std::ls {
dir: string;
recursive: boolean;
maxResults: number
}(source)
std::grep
@alwaysUnder(dir)
effect std::grep {
pattern: string;
dir: string;
flags: string;
maxResults: number;
ignoreCase: boolean;
wholeWord: boolean;
filesOnly: boolean;
invert: boolean
}(source)
std::glob
@alwaysUnder(dir)
effect std::glob {
pattern: string;
dir: string;
maxResults: number
}(source)
Functions
exec
exec(
command: string,
args: string[] = [],
cwd: string = "",
timeout: number = 0,
stdin: string = "",
allowedExecutables: string[] = [],
blockedCommands: string[] = [],
allowedPaths: string[] = [],
useAgentCwd: boolean = false,
): ExecResultRun an executable directly with an array of arguments, bypassing the shell, and return its stdout, stderr, and exit code. Arguments are passed straight to the process without shell interpretation, which prevents command injection. Prefer this whenever you have a known command and structured arguments.
@param command - The executable to run @param args - Arguments to pass @param cwd - Working directory for the command @param timeout - Time limit in milliseconds (e.g. 30s) @param stdin - Input to feed to the command @param allowedExecutables - Only allow running these executables (allow-list) @param blockedCommands - Block running these executables @param allowedPaths - Only allow cwd values under these path prefixes @param useAgentCwd - When true, a relative or empty cwd is resolved against the agent working directory if one is set; an absolute cwd is left unchanged
Parameters:
| Name | Type | Default |
|---|---|---|
| command | string | |
| args | string[] | [] |
| cwd | string | "" |
| timeout | number | 0 |
| stdin | string | "" |
| allowedExecutables | string[] | [] |
| blockedCommands | string[] | [] |
| allowedPaths | string[] | [] |
| useAgentCwd | boolean | false |
Returns: ExecResult
Throws: std::exec
(source)
bash
bash(
command: string,
cwd: string = "",
timeout: number = 0,
stdin: string = "",
blockedCommands: string[] = [],
allowedPaths: string[] = [],
useAgentCwd: boolean = false,
): ExecResultRun a shell command string via sh -c and return its stdout, stderr, and exit code. The shell interprets the string, so pipes, redirects, and globbing work. Interpolated values are also subject to shell interpretation, so prefer running an executable directly with structured arguments when passing untrusted or dynamic values.
@param command - The shell command to run @param cwd - Working directory for the command @param timeout - Time limit in milliseconds (e.g. 30s) @param stdin - Input to feed to the command @param blockedCommands - Block commands that start with these strings @param allowedPaths - Only allow cwd values under these path prefixes @param useAgentCwd - When true, a relative or empty cwd is resolved against the agent working directory if one is set; an absolute cwd is left unchanged
allowedPaths restricts cwd, but bash cannot meaningfully restrict the shell command string itself, so prefer running an executable directly with structured arguments when capability narrowing matters.
Parameters:
| Name | Type | Default |
|---|---|---|
| command | string | |
| cwd | string | "" |
| timeout | number | 0 |
| stdin | string | "" |
| blockedCommands | string[] | [] |
| allowedPaths | string[] | [] |
| useAgentCwd | boolean | false |
Returns: ExecResult
Throws: std::bash
(source)
ls
ls(
dir: string = ".",
recursive: boolean = false,
maxResults: number = 1000,
allowedPaths: string[] = [],
useAgentCwd: boolean = false,
): ResultList entries in a directory. Each entry has name, path, type ("file", "dir", or "other"; symlinked entries are left out), and size. Set recursive to true to walk subdirectories. Fails if the directory cannot be read.
A recursive listing skips heavyweight dirs (node_modules, .git, dist, build, .next, .cache) and stops at maxResults. A non-recursive listing still shows those dirs. If entries look truncated, narrow dir or raise maxResults.
@param dir - The directory to list @param recursive - Whether to walk subdirectories @param maxResults - Maximum number of entries to return Symlinked entries are left out. Symlinks below dir are never followed.
@param allowedPaths - Only allow listing directories under these prefixes @param useAgentCwd - When true, resolve a relative dir against the agent working directory if one is set
Parameters:
| Name | Type | Default |
|---|---|---|
| dir | string | "." |
| recursive | boolean | false |
| maxResults | number | 1000 |
| allowedPaths | string[] | [] |
| useAgentCwd | boolean | false |
Returns: Result
Throws: std::ls
(source)
grep
grep(
pattern: string,
dir: string = ".",
flags: string = "",
maxResults: number = 200,
allowedPaths: string[] = [],
useAgentCwd: boolean = false,
ignoreCase: boolean = false,
wholeWord: boolean = false,
filesOnly: boolean = false,
invert: boolean = false,
respectGitignore: boolean = true,
): ResultSearch files under a directory for a regular expression, like grep -rn. The search is always recursive and every match comes back with its file path, line number, and line text. Skips node_modules, .git, dist, build, and by default anything the directory's .gitignore files ignore, so generated output does not crowd out source. Patterns use JavaScript regex syntax, not grep's. Fails if the pattern is not a valid regex or the directory cannot be read.
Returned file values are relative to dir. Returns at most maxResults matches; if matches look truncated, narrow dir or refine the pattern. Symlinked entries are left out. Symlinks below dir are never followed.
@param pattern - The regex pattern to search for, in JavaScript regex syntax @param dir - The directory to search in @param flags - JavaScript regex flags (i, m, s, u). grep's -r and -n are always on. For -w, -l, and -v use wholeWord, filesOnly, and invert. @param maxResults - Maximum number of results to return @param allowedPaths - Only allow searching under these path prefixes @param useAgentCwd - When true, resolve a relative dir against the agent working directory if one is set @param ignoreCase - Match regardless of letter case (grep -i) @param wholeWord - Match only where the pattern is a whole word (grep -w) @param filesOnly - Return just the paths of the files with a match, one entry per file, instead of the matching lines (grep -l) @param invert - Return the lines that do NOT match (grep -v) @param respectGitignore - Skip files and directories that the .gitignore files under dir ignore. True by default; pass false to search build output too.
The flags string is translated before it reaches the RegExp, so a caller who writes grep-style letters gets a search or a message naming the parameter to use, never a RegExp constructor error. The rule table is in lib/stdlib/grepQuery.ts.
Parameters:
| Name | Type | Default |
|---|---|---|
| pattern | string | |
| dir | string | "." |
| flags | string | "" |
| maxResults | number | 200 |
| allowedPaths | string[] | [] |
| useAgentCwd | boolean | false |
| ignoreCase | boolean | false |
| wholeWord | boolean | false |
| filesOnly | boolean | false |
| invert | boolean | false |
| respectGitignore | boolean | true |
Returns: Result
Throws: std::grep
(source)
glob
glob(
pattern: string,
dir: string = ".",
maxResults: number = 500,
allowedPaths: string[] = [],
useAgentCwd: boolean = false,
): ResultFind files whose paths match a glob pattern (e.g. "src/**/*.ts"). Fails if the pattern is not valid glob syntax or the directory cannot be read. Symlinked entries are left out. Symlinks below dir are never followed.
@param pattern - The glob pattern to match @param dir - The directory to search in @param maxResults - Maximum number of results to return @param allowedPaths - Only allow searching under these path prefixes @param useAgentCwd - When true, resolve a relative dir against the agent working directory if one is set
Parameters:
| Name | Type | Default |
|---|---|---|
| pattern | string | |
| dir | string | "." |
| maxResults | number | 500 |
| allowedPaths | string[] | [] |
| useAgentCwd | boolean | false |
Returns: Result
Throws: std::glob
(source)
stat
stat(
filename: string,
dir: string = "",
allowedPaths: string[] = [],
useAgentCwd: boolean = false,
): StatInfoReturn metadata about a filesystem entry: whether it exists, its type ("file", "dir", "other", or "missing" if absent), size in bytes, and mtime in ms. A symlink below dir is reported as missing. With no dir, the path itself is resolved the way you spelled it.
@param filename - The path to stat @param dir - Directory to resolve a relative filename against; filename cannot escape it. When empty, filename resolves against the process cwd and absolute paths are accepted @param allowedPaths - Only allow paths under these prefixes @param useAgentCwd - When true, resolve a relative filename against the agent working directory if one is set; absolute filenames are unaffected
Parameters:
| Name | Type | Default |
|---|---|---|
| filename | string | |
| dir | string | "" |
| allowedPaths | string[] | [] |
| useAgentCwd | boolean | false |
Returns: StatInfo
(source)
exists
exists(
filename: string,
dir: string = "",
allowedPaths: string[] = [],
useAgentCwd: boolean = false,
): booleanReturn true if a file or directory exists at the given path. A symlink below dir is reported as missing. Probing a path outside allowedPaths raises an error rather than silently returning false.
@param filename - The path to check @param dir - Directory to resolve a relative filename against; filename cannot escape it. When empty, filename resolves against the process cwd and absolute paths are accepted @param allowedPaths - Only allow paths under these prefixes @param useAgentCwd - When true, resolve a relative filename against the agent working directory if one is set; absolute filenames are unaffected
Parameters:
| Name | Type | Default |
|---|---|---|
| filename | string | |
| dir | string | "" |
| allowedPaths | string[] | [] |
| useAgentCwd | boolean | false |
Returns: boolean
(source)
which
which(command: string): stringLocate an executable in PATH and return its absolute path, or an empty string if not found. On Windows, also tries PATHEXT extensions.
@param command - The executable to find
Parameters:
| Name | Type | Default |
|---|---|---|
| command | string |
Returns: string
(source)