L'app lanciava solo `claude -p`. Si vuole usare dalla stessa chat anche **OpenAI Codex CLI** e **Antigravity CLI** (`agy`), così come `claude` già installati da terminale dall'utente, su Windows e Linux. L'app non li installa e non gestisce login: sono programmi esterni, autenticati a parte.
- **Astrazione "motore"** in C#. Ogni motore descrive: nome e eseguibile, argomenti per il primo messaggio e per la ripresa, elenco modelli, supporto effort, modo per ottenere l'id di sessione. `RunClaude` è diventato `EngineRunner` con il motore come parametro.
- **Rilevamento** dei motori cercando l'eseguibile nel PATH (su Windows anche le estensioni di PATHEXT). I motori assenti sono disabilitati nelle Impostazioni, con messaggio chiaro; la CLI esce con 127 come oggi.
- **Una chat = un motore**. Il file JSON della chat memorizza il motore; il contesto di sessione non passa da un motore all'altro, quindi cambiare motore apre una nuova chat.
- **Impostazioni** nella GUI: interruttore **CLI** (motore attivo), modello, effort. Cambiare motore apre una nuova chat; modello ed effort tornano ai valori iniziali del motore (il modello più piccolo ed effort `low`; "Predefinito" resta selezionabile) e le liste sono quelle del motore. La persistenza su disco delle impostazioni è rinviata. La CLI ottiene `--engine <id>` (`claude`, `codex`, `agy`).
- **Sessione**: per Claude Code l'id lo sceglie l'app; per Codex e Antigravity lo genera il motore e l'app lo legge dall'output (`thread_id` per Codex, `conversation_id` per Antigravity). Il JSON della chat ha quindi un campo `Engine` e un campo `SessionId` separato dall'id della chat (che resta il nome del file). I file scritti prima (senza questi campi) si leggono come chat di Claude Code con `SessionId` = id della chat.
- L'id di sessione non si sceglie: compare nel primo evento JSONL `{"type":"thread.started","thread_id":"<uuid>"}`. Nel testo normale compare solo nell'intestazione su stderr.
- Con `--json`, stdout contiene solo eventi: `thread.started`, `turn.started`, `item.completed` (con `item.type = "agent_message"` e il testo della risposta; con `"error"` sono avvisi non fatali), `turn.completed`, e in caso di errore `error` e `turn.failed`. Il messaggio di errore è una stringa che contiene a sua volta un JSON (`error.message`): l'app estrae il messaggio interno. L'exit code è 1 se il turno fallisce.
- La risposta mostrata è l'**ultimo** `agent_message` del turno (come `--output-last-message`).
-`exec resume`**non accetta `-s/--sandbox`**: la sola lettura si ottiene con `-c 'sandbox_mode="read-only"'`, verificato (un file richiesto in scrittura non viene creato). Accetta `-m` e `-c`.
-`--skip-git-repo-check` serve perché la cartella dell'exe non è un repository Git.
-`--` prima del prompt evita che un prompt che inizia con `-` sia letto come opzione (verificato).
- Lo stdin va chiuso subito, come per Claude Code: altrimenti Codex stampa "Reading additional input from stdin…" e attende.
- Il modello predefinito è quello di `~/.codex/config.toml`. Se richiede una versione più recente di Codex l'errore è chiaro (`requires a newer version of Codex`): l'app lo mostra e [INSTALL.md](../INSTALL.md) indica `codex update`.
- Il modello più piccolo di Codex è assunto essere GPT-5.6 Luna (nome e supporto agli effort inferiori: non dichiarato da OpenAI nelle prove); da rivedere quando cambia il catalogo.
- Il catalogo modelli di Codex è dinamico (`~/.codex/models_cache.json`); l'app ne usa uno fisso, da aggiornare, con "Predefinito" e "Altro ID…" sempre disponibili.
- Eseguibile nativo: ELF su Linux (`~/.gemini/bin/agy`), `.exe` nativo su Windows.
- Permessi e sicurezza: per usare `agy` in modalità non interattiva (`-p`) in sola lettura, nel file `~/.gemini/antigravity-cli/settings.json` deve essere presente la regola `'read_file(*)'` sotto `'permissions.allow'` (altrimenti headless mode nega `read_file` con errore jetski: `a tool required the read_file permission that headless mode cannot prompt for`), mentre scritture e comandi restano negati di default. Non si passa `--mode plan` (che fallisce anch'esso con errore jetski) né `--mode auto` (non disponibile per l'account) né alcun flag `--mode`. Mai usare `--dangerously-skip-permissions`.
- Posizione di `-p`: tutti i flag di configurazione vanno passati rigorosamente prima di `-p <prompt>`.
- Formato output: per la GUI (`structured = true`) si passa `--output-format json`; per la CLI si omette per ereditare testo normale. L'output JSON contiene `conversation_id`, `status` ("SUCCESS") e `response` con il testo generato.
- Sessione: l'id di sessione è un UUID generato da `agy` (`OwnsSessionId => true`), letto da `conversation_id`. La ripresa avviene passando `--conversation <sessionId>`.
- Blocco sottoprocesso su output rediretto (issue #318): mitigato passando `--print-timeout 120s` (formato durata Go) e assicurando la chiusura immediata dello stdin.
- Modelli ed effort: modelli fissi da catalogo `agy models`, modello più piccolo predefinito `gemini-3.0-flash-low`, effort supportati `low`, `medium`, `high`, `xhigh`, `max` (default `low`).
**Positive**: un solo flusso di avvio; nuovi motori aggiungibili con una definizione; elimina la duplicazione CLI/GUI.
**Negative**: i flag delle CLI cambiano nel tempo e vanno mantenuti; le sessioni non si trasferiscono tra motori; più superficie da testare su due sistemi operativi.
- [x]**Antigravity**: verificato il comando non interattivo `agy [flag] -p <prompt>`, output JSON `--output-format json`, ripresa con `--conversation`, timeout con `--print-timeout 120s` e chiusura stdin.
- [ ]**Forma dell'eseguibile**: `claude` e `agy` sono binari nativi avviabili direttamente; per installazioni tramite gestori di pacchetti verificare eventuali script wrapper su Windows.