Claude Platform Docs
Messages工具

Bash 工具

让 Claude 请求 shell 命令,由您的应用程序在持久化的 bash 会话中运行,并将结果作为工具结果返回。

Bash 工具是一种 client tool(客户端工具):Claude 本身不会运行命令。当您在请求中包含该工具时,Claude 会回复一个 tool_use 块,其中指明要运行的命令。您的应用程序在其拥有的 bash 会话中运行该命令,并在 tool_result 块中返回输出。

您的应用程序在多次工具调用之间保持一个 bash 进程存活,因此状态会在命令之间持久保留。工作目录、环境变量以及命令创建的任何文件在下一条命令执行时仍然存在。

该工具的当前版本为 bash_20250124。有关模型支持、beta 头以及早期版本的信息,请参阅工具版本。有关 Anthropic 提供的所有工具,请参阅工具参考。

使用场景

  • 开发工作流: 运行构建命令、测试和开发工具
  • 系统自动化: 执行脚本、管理文件、自动化任务
  • 数据处理: 处理文件、运行分析脚本、管理数据集
  • 环境设置: 安装软件包、配置环境

快速开始

client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=1024,
    tools=[{"type": "bash_20250124", "name": "bash"}],
    messages=[
        {"role": "user", "content": "List all Python files in the current directory."}
    ],
)

print(response)

Claude 会以 stop_reason: "tool_use" 和一个 tool_use 块进行响应,其中包含供您的应用程序运行的命令:

Output
{
  "id": "msg_01XAbCDeFgHiJkLmNoPQrStU",
  "model": "claude-opus-5-5",
  "stop_reason": "tool_use",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "I'll list all Python files in the current directory for you."
    },
    {
      "type": "tool_use",
      "id": "toolu_01A09q90qw90lq917835lq9",
      "name": "bash",
      "input": {
        "command": "ls *.py"
      }
    }
  ]
}

在您的 bash 会话中运行 input.command,并将输出作为 tool_result 发送回去。有关完整的往返流程,请参阅实现 bash 工具。

工作原理

每次工具调用都是 Claude 与您的应用程序之间的一次往返:

  1. Claude 返回一个包含要运行的 command 的 tool_use 块。
  2. 您的应用程序在其 bash 会话中运行该命令。
  3. 您的应用程序将命令的输出(stdout 和 stderr 合并在一起)通过 tool_result 块返回给 Claude。
  4. Claude 要么在同一会话中请求另一条命令,要么以文本进行响应。

Claude 也可能在一次响应中返回多个 tool_use 块。请在同一会话中按顺序运行它们,并在一条 user 消息中返回所有结果。请参阅并行工具使用。

API 是无状态的。您的 shell 会话的任何信息都不会在请求之间传递,因此由您的应用程序决定会话何时开始、存活多久以及何时重启。有关完整的请求和响应周期,请参阅处理工具调用。

参数

Bash 工具定义有两个必填字段:type 和 name,且 name 必须为 bash。该工具是无 schema 的:您无需提供 input_schema,因为 schema 已内置于 Claude 的模型中且无法修改。下表列出了 Claude 调用该工具时设置的输入字段。

参数必填描述
command是*要运行的 bash 命令
restart否设置为 true 以重启 bash 会话

*除非使用 restart,否则为必填

要处理 restart: true,请终止 shell 进程,启动一个新进程,并返回一个确认重启的 tool_result。重启后的会话从干净状态开始:工作目录、环境变量以及任何正在运行的进程都将消失。

工具版本

bash_20250124 是该工具的当前版本,不需要 beta 头。从 Claude Sonnet 3.7(已退役)起的每个模型都接受它,包括所有当前的 Claude 模型。

最初的 bash_20241022 版本仅适用于 2024 年 10 月的 Claude Sonnet 3.5 模型(已退役)。使用它的请求需要 anthropic-beta: computer-use-2024-10-22 头,并且 SDK 仅在其 beta 命名空间中公开它。新的集成应使用 bash_20250124。

示例:多步骤自动化

Claude 可以跨多次工具调用串联命令,以完成多步骤任务:

User request:
"Install the requests library and create a simple Python script that
fetches a joke from an API, then run it."

Claude's tool uses:
1. Install package
   {"command": "pip install requests"}

2. Create script
   {"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. Run script
   {"command": "python fetch_joke.py"}

会话在命令之间保持状态,因此在第 2 步中创建的文件在第 3 步中可用。

实现 bash 工具

Claude 决定运行哪条命令。其他一切都由您的应用程序负责:shell 进程、超时以及安全检查。以下步骤展示了一个最小实现。

  1. 创建持久化的 bash 会话

    启动一个长期存活的 bash 进程,并在其中运行每条命令。由于连接到存活进程的管道永远不会报告文件结束(end-of-file),会话会在每条命令之后打印一行唯一的哨兵(sentinel)行,以标记该命令输出的结束位置:

    import subprocess
    import uuid
    
    
    class BashSession:
        """A bash process that stays alive between commands so state persists."""
    
        def __init__(self):
            self.process = subprocess.Popen(
                ["/bin/bash"],
                stdin=subprocess.PIPE,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,  # interleave errors with output, in order
                start_new_session=True,  # own process group: a timeout can kill every child
                text=True,
            )
    
        def execute_command(self, command):
            """Run a command in the session and return its output."""
            sentinel = f"__CLAUDE_BASH_DONE_{uuid.uuid4().hex}__"  # unique per call
            self.process.stdin.write(f"{command}\necho {sentinel}\n")
            self.process.stdin.flush()
    
            output = []
            for line in self.process.stdout:
                if sentinel in line:  # this command's output is complete
                    break
                output.append(line)
            return "".join(output)
    
        def restart(self):
            self.process.kill()
            self.process.wait()
            self.__init__()
    
    
    bash_session = BashSession()
    print(bash_session.execute_command("cd /tmp && pwd"))
    print(bash_session.execute_command("pwd"))  # still /tmp: the session kept its state

    会话将 stderr 与 stdout 交错输出,因此错误消息会出现在其发生的位置。该示例省略了完整实现还需要的内容:一个超时机制,当命令挂起时终止 shell 及其启动的所有进程,然后重启会话。使用命令超时最佳实践展示了一种添加方式。

  2. 处理 Claude 的工具调用

    从 Claude 的响应中提取并运行命令:

    tool_results = []
    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)
    
            # 每个 tool_use 块对应一个 tool_result,全部在下一条用户消息中返回
            tool_results.append(
                {"type": "tool_result", "tool_use_id": content.id, "content": result}
            )
  3. 将结果返回给 Claude

    在延续同一对话的 user 消息中将 tool_result 发送回去。Claude 要么在同一会话中请求另一条命令,要么完成其回答:

    client = anthropic.Anthropic()
    
    response = client.messages.create(
        model="claude-opus-5-5",
        max_tokens=1024,
        tools=[{"type": "bash_20250124", "name": "bash"}],
        messages=[
            {"role": "user", "content": "List all Python files in the current directory."},
            {
                "role": "assistant",
                "content": [
                    {
                        "type": "tool_use",
                        "id": "toolu_01A09q90qw90lq917835lq9",
                        "name": "bash",
                        "input": {"command": "ls *.py"},
                    }
                ],
            },
            {
                "role": "user",
                "content": [
                    {
                        "type": "tool_result",
                        "tool_use_id": "toolu_01A09q90qw90lq917835lq9",
                        "content": "analysis.py\nprocess_data.py\n",
                    }
                ],
            },
        ],
    )
    
    print(response.content)

    当 stop_reason 为 tool_use 时,重复"运行并返回"的循环。有关完整循环,请参阅处理客户端工具的结果。

  4. 实施安全措施

    添加验证和限制。使用允许列表(allowlist)而非阻止列表(blocklist):阻止列表会遗漏任何未预料到的命令。该示例还会拒绝作为独立单词出现的 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(("$", "`")):
                return False, f"Shell operator '{token}' is not allowed"
    
        return True, None

    此检查是针对明显错误的绊线,而非强制执行边界。它会拒绝本页其他示例中使用的带空格的链式操作(&&)、管道和重定向。它无法捕获与单词粘连在一起的操作符,例如 cat data.txt|grep x,因为分词器会将 data.txt|grep 保留在一个令牌内。请决定您的应用程序允许哪些命令和操作符。真正的控制手段是隔离:在容器或虚拟机中运行整个会话(请参阅安全)。

处理错误

当命令失败或会话中断时,请告知 Claude 发生了什么。将消息作为 tool_result 内容返回,并将 is_error 设置为 true,这会将该工具调用标记为失败。请参阅使用 is_error 处理错误。

遵循实现最佳实践

安全

除隔离之外,还应添加以下控制措施:

  • 在运行命令之前进行验证,使用允许列表而非阻止列表。请参阅实现 bash 工具。
  • 对 shell 进程设置资源限制(CPU、内存和磁盘),例如使用 ulimit。
  • 记录每条命令及其输出,以便您可以审计运行过的内容。
  • 在将输出返回给 Claude 之前,对其中的凭据和其他机密信息进行脱敏处理。

定价

bash 工具定义会向您的请求中添加以下 input tokens(输入令牌)。这是在每个模型的工具使用系统提示之外额外添加的,只要存在任何工具,该系统提示就会生效。

模型额外输入令牌
Claude Opus 5、Claude Opus 4.8 和 Claude Opus 4.7325 个令牌
Claude Opus 4.6、Claude Sonnet 4.6 及更早版本244 个令牌

以下内容会消耗额外的令牌:

  • 命令输出(stdout/stderr)
  • 错误消息
  • 大型文件内容

有关完整的定价详情,请参阅工具使用定价。

常见模式

开发工作流

  • 运行测试:pytest && coverage report
  • 构建项目:npm install && npm run build
  • Git 操作:git status && git add . && git commit -m "message"

有关在长时间运行的智能体工作流中将 git 用作检查点与恢复机制的指导,请参阅状态管理最佳实践。

文件操作

  • 处理数据: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、密码提示或任何在 stdin 上等待输入的命令。
  • 不支持 GUI 应用程序: 会话仅限命令行。
  • 会话范围: Bash 会话状态位于客户端。您的应用程序负责在轮次之间维护 shell 会话。
  • 输出限制: API 不会截断工具结果(过大的请求会被拒绝)。请在将大型输出返回给 Claude 之前,在您的应用程序中对其进行截断。
  • 不支持流式传输: 只有当您的应用程序在下一个请求中返回 tool_result 时,输出才会到达 Claude。

与其他工具结合使用

Bash 工具与文本编辑器工具搭配使用效果很好:Claude 使用一个工具编辑文件,并使用另一个工具请求运行该文件的命令。

后续步骤

查看和修改文本文件,以调试、修复和改进代码。

将 Claude 连接到外部工具和 API。了解工具在何处执行、Claude 何时调用它们,以及哪种工具适合您的任务。

Was this page helpful?