bashkit

TypeScript API reference#

Auto-generated reference for the @everruns/bashkit npm package. Reflects the latest published release.

Install with npm install @everruns/bashkit. See the Embedding guide and LLM tools guide for task-oriented walkthroughs.

Bash#

Core bash interpreter with virtual filesystem.

State persists between calls — files created in one execute() are available in subsequent calls.

import { Bash } from '@everruns/bashkit';

const bash = new Bash();
const result = bash.executeSync('echo "Hello, World!"');
console.log(result.stdout); // Hello, World!\n

Constructor#

new Bash(options?: BashOptions): Bash

addBuiltin#

bash.addBuiltin(name: string, callback: BuiltinCallback): void

Register a JS callback as a custom bash builtin.

The callback receives a BuiltinContext and returns the stdout to emit. Sync (string) and async (Promise<string>) returns are both supported. Exceptions become stderr + exit code 1.

Safe to call at any time — the new builtin is visible to the next execute*() invocation with no interpreter rebuild or VFS disturbance. Survives reset().

appendFile#

bash.appendFile(path: string, content: string): void

Append content to a file.

cancel#

bash.cancel(): void

Cancel the currently running execution.

chmod#

bash.chmod(path: string, mode: number): void

Change file permissions (octal mode, e.g. 0o755).

clearCancel#

bash.clearCancel(): void

Clear the cancellation flag so subsequent executions proceed normally.

Call this after cancel() once the in-flight execution has finished and you want to reuse the same instance without discarding shell or VFS state.

execute#

bash.execute(commands: string, options?: ExecuteOptions): Promise<ExecResult>

Execute bash commands asynchronously, returning a Promise.

Non-blocking for the Node.js event loop. If onOutput is provided, it receives chunk objects with { stdout, stderr } during execution. Chunks are not line-aligned. The callback must be synchronous; Promise-returning handlers are rejected. Do not re-enter the same instance from onOutput via execute*, readFile, fs(), etc.

const result = await bash.execute('echo hello');
console.log(result.stdout); // hello\n

executeOrThrow#

bash.executeOrThrow(commands: string, options?: ExecuteOptions): Promise<ExecResult>

Execute bash commands asynchronously. Throws BashError on non-zero exit.

executeSync#

bash.executeSync(commands: string, options?: ExecuteOptions): ExecResult

Execute bash commands synchronously and return the result.

If signal is provided, the execution will be cancelled when the signal is aborted. If onOutput is provided, it receives chunk objects with { stdout, stderr } during execution. Chunks are not line-aligned. The callback must be synchronous; Promise-returning handlers are rejected. Do not re-enter the same instance from onOutput via execute*, readFile, fs(), etc.

executeSyncOrThrow#

bash.executeSyncOrThrow(commands: string, options?: ExecuteOptions): ExecResult

Execute bash commands synchronously. Throws BashError on non-zero exit.

exists#

bash.exists(path: string): boolean

Check if a path exists in the virtual filesystem.

fs#

bash.fs(): FileSystem

Get a FileSystem handle for direct VFS operations.

glob#

bash.glob(pattern: string): string[]

Find files matching a name pattern. Returns absolute paths.

ls#

bash.ls(path?: string): string[]

List entry names in a directory. Returns empty array if directory does not exist.

mkdir#

bash.mkdir(path: string, recursive?: boolean): void

Create a directory. If recursive is true, creates parents as needed.

mount#

bash.mount(vfsPath: string, fs: FileSystem): void

Mount either a host directory or a FileSystem into the VFS.

readDir#

bash.readDir(path: string): ({ metadata: { created: number; fileType: string; mode: number; modified: number; size: number }; name: string })[]

List directory entries with metadata.

readFile#

bash.readFile(path: string): string

Read a file from the virtual filesystem as a UTF-8 string.

bash.readLink(path: string): string

Read the target of a symbolic link.

remove#

bash.remove(path: string, recursive?: boolean): void

Remove a file or directory. If recursive is true, removes contents.

removeBuiltin#

bash.removeBuiltin(name: string): void

Remove a previously registered custom builtin.

reset#

bash.reset(): void

Reset interpreter to fresh state, preserving configuration.

restoreSnapshot#

bash.restoreSnapshot(data: Uint8Array, options?: SnapshotOptions): void

Restore interpreter state from a previously captured snapshot. Preserves current configuration (limits, builtins) but replaces shell state and VFS contents.

restoreSnapshotKeyed#

bash.restoreSnapshotKeyed(data: Uint8Array, key: Uint8Array): void

Restore interpreter state from a HMAC-protected snapshot.

shellState#

bash.shellState(): ShellState

Capture a lightweight snapshot of shell state (variables, env, cwd, arrays, aliases, traps) for inspection — e.g. prompt rendering or debugging. Function definitions are omitted; use snapshot() for full state capture/restore.

snapshot#

bash.snapshot(options?: SnapshotOptions): Uint8Array

Serialize interpreter state (variables, VFS, counters) to a Uint8Array.

Use hmacKey when snapshots are stored outside the current trust boundary (network, user uploads, shared storage). Without hmacKey, the snapshot digest only detects accidental corruption and is forgeable.

const bash = new Bash();
await bash.execute("x=42");
const snapshot = bash.snapshot();
// persist snapshot...
const bash2 = Bash.fromSnapshot(snapshot);
const r = await bash2.execute("echo $x"); // "42\n"

snapshotKeyed#

bash.snapshotKeyed(key: Uint8Array, options?: SnapshotOptions): Uint8Array

Serialize interpreter state with HMAC-SHA256 using a caller-provided key. Use for snapshots crossing trust boundaries.

stat#

bash.stat(path: string): { created: number; fileType: string; mode: number; modified: number; size: number }

Get metadata for a path (fileType, size, mode, timestamps).

bash.symlink(target: string, link: string): void

Create a symbolic link pointing to target.

unmount#

bash.unmount(vfsPath: string): void

Unmount a previously mounted filesystem.

writeFile#

bash.writeFile(path: string, content: string): void

Write a string to a file in the virtual filesystem.

create#

Bash.create(options?: BashOptions): Promise<Bash>

Create a Bash instance with support for async file providers.

Use this instead of new Bash() when file values are async functions.

const bash = await Bash.create({
  files: {
    "/data/remote.json": async () => await fetchData(),
  }
});

fromSnapshot#

Bash.fromSnapshot(data: Uint8Array, options?: SnapshotOptions): Bash

Create a new Bash instance from a snapshot.

const snapshot = existingBash.snapshot();
const restored = Bash.fromSnapshot(snapshot);

fromSnapshotKeyed#

Bash.fromSnapshotKeyed(data: Uint8Array, key: Uint8Array): Bash

Create a new Bash instance from a HMAC-protected snapshot.

BashTool#

Bash interpreter with tool-contract metadata.

Use this when integrating with AI frameworks that need tool definitions.

import { BashTool } from '@everruns/bashkit';

const tool = new BashTool();
console.log(tool.name);           // "bashkit"
console.log(tool.inputSchema());  // JSON schema string
console.log(tool.help());         // Markdown help document

const result = tool.executeSync('echo hello');
console.log(result.stdout);       // hello\n

Constructor#

new BashTool(options?: BashOptions): BashTool

name#

name: string

Tool name.

shortDescription#

shortDescription: string

Short description.

version#

version: string

Tool version.

addBuiltin#

bashTool.addBuiltin(name: string, callback: BuiltinCallback): void

Register a JS callback as a custom builtin. See Bash.addBuiltin.

appendFile#

bashTool.appendFile(path: string, content: string): void

Append content to a file.

cancel#

bashTool.cancel(): void

Cancel the currently running execution.

chmod#

bashTool.chmod(path: string, mode: number): void

Change file permissions (octal mode, e.g. 0o755).

clearCancel#

bashTool.clearCancel(): void

Clear the cancellation flag so subsequent executions proceed normally.

Call this after cancel() once the in-flight execution has finished and you want to reuse the same instance without discarding shell or VFS state.

description#

bashTool.description(): string

Token-efficient tool description.

execute#

bashTool.execute(commands: string, options?: ExecuteOptions): Promise<ExecResult>

Execute bash commands asynchronously, returning a Promise.

If onOutput is provided, it must be synchronous; Promise-returning handlers are rejected. Do not re-enter the same instance from onOutput via execute*, readFile, fs(), etc.

executeOrThrow#

bashTool.executeOrThrow(commands: string, options?: ExecuteOptions): Promise<ExecResult>

Execute bash commands asynchronously. Throws BashError on non-zero exit.

executeSync#

bashTool.executeSync(commands: string, options?: ExecuteOptions): ExecResult

Execute bash commands synchronously and return the result.

If onOutput is provided, it must be synchronous; Promise-returning handlers are rejected. Do not re-enter the same instance from onOutput via execute*, readFile, fs(), etc.

executeSyncOrThrow#

bashTool.executeSyncOrThrow(commands: string, options?: ExecuteOptions): ExecResult

Execute bash commands synchronously. Throws BashError on non-zero exit.

exists#

bashTool.exists(path: string): boolean

Check whether a path exists in the virtual filesystem.

fs#

bashTool.fs(): FileSystem

Get a FileSystem handle for direct VFS operations.

glob#

bashTool.glob(pattern: string): string[]

Find files matching a name pattern. Returns absolute paths.

help#

bashTool.help(): string

Markdown help document.

inputSchema#

bashTool.inputSchema(): string

JSON input schema as string.

ls#

bashTool.ls(path?: string): string[]

List entry names in a directory. Returns empty array if directory does not exist.

mkdir#

bashTool.mkdir(path: string, recursive?: boolean): void

Create a directory. If recursive is true, creates parents as needed.

mount#

bashTool.mount(vfsPath: string, fs: FileSystem): void

Mount either a host directory or a FileSystem into the VFS.

outputSchema#

bashTool.outputSchema(): string

JSON output schema as string.

readDir#

bashTool.readDir(path: string): ({ metadata: { created: number; fileType: string; mode: number; modified: number; size: number }; name: string })[]

List directory entries with metadata.

readFile#

bashTool.readFile(path: string): string

Read file contents from the virtual filesystem. Throws BashError if the file does not exist.

bashTool.readLink(path: string): string

Read the target of a symbolic link.

remove#

bashTool.remove(path: string, recursive?: boolean): void

Remove a file or directory. If recursive is true, removes contents.

removeBuiltin#

bashTool.removeBuiltin(name: string): void

Remove a previously registered custom builtin.

reset#

bashTool.reset(): void

Reset interpreter to fresh state, preserving configuration.

restoreSnapshot#

bashTool.restoreSnapshot(data: Uint8Array, options: SnapshotOptions & { hmacKey: Uint8Array }): void

Restore interpreter state from an HMAC-authenticated snapshot. Preserves current configuration (limits, identity) but replaces shell state and VFS contents.

restoreSnapshotKeyed#

bashTool.restoreSnapshotKeyed(data: Uint8Array, key: Uint8Array): void

Restore interpreter state from a HMAC-protected snapshot.

shellState#

bashTool.shellState(): ShellState

Capture a lightweight snapshot of shell state (variables, env, cwd, arrays, aliases, traps) for inspection — e.g. prompt rendering or debugging. Function definitions are omitted; use snapshot() for full state capture/restore.

snapshot#

bashTool.snapshot(options: SnapshotOptions & { hmacKey: Uint8Array }): Uint8Array

Serialize interpreter state (variables, VFS, counters) to an HMAC-authenticated Uint8Array. BashTool snapshots require hmacKey because they include tenant-controlled shell state, VFS contents, and counters.

snapshotKeyed#

bashTool.snapshotKeyed(key: Uint8Array, options?: SnapshotOptions): Uint8Array

Serialize interpreter state with HMAC-SHA256 using a caller-provided key.

stat#

bashTool.stat(path: string): { created: number; fileType: string; mode: number; modified: number; size: number }

Get metadata for a path (fileType, size, mode, timestamps).

bashTool.symlink(target: string, link: string): void

Create a symbolic link pointing to target.

systemPrompt#

bashTool.systemPrompt(): string

Compact system prompt for orchestration.

unmount#

bashTool.unmount(vfsPath: string): void

Unmount a previously mounted filesystem.

writeFile#

bashTool.writeFile(path: string, content: string): void

Write content to a file in the virtual filesystem. Creates parent directories as needed.

create#

BashTool.create(options?: BashOptions): Promise<BashTool>

Create a BashTool instance with support for async file providers.

fromSnapshot#

BashTool.fromSnapshot(data: Uint8Array, options: undefined | BashOptions, snapshotOptions: SnapshotOptions & { hmacKey: Uint8Array }): BashTool

Create a new BashTool instance from an HMAC-authenticated snapshot.

Any provided Bash options are applied before restoring the snapshot so limits and identity settings survive round-trips.

fromSnapshotKeyed#

BashTool.fromSnapshotKeyed(data: Uint8Array, key: Uint8Array, options?: BashOptions): BashTool

Create a new BashTool instance from a HMAC-protected snapshot.

ScriptedTool#

Compose JS callbacks as bash builtins for multi-tool orchestration.

Each registered tool becomes a bash builtin command. An LLM (or user) writes a single bash script that pipes, loops, and branches across all tools.

import { ScriptedTool } from '@everruns/bashkit';

const tool = new ScriptedTool({ name: "api" });
tool.addTool("greet", "Greet user",
  (params) => `hello ${params.name ?? "world"}\n`
);
const result = tool.executeSync("greet --name Alice");
console.log(result.stdout); // hello Alice\n

Constructor#

new ScriptedTool(options: ScriptedToolOptions): ScriptedTool

name#

name: string

Tool name.

shortDescription#

shortDescription: string

Short description.

version#

version: string

Tool version.

addTool#

scriptedTool.addTool(name: string, description: string, callback: ToolCallback, schema?: Record<string, unknown>): void

Register a tool command.

description#

scriptedTool.description(): string

Token-efficient tool description.

env#

scriptedTool.env(key: string, value: string): void

Add an environment variable visible inside scripts.

execute#

scriptedTool.execute(commands: string): Promise<ExecResult>

Execute a bash script asynchronously, returning a Promise.

This is the recommended execution method for ScriptedTool since tool callbacks require the Node.js event loop to be running.

executeOrThrow#

scriptedTool.executeOrThrow(commands: string): Promise<ExecResult>

Execute asynchronously. Throws BashError on non-zero exit.

executeSync#

scriptedTool.executeSync(commands: string): ExecResult

Execute a bash script synchronously.

Note: ScriptedTool callbacks run asynchronously via Node’s event loop. If a registered tool is invoked, this method returns a non-zero result instead of queueing a callback that would deadlock. Use execute() (async) for scripts that call registered tools. Only use this for scripts that don’t invoke any registered tools (e.g., pure bash).

executeSyncOrThrow#

scriptedTool.executeSyncOrThrow(commands: string): ExecResult

Execute synchronously. Throws BashError on non-zero exit.

Same caveats as executeSync() — throws when a registered tool would require the blocked Node event loop. Use executeOrThrow() instead.

help#

scriptedTool.help(): string

Markdown help document.

inputSchema#

scriptedTool.inputSchema(): string

JSON input schema as string.

outputSchema#

scriptedTool.outputSchema(): string

JSON output schema as string.

systemPrompt#

scriptedTool.systemPrompt(): string

Compact system prompt for orchestration.

toolCount#

scriptedTool.toolCount(): number

Number of registered tools.

FileSystem#

Constructor#

new FileSystem(): FileSystem

appendFile#

fileSystem.appendFile(path: string, content: string): void

chmod#

fileSystem.chmod(path: string, mode: number): void

copy#

fileSystem.copy(fromPath: string, toPath: string): void

exists#

fileSystem.exists(path: string): boolean

mkdir#

fileSystem.mkdir(path: string, recursive?: boolean): void

readDir#

fileSystem.readDir(path: string): ({ metadata: { created: number; fileType: string; mode: number; modified: number; size: number }; name: string })[]

readFile#

fileSystem.readFile(path: string): string
fileSystem.readLink(path: string): string

remove#

fileSystem.remove(path: string, recursive?: boolean): void

rename#

fileSystem.rename(fromPath: string, toPath: string): void

stat#

fileSystem.stat(path: string): { created: number; fileType: string; mode: number; modified: number; size: number }
fileSystem.symlink(target: string, link: string): void

toExternal#

fileSystem.toExternal(): unknown

writeFile#

fileSystem.writeFile(path: string, content: string): void

fromExternal#

FileSystem.fromExternal(external: unknown): FileSystem

fromNative#

FileSystem.fromNative(nativeFs: any): FileSystem

real#

FileSystem.real(hostPath: string, options: FileSystemRealOptions): FileSystem

BashError#

Error thrown when a bash command execution fails.

Properties#

  • exitCodenumber
  • stderrstring

Constructor#

new BashError(result: ExecResult): BashError

display#

bashError.display(): string

getVersion()#

getVersion(): string

Get the bashkit version string.

BashOptions#

Options for creating a Bash or BashTool instance.

Fields#

  • allowedMountPaths?string[]

    Allowlist of host path prefixes permitted for real filesystem mounts.

    Required for mounts and runtime mount() APIs. Mount targets must resolve under one of these prefixes; otherwise the call is rejected.

  • customBuiltins?Record<string, BuiltinCallback>

    Custom JS callbacks registered as bash builtins.

    Each entry becomes a bash command that shares the instance’s VFS — files created by the callback persist across execute() calls. Callbacks can be sync (string return) or async (Promise<string>); exceptions surface as stderr with exit code 1.

    Equivalent to calling addBuiltin(name, cb) for each entry. Survives reset(); not preserved through snapshot()/restoreSnapshot() — pass the option again after restoring.

    Override precedence: shell function > POSIX special builtin > custom builtin > baked-in builtin > PATH.

  • cwd?string

    Initial working directory for the shell.

    Sets the starting cwd directly instead of running a leading cd "${cwd}" command, avoiding the parse/exec overhead.

  • env?Record<string, string>

    Initial environment variables, applied before execution.

    Scripts see these immediately without an export prelude. Keys are variable names, values are their string values.

  • externalFunctions?string[]

    Names of external functions callable from embedded Python code.

    These function names become available as Python builtins within the embedded interpreter. When called, they invoke the external handler.

  • files?Record<string, FileValue>

    Files to mount in the virtual filesystem. Keys are absolute paths, values are content strings or lazy providers.

    String values are mounted immediately. Function values are called on first read and the result is cached.

  • hostname?string

  • maxCommands?number

  • maxInputBytes?number

    Maximum script input size in UTF-8 bytes.

    Async execute validates this before entering the per-instance queue so oversized calls cannot wait while retaining large command strings.

  • maxLoopIterations?number

  • maxMemory?number

    Maximum interpreter memory in bytes (variables, arrays, functions).

    Caps the total byte budget for variable storage and function bodies. Prevents OOM from untrusted input such as exponential string doubling.

  • maxTotalLoopIterations?number

  • mounts?({ path: string; root: string; writable?: boolean })[]

    Real filesystem mounts. Each mount maps a host directory into the VFS.

  • network?NetworkOptions

    Outbound network configuration. When set, enables curl/wget restricted to the configured allowlist, with optional transparent credential injection. Omitted = network disabled (no curl/wget).

    Must specify either allow (list of URL patterns) or allowAll: true, not both. blockPrivateIps defaults to true.

  • python?boolean

    Enable embedded Python execution (python/python3 builtins).

    When true, bash scripts can use python -c '...' or python3 script.py to run Python code within the sandbox.

  • sqlite?boolean

    Enable the embedded SQLite builtin (sqlite/sqlite3).

    Backed by Turso. When true, the binding both registers the builtin and injects BASHKIT_ALLOW_INPROCESS_SQLITE=1 so the runtime gate is satisfied. Defaults to false. Default SqliteLimits apply: 4 MiB script cap, 256 MiB DB cap, 30 s wall-clock budget, resource-affecting PRAGMAs and ATTACH/DETACH rejected.

  • timeoutMs?number

    Execution timeout in milliseconds.

    When set, commands that exceed this duration are aborted with exit code 124 (matching the bash timeout convention).

  • username?string

BuiltinContext#

Execution context passed to a custom builtin registered via customBuiltins or addBuiltin.

name, argv, stdin, env, and cwd are snapshots of the shell state at invocation time; fs is a live handle to the interpreter’s virtual filesystem.

Fields#

  • argvstring[]

    Arguments (not including the command name).

  • cwdstring

    Current working directory.

  • envRecord<string, string>

    Environment variables visible at the call site.

  • fsFileSystem

    Live handle to the interpreter’s virtual filesystem — the same VFS the executing script sees. Reads observe earlier script writes and writes are visible to subsequent commands. Inherits mounts and read-only configuration.

  • namestring

    The command name as invoked.

  • stdinnull | string

    Piped input, or null if there is no pipe.

CredentialHeader#

A single HTTP header (name/value pair) for credential injection.

Fields#

  • namestring
  • valuestring

ExecResult#

Result from executing bash commands.

Fields#

  • error?string

  • exitCodenumber

  • finalEnv?Record<string, string>

  • stderrstring

  • stderrTruncatedboolean

  • stdoutstring

  • stdoutTruncatedboolean

  • successboolean

    True if exit_code is 0.

ExecuteOptions#

Fields#

  • onOutput?OnOutput

    Live chunk callback. Must be synchronous.

    Limitation: do not call back into the same Bash / BashTool instance from this handler (execute*, readFile, fs(), etc.). The current binding rejects same-instance re-entry to avoid deadlocks and runtime panics.

  • signal?AbortSignal

FileSystemRealOptions#

Standalone filesystem handle for direct VFS operations and native addon interop.

Fields#

  • allowedMountPathsstring[]
  • writable?boolean

NetworkCredential#

Credential injected into outbound HTTP requests matching pattern.

kind selects the shape: "bearer" (requires token), "header" (requires name + value), or "headers" (requires headers). Scripts never see the secret — it is attached on the wire only.

Fields#

  • headers?CredentialHeader[]

    Header list (for kind: "headers").

  • kindstring

    One of "bearer", "header", "headers".

  • name?string

    Header name (for kind: "header").

  • patternstring

    URL pattern the credential applies to (e.g. https://api.example.com/**).

  • token?string

    Bearer token (for kind: "bearer").

  • value?string

    Header value (for kind: "header").

NetworkCredentialPlaceholder#

Placeholder-mode credential injection: env is set to an opaque placeholder value visible to scripts; outbound requests matching pattern have the placeholder replaced with the real credential.

Fields#

  • envstring

    Environment variable that receives the placeholder value.

  • headers?CredentialHeader[]

    Header list (for kind: "headers").

  • kindstring

    One of "bearer", "header", "headers".

  • name?string

    Header name (for kind: "header").

  • patternstring

    URL pattern the credential applies to.

  • token?string

    Bearer token (for kind: "bearer").

  • value?string

    Header value (for kind: "header").

NetworkOptions#

Outbound network configuration (enables curl/wget).

Must specify either allow (list of URL patterns) or allowAll: true, not both. blockPrivateIps defaults to true.

Fields#

  • allow?string[]

    URL patterns permitted for outbound requests.

  • allowAll?boolean

    Allow all outbound requests (mutually exclusive with allow).

  • blockPrivateIps?boolean

    Block requests resolving to private/loopback IPs (default: true).

  • credentialPlaceholders?NetworkCredentialPlaceholder[]

    Placeholder-mode credential injection (see type docs).

  • credentials?NetworkCredential[]

    Credentials injected transparently into matching requests.

OutputChunk#

Fields#

  • stderrstring
  • stdoutstring

ScriptedToolOptions#

Options for creating a ScriptedTool instance.

Fields#

  • maxCommands?number
  • maxLoopIterations?number
  • namestring
  • shortDescription?string

ShellState#

Lightweight snapshot of shell state for inspection (prompt rendering, debugging). Mirrors the Python binding’s ShellState; omits function definitions (use snapshot() for full state capture/restore).

Fields#

  • aliasesRecord<string, string>

    Shell aliases.

  • arraysRecord<string, Record<string, string>>

    Indexed arrays: name → { index (as string) → value }. Sparse indices are preserved, hence a map rather than a dense JS array.

  • assocArraysRecord<string, Record<string, string>>

    Associative arrays: name → { key → value }.

  • cwdstring

    Current working directory.

  • envRecord<string, string>

    Environment variables.

  • lastExitCodenumber

    Exit code of the last executed command.

  • trapsRecord<string, string>

    Trap handlers keyed by signal/condition name.

  • variablesRecord<string, string>

    Shell variables (non-exported).

SnapshotOptions#

Fields#

  • excludeFilesystem?boolean

  • excludeFunctions?boolean

  • hmacKey?Uint8Array<ArrayBufferLike>

    Secret key used to authenticate snapshot bytes with HMAC-SHA256. Required for BashTool snapshots because tool snapshots may cross tenant or network trust boundaries. Recommended for any snapshot accepted from users, shared storage, or remote callers.

BuiltinCallback#

Callback signature for custom builtins. Return the stdout to emit. Both sync (string) and async (Promise<string>) returns are supported. Exceptions / rejections surface as stderr with exit code 1.

type BuiltinCallback = (ctx: BuiltinContext) => string | Promise<string>

FileValue#

A file value: either a string, a sync function returning a string, or an async function returning a Promise.

Function values are resolved lazily on first read and cached.

type FileValue = string | () => string | () => Promise<string>

OnOutput#

type OnOutput = (chunk: OutputChunk) => void

ToolCallback#

Callback type for ScriptedTool tool commands.

Receives parsed --key value flags as params and optional piped input as stdin. Must return a string.

type ToolCallback = (params: Record<string, unknown>, stdin: string | null) => string

Framework integrations#

@everruns/bashkit/langchain#

LangChain.js integration for Bashkit.

Provides LangChain-compatible tools wrapping BashTool and ScriptedTool for use with LangChain agents and chains.

import { createBashTool, createScriptedTool } from '@everruns/bashkit/langchain';

// Basic bash tool
const tool = createBashTool();
const result = await tool.invoke({ commands: "echo hello" });

// Scripted tool
import { ScriptedTool } from '@everruns/bashkit';
const st = new ScriptedTool({ name: "api" });
st.addTool("greet", "Greet user", (p) => `hello ${p.name}\n`);
const langchainTool = createScriptedTool(st);

createBashTool()#

createBashTool(options?: Omit<BashOptions, "files">): DynamicStructuredTool

Create a LangChain-compatible Bashkit tool.

Returns a DynamicStructuredTool that can be passed directly to LangChain agents like createReactAgent.

import { createBashTool } from '@everruns/bashkit/langchain';
import { createReactAgent } from '@langchain/langgraph/prebuilt';

const tool = createBashTool({ username: "agent" });
const agent = createReactAgent({ llm: model, tools: [tool] });

createScriptedTool()#

createScriptedTool(scriptedTool: ScriptedTool): DynamicStructuredTool

Create a LangChain-compatible tool from a configured ScriptedTool.

The ScriptedTool should already have tools registered via addTool().

import { ScriptedTool } from '@everruns/bashkit';
import { createScriptedTool } from '@everruns/bashkit/langchain';

const st = new ScriptedTool({ name: "api" });
st.addTool("get_data", "Fetch data", (p) => JSON.stringify({ id: p.id }));
const tool = createScriptedTool(st);

@everruns/bashkit/anthropic#

Anthropic SDK adapter for Bashkit.

Returns a ready-to-use { system, tools, handler } object for Claude’s messages.create() API, eliminating boilerplate for tool integration.

import Anthropic from "@anthropic-ai/sdk";
import { bashTool } from "@everruns/bashkit/anthropic";

const client = new Anthropic();
const bash = bashTool();

const response = await client.messages.create({
  model: "claude-haiku-4-5-20251001",
  max_tokens: 1024,
  system: bash.system,
  tools: bash.tools,
  messages: [{ role: "user", content: "List files in /home" }],
});

for (const block of response.content) {
  if (block.type === "tool_use") {
    const result = await bash.handler(block);
    // send result back as tool_result
  }
}

bashTool()#

bashTool(options?: BashToolOptions): BashToolAdapter

Create a bash tool adapter for the Anthropic SDK.

Returns { system, tools, handler } that plugs directly into client.messages.create().

import Anthropic from "@anthropic-ai/sdk";
import { bashTool } from "@everruns/bashkit/anthropic";

const client = new Anthropic();
const bash = bashTool({ files: { "/data.txt": "hello" } });

const response = await client.messages.create({
  model: "claude-haiku-4-5-20251001",
  max_tokens: 256,
  system: bash.system,
  tools: bash.tools,
  messages: [{ role: "user", content: "Read /data.txt" }],
});

BashToolAdapter#

Return value of bashTool().

Fields#

  • bashBashTool

    The underlying BashTool instance for direct access.

  • handler(toolUse: ToolUseBlock, options: HandlerOptions) => Promise<ToolResult>

    Handler that executes a tool_use block and returns a tool_result.

    Pass an AbortSignal via the options parameter to cancel execution when the framework aborts the tool call:

    const controller = new AbortController();
    const result = await bash.handler(block, { signal: controller.signal });
  • systemstring

    System prompt describing bash capabilities and constraints.

  • toolsAnthropicTool[]

    Tool definitions for Anthropic’s messages.create() API.

BashToolOptions#

Options for configuring the bash tool adapter.

Fields#

  • allowedMountPaths?string[]

    Allowlist of host path prefixes permitted for real filesystem mounts.

    Required for mounts and runtime mount() APIs. Mount targets must resolve under one of these prefixes; otherwise the call is rejected.

  • customBuiltins?Record<string, BuiltinCallback>

    Custom JS callbacks registered as bash builtins.

    Each entry becomes a bash command that shares the instance’s VFS — files created by the callback persist across execute() calls. Callbacks can be sync (string return) or async (Promise<string>); exceptions surface as stderr with exit code 1.

    Equivalent to calling addBuiltin(name, cb) for each entry. Survives reset(); not preserved through snapshot()/restoreSnapshot() — pass the option again after restoring.

    Override precedence: shell function > POSIX special builtin > custom builtin > baked-in builtin > PATH.

  • cwd?string

    Initial working directory for the shell.

    Sets the starting cwd directly instead of running a leading cd "${cwd}" command, avoiding the parse/exec overhead.

  • env?Record<string, string>

    Initial environment variables, applied before execution.

    Scripts see these immediately without an export prelude. Keys are variable names, values are their string values.

  • externalFunctions?string[]

    Names of external functions callable from embedded Python code.

    These function names become available as Python builtins within the embedded interpreter. When called, they invoke the external handler.

  • files?Record<string, string>

    Pre-populate VFS files. Keys are absolute paths, values are file contents.

  • hostname?string

  • maxCommands?number

  • maxInputBytes?number

    Maximum script input size in UTF-8 bytes.

    Async execute validates this before entering the per-instance queue so oversized calls cannot wait while retaining large command strings.

  • maxLoopIterations?number

  • maxMemory?number

    Maximum interpreter memory in bytes (variables, arrays, functions).

    Caps the total byte budget for variable storage and function bodies. Prevents OOM from untrusted input such as exponential string doubling.

  • maxOutputLength?number

    Maximum output length in characters (default: 100000).

    Output exceeding this limit is truncated with a [truncated] marker. Prevents context window flooding when scripts produce large output.

  • maxTotalLoopIterations?number

  • mounts?({ path: string; root: string; writable?: boolean })[]

    Real filesystem mounts. Each mount maps a host directory into the VFS.

  • network?NetworkOptions

    Outbound network configuration. When set, enables curl/wget restricted to the configured allowlist, with optional transparent credential injection. Omitted = network disabled (no curl/wget).

    Must specify either allow (list of URL patterns) or allowAll: true, not both. blockPrivateIps defaults to true.

  • python?boolean

    Enable embedded Python execution (python/python3 builtins).

    When true, bash scripts can use python -c '...' or python3 script.py to run Python code within the sandbox.

  • sanitizeOutput?boolean

    Wrap tool output in XML boundary markers (default: false).

    When enabled, output is wrapped in <tool_output>...</tool_output> tags to help LLMs distinguish tool output data from instructions, reducing prompt injection risk via tool output.

    Security note: This is a defense-in-depth measure. Tool output from untrusted sources (files, network) may contain text that attempts to manipulate LLM behavior. Boundary markers help but do not eliminate this risk.

  • sqlite?boolean

    Enable the embedded SQLite builtin (sqlite/sqlite3).

    Backed by Turso. When true, the binding both registers the builtin and injects BASHKIT_ALLOW_INPROCESS_SQLITE=1 so the runtime gate is satisfied. Defaults to false. Default SqliteLimits apply: 4 MiB script cap, 256 MiB DB cap, 30 s wall-clock budget, resource-affecting PRAGMAs and ATTACH/DETACH rejected.

  • timeoutMs?number

    Execution timeout in milliseconds.

    When set, this is passed to the underlying BashTool as timeoutMs. Commands exceeding this duration are aborted with exit code 124. Framework-level timeouts can be propagated here to ensure bashkit stops execution when the framework cancels a tool call.

  • username?string

HandlerOptions#

Options for handler invocation.

Fields#

  • signal?AbortSignal

    AbortSignal to cancel execution when the framework aborts the tool call.

ToolResult#

Result from handling a tool call, ready to send back as tool_result.

Fields#

  • contentstring
  • is_error?boolean
  • tool_use_idstring
  • type"tool_result"

@everruns/bashkit/openai#

OpenAI SDK adapter for Bashkit.

Returns a ready-to-use { system, tools, handler } object for OpenAI’s chat.completions.create() API.

import OpenAI from "openai";
import { bashTool } from "@everruns/bashkit/openai";

const client = new OpenAI();
const bash = bashTool();

const response = await client.chat.completions.create({
  model: "gpt-4.1-mini",
  tools: bash.tools,
  messages: [
    { role: "system", content: bash.system },
    { role: "user", content: "Create a file with today's date" },
  ],
});

for (const call of response.choices[0].message.tool_calls ?? []) {
  const result = await bash.handler(call);
  // send result back as tool message
}

bashTool()#

bashTool(options?: BashToolOptions): BashToolAdapter

Create a bash tool adapter for the OpenAI SDK.

Returns { system, tools, handler } that plugs directly into client.chat.completions.create().

import OpenAI from "openai";
import { bashTool } from "@everruns/bashkit/openai";

const client = new OpenAI();
const bash = bashTool({ files: { "/data.txt": "42" } });

const response = await client.chat.completions.create({
  model: "gpt-4.1-nano",
  tools: bash.tools,
  messages: [
    { role: "system", content: bash.system },
    { role: "user", content: "What's in /data.txt?" },
  ],
});

BashToolAdapter#

Return value of bashTool().

Fields#

  • bashBashTool

    The underlying BashTool instance for direct access.

  • handler(toolCall: OpenAIToolCall, options: HandlerOptions) => Promise<ToolResult>

    Handler that executes a tool_call and returns a tool message.

    Pass an AbortSignal via the options parameter to cancel execution when the framework aborts the tool call:

    const controller = new AbortController();
    const result = await bash.handler(call, { signal: controller.signal });
  • systemstring

    System prompt describing bash capabilities and constraints.

  • toolsOpenAITool[]

    Tool definitions for OpenAI’s chat.completions.create() API.

BashToolOptions#

Options for configuring the bash tool adapter.

Fields#

  • allowedMountPaths?string[]

    Allowlist of host path prefixes permitted for real filesystem mounts.

    Required for mounts and runtime mount() APIs. Mount targets must resolve under one of these prefixes; otherwise the call is rejected.

  • customBuiltins?Record<string, BuiltinCallback>

    Custom JS callbacks registered as bash builtins.

    Each entry becomes a bash command that shares the instance’s VFS — files created by the callback persist across execute() calls. Callbacks can be sync (string return) or async (Promise<string>); exceptions surface as stderr with exit code 1.

    Equivalent to calling addBuiltin(name, cb) for each entry. Survives reset(); not preserved through snapshot()/restoreSnapshot() — pass the option again after restoring.

    Override precedence: shell function > POSIX special builtin > custom builtin > baked-in builtin > PATH.

  • cwd?string

    Initial working directory for the shell.

    Sets the starting cwd directly instead of running a leading cd "${cwd}" command, avoiding the parse/exec overhead.

  • env?Record<string, string>

    Initial environment variables, applied before execution.

    Scripts see these immediately without an export prelude. Keys are variable names, values are their string values.

  • externalFunctions?string[]

    Names of external functions callable from embedded Python code.

    These function names become available as Python builtins within the embedded interpreter. When called, they invoke the external handler.

  • files?Record<string, string>

    Pre-populate VFS files. Keys are absolute paths, values are file contents.

  • hostname?string

  • maxCommands?number

  • maxInputBytes?number

    Maximum script input size in UTF-8 bytes.

    Async execute validates this before entering the per-instance queue so oversized calls cannot wait while retaining large command strings.

  • maxLoopIterations?number

  • maxMemory?number

    Maximum interpreter memory in bytes (variables, arrays, functions).

    Caps the total byte budget for variable storage and function bodies. Prevents OOM from untrusted input such as exponential string doubling.

  • maxOutputLength?number

    Maximum output length in characters (default: 100000).

    Output exceeding this limit is truncated with a [truncated] marker. Prevents context window flooding when scripts produce large output.

  • maxTotalLoopIterations?number

  • mounts?({ path: string; root: string; writable?: boolean })[]

    Real filesystem mounts. Each mount maps a host directory into the VFS.

  • network?NetworkOptions

    Outbound network configuration. When set, enables curl/wget restricted to the configured allowlist, with optional transparent credential injection. Omitted = network disabled (no curl/wget).

    Must specify either allow (list of URL patterns) or allowAll: true, not both. blockPrivateIps defaults to true.

  • python?boolean

    Enable embedded Python execution (python/python3 builtins).

    When true, bash scripts can use python -c '...' or python3 script.py to run Python code within the sandbox.

  • sanitizeOutput?boolean

    Wrap tool output in XML boundary markers (default: false).

    When enabled, output is wrapped in <tool_output>...</tool_output> tags to help LLMs distinguish tool output data from instructions, reducing prompt injection risk via tool output.

  • sqlite?boolean

    Enable the embedded SQLite builtin (sqlite/sqlite3).

    Backed by Turso. When true, the binding both registers the builtin and injects BASHKIT_ALLOW_INPROCESS_SQLITE=1 so the runtime gate is satisfied. Defaults to false. Default SqliteLimits apply: 4 MiB script cap, 256 MiB DB cap, 30 s wall-clock budget, resource-affecting PRAGMAs and ATTACH/DETACH rejected.

  • timeoutMs?number

    Execution timeout in milliseconds.

    When set, this is passed to the underlying BashTool as timeoutMs. Commands exceeding this duration are aborted with exit code 124. Framework-level timeouts can be propagated here to ensure bashkit stops execution when the framework cancels a tool call.

  • username?string

HandlerOptions#

Options for handler invocation.

Fields#

  • signal?AbortSignal

    AbortSignal to cancel execution when the framework aborts the tool call.

ToolResult#

Result from handling a tool call, ready to send as a tool message.

Fields#

  • contentstring
  • role"tool"
  • tool_call_idstring

@everruns/bashkit/ai#

Vercel AI SDK adapter for Bashkit.

Returns { system, tools } that plugs directly into generateText() / streamText() with zero boilerplate. Tools include built-in execute functions, so the AI SDK auto-executes tool calls in its maxSteps loop.

import { generateText } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import { bashTool } from "@everruns/bashkit/ai";

const bash = bashTool({
  files: { "/home/user/data.csv": "name,age\nAlice,30\nBob,25" },
});

const { text } = await generateText({
  model: anthropic("claude-haiku-4-5-20251001"),
  system: bash.system,
  tools: bash.tools,
  maxSteps: 5,
  prompt: "Analyze the CSV file and tell me the average age",
});

bashTool()#

bashTool(options?: BashToolOptions): BashToolAdapter

Create a bash tool adapter for the Vercel AI SDK.

Returns { system, tools } that plugs directly into generateText() or streamText(). The tool includes a built-in execute function, so tool calls are auto-executed when using maxSteps.

import { generateText } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import { bashTool } from "@everruns/bashkit/ai";

const bash = bashTool({ files: { "/test.txt": "hello world" } });

const { text } = await generateText({
  model: anthropic("claude-haiku-4-5-20251001"),
  system: bash.system,
  tools: bash.tools,
  maxSteps: 3,
  prompt: "Read /test.txt and tell me what it says",
});

BashToolAdapter#

Return value of bashTool().

Fields#

  • bashBashTool

    The underlying BashTool instance for direct access.

  • systemstring

    System prompt describing bash capabilities and constraints.

  • toolsRecord<string, AiTool>

    Tool definitions for Vercel AI SDK’s generateText/streamText.

BashToolOptions#

Options for configuring the bash tool adapter.

Fields#

  • allowedMountPaths?string[]

    Allowlist of host path prefixes permitted for real filesystem mounts.

    Required for mounts and runtime mount() APIs. Mount targets must resolve under one of these prefixes; otherwise the call is rejected.

  • customBuiltins?Record<string, BuiltinCallback>

    Custom JS callbacks registered as bash builtins.

    Each entry becomes a bash command that shares the instance’s VFS — files created by the callback persist across execute() calls. Callbacks can be sync (string return) or async (Promise<string>); exceptions surface as stderr with exit code 1.

    Equivalent to calling addBuiltin(name, cb) for each entry. Survives reset(); not preserved through snapshot()/restoreSnapshot() — pass the option again after restoring.

    Override precedence: shell function > POSIX special builtin > custom builtin > baked-in builtin > PATH.

  • cwd?string

    Initial working directory for the shell.

    Sets the starting cwd directly instead of running a leading cd "${cwd}" command, avoiding the parse/exec overhead.

  • env?Record<string, string>

    Initial environment variables, applied before execution.

    Scripts see these immediately without an export prelude. Keys are variable names, values are their string values.

  • externalFunctions?string[]

    Names of external functions callable from embedded Python code.

    These function names become available as Python builtins within the embedded interpreter. When called, they invoke the external handler.

  • files?Record<string, string>

    Pre-populate VFS files. Keys are absolute paths, values are file contents.

  • hostname?string

  • maxCommands?number

  • maxInputBytes?number

    Maximum script input size in UTF-8 bytes.

    Async execute validates this before entering the per-instance queue so oversized calls cannot wait while retaining large command strings.

  • maxLoopIterations?number

  • maxMemory?number

    Maximum interpreter memory in bytes (variables, arrays, functions).

    Caps the total byte budget for variable storage and function bodies. Prevents OOM from untrusted input such as exponential string doubling.

  • maxTotalLoopIterations?number

  • mounts?({ path: string; root: string; writable?: boolean })[]

    Real filesystem mounts. Each mount maps a host directory into the VFS.

  • network?NetworkOptions

    Outbound network configuration. When set, enables curl/wget restricted to the configured allowlist, with optional transparent credential injection. Omitted = network disabled (no curl/wget).

    Must specify either allow (list of URL patterns) or allowAll: true, not both. blockPrivateIps defaults to true.

  • python?boolean

    Enable embedded Python execution (python/python3 builtins).

    When true, bash scripts can use python -c '...' or python3 script.py to run Python code within the sandbox.

  • sqlite?boolean

    Enable the embedded SQLite builtin (sqlite/sqlite3).

    Backed by Turso. When true, the binding both registers the builtin and injects BASHKIT_ALLOW_INPROCESS_SQLITE=1 so the runtime gate is satisfied. Defaults to false. Default SqliteLimits apply: 4 MiB script cap, 256 MiB DB cap, 30 s wall-clock budget, resource-affecting PRAGMAs and ATTACH/DETACH rejected.

  • timeoutMs?number

    Execution timeout in milliseconds.

    When set, commands that exceed this duration are aborted with exit code 124 (matching the bash timeout convention).

  • username?string