bash-tool
v1.3.7
Published
Generic bash tool for AI agents, compatible with AI SDK
Maintainers
Readme
bash-tool
Generic bash tool for AI agents, compatible with AI SDK.
Installation
npm install bash-tool just-bashFor full VM support, install @vercel/sandbox or another sandbox product instead of just-bash.
Usage
import { createBashTool } from "bash-tool";
import { ToolLoopAgent, stepCountIs } from "ai";
const { tools } = await createBashTool({
files: {
"src/index.ts": "export const hello = 'world';",
"package.json": '{"name": "my-project"}',
},
});
const agent = new ToolLoopAgent({
model: yourModel,
tools,
// Or use just the bash tool as tools: {bash: tools.bash}
stopWhen: stepCountIs(20),
});
const result = await agent.generate({
prompt: "Analyze the project and create a summary report",
});Tools
The tools object contains three tools that can be used by AI agents:
bash
Execute bash commands in the sandbox environment. For analysis agents, this may be the only tool you need to give to the agent.
Input:
command(string): The bash command to execute
Returns:
stdout(string): Standard output from the commandstderr(string): Standard error from the commandexitCode(number): Exit code of the command
readFile
Read the contents of a file from the sandbox.
Input:
path(string): The path to the file to read
Returns:
content(string): The file contents
writeFile
Write content to a file in the sandbox. Creates parent directories if needed.
Input:
path(string): The path where the file should be writtencontent(string): The content to write to the file
Returns:
success(boolean):trueif the write succeeded
Advanced Usage
Upload a local directory
const { bash } = await createBashTool({
uploadDirectory: {
source: "./my-project",
include: "**/*.{ts,json}", // optional glob filter
},
});Use @vercel/sandbox for full VM
import { Sandbox } from "@vercel/sandbox";
const sandbox = await Sandbox.create();
// Files are written to ./workspace by default
const { tools } = await createBashTool({
sandbox,
files: { "index.ts": "console.log('hello');" },
});Persistent sandbox across serverless invocations
Use Sandbox.get to reconnect to an existing sandbox by ID:
import { Sandbox } from "@vercel/sandbox";
// First invocation: create sandbox and store the ID
const newSandbox = await Sandbox.create();
const sandboxId = newSandbox.sandboxId;
// Store sandboxId in database, session, or return to client
// Subsequent invocations: reconnect to existing sandbox
const existingSandbox = await Sandbox.get({ sandboxId });
const { tools } = await createBashTool({ sandbox: existingSandbox });
// All previous files and state are preservedUse a custom just-bash instance
import { Bash } from "just-bash";
const sandbox = new Bash({ cwd: "/app" });
const { tools } = await createBashTool({
sandbox,
destination: "/app",
});Intercept bash commands
const { tools } = await createBashTool({
onBeforeBashCall: ({ command }) => {
console.log("Running:", command);
// Optionally modify the command
if (command.includes("rm -rf")) {
return { command: "echo 'Blocked dangerous command'" };
}
},
onAfterBashCall: ({ command, result }) => {
console.log(`Exit code: ${result.exitCode}`);
// Optionally modify the result
return { result: { ...result, stdout: result.stdout.trim() } };
},
});Custom sandbox implementation
import { createBashTool, Sandbox } from "bash-tool";
const customSandbox: Sandbox = {
async executeCommand(command) {
// Your implementation here
return { stdout: "", stderr: "", exitCode: 0 };
},
async readFile(path) {
// Your implementation here
return "";
},
async writeFiles(files) {
// Your implementation here - files is Array<{path, content}>
},
};
const { tools } = await createBashTool({ sandbox: customSandbox });Skills (Experimental)
Skills are modular capabilities that extend agent functionality. Each skill is a directory containing a SKILL.md file with instructions and optional scripts.
import {
experimental_createSkillTool as createSkillTool,
createBashTool,
} from "bash-tool";
import { ToolLoopAgent } from "ai";
// Discover skills and get files to upload
const { loadSkill, files, instructions } = await createSkillTool({
skillsDirectory: "./skills",
});
// Create bash tool with skill files
const { tools } = await createBashTool({
files,
extraInstructions: instructions,
});
// Use both tools with an agent
const agent = new ToolLoopAgent({
model,
tools: { loadSkill, ...tools },
});Skill Directory Structure
skills/
├── csv/
│ ├── SKILL.md # Required: instructions with YAML frontmatter
│ ├── analyze.sh # Optional: scripts the agent can run
│ └── filter.sh
└── text/
├── SKILL.md
└── search.shSKILL.md Format
---
name: csv
description: Analyze and transform CSV files
---
# CSV Processing
Use `./skills/csv/analyze.sh <file>` to analyze a CSV file.How It Works
createSkillTooldiscovers skills and returns:loadSkill- Tool for the agent to load a skill's instructions on demandfiles- All skill files to pass tocreateBashToolinstructions- Extra instructions listing available skills
The agent sees skill names in the
loadSkilltool descriptionWhen the agent needs a skill, it calls
loadSkill("csv")to get detailed instructionsThe agent uses
bashto run scripts from./skills/csv/
AI Agent Instructions
For AI agents working with bash-tool, additional guidance is available in AGENTS.md:
cat node_modules/bash-tool/dist/AGENTS.mdLicense
MIT
