Herramienta bash
Permite que Claude solicite comandos de shell que tu aplicación ejecuta en una sesión bash persistente y devuelve como resultados de herramientas.
La herramienta bash es una herramienta de cliente: Claude no ejecuta comandos por sí mismo. Cuando incluyes la herramienta en una solicitud, Claude responde con un bloque tool_use que indica el comando a ejecutar. Tu aplicación ejecuta ese comando en una sesión bash de su propiedad y devuelve la salida en un bloque tool_result.
Tu aplicación mantiene un proceso bash activo a lo largo de las llamadas a herramientas, por lo que el estado persiste entre comandos. El directorio de trabajo, las variables de entorno y cualquier archivo que cree un comando siguen ahí para el siguiente comando.
La versión actual de la herramienta es bash_20250124. Para conocer la compatibilidad de modelos, los encabezados beta y la versión anterior, consulta Versiones de la herramienta. Para ver todas las herramientas proporcionadas por Anthropic, consulta la Referencia de herramientas.
Casos de uso
- Flujos de trabajo de desarrollo: Ejecuta comandos de compilación, pruebas y herramientas de desarrollo
- Automatización de sistemas: Ejecuta scripts, administra archivos, automatiza tareas
- Procesamiento de datos: Procesa archivos, ejecuta scripts de análisis, administra conjuntos de datos
- Configuración de entornos: Instala paquetes, configura entornos
Inicio rápido
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 responde con stop_reason: "tool_use" y un bloque tool_use que contiene el comando que tu aplicación debe ejecutar:
{
"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"
}
}
]
}Ejecuta input.command en tu sesión bash y envía la salida de vuelta como un tool_result. Consulta Implementa la herramienta bash para ver el ciclo completo de ida y vuelta.
Cómo funciona
Cada llamada a la herramienta es un ciclo de ida y vuelta entre Claude y tu aplicación:
- Claude devuelve un bloque
tool_useque contiene elcommanda ejecutar. - Tu aplicación ejecuta el comando en su sesión bash.
- Tu aplicación devuelve la salida del comando, stdout y stderr juntos, a Claude en un bloque
tool_result. - Claude solicita otro comando en la misma sesión o responde con texto.
Claude también puede devolver varios bloques tool_use en una sola respuesta. Ejecútalos en orden en la misma sesión y devuelve todos los resultados en un solo mensaje user. Consulta Uso de herramientas en paralelo.
La API no tiene estado. Nada de tu sesión de shell viaja entre solicitudes, por lo que tu aplicación decide cuándo comienza la sesión, cuánto tiempo vive y cuándo reiniciarla. Para ver el ciclo completo de solicitud y respuesta, consulta Maneja las llamadas a herramientas.
Parámetros
Una definición de la herramienta bash tiene dos campos obligatorios, type y name, y el name debe ser bash. La herramienta no tiene esquema: no proporcionas un input_schema, porque el esquema está integrado en el modelo de Claude y no se puede modificar. La siguiente tabla enumera los campos de entrada que Claude establece cuando llama a la herramienta.
| Parámetro | Obligatorio | Descripción |
|---|---|---|
command | Sí* | El comando bash a ejecutar |
restart | No | Establécelo en true para reiniciar la sesión bash |
*Obligatorio a menos que se use restart
Para manejar restart: true, termina el proceso de shell, inicia uno nuevo y devuelve un tool_result que confirme el reinicio. Una sesión reiniciada comienza limpia: el directorio de trabajo, las variables de entorno y cualquier proceso en ejecución desaparecen.
Ejecuta un comando:
{
"command": "ls -la *.py"
}Reinicia la sesión:
{
"restart": true
}Versiones de la herramienta
bash_20250124 es la versión actual de la herramienta y no requiere ningún encabezado beta. Todos los modelos desde Claude Sonnet 3.7 (retirado) en adelante la aceptan, incluidos todos los modelos actuales de Claude.
La versión original bash_20241022 funciona únicamente con el modelo Claude Sonnet 3.5 de octubre de 2024 (retirado). Las solicitudes que la usan necesitan el encabezado anthropic-beta: computer-use-2024-10-22, y los SDK la exponen solo en sus espacios de nombres beta. Las integraciones nuevas deben usar bash_20250124.
Ejemplo: Automatización de varios pasos
Claude puede encadenar comandos a lo largo de varias llamadas a herramientas para completar una tarea de varios pasos:
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"}La sesión mantiene el estado entre comandos, por lo que los archivos creados en el paso 2 están disponibles en el paso 3.
Implementa la herramienta bash
Claude determina qué comando ejecutar. Tu aplicación es dueña de todo lo demás: el proceso de shell, el tiempo de espera y las verificaciones de seguridad. Los siguientes pasos muestran una implementación mínima.
Crea una sesión bash persistente
Inicia un proceso bash de larga duración y ejecuta cada comando dentro de él. Dado que una tubería hacia un proceso activo nunca informa el fin de archivo, la sesión imprime una línea centinela única después de cada comando para marcar dónde termina la salida de ese comando:
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 stateLa sesión intercala stderr con stdout, por lo que los mensajes de error aparecen donde ocurrieron. El ejemplo omite lo que una implementación completa también necesita: un tiempo de espera que termine el shell y todos los procesos que inició cuando un comando se queda colgado, y que luego reinicie la sesión. La práctica recomendada Usa tiempos de espera para los comandos muestra una forma de agregarlo.
Procesa las llamadas a herramientas de Claude
Extrae y ejecuta los comandos de las respuestas de 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) # Un tool_result por cada bloque tool_use, todos devueltos en el siguiente mensaje del usuario tool_results.append( {"type": "tool_result", "tool_use_id": content.id, "content": result} )Devuelve el resultado a Claude
Envía el
tool_resultde vuelta en un mensajeuserque continúe la misma conversación. Claude solicita otro comando en la misma sesión o termina su respuesta: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)Repite el ciclo de ejecutar y devolver mientras
stop_reasonseatool_use. Para ver el bucle completo, consulta Manejo de resultados de herramientas de cliente.Implementa medidas de seguridad
Agrega validación y restricciones. Usa una lista de permitidos en lugar de una lista de bloqueados: una lista de bloqueados pasa por alto cualquier comando que no haya anticipado. El ejemplo también rechaza los operadores de shell que aparecen como palabras separadas:
import shlex ALLOWED_COMMANDS = {"ls", "cat", "echo", "pwd", "grep", "find", "wc", "head", "tail"} SHELL_OPERATORS = {"&&", "||", "|", ";", "&", ">", "<", ">>"} def validate_command(command): # Permitir solo comandos de una lista de permitidos explícita 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" # Rechazar operadores de shell escritos como palabras separadas for token in tokens[1:]: if token in SHELL_OPERATORS or token.startswith(("$", "`")): return False, f"Shell operator '{token}' is not allowed" return True, NoneEsta verificación es una alarma para errores obvios, no una barrera de cumplimiento. Rechaza el encadenamiento con espacios (
&&), las tuberías y la redirección que usan los demás ejemplos de esta página. No detecta un operador pegado a una palabra, comocat data.txt|grep x, porque el tokenizador mantienedata.txt|grepdentro de un solo token. Decide qué comandos y operadores permite tu aplicación. El control real es el aislamiento: ejecuta toda la sesión dentro de un contenedor o una máquina virtual (consulta Seguridad).
Maneja los errores
Cuando un comando falla o la sesión se rompe, dile a Claude qué pasó. Devuelve el mensaje como contenido del tool_result y establece is_error en true, lo que marca la llamada a la herramienta como fallida. Consulta Manejo de errores con is_error.
Si un comando tarda demasiado en ejecutarse:
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9",
"content": "Error: command did not finish within 30 seconds",
"is_error": true
}
]
}Si un comando no existe:
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9",
"content": "bash: nonexistentcommand: command not found",
"is_error": true
}
]
}Si hay problemas de permisos:
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9",
"content": "bash: /root/sensitive-file: Permission denied",
"is_error": true
}
]
}Sigue las prácticas recomendadas de implementación
Un comando que nunca termina, como uno que espera una entrada, bloquea la sesión para siempre porque su línea centinela nunca llega. Dale a cada comando un plazo límite. Cuando el plazo se cumpla, detén el shell y todo lo que el comando haya iniciado, y luego reinicia la sesión:
import concurrent.futures
import os
import signal
def execute_with_timeout(session, command, timeout=30):
"""Run a command in the session, replacing the session if the command hangs."""
with concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool:
future = pool.submit(session.execute_command, command)
try:
return future.result(timeout=timeout)
except concurrent.futures.TimeoutError:
# El grupo es el shell y cada proceso que el comando inició
os.killpg(session.process.pid, signal.SIGKILL)
session.restart()
return f"Error: command did not finish within {timeout} seconds"La terminación detiene el comando colgado y todo lo que inició. Devuelve el mensaje como un tool_result de error (consulta Maneja los errores), lo que marca la llamada a la herramienta como fallida.
Mantén la sesión bash persistente para conservar las variables de entorno y el directorio de trabajo:
# Los comandos ejecutados en la misma sesión mantienen el estado
commands = [
"cd /tmp",
"echo 'Hello' > test.txt",
"cat test.txt", # The session is still in /tmp
]Trunca las salidas grandes para evitar problemas con el límite de tokens:
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 outputMantén un registro de auditoría. Dirige cada comando a través de un único envoltorio que registre el comando antes de que se ejecute y la salida después de que termine. Un comando que se queda colgado o rompe la sesión igualmente deja un registro:
import logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(message)s")
def execute_and_log(session, command):
"""Run a command in the session and keep an audit record of it."""
logging.info("command=%r", command)
output = session.execute_command(command)
logging.info("output=%r", output[:200]) # first 200 characters
return outputLos registros van a stderr de forma predeterminada; dirígelos a un archivo o a tu canal de registro para conservarlos. Incluye lo que vincule el registro con la solicitud en tu aplicación, como el usuario final y el tool_use_id.
Seguridad
Además del aislamiento, agrega estos controles:
- Valida los comandos antes de ejecutarlos, con una lista de permitidos en lugar de una lista de bloqueados. Consulta Implementa la herramienta bash.
- Establece límites de recursos en el proceso de shell (CPU, memoria y disco), por ejemplo con
ulimit. - Registra cada comando y su salida para poder auditar lo que se ejecutó.
- Oculta las credenciales y otros secretos de la salida antes de devolverla a Claude.
Precios
La definición de la herramienta bash agrega los siguientes tokens de entrada a tu solicitud. Esto es adicional a la indicación del sistema de uso de herramientas por modelo que se aplica siempre que haya alguna herramienta presente.
| Modelo | Tokens de entrada adicionales |
|---|---|
| Claude Opus 5, Claude Opus 4.8 y Claude Opus 4.7 | 325 tokens |
| Claude Opus 4.6, Claude Sonnet 4.6 y anteriores | 244 tokens |
Se consumen tokens adicionales por:
- Salidas de comandos (stdout/stderr)
- Mensajes de error
- Contenidos de archivos grandes
Consulta los precios del uso de herramientas para ver los detalles completos de precios.
Patrones comunes
Flujos de trabajo de desarrollo
- Ejecutar pruebas:
pytest && coverage report - Compilar proyectos:
npm install && npm run build - Operaciones de Git:
git status && git add . && git commit -m "message"
Para obtener orientación sobre el uso de git como mecanismo de puntos de control y recuperación en flujos de trabajo de agentes de larga duración, consulta las prácticas recomendadas de gestión de estado.
Operaciones con archivos
- Procesar datos:
wc -l *.csv && ls -lh *.csv - Buscar archivos:
find . -name "*.py" | xargs grep "pattern" - Crear copias de seguridad:
tar -czf backup.tar.gz ./data
Tareas del sistema
- Verificar recursos:
df -h && free -m - Gestión de procesos:
ps aux | grep python - Configuración del entorno:
export PATH=$PATH:/new/path && echo $PATH
Limitaciones
- Sin comandos interactivos: La sesión no puede ejecutar
vim,less, solicitudes de contraseña ni ningún comando que espere una entrada en stdin. - Sin aplicaciones con interfaz gráfica: La sesión es solo de línea de comandos.
- Alcance de la sesión: El estado de la sesión bash está del lado del cliente. Tu aplicación es responsable de mantener la sesión de shell entre turnos.
- Límites de salida: La API no trunca los resultados de herramientas (una solicitud demasiado grande se rechaza). Trunca las salidas grandes en tu aplicación antes de devolverlas a Claude.
- Sin streaming: La salida llega a Claude solo cuando tu aplicación devuelve el
tool_resulten la siguiente solicitud.
Combinación con otras herramientas
La herramienta bash se complementa bien con la Herramienta de editor de texto: Claude edita un archivo con una herramienta y solicita el comando que lo ejecuta con la otra.
Próximos pasos
Visualiza y modifica archivos de texto para depurar, corregir y mejorar código.
Conecta Claude a herramientas y API externas. Descubre dónde se ejecutan las herramientas, cuándo las llama Claude y qué herramienta se adapta a tu tarea.
Was this page helpful?