Bash 도구는 클라이언트 도구입니다. Claude는 명령어를 직접 실행하지 않습니다. 요청에 이 도구를 포함하면 Claude는 실행할 명령어를 지정하는 tool_use 블록으로 응답합니다. 애플리케이션은 자체적으로 소유한 bash 세션에서 해당 명령어를 실행하고 출력을 tool_result 블록으로 반환합니다.
애플리케이션은 도구 호출 간에 하나의 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와 애플리케이션 간의 한 번의 왕복입니다.
command가 포함된 tool_use 블록을 반환합니다.tool_result 블록으로 Claude에 반환합니다.Claude는 하나의 응답에서 여러 tool_use 블록을 반환할 수도 있습니다. 동일한 세션에서 순서대로 실행하고 모든 결과를 하나의 user 메시지로 반환하세요. 병렬 도구 사용을 참조하세요.
API는 상태를 저장하지 않습니다. 셸 세션에 대한 어떤 정보도 요청 간에 전달되지 않으므로, 세션이 언제 시작되고, 얼마나 유지되며, 언제 재시작할지는 애플리케이션이 결정합니다. 전체 요청 및 응답 주기는 도구 호출 처리를 참조하세요.
Bash 도구 정의에는 두 개의 필수 필드인 type과 name이 있으며, name은 반드시 bash여야 합니다. 이 도구는 스키마가 없습니다. 스키마가 Claude의 모델에 내장되어 있고 수정할 수 없으므로 input_schema를 제공하지 않습니다. 다음 표는 Claude가 도구를 호출할 때 설정하는 입력 필드를 나열합니다.
| 매개변수 | 필수 | 설명 |
|---|---|---|
command | 예* | 실행할 bash 명령어 |
restart | 아니요 | bash 세션을 재시작하려면 true로 설정 |
*restart를 사용하지 않는 경우 필수
restart: true를 처리하려면 셸 프로세스를 종료하고 새 프로세스를 시작한 다음, 재시작을 확인하는 tool_result를 반환하세요. 재시작된 세션은 초기 상태로 시작됩니다. 작업 디렉터리, 환경 변수 및 실행 중이던 모든 프로세스가 사라집니다.
bash_20250124는 현재 도구 버전이며 베타 헤더가 필요하지 않습니다. Claude Sonnet 3.7(종료됨) 이후의 모든 모델이 이를 지원하며, 현재 모든 Claude 모델이 포함됩니다.
원래의 bash_20241022 버전은 computer use 베타의 일부이며, 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 프로세스를 시작하고 모든 명령어를 그 안에서 실행하세요. 활성 프로세스에 대한 파이프는 파일 끝(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과 교차 배치하므로 오류 메시지가 발생한 위치에 표시됩니다. 이 예시에는 완전한 구현에 필요한 부분이 빠져 있습니다. 명령어가 멈췄을 때 셸과 셸이 시작한 모든 프로세스를 종료한 다음 세션을 재시작하는 타임아웃입니다. 명령어 타임아웃 사용 모범 사례에서 이를 추가하는 한 가지 방법을 보여줍니다.
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}
)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인 동안 실행 및 반환 주기를 반복하세요. 전체 루프는 클라이언트 도구의 결과 처리를 참조하세요.
안전 조치 구현
검증 및 제한을 추가하세요. 차단 목록(blocklist)보다는 허용 목록(allowlist)을 사용하세요. 차단 목록은 예상하지 못한 명령어를 놓칩니다. 이 예시는 별도의 단어로 나타나는 셸 연산자도 거부합니다.
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을 하나의 토큰으로 유지하기 때문입니다. 애플리케이션에서 허용할 명령어와 연산자를 결정하세요. 실질적인 제어는 격리입니다. 전체 세션을 컨테이너나 가상 머신 내에서 실행하세요(보안 참조).
명령어가 실패하거나 세션이 중단되면 Claude에게 무슨 일이 일어났는지 알려주세요. 메시지를 tool_result 콘텐츠로 반환하고 is_error를 true로 설정하면 도구 호출이 실패로 표시됩니다. is_error로 오류 처리를 참조하세요.
격리 외에도 다음 제어를 추가하세요.
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를 외부 도구 및 API에 연결하세요. 도구가 어디서 실행되는지, Claude가 언제 호출하는지, 어떤 도구가 작업에 적합한지 확인하세요.
Was this page helpful?