Aggiunge la Fase 4 alla roadmap (più motori, selezione dalle Impostazioni) e un rimando nel fuori scope di MVP.md. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
65 lines
6.8 KiB
Markdown
65 lines
6.8 KiB
Markdown
# MVP (doc-first)
|
||
|
||
## Obiettivo
|
||
Eseguibile C# a riga di comando che inoltra un prompt a Claude Code (`claude`) lanciandolo nella directory dell'eseguibile, e ne mostra l'output.
|
||
|
||
## Uso
|
||
```
|
||
llmrun.exe "spiega questo progetto"
|
||
```
|
||
Tutti gli argomenti sono uniti in un unico prompt.
|
||
|
||
## Comportamento
|
||
1. Se non ci sono argomenti: stampa l'uso ed esce con codice 2.
|
||
2. Avvia `claude -p <prompt>` (modalità non interattiva) con `WorkingDirectory = AppContext.BaseDirectory`.
|
||
3. Ritrasmette stdout e stderr del processo figlio in tempo reale.
|
||
4. Esce con lo stesso exit code di `claude`.
|
||
5. Se `claude` non è trovato: messaggio chiaro ed exit code 127.
|
||
|
||
## GUI (chat)
|
||
Senza argomenti si apre una finestra WinForms che contiene solo un WebView2: l'intera interfaccia (header, conversazione, composer) è HTML/CSS in `ui.html`, in stile claude.ai/ChatGPT. Con argomenti resta la CLI.
|
||
|
||
**Struttura della pagina**
|
||
- **Barra laterale** (sinistra, comprimibile): logo e nome, pulsante **Nuova chat**, elenco delle chat salvate (titolo = inizio del primo messaggio, data/ora dell'ultimo scambio; la chat aperta è evidenziata). Un clic su una chat la riapre; la ✕ (con conferma) la elimina. Elenco vuoto: "Nessuna chat salvata".
|
||
- **Conversazione**: messaggi alternati utente/Claude, aggiunti al DOM uno alla volta (nessun ricaricamento, nessuno sfarfallio). Le risposte sono renderizzate in markdown (Markdig, lato C#): titoli, liste, tabelle, citazioni, blocchi di codice. Sulle risposte il pulsante **Copia** copia il markdown; sui blocchi di codice copia il codice.
|
||
- **Schermata iniziale** (chat vuota): titolo, sottotitolo e quattro suggerimenti cliccabili che precompilano il campo.
|
||
- **Composer** (in basso, scheda arrotondata): textarea che cresce fino a ~8 righe, selettori **Modello** (Predefinito, Fable 5.1, Opus 5.5, Sonnet 5.5, Haiku 5.5, "Altro ID…" con campo libero) ed **Effort** (Predefinito, low, medium, high, xhigh, max), pulsante Invia circolare con icona. `Invio` invia, `Maiusc+Invio` va a capo. Hint sulla tastiera sotto la scheda.
|
||
- Passati come `--model` / `--effort`; con "Predefinito" il flag viene omesso. Solo GUI.
|
||
- **Contesto**: `claude -p --session-id <guid>` al primo messaggio, `--resume <guid>` ai successivi. "Nuova chat" svuota la vista e genera un nuovo guid.
|
||
- **Cronologia**: dopo ogni scambio la chat è salvata in `%LOCALAPPDATA%\LlmRun\chats\<guid>.json` (guid = id di sessione di `claude`, titolo, data, flag `started`, messaggi con ruolo e testo). Riaprendo una chat si rimostra la conversazione e si prosegue con `--resume <guid>`, quindi `claude` ricorda il contesto. Il messaggio dell'utente viene salvato subito, prima della risposta (così non si perde se l'app si chiude mentre Claude risponde); la risposta si aggiunge appena arriva. Una chat nuova e vuota non viene salvata. **All'avvio l'app riapre automaticamente l'ultima conversazione** (la più recente); se non ce ne sono parte con la schermata iniziale. "Nuova chat" resta sempre disponibile. Eliminare una chat cancella solo il file JSON, non la sessione di `claude`. Non si può aprire/eliminare una chat mentre Claude sta rispondendo.
|
||
- **Limite noto**: la sessione di `claude` è legata alla cartella in cui gira (quella dell'exe): se si sposta l'exe, le vecchie chat si leggono ancora ma `--resume` non ritrova il contesto.
|
||
- La risposta compare a fine generazione (nessuno streaming); durante l'attesa un indicatore a puntini animati e Invia disabilitato. Se `claude` esce con errore, lo stderr appare come messaggio di errore.
|
||
- I link si aprono nel browser di sistema. L'HTML grezzo nel markdown è disabilitato.
|
||
- Finestra orizzontale con proporzioni 16:10: larga il 75% dell'area utile dello schermo (max 1440px), altezza di conseguenza (max 90% dell'area utile), centrata; minimo 900x600. Su un monitor Full HD 1920x1080 risulta circa 1440x900.
|
||
|
||
**Protocollo pagina ↔ C#** (`WebMessage` JSON). Pagina→C#: `{type:"send", text, model, effort}`, `{type:"reset"}`, `{type:"list"}`, `{type:"open", id}`, `{type:"delete", id}`. C#→pagina: `{type:"ai", html, md}`, `{type:"err", text}`, `{type:"done"}`, `{type:"chats", current, items:[{id,title,updated}]}`, `{type:"load", messages:[{role,text,html?}]}` (sostituisce la conversazione mostrata).
|
||
|
||
### Design (UI/UX)
|
||
Sorgente di verità per l'aspetto, derivato dalla skill `ui-ux-pro-max` (stile "strumento per sviluppatori": slate + accento verde).
|
||
- **Tema**: segue Windows (chiaro/scuro) via `prefers-color-scheme`; la barra del titolo segue `Application.SetColorMode(SystemColorMode.System)`; lo sfondo del WebView2 è impostato per evitare il lampo bianco all'avvio.
|
||
- **Token** (chiaro / scuro): sfondo `#FFFFFF` / `#0F172A`, superficie composer `#FFFFFF` / `#1E293B`, testo `#0F172A` / `#F8FAFC`, testo secondario `#475569` / `#94A3B8`, bordi `#CBD5E1` / `#334155`, accento `#15803D` / `#22C55E`, errore `#B91C1C` / `#F87171`. Contrasto testo ≥ 4.5:1.
|
||
- **Tipografia**: Segoe UI Variable (corpo 15.5px, interlinea 1.65), Cascadia Code/Consolas per il codice. Nessun font web (funziona offline).
|
||
- **Forma e movimento**: raggi 10–20px, ombra leggera sul composer, transizioni 150ms, comparsa dei messaggi 180ms; con `prefers-reduced-motion` tutto fermo.
|
||
- **Barra laterale**: sfondo `--muted`, 272px; voce attiva con barra d'accento a sinistra; ✕ visibile solo al passaggio/focus.
|
||
- **Accessibilità**: focus sempre visibile, `aria-label` sui pulsanti a sola icona, `role=log`/`aria-live` sulla conversazione, `role=status` sull'attesa, target ≥ 36px, nessuna emoji come icona.
|
||
- **Non incluso**: evidenziazione sintattica del codice (richiederebbe una libreria da incorporare).
|
||
|
||
## Scelte tecniche
|
||
- .NET 10 (WinForms). `Program.cs` (CLI + avvio) e `Gui.cs` (chat). Dipendenze NuGet solo per la GUI: `Markdig` (markdown→HTML) e `Microsoft.Web.WebView2` (richiede il runtime WebView2, già presente su Windows 11).
|
||
- `ProcessStartInfo.ArgumentList` per passare il prompt (niente problemi di quoting).
|
||
- `claude` è un .exe nativo (`~/.local/bin`): si avvia direttamente, senza `cmd /c`. Lo stdin è chiuso subito per evitare l'attesa di 3s di claude.
|
||
- Working dir: `AppContext.BaseDirectory`, non la cwd del chiamante.
|
||
|
||
## Fuori scope (MVP)
|
||
Streaming token-per-token nella GUI, annullamento di una risposta in corso, rinomina/ricerca delle chat, config file, altri motori oltre a Claude Code (Codex, Antigravity: vedi [ROADMAP.md](ROADMAP.md), Fase 4), logging su file, test automatici, supporto Linux/macOS.
|
||
|
||
## Criteri di accettazione
|
||
- [ ] Eseguito da un'altra cartella, `claude` parte nella cartella dell'exe (verificabile chiedendo "pwd").
|
||
- [ ] L'output appare in streaming, non solo alla fine.
|
||
- [ ] L'exit code è propagato.
|
||
- [ ] Un prompt con virgolette e spazi arriva intatto.
|
||
|
||
## Domande aperte
|
||
- Permessi: serve `--allowedTools` o `--permission-mode` per l'uso non interattivo?
|
||
- Formato output: testo semplice o `--output-format stream-json`?
|