Ho Intercettato il Cervello di Cursor: Reverse Engineering dell’Editor AI Piu’ Usato al Mondo

Technical illustration of reverse engineering Cursor AI code editor

🇬🇧 Read this article in English

Ho puntato un proxy LiteLLM verso Cursor, ho scritto “hello,” e ho catturato l’intera traccia API. Quello che e’ tornato indietro e’ un file JSON da 577KB contenente il system prompt completo, tutte le 16 definizioni degli strumenti, i parametri dei modelli, le catene di fallback, e l’intera architettura di uno degli agenti AI per il coding piu’ popolari al mondo.

Non sono speculazioni. Non e’ un “secondo me Cursor probabilmente fa X.” Questa e’ la traccia grezza, catturata direttamente dalla rete. Ed e’ affascinante.

Il Setup: Come Catturare il Cervello di Cursor

Cursor non parla direttamente con OpenAI. Nelle configurazioni enterprise, passa attraverso un proxy. Ho configurato LiteLLM (un gateway LLM open-source) con il tracing di Langfuse abilitato, ho puntato Cursor verso di esso, e ho scritto una sola parola: “hello.”

La traccia ha catturato tutto: il body completo della richiesta HTTP, i parametri del modello, gli schemi degli strumenti, e l’intera architettura della conversazione. Una parola da parte mia. Piu’ di 10.000 parole da Cursor verso il modello. Analizziamole.

Il System Prompt: 10.000 Parole Prima Che Tu Dica Qualcosa

Qui le cose si fanno interessanti. Prima che il tuo messaggio raggiunga il modello, Cursor inietta un system prompt di oltre 10.000 parole. Questo e’ il manuale di istruzioni che il modello legge prima di elaborare un singolo carattere del tuo input.

Prima di analizzare il prompt, due parametri del modello nella traccia saltano all’occhio. Lo sforzo di ragionamento e’ impostato su “medium”, non al massimo. Cursor non brucia token per catene di pensiero profonde ad ogni interazione. E viene richiesto reasoning.encrypted_content, il che significa che il ragionamento interno del modello e’ criptato in transito. Non vedi mai la catena di pensiero grezza. Il modello pensa in privato.

Il prompt e’ strutturato usando tag simili a XML come delimitatori di sezione. Non perche’ l’XML sia di moda (non lo e’), ma perche’ gli LLM sono estremamente bravi a rispettare i confini definiti dai tag. Ecco lo scheletro:

<persistence> ... </persistence>
<system-communication> ... </system-communication>
<markdown_spec> ... </markdown_spec>
<user_updates_spec> ... </user_updates_spec>
<tone_and_style> ... </tone_and_style>
<tool_calling> ... </tool_calling>
<making_code_changes> ... </making_code_changes>
<citing_code> ... </citing_code>
<terminal_files_information> ... </terminal_files_information>
<task_management> ... </task_management>
<mcp_file_system> ... </mcp_file_system>
<mode_selection> ... </mode_selection>

Analizziamo le sezioni piu’ interessanti.

La Direttiva di Persistenza: “Non Fermarti Mai”

La primissima sezione e’ <persistence>, ed e’ etichettata come CRITICAL. Recita:

“Sei un agente: continua finche’ la richiesta dell’utente non e’ completamente risolta, prima di terminare il tuo turno. Non fermarti mai davanti all’incertezza: ricerca o deduci l’approccio piu’ ragionevole e continua. Non chiedere all’umano di confermare le assunzioni: documentale, agisci su di esse, e aggiusta in corsa se si rivelano sbagliate.”

Questa e’ la singola istruzione piu’ importante dell’intero prompt. Trasforma il modello da un chatbot che si ferma e fa domande in un agente autonomo che capisce le cose e va avanti. La maggior parte dei builder di agenti amatoriali perde completamente questo punto. Lasciano che il modello chieda “devo continuare?” ad ogni punto di decisione, creando un’esperienza utente terribile. Cursor lo proibisce esplicitamente.

Aggiornamenti Utente: Il Protocollo di Comunicazione

La sezione <user_updates_spec> e’ sorprendentemente dettagliata. Stabilisce esattamente come l’agente deve comunicare i progressi:

  • Lunghezza aggiornamento: 1-2 frasi, 25-50 parole. Mai piu’ di 3 frasi tranne nel piano iniziale e nella risposta finale.
  • Cadenza: Un aggiornamento ogni 2-3 chiamate di tool. Mai piu’ di 5 tool call senza aggiornare.
  • Tono: “Amichevole, sicuro, collaborativo. Sii positivo e umile; ammetti gli errori e correggili velocemente.”
  • Esplicitamente: niente header markdown negli aggiornamenti, solo nel riassunto finale.

Questa e’ ingegneria UX integrata direttamente nel prompt. Cursor ha riconosciuto che guardare un agente lavorare in silenzio per 30 secondi genera ansia, quindi hanno reso obbligatori gli aggiornamenti regolari.

Modifiche al Codice: La Regola “Leggi Prima”

C’e’ una regola nascosta in <making_code_changes> facile da perdere ma critica: “DEVI usare lo strumento Read almeno una volta prima di modificare.” Questo impedisce al modello di allucinare il contenuto dei file e sovrascrivere codice basandosi su quello che pensa ci sia nel file piuttosto che quello che c’e’ davvero. E’ l’equivalente software di “misura due volte, taglia una volta,” ed e’ applicato a livello di prompt.

I 16 Strumenti: Cosa Puo’ Fare Davvero Cursor

Ogni definizione di strumento viene inviata per intero con ogni chiamata API. Costoso in termini di token, ma necessario perche’ il modello non ha memoria persistente degli schemi tra le chiamate. Ecco il toolkit completo:

Operazioni su File (5 strumenti)

  • Read: Legge file con offset/limit opzionali. Supporta immagini (JPEG, PNG, GIF, WebP) e PDF.
  • ApplyPatch: Il gioiello della corona. Ne parliamo dopo.
  • Delete: Cancellazione file semplice con fallimento grazioso.
  • Glob: Pattern matching su file, ordinati per data di modifica.
  • EditNotebook: Modifica celle di notebook Jupyter.

Ricerca (2 strumenti)

  • Grep: Basato su ripgrep. Supporta regex, filtraggio per tipo di file, modalita’ di output, paginazione.
  • SemanticSearch: Ricerca basata su embedding che trova codice per significato, non per testo esatto.

Esecuzione (1 strumento)

  • Shell: Esecuzione comandi con sessioni stateful (cwd e variabili d’ambiente persistono). Supporta processi in background con un filesystem di terminale. Non e’ un banale wrapper subprocess.run().

Web (2 strumenti)

  • WebSearch: Ricerca web in tempo reale con data di oggi iniettata dinamicamente.
  • WebFetch: Fetch di contenuti URL con conversione in markdown.

Integrazione IDE (2 strumenti)

  • ReadLints: Recupera errori del linter dal workspace.
  • SwitchMode: Cambia tra le modalita’ Agent, Plan, Debug e Ask.

Orchestrazione Agenti (1 strumento)

  • Task: Lancia subagenti. Questo e’ il sistema multi-agente di Cursor.

Interazione Utente (2 strumenti)

  • AskQuestion: Presenta domande a scelta multipla strutturate all’utente.
  • GenerateImage: Generazione immagini da descrizioni testuali.

Estensibilita’ (2 strumenti)

  • CallMcpTool: Chiama qualsiasi strumento MCP (Model Context Protocol). E’ cosi’ che Cursor integra automazione browser, API personalizzate e strumenti di terze parti.
  • FetchMcpResource: Legge risorse MCP (dati in sola lettura dai server MCP).
Visualizzazione dei 16 strumenti interconnessi di Cursor e architettura multi-agente
Sedici strumenti, quattro tipi di agenti, un system prompt molto lungo.

ApplyPatch: Il Linguaggio Diff Personalizzato di Cursor

Questo e’ lo strumento tecnicamente piu’ interessante dell’intera suite. Cursor non usa i diff unificati standard. Non usa l’approccio di passare interi contenuti di file. Ha inventato il suo linguaggio di patch con una grammatica formale definita in Lark (un toolkit di parsing Python):

start: begin_patch hunk end_patch
begin_patch: "*** Begin Patch" LF
end_patch: "*** End Patch" LF?

hunk: add_hunk | update_hunk
add_hunk: "*** Add File: " filename LF add_line+
update_hunk: "*** Update File: " filename LF change?

Questo e’ un formato di decodifica vincolata. Il modello deve produrre patch sintatticamente valide. Perche’ tutta questa fatica? Tre ragioni:

  1. Efficienza di token: Inviare solo le righe modificate con 3 righe di contesto e’ drasticamente piu’ economico che inviare l’intero file per ogni modifica.
  2. Applicazione deterministica: Il formato patch puo’ essere analizzato e applicato meccanicamente.
  3. Vincoli grammaticali: Fornendo una grammatica formale, Cursor puo’ usare la decodifica vincolata per garantire che l’output del modello sia una patch valida.

Se stai costruendo il tuo agente di coding, questa e’ l’idea a piu’ alto impatto da rubare. La maggior parte degli agenti o riscrive interi file (costoso, soggetto a errori) o usa str.replace() (fragile). L’approccio di Cursor sta nel punto ideale.

Il Sistema Multi-Agente: Subagenti e Parallelismo

Lo strumento Task rivela che Cursor non e’ un singolo agente. E’ un coordinatore che puo’ generare subagenti specializzati:

  • generalPurpose: Ricerca e implementazione multi-step.
  • explore: Esplorazione veloce del codebase. Ha livelli di approfondimento: “quick,” “medium,” “very thorough.”
  • shell: Specialista nell’esecuzione di comandi.
  • browser-use: Automazione browser per testare applicazioni web. Stateful (puo’ riprendere sessioni precedenti).

Il prompt dice esplicitamente: “Lancia piu’ agenti in parallelo quando possibile. NON lanciare piu’ di 4 agenti contemporaneamente.” Quindi quando Cursor deve capire un codebase grande, apre fino a 4 agenti explore paralleli su directory diverse.

Iniezione dello Stato IDE: Cosa Sa Cursor di Te

Il messaggio utente non e’ solo il tuo testo. Cursor inietta un’enorme quantita’ di contesto IDE prima della tua query: sistema operativo, shell, percorso del workspace, stato git, data di oggi, file aperti, regole del workspace, skill disponibili. Ogni regola Cursor che hai scritto in .cursor/rules/ viene iniettata testualmente nel messaggio utente.

Il sistema dei terminali e’ particolarmente elegante. Lo stato del terminale e’ rappresentato come file di testo su disco ($id.txt) con header di metadati (pid, cwd, ultimo comando, codice di uscita). Il modello legge e scrive questi file come qualsiasi altro file. Nessuna API speciale per il terminale. Solo file. Semplicita’ nella forma piu’ bella.

Illustrazione dell'architettura del system prompt di Cursor con tag XML strutturati
10.000 parole di istruzioni. Il modello le legge tutte prima di vedere il tuo “hello.”

Costruire un Cursor Minimale: La Guida all’Architettura

Quindi vuoi costruire il tuo. Ecco cosa la traccia ci dice sull’architettura minima per un agente di coding in stile Cursor:

  1. System prompt (~2.000 righe) con tag XML come delimitatori di sezione. Le sezioni critiche: persistenza, protocollo di comunicazione, regole d’uso degli strumenti, protocollo di modifica codice, sicurezza.
  2. Registro strumenti (almeno 8): Read/Write file, ricerca esatta + semantica, Shell stateful, formato diff vincolato, linter.
  3. Routing modelli: Usa LiteLLM per catene di fallback. Prova modelli economici prima, ricadi su quelli costosi. Risparmi 60-80% sui costi di inferenza.
  4. Iniezione di contesto: Prima di ogni chiamata API, inietta: file aperti, directory corrente, stato git, errori linter, regole utente.
  5. Orchestrazione multi-agente: Per task complessi, genera subagenti con specializzazioni diverse. Limita la concorrenza.
  6. MCP per l’estensibilita’: MCP e’ come rendi l’agente estensibile senza modificare il codice core. Se vuoi partire avvantaggiato, il Claude Agent SDK ti da’ integrazione MCP, strumenti per file e shell execution pronti all’uso.

Cosa Significa Tutto Questo

La traccia rivela che Cursor e’ fondamentalmente un prompt molto ben ingegnerizzato piu’ un layer di orchestrazione degli strumenti. Nessuna magia. Nessun modello fine-tuned. Nessuna salsa segreta proprietaria nell’AI stessa. L’intelligenza viene da:

  1. Un system prompt meticolosamente costruito che trasforma un LLM generico in un agente di coding
  2. Una suite di strumenti pensata che da’ al modello capacita’ reali
  3. Infrastruttura intelligente (routing modelli, decodifica vincolata, terminal-as-files)
  4. Dettagli UX ossessivi (cadenza di comunicazione, formato citazione codice, cambio modalita’)

Questo e’ sia rassicurante che terrificante. Rassicurante perche’ significa che puoi costruire qualcosa di simile con strumenti open-source e un buon prompt (abbiamo scritto una guida pratica alla costruzione di sistemi AI agentici con il Claude Agent SDK che copre esattamente questo). Terrificante perche’ significa che il fossato non e’ la tecnologia. E’ il polish del prodotto e l’ecosistema (regole, skill, integrazioni MCP) che Cursor ha costruito attorno ad esso.

Il vero vantaggio competitivo non e’ il system prompt (che, come puoi vedere, e’ catturabile). E’ l’integrazione IDE, il rendering dei diff, la UI di gestione dei processi in background, l’integrazione terminale, e le migliaia di piccole decisioni UX che fanno sembrare “un LLM con degli strumenti” un partner di coding invece di un chatbot con accesso ai file.

Se vuoi costruire un concorrente di Cursor, il prompt e gli strumenti sono il minimo. La parte difficile e’ tutto quello che ci gira attorno. Ed e’ esattamente quello che rende il software grande: non il motore, ma l’auto.

English|Español|Italiano