Claude Platform Docs
MessagesTools

Bash-Tool

Lass Claude Shell-Befehle anfordern, die deine Anwendung in einer persistenten Bash-Sitzung ausführt und als Tool-Ergebnisse zurückgibt.

Das Bash-Tool ist ein Client-Tool: Claude führt Befehle nicht selbst aus. Wenn du das Tool in eine Anfrage aufnimmst, antwortet Claude mit einem tool_use-Block, der den auszuführenden Befehl benennt. Deine Anwendung führt diesen Befehl in einer Bash-Sitzung aus, die ihr gehört, und gibt die Ausgabe in einem tool_result-Block zurück.

Deine Anwendung hält einen Bash-Prozess über Tool-Aufrufe hinweg am Leben, sodass der Zustand zwischen Befehlen erhalten bleibt. Das Arbeitsverzeichnis, Umgebungsvariablen und alle Dateien, die ein Befehl erstellt, sind für den nächsten Befehl noch vorhanden.

Die aktuelle Version des Tools ist bash_20250124. Informationen zur Modellunterstützung, zu Beta-Headern und zur früheren Version findest du unter Tool-Versionen. Alle von Anthropic bereitgestellten Tools findest du in der Tool-Referenz.

Anwendungsfälle

  • Entwicklungs-Workflows: Build-Befehle, Tests und Entwicklungstools ausführen
  • Systemautomatisierung: Skripte ausführen, Dateien verwalten, Aufgaben automatisieren
  • Datenverarbeitung: Dateien verarbeiten, Analyseskripte ausführen, Datensätze verwalten
  • Umgebungseinrichtung: Pakete installieren, Umgebungen konfigurieren

Schnellstart

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 antwortet mit stop_reason: "tool_use" und einem tool_use-Block, der den Befehl enthält, den deine Anwendung ausführen soll:

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"
      }
    }
  ]
}

Führe input.command in deiner Bash-Sitzung aus und sende die Ausgabe als tool_result zurück. Den vollständigen Roundtrip findest du unter Das Bash-Tool implementieren.

So funktioniert es

Jeder Tool-Aufruf ist ein Roundtrip zwischen Claude und deiner Anwendung:

  1. Claude gibt einen tool_use-Block zurück, der den auszuführenden command enthält.
  2. Deine Anwendung führt den Befehl in ihrer Bash-Sitzung aus.
  3. Deine Anwendung gibt die Ausgabe des Befehls, stdout und stderr zusammen, in einem tool_result-Block an Claude zurück.
  4. Claude fordert entweder einen weiteren Befehl in derselben Sitzung an oder antwortet mit Text.

Claude kann auch mehrere tool_use-Blöcke in einer Antwort zurückgeben. Führe sie der Reihe nach in derselben Sitzung aus und gib alle Ergebnisse in einer einzigen user-Nachricht zurück. Siehe Parallele Tool-Nutzung.

Die API ist zustandslos. Nichts über deine Shell-Sitzung wird zwischen Anfragen übertragen, daher entscheidet deine Anwendung, wann die Sitzung beginnt, wie lange sie lebt und wann sie neu gestartet wird. Den vollständigen Anfrage- und Antwortzyklus findest du unter Tool-Aufrufe verarbeiten.

Parameter

Eine Bash-Tool-Definition hat zwei Pflichtfelder, type und name, und name muss bash sein. Das Tool ist schemalos: Du gibst kein input_schema an, da das Schema in Claudes Modell eingebaut ist und nicht geändert werden kann. Die folgende Tabelle listet die Eingabefelder auf, die Claude setzt, wenn es das Tool aufruft.

ParameterErforderlichBeschreibung
commandJa*Der auszuführende Bash-Befehl
restartNeinAuf true setzen, um die Bash-Sitzung neu zu starten

*Erforderlich, sofern nicht restart verwendet wird

Um restart: true zu verarbeiten, beende den Shell-Prozess, starte einen neuen und gib ein tool_result zurück, das den Neustart bestätigt. Eine neu gestartete Sitzung beginnt sauber: Das Arbeitsverzeichnis, Umgebungsvariablen und alle laufenden Prozesse sind weg.

Tool-Versionen

bash_20250124 ist die aktuelle Version des Tools und erfordert keinen Beta-Header. Jedes Modell ab Claude Sonnet 3.7 (eingestellt) akzeptiert sie, einschließlich aller aktuellen Claude-Modelle.

Die ursprüngliche Version bash_20241022 funktioniert nur mit dem Claude Sonnet 3.5-Modell vom Oktober 2024 (eingestellt). Anfragen, die sie verwenden, benötigen den Header anthropic-beta: computer-use-2024-10-22, und die SDKs stellen sie nur in ihren Beta-Namespaces bereit. Neue Integrationen sollten bash_20250124 verwenden.

Beispiel: Mehrstufige Automatisierung

Claude kann Befehle über Tool-Aufrufe hinweg verketten, um eine mehrstufige Aufgabe zu erledigen:

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"}

Die Sitzung behält den Zustand zwischen Befehlen bei, sodass in Schritt 2 erstellte Dateien in Schritt 3 verfügbar sind.

Das Bash-Tool implementieren

Claude bestimmt, welcher Befehl ausgeführt wird. Deine Anwendung ist für alles andere verantwortlich: den Shell-Prozess, das Timeout und die Sicherheitsprüfungen. Die folgenden Schritte zeigen eine minimale Implementierung.

  1. Eine persistente Bash-Sitzung erstellen

    Starte einen langlebigen Bash-Prozess und führe jeden Befehl darin aus. Da eine Pipe zu einem laufenden Prozess niemals ein Dateiende meldet, gibt die Sitzung nach jedem Befehl eine eindeutige Sentinel-Zeile aus, um zu markieren, wo die Ausgabe dieses Befehls endet:

    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

    Die Sitzung verschränkt stderr mit stdout, sodass Fehlermeldungen dort landen, wo sie aufgetreten sind. Das Beispiel lässt aus, was eine vollständige Implementierung ebenfalls benötigt: ein Timeout, das die Shell und jeden von ihr gestarteten Prozess beendet, wenn ein Befehl hängt, und dann die Sitzung neu startet. Die Best Practice Befehls-Timeouts verwenden zeigt eine Möglichkeit, dies hinzuzufügen.

  2. Claudes Tool-Aufrufe verarbeiten

    Extrahiere Befehle aus Claudes Antworten und führe sie aus:

    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)
    
            # Ein tool_result pro tool_use-Block, alle in der nächsten User-Nachricht zurückgegeben
            tool_results.append(
                {"type": "tool_result", "tool_use_id": content.id, "content": result}
            )
  3. Das Ergebnis an Claude zurückgeben

    Sende das tool_result in einer user-Nachricht zurück, die dieselbe Konversation fortsetzt. Claude fordert entweder einen weiteren Befehl in derselben Sitzung an oder schließt seine Antwort ab:

    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)

    Wiederhole den Zyklus aus Ausführen und Zurückgeben, solange stop_reason den Wert tool_use hat. Die vollständige Schleife findest du unter Ergebnisse von Client-Tools verarbeiten.

  4. Sicherheitsmaßnahmen implementieren

    Füge Validierung und Einschränkungen hinzu. Verwende eine „allowlist" (Positivliste) statt einer „blocklist" (Sperrliste): Eine Blocklist übersieht jeden Befehl, den sie nicht vorhergesehen hat. Das Beispiel lehnt außerdem Shell-Operatoren ab, die als separate Wörter auftreten:

    import shlex
    
    ALLOWED_COMMANDS = {"ls", "cat", "echo", "pwd", "grep", "find", "wc", "head", "tail"}
    SHELL_OPERATORS = {"&&", "||", "|", ";", "&", ">", "<", ">>"}
    
    
    def validate_command(command):
        # Erlaube nur Befehle aus einer expliziten Allowlist
        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"
    
        # Lehne Shell-Operatoren ab, die als separate Wörter geschrieben sind
        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

    Diese Prüfung ist ein Stolperdraht für offensichtliche Fehler, keine Durchsetzungsgrenze. Sie lehnt die mit Leerzeichen getrennte Verkettung (&&), Pipes und Umleitungen ab, die die anderen Beispiele auf dieser Seite verwenden. Sie erkennt keinen Operator, der an ein Wort geklebt ist, wie etwa cat data.txt|grep x, da der Tokenizer data.txt|grep innerhalb eines Tokens belässt. Entscheide, welche Befehle und Operatoren deine Anwendung zulässt. Die eigentliche Kontrolle ist Isolation: Führe die gesamte Sitzung in einem Container oder einer virtuellen Maschine aus (siehe Sicherheit).

Fehler behandeln

Wenn ein Befehl fehlschlägt oder die Sitzung abbricht, teile Claude mit, was passiert ist. Gib die Meldung als tool_result-Inhalt zurück und setze is_error auf true, was den Tool-Aufruf als fehlgeschlagen markiert. Siehe Fehlerbehandlung mit is_error.

Best Practices für die Implementierung befolgen

Sicherheit

Füge über die Isolation hinaus diese Kontrollen hinzu:

  • Validiere Befehle vor der Ausführung, mit einer Allowlist statt einer Blocklist. Siehe Das Bash-Tool implementieren.
  • Setze Ressourcenlimits für den Shell-Prozess (CPU, Arbeitsspeicher und Festplatte), zum Beispiel mit ulimit.
  • Protokolliere jeden Befehl und seine Ausgabe, damit du prüfen kannst, was ausgeführt wurde.
  • Schwärze Zugangsdaten und andere Geheimnisse in der Ausgabe, bevor du sie an Claude zurückgibst.

Preise

Die Bash-Tool-Definition fügt deiner Anfrage die folgenden Input-Token hinzu. Dies gilt zusätzlich zum modellspezifischen System-Prompt für die Tool-Nutzung, der immer dann angewendet wird, wenn ein beliebiges Tool vorhanden ist.

ModellZusätzliche Input-Token
Claude Opus 5, Claude Opus 4.8 und Claude Opus 4.7325 Token
Claude Opus 4.6, Claude Sonnet 4.6 und früher244 Token

Zusätzliche Token werden verbraucht durch:

  • Befehlsausgaben (stdout/stderr)
  • Fehlermeldungen
  • Große Dateiinhalte

Vollständige Preisdetails findest du unter Preise für Tool-Nutzung.

Häufige Muster

Entwicklungs-Workflows

  • Tests ausführen: pytest && coverage report
  • Projekte bauen: npm install && npm run build
  • Git-Operationen: git status && git add . && git commit -m "message"

Hinweise zur Verwendung von git als Checkpoint- und Wiederherstellungsmechanismus in lang laufenden Agenten-Workflows findest du unter Best Practices für die Zustandsverwaltung.

Dateioperationen

  • Daten verarbeiten: wc -l *.csv && ls -lh *.csv
  • Dateien durchsuchen: find . -name "*.py" | xargs grep "pattern"
  • Backups erstellen: tar -czf backup.tar.gz ./data

Systemaufgaben

  • Ressourcen prüfen: df -h && free -m
  • Prozessverwaltung: ps aux | grep python
  • Umgebungseinrichtung: export PATH=$PATH:/new/path && echo $PATH

Einschränkungen

  • Keine interaktiven Befehle: Die Sitzung kann vim, less, Passwortabfragen oder andere Befehle, die auf Eingabe über stdin warten, nicht ausführen.
  • Keine GUI-Anwendungen: Die Sitzung ist rein kommandozeilenbasiert.
  • Sitzungsumfang: Der Zustand der Bash-Sitzung liegt clientseitig. Deine Anwendung ist dafür verantwortlich, die Shell-Sitzung zwischen den Turns aufrechtzuerhalten.
  • Ausgabelimits: Die API kürzt Tool-Ergebnisse nicht (eine zu große Anfrage wird abgelehnt). Kürze große Ausgaben in deiner Anwendung, bevor du sie an Claude zurückgibst.
  • Kein Streaming: Die Ausgabe erreicht Claude erst, wenn deine Anwendung das tool_result in der nächsten Anfrage zurückgibt.

Kombination mit anderen Tools

Das Bash-Tool lässt sich gut mit dem Texteditor-Tool kombinieren: Claude bearbeitet eine Datei mit dem einen Tool und fordert mit dem anderen den Befehl an, der sie ausführt.

Nächste Schritte

Textdateien anzeigen und ändern, um Code zu debuggen, zu korrigieren und zu verbessern.

Verbinde Claude mit externen Tools und APIs. Erfahre, wo Tools ausgeführt werden, wann Claude sie aufruft und welches Tool zu deiner Aufgabe passt.

Was this page helpful?