「zero data retention」(ゼロデータ保持)、すなわちZDRがこの機能にどのように適用されるかについては、APIとデータ保持を参照してください。
bashツールはクライアントツールです。Claude自身がコマンドを実行するわけではありません。リクエストにこのツールを含めると、Claudeは実行するコマンドを指定したtool_useブロックで応答します。アプリケーションは自身が所有するbashセッションでそのコマンドを実行し、出力をtool_resultブロックで返します。
アプリケーションはツール呼び出しをまたいで1つのbashプロセスを維持するため、コマンド間で状態が保持されます。作業ディレクトリ、環境変数、コマンドが作成したファイルは、次のコマンドでもそのまま利用できます。
ツールの現在のバージョンはbash_20250124です。モデルのサポート、ベータヘッダー、以前のバージョンについては、ツールバージョンを参照してください。Anthropicが提供するすべてのツールについては、ツールリファレンスを参照してください。
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-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ブロックで応答します。
{
"id": "msg_01XAbCDeFgHiJkLmNoPQrStU",
"model": "claude-opus-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回の往復です。
commandを含むtool_useブロックを返します。tool_resultブロックでClaudeに返します。Claudeは1つの応答で複数のtool_useブロックを返すこともあります。それらを同じセッションで順番に実行し、すべての結果を1つのuserメッセージで返してください。並列ツール使用を参照してください。
APIはステートレスです。シェルセッションに関する情報はリクエスト間で受け渡されないため、セッションをいつ開始し、どれだけ維持し、いつ再起動するかはアプリケーションが決定します。リクエストとレスポンスの完全なサイクルについては、ツール呼び出しの処理を参照してください。
bashツールの定義には、typeとnameという2つの必須フィールドがあり、nameはbashでなければなりません。このツールはスキーマレスです。スキーマはClaudeのモデルに組み込まれており変更できないため、input_schemaを指定しません。次の表は、Claudeがツールを呼び出す際に設定する入力フィールドの一覧です。
| パラメータ | 必須 | 説明 |
|---|---|---|
command | はい* | 実行するbashコマンド |
restart | いいえ | trueに設定するとbashセッションを再起動します |
*restartを使用する場合を除き必須
restart: trueを処理するには、シェルプロセスを終了し、新しいプロセスを開始して、再起動を確認するtool_resultを返します。再起動されたセッションはクリーンな状態から始まります。作業ディレクトリ、環境変数、実行中のプロセスはすべて失われます。
bash_20250124はツールの現在のバージョンで、ベータヘッダーは不要です。Claude Sonnet 3.7(廃止済み)以降のすべてのモデル(現行のすべてのClaudeモデルを含む)で使用できます。
元のbash_20241022バージョンはコンピュータ使用ベータの一部であり、2024年10月リリースのClaude Sonnet 3.5(廃止済み)のみが対応しています。これを使用するリクエストにはanthropic-beta: computer-use-2024-10-22ヘッダーが必要で、SDKではベータ名前空間でのみ公開されています。新しい統合では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でも利用できます。
どのコマンドを実行するかはClaudeが決定します。それ以外のすべて、つまりシェルプロセス、タイムアウト、安全性チェックはアプリケーションが担います。以下の手順は最小限の実装を示しています。
永続的なbashセッションを作成する
長時間稼働するbashプロセスを1つ起動し、すべてのコマンドをその中で実行します。稼働中のプロセスへのパイプはファイル終端(end-of-file)を報告しないため、セッションは各コマンドの後に一意のセンチネル行を出力して、そのコマンドの出力がどこで終わるかを示します。
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に織り交ぜるため、エラーメッセージは発生した場所に出力されます。この例では、完全な実装に必要な要素を省略しています。具体的には、コマンドがハングした際にシェルとそれが起動したすべてのプロセスを終了させ、セッションを再起動するタイムアウトです。コマンドタイムアウトを使用するのベストプラクティスで、その追加方法の一例を示しています。
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ブロックごとに1つのtool_resultを、すべて次のユーザーメッセージで返します
tool_results.append(
{"type": "tool_result", "tool_use_id": content.id, "content": result}
)結果をClaudeに返す
同じ会話を継続するuserメッセージでtool_resultを送り返します。Claudeは同じセッションで別のコマンドをリクエストするか、回答を完成させます。
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-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である間、実行と返却のサイクルを繰り返します。完全なループについては、クライアントツールからの結果の処理を参照してください。
安全対策を実装する
検証と制限を追加します。ブロックリストではなく許可リストを使用してください。ブロックリストは想定していなかったコマンドを見逃します。この例では、独立した単語として現れるシェル演算子も拒否します。
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"
# 別の単語として書かれたシェル演算子を拒否する
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を1つのトークンとして扱うためです。アプリケーションがどのコマンドと演算子を許可するかを決定してください。本当の制御は分離です。セッション全体をコンテナまたは仮想マシン内で実行してください(セキュリティを参照)。
コマンドが失敗したりセッションが壊れたりした場合は、何が起きたかをClaudeに伝えます。メッセージをtool_resultのコンテンツとして返し、is_errorをtrueに設定します。これによりツール呼び出しが失敗としてマークされます。is_errorによるエラー処理を参照してください。
アプリケーションはClaudeがリクエストしたコマンドをそのまま実行します。セッションはコンテナや仮想マシンなどの分離された環境で、作業に必要な最小限の権限を持つユーザーとして実行してください。すべてのコマンドを信頼できない入力として扱ってください。
分離に加えて、次の制御を追加してください。
ulimitを使用します。bashツール定義は、リクエストに以下の入力トークンを追加します。これは、ツールが存在する場合に常に適用されるモデルごとのツール使用システムプロンプトに加えて追加されるものです。
| モデル | 追加入力トークン |
|---|---|
| Claude Opus 5、Claude Opus 4.8、Claude Opus 4.7 | 325トークン |
| Claude Opus 4.6、Claude Sonnet 4.6、およびそれ以前 | 244トークン |
追加のトークンは以下によって消費されます:
料金の詳細については、ツール使用の料金を参照してください。
pytest && coverage reportnpm install && npm run buildgit status && git add . && git commit -m "message"長時間実行されるエージェントワークフローでgitをチェックポイントと復旧のメカニズムとして使用する方法については、状態管理のベストプラクティスを参照してください。
wc -l *.csv && ls -lh *.csvfind . -name "*.py" | xargs grep "pattern"tar -czf backup.tar.gz ./datadf -h && free -mps aux | grep pythonexport PATH=$PATH:/new/path && echo $PATHvim、less、パスワードプロンプトなど、stdinからの入力を待つコマンドは実行できません。tool_resultを返したときにのみClaudeに届きます。bashツールはテキストエディタツールと相性が良いです。Claudeは一方のツールでファイルを編集し、もう一方のツールでそれを実行するコマンドをリクエストします。
コード実行ツールも使用している場合、Claudeは2つの別々の実行環境にアクセスできます。ローカルのbashセッションとAnthropicのサンドボックス化されたコンテナです。これらの間で状態は共有されません。環境を区別するようにClaudeにプロンプトを与える方法については、コード実行を他の実行ツールと併用するを参照してください。
テキストファイルを表示・変更して、コードのデバッグ、修正、改善を行います。
Claudeを外部ツールやAPIに接続します。ツールがどこで実行されるか、Claudeがいつ呼び出すか、どのツールがタスクに適しているかを確認できます。
Was this page helpful?