npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

bash-tool

v1.3.7

Published

Generic bash tool for AI agents, compatible with AI SDK

Readme

bash-tool

Generic bash tool for AI agents, compatible with AI SDK.

Installation

npm install bash-tool just-bash

For 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 command
  • stderr (string): Standard error from the command
  • exitCode (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 written
  • content (string): The content to write to the file

Returns:

  • success (boolean): true if 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 preserved

Use 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.sh

SKILL.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

  1. createSkillTool discovers skills and returns:

    • loadSkill - Tool for the agent to load a skill's instructions on demand
    • files - All skill files to pass to createBashTool
    • instructions - Extra instructions listing available skills
  2. The agent sees skill names in the loadSkill tool description

  3. When the agent needs a skill, it calls loadSkill("csv") to get detailed instructions

  4. The agent uses bash to 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.md

License

MIT