Lingkungan self-hosted berada dalam beta publik pada paket Team dan Enterprise; Ketersediaan dan batasan mencakup jalur pengaktifan. Halaman ini adalah resep uji CI; lihat quickstart untuk setup dan Deploy ke production untuk resep fleet.
Instal hook capture pada runner uji Anda
Pembacaan kembali bekerja melalui Claude Code Stop hook: ketika Claude menyelesaikan giliran, hook menerima pesan asisten akhir sebagailast_assistant_message dalam JSON stdin-nya dan menambahkannya ke $E2E_REPLY_DIR/<session_id>.txt. Instal dengan cara yang sama seperti commit-nudge Stop hook, pada ~/.claude/ host runner, yang runner semai ke dalam setiap sesi.
Simpan file hook
Simpan dua file di bawah pada host runner:- Blok settings: gabungkan ke
~/.claude/settings.jsonpada host runner - Skrip: simpan sebagai
~/.claude/hooks/e2e-stop-hook-capture.shpada host runner dan buat dapat dieksekusi
Sebelum Anda memulai runner
Hook memiliki persyaratan berikut:- Instal sebelum Anda memulai runner. Runner mengambil snapshot
~/.claude/sekali saat startup, jadi hook yang ditambahkan ke runner yang berjalan hanya berlaku setelah restart. - Ekspor
E2E_REPLY_DIRke proses runner. Hook adalah no-op ketika variabel tidak diatur atau direktori tidak ada, jadi atur di mana pun Anda memulai runner, seperti unit systemd, pod spec, atau langkah CI. Skrip uji di bawah juga memerlukan itu.
E2E_REPLY_DIR ada, yang tidak berbahaya pada runner CI yang dapat dibuang tetapi bukan sesuatu yang dibawa ke gambar runner lingkungan produksi di mana variabel mungkin diatur secara tidak sengaja.
Jalankan loop uji
Flag dispatch--environment dan --ref memerlukan Claude Code v2.1.224 atau lebih baru pada mesin yang menjalankan skrip, lantai yang sama dengan runner itu sendiri. Dengan hook di tempat dan runner dimulai pada host ini, skrip uji:
- Membuat sesi pada lingkungan uji dengan
claude -p "<prompt>" --environment <environment-id> --output-format json. Jalankan perintah dari checkout git sehingga CLI dapat mendeteksi repositori secara otomatis dari remoteorigin.--ref <branch>opsional mendasarkan checkout sesi pada ref bernama alih-alih HEAD lokal. Perintah keluar tanpa menunggu balasan Claude. Apa yang dicetaknya memberi tahu skrip Anda hasilnya:- Sesi berhasil dibuat: satu baris JSON seperti
{"ok":true,"session_id":"session_...","title":"...","url":"...","pool_id":"..."} - Pembuatan sesi gagal: baris
{"ok":false,"error":"..."}, dan perintah keluar dengan status 1 - Beberapa error yang lebih awal, seperti sesi cloud yang tidak tersedia untuk organisasi Anda atau prompt yang tidak ada: error di stderr tanpa baris JSON, dan perintah keluar dengan status 1
- Sesi berhasil dibuat: satu baris JSON seperti
- Menunggu balasan muncul di
$E2E_REPLY_DIR/<session_id>.txt, ditulis oleh hook Stop pada runner setelah giliran selesai. - Mengirim follow-up dengan
claude -p "<message>" --cloud <session_id> --output-format json(lihat Kirim pesan follow-up ke sesi yang berjalan), yang memposting acara pengguna ke sesi yang ada dan keluar. - Menunggu balasan follow-up dengan cara yang sama seperti langkah 2.
Perilaku dispatch --environment
Claude Code membuat sesi, mencetak ID sesi dan tautan ke sesi, dan keluar.
Flag mengambil prioritas atas pengaturan remote.defaultEnvironmentId. Ini tidak mendukung --output-format stream-json, dan tidak dapat digabungkan dengan flag yang melanjutkan, melampirkan, atau prekonfigurasi sesi, seperti --resume, --continue, --teleport, --session-id, atau --init-only. --cloud ditolak dengan ID sesi atau URL, dan dalam run non-interaktif ketika membawa deskripsi. --cloud kosong diperlakukan sebagai tidak ada. Dari terminal, Anda dapat meneruskan tugas sebagai deskripsi --cloud daripada prompt posisional.
Skrip contoh
Skrip contoh berjalan pada mesin yang sama dengan test runner. Sebelum Anda menjalankannya, siapkan mesin tersebut:- Checkout repositori: jalankan skrip dari checkout git repositori yang ingin dikerjakan sesi.
- Runner: mulai runner pada host ini dengan hook capture terinstal dan
E2E_REPLY_DIRdiekspor. - Masuk: masuk dengan akun claude.ai pada mesin yang menjalankan skrip, seperti yang dijelaskan dalam Autentikasi dari CI.
- ID lingkungan: atur
CLAUDE_TEST_ENVIRONMENT_IDke IDccpool_...lingkungan uji Anda, yang ditampilkan dalam dialog detail lingkungan pada halaman admin atau dikembalikan oleh panggilan create-environment.
$CLAUDE_TEST_ENVIRONMENT_ID dan menegaskan pada frasa sentinel di setiap balasan.
TURN1/TURN2 dan sentinel EXPECT1/EXPECT2 dengan apa pun yang menjalankan setup Anda, seperti meminta Claude menjalankan salah satu alat MCP kustom Anda dan menegaskan pada outputnya.
Remote test runners
Jika runner uji Anda berada pada infrastruktur terpisah, seperti fleet Kubernetes persisten yang pekerjaan CI Anda tidak dapat berbagi filesystem dengannya, tukar penulisan file dalam hook Stop untuk POST ke endpoint yang driver Anda dengarkan:Autentikasi dari CI
Baikclaude -p ... --environment maupun claude -p ... --cloud autentikasi dengan token OAuth claude.ai; kunci API, seperti sk-ant-xxxxx, tidak diterima untuk panggilan apa pun. Dua pendekatan membuat token tersedia di CI.
Host CI jangka panjang
Jalankanclaude auth login sekali secara interaktif pada mesin yang menjalankan skrip, menggunakan akun pengguna khusus untuk otomasi. Claude Code menyimpan token di OS keychain pada macOS, atau di ~/.claude/.credentials.json pada Linux dan Windows. Pada host macOS yang Keychain-nya tidak dapat ditulis, seperti yang khas dalam sesi SSH di mana Keychain login tetap terkunci, Claude Code menyimpan token di ~/.claude/.credentials.json di sana juga. Lihat Credential management.
CLI menyegarkan token akses jangka pendek secara otomatis pada setiap invokasi, tetapi hibah refresh-token yang mendasar dibatasi pada 30 hari dari login awal, jadi jalankan kembali claude auth login secara interaktif pada host itu setiap 30 hari.
Runner CI Ephemeral
Tidak ada token CI jangka panjang untuk ini hari ini. Scope yang memberikan kontrol sesi jarak jauh,user:sessions:claude_code, dibatasi server-side pada 30 hari, jadi claude setup-token, yang mencetak token inference-only satu tahun, tidak mencakupnya. Environment secret juga tidak diterima, karena hanya mengotorisasi runner untuk mendaftar dengan lingkungan, bukan untuk membuat sesi.
Untuk menyediakan login yang disimpan ke runner ephemeral, atur CLAUDE_CODE_OAUTH_REFRESH_TOKEN dan CLAUDE_CODE_OAUTH_SCOPES sehingga claude auth login menukar token tanpa browser; batas 30 hari yang sama berlaku untuk hibah refresh. Hubungi tim akun Anthropic Anda jika Anda memerlukan jalur identitas mesin yang tidak terikat pada akun manusia.
Buat lingkungan uji khusus
Buat dan hapus lingkungan secara terprogram sehingga setiap run CI mendapatkan yang bersih; runner yang pekerjaan CI Anda mulai mendaftar ke lingkungan segar. Panggilan create dan delete di bawah adalah endpoint yang sama yang digunakan halaman admin Cloud environments pada claude.ai, dan mereka memerlukan headeranthropic-beta: ccr-byoc-2025-07-29.
Cetak token admin
$ADMIN_TOKEN adalah token akses OAuth claude.ai untuk akun yang memegang peran Owner, dicetak dengan cara yang sama seperti Authenticate from CI:
- Cetak itu: jalankan
claude auth logindengan akun yang memegang peran Owner, kemudian baca token akses saat ini dari mana pun Long-lived CI host mengatakan Claude Code menyimpannya. - Baca segar setiap run: CLI memutar token akses, dan batas hibah refresh 30 hari yang sama berlaku, jadi jangan simpan salinan.
- Teruskan melalui stdin: seperti contoh, jadi token tidak pernah mendarat di daftar argumen curl atau log build Anda.
Buat lingkungan
Tangkap respons tanpa mencetaknya:pool_secret adalah kredensial jangka panjang yang dapat mendaftarkan runner ke lingkungan, jadi simpan sebagai rahasia CI yang disembunyikan dan cetak hanya ID lingkungan. Bentuk -H @- yang membuat token keluar dari daftar proses memerlukan curl 7.55 atau lebih baru; curl yang lebih lama memperlakukan @- sebagai header literal dan mengirim permintaan tanpa otorisasi.
403 permission_error membaca self-hosted runners are disabled by your organization's policy.
Mulai runner pada host ini dengan SELF_HOSTED_RUNNER_ENVIRONMENT_SECRET=$ENVIRONMENT_SECRET, ditambah hook capture dan E2E_REPLY_DIR per Install the capture hook, kemudian jalankan skrip uji.