everruns/bashkit

Virtual Bash interpreter with a virtual file system for multi-tenant environments.

Bashkit is a Rust library that reimplements the bash shell from scratch inside a virtual sandbox, so you can run shell commands safely in-process without ever forking real processes. It's built specifically as a tool for LLM agents: an agent can execute bash commands, get streaming output, and have its state (files, variables, git repos, even Python/TypeScript/SQLite) isolated and resettable.

Key capabilities

  • No real OS access by default — all 167 built-in commands (echo, grep, tar, jq, etc.) are implemented in Rust and run against a virtual filesystem; no fork/exec, no network unless allowlisted.
  • Full shell semantics — POSIX-compliant, plus bashisms like arrays, [[ ]], process substitution, globs, here-docs.
  • Resource limits — cap command count, loop iterations, output size, etc.
  • LLM tool contract — BashTool exposes discovery metadata, a system prompt, and streaming output; analyze() statically inspects a script before running it so hosts can decide whether to ask the user for approval.
  • Virtual filesystem — in-memory, overlay, and mountable layers; optional real-fs backend.
  • Extensibility — register custom builtins in Rust, JS, or Python.
  • Embedded language runtimes (experimental) — Python (Monty or real CPython in WASM), TypeScript (ZapCode), SQLite (Turso), virtual git.
  • Snapshots — serialize shell state + VFS to bytes for checkpoints/resume.
  • Bindings — Python (PyO3) and JS/TS (NAPI-RS), plus a CLI.

How it works Every command runs against an in-process interpreter with its own virtual filesystem and environment. No host processes are spawned; even background jobs and pipelines are emulated. The VFS makes it easy to give an agent a disposable workspace.

Use cases

  • Giving LLM agents a bash tool with hard isolation and permission checks.
  • Multi-tenant execution of user-provided shell code.
  • Training/evals — measuring how well models use bash (the project includes an eval suite with published results).

Quick start

use bashkit::Bash;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let mut bash = Bash::new();
    let result = bash.exec("echo hello world").await?;
    println!("{}", result.stdout); // "hello world\n"
    Ok(())
}

Install with cargo add bashkit (optional features: git, python, cpython, typescript, sqlite, realfs). A separate crate bashkit-scripted-tool helps compose tool definitions.

Related

  • Project
  • Project
  • Project
  • Project