Skip to main content
Self-Hosted-Umgebungen befinden sich in der öffentlichen Beta auf Team- und Enterprise-Plänen; Verfügbarkeit und Einschränkungen behandelt den Aktivierungspfad. Diese Seite ist das CI-Test-Rezept; siehe Schnellstart für Setup und In Produktion bereitstellen für die Fleet-Rezepte.
In einer Self-Hosted-Umgebung werden Claude Code Cloud-Sitzungen auf einem Runner-Image ausgeführt, das Sie erstellen und verwalten. Bevor Sie ein neues Image in Ihrer Produktionsumgebung bereitstellen, führen Sie eine vollständige Sitzung gegen eine Test-Umgebung aus einem Skript aus: erstellen Sie eine Sitzung, lesen Sie Claudes Antwort, senden Sie eine Nachfrage und lesen Sie auch diese Antwort. Dies ist die Form eines CI-Smoke-Tests, der Ihr Runner-Image, Git-Zugriff und alle benutzerdefinierten Tools überprüft, bevor Sie eine Änderung durchführen. Dieses Rezept setzt voraus, dass Sie bereits eine Umgebung und einen Runner eingerichtet haben, und dass Ihr CI-Job den Runner-Prozess auf demselben Host wie das Test-Skript startet, das natürliche Setup zum Testen eines neuen Runner-Images. Ein Stop-Hook, den Sie auf dem Runner installieren, schreibt die endgültige Antwort jeder Runde in eine lokale Datei, und das Skript liest sie von dort, sodass die einzigen Aufrufe der Anthropic API die beiden Dispatches selbst sind. Wenn sich Ihre Test-Runner auf separater Infrastruktur befinden, siehe Remote-Test-Runner.

Installieren Sie den Capture-Hook auf Ihrem Test-Runner

Das Zurücklesen funktioniert über einen Claude Code Stop-Hook: Wenn Claude eine Runde beendet, erhält der Hook die endgültige Assistenten-Nachricht als last_assistant_message in seinem stdin-JSON und hängt sie an $E2E_REPLY_DIR/<session_id>.txt an. Installieren Sie ihn auf die gleiche Weise wie den commit-nudge Stop-Hook, auf dem ~/.claude/ des Runner-Hosts, das der Runner in jede Sitzung einspeist.

Speichern Sie die Hook-Dateien

Speichern Sie die beiden folgenden Dateien auf dem Runner-Host:
  • Der Einstellungsblock: Zusammenführen in ~/.claude/settings.json auf dem Runner-Host
  • Das Skript: Speichern als ~/.claude/hooks/e2e-stop-hook-capture.sh auf dem Runner-Host und machen Sie es ausführbar

Bevor Sie den Runner starten

Zwei Dinge, auf die der Hook angewiesen ist:
  • Installieren Sie ihn, bevor Sie den Runner starten. Der Runner erstellt eine Momentaufnahme von ~/.claude/ einmal beim Start, sodass ein Hook, der zu einem laufenden Runner hinzugefügt wird, erst nach einem Neustart wirksam wird.
  • Exportieren Sie E2E_REPLY_DIR zum Runner-Prozess. Der Hook ist ein No-Op, wenn die Variable nicht gesetzt ist oder das Verzeichnis nicht existiert. Setzen Sie sie daher überall dort, wo Sie den Runner starten, z. B. in der systemd-Unit, Pod-Spezifikation oder CI-Schritt. Das Test-Skript unten benötigt es auch.
Installieren Sie diesen Hook nur auf Runnern, die Ihre Test-Umgebung bedienen. Er schreibt die endgültige Antwort jeder Sitzung auf die Festplatte, wenn E2E_REPLY_DIR existiert, was auf einem Wegwerf-CI-Runner harmlos ist, aber nicht in ein Produktionsumgebungs-Runner-Image gehört, in dem die Variable versehentlich gesetzt werden könnte.

Führen Sie die Test-Schleife aus

Die Dispatch-Flags --environment und --ref erfordern Claude Code v2.1.224 oder später auf dem Computer, auf dem das Skript ausgeführt wird, die gleiche Untergrenze wie der Runner selbst. Mit dem Hook an Ort und Stelle und einem auf diesem Host gestarteten Runner führt das Test-Skript folgende Schritte aus:
  1. Erstellt eine Sitzung in der Test-Umgebung mit claude -p "<prompt>" --environment <environment-id> --output-format json, ausgeführt aus einem Git-Checkout, damit die CLI das Repository aus dem origin-Remote automatisch erkennen kann. Das optionale --ref <branch> basiert auf dem Checkout der Sitzung auf einer benannten Referenz statt auf lokalem HEAD. Der Befehl erstellt die Sitzung, gibt eine Zeile JSON mit session_id aus und beendet sich, ohne auf Claudes Antwort zu warten.
  2. Wartet darauf, dass die Antwort in $E2E_REPLY_DIR/<session_id>.txt erscheint, geschrieben vom Stop-Hook auf dem Runner, sobald die Runde abgeschlossen ist.
  3. Sendet eine Nachverfolgung mit claude -p "<message>" --cloud <session_id> --output-format json (siehe Senden Sie eine Nachverfolgungsnachricht an eine laufende Sitzung), die ein Benutzerereignis in der vorhandenen Sitzung bereitstellt und beendet sich.
  4. Wartet auf die Antwort der Nachverfolgung auf die gleiche Weise wie Schritt 2.

--environment Dispatch-Verhalten

Claude Code erstellt die Sitzung, gibt die Sitzungs-ID und einen Link dazu aus und beendet sich. Das Flag hat Vorrang vor der remote.defaultEnvironmentId-Einstellung. Es unterstützt nicht --output-format stream-json und kann nicht mit Flags kombiniert werden, die eine Sitzung fortsetzen, anhängen oder vorkonfigurieren, wie z. B. --resume, --continue, --teleport, --session-id oder --init-only. --cloud wird mit einer Sitzungs-ID oder URL abgelehnt und in nicht-interaktiven Läufen, wenn es eine Beschreibung trägt. Ein bloßes --cloud wird als abwesend behandelt. Von einem Terminal aus können Sie die Aufgabe statt eines positionalen Prompts als --cloud-Beschreibung übergeben.

Beispielskript

Das folgende Skript führt die vollständige Schleife gegen $CLAUDE_TEST_ENVIRONMENT_ID, die ccpool_...-ID Ihrer Test-Umgebung, angezeigt im Detaildialog der Umgebung auf der Admin-Seite oder zurückgegeben durch den create-environment-Aufruf, aus und behauptet eine Sentinel-Phrase in jeder Antwort. Führen Sie es aus einem Git-Checkout des Repositorys aus, in dem die Sitzung arbeiten soll, nachdem Sie einen Runner auf diesem Host mit dem installierten Capture-Hook und exportiertem E2E_REPLY_DIR gestartet haben.
Ersetzen Sie die TURN1/TURN2-Prompts und EXPECT1/EXPECT2-Sentinels durch alles, was Ihr Setup ausübt, z. B. Claude auffordern, eines Ihrer benutzerdefinierten MCP-Tools auszuführen und seine Ausgabe zu behaupten.

Remote-Test-Runner

Wenn sich Ihre Test-Runner auf separater Infrastruktur befinden, z. B. eine persistente Kubernetes-Fleet, mit der Ihr CI-Job kein Dateisystem teilen kann, tauschen Sie den Dateischreibvorgang im Stop-Hook gegen einen POST an einen Endpunkt aus, auf den Ihr Driver lauscht:
Führen Sie auf der Driver-Seite alles aus, das den POST akzeptiert und die Antwort hält, bis der Test sie anfordert, z. B. einen kleinen HTTP-Listener innerhalb des CI-Jobs oder einen Webhook-Receiver, den Sie bereits ausführen. Der Hook wird auf Ihrer Infrastruktur ausgeführt, sodass der Endpunkt nur von Ihren Runnern erreichbar sein muss.

Authentifizieren Sie sich von CI

Sowohl claude -p ... --environment als auch claude -p ... --cloud authentifizieren sich mit einem claude.ai OAuth-Token; API-Schlüssel wie sk-ant-xxxxx werden für keinen der beiden Aufrufe akzeptiert. Zwei Ansätze machen ein Token in CI verfügbar.

Langlebiger CI-Host

Führen Sie claude auth login einmal interaktiv auf dem Computer aus, auf dem das Skript ausgeführt wird, mit einem dedizierten Benutzerkonto für Automatisierung. Claude Code speichert das Token im OS-Keychain auf macOS oder in ~/.claude/.credentials.json auf Linux und Windows. Auf einem macOS-Host, dessen Keychain nicht geschrieben werden kann, wie es typisch in einer SSH-Sitzung der Fall ist, in der der Login-Keychain gesperrt bleibt, speichert Claude Code das Token auch dort in ~/.claude/.credentials.json. Siehe Credential-Verwaltung. Die CLI aktualisiert das kurzlebige Zugriffstoken automatisch bei jeder Invokation, aber die zugrunde liegende Refresh-Token-Gewährung ist auf 30 Tage ab der ersten Anmeldung begrenzt. Führen Sie daher claude auth login interaktiv auf diesem Host alle 30 Tage erneut aus.

Ephemere CI-Runner

Es gibt heute kein langlebiges CI-Token dafür. Der Umfang, der Remote-Sitzungskontrolle gewährt, user:sessions:claude_code, ist serverseitig auf 30 Tage begrenzt, sodass claude setup-token, das ein einjähriges Inference-only-Token prägt, es nicht abdeckt. Das Umgebungsgeheimnis wird auch nicht akzeptiert, da es nur einen Runner autorisiert, sich bei der Umgebung zu registrieren, nicht um Sitzungen zu erstellen. Um eine gespeicherte Anmeldung auf einem ephemeren Runner bereitzustellen, setzen Sie CLAUDE_CODE_OAUTH_REFRESH_TOKEN und CLAUDE_CODE_OAUTH_SCOPES, damit claude auth login das Token ohne Browser austauscht; die gleiche 30-Tage-Obergrenze gilt für die Refresh-Gewährung. Kontaktieren Sie Ihr Anthropic-Kontoteam, wenn Sie einen Machine-Identity-Pfad benötigen, der nicht an ein menschliches Konto gebunden ist.

Erstellen Sie eine dedizierte Test-Umgebung

Erstellen und löschen Sie Umgebungen programmgesteuert, damit jeder CI-Lauf eine saubere erhält; der Runner, den Ihr CI-Job startet, registriert sich in der neuen Umgebung. Die unten aufgeführten Aufrufe zum Erstellen und Löschen sind die gleichen Endpunkte, die die Cloud-Umgebungen-Admin-Seite auf claude.ai verwendet, und sie erfordern den Header anthropic-beta: ccr-byoc-2025-07-29.

Prägen Sie das Admin-Token

$ADMIN_TOKEN ist ein claude.ai OAuth-Zugriffstoken für ein Konto, das eine Owner-Rolle hält, geprägt auf die gleiche Weise wie Authentifizieren Sie sich von CI:
  • Prägen Sie es: Führen Sie claude auth login mit einem Konto aus, das eine Owner-Rolle hält, und lesen Sie dann das aktuelle Zugriffstoken von überall dort, wo Langlebiger CI-Host sagt, dass Claude Code es gespeichert hat.
  • Lesen Sie es bei jedem Lauf neu: Die CLI rotiert das Zugriffstoken, und die gleiche 30-Tage-Refresh-Grant-Obergrenze gilt, speichern Sie also keine Kopie.
  • Übergeben Sie es über stdin: wie das Beispiel, damit das Token nie in Curls Argumentliste oder Ihrem Build-Log landet.

Erstellen Sie die Umgebung

Erfassen Sie die Antwort, ohne sie auszugeben: pool_secret ist eine langlebige Anmeldeinformation, die Runner in der Umgebung registrieren kann. Speichern Sie sie als maskiertes CI-Geheimnis und geben Sie nur die Umgebungs-ID aus. Das -H @--Formular, das das Token aus der Prozessliste hält, erfordert curl 7.55 oder später; älteres curl behandelt @- als wörtlichen Header und sendet die Anfrage ohne Autorisierung.
Bis ein Owner Allow self-hosted environments für die Organisation aktiviert hat, schlägt der Aufruf mit einem 403 permission_error fehl, der self-hosted runners are disabled by your organization's policy liest. Starten Sie einen Runner auf diesem Host mit SELF_HOSTED_RUNNER_ENVIRONMENT_SECRET=$ENVIRONMENT_SECRET, plus den Capture-Hook und E2E_REPLY_DIR pro Installieren Sie den Capture-Hook, dann führen Sie das Test-Skript aus.

Löschen Sie die Umgebung

Löschen Sie die Umgebung, wenn der Lauf beendet ist, damit jeder CI-Lauf sauber startet: