Code Intelligence & Engines
ag-bash
AI-native bash interpreter, in TypeScript.
2 min read · 387 words
AI agents need deterministic, sandboxed shell execution for tool-calling. ag-bash is a bash interpreter implemented entirely in TypeScript that gives them exactly that — exposed as the @ag-bash/bash shell engine plus an MCP server and an agent terminal bridge.
It parses shell syntax with a Tree-sitter WASM grammar and executes against sandboxed WASM runtimes (CPython, QuickJS, SQLite3) instead of the host shell, enabling patterns like fork-speculation (try N approaches, keep the winner) and self-healing recovery. Built and bundled with esbuild (ESM + CJS); 5 green CI workflows including CodeQL and security fuzzing.
- In-process sandboxed execution, no host shell
- Tree-sitter WASM parser · WASM language runtimes
- MCP server · fork-speculation · self-healing
Systems + security breadth. 449 commits, 5 CI gates.
Architecture
Three packages ship from one pnpm monorepo at a synchronized version (currently 6.0.4): @ag-bash/bash (the core interpreter and its ExecutionPipeline), @ag-bash/mcp-server (a standalone MCP server exposing 70 tools over stdio, published to the MCP Registry as io.github.sairam0424/ag-bash), and @ag-bash/agent-bridge (the terminal UI bridge). Everything is TypeScript end to end — there is no Rust or native binding anywhere in the tree; the Tree-sitter grammar itself compiles to WASM rather than linking a native parser. The one binary the repo can't express in source is vendor/cpython-emscripten/python.wasm, the CPython WASM runtime, tracked via Git LFS — any CI job touching Python or the WASM suite has to check out with lfs: true or it runs against a 132-byte pointer file instead of the real interpreter.
How It Works
- A script string hits the Tree-sitter WASM grammar, which parses it into an AST — no shelling out to the host
/bin/shat any point. ASTCachekeys the parsed result with a 64-bit FNV-1a hash so a repeated script skips re-parsing entirely.- The AST flows through
ExecutionPipeline— the sole execution path since v6.0.0, when a 200+ line legacy inlineexec()code path was deleted outright. One stage,DestructiveStage, walks the AST looking forrm -rf /, fork bombs,$IFSobfuscation, and decode-pipe-to-shell patterns. - Execution itself dispatches in-process to the matching WASM runtime — CPython, QuickJS, or SQLite3 — sandboxed away from the host shell.
- Output streams back live through
execStream(), andbash.fork()/bash.speculate()can run N candidate command sequences concurrently and keep only the winner. - The MCP server and agent-bridge sit on top of this same pipeline, exposing it to agents over stdio or a terminal UI respectively.