Bash tool
此功能符合零数据留存 (ZDR) 条件。当你的组织有 ZDR 安排时,通过此功能发送的数据在 API 响应返回后不会被存储。
Bash tool 使 Claude 能够在持久的 bash 会话中执行 shell 命令,实现系统操作、脚本执行和命令行自动化。Shell 访问是 agent 的基础能力。在 Terminal-Bench 2.0(一个使用纯 shell 验证评估真实终端任务的基准测试)上,Claude 在获得持久 bash 会话访问后表现出显著的性能提升。
概述
Bash tool 为 Claude 提供:
- 维持状态的持久 bash 会话
- 运行任何 shell 命令的能力
- 访问环境变量和工作目录
- 命令链和脚本能力
模型支持参见工具参考。
使用场景
- 开发工作流: 运行构建命令、测试和开发工具
- 系统自动化: 执行脚本、管理文件、自动化任务
- 数据处理: 处理文件、运行分析脚本、管理数据集
- 环境设置: 安装包、配置环境
快速开始
curl https://api.anthropic.com/v1/messages \
-H "content-type: application/json" \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "claude-opus-4-7",
"max_tokens": 1024,
"tools": [
{
"type": "bash_20250124",
"name": "bash"
}
],
"messages": [
{
"role": "user",
"content": "List all Python files in the current directory."
}
]
}'
ant messages create \
--model claude-opus-4-7 \
--max-tokens 1024 \
--tool '{type: bash_20250124, name: bash}' \
--message '{role: user, content: List all Python files in the current directory.}'
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-4-7",
max_tokens=1024,
tools=[{"type": "bash_20250124", "name": "bash"}],
messages=[
{"role": "user", "content": "List all Python files in the current directory."}
],
)
print(response)
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const response = await client.messages.create({
model: "claude-opus-4-7",
max_tokens: 1024,
tools: [{ type: "bash_20250124", name: "bash" }],
messages: [
{
role: "user",
content: "List all Python files in the current directory."
}
]
});
console.log(response);
using Anthropic;
using Anthropic.Models.Messages;
var client = new AnthropicClient();
var response = await client.Messages.Create(
new()
{
Model = Model.ClaudeOpus4_7,
MaxTokens = 1024,
Tools = [new ToolBash20250124()],
Messages =
[
new()
{
Role = Role.User,
Content = "List all Python files in the current directory.",
},
],
}
);
Console.WriteLine(response);
package main
import (
"context"
"fmt"
"log"
"github.com/anthropics/anthropic-sdk-go"
)
func main() {
client := anthropic.NewClient()
response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
Model: anthropic.ModelClaudeOpus4_7,
MaxTokens: 1024,
Tools: []anthropic.ToolUnionParam{
{OfBashTool20250124: &anthropic.ToolBash20250124Param{}},
},
Messages: []anthropic.MessageParam{
anthropic.NewUserMessage(anthropic.NewTextBlock("List all Python files in the current directory.")),
},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(response)
}
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import com.anthropic.models.messages.Message;
import com.anthropic.models.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;
import com.anthropic.models.messages.ToolBash20250124;
void main() {
AnthropicClient client = AnthropicOkHttpClient.fromEnv();
Message response = client.messages().create(
MessageCreateParams.builder()
.model(Model.CLAUDE_OPUS_4_7)
.maxTokens(1024)
.addTool(ToolBash20250124.builder().build())
.addUserMessage("List all Python files in the current directory.")
.build()
);
IO.println(response);
}
<?php
use Anthropic\Client;
use Anthropic\Messages\ToolBash20250124;
$client = new Client();
$response = $client->messages->create(
model: 'claude-opus-4-7',
maxTokens: 1024,
tools: [new ToolBash20250124()],
messages: [
['role' => 'user', 'content' => 'List all Python files in the current directory.'],
],
);
echo $response;
require "anthropic"
client = Anthropic::Client.new
response = client.messages.create(
model: "claude-opus-4-7",
max_tokens: 1024,
tools: [{type: "bash_20250124", name: "bash"}],
messages: [
{role: "user", content: "List all Python files in the current directory."}
]
)
puts response
工作原理
Bash tool 维护一个持久会话:
- Claude 确定要运行的命令
- 你在 bash shell 中执行命令
- 将输出(stdout 和 stderr)返回给 Claude
- 会话状态在命令之间持久化(环境变量、工作目录)
参数
| 参数 | 必填 | 描述 |
|---|---|---|
command | 是* | 要运行的 bash 命令 |
restart | 否 | 设置为 true 以重启 bash 会话 |
*除非使用 restart,否则必填
使用示例
运行命令:
{
"command": "ls -la *.py"
}
重启会话:
{
"restart": true
}
示例:多步骤自动化
Claude 可以链接命令来完成复杂任务:
用户请求:
"Install the requests library and create a simple Python script that
fetches a joke from an API, then run it."
Claude 的工具调用:
1. 安装包
{"command": "pip install requests"}
2. 创建脚本
{"command": "cat > fetch_joke.py << 'EOF'\nimport requests\nresponse = requests.get('https://official-joke-api.appspot.com/random_joke')\njoke = response.json()\nprint(f\"Setup: {joke['setup']}\")\nprint(f\"Punchline: {joke['punchline']}\")\nEOF"}
3. 运行脚本
{"command": "python fetch_joke.py"}
会话在命令之间维护状态,因此步骤 2 中创建的文件在步骤 3 中可用。
实现 bash tool
Bash tool 作为无 schema 工具实现。使用此工具时,你不需要像其他工具那样提供输入 schema;schema 内置在 Claude 的模型中,无法修改。
设置 bash 环境
创建一个 Claude 可以交互的持久 bash 会话:
import subprocess import threading import queue class BashSession: def __init__(self): self.process = subprocess.Popen( ["/bin/bash"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, bufsize=0, ) self.output_queue = queue.Queue() self.error_queue = queue.Queue() self._start_readers() def _start_readers(self): ...处理命令执行
创建一个执行命令并捕获输出的函数:
class BashSession: def _read_output(self, timeout): ... def execute_command(self, command): # 将命令发送到 bash self.process.stdin.write(command + "\n") self.process.stdin.flush() # 捕获带超时的输出 output = self._read_output(timeout=10) return output process = None处理 Claude 的工具调用
从 Claude 的响应中提取并执行命令:
from types import SimpleNamespace as _SN response = _SN( content=[_SN(type="tool_use", name="bash", input={"command": "ls"}, id="toolu_01")] ) bash_session = _SN(restart=lambda: None, execute_command=lambda c: "output") for content in response.content: if content.type == "tool_use" and content.name == "bash": if content.input.get("restart"): bash_session.restart() result = "Bash session restarted" else: command = content.input.get("command") result = bash_session.execute_command(command) # 将结果返回给 Claude tool_result = { "type": "tool_result", "tool_use_id": content.id, "content": result, }实现安全措施
添加验证和限制。使用允许列表而非阻止列表,因为阻止列表很容易被绕过。拒绝 shell 操作符,使链接的命令无法绕过允许列表:
import shlex ALLOWED_COMMANDS = {"ls", "cat", "echo", "pwd", "grep", "find", "wc", "head", "tail"} SHELL_OPERATORS = {"&&", "||", "|", ";", "&", ">", "<", ">>"} def validate_command(command): # 仅允许来自显式允许列表的命令 try: tokens = shlex.split(command) except ValueError: return False, "Could not parse command" if not tokens: return False, "Empty command" executable = tokens[0] if executable not in ALLOWED_COMMANDS: return False, f"Command '{executable}' is not in the allowlist" # 拒绝会链接额外命令的 shell 操作符 for token in tokens[1:]: if token in SHELL_OPERATORS or token.startswith(("{{CONTENT}}quot;, "`")): return False, f"Shell operator '{token}' is not allowed" return True, None此检查是第一道防线。要获得更强的隔离,请使用
shell=False运行已验证的命令,并将shlex.split(command)作为参数列表传递,这样 shell 就不会解释字符串。
错误处理
实现 bash tool 时,处理各种错误场景:
命令执行超时
如果命令执行时间过长:
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9",
"content": "Error: Command timed out after 30 seconds",
"is_error": true
}
]
}
命令未找到
如果命令不存在:
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9",
"content": "bash: nonexistentcommand: command not found",
"is_error": true
}
]
}
权限被拒绝
如果有权限问题:
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9",
"content": "bash: /root/sensitive-file: Permission denied",
"is_error": true
}
]
}
遵循实现最佳实践
使用命令超时
实现超时以防止命令挂起:
import subprocess
def execute_with_timeout(command, timeout=30):
try:
result = subprocess.run(
command, shell=True, capture_output=True, text=True, timeout=timeout
)
return result.stdout + result.stderr
except subprocess.TimeoutExpired:
return f"Command timed out after \{timeout\} seconds"
维护会话状态
保持 bash 会话持久化以维护环境变量和工作目录:
# 在同一会话中运行的命令会维护状态
commands = [
"cd /tmp",
"echo 'Hello' > test.txt",
"cat test.txt", # 这可以工作,因为我们仍在 /tmp 中
]
处理大型输出
截断非常大的输出以防止 token 限制问题:
def truncate_output(output, max_lines=100):
lines = output.split("\n")
if len(lines) > max_lines:
truncated = "\n".join(lines[:max_lines])
return f"\{truncated\}\n\n... Output truncated ({len(lines)} total lines) ..."
return output
记录所有命令
保留已执行命令的审计跟踪:
import logging
def log_command(command, output, user_id):
logging.info(f"User \{user_id\} executed: \{command\}")
logging.info(f"Output: {output[:200]}...") # 记录前 200 个字符
清理输出
从命令输出中移除敏感信息:
def sanitize_output(output):
# 移除潜在的密钥或凭证
import re
# 示例:移除 AWS 凭证
output = re.sub(r"aws_access_key_id\s*=\s*\S+", "aws_access_key_id=***", output)
output = re.sub(
r"aws_secret_access_key\s*=\s*\S+", "aws_secret_access_key=***", output
)
return output
安全
Bash tool 提供直接的系统访问。请实施以下基本安全措施:
- 在隔离环境中运行(Docker/VM)
- 实施命令过滤和允许列表
- 设置资源限制(CPU、内存、磁盘)
- 记录所有已执行的命令
关键建议
- 使用
ulimit设置资源约束 - 过滤危险命令(
sudo、rm -rf等) - 以最小用户权限运行
- 监控和记录所有命令执行
定价
Bash tool 为你的 API 调用增加 245 个输入 token。
以下内容会消耗额外 token:
- 命令输出(stdout/stderr)
- 错误消息
- 大型文件内容
完整的定价详情参见工具使用定价。
常见模式
开发工作流
- 运行测试:
pytest && coverage report - 构建项目:
npm install && npm run build - Git 操作:
git status && git add . && git commit -m "message"
基于 Git 的检查点
Git 在长时间运行的 agent 工作流中作为结构化的恢复机制,而不仅仅是保存更改的方式:
- 捕获基线: 在任何 agent 工作开始之前,提交当前状态。这是已知良好的起点。
- 按功能提交: 每个完成的功能都有自己的提交。如果后续出现问题,这些提交可以作为回滚点。
- 在会话开始时重建状态: 读取
git log和进度文件以了解已完成的工作和接下来的内容。 - 失败时回滚: 如果工作出错,
git checkout会回退到最后一个良好的提交,而不是尝试调试损坏的状态。
文件操作
- 处理数据:
wc -l *.csv && ls -lh *.csv - 搜索文件:
find . -name "*.py" | xargs grep "pattern" - 创建备份:
tar -czf backup.tar.gz ./data
系统任务
- 检查资源:
df -h && free -m - 进程管理:
ps aux | grep python - 环境设置:
export PATH=$PATH:/new/path && echo $PATH
限制
- 无交互式命令: 无法处理
vim、less或密码提示 - 无 GUI 应用: 仅限命令行
- 会话范围: Bash 会话状态在客户端。API 是无状态的。你的应用程序负责在轮次之间维护 shell 会话。
- 输出限制: 大型输出可能被截断
- 无流式传输: 结果在完成后返回
与其他工具组合
Bash tool 与文本编辑器和其他工具组合使用时最强大。
如果你同时使用 code execution tool,Claude 可以访问两个独立的执行环境:你的本地 bash 会话和 Anthropic 的沙箱容器。状态不会在它们之间共享。有关提示 Claude 区分环境的指导,请参见将代码执行与其他执行工具一起使用。