
Research
/Security News
5 Malicious Rust Crates Posed as Time Utilities to Exfiltrate .env Files
Published late February to early March 2026, these crates impersonate timeapi.io and POST .env secrets to a threat actor-controlled lookalike domain.
Generic bash tool for AI agents, compatible with AI SDK.
npm install bash-tool just-bash
For full VM support, install @vercel/sandbox or another sandbox product instead of just-bash.
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",
});
The tools object contains three tools that can be used by AI agents:
bashExecute 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 executeReturns:
stdout (string): Standard output from the commandstderr (string): Standard error from the commandexitCode (number): Exit code of the commandreadFileRead the contents of a file from the sandbox.
Input:
path (string): The path to the file to readReturns:
content (string): The file contentswriteFileWrite 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 fileReturns:
success (boolean): true if the write succeededconst { bash } = await createBashTool({
uploadDirectory: {
source: "./my-project",
include: "**/*.{ts,json}", // optional glob filter
},
});
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');" },
});
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
import { Bash } from "just-bash";
const sandbox = new Bash({ cwd: "/app" });
const { tools } = await createBashTool({
sandbox,
destination: "/app",
});
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() } };
},
});
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 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 { skill, files, instructions } = await createSkillTool({
skillsDirectory: "./skills",
});
// Providing a bash tool with skills is optional if your skill only has a SKILL.md file
// and no further files and scripts.
const { tools } = await createBashTool({
files,
extraInstructions: instructions,
});
// Use both tools with an agent
const agent = new ToolLoopAgent({
model,
tools: { skill, ...tools },
});
Full Example and see Skills.sh for a directory of publicly available skills.
skills/
├── csv/
│ ├── SKILL.md # Required: instructions with YAML frontmatter
│ └── scripts/ # Optional: scripts the agent can run
│ ├── analyze.sh
│ └── filter.sh
└── text/
├── SKILL.md
└── scripts/
└── search.sh
See the example skills for a complete reference.
For AI agents working with bash-tool, additional guidance is available in AGENTS.md:
cat node_modules/bash-tool/dist/AGENTS.md
MIT
FAQs
Generic bash tool for AI agents, compatible with AI SDK
The npm package bash-tool receives a total of 38,811 weekly downloads. As such, bash-tool popularity was classified as popular.
We found that bash-tool demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
Published late February to early March 2026, these crates impersonate timeapi.io and POST .env secrets to a threat actor-controlled lookalike domain.

Security News
A recent burst of security disclosures in the OpenClaw project is drawing attention to how vulnerability information flows across advisory and CVE systems.

Research
/Security News
Mixed-script homoglyphs and a lookalike domain mimic imToken’s import flow to capture mnemonics and private keys.