Gli ambienti self-hosted sono in beta pubblica sui piani Team ed Enterprise; Disponibilità e limitazioni copre il percorso di abilitazione. Questa pagina è la ricetta di test CI; vedere quickstart per la configurazione e Distribuire in produzione per le ricette della flotta.
Installare l’hook di cattura sul vostro runner di test
La lettura funziona attraverso un hook Stop di Claude Code: quando Claude termina un turno, l’hook riceve il messaggio dell’assistente finale comelast_assistant_message nel JSON stdin e lo aggiunge a $E2E_REPLY_DIR/<session_id>.txt. Installatelo nello stesso modo dell’hook Stop commit-nudge, su ~/.claude/ dell’host del runner, che il runner semina in ogni sessione.
Salvare i file dell’hook
Salvate i due file seguenti sull’host del runner:- Il blocco delle impostazioni: unite in
~/.claude/settings.jsonsull’host del runner - Lo script: salvate come
~/.claude/hooks/e2e-stop-hook-capture.shsull’host del runner e rendetelo eseguibile
Prima di avviare il runner
Due cose da cui dipende l’hook:- Installatelo prima di avviare il runner. Il runner crea uno snapshot di
~/.claude/una sola volta all’avvio, quindi un hook aggiunto a un runner in esecuzione ha effetto solo dopo un riavvio. - Esportate
E2E_REPLY_DIRal processo del runner. L’hook è un no-op quando la variabile non è impostata o la directory non esiste, quindi impostatela ovunque avviate il runner, come l’unità systemd, la specifica del pod o il passo CI. Lo script di test di seguito lo richiede anche.
E2E_REPLY_DIR esiste, il che è innocuo su un runner CI monouso ma non qualcosa da portare in un’immagine di runner dell’ambiente di produzione dove la variabile potrebbe essere impostata accidentalmente.
Eseguire il ciclo di test
I flag di dispatch--environment e --ref richiedono Claude Code v2.1.224 o successivo sulla macchina che esegue lo script, lo stesso limite minimo del runner stesso. Con l’hook in posizione e un runner avviato su questo host, lo script di test:
- Crea una sessione sull’ambiente di test con
claude -p "<prompt>" --environment <environment-id> --output-format json, eseguito da un checkout git in modo che la CLI possa rilevare automaticamente il repository dal remoteorigin. L’opzionale--ref <branch>basa il checkout della sessione su un ref denominato invece di HEAD locale. Il comando crea la sessione, stampa una riga di JSON contenentesession_ide esce senza attendere la risposta di Claude. - Attende che la risposta appaia in
$E2E_REPLY_DIR/<session_id>.txt, scritta dall’hook Stop sul runner una volta completato il turno. - Invia un follow-up con
claude -p "<message>" --cloud <session_id> --output-format json(vedere Inviare un messaggio di follow-up a una sessione in esecuzione), che pubblica un evento utente nella sessione esistente e esce. - Attende la risposta del follow-up nello stesso modo del passo 2.
Comportamento del dispatch --environment
Claude Code crea la sessione, stampa l’ID della sessione e un link ad essa, e esce.
Il flag ha la precedenza sull’impostazione remote.defaultEnvironmentId. Non supporta --output-format stream-json e non può essere combinato con flag che riprendono, si collegano o preconfigurano una sessione, come --resume, --continue, --teleport, --session-id o --init-only. --cloud viene rifiutato con un ID di sessione o URL, e nelle esecuzioni non interattive quando porta una descrizione. Un --cloud nudo viene trattato come assente. Da un terminale, potete passare l’attività come descrizione --cloud invece di un prompt posizionale.
Script di esempio
Lo script seguente esegue il ciclo completo contro$CLAUDE_TEST_ENVIRONMENT_ID, l’ID ccpool_... del vostro ambiente di test, mostrato nella finestra di dialogo dei dettagli dell’ambiente nella pagina di amministrazione o restituito dalla chiamata create-environment, e asserisce su una frase sentinella in ogni risposta. Eseguitelo da un checkout git del repository su cui desiderate che la sessione funzioni, dopo aver avviato un runner su questo host con l’hook di cattura installato e E2E_REPLY_DIR esportato.
TURN1/TURN2 e i sentinella EXPECT1/EXPECT2 con qualsiasi cosa eserciti la vostra configurazione, come chiedere a Claude di eseguire uno dei vostri strumenti MCP personalizzati e asserire sul suo output.
Runner di test remoti
Se i vostri runner di test si trovano su infrastrutture separate, come una flotta Kubernetes persistente con cui il vostro job CI non può condividere un filesystem, scambiate la scrittura del file nell’hook Stop con un POST a un endpoint su cui il vostro driver ascolta:Autenticarsi da CI
Siaclaude -p ... --environment che claude -p ... --cloud si autenticano con un token OAuth di claude.ai; le chiavi API, come sk-ant-xxxxx, non sono accettate per nessuna delle due chiamate. Due approcci rendono disponibile un token in CI.
Host CI di lunga durata
Eseguiteclaude auth login una sola volta in modo interattivo sulla macchina che esegue lo script, utilizzando un account utente dedicato per l’automazione. Claude Code memorizza il token nel keychain del sistema operativo su macOS, o in ~/.claude/.credentials.json su Linux e Windows. Su un host macOS il cui Keychain non può essere scritto, come è tipico in una sessione SSH dove il Keychain di login rimane bloccato, Claude Code memorizza il token in ~/.claude/.credentials.json anche lì. Vedere Gestione delle credenziali.
La CLI aggiorna automaticamente il token di accesso di breve durata ad ogni invocazione, ma la concessione del token di aggiornamento sottostante è limitata a 30 giorni dall’accesso iniziale, quindi eseguite di nuovo claude auth login in modo interattivo su quell’host ogni 30 giorni.
Runner CI effimeri
Non esiste un token CI di lunga durata per questo oggi. L’ambito che concede il controllo della sessione remota,user:sessions:claude_code, è limitato lato server a 30 giorni, quindi claude setup-token, che conia un token di sola inferenza di un anno, non lo copre. Il segreto dell’ambiente non è accettato neanche, poiché autorizza solo un runner a registrarsi con l’ambiente, non a creare sessioni.
Per fornire un accesso memorizzato su un runner effimero, impostate CLAUDE_CODE_OAUTH_REFRESH_TOKEN e CLAUDE_CODE_OAUTH_SCOPES in modo che claude auth login scambi il token senza un browser; lo stesso limite di 30 giorni si applica alla concessione di aggiornamento. Contattate il vostro team di account Anthropic se avete bisogno di un percorso di identità della macchina che non sia legato a un account umano.
Creare un ambiente di test dedicato
Create e eliminate gli ambienti a livello di programmazione in modo che ogni esecuzione CI ottenga uno pulito; il runner che il vostro job CI avvia si registra nell’ambiente nuovo. Le chiamate di creazione e eliminazione di seguito sono gli stessi endpoint che la pagina di amministrazione Cloud environments su claude.ai utilizza, e richiedono l’intestazioneanthropic-beta: ccr-byoc-2025-07-29.
Coniare il token di amministrazione
$ADMIN_TOKEN è un token di accesso OAuth di claude.ai per un account che detiene un ruolo Owner, coniato nello stesso modo di Autenticarsi da CI:
- Coniarlo: eseguite
claude auth logincon un account che detiene un ruolo Owner, quindi leggete il token di accesso corrente da dove Host CI di lunga durata dice che Claude Code lo ha memorizzato. - Leggerlo fresco ad ogni esecuzione: la CLI ruota il token di accesso, e lo stesso limite di 30 giorni per la concessione di aggiornamento si applica, quindi non memorizzate una copia.
- Passarlo via stdin: come fa l’esempio, in modo che il token non finisca mai nell’elenco degli argomenti di curl o nel vostro log di build.
Creare l’ambiente
Catturate la risposta senza ecoarla:pool_secret è una credenziale di lunga durata che può registrare runner nell’ambiente, quindi memorizzatela come segreto CI mascherato e stampate solo l’ID dell’ambiente. La forma -H @- che mantiene il token fuori dall’elenco dei processi richiede curl 7.55 o successivo; curl più vecchio tratta @- come un’intestazione letterale e invia la richiesta senza autorizzazione.
403 permission_error che legge self-hosted runners are disabled by your organization's policy.
Avviate un runner su questo host con SELF_HOSTED_RUNNER_ENVIRONMENT_SECRET=$ENVIRONMENT_SECRET, più l’hook di cattura e E2E_REPLY_DIR per Installare l’hook di cattura, quindi eseguite lo script di test.