[{"data":1,"prerenderedAt":20493},["ShallowReactive",2],{"guide-harness-engineering-controllare-agenti-ai":3,"related-guide-harness-engineering-controllare-agenti-ai":1289,"all-guide":8073},{"id":4,"title":5,"author":6,"body":9,"category":1268,"contentType":1269,"description":1270,"difficulty":1271,"extension":1272,"featured":1273,"icon":1269,"image":1274,"meta":1275,"navigation":444,"path":1276,"publishedAt":1277,"readingTime":1278,"seo":1279,"stem":1280,"steps":1269,"tags":1281,"youtubeId":1269,"__hash__":1288},"guides/guides/harness-engineering-controllare-agenti-ai.md","Harness Engineering: Come Controllare gli Agenti AI Senza Soffocarli",{"name":7,"initials":8},"Alessandro Saiani","AS",{"type":10,"value":11,"toc":1221},"minimark",[12,16,20,28,31,34,37,42,45,51,54,57,62,65,78,81,103,106,109,111,115,118,122,125,133,136,139,143,150,153,185,188,191,195,198,201,204,211,213,217,220,227,230,237,240,243,293,296,298,302,309,313,320,327,331,334,342,345,356,359,363,370,373,376,383,385,389,392,396,399,458,461,465,468,474,477,480,484,487,506,509,513,516,538,541,549,551,555,558,562,565,569,572,586,590,593,604,607,610,614,617,620,622,626,629,649,652,656,662,668,674,678,689,691,745,748,750,754,757,764,768,771,775,778,782,785,804,807,810,813,815,819,826,829,832,835,838,841,861,869,871,875,878,881,895,898,901,908,915,917,921,924,928,975,979,1008,1012,1042,1046,1076,1080,1110,1112,1116,1119,1122,1125,1128,1131,1134,1137,1139,1144,1217],[13,14,5],"h1",{"id":15},"harness-engineering-come-controllare-gli-agenti-ai-senza-soffocarli",[17,18,19],"p",{},"LangChain ha preso lo stesso identico modello -- GPT-5.2-Codex -- e ha cambiato solo l'infrastruttura intorno. Il punteggio su Terminal Bench 2.0 è passato dal 52.8% al 66.5%. Quattordici punti percentuali. Zero modifiche al modello.",[17,21,22,23,27],{},"Quel dato racconta una verita scomoda per chi passa settimane a scegliere quale LLM usare: ",[24,25,26],"strong",{},"l'harness conta più del modello",". E la maggior parte di noi non ha ancora un harness degno di questo nome.",[17,29,30],{},"Il termine è esploso nelle ultime settimane. OpenAI lo ha coniato a febbraio, Martin Fowler lo ha legittimato, Anthropic ha pubblicato best practice concrete. Al QCon London di otto giorni fa, Birgitta Bockeler di Thoughtworks ha mostrato numeri che dovrebbero togliere il sonno a chi lancia agenti senza protezioni.",[17,32,33],{},"Questa guida smonta l'harness engineering pezzo per pezzo: cos'è, perché serve, e soprattutto cosa puoi fare domani mattina per implementarlo.",[35,36],"hr",{},[38,39,41],"h2",{"id":40},"cose-lharness-engineering-e-cosa-non-e","Cos'e l'Harness Engineering (e Cosa NON E)",[17,43,44],{},"Partiamo dalla definizione, perché la confusione in giro è tanta.",[17,46,47,48],{},"Birgitta Bockeler lo definisce come \"the tooling and practices we can use to keep AI agents in check\" -- ma aggiunge subito la parte che conta: ",[24,49,50],{},"\"a good harness makes agents more capable, not just more controlled.\"",[17,52,53],{},"Questa seconda meta della frase è tutto. Non stiamo parlando di mettere guinzagli agli agenti. Stiamo parlando di costruire l'infrastruttura che permette loro di lavorare meglio, più a lungo, con meno errori.",[17,55,56],{},"La metafora originale viene dall'equitazione: redini, sella, morso -- l'equipaggiamento completo per guidare un animale potente ma imprevedibile nella direzione giusta. Non lo limiti. Lo indirizzi.",[58,59,61],"h3",{"id":60},"cosa-non-e","Cosa NON e",[17,63,64],{},"Non è prompt engineering. Il prompt engineering si occupa di come formuli una singola domanda per ottenere una buona risposta. E un singolo turno, un singolo messaggio.",[17,66,67,68,73,74,77],{},"Non è nemmeno solo context engineering, anche se lo include. Il ",[69,70,72],"a",{"href":71},"/teoria/context-engineering-come-funziona-davvero","context engineering"," si occupa di ",[24,75,76],{},"cosa"," vede l'agente -- quale documentazione, quali file, quale memoria. E un pezzo fondamentale, ma è un pezzo.",[17,79,80],{},"L'harness engineering è il sistema completo. Include il contesto, ma anche i vincoli architetturali, il monitoraggio, la sicurezza, la pulizia automatica. Pensa alla differenza così:",[82,83,84,91,97],"ul",{},[85,86,87,90],"li",{},[24,88,89],{},"Prompt engineering",": come parli al modello",[85,92,93,96],{},[24,94,95],{},"Context engineering",": cosa vede il modello",[85,98,99,102],{},[24,100,101],{},"Harness engineering",": l'intero ambiente in cui il modello opera",[17,104,105],{},"O, come lo sintetizza un articolo su Substack: \"Context engineering asks what should the agent see; harness engineering is about what should the system prevent, measure, and correct.\"",[17,107,108],{},"Un output sbagliato una volta? Probabilmente un problema di contesto. Un degrado lento su settimane? Quello è un problema di harness.",[35,110],{},[38,112,114],{"id":113},"le-tre-componenti-il-framework-fowler-bockeler","Le Tre Componenti: Il Framework Fowler-Bockeler",[17,116,117],{},"Birgitta Bockeler ha pubblicato sul blog di Martin Fowler un'analisi dell'esperimento OpenAI che identifica tre componenti dell'harness. È il framework più pulito che abbiamo, e vale la pena usarlo come mappa.",[58,119,121],{"id":120},"_1-context-engineering","1. Context Engineering",[17,123,124],{},"La knowledge base continuamente migliorata nel codebase, più l'accesso dell'agente a contesto dinamico.",[17,126,127,128,132],{},"Ne abbiamo gia parlato in dettaglio nella ",[69,129,131],{"href":130},"/guide/context-engineering-pratico-rules-mcp-workflow","guida pratica al context engineering",". Il succo: CLAUDE.md, .cursorrules, AGENTS.md, MCP server. Tutto cio che l'agente vede quando inizia a lavorare.",[17,134,135],{},"Ma nel framework dell'harness, il context engineering ha una sfumatura diversa: non è statico. E un sistema che si auto-migliora. OpenAI lo descrive così: \"When the agent struggles, they treat it as a signal: identify what is missing -- tools, guardrails, documentation -- and feed it back into the repository.\"",[17,137,138],{},"L'agente fatica? Non è un fallimento. È un segnale. Qualcosa manca nel contesto, e tu lo aggiungi. Il contesto migliora iterazione dopo iterazione.",[58,140,142],{"id":141},"_2-architectural-constraints","2. Architectural Constraints",[17,144,145,146,149],{},"I vincoli architetturali sono la parte che distingue l'harness dal semplice context engineering. Non stai solo dicendo all'agente cosa fare -- stai rendendo ",[24,147,148],{},"impossibile"," fare certe cose sbagliate.",[17,151,152],{},"Concretamente:",[82,154,155,161,167,173,179],{},[85,156,157,160],{},[24,158,159],{},"Pre-commit hooks"," che bloccano codice non conforme",[85,162,163,166],{},[24,164,165],{},"Linter personalizzati"," che verificano pattern architetturali",[85,168,169,172],{},[24,170,171],{},"Test strutturali"," (tipo ArchUnit) che impediscono violazioni dei layer",[85,174,175,178],{},[24,176,177],{},"Sandbox"," con allow-listing dei comandi eseguibili",[85,180,181,184],{},[24,182,183],{},"Isolamento di rete"," per ambienti di esecuzione",[17,186,187],{},"Il punto chiave, citando Fowler: \"Increasing trust and reliability required constraining the solution space: specific architectural patterns, enforced boundaries, standardized structures.\"",[17,189,190],{},"Per fidarti di più dell'agente, devi dargli meno libertà. Non è un paradosso -- è design.",[58,192,194],{"id":193},"_3-garbage-collection","3. Garbage Collection",[17,196,197],{},"La componente che nessuno vuole implementare è che fa la differenza più grande su tempi lunghi.",[17,199,200],{},"Agenti periodici che passano il codebase e trovano inconsistenze nella documentazione, violazioni dei vincoli architetturali, drift tra codice e specifiche. È la pulizia automatica del debito che gli agenti accumulano lavorando.",[17,202,203],{},"Senza garbage collection, ogni sessione agente lascia un po' di entropia. Dopo settimane, l'entropia diventa debito tecnico ingestibile. Con la garbage collection, il codebase si auto-ripara.",[17,205,206],{},[207,208],"img",{"alt":209,"src":210},"Le tre componenti dell'harness engineering","/images/body/harness-engineering-componenti.webp",[35,212],{},[38,214,216],{"id":215},"il-costo-di-non-farlo","Il Costo di NON Farlo",[17,218,219],{},"Al QCon London del 16 marzo, Birgitta Bockeler ha messo sul tavolo numeri che meritano attenzione.",[17,221,222,223,226],{},"Un agente AI nel 2026 costa circa ",[24,224,225],{},"$380 al giorno",". Fanno $91.200 l'anno -- lo stipendio di uno sviluppatore solido in Germania. Nel 2024 si parlava di $0.12 per 100 righe di codice. In due anni il costo si è moltiplicato di ordini di grandezza, perché siamo passati da suggerimenti inline ad agenti autonomi che girano per 20 minuti senza supervisione.",[17,228,229],{},"Ma il costo vero non è il prezzo dell'API. E quello che succede quando l'agente sbaglia senza che nessuno se ne accorga.",[17,231,232,233,236],{},"Bockeler riporta ",[24,234,235],{},"incidenti di prompt injection con cadenza settimanale"," nei team Thoughtworks. Undici giorni prima del talk, un attaccante ha usato un GitHub issue costruito ad arte per sfruttare un agente non supervisionato: ha estratto segreti e pubblicato pacchetti NPM malevoli.",[17,238,239],{},"Non è teoria. E cronaca.",[17,241,242],{},"Il framework di rischio che propone ha tre variabili:",[244,245,246,259],"table",{},[247,248,249],"thead",{},[250,251,252,256],"tr",{},[253,254,255],"th",{},"Variabile",[253,257,258],{},"Domanda",[260,261,262,273,283],"tbody",{},[250,263,264,270],{},[265,266,267],"td",{},[24,268,269],{},"Probabilita di errore",[265,271,272],{},"Quanto spesso l'agente sbaglia su questo tipo di task?",[250,274,275,280],{},[265,276,277],{},[24,278,279],{},"Impatto dell'errore",[265,281,282],{},"Cosa succede se sbaglia?",[250,284,285,290],{},[265,286,287],{},[24,288,289],{},"Rilevabilità dell'errore",[265,291,292],{},"Quanto è facile accorgersi che ha sbagliato?",[17,294,295],{},"Quando tutte e tre sono alte -- alta probabilità, alto impatto, bassa rilevabilità -- sei nel territorio del disastro. È senza un harness, ci sei più spesso di quanto pensi.",[35,297],{},[38,299,301],{"id":300},"context-engineering-nellharness-oltre-il-claudemd","Context Engineering nell'Harness: Oltre il CLAUDE.md",[17,303,304,305,308],{},"Se hai seguito la nostra ",[69,306,307],{"href":130},"guida al context engineering pratico",", hai gia la base. Ma nell'ottica dell'harness, il contesto ha regole più stringenti.",[58,310,312],{"id":311},"la-regola-delle-60-righe","La regola delle 60 righe",[17,314,315,316,319],{},"HumanLayer consiglia di mantenere CLAUDE.md e AGENTS.md ",[24,317,318],{},"sotto le 60 righe",". È più restrittivo del limite di 150-200 istruzioni che cita Anthropic, e c'è un motivo: nell'harness engineering, il contesto statico deve essere chirurgico. Ogni riga superflua ruba spazio al contesto dinamico che l'agente accumula lavorando.",[17,321,322,323,326],{},"Birgitta Bockeler lo conferma con un dato: ",[24,324,325],{},"il 15% della context window è già consumato prima del primo prompt dell'utente",". System prompt, definizioni tool, rules file -- tutto questo mangia contesto prima ancora che tu dica \"ciao\".",[58,328,330],{"id":329},"progressive-disclosure","Progressive disclosure",[17,332,333],{},"La soluzione non è scrivere meno. E scrivere in modo stratificato.",[17,335,336,337,341],{},"LangChain lo chiama \"skills con progressive disclosure\": le informazioni dettagliate non vengono caricate all'inizio. Vengono iniettate quando servono, in base al task corrente. Come descrivevamo nell'articolo sulle ",[69,338,340],{"href":339},"/articoli/skill-ai-condivise-paradosso-expertise","skill AI condivise",", le skill generiche non funzionano -- e nell'harness engineering questo principio diventa strutturale.",[17,343,344],{},"In pratica:",[346,347,352],"pre",{"className":348,"code":350,"language":351},[349],"language-text","CLAUDE.md (caricato sempre):\n  - Stack, comandi, convenzioni critiche (30-40 righe)\n\n.claude/rules/database.md (caricato on-demand):\n  - Schema, migration, query patterns\n\n.claude/rules/security.md (caricato on-demand):\n  - Policy di sicurezza, gestione segreti, validazione input\n","text",[353,354,350],"code",{"__ignoreMap":355},"",[17,357,358],{},"L'agente parte leggero. Carica il dettaglio solo quando ne ha bisogno.",[58,360,362],{"id":361},"lo-studio-eth-zurich-attenzione-ai-file-ai-generated","Lo studio ETH Zurich: attenzione ai file AI-generated",[17,364,365,366,369],{},"Un dato che dovrebbe far riflettere chiunque faccia generare il proprio CLAUDE.md all'AI: uno studio ETH Zurich su 138 task Python reali ha mostrato che i file di contesto generati da LLM ",[24,367,368],{},"peggiorano la performance del 3%"," e aumentano i costi di inferenza del 20%+.",[17,371,372],{},"File scritti da umani? Miglioramento marginale del 4%, con aumento dei costi del 19%.",[17,374,375],{},"Il punto è che i file AI-generated tendono a duplicare informazione già presente nel codebase. Quando i ricercatori hanno rimosso README e docs esistenti, i file LLM-generated hanno migliorato del 2.7% -- dimostrando che aggiungono valore solo quando colmano un vuoto informativo.",[17,377,378,379,382],{},"La raccomandazione: limita le istruzioni a dettagli che l'agente ",[24,380,381],{},"non può inferire dal codice",". Tooling specifico, comandi di build custom, convenzioni che rompono cose se ignorate. Tutto il resto è rumore.",[35,384],{},[38,386,388],{"id":387},"architectural-constraints-il-sandbox-che-libera","Architectural Constraints: Il Sandbox che Libera",[17,390,391],{},"Sembra controintuitivo, ma vincolare l'agente lo rende più efficace. Ridurre lo spazio delle soluzioni significa meno esplorazione casuale, meno errori, più consistenza.",[58,393,395],{"id":394},"git-worktree-e-branch-isolati","Git Worktree e Branch Isolati",[17,397,398],{},"Ogni sessione agente dovrebbe operare su un branch dedicato. Meglio ancora: un git worktree separato. Così l'agente lavora in una copia isolata del repo, e le sue modifiche non toccano il branch principale finché non passano la review.",[346,400,404],{"className":401,"code":402,"language":403,"meta":355,"style":355},"language-bash shiki shiki-themes github-light github-dark","# Crea un worktree isolato per l'agente\ngit worktree add ../agent-feature-x -b feature/agent-task-x\n\n# L'agente lavora in ../agent-feature-x\n# Le modifiche restano isolate fino al merge\n","bash",[353,405,406,415,439,446,452],{"__ignoreMap":355},[407,408,411],"span",{"class":409,"line":410},"line",1,[407,412,414],{"class":413},"sJ8bj","# Crea un worktree isolato per l'agente\n",[407,416,418,422,426,429,432,436],{"class":409,"line":417},2,[407,419,421],{"class":420},"sScJk","git",[407,423,425],{"class":424},"sZZnC"," worktree",[407,427,428],{"class":424}," add",[407,430,431],{"class":424}," ../agent-feature-x",[407,433,435],{"class":434},"sj4cs"," -b",[407,437,438],{"class":424}," feature/agent-task-x\n",[407,440,442],{"class":409,"line":441},3,[407,443,445],{"emptyLinePlaceholder":444},true,"\n",[407,447,449],{"class":409,"line":448},4,[407,450,451],{"class":413},"# L'agente lavora in ../agent-feature-x\n",[407,453,455],{"class":409,"line":454},5,[407,456,457],{"class":413},"# Le modifiche restano isolate fino al merge\n",[17,459,460],{},"Anthropic usa questo pattern per gli agenti di lunga durata: commit puliti tra le sessioni, messaggi descrittivi, una feature per sessione.",[58,462,464],{"id":463},"layer-enforcement","Layer Enforcement",[17,466,467],{},"L'esperimento OpenAI definisce layer di dipendenza espliciti:",[346,469,472],{"className":470,"code":471,"language":351},[349],"Types -> Config -> Repo -> Service -> Runtime -> UI\n",[353,473,471],{"__ignoreMap":355},[17,475,476],{},"Un layer può dipendere solo dai layer alla sua sinistra. Mai al contrario. Questa regola viene enforced da test strutturali automatici -- non da istruzioni nel prompt.",[17,478,479],{},"La differenza è fondamentale: un'istruzione nel prompt può essere ignorata. Un test che fallisce blocca il merge.",[58,481,483],{"id":482},"sandbox-e-allow-listing","Sandbox e Allow-Listing",[17,485,486],{},"L'agente non dovrebbe avere accesso a tutto. LangChain descrive ambienti sandboxed con:",[82,488,489,495,500],{},[85,490,491,494],{},[24,492,493],{},"Allow-listing dei comandi",": l'agente può eseguire solo comandi esplicitamente autorizzati",[85,496,497,499],{},[24,498,183],{},": nessun accesso a internet non necessario",[85,501,502,505],{},[24,503,504],{},"Filesystem limitato",": accesso solo alle directory del progetto",[17,507,508],{},"Non è sfiducia. E buon senso. Lo stesso motivo per cui i server di produzione non danno l'accesso root a tutti.",[58,510,512],{"id":511},"checkpoint-system","Checkpoint System",[17,514,515],{},"Anthropic descrive un sistema di checkpoint per agenti di lunga durata. Due componenti:",[517,518,519,532],"ol",{},[85,520,521,524,525,528,529],{},[24,522,523],{},"Initializer Agent",": configura l'ambiente, scrive un ",[353,526,527],{},"init.sh",", crea il primo commit, produce un ",[353,530,531],{},"claude-progress.txt",[85,533,534,537],{},[24,535,536],{},"Coding Agent",": lavora in sessioni discrete, aggiorna il progresso, committa tra le sessioni",[17,539,540],{},"L'analogia è perfetta: \"Engineers working in shifts, where each new engineer arrives with no memory of what happened.\" Il checkpoint è l'unico modo per mantenere continuità.",[17,542,543,544,548],{},"Come descritto nell'articolo su ",[69,545,547],{"href":546},"/articoli/karpathy-non-scrive-codice-da-dicembre-agenti-16-ore","Karpathy e gli agenti che lavorano 16 ore",", il pattern di sessioni brevi con handoff strutturato è quello che separa chi ottiene risultati da chi accumula caos.",[35,550],{},[38,552,554],{"id":553},"garbage-collection-pulire-dopo-lagente","Garbage Collection: Pulire Dopo l'Agente",[17,556,557],{},"È la componente più trascurata e forse la più importante per chi lavora con agenti su tempi lunghi.",[58,559,561],{"id":560},"il-problema-dellentropia","Il problema dell'entropia",[17,563,564],{},"Ogni sessione agente lascia tracce: commenti TODO dimenticati, documentazione non aggiornata, codice morto, inconsistenze tra moduli. Su una singola sessione il danno è trascurabile. Su settimane di lavoro con agenti multipli, l'entropia si accumula fino a rendere il codebase ingestibile.",[58,566,568],{"id":567},"compaction-e-summarization","Compaction e Summarization",[17,570,571],{},"LangChain descrive due tecniche per gestire il contesto che cresce:",[82,573,574,580],{},[85,575,576,579],{},[24,577,578],{},"Compaction",": quando il contesto si avvicina ai limiti, viene riassunto automaticamente. Le informazioni recenti restano intatte, quelle vecchie vengono compresse",[85,581,582,585],{},[24,583,584],{},"Tool output offloading",": output grandi (log, dump di database, tracce di errore) vengono scaricati su filesystem invece di restare nella context window",[58,587,589],{"id":588},"agenti-di-pulizia","Agenti di pulizia",[17,591,592],{},"Il pattern più avanzato prevede agenti dedicati alla manutenzione:",[82,594,595,598,601],{},[85,596,597],{},"Un agente che verifica la coerenza tra codice e documentazione",[85,599,600],{},"Un agente che cerca violazioni dei vincoli architetturali",[85,602,603],{},"Un agente che identifica codice duplicato o pattern inconsistenti",[17,605,606],{},"Non sono agenti che scrivono feature. Sono agenti che mantengono l'igiene del codebase. Sono la garbage collection del vostro sistema.",[17,608,609],{},"OpenAI li chiama esplicitamente parte dell'harness: \"Documentazione cross-linked validata meccanicamente tramite linter e CI.\"",[58,611,613],{"id":612},"loop-detection","Loop Detection",[17,615,616],{},"LangChain introduce un middleware specifico per prevenire i \"doom loop\" -- situazioni in cui l'agente ripete lo stesso approccio fallito all'infinito. Il middleware traccia le modifiche ai file e interviene quando rileva pattern circolari.",[17,618,619],{},"Se hai mai visto un agente tentare la stessa fix 5 volte di fila, sai quanto vale questo componente.",[35,621],{},[38,623,625],{"id":624},"sicurezza-la-lethal-trifecta","Sicurezza: La Lethal Trifecta",[17,627,628],{},"Simon Willison ha identificato una combinazione letale che ogni harness deve prevenire. La chiama \"Lethal Trifecta\" e si verifica quando tre condizioni coesistono:",[517,630,631,637,643],{},[85,632,633,636],{},[24,634,635],{},"Esposizione a contenuto non fidato",": l'agente processa testo controllato dall'attaccante (issue GitHub, email, commenti)",[85,638,639,642],{},[24,640,641],{},"Accesso a dati privati",": l'agente può leggere segreti, credenziali, dati sensibili",[85,644,645,648],{},[24,646,647],{},"Capacita di comunicare esternamente",": l'agente può inviare dati fuori dal sistema (email, API call, push su registry)",[17,650,651],{},"Quando le tre condizioni si combinano, un prompt injection può trasformare il tuo agente in un vettore di attacco. Non è fantascienza -- è già successo.",[58,653,655],{"id":654},"gli-incidenti-reali-del-2026","Gli incidenti reali del 2026",[17,657,658,661],{},[24,659,660],{},"Clinejection"," (febbraio 2026): un prompt injection nascosto nel titolo di un GitHub issue ha compromesso la supply chain NPM. Circa 4.000 macchine sviluppatore infettate. L'agente ha letto l'input non fidato, eseguito comandi arbitrari, rubato segreti di produzione per pubblicare pacchetti malevoli.",[17,663,664,667],{},[24,665,666],{},"RoguePilot"," (febbraio 2026): istruzioni nascoste in commenti HTML di GitHub issue, processate automaticamente da Copilot in GitHub Codespaces, hanno causato l'esfiltrazione del GITHUB_TOKEN. Risultato: takeover del repository.",[17,669,670,673],{},[24,671,672],{},"ToxicSkills"," (Snyk, febbraio 2026): analisi di 3.984 skill da piattaforme pubbliche. Il 36% (1.467 skill) presenta almeno un problema di sicurezza. 76 payload confermati come malevoli, progettati per furto credenziali, installazione backdoor ed esfiltrazione dati. Le submission giornaliere sono passate da meno di 50 a oltre 500 in poche settimane.",[58,675,677],{"id":676},"come-difendersi","Come difendersi",[17,679,680,681,684,685,688],{},"La risposta di Willison e netta: i prodotti \"guardrail\" che affermano di prevenire il 95% degli attacchi ",[24,682,683],{},"non sono affidabili",". Gli LLM non distinguono l'importanza delle istruzioni in base alla provenienza. Non puoi fidarti della detection. Devi ",[24,686,687],{},"evitare la combinazione",".",[17,690,344],{},[244,692,693,703],{},[247,694,695],{},[250,696,697,700],{},[253,698,699],{},"Principio",[253,701,702],{},"Implementazione",[260,704,705,715,725,735],{},[250,706,707,712],{},[265,708,709],{},[24,710,711],{},"Minimizza l'input non fidato",[265,713,714],{},"Non far processare all'agente issue/email/commenti esterni senza sanitizzazione",[250,716,717,722],{},[265,718,719],{},[24,720,721],{},"Limita l'accesso ai segreti",[265,723,724],{},"L'agente non dovrebbe MAI vedere credenziali o token in chiaro. Usa variable d'ambiente isolate",[250,726,727,732],{},[265,728,729],{},[24,730,731],{},"Blocca le comunicazioni esterne",[265,733,734],{},"Sandbox di rete. L'agente non pubblica su registry, non invia email, non fa push senza approvazione umana",[250,736,737,742],{},[265,738,739],{},[24,740,741],{},"Human-in-the-loop per azioni irreversibili",[265,743,744],{},"Qualsiasi operazione che modifica stato esterno (deploy, publish, invio) richiede approvazione",[17,746,747],{},"Come dice Bockeler: \"Security is not a technical problem; it's a conceptual problem.\" Non è una questione di tool migliori. E una questione di design del sistema.",[35,749],{},[38,751,753],{"id":752},"il-dato-langchain-lharness-conta-piu-del-modello","Il Dato LangChain: L'Harness Conta Piu del Modello",[17,755,756],{},"Vale la pena tornare sul dato più importante di tutta la ricerca, perché cambia le priorita di investimento.",[17,758,759,760,763],{},"LangChain ha preso il suo agente è lo ha ottimizzato ",[24,761,762],{},"solo a livello di harness"," -- stesso modello, stesso dataset, stesso benchmark. Tre aree di intervento:",[58,765,767],{"id":766},"_1-system-prompt","1. System Prompt",[17,769,770],{},"Non il prompt dell'utente -- il system prompt del framework. Ottimizzato per dare all'agente consapevolezza dell'ambiente: struttura directory, tool disponibili, budget di tempo.",[58,772,774],{"id":773},"_2-tools","2. Tools",[17,776,777],{},"I tool a disposizione dell'agente. Non più tool, ma tool migliori. Piu mirati, con output più puliti, meno rumore nella context window.",[58,779,781],{"id":780},"_3-middleware","3. Middleware",[17,783,784],{},"Tre middleware specifici:",[82,786,787,793,799],{},[85,788,789,792],{},[24,790,791],{},"Self-Verification Loop",": ciclo build-verify-fix con testing e cross-checking contro le specifiche del task",[85,794,795,798],{},[24,796,797],{},"LocalContextMiddleware",": inietta consapevolezza dell'ambiente",[85,800,801,803],{},[24,802,613],{},": previene i doom loop",[17,805,806],{},"Il middleware più impattante è il Self-Verification Loop. L'agente non si limita a generare codice -- genera, testa, verifica contro le specifiche, e itera se qualcosa non torna. E il testing automatizzato integrato nel loop dell'agente.",[17,808,809],{},"Risultato: dal 52.8% al 66.5% su Terminal Bench 2.0. Da Top 30 a Top 5 nella classifica. Stesso modello.",[17,811,812],{},"Chi nella tua organizzazione investe settimane a fare benchmark di modelli LLM probabilmente otterrebbe risultati migliori investendo quelle settimane sull'harness.",[35,814],{},[38,816,818],{"id":817},"lesperimento-openai-1-milione-di-righe-zero-codice-manuale","L'Esperimento OpenAI: 1 Milione di Righe, Zero Codice Manuale",[17,820,821,822,825],{},"Il case study più ambizioso sull'harness engineering viene da OpenAI stessa. Tre ingegneri, cinque mesi, una regola: ",[24,823,824],{},"nessun codice scritto manualmente",". Solo Codex.",[17,827,828],{},"Il risultato: un prodotto beta funzionante con oltre 1 milione di righe di codice. Logica applicativa, documentazione, configurazione CI, setup observability, tooling -- tutto generato da agenti.",[17,830,831],{},"Ma il punto non è il milione di righe. E il principio che ha guidato tutto: \"When the agent struggles, they treat it as a signal.\"",[17,833,834],{},"Ogni volta che Codex faticava su un task, i tre ingegneri non lo risolvevano manualmente. Identificavano cosa mancava -- tool, guardrail, documentazione -- è lo aggiungevano al repository. Facendo scrivere la fix a Codex stesso.",[17,836,837],{},"E un feedback loop potente: l'harness migliora a ogni fallimento dell'agente. Il fallimento è il motore del miglioramento, non un problema da aggirare.",[17,839,840],{},"Le componenti concrete del loro harness:",[82,842,843,846,849,852,855,858],{},[85,844,845],{},"Pre-commit hooks per ogni merge",[85,847,848],{},"Linter personalizzati per pattern architetturali",[85,850,851],{},"ArchUnit per test strutturali",[85,853,854],{},"Layer di dipendenza enforced (Types -> Config -> Repo -> Service -> Runtime -> UI)",[85,856,857],{},"Documentazione cross-linked validata meccanicamente",[85,859,860],{},"Prompts dichiarativi anziche script handcrafted",[17,862,863,864,868],{},"Come scrivevamo nell'articolo sull'",[69,865,867],{"href":866},"/articoli/agentic-engineering-da-vibe-coding-a-disciplina","agentic engineering",", il 70% del lavoro sta nella definizione del problema e dei vincoli. L'esperimento OpenAI è la dimostrazione empirica che quel 70% produce risultati su scala industriale.",[35,870],{},[38,872,874],{"id":873},"le-istruzioni-ai-generated-peggiorano-le-cose","Le Istruzioni AI-Generated Peggiorano le Cose",[17,876,877],{},"Lo studio ETH Zurich merita una sezione a parte perché demolisce un pattern diffusissimo: far generare il CLAUDE.md all'AI.",[17,879,880],{},"Su 138 task Python reali (dataset AGENTbench, repository di nicchia), i file di contesto generati da LLM:",[82,882,883,889],{},[85,884,885,888],{},[24,886,887],{},"Peggiorano"," la performance del 3%",[85,890,891,894],{},[24,892,893],{},"Aumentano"," i costi di inferenza del 20%+",[17,896,897],{},"Perche? Perché duplicano informazione già presente nel codebase. L'agente si ritrova a processare due volte le stesse informazioni -- una nel codice, una nelle istruzioni -- sprecando contesto e introducendo potenziali contraddizioni.",[17,899,900],{},"I file scritti da umani fanno leggermente meglio (+4%), ma il costo-beneficio e comunque discutibile (+19% costi).",[17,902,903,904,907],{},"La lezione e chiara: le istruzioni nel rules file devono contenere ",[24,905,906],{},"solo cio che l'agente non può dedurre dal codice",". Comandi di build non ovvi, convenzioni che causano bug se ignorate, workaround per problemi noti. Tutto il resto -- lo stile del codice, la struttura dei file, i pattern architetturali -- l'agente lo impara dal codebase.",[17,909,910,911,914],{},"E un principio che avevamo gia esplorato nella guida al ",[69,912,913],{"href":130},"context engineering pratico",": ogni token nel rules file deve guadagnarsi il suo posto.",[35,916],{},[38,918,920],{"id":919},"cosa-fare-domani-la-checklist","Cosa Fare Domani: La Checklist",[17,922,923],{},"L'harness engineering non si implementa in un giorno. Ma puoi iniziare domani con azioni concrete e iterare da li.",[58,925,927],{"id":926},"settimana-1-le-basi","Settimana 1: Le Basi",[82,929,932,945,954,963],{"className":930},[931],"contains-task-list",[85,933,936,940,941,944],{"className":934},[935],"task-list-item",[937,938],"input",{"disabled":444,"type":939},"checkbox"," ",[24,942,943],{},"Rivedi il tuo rules file"," -- taglia tutto cio che l'agente può dedurre dal codice. Obiettivo: sotto 60 righe",[85,946,948,940,950,953],{"className":947},[935],[937,949],{"disabled":444,"type":939},[24,951,952],{},"Aggiungi pre-commit hooks"," -- almeno linting e formatting automatici. L'agente non deve poter committare codice che non passa i controlli base",[85,955,957,940,959,962],{"className":956},[935],[937,958],{"disabled":444,"type":939},[24,960,961],{},"Isola le sessioni agente"," -- un branch o worktree per sessione. Mai lavorare direttamente su main",[85,964,966,940,968,971,972,974],{"className":965},[935],[937,967],{"disabled":444,"type":939},[24,969,970],{},"Attiva il checkpoint"," -- ",[353,973,531],{}," o equivalente. Ogni sessione deve lasciare traccia strutturata",[58,976,978],{"id":977},"settimana-2-sicurezza","Settimana 2: Sicurezza",[82,980,982,991,1000],{"className":981},[931],[85,983,985,940,987,990],{"className":984},[935],[937,986],{"disabled":444,"type":939},[24,988,989],{},"Verifica la Lethal Trifecta"," -- il tuo agente ha accesso a input non fidato + dati sensibili + comunicazioni esterne? Se si, chiudi almeno un lato del triangolo",[85,992,994,940,996,999],{"className":993},[935],[937,995],{"disabled":444,"type":939},[24,997,998],{},"Audita le skill/MCP"," -- stai usando skill di terze parti? Verifica la provenienza. Il 13.4% ha problemi di sicurezza",[85,1001,1003,940,1005,1007],{"className":1002},[935],[937,1004],{"disabled":444,"type":939},[24,1006,741],{}," -- deploy, publish, invio email: niente di automatico senza approvazione",[58,1009,1011],{"id":1010},"settimana-3-vincoli-architetturali","Settimana 3: Vincoli Architetturali",[82,1013,1015,1024,1033],{"className":1014},[931],[85,1016,1018,940,1020,1023],{"className":1017},[935],[937,1019],{"disabled":444,"type":939},[24,1021,1022],{},"Definisci i layer"," -- quali moduli possono dipendere da quali? Scrivilo, poi enforcea con test",[85,1025,1027,940,1029,1032],{"className":1026},[935],[937,1028],{"disabled":444,"type":939},[24,1030,1031],{},"Aggiungi test strutturali"," -- ArchUnit, eslint rules custom, o anche solo script bash che verificano i pattern",[85,1034,1036,940,1038,1041],{"className":1035},[935],[937,1037],{"disabled":444,"type":939},[24,1039,1040],{},"Configura il sandbox"," -- limita i comandi eseguibili dall'agente. Allow-list, non block-list",[58,1043,1045],{"id":1044},"settimana-4-garbage-collection","Settimana 4: Garbage Collection",[82,1047,1049,1058,1067],{"className":1048},[931],[85,1050,1052,940,1054,1057],{"className":1051},[935],[937,1053],{"disabled":444,"type":939},[24,1055,1056],{},"Crea un agente di pulizia"," -- un prompt che gira periodicamente e verifica coerenza tra codice e documentazione",[85,1059,1061,940,1063,1066],{"className":1060},[935],[937,1062],{"disabled":444,"type":939},[24,1064,1065],{},"Attiva loop detection"," -- monitora quando l'agente ripete le stesse modifiche. Puo essere semplice come un hook che confronta le ultime N diff",[85,1068,1070,940,1072,1075],{"className":1069},[935],[937,1071],{"disabled":444,"type":939},[24,1073,1074],{},"Misura il contesto"," -- quanto della context window e consumato prima del primo prompt? Se sei sopra il 20%, hai un problema",[58,1077,1079],{"id":1078},"ongoing","Ongoing",[82,1081,1083,1092,1101],{"className":1082},[931],[85,1084,1086,940,1088,1091],{"className":1085},[935],[937,1087],{"disabled":444,"type":939},[24,1089,1090],{},"Tratta ogni fallimento dell'agente come un segnale"," -- non risolvere manualmente. Identifica cosa manca nell'harness e aggiungilo",[85,1093,1095,940,1097,1100],{"className":1094},[935],[937,1096],{"disabled":444,"type":939},[24,1098,1099],{},"Rivedi il rules file ogni settimana"," -- togli le regole che l'agente segue gia da solo, aggiungi quelle che servono",[85,1102,1104,940,1106,1109],{"className":1103},[935],[937,1105],{"disabled":444,"type":939},[24,1107,1108],{},"Monitora i costi"," -- $380/giorno è il benchmark. Sai quanto spendi?",[35,1111],{},[38,1113,1115],{"id":1114},"lharness-come-conoscenza-istituzionale","L'Harness Come Conoscenza Istituzionale",[17,1117,1118],{},"C'e un effetto collaterale dell'harness engineering che nessuno menziona ma che potrebbe essere il più prezioso di tutti.",[17,1120,1121],{},"Quando costruisci un harness -- rules file, test strutturali, linter personalizzati, agenti di pulizia, documentazione validata meccanicamente -- stai documentando la conoscenza istituzionale del team in formato machine-readable.",[17,1123,1124],{},"Quel CLAUDE.md snello di 60 righe? Sono le 60 cose più importanti da sapere sul progetto. Quei test strutturali? Sono le decisioni architetturali cristallizzate in codice. Quei pre-commit hooks? Sono gli errori che il team ha gia fatto e ha deciso di non ripetere.",[17,1126,1127],{},"E tutto questo funziona sia per gli agenti AI che per gli sviluppatori umani che entrano nel team. L'harness è il miglior documento di onboarding che possiate avere, perché e sempre aggiornato -- se non lo fosse, gli agenti smetterebbero di funzionare.",[17,1129,1130],{},"La disciplina di mantenere l'harness in ordine costringe il team a rendere esplicito cio che di solito resta implicito. E quello e oro, indipendentemente dall'AI.",[17,1132,1133],{},"L'harness engineering non è un costo. E un investimento in infrastruttura che paga dividendi sia con gli agenti che senza.",[17,1135,1136],{},"Chi inizia adesso, prima che il codebase diventi ingestibile, avra un vantaggio competitivo nei prossimi mesi. Chi aspetta, paghera il prezzo in entropia accumulata -- e i $380 al giorno saranno spesi molto peggio.",[35,1138],{},[17,1140,1141],{},[24,1142,1143],{},"Fonti:",[517,1145,1146,1154,1161,1168,1175,1182,1189,1196,1203,1210],{},[85,1147,1148],{},[69,1149,1153],{"href":1150,"rel":1151},"https://www.infoq.com/news/2026/03/ai-coding-state/",[1152],"nofollow","InfoQ - State of Play: AI Coding Assistants (QCon London 2026)",[85,1155,1156],{},[69,1157,1160],{"href":1158,"rel":1159},"https://www.theregister.com/2026/03/18/ai_for_software_developers_qcon/",[1152],"The Register - AI for software developers is in a 'dangerous state' (QCon London)",[85,1162,1163],{},[69,1164,1167],{"href":1165,"rel":1166},"https://martinfowler.com/articles/exploring-gen-ai/harness-engineering.html",[1152],"Martin Fowler / Birgitta Bockeler - Harness Engineering",[85,1169,1170],{},[69,1171,1174],{"href":1172,"rel":1173},"https://openai.com/index/harness-engineering/",[1152],"OpenAI - Harness Engineering: Leveraging Codex in an Agent-First World",[85,1176,1177],{},[69,1178,1181],{"href":1179,"rel":1180},"https://blog.langchain.com/the-anatomy-of-an-agent-harness/",[1152],"LangChain - The Anatomy of an Agent Harness",[85,1183,1184],{},[69,1185,1188],{"href":1186,"rel":1187},"https://blog.langchain.com/improving-deep-agents-with-harness-engineering/",[1152],"LangChain - Improving Deep Agents with Harness Engineering",[85,1190,1191],{},[69,1192,1195],{"href":1193,"rel":1194},"https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents",[1152],"Anthropic - Effective Harnesses for Long-Running Agents",[85,1197,1198],{},[69,1199,1202],{"href":1200,"rel":1201},"https://simonwillison.net/2025/Jun/16/the-lethal-trifecta/",[1152],"Simon Willison - The Lethal Trifecta",[85,1204,1205],{},[69,1206,1209],{"href":1207,"rel":1208},"https://www.humanlayer.dev/blog/skill-issue-harness-engineering-for-coding-agents",[1152],"HumanLayer - Skill Issue: Harness Engineering for Coding Agents",[85,1211,1212],{},[69,1213,1216],{"href":1214,"rel":1215},"https://snyk.io/blog/toxicskills-malicious-ai-agent-skills-clawhub/",[1152],"Snyk - ToxicSkills: Malicious AI Agent Skills on ClawHub",[1218,1219,1220],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":355,"searchDepth":417,"depth":417,"links":1222},[1223,1226,1231,1232,1237,1243,1249,1253,1258,1259,1260,1267],{"id":40,"depth":417,"text":41,"children":1224},[1225],{"id":60,"depth":441,"text":61},{"id":113,"depth":417,"text":114,"children":1227},[1228,1229,1230],{"id":120,"depth":441,"text":121},{"id":141,"depth":441,"text":142},{"id":193,"depth":441,"text":194},{"id":215,"depth":417,"text":216},{"id":300,"depth":417,"text":301,"children":1233},[1234,1235,1236],{"id":311,"depth":441,"text":312},{"id":329,"depth":441,"text":330},{"id":361,"depth":441,"text":362},{"id":387,"depth":417,"text":388,"children":1238},[1239,1240,1241,1242],{"id":394,"depth":441,"text":395},{"id":463,"depth":441,"text":464},{"id":482,"depth":441,"text":483},{"id":511,"depth":441,"text":512},{"id":553,"depth":417,"text":554,"children":1244},[1245,1246,1247,1248],{"id":560,"depth":441,"text":561},{"id":567,"depth":441,"text":568},{"id":588,"depth":441,"text":589},{"id":612,"depth":441,"text":613},{"id":624,"depth":417,"text":625,"children":1250},[1251,1252],{"id":654,"depth":441,"text":655},{"id":676,"depth":441,"text":677},{"id":752,"depth":417,"text":753,"children":1254},[1255,1256,1257],{"id":766,"depth":441,"text":767},{"id":773,"depth":441,"text":774},{"id":780,"depth":441,"text":781},{"id":817,"depth":417,"text":818},{"id":873,"depth":417,"text":874},{"id":919,"depth":417,"text":920,"children":1261},[1262,1263,1264,1265,1266],{"id":926,"depth":441,"text":927},{"id":977,"depth":441,"text":978},{"id":1010,"depth":441,"text":1011},{"id":1044,"depth":441,"text":1045},{"id":1078,"depth":441,"text":1079},{"id":1114,"depth":417,"text":1115},"Guide",null,"LangChain ha migliorato del 14% le performance di un agente senza cambiare modello: solo l'harness. Guida pratica alle 3 componenti che rendono gli agenti più capaci.","Avanzato","md",false,"/images/guides/harness-engineering-controllare-agenti-ai.webp",{},"/guides/harness-engineering-controllare-agenti-ai","2026-03-24",17,{"title":5,"description":1270},"guides/harness-engineering-controllare-agenti-ai",[1282,1283,1284,1285,1286,1287],"Harness Engineering","AI Coding","Agenti AI","Context Engineering","Sicurezza","Claude Code","Ux0418U_1jlNby8m0ZtOl8N-2Oe49HfxkSlw0OGFmhQ",[1290,2777,4531],{"id":1291,"title":1292,"author":1293,"body":1294,"category":2766,"contentType":1269,"description":2767,"difficulty":2768,"extension":1272,"featured":444,"icon":1269,"image":2769,"meta":2770,"navigation":444,"path":2771,"publishedAt":2772,"readingTime":1714,"seo":2773,"stem":2774,"steps":1269,"tags":2775,"youtubeId":1269,"__hash__":2776},"guides/guides/come-scrivere-claude-md-che-funziona.md","Come Scrivere un CLAUDE.md che Funziona Davvero",{"name":7,"initials":8},{"type":10,"value":1295,"toc":2734},[1296,1299,1305,1308,1315,1318,1320,1324,1327,1454,1465,1476,1480,1514,1516,1520,1523,1529,1533,1547,1551,1628,1632,1635,1798,1804,1806,1810,1813,1817,1837,1840,1844,1864,1875,1879,1888,1895,1904,1907,1911,1921,1925,1932,1938,1940,1944,1947,1976,1979,1982,1984,1988,1994,2000,2007,2060,2085,2096,2098,2102,2177,2187,2190,2244,2247,2249,2253,2256,2363,2367,2372,2379,2394,2398,2401,2417,2420,2422,2426,2433,2449,2452,2456,2485,2487,2491,2495,2498,2527,2531,2537,2543,2555,2561,2576,2578,2582,2585,2651,2658,2660,2665,2731],[13,1297,1292],{"id":1298},"come-scrivere-un-claudemd-che-funziona-davvero",[17,1300,1301,1302,688],{},"Ogni volta che avvii Claude Code, la prima cosa che fa è leggere un file: ",[24,1303,1304],{},"CLAUDE.md",[17,1306,1307],{},"È un file Markdown che viene iniettato nel system prompt di ogni conversazione. Contiene le istruzioni del tuo progetto: stack tecnologico, comandi, convenzioni, architettura, cose da non fare. È la differenza tra un agente che capisce il tuo progetto e uno che lavora alla cieca.",[17,1309,1310,1311,1314],{},"Il problema è che la maggior parte dei CLAUDE.md là fuori è o troppo lunga, o troppo generica, o piena di cose che Claude sa già. E un CLAUDE.md scritto male non è neutro — è ",[24,1312,1313],{},"attivamente dannoso",", perché consuma context window senza dare valore.",[17,1316,1317],{},"Questa guida ti spiega come scriverne uno che funziona.",[35,1319],{},[38,1321,1323],{"id":1322},"la-gerarchia-6-livelli-di-istruzioni","La Gerarchia: 6 Livelli di Istruzioni",[17,1325,1326],{},"Claude Code non legge un solo CLAUDE.md. Ne legge diversi, a livelli, dal più generico al più specifico:",[244,1328,1329,1345],{},[247,1330,1331],{},[250,1332,1333,1336,1339,1342],{},[253,1334,1335],{},"Livello",[253,1337,1338],{},"Dove",[253,1340,1341],{},"Scopo",[253,1343,1344],{},"Condiviso con",[260,1346,1347,1365,1383,1402,1419,1437],{},[250,1348,1349,1354,1359,1362],{},[265,1350,1351],{},[24,1352,1353],{},"Managed Policy",[265,1355,1356],{},[353,1357,1358],{},"C:\\Program Files\\ClaudeCode\\CLAUDE.md",[265,1360,1361],{},"Regole aziendali (IT/DevOps)",[265,1363,1364],{},"Tutta l'organizzazione",[250,1366,1367,1372,1377,1380],{},[265,1368,1369],{},[24,1370,1371],{},"User Memory",[265,1373,1374],{},[353,1375,1376],{},"~/.claude/CLAUDE.md",[265,1378,1379],{},"Preferenze personali globali",[265,1381,1382],{},"Solo te (tutti i progetti)",[250,1384,1385,1390,1396,1399],{},[265,1386,1387],{},[24,1388,1389],{},"Project Memory",[265,1391,1392,1395],{},[353,1393,1394],{},"./CLAUDE.md"," (root progetto)",[265,1397,1398],{},"Istruzioni del team",[265,1400,1401],{},"Team (via git)",[250,1403,1404,1409,1414,1417],{},[265,1405,1406],{},[24,1407,1408],{},"Project Rules",[265,1410,1411],{},[353,1412,1413],{},".claude/rules/*.md",[265,1415,1416],{},"Regole modulari per topic",[265,1418,1401],{},[250,1420,1421,1426,1431,1434],{},[265,1422,1423],{},[24,1424,1425],{},"Project Local",[265,1427,1428],{},[353,1429,1430],{},"./CLAUDE.local.md",[265,1432,1433],{},"Preferenze personali per progetto",[265,1435,1436],{},"Solo te",[250,1438,1439,1444,1449,1452],{},[265,1440,1441],{},[24,1442,1443],{},"Auto Memory",[265,1445,1446],{},[353,1447,1448],{},"~/.claude/projects/\u003Cproject>/memory/",[265,1450,1451],{},"Note automatiche di Claude",[265,1453,1436],{},[17,1455,1456,1457,1460,1461,1464],{},"Le istruzioni più specifiche hanno ",[24,1458,1459],{},"precedenza"," su quelle più generiche. I file nelle directory figlie vengono caricati ",[24,1462,1463],{},"on demand"," — solo quando Claude lavora su file in quelle cartelle.",[17,1466,1467,1468,1471,1472,1475],{},"Il ",[353,1469,1470],{},"CLAUDE.local.md"," viene aggiunto automaticamente al ",[353,1473,1474],{},".gitignore"," — è il posto giusto per le tue preferenze personali che non vuoi condividere col team.",[58,1477,1479],{"id":1478},"la-regola-pratica","La regola pratica",[82,1481,1482,1490,1497,1506],{},[85,1483,1484,1486,1487,1489],{},[24,1485,1371],{}," (",[353,1488,1376],{},"): preferenze che valgono per TUTTI i tuoi progetti (es: \"usa git bash su Windows\", \"non fare commit senza chiedere\")",[85,1491,1492,1486,1494,1496],{},[24,1493,1389],{},[353,1495,1394],{},"): tutto ciò che il team deve sapere (stack, comandi, architettura)",[85,1498,1499,1486,1502,1505],{},[24,1500,1501],{},"Rules",[353,1503,1504],{},".claude/rules/","): regole specifiche per area (frontend, backend, testing)",[85,1507,1508,1486,1511,1513],{},[24,1509,1510],{},"Local",[353,1512,1430],{},"): le tue abitudini personali su quel progetto",[35,1515],{},[38,1517,1519],{"id":1518},"cosa-metterci","Cosa Metterci",[17,1521,1522],{},"Il principio guida lo dà Anthropic stessa:",[1524,1525,1526],"blockquote",{},[17,1527,1528],{},"\"Per ogni riga del CLAUDE.md, chiediti: rimuovere questa istruzione causerebbe errori a Claude? Se la risposta è no, eliminala.\"",[58,1530,1532],{"id":1531},"il-framework-cosa-perché-come","Il framework: COSA-PERCHÉ-COME",[17,1534,1535,1538,1539,1542,1543,1546],{},[24,1536,1537],{},"COSA"," — Il progetto, lo stack, la struttura.\n",[24,1540,1541],{},"PERCHÉ"," — Le decisioni architetturali e il motivo dietro le scelte.\n",[24,1544,1545],{},"COME"," — I comandi, il workflow, le regole operative.",[58,1548,1550],{"id":1549},"cosa-ha-senso-includere","Cosa ha senso includere",[244,1552,1553,1563],{},[247,1554,1555],{},[250,1556,1557,1560],{},[253,1558,1559],{},"Includi",[253,1561,1562],{},"Perché",[260,1564,1565,1576,1588,1596,1604,1612,1620],{},[250,1566,1567,1570],{},[265,1568,1569],{},"Comandi che Claude non può indovinare",[265,1571,1572,1575],{},[353,1573,1574],{},"npm run dev -- --port 3002"," non è ovvio",[250,1577,1578,1585],{},[265,1579,1580,1581,1584],{},"Regole di stile che ",[24,1582,1583],{},"differiscono"," dai default",[265,1586,1587],{},"Se usi tab invece di spazi, dillo. Se usi 2 spazi come tutti, no",[250,1589,1590,1593],{},[265,1591,1592],{},"Test runner e come eseguire i test",[265,1594,1595],{},"Claude deve poter verificare il suo lavoro",[250,1597,1598,1601],{},[265,1599,1600],{},"Convenzioni del repo (branch naming, formato PR)",[265,1602,1603],{},"Non sono nel codice",[250,1605,1606,1609],{},[265,1607,1608],{},"Decisioni architetturali specifiche",[265,1610,1611],{},"\"Usiamo SSG, non SSR\" cambia tutto l'approccio",[250,1613,1614,1617],{},[265,1615,1616],{},"Gotcha e comportamenti non ovvi",[265,1618,1619],{},"\"Il deploy su IIS non serve filename troppo lunghi\"",[250,1621,1622,1625],{},[265,1623,1624],{},"Variabili d'ambiente richieste",[265,1626,1627],{},"Claude non può leggerle dal tuo .env",[58,1629,1631],{"id":1630},"esempio-concreto","Esempio concreto",[17,1633,1634],{},"Ecco un CLAUDE.md reale per un progetto Nuxt:",[346,1636,1640],{"className":1637,"code":1638,"language":1639,"meta":355,"style":355},"language-markdown shiki shiki-themes github-light github-dark","# Agent Coding Italia\n\nBlog statico su AI e coding.\n\n## Stack\n- Nuxt 4.3.0 + @nuxt/content v3 + TailwindCSS\n- SSG: `nuxt generate` (NON SSR)\n- Deploy: `python deploy.py` (FTP su Windows Server/IIS)\n\n## Comandi\n- `npm run dev -- --port 3002` — dev server\n- `npm run generate` — build statico\n- `python deploy.py` — build + deploy FTP\n\n## Architettura contenuti\n- Collezioni: articles, guides, tools, videos, lives, teoria, news\n- Definite in `content.config.ts`\n- API: `queryCollection('collectionName').all()` (v3 syntax)\n- File con `_` prefix sono draft (es: `_articolo-bozza.md`)\n\n## Convenzioni\n- useContentData composable per tutte le query (MAI getCachedData: () => null)\n- Immagini: `/public/images/{sezione}/{slug}.webp` (1536x1024)\n- Ogni articolo ha frontmatter: title, description, publishedAt, author, image, category, tags, readingTime\n\n## Cose da NON fare\n- NON usare getCachedData: () => null in useAsyncData (causa contenuti vuoti)\n- NON caricare su IIS file con nomi troppo lunghi (>40 caratteri)\n","markdown",[353,1641,1642,1647,1651,1656,1660,1665,1671,1677,1683,1688,1694,1700,1706,1712,1717,1723,1729,1734,1740,1746,1751,1757,1763,1769,1775,1780,1786,1792],{"__ignoreMap":355},[407,1643,1644],{"class":409,"line":410},[407,1645,1646],{},"# Agent Coding Italia\n",[407,1648,1649],{"class":409,"line":417},[407,1650,445],{"emptyLinePlaceholder":444},[407,1652,1653],{"class":409,"line":441},[407,1654,1655],{},"Blog statico su AI e coding.\n",[407,1657,1658],{"class":409,"line":448},[407,1659,445],{"emptyLinePlaceholder":444},[407,1661,1662],{"class":409,"line":454},[407,1663,1664],{},"## Stack\n",[407,1666,1668],{"class":409,"line":1667},6,[407,1669,1670],{},"- Nuxt 4.3.0 + @nuxt/content v3 + TailwindCSS\n",[407,1672,1674],{"class":409,"line":1673},7,[407,1675,1676],{},"- SSG: `nuxt generate` (NON SSR)\n",[407,1678,1680],{"class":409,"line":1679},8,[407,1681,1682],{},"- Deploy: `python deploy.py` (FTP su Windows Server/IIS)\n",[407,1684,1686],{"class":409,"line":1685},9,[407,1687,445],{"emptyLinePlaceholder":444},[407,1689,1691],{"class":409,"line":1690},10,[407,1692,1693],{},"## Comandi\n",[407,1695,1697],{"class":409,"line":1696},11,[407,1698,1699],{},"- `npm run dev -- --port 3002` — dev server\n",[407,1701,1703],{"class":409,"line":1702},12,[407,1704,1705],{},"- `npm run generate` — build statico\n",[407,1707,1709],{"class":409,"line":1708},13,[407,1710,1711],{},"- `python deploy.py` — build + deploy FTP\n",[407,1713,1715],{"class":409,"line":1714},14,[407,1716,445],{"emptyLinePlaceholder":444},[407,1718,1720],{"class":409,"line":1719},15,[407,1721,1722],{},"## Architettura contenuti\n",[407,1724,1726],{"class":409,"line":1725},16,[407,1727,1728],{},"- Collezioni: articles, guides, tools, videos, lives, teoria, news\n",[407,1730,1731],{"class":409,"line":1278},[407,1732,1733],{},"- Definite in `content.config.ts`\n",[407,1735,1737],{"class":409,"line":1736},18,[407,1738,1739],{},"- API: `queryCollection('collectionName').all()` (v3 syntax)\n",[407,1741,1743],{"class":409,"line":1742},19,[407,1744,1745],{},"- File con `_` prefix sono draft (es: `_articolo-bozza.md`)\n",[407,1747,1749],{"class":409,"line":1748},20,[407,1750,445],{"emptyLinePlaceholder":444},[407,1752,1754],{"class":409,"line":1753},21,[407,1755,1756],{},"## Convenzioni\n",[407,1758,1760],{"class":409,"line":1759},22,[407,1761,1762],{},"- useContentData composable per tutte le query (MAI getCachedData: () => null)\n",[407,1764,1766],{"class":409,"line":1765},23,[407,1767,1768],{},"- Immagini: `/public/images/{sezione}/{slug}.webp` (1536x1024)\n",[407,1770,1772],{"class":409,"line":1771},24,[407,1773,1774],{},"- Ogni articolo ha frontmatter: title, description, publishedAt, author, image, category, tags, readingTime\n",[407,1776,1778],{"class":409,"line":1777},25,[407,1779,445],{"emptyLinePlaceholder":444},[407,1781,1783],{"class":409,"line":1782},26,[407,1784,1785],{},"## Cose da NON fare\n",[407,1787,1789],{"class":409,"line":1788},27,[407,1790,1791],{},"- NON usare getCachedData: () => null in useAsyncData (causa contenuti vuoti)\n",[407,1793,1795],{"class":409,"line":1794},28,[407,1796,1797],{},"- NON caricare su IIS file con nomi troppo lunghi (>40 caratteri)\n",[17,1799,1800,1803],{},[24,1801,1802],{},"60 righe. Zero fuffa."," Tutto quello che serve a Claude per lavorare correttamente su questo progetto.",[35,1805],{},[38,1807,1809],{"id":1808},"cosa-non-metterci","Cosa NON Metterci",[17,1811,1812],{},"Questo è il punto dove la maggior parte dei CLAUDE.md fallisce.",[58,1814,1816],{"id":1815},"_1-cose-che-claude-sa-già","1. Cose che Claude sa già",[346,1818,1820],{"className":1637,"code":1819,"language":1639,"meta":355,"style":355},"❌ \"Scrivi codice pulito e ben organizzato\"\n❌ \"Usa nomi di variabili significativi\"\n❌ \"Gestisci gli errori correttamente\"\n",[353,1821,1822,1827,1832],{"__ignoreMap":355},[407,1823,1824],{"class":409,"line":410},[407,1825,1826],{},"❌ \"Scrivi codice pulito e ben organizzato\"\n",[407,1828,1829],{"class":409,"line":417},[407,1830,1831],{},"❌ \"Usa nomi di variabili significativi\"\n",[407,1833,1834],{"class":409,"line":441},[407,1835,1836],{},"❌ \"Gestisci gli errori correttamente\"\n",[17,1838,1839],{},"Claude lo fa già. Stai sprecando token per dirgli di fare il suo lavoro.",[58,1841,1843],{"id":1842},"_2-regole-di-stile-che-un-linter-fa-meglio","2. Regole di stile che un linter fa meglio",[346,1845,1847],{"className":1637,"code":1846,"language":1639,"meta":355,"style":355},"❌ \"Usa 2 spazi per l'indentazione\"\n❌ \"Metti sempre il punto e virgola\"\n❌ \"Ordina gli import alfabeticamente\"\n",[353,1848,1849,1854,1859],{"__ignoreMap":355},[407,1850,1851],{"class":409,"line":410},[407,1852,1853],{},"❌ \"Usa 2 spazi per l'indentazione\"\n",[407,1855,1856],{"class":409,"line":417},[407,1857,1858],{},"❌ \"Metti sempre il punto e virgola\"\n",[407,1860,1861],{"class":409,"line":441},[407,1862,1863],{},"❌ \"Ordina gli import alfabeticamente\"\n",[17,1865,1866,1867,1870,1871,1874],{},"Come dice il team di HumanLayer: ",[24,1868,1869],{},"\"Never send an LLM to do a linter's job.\""," Se hai ESLint o Prettier configurato, usa gli ",[24,1872,1873],{},"hooks"," per eseguirli automaticamente dopo ogni modifica. È deterministico, veloce e non consuma context.",[58,1876,1878],{"id":1877},"_3-documentazione-lunga","3. Documentazione lunga",[346,1880,1882],{"className":1637,"code":1881,"language":1639,"meta":355,"style":355},"❌ \"La nostra API REST segue questi pattern: [300 righe di documentazione]\"\n",[353,1883,1884],{"__ignoreMap":355},[407,1885,1886],{"class":409,"line":410},[407,1887,1881],{},[17,1889,1890,1891,1894],{},"Usa invece un ",[24,1892,1893],{},"puntatore",":",[346,1896,1898],{"className":1637,"code":1897,"language":1639,"meta":355,"style":355},"✅ \"Per i pattern API, vedi docs/api-patterns.md\"\n",[353,1899,1900],{"__ignoreMap":355},[407,1901,1902],{"class":409,"line":410},[407,1903,1897],{},[17,1905,1906],{},"Claude leggerà il file quando ne avrà bisogno. Non serve caricarlo in ogni sessione.",[58,1908,1910],{"id":1909},"_4-credenziali-e-segreti","4. Credenziali e segreti",[17,1912,1913,1914,1917,1918,1920],{},"Il CLAUDE.md va in git. ",[24,1915,1916],{},"Mai"," metterci API key, password o token. Usa il ",[353,1919,1470],{}," (che è in .gitignore) per riferimenti a variabili d'ambiente locali.",[58,1922,1924],{"id":1923},"_5-un-claudemd-troppo-lungo","5. Un CLAUDE.md troppo lungo",[17,1926,1927,1928,1931],{},"La ricerca mostra che la qualità con cui i modelli seguono le istruzioni ",[24,1929,1930],{},"degrada linearmente"," con il numero di istruzioni. Con un CLAUDE.md da 500+ righe, le regole importanti si perdono nel rumore.",[17,1933,1934,1937],{},[24,1935,1936],{},"La community concorda: sotto le 200 righe è l'ideale."," HumanLayer tiene il suo sotto le 60.",[35,1939],{},[38,1941,1943],{"id":1942},"il-sistema-imports","Il Sistema @imports",[17,1945,1946],{},"Non serve mettere tutto in un file. CLAUDE.md supporta gli import:",[346,1948,1950],{"className":1637,"code":1949,"language":1639,"meta":355,"style":355},"# Progetto\n\nVedi @README.md per overview del progetto\nConvenzioni API: @docs/api-conventions.md\nWorkflow git: @docs/git-workflow.md\n",[353,1951,1952,1957,1961,1966,1971],{"__ignoreMap":355},[407,1953,1954],{"class":409,"line":410},[407,1955,1956],{},"# Progetto\n",[407,1958,1959],{"class":409,"line":417},[407,1960,445],{"emptyLinePlaceholder":444},[407,1962,1963],{"class":409,"line":441},[407,1964,1965],{},"Vedi @README.md per overview del progetto\n",[407,1967,1968],{"class":409,"line":448},[407,1969,1970],{},"Convenzioni API: @docs/api-conventions.md\n",[407,1972,1973],{"class":409,"line":454},[407,1974,1975],{},"Workflow git: @docs/git-workflow.md\n",[17,1977,1978],{},"I path sono relativi al file che contiene l'import. Supporta fino a 5 livelli di profondità. Al primo utilizzo, Claude Code chiede conferma.",[17,1980,1981],{},"Questo è il pattern giusto per progetti grandi: un CLAUDE.md snello con puntatori a documenti di dettaglio.",[35,1983],{},[38,1985,1987],{"id":1986},"rules-directory-regole-modulari","Rules Directory: Regole Modulari",[17,1989,1990,1991,1993],{},"Per progetti con più aree (frontend, backend, infra), le regole modulari in ",[353,1992,1504],{}," sono più efficaci di un unico CLAUDE.md monolitico.",[346,1995,1998],{"className":1996,"code":1997,"language":351},[349],".claude/rules/\n  frontend.md\n  backend.md\n  testing.md\n  security.md\n",[353,1999,1997],{"__ignoreMap":355},[17,2001,2002,2003,2006],{},"Il vantaggio: puoi usare ",[24,2004,2005],{},"path-specific targeting"," con frontmatter YAML:",[346,2008,2010],{"className":1637,"code":2009,"language":1639,"meta":355,"style":355},"---\npaths:\n  - \"src/api/**/*.ts\"\n  - \"lib/**/*.ts\"\n---\n\n# Regole API\n- Tutti gli endpoint includono validazione input\n- Usa il formato standard per le risposte errore\n- I test vanno in `__tests__/` accanto al file sorgente\n",[353,2011,2012,2017,2022,2027,2032,2036,2040,2045,2050,2055],{"__ignoreMap":355},[407,2013,2014],{"class":409,"line":410},[407,2015,2016],{},"---\n",[407,2018,2019],{"class":409,"line":417},[407,2020,2021],{},"paths:\n",[407,2023,2024],{"class":409,"line":441},[407,2025,2026],{},"  - \"src/api/**/*.ts\"\n",[407,2028,2029],{"class":409,"line":448},[407,2030,2031],{},"  - \"lib/**/*.ts\"\n",[407,2033,2034],{"class":409,"line":454},[407,2035,2016],{},[407,2037,2038],{"class":409,"line":1667},[407,2039,445],{"emptyLinePlaceholder":444},[407,2041,2042],{"class":409,"line":1673},[407,2043,2044],{},"# Regole API\n",[407,2046,2047],{"class":409,"line":1679},[407,2048,2049],{},"- Tutti gli endpoint includono validazione input\n",[407,2051,2052],{"class":409,"line":1685},[407,2053,2054],{},"- Usa il formato standard per le risposte errore\n",[407,2056,2057],{"class":409,"line":1690},[407,2058,2059],{},"- I test vanno in `__tests__/` accanto al file sorgente\n",[17,2061,2062,2063,2066,2067,2070,2071,2074,2075,2078,2079,2078,2082,688],{},"Le regole ",[24,2064,2065],{},"senza"," frontmatter ",[353,2068,2069],{},"paths"," si applicano a tutti i file. Quelle ",[24,2072,2073],{},"con"," paths si caricano solo quando Claude lavora su file corrispondenti. Supporta glob patterns: ",[353,2076,2077],{},"**/*.ts",", ",[353,2080,2081],{},"src/**/*",[353,2083,2084],{},"*.{ts,tsx}",[17,2086,2087,2088,2091,2092,2095],{},"Risultato: ",[24,2089,2090],{},"meno token consumati"," perché le regole si caricano on demand, e ",[24,2093,2094],{},"più precisione"," perché le regole sono specifiche per il contesto.",[35,2097],{},[38,2099,2101],{"id":2100},"hooks-vs-claudemd-quando-usare-cosa","Hooks vs CLAUDE.md: Quando Usare Cosa",[244,2103,2104,2115],{},[247,2105,2106],{},[250,2107,2108,2110,2112],{},[253,2109],{},[253,2111,1304],{},[253,2113,2114],{},"Hooks",[260,2116,2117,2138,2151,2164],{},[250,2118,2119,2124,2132],{},[265,2120,2121],{},[24,2122,2123],{},"Natura",[265,2125,2126,2127,2131],{},"Advisory — Claude ",[2128,2129,2130],"em",{},"può"," ignorarlo",[265,2133,2134,2135],{},"Deterministico — si esegue ",[2128,2136,2137],{},"sempre",[250,2139,2140,2145,2148],{},[265,2141,2142],{},[24,2143,2144],{},"Caricamento",[265,2146,2147],{},"Nel contesto LLM",[265,2149,2150],{},"Eseguito come script shell",[250,2152,2153,2158,2161],{},[265,2154,2155],{},[24,2156,2157],{},"Uso",[265,2159,2160],{},"Convenzioni, preferenze, contesto",[265,2162,2163],{},"Azioni che DEVONO succedere",[250,2165,2166,2171,2174],{},[265,2167,2168],{},[24,2169,2170],{},"Esempio",[265,2172,2173],{},"\"Preferisci composable a mixin\"",[265,2175,2176],{},"\"Esegui ESLint dopo ogni edit\"",[17,2178,2179,2182,2183,2186],{},[24,2180,2181],{},"La regola",": se un'azione deve succedere il ",[24,2184,2185],{},"100% delle volte"," (linting, formatting, validazione), usa un hook. Se è una preferenza o una convenzione che richiede giudizio, mettila nel CLAUDE.md.",[17,2188,2189],{},"Un hook tipico per linting:",[346,2191,2195],{"className":2192,"code":2193,"language":2194,"meta":355,"style":355},"language-json shiki shiki-themes github-light github-dark","{\n  \"hooks\": {\n    \"postEdit\": {\n      \"command\": \"npx eslint --fix $FILE\"\n    }\n  }\n}\n","json",[353,2196,2197,2203,2211,2218,2229,2234,2239],{"__ignoreMap":355},[407,2198,2199],{"class":409,"line":410},[407,2200,2202],{"class":2201},"sVt8B","{\n",[407,2204,2205,2208],{"class":409,"line":417},[407,2206,2207],{"class":434},"  \"hooks\"",[407,2209,2210],{"class":2201},": {\n",[407,2212,2213,2216],{"class":409,"line":441},[407,2214,2215],{"class":434},"    \"postEdit\"",[407,2217,2210],{"class":2201},[407,2219,2220,2223,2226],{"class":409,"line":448},[407,2221,2222],{"class":434},"      \"command\"",[407,2224,2225],{"class":2201},": ",[407,2227,2228],{"class":424},"\"npx eslint --fix $FILE\"\n",[407,2230,2231],{"class":409,"line":454},[407,2232,2233],{"class":2201},"    }\n",[407,2235,2236],{"class":409,"line":1667},[407,2237,2238],{"class":2201},"  }\n",[407,2240,2241],{"class":409,"line":1673},[407,2242,2243],{"class":2201},"}\n",[17,2245,2246],{},"Nessun token speso. Nessuna possibilità che Claude \"dimentichi\".",[35,2248],{},[38,2250,2252],{"id":2251},"confronto-claudemd-vs-cursorrules-vs-agentsmd","Confronto: CLAUDE.md vs .cursorrules vs AGENTS.md",[17,2254,2255],{},"Ogni tool ha il suo sistema di configurazione. Ecco come si confrontano:",[244,2257,2258,2271],{},[247,2259,2260],{},[250,2261,2262,2265,2268],{},[253,2263,2264],{},"Tool",[253,2266,2267],{},"File",[253,2269,2270],{},"Standard",[260,2272,2273,2288,2307,2321,2335,2349],{},[250,2274,2275,2279,2285],{},[265,2276,2277],{},[24,2278,1287],{},[265,2280,2281,2078,2283],{},[353,2282,1304],{},[353,2284,1504],{},[265,2286,2287],{},"Proprietario",[250,2289,2290,2295,2304],{},[265,2291,2292],{},[24,2293,2294],{},"Cursor",[265,2296,2297,2078,2300,2303],{},[353,2298,2299],{},".cursor/rules/",[353,2301,2302],{},".cursorrules"," (legacy)",[265,2305,2306],{},"Proprietario + AGENTS.md",[250,2308,2309,2314,2319],{},[265,2310,2311],{},[24,2312,2313],{},"GitHub Copilot",[265,2315,2316],{},[353,2317,2318],{},".github/copilot-instructions.md",[265,2320,2287],{},[250,2322,2323,2328,2333],{},[265,2324,2325],{},[24,2326,2327],{},"Gemini CLI",[265,2329,2330],{},[353,2331,2332],{},"GEMINI.md",[265,2334,2306],{},[250,2336,2337,2342,2347],{},[265,2338,2339],{},[24,2340,2341],{},"OpenAI Codex",[265,2343,2344],{},[353,2345,2346],{},"AGENTS.md",[265,2348,2346],{},[250,2350,2351,2356,2361],{},[265,2352,2353],{},[24,2354,2355],{},"Windsurf",[265,2357,2358],{},[353,2359,2360],{},".windsurfrules",[265,2362,2306],{},[58,2364,2366],{"id":2365},"agentsmd-lo-standard-aperto","AGENTS.md: lo standard aperto",[17,2368,2369,2371],{},[24,2370,2346],{}," è uno standard aperto sotto la Linux Foundation, adottato da 60.000+ progetti open source. Lo supportano Codex, Cursor, Amp, Google Jules, Zed, Warp e molti altri.",[17,2373,2374,2375,2378],{},"Claude Code ",[24,2376,2377],{},"non supporta AGENTS.md nativamente"," (c'è una feature request aperta su GitHub). Il workaround: crea un AGENTS.md come source of truth e importalo nel CLAUDE.md:",[346,2380,2382],{"className":1637,"code":2381,"language":1639,"meta":355,"style":355},"# CLAUDE.md\n@AGENTS.md\n",[353,2383,2384,2389],{"__ignoreMap":355},[407,2385,2386],{"class":409,"line":410},[407,2387,2388],{},"# CLAUDE.md\n",[407,2390,2391],{"class":409,"line":417},[407,2392,2393],{},"@AGENTS.md\n",[58,2395,2397],{"id":2396},"se-usi-più-tool","Se usi più tool",[17,2399,2400],{},"Se alterni tra Claude Code e Cursor (o altri), il consiglio è:",[517,2402,2403,2409],{},[85,2404,2405,2406,2408],{},"Mantieni un ",[24,2407,2346],{}," come documentazione universale del progetto",[85,2410,2411,2412,2078,2414,2416],{},"Crea file tool-specific (",[353,2413,1304],{},[353,2415,2302],{},") che importano AGENTS.md e aggiungono solo le istruzioni specifiche per quel tool",[17,2418,2419],{},"In questo modo non duplichi informazioni e ogni tool ha le sue regole specifiche.",[35,2421],{},[38,2423,2425],{"id":2424},"limpatto-sulla-context-window","L'Impatto sulla Context Window",[17,2427,2428,2429,2432],{},"Ogni riga del CLAUDE.md viene caricata in ",[24,2430,2431],{},"ogni sessione",". Su una context window di 200K token, il budget è limitato:",[82,2434,2435,2438,2441,2444],{},[85,2436,2437],{},"System prompt: ~5-15K token",[85,2439,2440],{},"CLAUDE.md + rules: ~1-10K token",[85,2442,2443],{},"MCP tools schema: ~5-20K token",[85,2445,2446],{},[24,2447,2448],{},"Spazio per lavorare: ~140-150K token",[17,2450,2451],{},"Un CLAUDE.md da 300 righe consuma circa 2-5K token. Non sembra molto, ma sommato a rules, MCP tools e system prompt, il contesto disponibile si riduce velocemente.",[58,2453,2455],{"id":2454},"strategie","Strategie",[82,2457,2458,2464,2470,2476],{},[85,2459,2460,2463],{},[24,2461,2462],{},"Prompt caching",": Anthropic applica automaticamente il caching per il CLAUDE.md — le parti statiche costano meno nelle richieste successive",[85,2465,2466,2469],{},[24,2467,2468],{},"Rules con path targeting",": si caricano solo quando servono",[85,2471,2472,2475],{},[24,2473,2474],{},"@imports",": Claude legge i file referenziati solo quando ne ha bisogno",[85,2477,2478,2484],{},[24,2479,2480,2483],{},[353,2481,2482],{},"/clear"," tra task non correlati",": resetta il contesto accumulato",[35,2486],{},[38,2488,2490],{"id":2489},"tips-dai-power-user","Tips dai Power User",[58,2492,2494],{"id":2493},"boris-cherny-creatore-di-claude-code","Boris Cherny (creatore di Claude Code)",[17,2496,2497],{},"Il suo setup è \"sorprendentemente vanilla\":",[82,2499,2500,2507,2513,2520],{},[85,2501,2502,2503,2506],{},"Un ",[24,2504,2505],{},"singolo CLAUDE.md"," condiviso col team, committato in git",[85,2508,2509,2510],{},"Il team lo aggiorna più volte a settimana: ",[2128,2511,2512],{},"\"Anytime we see Claude do something incorrectly we add it to the CLAUDE.md, so Claude knows not to do it next time\"",[85,2514,2515,2516,2519],{},"Usa ",[24,2517,2518],{},"Plan Mode"," prima di tutto, poi auto-accept",[85,2521,2522,2523,2526],{},"La cosa più importante: ",[24,2524,2525],{},"dare a Claude un modo per verificare il suo lavoro"," — questo da solo raddoppia la qualità",[58,2528,2530],{"id":2529},"pattern-ricorrenti-della-community","Pattern ricorrenti della community",[17,2532,2533,2536],{},[24,2534,2535],{},"Tratta il CLAUDE.md come codice."," Fai review quando qualcosa va storto, pruna le regole che non servono più, testa le modifiche.",[17,2538,2539,2542],{},[24,2540,2541],{},"Enfasi per istruzioni critiche."," \"IMPORTANT\" o \"MAI\" migliorano l'aderenza. Ma usali con parsimonia — se tutto è importante, niente lo è.",[17,2544,2545,2551,2552,2554],{},[24,2546,2547,2548,688],{},"Il tasto ",[353,2549,2550],{},"#"," Premendo ",[353,2553,2550],{}," all'inizio di un messaggio in Claude Code, puoi aggiungere rapidamente una nota al CLAUDE.md senza aprire il file. Utile quando Claude fa un errore e vuoi che non lo ripeta.",[17,2556,2557,2560],{},[24,2558,2559],{},"Compaction personalizzata."," Quando il contesto si riempie, Claude riassume la conversazione. Puoi guidare cosa preservare:",[346,2562,2564],{"className":1637,"code":2563,"language":1639,"meta":355,"style":355},"## Compaction\nQuando comprimi il contesto, preserva SEMPRE la lista completa dei file modificati.\n",[353,2565,2566,2571],{"__ignoreMap":355},[407,2567,2568],{"class":409,"line":410},[407,2569,2570],{},"## Compaction\n",[407,2572,2573],{"class":409,"line":417},[407,2574,2575],{},"Quando comprimi il contesto, preserva SEMPRE la lista completa dei file modificati.\n",[35,2577],{},[38,2579,2581],{"id":2580},"checklist-finale","Checklist Finale",[17,2583,2584],{},"Prima di committare il tuo CLAUDE.md, verifica:",[82,2586,2588,2597,2606,2615,2624,2633,2642],{"className":2587},[931],[85,2589,2591,940,2593,2596],{"className":2590},[935],[937,2592],{"disabled":444,"type":939},[24,2594,2595],{},"Sotto le 200 righe?"," Se no, probabilmente stai includendo cose inutili",[85,2598,2600,940,2602,2605],{"className":2599},[935],[937,2601],{"disabled":444,"type":939},[24,2603,2604],{},"Ogni riga è necessaria?"," Se la togli, Claude farebbe errori?",[85,2607,2609,940,2611,2614],{"className":2608},[935],[937,2610],{"disabled":444,"type":939},[24,2612,2613],{},"Zero credenziali?"," API key, password, token devono stare altrove",[85,2616,2618,940,2620,2623],{"className":2617},[935],[937,2619],{"disabled":444,"type":939},[24,2621,2622],{},"Niente ovvietà?"," \"Scrivi codice pulito\" non serve a nessuno",[85,2625,2627,940,2629,2632],{"className":2626},[935],[937,2628],{"disabled":444,"type":939},[24,2630,2631],{},"Niente regole da linter?"," Usa hooks per formatting e linting",[85,2634,2636,940,2638,2641],{"className":2635},[935],[937,2637],{"disabled":444,"type":939},[24,2639,2640],{},"Comandi specifici?"," Dev server, test runner, deploy — tutto ciò che Claude non può indovinare",[85,2643,2645,940,2647,2650],{"className":2644},[935],[937,2646],{"disabled":444,"type":939},[24,2648,2649],{},"Gotcha documentati?"," Comportamenti non ovvi, bug noti, cose che rompono",[17,2652,2653,2654,2657],{},"Se il tuo CLAUDE.md supera questo filtro, hai un file che ",[24,2655,2656],{},"funziona davvero"," — non uno che occupa spazio nel contesto sperando che Claude lo legga.",[35,2659],{},[17,2661,2662,1894],{},[24,2663,2664],{},"Fonti e approfondimenti",[82,2666,2667,2675,2683,2691,2699,2707,2715,2723],{},[85,2668,2669,2674],{},[69,2670,2673],{"href":2671,"rel":2672},"https://claude.com/blog/using-claude-md-files",[1152],"Anthropic - Using CLAUDE.md Files"," — Guida ufficiale",[85,2676,2677,2682],{},[69,2678,2681],{"href":2679,"rel":2680},"https://code.claude.com/docs/en/best-practices",[1152],"Claude Code - Best Practices"," — Documentazione ufficiale",[85,2684,2685,2690],{},[69,2686,2689],{"href":2687,"rel":2688},"https://code.claude.com/docs/en/memory",[1152],"Claude Code - Memory Management"," — Gerarchia completa dei file",[85,2692,2693,2698],{},[69,2694,2697],{"href":2695,"rel":2696},"https://www.humanlayer.dev/blog/writing-a-good-claude-md",[1152],"HumanLayer - Writing a Good CLAUDE.md"," — Anti-pattern e framework WHAT-WHY-HOW",[85,2700,2701,2706],{},[69,2702,2705],{"href":2703,"rel":2704},"https://www.builder.io/blog/claude-md-guide",[1152],"Builder.io - How to Write a Good CLAUDE.md"," — Guida pratica con esempi",[85,2708,2709,2714],{},[69,2710,2713],{"href":2711,"rel":2712},"https://howborisusesclaudecode.com/",[1152],"Boris Cherny - How I Use Claude Code"," — Setup del creatore di Claude Code",[85,2716,2717,2722],{},[69,2718,2721],{"href":2719,"rel":2720},"https://agents.md/",[1152],"AGENTS.md - Standard Aperto"," — Lo standard Linux Foundation",[85,2724,2725,2730],{},[69,2726,2729],{"href":2727,"rel":2728},"https://github.com/josix/awesome-claude-md",[1152],"awesome-claude-md (GitHub)"," — Collezione di CLAUDE.md da progetti open source",[1218,2732,2733],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":355,"searchDepth":417,"depth":417,"links":2735},[2736,2739,2744,2751,2752,2753,2754,2758,2761,2765],{"id":1322,"depth":417,"text":1323,"children":2737},[2738],{"id":1478,"depth":441,"text":1479},{"id":1518,"depth":417,"text":1519,"children":2740},[2741,2742,2743],{"id":1531,"depth":441,"text":1532},{"id":1549,"depth":441,"text":1550},{"id":1630,"depth":441,"text":1631},{"id":1808,"depth":417,"text":1809,"children":2745},[2746,2747,2748,2749,2750],{"id":1815,"depth":441,"text":1816},{"id":1842,"depth":441,"text":1843},{"id":1877,"depth":441,"text":1878},{"id":1909,"depth":441,"text":1910},{"id":1923,"depth":441,"text":1924},{"id":1942,"depth":417,"text":1943},{"id":1986,"depth":417,"text":1987},{"id":2100,"depth":417,"text":2101},{"id":2251,"depth":417,"text":2252,"children":2755},[2756,2757],{"id":2365,"depth":441,"text":2366},{"id":2396,"depth":441,"text":2397},{"id":2424,"depth":417,"text":2425,"children":2759},[2760],{"id":2454,"depth":441,"text":2455},{"id":2489,"depth":417,"text":2490,"children":2762},[2763,2764],{"id":2493,"depth":441,"text":2494},{"id":2529,"depth":441,"text":2530},{"id":2580,"depth":417,"text":2581},"Produttività","CLAUDE.md determina se Claude Code lavora bene sul tuo progetto. Gerarchia, cosa scrivere, cosa evitare e confronto con .cursorrules e AGENTS.md.","Intermedio","/images/guides/come-scrivere-claude-md.webp",{},"/guides/come-scrivere-claude-md-che-funziona","2026-02-17",{"title":1292,"description":2767},"guides/come-scrivere-claude-md-che-funziona",[1287,1304,1285,2766,1268],"3un5QliVt32rfmi0cFljnXlGxT7EQLOZQuw4fAoO_6Y",{"id":2778,"title":2779,"author":2780,"body":2781,"category":2766,"contentType":1269,"description":4520,"difficulty":2768,"extension":1272,"featured":444,"icon":1269,"image":4521,"meta":4522,"navigation":444,"path":4523,"publishedAt":4524,"readingTime":1725,"seo":4525,"stem":4526,"steps":1269,"tags":4527,"youtubeId":1269,"__hash__":4530},"guides/guides/context-engineering-pratico-rules-mcp-workflow.md","Context Engineering Pratico: Rules, MCP, Workflow Completo",{"name":7,"initials":8},{"type":10,"value":2782,"toc":4473},[2783,2786,2793,2796,2803,2805,2809,2812,2818,2825,2828,2830,2834,2837,2841,2955,2958,2967,2970,2974,2980,2983,2988,3073,3078,3113,3117,3120,3214,3217,3221,3224,3247,3250,3252,3256,3263,3267,3274,3285,3289,3300,3303,3307,3313,3318,3329,3334,3339,3343,3350,3467,3473,3477,3480,3563,3566,3568,3572,3578,3582,3585,3591,3595,3598,3612,3615,3619,3622,3628,3631,3637,3640,3644,3647,3673,3677,3680,3686,3689,3695,3702,3704,3708,3711,3715,3720,3723,3728,3731,3736,3746,3781,3790,3795,3798,3802,3808,3812,3815,3821,3828,3830,3834,3837,3841,3848,3936,3939,3943,3946,3952,3955,3959,3965,3968,3972,3978,3984,3986,3992,3995,3999,4006,4012,4015,4019,4022,4028,4031,4035,4038,4060,4066,4068,4072,4076,4082,4088,4094,4098,4103,4108,4113,4117,4122,4127,4132,4136,4141,4146,4151,4155,4160,4165,4170,4172,4176,4179,4281,4284,4287,4289,4293,4299,4380,4383,4386,4393,4395,4400,4470],[13,2784,2779],{"id":2785},"context-engineering-pratico-rules-mcp-workflow-completo",[17,2787,2788,2789,2792],{},"Nell'articolo su ",[69,2790,2791],{"href":71},"cosa vede e non vede l'AI"," abbiamo smontato il motore. Abbiamo visto come funziona la context window, perché si degrada, cosa succede quando si riempie.",[17,2794,2795],{},"Oggi lo rimettiamo in moto. Questa è la guida operativa: come strutturare i file di regole, configurare MCP server, gestire le sessioni e costruire un workflow quotidiano che ti fa ottenere risultati consistenti.",[17,2797,2798,2799,2802],{},"Non teoria — ",[24,2800,2801],{},"azioni",". Template pronti, pattern testati, errori da evitare.",[35,2804],{},[38,2806,2808],{"id":2807},"il-principio-meno-è-meglio-se-è-giusto","Il Principio: Meno È Meglio, Se È Giusto",[17,2810,2811],{},"Prima di entrare nel pratico, un concetto che cambia tutto.",[17,2813,2814,2815,688],{},"Il tuo agente AI ha una \"RAM\" limitata — la context window. Ogni token che ci metti è un token in meno per ragionare e rispondere. Questo significa che ",[24,2816,2817],{},"il context engineering non è aggiungere informazione — è selezionare quella giusta",[17,2819,2820,2821,2824],{},"Anthropic lo dice esplicitamente nella documentazione di Claude Code: i modelli frontier riescono a seguire circa ",[24,2822,2823],{},"150-200 istruzioni"," con ragionevole consistenza. Oltre, la qualità degrada.",[17,2826,2827],{},"Quindi la domanda non è \"cosa posso aggiungere?\". È \"cosa posso togliere senza perdere valore?\"",[35,2829],{},[38,2831,2833],{"id":2832},"livello-1-i-file-di-regole","Livello 1: I File di Regole",[17,2835,2836],{},"Ogni tool di AI coding ha il suo sistema di istruzioni persistenti. I nomi cambiano, il concetto è lo stesso: un file che viene iniettato nel contesto a ogni sessione.",[58,2838,2840],{"id":2839},"la-mappa-completa","La mappa completa",[244,2842,2843,2858],{},[247,2844,2845],{},[250,2846,2847,2849,2852,2855],{},[253,2848,2264],{},[253,2850,2851],{},"File principale",[253,2853,2854],{},"File aggiuntivi",[253,2856,2857],{},"Gerarchia",[260,2859,2860,2882,2901,2921,2939],{},[250,2861,2862,2866,2870,2879],{},[265,2863,2864],{},[24,2865,1287],{},[265,2867,2868,1395],{},[353,2869,1304],{},[265,2871,2872,2874,2875,2078,2877],{},[353,2873,1376],{}," (globale), ",[353,2876,1413],{},[353,2878,1470],{},[265,2880,2881],{},"6 livelli, dal globale al locale",[250,2883,2884,2888,2892,2898],{},[265,2885,2886],{},[24,2887,2294],{},[265,2889,2890,1395],{},[353,2891,2302],{},[265,2893,2894,2897],{},[353,2895,2896],{},".cursor/rules/*.mdc"," con metadata",[265,2899,2900],{},"Flat + rules modulari",[250,2902,2903,2908,2912,2918],{},[265,2904,2905],{},[24,2906,2907],{},"Codex CLI",[265,2909,2910,1395],{},[353,2911,2346],{},[265,2913,2914,2917],{},[353,2915,2916],{},"codex.toml"," per config",[265,2919,2920],{},"Gerarchico per cartella",[250,2922,2923,2927,2931,2937],{},[265,2924,2925],{},[24,2926,2327],{},[265,2928,2929,1395],{},[353,2930,2332],{},[265,2932,2933,2936],{},[353,2934,2935],{},"~/.gemini/GEMINI.md"," (globale), sotto-cartelle",[265,2938,2920],{},[250,2940,2941,2945,2949,2952],{},[265,2942,2943],{},[24,2944,2313],{},[265,2946,2947],{},[353,2948,2318],{},[265,2950,2951],{},"N/A",[265,2953,2954],{},"Singolo livello",[58,2956,2957],{"id":2365},"AGENTS.md: Lo standard aperto",[17,2959,2960,2962,2963,2966],{},[353,2961,2346],{}," è nato come convenzione proposta da OpenAI per Codex CLI, ma sta diventando uno ",[24,2964,2965],{},"standard de facto"," riconosciuto da più tool. L'idea è semplice: un singolo formato di istruzioni leggibile da qualsiasi agente AI.",[17,2968,2969],{},"Se il tuo team usa tool diversi, puoi mantenere sia il file specifico (CLAUDE.md, .cursorrules) sia un AGENTS.md con le istruzioni comuni. Non è duplicazione — è interoperabilità.",[58,2971,2973],{"id":2972},"cosa-mettere-nei-rules-file","Cosa mettere nei rules file",[17,2975,2976,2977,688],{},"Regola d'oro: ",[24,2978,2979],{},"scrivi solo ciò che l'agente non può dedurre dal codice",[17,2981,2982],{},"L'AI è un in-context learner — se il tuo codice segue pattern consistenti, l'agente li replicherà senza che tu glielo dica. Non serve scrivere \"usa TypeScript\" se ogni file del progetto è .ts.",[17,2984,2985],{},[24,2986,2987],{},"Sì, metti questo:",[346,2989,2991],{"className":1637,"code":2990,"language":1639,"meta":355,"style":355},"## Stack\n- Nuxt 4.3 + @nuxt/content v3 + TailwindCSS\n- Dev server: porta 3002\n- Deploy: `python deploy.py`\n\n## Comandi\n- `npm run dev -- --port 3002` (dev)\n- `npm run generate` (build statico)\n\n## Convenzioni non ovvie\n- I file che iniziano con `_` sono draft — filtrarli nelle query\n- Content API: `queryCollection('nome').all()` (v3, NON v2)\n- Immagini: 1536x1024 webp, in `public/images/{sezione}/`\n\n## Errori noti\n- NON usare `getCachedData: () => null` in useAsyncData (causa fetch vuoti)\n- Path: usa `item.path` NON `item._path` (v3 breaking change)\n",[353,2992,2993,2997,3002,3007,3012,3016,3020,3025,3030,3034,3039,3044,3049,3054,3058,3063,3068],{"__ignoreMap":355},[407,2994,2995],{"class":409,"line":410},[407,2996,1664],{},[407,2998,2999],{"class":409,"line":417},[407,3000,3001],{},"- Nuxt 4.3 + @nuxt/content v3 + TailwindCSS\n",[407,3003,3004],{"class":409,"line":441},[407,3005,3006],{},"- Dev server: porta 3002\n",[407,3008,3009],{"class":409,"line":448},[407,3010,3011],{},"- Deploy: `python deploy.py`\n",[407,3013,3014],{"class":409,"line":454},[407,3015,445],{"emptyLinePlaceholder":444},[407,3017,3018],{"class":409,"line":1667},[407,3019,1693],{},[407,3021,3022],{"class":409,"line":1673},[407,3023,3024],{},"- `npm run dev -- --port 3002` (dev)\n",[407,3026,3027],{"class":409,"line":1679},[407,3028,3029],{},"- `npm run generate` (build statico)\n",[407,3031,3032],{"class":409,"line":1685},[407,3033,445],{"emptyLinePlaceholder":444},[407,3035,3036],{"class":409,"line":1690},[407,3037,3038],{},"## Convenzioni non ovvie\n",[407,3040,3041],{"class":409,"line":1696},[407,3042,3043],{},"- I file che iniziano con `_` sono draft — filtrarli nelle query\n",[407,3045,3046],{"class":409,"line":1702},[407,3047,3048],{},"- Content API: `queryCollection('nome').all()` (v3, NON v2)\n",[407,3050,3051],{"class":409,"line":1708},[407,3052,3053],{},"- Immagini: 1536x1024 webp, in `public/images/{sezione}/`\n",[407,3055,3056],{"class":409,"line":1714},[407,3057,445],{"emptyLinePlaceholder":444},[407,3059,3060],{"class":409,"line":1719},[407,3061,3062],{},"## Errori noti\n",[407,3064,3065],{"class":409,"line":1725},[407,3066,3067],{},"- NON usare `getCachedData: () => null` in useAsyncData (causa fetch vuoti)\n",[407,3069,3070],{"class":409,"line":1278},[407,3071,3072],{},"- Path: usa `item.path` NON `item._path` (v3 breaking change)\n",[17,3074,3075],{},[24,3076,3077],{},"No, non mettere questo:",[346,3079,3081],{"className":1637,"code":3080,"language":1639,"meta":355,"style":355},"## ❌ Cose che l'AI sa già\n- \"Scrivi codice pulito e leggibile\" → sa già cos'è\n- \"Usa le best practice\" → troppo generico, zero valore\n- \"Gestisci gli errori\" → lo fa comunque\n- \"Segui i principi SOLID\" → non aggiunge nulla di specifico al progetto\n- L'intero README del progetto copia-incollato → spreco di token\n",[353,3082,3083,3088,3093,3098,3103,3108],{"__ignoreMap":355},[407,3084,3085],{"class":409,"line":410},[407,3086,3087],{},"## ❌ Cose che l'AI sa già\n",[407,3089,3090],{"class":409,"line":417},[407,3091,3092],{},"- \"Scrivi codice pulito e leggibile\" → sa già cos'è\n",[407,3094,3095],{"class":409,"line":441},[407,3096,3097],{},"- \"Usa le best practice\" → troppo generico, zero valore\n",[407,3099,3100],{"class":409,"line":448},[407,3101,3102],{},"- \"Gestisci gli errori\" → lo fa comunque\n",[407,3104,3105],{"class":409,"line":454},[407,3106,3107],{},"- \"Segui i principi SOLID\" → non aggiunge nulla di specifico al progetto\n",[407,3109,3110],{"class":409,"line":1667},[407,3111,3112],{},"- L'intero README del progetto copia-incollato → spreco di token\n",[58,3114,3116],{"id":3115},"la-struttura-che-funziona","La struttura che funziona",[17,3118,3119],{},"Dopo mesi di iterazione, questa è la struttura che produce i risultati migliori:",[346,3121,3123],{"className":1637,"code":3122,"language":1639,"meta":355,"style":355},"# CLAUDE.md\n\n## Contesto progetto (2-3 righe)\nCos'è, per chi, una riga sullo stack.\n\n## Comandi (lista secca)\nDev, build, test, deploy. Solo i comandi.\n\n## Architettura (solo le parti non ovvie)\nStruttura cartelle SE non è standard.\nPattern custom che l'AI non può dedurre.\n\n## Convenzioni critiche (quelle che causano bug)\nLe cose che SE l'AI non le sa, rompe qualcosa.\nOgni regola qui ha una storia di debug dietro.\n\n## Errori noti (sezione vivente)\nBug incontrati e come risolverli.\nQuesta sezione cresce col tempo.\n",[353,3124,3125,3129,3133,3138,3143,3147,3152,3157,3161,3166,3171,3176,3180,3185,3190,3195,3199,3204,3209],{"__ignoreMap":355},[407,3126,3127],{"class":409,"line":410},[407,3128,2388],{},[407,3130,3131],{"class":409,"line":417},[407,3132,445],{"emptyLinePlaceholder":444},[407,3134,3135],{"class":409,"line":441},[407,3136,3137],{},"## Contesto progetto (2-3 righe)\n",[407,3139,3140],{"class":409,"line":448},[407,3141,3142],{},"Cos'è, per chi, una riga sullo stack.\n",[407,3144,3145],{"class":409,"line":454},[407,3146,445],{"emptyLinePlaceholder":444},[407,3148,3149],{"class":409,"line":1667},[407,3150,3151],{},"## Comandi (lista secca)\n",[407,3153,3154],{"class":409,"line":1673},[407,3155,3156],{},"Dev, build, test, deploy. Solo i comandi.\n",[407,3158,3159],{"class":409,"line":1679},[407,3160,445],{"emptyLinePlaceholder":444},[407,3162,3163],{"class":409,"line":1685},[407,3164,3165],{},"## Architettura (solo le parti non ovvie)\n",[407,3167,3168],{"class":409,"line":1690},[407,3169,3170],{},"Struttura cartelle SE non è standard.\n",[407,3172,3173],{"class":409,"line":1696},[407,3174,3175],{},"Pattern custom che l'AI non può dedurre.\n",[407,3177,3178],{"class":409,"line":1702},[407,3179,445],{"emptyLinePlaceholder":444},[407,3181,3182],{"class":409,"line":1708},[407,3183,3184],{},"## Convenzioni critiche (quelle che causano bug)\n",[407,3186,3187],{"class":409,"line":1714},[407,3188,3189],{},"Le cose che SE l'AI non le sa, rompe qualcosa.\n",[407,3191,3192],{"class":409,"line":1719},[407,3193,3194],{},"Ogni regola qui ha una storia di debug dietro.\n",[407,3196,3197],{"class":409,"line":1725},[407,3198,445],{"emptyLinePlaceholder":444},[407,3200,3201],{"class":409,"line":1278},[407,3202,3203],{},"## Errori noti (sezione vivente)\n",[407,3205,3206],{"class":409,"line":1736},[407,3207,3208],{},"Bug incontrati e come risolverli.\n",[407,3210,3211],{"class":409,"line":1742},[407,3212,3213],{},"Questa sezione cresce col tempo.\n",[17,3215,3216],{},"Notare cosa manca: niente saluti, niente filosofia, niente istruzioni generiche. Ogni token ha un motivo per essere lì.",[58,3218,3220],{"id":3219},"quanto-deve-essere-lungo","Quanto deve essere lungo?",[17,3222,3223],{},"Il dato di Anthropic sui 150-200 istruzioni è un buon riferimento. In pratica:",[82,3225,3226,3232,3238],{},[85,3227,3228,3231],{},[24,3229,3230],{},"Progetto piccolo",": 50-100 righe bastano",[85,3233,3234,3237],{},[24,3235,3236],{},"Progetto medio",": 100-200 righe",[85,3239,3240,3243,3244,3246],{},[24,3241,3242],{},"Monorepo aziendale",": usa la gerarchia — CLAUDE.md globale snello + ",[353,3245,1504],{}," per area",[17,3248,3249],{},"Se il tuo rules file supera le 300 righe, probabilmente stai descrivendo cose che l'AI può dedurre dal codice. Taglia.",[35,3251],{},[38,3253,3255],{"id":3254},"livello-2-mcp-il-contesto-esterno","Livello 2: MCP — Il Contesto Esterno",[17,3257,3258,3259,3262],{},"I file di regole gestiscono il contesto statico. ",[24,3260,3261],{},"MCP (Model Context Protocol)"," gestisce il contesto dinamico — tutto ciò che viene da fuori il codebase.",[58,3264,3266],{"id":3265},"cosè-mcp-in-30-secondi","Cos'è MCP in 30 secondi",[17,3268,3269,3270,3273],{},"MCP è un protocollo standard (creato da Anthropic, ora open) che permette agli agenti AI di connettersi a ",[24,3271,3272],{},"tool esterni",": database, API, browser, servizi. Invece di dire all'AI \"vai su questo sito e copia i dati\", configuri un MCP server e l'AI ci parla direttamente.",[17,3275,3276,3277,3281,3282,688],{},"Abbiamo scritto una ",[69,3278,3280],{"href":3279},"/guide/costruire-mcp-server-guida-pratica","guida completa su come costruire un MCP server",". Qui ci concentriamo sull'aspetto di context engineering: ",[24,3283,3284],{},"come configurarli senza inquinare il contesto",[58,3286,3288],{"id":3287},"il-problema-context-pollution-da-mcp","Il problema: context pollution da MCP",[17,3290,3291,3292,3295,3296,3299],{},"Ogni MCP server che connetti aggiunge ",[24,3293,3294],{},"definizioni di tool"," nel contesto. Ogni tool ha un nome, una descrizione, parametri con schema JSON. Un singolo MCP server complesso può aggiungere ",[24,3297,3298],{},"migliaia di token"," di definizioni.",[17,3301,3302],{},"Connetti 5 MCP server e hai già consumato 10-15K token prima ancora di scrivere la prima riga di codice. In una finestra da 200K sembra poco — ma ricorda il paper NoLiMa: a 32K token la maggior parte dei modelli è già sotto il 50% della baseline.",[58,3304,3306],{"id":3305},"la-regola-meno-server-più-mirati","La regola: meno server, più mirati",[17,3308,3309,3312],{},[24,3310,3311],{},"Non connettere tutti gli MCP server disponibili",". Connetti solo quelli che ti servono per il task corrente.",[17,3314,3315],{},[24,3316,3317],{},"Sì:",[82,3319,3320,3323,3326],{},[85,3321,3322],{},"Stai debuggando il frontend → connetti Playwright MCP per testare nel browser",[85,3324,3325],{},"Stai lavorando sul database → connetti il database MCP",[85,3327,3328],{},"Stai facendo deploy → connetti il server MCP per il cloud",[17,3330,3331],{},[24,3332,3333],{},"No:",[82,3335,3336],{},[85,3337,3338],{},"Connettere Playwright + Database + Sentry + GitHub + Slack + Linear tutti insieme \"perché magari servono\"",[58,3340,3342],{"id":3341},"configurazione-pratica-mcpjson","Configurazione pratica: .mcp.json",[17,3344,3345,3346,3349],{},"Per Claude Code, puoi configurare MCP server a livello di progetto con un file ",[353,3347,3348],{},".mcp.json"," nella root:",[346,3351,3353],{"className":2192,"code":3352,"language":2194,"meta":355,"style":355},"{\n  \"mcpServers\": {\n    \"playwright\": {\n      \"command\": \"npx\",\n      \"args\": [\"@anthropic/mcp-playwright\"]\n    },\n    \"postgres\": {\n      \"command\": \"npx\",\n      \"args\": [\"@anthropic/mcp-postgres\"],\n      \"env\": {\n        \"DATABASE_URL\": \"postgresql://localhost:5432/mydb\"\n      }\n    }\n  }\n}\n",[353,3354,3355,3359,3366,3373,3385,3399,3404,3411,3421,3433,3440,3450,3455,3459,3463],{"__ignoreMap":355},[407,3356,3357],{"class":409,"line":410},[407,3358,2202],{"class":2201},[407,3360,3361,3364],{"class":409,"line":417},[407,3362,3363],{"class":434},"  \"mcpServers\"",[407,3365,2210],{"class":2201},[407,3367,3368,3371],{"class":409,"line":441},[407,3369,3370],{"class":434},"    \"playwright\"",[407,3372,2210],{"class":2201},[407,3374,3375,3377,3379,3382],{"class":409,"line":448},[407,3376,2222],{"class":434},[407,3378,2225],{"class":2201},[407,3380,3381],{"class":424},"\"npx\"",[407,3383,3384],{"class":2201},",\n",[407,3386,3387,3390,3393,3396],{"class":409,"line":454},[407,3388,3389],{"class":434},"      \"args\"",[407,3391,3392],{"class":2201},": [",[407,3394,3395],{"class":424},"\"@anthropic/mcp-playwright\"",[407,3397,3398],{"class":2201},"]\n",[407,3400,3401],{"class":409,"line":1667},[407,3402,3403],{"class":2201},"    },\n",[407,3405,3406,3409],{"class":409,"line":1673},[407,3407,3408],{"class":434},"    \"postgres\"",[407,3410,2210],{"class":2201},[407,3412,3413,3415,3417,3419],{"class":409,"line":1679},[407,3414,2222],{"class":434},[407,3416,2225],{"class":2201},[407,3418,3381],{"class":424},[407,3420,3384],{"class":2201},[407,3422,3423,3425,3427,3430],{"class":409,"line":1685},[407,3424,3389],{"class":434},[407,3426,3392],{"class":2201},[407,3428,3429],{"class":424},"\"@anthropic/mcp-postgres\"",[407,3431,3432],{"class":2201},"],\n",[407,3434,3435,3438],{"class":409,"line":1690},[407,3436,3437],{"class":434},"      \"env\"",[407,3439,2210],{"class":2201},[407,3441,3442,3445,3447],{"class":409,"line":1696},[407,3443,3444],{"class":434},"        \"DATABASE_URL\"",[407,3446,2225],{"class":2201},[407,3448,3449],{"class":424},"\"postgresql://localhost:5432/mydb\"\n",[407,3451,3452],{"class":409,"line":1702},[407,3453,3454],{"class":2201},"      }\n",[407,3456,3457],{"class":409,"line":1708},[407,3458,2233],{"class":2201},[407,3460,3461],{"class":409,"line":1714},[407,3462,2238],{"class":2201},[407,3464,3465],{"class":409,"line":1719},[407,3466,2243],{"class":2201},[17,3468,3469,3470,688],{},"Questo file si committa nel repo — chiunque nel team clona il progetto e ha gli stessi MCP server configurati. È context engineering di team: ",[24,3471,3472],{},"tutti lavorano con lo stesso contesto",[58,3474,3476],{"id":3475},"mcp-server-che-vale-la-pena-avere","MCP server che vale la pena avere",[17,3478,3479],{},"Nella pratica quotidiana, questi sono quelli con il miglior rapporto valore/token:",[244,3481,3482,3495],{},[247,3483,3484],{},[250,3485,3486,3489,3492],{},[253,3487,3488],{},"MCP Server",[253,3490,3491],{},"Quando serve",[253,3493,3494],{},"Costo in token",[260,3496,3497,3510,3523,3537,3550],{},[250,3498,3499,3504,3507],{},[265,3500,3501],{},[24,3502,3503],{},"Playwright",[265,3505,3506],{},"Testing frontend, verifica visiva",[265,3508,3509],{},"Medio (~2-3K definizioni)",[250,3511,3512,3517,3520],{},[265,3513,3514],{},[24,3515,3516],{},"Filesystem",[265,3518,3519],{},"Accesso a file fuori dal progetto",[265,3521,3522],{},"Basso (~1K)",[250,3524,3525,3531,3534],{},[265,3526,3527,3530],{},[24,3528,3529],{},"Database"," (Postgres/SQLite)",[265,3532,3533],{},"Query dirette, debug dati",[265,3535,3536],{},"Medio (~2-3K)",[250,3538,3539,3544,3547],{},[265,3540,3541],{},[24,3542,3543],{},"Git",[265,3545,3546],{},"Operazioni git avanzate",[265,3548,3549],{},"Basso (~1-2K)",[250,3551,3552,3557,3560],{},[265,3553,3554],{},[24,3555,3556],{},"Sentry/Error tracking",[265,3558,3559],{},"Debug errori in produzione",[265,3561,3562],{},"Alto (~4-5K)",[17,3564,3565],{},"La colonna \"costo in token\" è il prezzo che paghi in contesto solo per avere il server connesso, anche se non lo usi. Per questo la regola è: connetti solo quello che serve adesso.",[35,3567],{},[38,3569,3571],{"id":3570},"livello-3-la-gestione-delle-sessioni","Livello 3: La Gestione delle Sessioni",[17,3573,3574,3575,688],{},"Hai i rules file. Hai gli MCP server. Ora manca il pezzo più importante: ",[24,3576,3577],{},"come lavori giorno per giorno",[58,3579,3581],{"id":3580},"il-nemico-il-context-rot","Il nemico: il Context Rot",[17,3583,3584],{},"Lo abbiamo visto nel dettaglio nell'articolo sulla context window: la qualità dell'output degrada con la lunghezza della conversazione. Non linearmente — in modo insidioso. Le prime risposte sono ottime, poi peggiorano gradualmente senza che te ne accorga.",[17,3586,3587,3588,688],{},"La soluzione è semplice nella teoria, difficile nella pratica: ",[24,3589,3590],{},"sessioni corte e focalizzate",[58,3592,3594],{"id":3593},"la-regola-dei-20-minuti","La regola dei 20 minuti",[17,3596,3597],{},"Non è un numero magico, ma è un buon riferimento. Dopo 20-30 minuti di lavoro intenso con un agente, il contesto è probabilmente saturo. A quel punto hai due opzioni:",[517,3599,3600,3606],{},[85,3601,3602,3605],{},[24,3603,3604],{},"Continuare"," — e accettare che la qualità scende",[85,3607,3608,3611],{},[24,3609,3610],{},"Nuova sessione"," — contesto pulito, istruzioni rilette, agente fresco",[17,3613,3614],{},"La scelta giusta è quasi sempre la seconda. Ma richiede disciplina, perché il cervello umano preferisce non interrompere il flusso.",[58,3616,3618],{"id":3617},"un-task-una-sessione","Un task, una sessione",[17,3620,3621],{},"Il pattern più efficace:",[346,3623,3626],{"className":3624,"code":3625,"language":351},[349],"Sessione 1: \"Implementa il componente UserCard\"\nSessione 2: \"Aggiungi i test per UserCard\"\nSessione 3: \"Integra UserCard nella pagina profilo\"\n",[353,3627,3625],{"__ignoreMap":355},[17,3629,3630],{},"Invece di:",[346,3632,3635],{"className":3633,"code":3634,"language":351},[349],"Sessione unica: \"Implementa UserCard, testala e integrala nel profilo\"\n",[353,3636,3634],{"__ignoreMap":355},[17,3638,3639],{},"Perché? Nella sessione unica, quando arrivi all'integrazione hai 50+ messaggi di contesto dall'implementazione e dai test — contesto che è solo rumore per il task di integrazione. Nella versione a sessioni separate, ogni task parte con contesto pulito.",[58,3641,3643],{"id":3642},"quando-cambiare-sessione","Quando cambiare sessione",[17,3645,3646],{},"Cambia sessione quando:",[82,3648,3649,3655,3661,3667],{},[85,3650,3651,3654],{},[24,3652,3653],{},"Cambi argomento"," — da frontend a backend, da feature a bug fix",[85,3656,3657,3660],{},[24,3658,3659],{},"L'agente inizia a \"dimenticare\""," — ripete errori già corretti, ignora convenzioni",[85,3662,3663,3666],{},[24,3664,3665],{},"Hai completato un task"," — anche se il prossimo è correlato",[85,3668,3669,3672],{},[24,3670,3671],{},"Senti che le risposte peggiorano"," — fidati dell'intuito, di solito hai ragione",[58,3674,3676],{"id":3675},"checkpoint-la-memoria-fuori-dalla-finestra","Checkpoint: la memoria fuori dalla finestra",[17,3678,3679],{},"Prima di chiudere una sessione, fai scrivere all'agente un checkpoint:",[346,3681,3684],{"className":3682,"code":3683,"language":351},[349],"\"Scrivi un riassunto di quello che abbiamo fatto e delle decisioni prese\nin un commento in cima al file o in un file progress.md\"\n",[353,3685,3683],{"__ignoreMap":355},[17,3687,3688],{},"Nella sessione successiva:",[346,3690,3693],{"className":3691,"code":3692,"language":351},[349],"\"Leggi progress.md e continua da dove avevamo lasciato\"\n",[353,3694,3692],{"__ignoreMap":355},[17,3696,3697,3698,3701],{},"È il pattern usato da Anthropic stessa per agenti di lunga durata. Manus (l'agente di Monica.im) usa un ",[353,3699,3700],{},"todo.md"," che riscrive continuamente. Non è elegante, ma funziona meglio di qualsiasi meccanismo automatico.",[35,3703],{},[38,3705,3707],{"id":3706},"livello-4-il-workflow-completo","Livello 4: Il Workflow Completo",[17,3709,3710],{},"Mettiamo tutto insieme. Ecco il workflow quotidiano che uso e che produce risultati consistenti.",[58,3712,3714],{"id":3713},"setup-iniziale-del-progetto-una-volta","Setup iniziale del progetto (una volta)",[17,3716,3717],{},[24,3718,3719],{},"1. Crea il rules file principale",[17,3721,3722],{},"Scrivi il CLAUDE.md (o equivalente) seguendo la struttura descritta sopra. Parti snello — 50-80 righe — e fallo crescere solo quando incontri problemi reali.",[17,3724,3725],{},[24,3726,3727],{},"2. Configura gli MCP server essenziali",[17,3729,3730],{},"Solo quelli che usi quotidianamente. Per un progetto web tipico: Playwright per il testing visivo e basta. Aggiungi altri solo quando ne hai bisogno.",[17,3732,3733],{},[24,3734,3735],{},"3. Crea i comandi custom",[17,3737,3738,3739,3742,3743,1894],{},"Claude Code supporta comandi custom nella cartella ",[353,3740,3741],{},".claude/commands/",". Sono template Markdown che puoi invocare con ",[353,3744,3745],{},"/nome-comando",[346,3747,3749],{"className":1637,"code":3748,"language":1639,"meta":355,"style":355},"\u003C!-- .claude/commands/review.md -->\nAnalizza il file $ARGUMENTS per:\n1. Bug potenziali\n2. Violazioni delle convenzioni del progetto\n3. Performance issue\nSuggerisci fix concreti, non generici.\n",[353,3750,3751,3756,3761,3766,3771,3776],{"__ignoreMap":355},[407,3752,3753],{"class":409,"line":410},[407,3754,3755],{},"\u003C!-- .claude/commands/review.md -->\n",[407,3757,3758],{"class":409,"line":417},[407,3759,3760],{},"Analizza il file $ARGUMENTS per:\n",[407,3762,3763],{"class":409,"line":441},[407,3764,3765],{},"1. Bug potenziali\n",[407,3767,3768],{"class":409,"line":448},[407,3769,3770],{},"2. Violazioni delle convenzioni del progetto\n",[407,3772,3773],{"class":409,"line":454},[407,3774,3775],{},"3. Performance issue\n",[407,3777,3778],{"class":409,"line":1667},[407,3779,3780],{},"Suggerisci fix concreti, non generici.\n",[17,3782,3783,3784,3786,3787,688],{},"Stesso concetto per Cursor (",[353,3785,2299],{},") e Codex CLI (prompt template). L'idea è: ",[24,3788,3789],{},"le istruzioni che ripeti spesso diventano comandi",[17,3791,3792],{},[24,3793,3794],{},"4. Sezione \"Errori Noti\" nel rules file",[17,3796,3797],{},"Inizia vuota. Ogni volta che incontri un bug causato dall'AI che non conosceva una convenzione del progetto, aggiungilo. Dopo un mese avrai la sezione più preziosa di tutto il file.",[58,3799,3801],{"id":3800},"workflow-quotidiano","Workflow quotidiano",[346,3803,3806],{"className":3804,"code":3805,"language":351},[349],"1. Apri terminale / IDE\n2. Identifica il task (specifico, scope contenuto)\n3. Nuova sessione con l'agente\n4. Se serve contesto di sessioni precedenti → \"leggi progress.md\"\n5. Lavora sul task (max 20-30 min o fino a completamento)\n6. Se il task è complesso → checkpoint intermedi\n7. Task completato → verifica (test, browser, review)\n8. Se c'è un task correlato → nuova sessione\n9. A fine giornata → aggiorna rules file se hai scoperto nuove convenzioni\n",[353,3807,3805],{"__ignoreMap":355},[58,3809,3811],{"id":3810},"il-ciclo-di-miglioramento","Il ciclo di miglioramento",[17,3813,3814],{},"Il rules file non è statico. Evolve col progetto:",[346,3816,3819],{"className":3817,"code":3818,"language":351},[349],"Settimana 1: CLAUDE.md base — stack, comandi, struttura\nSettimana 2: Aggiungi \"Errori Noti\" dopo i primi bug\nSettimana 3: Aggiungi convenzioni che l'AI viola ripetutamente\nSettimana 4: Togli le regole che l'AI segue già da sola (le ha imparate dal codice)\n",[353,3820,3818],{"__ignoreMap":355},[17,3822,3823,3824,3827],{},"Anthropic suggerisce di trattare il CLAUDE.md come un prompt da ottimizzare: ",[24,3825,3826],{},"periodicamente, passalo attraverso un prompt improver"," o semplicemente rileggilo chiedendoti \"questo serve ancora?\".",[35,3829],{},[38,3831,3833],{"id":3832},"i-7-pattern-che-funzionano","I 7 Pattern che Funzionano",[17,3835,3836],{},"Dopo centinaia di sessioni, questi sono i pattern operativi che producono la differenza maggiore.",[58,3838,3840],{"id":3839},"_1-dai-tipi-non-implementazioni","1. Dai tipi, non implementazioni",[17,3842,3843,3844,3847],{},"In linguaggi tipizzati, fornire le ",[24,3845,3846],{},"interfacce e i tipi"," è enormemente più efficace che fornire l'implementazione:",[346,3849,3853],{"className":3850,"code":3851,"language":3852,"meta":355,"style":355},"language-typescript shiki shiki-themes github-light github-dark","// ✅ 15 token, massima informazione strutturale\ninterface User {\n  id: string\n  email: string\n  role: 'admin' | 'user'\n  createdAt: Date\n}\n\n// ❌ 200+ token per comunicare la stessa informazione\n// (più l'implementazione di validazione, getter, setter...)\n","typescript",[353,3854,3855,3860,3872,3883,3892,3908,3918,3922,3926,3931],{"__ignoreMap":355},[407,3856,3857],{"class":409,"line":410},[407,3858,3859],{"class":413},"// ✅ 15 token, massima informazione strutturale\n",[407,3861,3862,3866,3869],{"class":409,"line":417},[407,3863,3865],{"class":3864},"szBVR","interface",[407,3867,3868],{"class":420}," User",[407,3870,3871],{"class":2201}," {\n",[407,3873,3874,3878,3880],{"class":409,"line":441},[407,3875,3877],{"class":3876},"s4XuR","  id",[407,3879,1894],{"class":3864},[407,3881,3882],{"class":434}," string\n",[407,3884,3885,3888,3890],{"class":409,"line":448},[407,3886,3887],{"class":3876},"  email",[407,3889,1894],{"class":3864},[407,3891,3882],{"class":434},[407,3893,3894,3897,3899,3902,3905],{"class":409,"line":454},[407,3895,3896],{"class":3876},"  role",[407,3898,1894],{"class":3864},[407,3900,3901],{"class":424}," 'admin'",[407,3903,3904],{"class":3864}," |",[407,3906,3907],{"class":424}," 'user'\n",[407,3909,3910,3913,3915],{"class":409,"line":1667},[407,3911,3912],{"class":3876},"  createdAt",[407,3914,1894],{"class":3864},[407,3916,3917],{"class":420}," Date\n",[407,3919,3920],{"class":409,"line":1673},[407,3921,2243],{"class":2201},[407,3923,3924],{"class":409,"line":1679},[407,3925,445],{"emptyLinePlaceholder":444},[407,3927,3928],{"class":409,"line":1685},[407,3929,3930],{"class":413},"// ❌ 200+ token per comunicare la stessa informazione\n",[407,3932,3933],{"class":409,"line":1690},[407,3934,3935],{"class":413},"// (più l'implementazione di validazione, getter, setter...)\n",[17,3937,3938],{},"Un'interfaccia TypeScript di 20 righe comunica la stessa informazione strutturale di 300 righe di implementazione — usando un quindicesimo dei token.",[58,3940,3942],{"id":3941},"_2-esempio-mirato-file-intero","2. Esempio mirato > file intero",[17,3944,3945],{},"Quando vuoi che l'AI replichi uno stile:",[346,3947,3950],{"className":3948,"code":3949,"language":351},[349],"✅ \"Segui questo pattern per i composable:\n    const { data } = await useAsyncData('key', () => queryCollection('articles').all())\n    Filtra i draft con: items.filter(i => !i.path.split('/').pop()?.startsWith('_'))\"\n\n❌ \"Leggi il file pages/articoli/index.vue e fai uguale\"\n",[353,3951,3949],{"__ignoreMap":355},[17,3953,3954],{},"30 token mirati battono 300 righe di contesto. L'AI non ha bisogno dell'intero file per capire il pattern — ha bisogno dell'essenza del pattern.",[58,3956,3958],{"id":3957},"_3-specifiche-esempi-generici","3. Specifiche > esempi generici",[346,3960,3963],{"className":3961,"code":3962,"language":351},[349],"✅ \"Crea un endpoint POST /api/users con validazione Zod:\n    - email: z.string().email()\n    - name: z.string().min(2).max(50)\n    - role: z.enum(['admin', 'user']).default('user')\n    Ritorna 201 con l'utente creato, 400 con gli errori Zod.\"\n\n❌ \"Crea un endpoint per gli utenti, tipo quello che abbiamo per i prodotti\"\n",[353,3964,3962],{"__ignoreMap":355},[17,3966,3967],{},"La prima versione è 100% eseguibile senza ambiguità. La seconda richiede che l'AI legga l'endpoint prodotti (altri token consumati) e faccia assunzioni su cosa \"tipo\" significhi.",[58,3969,3971],{"id":3970},"_4-contesto-al-momento-giusto","4. Contesto al momento giusto",[17,3973,3974,3975,1894],{},"Non caricare tutto all'inizio. Fornisci contesto ",[24,3976,3977],{},"quando serve",[346,3979,3982],{"className":3980,"code":3981,"language":351},[349],"Messaggio 1: \"Implementa il componente UserCard con nome, email e avatar\"\n[L'AI implementa]\n\nMessaggio 2: \"Ora aggiungi il badge del ruolo. I ruoli possibili sono:\nadmin (badge rosso), moderator (badge giallo), user (badge grigio)\"\n[L'AI aggiunge]\n",[353,3983,3981],{"__ignoreMap":355},[17,3985,3630],{},[346,3987,3990],{"className":3988,"code":3989,"language":351},[349],"Messaggio 1: \"Implementa UserCard con nome, email, avatar, badge ruolo\n(admin=rosso, moderator=giallo, user=grigio), menu dropdown con azioni\n(edit, delete, ban), tooltip sul nome, skeleton loading, responsive\ncon breakpoint a 768px, dark mode...\"\n",[353,3991,3989],{"__ignoreMap":355},[17,3993,3994],{},"Il primo approccio mantiene il contesto pulito a ogni step. Il secondo affoga l'AI in specifiche che interferiscono tra loro.",[58,3996,3998],{"id":3997},"_5-ridondanza-mirata-nellultimo-messaggio","5. Ridondanza mirata nell'ultimo messaggio",[17,4000,4001,4002,4005],{},"Il tuo messaggio più recente ha il peso maggiore nella risposta dell'AI. Se un'informazione è critica, ",[24,4003,4004],{},"ripetila nell'ultimo messaggio"," anche se l'hai già detta:",[346,4007,4010],{"className":4008,"code":4009,"language":351},[349],"\"Implementa il sorting per la tabella utenti.\nIMPORTANTE: usa queryCollection v3 syntax, NON queryContent (v2).\"\n",[353,4011,4009],{"__ignoreMap":355},[17,4013,4014],{},"Anche se è nel CLAUDE.md, anche se l'hai detto 10 messaggi fa. Dopo 15+ messaggi, il contesto iniziale è nella \"zona morta\" (lost in the middle). La ridondanza nell'ultimo messaggio è l'antidoto.",[58,4016,4018],{"id":4017},"_6-sessioni-separate-per-task-diversi","6. Sessioni separate per task diversi",[17,4020,4021],{},"Questo è il pattern che nessuno vuole seguire e che fa la differenza maggiore:",[346,4023,4026],{"className":4024,"code":4025,"language":351},[349],"❌ Sessione unica di 2 ore:\n   \"Fix il bug del login\" → \"Ora aggiungi la registrazione\" →\n   \"Refactora il middleware auth\" → \"Scrivi i test\"\n\n✅ Quattro sessioni da 30 minuti:\n   Sessione 1: \"Fix il bug del login\"\n   Sessione 2: \"Aggiungi la registrazione\"\n   Sessione 3: \"Refactora il middleware auth\"\n   Sessione 4: \"Scrivi i test per auth\"\n",[353,4027,4025],{"__ignoreMap":355},[17,4029,4030],{},"Nella versione a sessione unica, quando scrivi i test hai 90 minuti di contesto accumulato — inclusi tutti gli errori, i tentativi falliti, i file letti e scartati del debug. Nella versione a sessioni separate, ogni task parte fresco.",[58,4032,4034],{"id":4033},"_7-il-git-come-checkpoint-naturale","7. Il git come checkpoint naturale",[17,4036,4037],{},"Dopo ogni task completato, committa. Il commit è il checkpoint perfetto:",[82,4039,4040,4043,4046,4049],{},[85,4041,4042],{},"Cristallizza le decisioni nel codice (non nella context window)",[85,4044,4045],{},"Fornisce un messaggio che descrive cosa è stato fatto",[85,4047,4048],{},"Permette di tornare indietro se il prossimo task rompe qualcosa",[85,4050,4051,4052,4055,4056,4059],{},"Nella sessione successiva, ",[353,4053,4054],{},"git log"," e ",[353,4057,4058],{},"git diff"," danno all'AI contesto preciso",[346,4061,4064],{"className":4062,"code":4063,"language":351},[349],"\"Committa le modifiche con un messaggio che descriva cosa abbiamo fatto\"\n[Nuova sessione]\n\"Guarda gli ultimi 3 commit per capire il contesto e continua con...\"\n",[353,4065,4063],{"__ignoreMap":355},[35,4067],{},[38,4069,4071],{"id":4070},"errori-comuni-e-come-evitarli","Errori Comuni e Come Evitarli",[58,4073,4075],{"id":4074},"_1-il-rules-file-enciclopedico","1. Il rules file enciclopedico",[17,4077,4078,4081],{},[24,4079,4080],{},"Errore",": CLAUDE.md di 500+ righe con tutto lo scibile del progetto.",[17,4083,4084,4087],{},[24,4085,4086],{},"Problema",": oltre 200 istruzioni la qualità degrada. Le regole importanti si perdono nel rumore.",[17,4089,4090,4093],{},[24,4091,4092],{},"Fix",": taglia tutto ciò che l'AI può dedurre dal codice. Se dopo aver tolto una regola l'AI continua a comportarsi correttamente, quella regola non serviva.",[58,4095,4097],{"id":4096},"_2-leggi-tutto-il-progetto","2. \"Leggi tutto il progetto\"",[17,4099,4100,4102],{},[24,4101,4080],{},": iniziare la sessione con \"leggi tutti i file nella cartella src per capire il progetto\".",[17,4104,4105,4107],{},[24,4106,4086],{},": 15 file letti = 15 file nel contesto = contesto saturo prima di aver fatto qualsiasi cosa.",[17,4109,4110,4112],{},[24,4111,4092],{},": lascia che l'AI navighi on-demand. Se sa cosa deve fare (grazie al rules file), sa anche cosa leggere.",[58,4114,4116],{"id":4115},"_3-mcp-server-a-pioggia","3. MCP server a pioggia",[17,4118,4119,4121],{},[24,4120,4080],{},": connettere 8 MCP server \"perché magari servono\".",[17,4123,4124,4126],{},[24,4125,4086],{},": migliaia di token di definizioni tool che non userai, che sottraggono spazio al contesto utile.",[17,4128,4129,4131],{},[24,4130,4092],{},": connetti solo quello che serve per il task corrente. Puoi sempre aggiungerne uno a metà sessione se ne hai bisogno.",[58,4133,4135],{"id":4134},"_4-la-sessione-infinita","4. La sessione infinita",[17,4137,4138,4140],{},[24,4139,4080],{},": lavorare 3 ore sulla stessa sessione cambiando topic.",[17,4142,4143,4145],{},[24,4144,4086],{},": Context Rot — la qualità degrada cumulativamente senza che te ne accorga.",[17,4147,4148,4150],{},[24,4149,4092],{},": sessioni corte e focalizzate. Un task, una sessione. Chiudi e riapri.",[58,4152,4154],{"id":4153},"_5-non-aggiornare-mai-il-rules-file","5. Non aggiornare mai il rules file",[17,4156,4157,4159],{},[24,4158,4080],{},": scrivere il CLAUDE.md una volta e non toccarlo più.",[17,4161,4162,4164],{},[24,4163,4086],{},": il progetto evolve, le convenzioni cambiano, l'AI continua a seguire regole obsolete.",[17,4166,4167,4169],{},[24,4168,4092],{},": il rules file è un documento vivente. Aggiornalo quando incontri nuovi pattern o quando regole vecchie non servono più.",[35,4171],{},[38,4173,4175],{"id":4174},"il-template-inizia-da-qui","Il Template: Inizia da Qui",[17,4177,4178],{},"Se vuoi partire subito, ecco un template minimale che funziona per la maggior parte dei progetti:",[346,4180,4182],{"className":1637,"code":4181,"language":1639,"meta":355,"style":355},"# CLAUDE.md\n\n## Progetto\n[Nome] - [cosa fa in una riga]. [Stack principale].\n\n## Comandi\n- Dev: `[comando dev]`\n- Build: `[comando build]`\n- Test: `[comando test]`\n- Deploy: `[comando deploy]`\n\n## Struttura (solo parti non standard)\n[Elenca solo le cartelle/file la cui organizzazione NON è ovvia]\n\n## Convenzioni critiche\n- [Cosa che se l'AI non sa, rompe qualcosa]\n- [Altra cosa che causa bug se ignorata]\n- [Pattern specifico del progetto]\n\n## Errori noti\n[Inizia vuoto. Aggiungi quando li incontri]\n",[353,4183,4184,4188,4192,4197,4202,4206,4210,4215,4220,4225,4230,4234,4239,4244,4248,4253,4258,4263,4268,4272,4276],{"__ignoreMap":355},[407,4185,4186],{"class":409,"line":410},[407,4187,2388],{},[407,4189,4190],{"class":409,"line":417},[407,4191,445],{"emptyLinePlaceholder":444},[407,4193,4194],{"class":409,"line":441},[407,4195,4196],{},"## Progetto\n",[407,4198,4199],{"class":409,"line":448},[407,4200,4201],{},"[Nome] - [cosa fa in una riga]. [Stack principale].\n",[407,4203,4204],{"class":409,"line":454},[407,4205,445],{"emptyLinePlaceholder":444},[407,4207,4208],{"class":409,"line":1667},[407,4209,1693],{},[407,4211,4212],{"class":409,"line":1673},[407,4213,4214],{},"- Dev: `[comando dev]`\n",[407,4216,4217],{"class":409,"line":1679},[407,4218,4219],{},"- Build: `[comando build]`\n",[407,4221,4222],{"class":409,"line":1685},[407,4223,4224],{},"- Test: `[comando test]`\n",[407,4226,4227],{"class":409,"line":1690},[407,4228,4229],{},"- Deploy: `[comando deploy]`\n",[407,4231,4232],{"class":409,"line":1696},[407,4233,445],{"emptyLinePlaceholder":444},[407,4235,4236],{"class":409,"line":1702},[407,4237,4238],{},"## Struttura (solo parti non standard)\n",[407,4240,4241],{"class":409,"line":1708},[407,4242,4243],{},"[Elenca solo le cartelle/file la cui organizzazione NON è ovvia]\n",[407,4245,4246],{"class":409,"line":1714},[407,4247,445],{"emptyLinePlaceholder":444},[407,4249,4250],{"class":409,"line":1719},[407,4251,4252],{},"## Convenzioni critiche\n",[407,4254,4255],{"class":409,"line":1725},[407,4256,4257],{},"- [Cosa che se l'AI non sa, rompe qualcosa]\n",[407,4259,4260],{"class":409,"line":1278},[407,4261,4262],{},"- [Altra cosa che causa bug se ignorata]\n",[407,4264,4265],{"class":409,"line":1736},[407,4266,4267],{},"- [Pattern specifico del progetto]\n",[407,4269,4270],{"class":409,"line":1742},[407,4271,445],{"emptyLinePlaceholder":444},[407,4273,4274],{"class":409,"line":1748},[407,4275,3062],{},[407,4277,4278],{"class":409,"line":1753},[407,4279,4280],{},"[Inizia vuoto. Aggiungi quando li incontri]\n",[17,4282,4283],{},"Sono ~20 righe. Meno di 500 token. Lascia il 99.7% della finestra per il lavoro vero.",[17,4285,4286],{},"Poi cresci da qui — ma solo quando hai un motivo concreto per aggiungere qualcosa.",[35,4288],{},[38,4290,4292],{"id":4291},"il-quadro-completo","Il Quadro Completo",[17,4294,4295,4296,1894],{},"Il context engineering non è un singolo file o una singola tecnica. È un ",[24,4297,4298],{},"sistema a 4 livelli",[244,4300,4301,4316],{},[247,4302,4303],{},[250,4304,4305,4307,4310,4313],{},[253,4306,1335],{},[253,4308,4309],{},"Cosa",[253,4311,4312],{},"Quando si configura",[253,4314,4315],{},"Frequenza di aggiornamento",[260,4317,4318,4334,4349,4364],{},[250,4319,4320,4325,4328,4331],{},[265,4321,4322],{},[24,4323,4324],{},"Rules file",[265,4326,4327],{},"Istruzioni persistenti",[265,4329,4330],{},"Setup progetto",[265,4332,4333],{},"Settimanale",[250,4335,4336,4341,4344,4346],{},[265,4337,4338],{},[24,4339,4340],{},"MCP server",[265,4342,4343],{},"Contesto esterno dinamico",[265,4345,4330],{},[265,4347,4348],{},"Raramente",[250,4350,4351,4356,4359,4362],{},[265,4352,4353],{},[24,4354,4355],{},"Gestione sessioni",[265,4357,4358],{},"Contesto conversazionale",[265,4360,4361],{},"Ogni sessione",[265,4363,4361],{},[250,4365,4366,4371,4374,4377],{},[265,4367,4368],{},[24,4369,4370],{},"Pattern operativi",[265,4372,4373],{},"Come comunichi con l'AI",[265,4375,4376],{},"Continuo",[265,4378,4379],{},"Si affina col tempo",[17,4381,4382],{},"I primi due livelli li configuri una volta e li mantieni. Gli ultimi due sono abitudini quotidiane che si costruiscono con la pratica.",[17,4384,4385],{},"La differenza tra chi usa l'AI coding \"bene\" e chi la usa \"così così\" non è il tool, non è il modello, non è la dimensione della context window. È la disciplina nel gestire il contesto.",[17,4387,4388,4389,4392],{},"E la buona notizia è che non servono configurazioni complesse o setup elaborati. Serve un rules file snello, sessioni corte, e l'abitudine di dare all'AI ",[24,4390,4391],{},"il giusto contesto al momento giusto"," — né troppo, né troppo poco.",[35,4394],{},[17,4396,4397,1894],{},[24,4398,4399],{},"Fonti",[82,4401,4402,4408,4415,4421,4428,4435,4442,4449,4456,4463],{},[85,4403,4404],{},[69,4405,4407],{"href":2679,"rel":4406},[1152],"Anthropic — Best Practices for Claude Code",[85,4409,4410],{},[69,4411,4414],{"href":4412,"rel":4413},"https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents",[1152],"Anthropic — Context Engineering for AI Agents",[85,4416,4417],{},[69,4418,4420],{"href":2695,"rel":4419},[1152],"HumanLayer — Writing a Good CLAUDE.md",[85,4422,4423],{},[69,4424,4427],{"href":4425,"rel":4426},"https://addyo.substack.com/p/context-engineering-bringing-engineering",[1152],"Addyo Substack — Context Engineering: Bringing Engineering Discipline",[85,4429,4430],{},[69,4431,4434],{"href":4432,"rel":4433},"https://contextual.ai/blog/context-engineering-for-your-mcp-client",[1152],"Contextual AI — Context Engineering for Your MCP Client",[85,4436,4437],{},[69,4438,4441],{"href":4439,"rel":4440},"https://codeconductor.ai/blog/context-engineering",[1152],"CodeConductor — Context Engineering Complete Guide",[85,4443,4444],{},[69,4445,4448],{"href":4446,"rel":4447},"https://martinfowler.com/articles/exploring-gen-ai/context-engineering-coding-agents.html",[1152],"Martin Fowler — Context Engineering for Coding Agents",[85,4450,4451],{},[69,4452,4455],{"href":4453,"rel":4454},"https://refactoring.fm/p/managing-context-for-ai-coding",[1152],"Refactoring.fm — How to Manage Context in AI Coding Workflows",[85,4457,4458],{},[69,4459,4462],{"href":4460,"rel":4461},"https://manus.im/blog/Context-Engineering-for-AI-Agents-Lessons-from-Building-Manus",[1152],"Manus — Context Engineering Lessons",[85,4464,4465],{},[69,4466,4469],{"href":4467,"rel":4468},"https://www.promptingguide.ai/guides/context-engineering-guide",[1152],"PromptingGuide.ai — Context Engineering Guide",[1218,4471,4472],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":355,"searchDepth":417,"depth":417,"links":4474},[4475,4476,4483,4490,4497,4502,4511,4518,4519],{"id":2807,"depth":417,"text":2808},{"id":2832,"depth":417,"text":2833,"children":4477},[4478,4479,4480,4481,4482],{"id":2839,"depth":441,"text":2840},{"id":2365,"depth":441,"text":2957},{"id":2972,"depth":441,"text":2973},{"id":3115,"depth":441,"text":3116},{"id":3219,"depth":441,"text":3220},{"id":3254,"depth":417,"text":3255,"children":4484},[4485,4486,4487,4488,4489],{"id":3265,"depth":441,"text":3266},{"id":3287,"depth":441,"text":3288},{"id":3305,"depth":441,"text":3306},{"id":3341,"depth":441,"text":3342},{"id":3475,"depth":441,"text":3476},{"id":3570,"depth":417,"text":3571,"children":4491},[4492,4493,4494,4495,4496],{"id":3580,"depth":441,"text":3581},{"id":3593,"depth":441,"text":3594},{"id":3617,"depth":441,"text":3618},{"id":3642,"depth":441,"text":3643},{"id":3675,"depth":441,"text":3676},{"id":3706,"depth":417,"text":3707,"children":4498},[4499,4500,4501],{"id":3713,"depth":441,"text":3714},{"id":3800,"depth":441,"text":3801},{"id":3810,"depth":441,"text":3811},{"id":3832,"depth":417,"text":3833,"children":4503},[4504,4505,4506,4507,4508,4509,4510],{"id":3839,"depth":441,"text":3840},{"id":3941,"depth":441,"text":3942},{"id":3957,"depth":441,"text":3958},{"id":3970,"depth":441,"text":3971},{"id":3997,"depth":441,"text":3998},{"id":4017,"depth":441,"text":4018},{"id":4033,"depth":441,"text":4034},{"id":4070,"depth":417,"text":4071,"children":4512},[4513,4514,4515,4516,4517],{"id":4074,"depth":441,"text":4075},{"id":4096,"depth":441,"text":4097},{"id":4115,"depth":441,"text":4116},{"id":4134,"depth":441,"text":4135},{"id":4153,"depth":441,"text":4154},{"id":4174,"depth":417,"text":4175},{"id":4291,"depth":417,"text":4292},"Guida operativa al context engineering: rules file, MCP server, gestione sessioni e workflow quotidiano per massimizzare la qualità dell'AI coding.","/images/guides/context-engineering-pratico.webp",{},"/guides/context-engineering-pratico-rules-mcp-workflow","2026-03-04",{"title":2779,"description":4520},"guides/context-engineering-pratico-rules-mcp-workflow",[1285,1304,4528,4529,2766,1287,2294,1268],"MCP","Workflow","AQPd10eNd8lHLA1xlYXsi4ulFkIwG3zzlrZBgl-1DHg",{"id":4532,"title":4533,"author":4534,"body":4535,"category":8060,"contentType":1269,"description":8061,"difficulty":2768,"extension":1272,"featured":444,"icon":1269,"image":8062,"meta":8063,"navigation":444,"path":8064,"publishedAt":8065,"readingTime":1719,"seo":8066,"stem":8067,"steps":1269,"tags":8068,"youtubeId":1269,"__hash__":8072},"guides/guides/costruire-mcp-server-guida-pratica.md","Costruire un MCP Server: Guida Pratica Step-by-Step",{"name":7,"initials":8},{"type":10,"value":4536,"toc":8034},[4537,4540,4548,4551,4562,4565,4567,4571,4578,4600,4603,4678,4694,4696,4700,4706,4765,4771,4889,4895,4953,4955,4959,4965,5812,5815,5846,5849,5862,5864,5868,5873,6325,6332,6334,6338,6349,6476,6479,6484,6548,6550,6554,6560,6663,6666,6668,6672,6679,6705,6712,6741,6744,6756,6758,6762,6765,6769,6772,6790,6846,6852,6864,6867,6942,6949,6953,6960,7014,7017,7027,7087,7089,7093,7100,7130,7377,7392,7395,7433,7435,7439,7447,7458,7475,7478,7482,7497,7500,7504,7511,7518,7525,7529,7536,7550,7554,7561,7568,7570,7574,7580,7585,7798,7807,7839,7841,7845,7848,7853,7873,7878,7904,7909,7940,7947,7953,7956,7958,7962,8031],[13,4538,4533],{"id":4539},"costruire-un-mcp-server-guida-pratica-step-by-step",[17,4541,4542,4543,4547],{},"Nell'",[69,4544,4546],{"href":4545},"/tools/mcp-model-context-protocol-cos-e","articolo su MCP"," abbiamo visto cos'è il Model Context Protocol, perché risolve il problema M × N delle integrazioni, e come l'industria l'ha adottato in 12 mesi. Sappiamo che ci sono 16.000+ server pubblici e 97 milioni di download mensili degli SDK.",[17,4549,4550],{},"Ora ne costruiamo uno.",[17,4552,4553,4554,4557,4558,4561],{},"In questa guida creiamo un ",[24,4555,4556],{},"MCP server funzionante"," da zero — un \"Dev Notes\" che salva, cerca e organizza appunti di sviluppo. Non un hello world: un server che mostra ",[24,4559,4560],{},"tools, resources e prompts"," in un caso d'uso reale. Prima in TypeScript, poi la versione Python in 25 righe.",[17,4563,4564],{},"Alla fine avrai un server testato con l'Inspector e collegato a Claude Desktop, Claude Code o Cursor.",[35,4566],{},[38,4568,4570],{"id":4569},"cosa-costruiamo","Cosa Costruiamo",[17,4572,4573,4574,4577],{},"Un server ",[24,4575,4576],{},"Dev Notes"," — una knowledge base personale per i tuoi appunti di sviluppo. Perché è il tipo di server che:",[82,4579,4580,4587,4594],{},[85,4581,4582,4583,4586],{},"È ",[24,4584,4585],{},"immediatamente utile"," (chi non ha appunti sparsi ovunque?)",[85,4588,4589,4590,4593],{},"Mostra ",[24,4591,4592],{},"tutte e tre le primitive MCP"," in azione",[85,4595,4582,4596,4599],{},[24,4597,4598],{},"autocontenuto"," — niente API esterne, niente database, solo un file JSON",[17,4601,4602],{},"Il server espone:",[244,4604,4605,4618],{},[247,4606,4607],{},[250,4608,4609,4612,4615],{},[253,4610,4611],{},"Primitiva",[253,4613,4614],{},"Nome",[253,4616,4617],{},"Cosa fa",[260,4619,4620,4634,4648,4663],{},[250,4621,4622,4626,4631],{},[265,4623,4624],{},[24,4625,2264],{},[265,4627,4628],{},[353,4629,4630],{},"add_note",[265,4632,4633],{},"Salva un nuovo appunto con titolo, contenuto e tag",[250,4635,4636,4640,4645],{},[265,4637,4638],{},[24,4639,2264],{},[265,4641,4642],{},[353,4643,4644],{},"search_notes",[265,4646,4647],{},"Cerca negli appunti per parola chiave o tag",[250,4649,4650,4655,4660],{},[265,4651,4652],{},[24,4653,4654],{},"Resource",[265,4656,4657],{},[353,4658,4659],{},"notes://all",[265,4661,4662],{},"Lista tutti gli appunti (dati di contesto)",[250,4664,4665,4670,4675],{},[265,4666,4667],{},[24,4668,4669],{},"Prompt",[265,4671,4672],{},[353,4673,4674],{},"summarize_project",[265,4676,4677],{},"Template per riassumere gli appunti di un progetto",[17,4679,4680,4681,4684,4685,4687,4688,4691,4692,688],{},"Quando lo colleghi a Claude, puoi dire cose tipo ",[2128,4682,4683],{},"\"Salva un appunto: il bug #342 è causato da un race condition nel modulo pagamenti\""," e Claude usa il tool ",[353,4686,4630],{},". Oppure ",[2128,4689,4690],{},"\"Cosa avevo scritto sul refactoring del database?\""," e usa ",[353,4693,4644],{},[35,4695],{},[38,4697,4699],{"id":4698},"setup-del-progetto-typescript","Setup del Progetto (TypeScript)",[17,4701,4702,4703,688],{},"Usiamo l'SDK ufficiale TypeScript — ",[353,4704,4705],{},"@modelcontextprotocol/sdk",[346,4707,4709],{"className":401,"code":4708,"language":403,"meta":355,"style":355},"mkdir dev-notes-mcp\ncd dev-notes-mcp\nnpm init -y\nnpm install @modelcontextprotocol/sdk zod\nnpm install -D @types/node typescript\n",[353,4710,4711,4719,4726,4737,4750],{"__ignoreMap":355},[407,4712,4713,4716],{"class":409,"line":410},[407,4714,4715],{"class":420},"mkdir",[407,4717,4718],{"class":424}," dev-notes-mcp\n",[407,4720,4721,4724],{"class":409,"line":417},[407,4722,4723],{"class":434},"cd",[407,4725,4718],{"class":424},[407,4727,4728,4731,4734],{"class":409,"line":441},[407,4729,4730],{"class":420},"npm",[407,4732,4733],{"class":424}," init",[407,4735,4736],{"class":434}," -y\n",[407,4738,4739,4741,4744,4747],{"class":409,"line":448},[407,4740,4730],{"class":420},[407,4742,4743],{"class":424}," install",[407,4745,4746],{"class":424}," @modelcontextprotocol/sdk",[407,4748,4749],{"class":424}," zod\n",[407,4751,4752,4754,4756,4759,4762],{"class":409,"line":454},[407,4753,4730],{"class":420},[407,4755,4743],{"class":424},[407,4757,4758],{"class":434}," -D",[407,4760,4761],{"class":424}," @types/node",[407,4763,4764],{"class":424}," typescript\n",[17,4766,4767,4768,1894],{},"Configura ",[353,4769,4770],{},"tsconfig.json",[346,4772,4774],{"className":2192,"code":4773,"language":2194,"meta":355,"style":355},"{\n  \"compilerOptions\": {\n    \"target\": \"ES2022\",\n    \"module\": \"Node16\",\n    \"moduleResolution\": \"Node16\",\n    \"outDir\": \"./build\",\n    \"rootDir\": \"./src\",\n    \"strict\": true,\n    \"esModuleInterop\": true\n  },\n  \"include\": [\"src/**/*\"]\n}\n",[353,4775,4776,4780,4787,4799,4811,4822,4834,4846,4858,4868,4873,4885],{"__ignoreMap":355},[407,4777,4778],{"class":409,"line":410},[407,4779,2202],{"class":2201},[407,4781,4782,4785],{"class":409,"line":417},[407,4783,4784],{"class":434},"  \"compilerOptions\"",[407,4786,2210],{"class":2201},[407,4788,4789,4792,4794,4797],{"class":409,"line":441},[407,4790,4791],{"class":434},"    \"target\"",[407,4793,2225],{"class":2201},[407,4795,4796],{"class":424},"\"ES2022\"",[407,4798,3384],{"class":2201},[407,4800,4801,4804,4806,4809],{"class":409,"line":448},[407,4802,4803],{"class":434},"    \"module\"",[407,4805,2225],{"class":2201},[407,4807,4808],{"class":424},"\"Node16\"",[407,4810,3384],{"class":2201},[407,4812,4813,4816,4818,4820],{"class":409,"line":454},[407,4814,4815],{"class":434},"    \"moduleResolution\"",[407,4817,2225],{"class":2201},[407,4819,4808],{"class":424},[407,4821,3384],{"class":2201},[407,4823,4824,4827,4829,4832],{"class":409,"line":1667},[407,4825,4826],{"class":434},"    \"outDir\"",[407,4828,2225],{"class":2201},[407,4830,4831],{"class":424},"\"./build\"",[407,4833,3384],{"class":2201},[407,4835,4836,4839,4841,4844],{"class":409,"line":1673},[407,4837,4838],{"class":434},"    \"rootDir\"",[407,4840,2225],{"class":2201},[407,4842,4843],{"class":424},"\"./src\"",[407,4845,3384],{"class":2201},[407,4847,4848,4851,4853,4856],{"class":409,"line":1679},[407,4849,4850],{"class":434},"    \"strict\"",[407,4852,2225],{"class":2201},[407,4854,4855],{"class":434},"true",[407,4857,3384],{"class":2201},[407,4859,4860,4863,4865],{"class":409,"line":1685},[407,4861,4862],{"class":434},"    \"esModuleInterop\"",[407,4864,2225],{"class":2201},[407,4866,4867],{"class":434},"true\n",[407,4869,4870],{"class":409,"line":1690},[407,4871,4872],{"class":2201},"  },\n",[407,4874,4875,4878,4880,4883],{"class":409,"line":1696},[407,4876,4877],{"class":434},"  \"include\"",[407,4879,3392],{"class":2201},[407,4881,4882],{"class":424},"\"src/**/*\"",[407,4884,3398],{"class":2201},[407,4886,4887],{"class":409,"line":1702},[407,4888,2243],{"class":2201},[17,4890,4891,4892,1894],{},"E aggiorna ",[353,4893,4894],{},"package.json",[346,4896,4898],{"className":2192,"code":4897,"language":2194,"meta":355,"style":355},"{\n  \"type\": \"module\",\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"start\": \"node build/index.js\"\n  }\n}\n",[353,4899,4900,4904,4916,4923,4935,4945,4949],{"__ignoreMap":355},[407,4901,4902],{"class":409,"line":410},[407,4903,2202],{"class":2201},[407,4905,4906,4909,4911,4914],{"class":409,"line":417},[407,4907,4908],{"class":434},"  \"type\"",[407,4910,2225],{"class":2201},[407,4912,4913],{"class":424},"\"module\"",[407,4915,3384],{"class":2201},[407,4917,4918,4921],{"class":409,"line":441},[407,4919,4920],{"class":434},"  \"scripts\"",[407,4922,2210],{"class":2201},[407,4924,4925,4928,4930,4933],{"class":409,"line":448},[407,4926,4927],{"class":434},"    \"build\"",[407,4929,2225],{"class":2201},[407,4931,4932],{"class":424},"\"tsc\"",[407,4934,3384],{"class":2201},[407,4936,4937,4940,4942],{"class":409,"line":454},[407,4938,4939],{"class":434},"    \"start\"",[407,4941,2225],{"class":2201},[407,4943,4944],{"class":424},"\"node build/index.js\"\n",[407,4946,4947],{"class":409,"line":1667},[407,4948,2238],{"class":2201},[407,4950,4951],{"class":409,"line":1673},[407,4952,2243],{"class":2201},[35,4954],{},[38,4956,4958],{"id":4957},"il-primo-tool-salvare-un-appunto","Il Primo Tool: Salvare un Appunto",[17,4960,4961,4962,1894],{},"Partiamo dal minimo funzionante. Crea ",[353,4963,4964],{},"src/index.ts",[346,4966,4968],{"className":3850,"code":4967,"language":3852,"meta":355,"style":355},"import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport fs from \"fs/promises\";\nimport path from \"path\";\n\n// Dove salviamo gli appunti\nconst NOTES_FILE = path.join(process.cwd(), \"notes.json\");\n\ninterface Note {\n  id: string;\n  title: string;\n  content: string;\n  tags: string[];\n  createdAt: string;\n}\n\nasync function readNotes(): Promise\u003CNote[]> {\n  try {\n    const data = await fs.readFile(NOTES_FILE, \"utf-8\");\n    return JSON.parse(data);\n  } catch {\n    return []; // File non esiste ancora? Array vuoto.\n  }\n}\n\nasync function writeNotes(notes: Note[]): Promise\u003Cvoid> {\n  await fs.writeFile(NOTES_FILE, JSON.stringify(notes, null, 2));\n}\n\n// --- Creiamo il server ---\n\nconst server = new McpServer({\n  name: \"dev-notes\",\n  version: \"1.0.0\"\n});\n\n// Tool: salva un appunto\nserver.tool(\n  \"add_note\",                              // nome del tool\n  \"Save a development note with tags\",     // descrizione per l'LLM\n  {                                         // schema input (Zod)\n    title: z.string().describe(\"Note title\"),\n    content: z.string().describe(\"Note content\"),\n    tags: z.array(z.string()).optional().describe(\"Tags for categorization\")\n  },\n  async ({ title, content, tags }) => {     // handler\n    const notes = await readNotes();\n    const note: Note = {\n      id: crypto.randomUUID(),\n      title,\n      content,\n      tags: tags || [],\n      createdAt: new Date().toISOString()\n    };\n    notes.push(note);\n    await writeNotes(notes);\n    return {\n      content: [{\n        type: \"text\",\n        text: `Note saved: \"${title}\" (id: ${note.id})`\n      }]\n    };\n  }\n);\n\n// Connessione via stdio\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n",[353,4969,4970,4987,5001,5015,5029,5043,5047,5052,5084,5088,5097,5108,5119,5130,5142,5152,5156,5160,5188,5195,5227,5243,5253,5263,5267,5271,5275,5308,5346,5351,5356,5362,5367,5386,5397,5406,5412,5417,5423,5435,5447,5459,5468,5491,5510,5542,5547,5581,5598,5614,5626,5632,5638,5650,5670,5676,5688,5699,5706,5712,5723,5748,5754,5759,5764,5769,5774,5780,5797],{"__ignoreMap":355},[407,4971,4972,4975,4978,4981,4984],{"class":409,"line":410},[407,4973,4974],{"class":3864},"import",[407,4976,4977],{"class":2201}," { McpServer } ",[407,4979,4980],{"class":3864},"from",[407,4982,4983],{"class":424}," \"@modelcontextprotocol/sdk/server/mcp.js\"",[407,4985,4986],{"class":2201},";\n",[407,4988,4989,4991,4994,4996,4999],{"class":409,"line":417},[407,4990,4974],{"class":3864},[407,4992,4993],{"class":2201}," { StdioServerTransport } ",[407,4995,4980],{"class":3864},[407,4997,4998],{"class":424}," \"@modelcontextprotocol/sdk/server/stdio.js\"",[407,5000,4986],{"class":2201},[407,5002,5003,5005,5008,5010,5013],{"class":409,"line":441},[407,5004,4974],{"class":3864},[407,5006,5007],{"class":2201}," { z } ",[407,5009,4980],{"class":3864},[407,5011,5012],{"class":424}," \"zod\"",[407,5014,4986],{"class":2201},[407,5016,5017,5019,5022,5024,5027],{"class":409,"line":448},[407,5018,4974],{"class":3864},[407,5020,5021],{"class":2201}," fs ",[407,5023,4980],{"class":3864},[407,5025,5026],{"class":424}," \"fs/promises\"",[407,5028,4986],{"class":2201},[407,5030,5031,5033,5036,5038,5041],{"class":409,"line":454},[407,5032,4974],{"class":3864},[407,5034,5035],{"class":2201}," path ",[407,5037,4980],{"class":3864},[407,5039,5040],{"class":424}," \"path\"",[407,5042,4986],{"class":2201},[407,5044,5045],{"class":409,"line":1667},[407,5046,445],{"emptyLinePlaceholder":444},[407,5048,5049],{"class":409,"line":1673},[407,5050,5051],{"class":413},"// Dove salviamo gli appunti\n",[407,5053,5054,5057,5060,5063,5066,5069,5072,5075,5078,5081],{"class":409,"line":1679},[407,5055,5056],{"class":3864},"const",[407,5058,5059],{"class":434}," NOTES_FILE",[407,5061,5062],{"class":3864}," =",[407,5064,5065],{"class":2201}," path.",[407,5067,5068],{"class":420},"join",[407,5070,5071],{"class":2201},"(process.",[407,5073,5074],{"class":420},"cwd",[407,5076,5077],{"class":2201},"(), ",[407,5079,5080],{"class":424},"\"notes.json\"",[407,5082,5083],{"class":2201},");\n",[407,5085,5086],{"class":409,"line":1685},[407,5087,445],{"emptyLinePlaceholder":444},[407,5089,5090,5092,5095],{"class":409,"line":1690},[407,5091,3865],{"class":3864},[407,5093,5094],{"class":420}," Note",[407,5096,3871],{"class":2201},[407,5098,5099,5101,5103,5106],{"class":409,"line":1696},[407,5100,3877],{"class":3876},[407,5102,1894],{"class":3864},[407,5104,5105],{"class":434}," string",[407,5107,4986],{"class":2201},[407,5109,5110,5113,5115,5117],{"class":409,"line":1702},[407,5111,5112],{"class":3876},"  title",[407,5114,1894],{"class":3864},[407,5116,5105],{"class":434},[407,5118,4986],{"class":2201},[407,5120,5121,5124,5126,5128],{"class":409,"line":1708},[407,5122,5123],{"class":3876},"  content",[407,5125,1894],{"class":3864},[407,5127,5105],{"class":434},[407,5129,4986],{"class":2201},[407,5131,5132,5135,5137,5139],{"class":409,"line":1714},[407,5133,5134],{"class":3876},"  tags",[407,5136,1894],{"class":3864},[407,5138,5105],{"class":434},[407,5140,5141],{"class":2201},"[];\n",[407,5143,5144,5146,5148,5150],{"class":409,"line":1719},[407,5145,3912],{"class":3876},[407,5147,1894],{"class":3864},[407,5149,5105],{"class":434},[407,5151,4986],{"class":2201},[407,5153,5154],{"class":409,"line":1725},[407,5155,2243],{"class":2201},[407,5157,5158],{"class":409,"line":1278},[407,5159,445],{"emptyLinePlaceholder":444},[407,5161,5162,5165,5168,5171,5174,5176,5179,5182,5185],{"class":409,"line":1736},[407,5163,5164],{"class":3864},"async",[407,5166,5167],{"class":3864}," function",[407,5169,5170],{"class":420}," readNotes",[407,5172,5173],{"class":2201},"()",[407,5175,1894],{"class":3864},[407,5177,5178],{"class":420}," Promise",[407,5180,5181],{"class":2201},"\u003C",[407,5183,5184],{"class":420},"Note",[407,5186,5187],{"class":2201},"[]> {\n",[407,5189,5190,5193],{"class":409,"line":1742},[407,5191,5192],{"class":3864},"  try",[407,5194,3871],{"class":2201},[407,5196,5197,5200,5203,5205,5208,5211,5214,5217,5220,5222,5225],{"class":409,"line":1748},[407,5198,5199],{"class":3864},"    const",[407,5201,5202],{"class":434}," data",[407,5204,5062],{"class":3864},[407,5206,5207],{"class":3864}," await",[407,5209,5210],{"class":2201}," fs.",[407,5212,5213],{"class":420},"readFile",[407,5215,5216],{"class":2201},"(",[407,5218,5219],{"class":434},"NOTES_FILE",[407,5221,2078],{"class":2201},[407,5223,5224],{"class":424},"\"utf-8\"",[407,5226,5083],{"class":2201},[407,5228,5229,5232,5235,5237,5240],{"class":409,"line":1753},[407,5230,5231],{"class":3864},"    return",[407,5233,5234],{"class":434}," JSON",[407,5236,688],{"class":2201},[407,5238,5239],{"class":420},"parse",[407,5241,5242],{"class":2201},"(data);\n",[407,5244,5245,5248,5251],{"class":409,"line":1759},[407,5246,5247],{"class":2201},"  } ",[407,5249,5250],{"class":3864},"catch",[407,5252,3871],{"class":2201},[407,5254,5255,5257,5260],{"class":409,"line":1765},[407,5256,5231],{"class":3864},[407,5258,5259],{"class":2201}," []; ",[407,5261,5262],{"class":413},"// File non esiste ancora? Array vuoto.\n",[407,5264,5265],{"class":409,"line":1771},[407,5266,2238],{"class":2201},[407,5268,5269],{"class":409,"line":1777},[407,5270,2243],{"class":2201},[407,5272,5273],{"class":409,"line":1782},[407,5274,445],{"emptyLinePlaceholder":444},[407,5276,5277,5279,5281,5284,5286,5289,5291,5293,5296,5298,5300,5302,5305],{"class":409,"line":1788},[407,5278,5164],{"class":3864},[407,5280,5167],{"class":3864},[407,5282,5283],{"class":420}," writeNotes",[407,5285,5216],{"class":2201},[407,5287,5288],{"class":3876},"notes",[407,5290,1894],{"class":3864},[407,5292,5094],{"class":420},[407,5294,5295],{"class":2201},"[])",[407,5297,1894],{"class":3864},[407,5299,5178],{"class":420},[407,5301,5181],{"class":2201},[407,5303,5304],{"class":434},"void",[407,5306,5307],{"class":2201},"> {\n",[407,5309,5310,5313,5315,5318,5320,5322,5324,5327,5329,5332,5335,5338,5340,5343],{"class":409,"line":1794},[407,5311,5312],{"class":3864},"  await",[407,5314,5210],{"class":2201},[407,5316,5317],{"class":420},"writeFile",[407,5319,5216],{"class":2201},[407,5321,5219],{"class":434},[407,5323,2078],{"class":2201},[407,5325,5326],{"class":434},"JSON",[407,5328,688],{"class":2201},[407,5330,5331],{"class":420},"stringify",[407,5333,5334],{"class":2201},"(notes, ",[407,5336,5337],{"class":434},"null",[407,5339,2078],{"class":2201},[407,5341,5342],{"class":434},"2",[407,5344,5345],{"class":2201},"));\n",[407,5347,5349],{"class":409,"line":5348},29,[407,5350,2243],{"class":2201},[407,5352,5354],{"class":409,"line":5353},30,[407,5355,445],{"emptyLinePlaceholder":444},[407,5357,5359],{"class":409,"line":5358},31,[407,5360,5361],{"class":413},"// --- Creiamo il server ---\n",[407,5363,5365],{"class":409,"line":5364},32,[407,5366,445],{"emptyLinePlaceholder":444},[407,5368,5370,5372,5375,5377,5380,5383],{"class":409,"line":5369},33,[407,5371,5056],{"class":3864},[407,5373,5374],{"class":434}," server",[407,5376,5062],{"class":3864},[407,5378,5379],{"class":3864}," new",[407,5381,5382],{"class":420}," McpServer",[407,5384,5385],{"class":2201},"({\n",[407,5387,5389,5392,5395],{"class":409,"line":5388},34,[407,5390,5391],{"class":2201},"  name: ",[407,5393,5394],{"class":424},"\"dev-notes\"",[407,5396,3384],{"class":2201},[407,5398,5400,5403],{"class":409,"line":5399},35,[407,5401,5402],{"class":2201},"  version: ",[407,5404,5405],{"class":424},"\"1.0.0\"\n",[407,5407,5409],{"class":409,"line":5408},36,[407,5410,5411],{"class":2201},"});\n",[407,5413,5415],{"class":409,"line":5414},37,[407,5416,445],{"emptyLinePlaceholder":444},[407,5418,5420],{"class":409,"line":5419},38,[407,5421,5422],{"class":413},"// Tool: salva un appunto\n",[407,5424,5426,5429,5432],{"class":409,"line":5425},39,[407,5427,5428],{"class":2201},"server.",[407,5430,5431],{"class":420},"tool",[407,5433,5434],{"class":2201},"(\n",[407,5436,5438,5441,5444],{"class":409,"line":5437},40,[407,5439,5440],{"class":424},"  \"add_note\"",[407,5442,5443],{"class":2201},",                              ",[407,5445,5446],{"class":413},"// nome del tool\n",[407,5448,5450,5453,5456],{"class":409,"line":5449},41,[407,5451,5452],{"class":424},"  \"Save a development note with tags\"",[407,5454,5455],{"class":2201},",     ",[407,5457,5458],{"class":413},"// descrizione per l'LLM\n",[407,5460,5462,5465],{"class":409,"line":5461},42,[407,5463,5464],{"class":2201},"  {                                         ",[407,5466,5467],{"class":413},"// schema input (Zod)\n",[407,5469,5471,5474,5477,5480,5483,5485,5488],{"class":409,"line":5470},43,[407,5472,5473],{"class":2201},"    title: z.",[407,5475,5476],{"class":420},"string",[407,5478,5479],{"class":2201},"().",[407,5481,5482],{"class":420},"describe",[407,5484,5216],{"class":2201},[407,5486,5487],{"class":424},"\"Note title\"",[407,5489,5490],{"class":2201},"),\n",[407,5492,5494,5497,5499,5501,5503,5505,5508],{"class":409,"line":5493},44,[407,5495,5496],{"class":2201},"    content: z.",[407,5498,5476],{"class":420},[407,5500,5479],{"class":2201},[407,5502,5482],{"class":420},[407,5504,5216],{"class":2201},[407,5506,5507],{"class":424},"\"Note content\"",[407,5509,5490],{"class":2201},[407,5511,5513,5516,5519,5522,5524,5527,5530,5532,5534,5536,5539],{"class":409,"line":5512},45,[407,5514,5515],{"class":2201},"    tags: z.",[407,5517,5518],{"class":420},"array",[407,5520,5521],{"class":2201},"(z.",[407,5523,5476],{"class":420},[407,5525,5526],{"class":2201},"()).",[407,5528,5529],{"class":420},"optional",[407,5531,5479],{"class":2201},[407,5533,5482],{"class":420},[407,5535,5216],{"class":2201},[407,5537,5538],{"class":424},"\"Tags for categorization\"",[407,5540,5541],{"class":2201},")\n",[407,5543,5545],{"class":409,"line":5544},46,[407,5546,4872],{"class":2201},[407,5548,5550,5553,5556,5559,5561,5564,5566,5569,5572,5575,5578],{"class":409,"line":5549},47,[407,5551,5552],{"class":3864},"  async",[407,5554,5555],{"class":2201}," ({ ",[407,5557,5558],{"class":3876},"title",[407,5560,2078],{"class":2201},[407,5562,5563],{"class":3876},"content",[407,5565,2078],{"class":2201},[407,5567,5568],{"class":3876},"tags",[407,5570,5571],{"class":2201}," }) ",[407,5573,5574],{"class":3864},"=>",[407,5576,5577],{"class":2201}," {     ",[407,5579,5580],{"class":413},"// handler\n",[407,5582,5584,5586,5589,5591,5593,5595],{"class":409,"line":5583},48,[407,5585,5199],{"class":3864},[407,5587,5588],{"class":434}," notes",[407,5590,5062],{"class":3864},[407,5592,5207],{"class":3864},[407,5594,5170],{"class":420},[407,5596,5597],{"class":2201},"();\n",[407,5599,5601,5603,5606,5608,5610,5612],{"class":409,"line":5600},49,[407,5602,5199],{"class":3864},[407,5604,5605],{"class":434}," note",[407,5607,1894],{"class":3864},[407,5609,5094],{"class":420},[407,5611,5062],{"class":3864},[407,5613,3871],{"class":2201},[407,5615,5617,5620,5623],{"class":409,"line":5616},50,[407,5618,5619],{"class":2201},"      id: crypto.",[407,5621,5622],{"class":420},"randomUUID",[407,5624,5625],{"class":2201},"(),\n",[407,5627,5629],{"class":409,"line":5628},51,[407,5630,5631],{"class":2201},"      title,\n",[407,5633,5635],{"class":409,"line":5634},52,[407,5636,5637],{"class":2201},"      content,\n",[407,5639,5641,5644,5647],{"class":409,"line":5640},53,[407,5642,5643],{"class":2201},"      tags: tags ",[407,5645,5646],{"class":3864},"||",[407,5648,5649],{"class":2201}," [],\n",[407,5651,5653,5656,5659,5662,5664,5667],{"class":409,"line":5652},54,[407,5654,5655],{"class":2201},"      createdAt: ",[407,5657,5658],{"class":3864},"new",[407,5660,5661],{"class":420}," Date",[407,5663,5479],{"class":2201},[407,5665,5666],{"class":420},"toISOString",[407,5668,5669],{"class":2201},"()\n",[407,5671,5673],{"class":409,"line":5672},55,[407,5674,5675],{"class":2201},"    };\n",[407,5677,5679,5682,5685],{"class":409,"line":5678},56,[407,5680,5681],{"class":2201},"    notes.",[407,5683,5684],{"class":420},"push",[407,5686,5687],{"class":2201},"(note);\n",[407,5689,5691,5694,5696],{"class":409,"line":5690},57,[407,5692,5693],{"class":3864},"    await",[407,5695,5283],{"class":420},[407,5697,5698],{"class":2201},"(notes);\n",[407,5700,5702,5704],{"class":409,"line":5701},58,[407,5703,5231],{"class":3864},[407,5705,3871],{"class":2201},[407,5707,5709],{"class":409,"line":5708},59,[407,5710,5711],{"class":2201},"      content: [{\n",[407,5713,5715,5718,5721],{"class":409,"line":5714},60,[407,5716,5717],{"class":2201},"        type: ",[407,5719,5720],{"class":424},"\"text\"",[407,5722,3384],{"class":2201},[407,5724,5726,5729,5732,5734,5737,5740,5742,5745],{"class":409,"line":5725},61,[407,5727,5728],{"class":2201},"        text: ",[407,5730,5731],{"class":424},"`Note saved: \"${",[407,5733,5558],{"class":2201},[407,5735,5736],{"class":424},"}\" (id: ${",[407,5738,5739],{"class":2201},"note",[407,5741,688],{"class":424},[407,5743,5744],{"class":2201},"id",[407,5746,5747],{"class":424},"})`\n",[407,5749,5751],{"class":409,"line":5750},62,[407,5752,5753],{"class":2201},"      }]\n",[407,5755,5757],{"class":409,"line":5756},63,[407,5758,5675],{"class":2201},[407,5760,5762],{"class":409,"line":5761},64,[407,5763,2238],{"class":2201},[407,5765,5767],{"class":409,"line":5766},65,[407,5768,5083],{"class":2201},[407,5770,5772],{"class":409,"line":5771},66,[407,5773,445],{"emptyLinePlaceholder":444},[407,5775,5777],{"class":409,"line":5776},67,[407,5778,5779],{"class":413},"// Connessione via stdio\n",[407,5781,5783,5785,5788,5790,5792,5795],{"class":409,"line":5782},68,[407,5784,5056],{"class":3864},[407,5786,5787],{"class":434}," transport",[407,5789,5062],{"class":3864},[407,5791,5379],{"class":3864},[407,5793,5794],{"class":420}," StdioServerTransport",[407,5796,5597],{"class":2201},[407,5798,5800,5803,5806,5809],{"class":409,"line":5799},69,[407,5801,5802],{"class":3864},"await",[407,5804,5805],{"class":2201}," server.",[407,5807,5808],{"class":420},"connect",[407,5810,5811],{"class":2201},"(transport);\n",[17,5813,5814],{},"Tre cose da notare:",[517,5816,5817,5823,5836],{},[85,5818,5819,5822],{},[24,5820,5821],{},"Zod valida automaticamente l'input"," prima di eseguire l'handler. Se il modello invia parametri sbagliati, il server risponde con un errore strutturato senza che tu debba gestirlo.",[85,5824,5825,5828,5829,5832,5833,688],{},[24,5826,5827],{},"La descrizione è per l'LLM",", non per l'utente. Scrivi in inglese perché è il linguaggio che i modelli capiscono meglio per il tool use. Sii specifico: ",[353,5830,5831],{},"\"Save a development note with tags\""," è meglio di ",[353,5834,5835],{},"\"Save note\"",[85,5837,5838,5841,5842,5845],{},[24,5839,5840],{},"Lo schema Zod diventa il JSON Schema"," che l'LLM vede per decidere quali parametri passare. I ",[353,5843,5844],{},".describe()"," sui singoli campi sono importanti — guidano il modello.",[17,5847,5848],{},"Compila e sei pronto:",[346,5850,5852],{"className":401,"code":5851,"language":403,"meta":355,"style":355},"npx tsc\n",[353,5853,5854],{"__ignoreMap":355},[407,5855,5856,5859],{"class":409,"line":410},[407,5857,5858],{"class":420},"npx",[407,5860,5861],{"class":424}," tsc\n",[35,5863],{},[38,5865,5867],{"id":5866},"il-secondo-tool-cercare-negli-appunti","Il Secondo Tool: Cercare negli Appunti",[17,5869,5870,5871,1894],{},"Aggiungi la ricerca — subito dopo ",[353,5872,4630],{},[346,5874,5876],{"className":3850,"code":5875,"language":3852,"meta":355,"style":355},"server.tool(\n  \"search_notes\",\n  \"Search notes by keyword in title/content, optionally filter by tag\",\n  {\n    query: z.string().describe(\"Search keyword\"),\n    tag: z.string().optional().describe(\"Filter by this tag\")\n  },\n  async ({ query, tag }) => {\n    const notes = await readNotes();\n    const q = query.toLowerCase();\n\n    let results = notes.filter(n =>\n      n.title.toLowerCase().includes(q) ||\n      n.content.toLowerCase().includes(q)\n    );\n\n    if (tag) {\n      results = results.filter(n =>\n        n.tags.some(t => t.toLowerCase() === tag.toLowerCase())\n      );\n    }\n\n    if (results.length === 0) {\n      return {\n        content: [{ type: \"text\", text: \"No notes found.\" }]\n      };\n    }\n\n    const formatted = results.map(n =>\n      `**${n.title}** [${n.tags.join(\", \")}]\\n${n.content}`\n    ).join(\"\\n\\n---\\n\\n\");\n\n    return {\n      content: [{ type: \"text\", text: formatted }]\n    };\n  }\n);\n",[353,5877,5878,5886,5893,5900,5905,5923,5945,5949,5969,5983,6000,6004,6029,6047,6061,6066,6070,6078,6096,6131,6136,6140,6144,6163,6170,6186,6191,6195,6199,6219,6269,6293,6297,6303,6313,6317,6321],{"__ignoreMap":355},[407,5879,5880,5882,5884],{"class":409,"line":410},[407,5881,5428],{"class":2201},[407,5883,5431],{"class":420},[407,5885,5434],{"class":2201},[407,5887,5888,5891],{"class":409,"line":417},[407,5889,5890],{"class":424},"  \"search_notes\"",[407,5892,3384],{"class":2201},[407,5894,5895,5898],{"class":409,"line":441},[407,5896,5897],{"class":424},"  \"Search notes by keyword in title/content, optionally filter by tag\"",[407,5899,3384],{"class":2201},[407,5901,5902],{"class":409,"line":448},[407,5903,5904],{"class":2201},"  {\n",[407,5906,5907,5910,5912,5914,5916,5918,5921],{"class":409,"line":454},[407,5908,5909],{"class":2201},"    query: z.",[407,5911,5476],{"class":420},[407,5913,5479],{"class":2201},[407,5915,5482],{"class":420},[407,5917,5216],{"class":2201},[407,5919,5920],{"class":424},"\"Search keyword\"",[407,5922,5490],{"class":2201},[407,5924,5925,5928,5930,5932,5934,5936,5938,5940,5943],{"class":409,"line":1667},[407,5926,5927],{"class":2201},"    tag: z.",[407,5929,5476],{"class":420},[407,5931,5479],{"class":2201},[407,5933,5529],{"class":420},[407,5935,5479],{"class":2201},[407,5937,5482],{"class":420},[407,5939,5216],{"class":2201},[407,5941,5942],{"class":424},"\"Filter by this tag\"",[407,5944,5541],{"class":2201},[407,5946,5947],{"class":409,"line":1673},[407,5948,4872],{"class":2201},[407,5950,5951,5953,5955,5958,5960,5963,5965,5967],{"class":409,"line":1679},[407,5952,5552],{"class":3864},[407,5954,5555],{"class":2201},[407,5956,5957],{"class":3876},"query",[407,5959,2078],{"class":2201},[407,5961,5962],{"class":3876},"tag",[407,5964,5571],{"class":2201},[407,5966,5574],{"class":3864},[407,5968,3871],{"class":2201},[407,5970,5971,5973,5975,5977,5979,5981],{"class":409,"line":1685},[407,5972,5199],{"class":3864},[407,5974,5588],{"class":434},[407,5976,5062],{"class":3864},[407,5978,5207],{"class":3864},[407,5980,5170],{"class":420},[407,5982,5597],{"class":2201},[407,5984,5985,5987,5990,5992,5995,5998],{"class":409,"line":1690},[407,5986,5199],{"class":3864},[407,5988,5989],{"class":434}," q",[407,5991,5062],{"class":3864},[407,5993,5994],{"class":2201}," query.",[407,5996,5997],{"class":420},"toLowerCase",[407,5999,5597],{"class":2201},[407,6001,6002],{"class":409,"line":1696},[407,6003,445],{"emptyLinePlaceholder":444},[407,6005,6006,6009,6012,6015,6018,6021,6023,6026],{"class":409,"line":1702},[407,6007,6008],{"class":3864},"    let",[407,6010,6011],{"class":2201}," results ",[407,6013,6014],{"class":3864},"=",[407,6016,6017],{"class":2201}," notes.",[407,6019,6020],{"class":420},"filter",[407,6022,5216],{"class":2201},[407,6024,6025],{"class":3876},"n",[407,6027,6028],{"class":3864}," =>\n",[407,6030,6031,6034,6036,6038,6041,6044],{"class":409,"line":1708},[407,6032,6033],{"class":2201},"      n.title.",[407,6035,5997],{"class":420},[407,6037,5479],{"class":2201},[407,6039,6040],{"class":420},"includes",[407,6042,6043],{"class":2201},"(q) ",[407,6045,6046],{"class":3864},"||\n",[407,6048,6049,6052,6054,6056,6058],{"class":409,"line":1714},[407,6050,6051],{"class":2201},"      n.content.",[407,6053,5997],{"class":420},[407,6055,5479],{"class":2201},[407,6057,6040],{"class":420},[407,6059,6060],{"class":2201},"(q)\n",[407,6062,6063],{"class":409,"line":1719},[407,6064,6065],{"class":2201},"    );\n",[407,6067,6068],{"class":409,"line":1725},[407,6069,445],{"emptyLinePlaceholder":444},[407,6071,6072,6075],{"class":409,"line":1278},[407,6073,6074],{"class":3864},"    if",[407,6076,6077],{"class":2201}," (tag) {\n",[407,6079,6080,6083,6085,6088,6090,6092,6094],{"class":409,"line":1736},[407,6081,6082],{"class":2201},"      results ",[407,6084,6014],{"class":3864},[407,6086,6087],{"class":2201}," results.",[407,6089,6020],{"class":420},[407,6091,5216],{"class":2201},[407,6093,6025],{"class":3876},[407,6095,6028],{"class":3864},[407,6097,6098,6101,6104,6106,6109,6112,6115,6117,6120,6123,6126,6128],{"class":409,"line":1742},[407,6099,6100],{"class":2201},"        n.tags.",[407,6102,6103],{"class":420},"some",[407,6105,5216],{"class":2201},[407,6107,6108],{"class":3876},"t",[407,6110,6111],{"class":3864}," =>",[407,6113,6114],{"class":2201}," t.",[407,6116,5997],{"class":420},[407,6118,6119],{"class":2201},"() ",[407,6121,6122],{"class":3864},"===",[407,6124,6125],{"class":2201}," tag.",[407,6127,5997],{"class":420},[407,6129,6130],{"class":2201},"())\n",[407,6132,6133],{"class":409,"line":1748},[407,6134,6135],{"class":2201},"      );\n",[407,6137,6138],{"class":409,"line":1753},[407,6139,2233],{"class":2201},[407,6141,6142],{"class":409,"line":1759},[407,6143,445],{"emptyLinePlaceholder":444},[407,6145,6146,6148,6151,6154,6157,6160],{"class":409,"line":1765},[407,6147,6074],{"class":3864},[407,6149,6150],{"class":2201}," (results.",[407,6152,6153],{"class":434},"length",[407,6155,6156],{"class":3864}," ===",[407,6158,6159],{"class":434}," 0",[407,6161,6162],{"class":2201},") {\n",[407,6164,6165,6168],{"class":409,"line":1771},[407,6166,6167],{"class":3864},"      return",[407,6169,3871],{"class":2201},[407,6171,6172,6175,6177,6180,6183],{"class":409,"line":1777},[407,6173,6174],{"class":2201},"        content: [{ type: ",[407,6176,5720],{"class":424},[407,6178,6179],{"class":2201},", text: ",[407,6181,6182],{"class":424},"\"No notes found.\"",[407,6184,6185],{"class":2201}," }]\n",[407,6187,6188],{"class":409,"line":1782},[407,6189,6190],{"class":2201},"      };\n",[407,6192,6193],{"class":409,"line":1788},[407,6194,2233],{"class":2201},[407,6196,6197],{"class":409,"line":1794},[407,6198,445],{"emptyLinePlaceholder":444},[407,6200,6201,6203,6206,6208,6210,6213,6215,6217],{"class":409,"line":5348},[407,6202,5199],{"class":3864},[407,6204,6205],{"class":434}," formatted",[407,6207,5062],{"class":3864},[407,6209,6087],{"class":2201},[407,6211,6212],{"class":420},"map",[407,6214,5216],{"class":2201},[407,6216,6025],{"class":3876},[407,6218,6028],{"class":3864},[407,6220,6221,6224,6226,6228,6230,6233,6235,6237,6239,6241,6243,6245,6248,6251,6254,6257,6260,6262,6264,6266],{"class":409,"line":5353},[407,6222,6223],{"class":424},"      `**${",[407,6225,6025],{"class":2201},[407,6227,688],{"class":424},[407,6229,5558],{"class":2201},[407,6231,6232],{"class":424},"}** [${",[407,6234,6025],{"class":2201},[407,6236,688],{"class":424},[407,6238,5568],{"class":2201},[407,6240,688],{"class":424},[407,6242,5068],{"class":420},[407,6244,5216],{"class":424},[407,6246,6247],{"class":424},"\", \"",[407,6249,6250],{"class":424},")",[407,6252,6253],{"class":424},"}]",[407,6255,6256],{"class":434},"\\n",[407,6258,6259],{"class":424},"${",[407,6261,6025],{"class":2201},[407,6263,688],{"class":424},[407,6265,5563],{"class":2201},[407,6267,6268],{"class":424},"}`\n",[407,6270,6271,6274,6276,6278,6281,6284,6287,6289,6291],{"class":409,"line":5358},[407,6272,6273],{"class":2201},"    ).",[407,6275,5068],{"class":420},[407,6277,5216],{"class":2201},[407,6279,6280],{"class":424},"\"",[407,6282,6283],{"class":434},"\\n\\n",[407,6285,6286],{"class":424},"---",[407,6288,6283],{"class":434},[407,6290,6280],{"class":424},[407,6292,5083],{"class":2201},[407,6294,6295],{"class":409,"line":5364},[407,6296,445],{"emptyLinePlaceholder":444},[407,6298,6299,6301],{"class":409,"line":5369},[407,6300,5231],{"class":3864},[407,6302,3871],{"class":2201},[407,6304,6305,6308,6310],{"class":409,"line":5388},[407,6306,6307],{"class":2201},"      content: [{ type: ",[407,6309,5720],{"class":424},[407,6311,6312],{"class":2201},", text: formatted }]\n",[407,6314,6315],{"class":409,"line":5399},[407,6316,5675],{"class":2201},[407,6318,6319],{"class":409,"line":5408},[407,6320,2238],{"class":2201},[407,6322,6323],{"class":409,"line":5414},[407,6324,5083],{"class":2201},[17,6326,6327,6328,6331],{},"Adesso il modello può sia scrivere che cercare. Ma finora abbiamo usato solo ",[24,6329,6330],{},"tools"," — le azioni che il modello invoca attivamente. MCP ha altre due primitive.",[35,6333],{},[38,6335,6337],{"id":6336},"resource-esporre-dati-di-contesto","Resource: Esporre Dati di Contesto",[17,6339,6340,6341,6344,6345,6348],{},"Una ",[24,6342,6343],{},"resource"," è diversa da un tool. Non è il modello a decidere quando leggerla — è il ",[24,6346,6347],{},"client"," (l'applicazione host). Pensala come un endpoint GET in REST: espone dati che il client può includere nel contesto quando serve.",[346,6350,6352],{"className":3850,"code":6351,"language":3852,"meta":355,"style":355},"server.resource(\n  \"all-notes\",            // nome identificativo\n  \"notes://all\",          // URI della risorsa\n  async (uri) => {\n    const notes = await readNotes();\n    return {\n      contents: [{\n        uri: uri.href,\n        mimeType: \"application/json\",\n        text: JSON.stringify(notes, null, 2)\n      }]\n    };\n  }\n);\n",[353,6353,6354,6362,6373,6384,6400,6414,6420,6425,6430,6440,6460,6464,6468,6472],{"__ignoreMap":355},[407,6355,6356,6358,6360],{"class":409,"line":410},[407,6357,5428],{"class":2201},[407,6359,6343],{"class":420},[407,6361,5434],{"class":2201},[407,6363,6364,6367,6370],{"class":409,"line":417},[407,6365,6366],{"class":424},"  \"all-notes\"",[407,6368,6369],{"class":2201},",            ",[407,6371,6372],{"class":413},"// nome identificativo\n",[407,6374,6375,6378,6381],{"class":409,"line":441},[407,6376,6377],{"class":424},"  \"notes://all\"",[407,6379,6380],{"class":2201},",          ",[407,6382,6383],{"class":413},"// URI della risorsa\n",[407,6385,6386,6388,6390,6393,6396,6398],{"class":409,"line":448},[407,6387,5552],{"class":3864},[407,6389,1486],{"class":2201},[407,6391,6392],{"class":3876},"uri",[407,6394,6395],{"class":2201},") ",[407,6397,5574],{"class":3864},[407,6399,3871],{"class":2201},[407,6401,6402,6404,6406,6408,6410,6412],{"class":409,"line":454},[407,6403,5199],{"class":3864},[407,6405,5588],{"class":434},[407,6407,5062],{"class":3864},[407,6409,5207],{"class":3864},[407,6411,5170],{"class":420},[407,6413,5597],{"class":2201},[407,6415,6416,6418],{"class":409,"line":1667},[407,6417,5231],{"class":3864},[407,6419,3871],{"class":2201},[407,6421,6422],{"class":409,"line":1673},[407,6423,6424],{"class":2201},"      contents: [{\n",[407,6426,6427],{"class":409,"line":1679},[407,6428,6429],{"class":2201},"        uri: uri.href,\n",[407,6431,6432,6435,6438],{"class":409,"line":1685},[407,6433,6434],{"class":2201},"        mimeType: ",[407,6436,6437],{"class":424},"\"application/json\"",[407,6439,3384],{"class":2201},[407,6441,6442,6444,6446,6448,6450,6452,6454,6456,6458],{"class":409,"line":1690},[407,6443,5728],{"class":2201},[407,6445,5326],{"class":434},[407,6447,688],{"class":2201},[407,6449,5331],{"class":420},[407,6451,5334],{"class":2201},[407,6453,5337],{"class":434},[407,6455,2078],{"class":2201},[407,6457,5342],{"class":434},[407,6459,5541],{"class":2201},[407,6461,6462],{"class":409,"line":1696},[407,6463,5753],{"class":2201},[407,6465,6466],{"class":409,"line":1702},[407,6467,5675],{"class":2201},[407,6469,6470],{"class":409,"line":1708},[407,6471,2238],{"class":2201},[407,6473,6474],{"class":409,"line":1714},[407,6475,5083],{"class":2201},[17,6477,6478],{},"Quando Claude Desktop o Cursor vedono questa resource, possono includerla nel contesto della conversazione. L'utente può anche forzarne il caricamento tramite l'interfaccia. È utile per dare al modello una visione d'insieme senza che debba esplicitamente \"cercare\".",[17,6480,6481],{},[24,6482,6483],{},"Quando usare tool vs resource:",[244,6485,6486,6501],{},[247,6487,6488],{},[250,6489,6490,6496],{},[253,6491,6492,6493,6495],{},"Usa un ",[24,6494,5431],{}," quando...",[253,6497,6498,6499,6495],{},"Usa una ",[24,6500,6343],{},[260,6502,6503,6519,6533],{},[250,6504,6505,6512],{},[265,6506,6507,6508,6511],{},"Il modello deve ",[24,6509,6510],{},"agire"," (scrivere, calcolare, chiamare API)",[265,6513,6514,6515,6518],{},"Vuoi ",[24,6516,6517],{},"esporre dati"," di contesto (config, liste, stati)",[250,6520,6521,6527],{},[265,6522,6523,6524],{},"L'operazione ha ",[24,6525,6526],{},"side effects",[265,6528,6529,6530],{},"I dati sono ",[24,6531,6532],{},"read-only",[250,6534,6535,6542],{},[265,6536,6537,6538,6541],{},"Il modello decide ",[24,6539,6540],{},"quando"," invocarli",[265,6543,6544,6545,6547],{},"Il client decide ",[24,6546,6540],{}," caricarli",[35,6549],{},[38,6551,6553],{"id":6552},"prompt-template-riutilizzabili","Prompt: Template Riutilizzabili",[17,6555,2502,6556,6559],{},[24,6557,6558],{},"prompt"," è un template di istruzioni parametrizzabile. Viene esposto all'utente come comando (tipo slash command) — non è il modello a invocarlo, è l'utente a sceglierlo.",[346,6561,6563],{"className":3850,"code":6562,"language":3852,"meta":355,"style":355},"server.prompt(\n  \"summarize_project\",\n  { project_name: z.string() },\n  ({ project_name }) => ({\n    messages: [{\n      role: \"user\",\n      content: {\n        type: \"text\",\n        text: `Read all my development notes and create a summary for the project \"${project_name}\". Group notes by topic, highlight open issues and action items, and note any decisions that were made.`\n      }\n    }]\n  })\n);\n",[353,6564,6565,6573,6580,6590,6605,6610,6620,6625,6633,6645,6649,6654,6659],{"__ignoreMap":355},[407,6566,6567,6569,6571],{"class":409,"line":410},[407,6568,5428],{"class":2201},[407,6570,6558],{"class":420},[407,6572,5434],{"class":2201},[407,6574,6575,6578],{"class":409,"line":417},[407,6576,6577],{"class":424},"  \"summarize_project\"",[407,6579,3384],{"class":2201},[407,6581,6582,6585,6587],{"class":409,"line":441},[407,6583,6584],{"class":2201},"  { project_name: z.",[407,6586,5476],{"class":420},[407,6588,6589],{"class":2201},"() },\n",[407,6591,6592,6595,6598,6600,6602],{"class":409,"line":448},[407,6593,6594],{"class":2201},"  ({ ",[407,6596,6597],{"class":3876},"project_name",[407,6599,5571],{"class":2201},[407,6601,5574],{"class":3864},[407,6603,6604],{"class":2201}," ({\n",[407,6606,6607],{"class":409,"line":454},[407,6608,6609],{"class":2201},"    messages: [{\n",[407,6611,6612,6615,6618],{"class":409,"line":1667},[407,6613,6614],{"class":2201},"      role: ",[407,6616,6617],{"class":424},"\"user\"",[407,6619,3384],{"class":2201},[407,6621,6622],{"class":409,"line":1673},[407,6623,6624],{"class":2201},"      content: {\n",[407,6626,6627,6629,6631],{"class":409,"line":1679},[407,6628,5717],{"class":2201},[407,6630,5720],{"class":424},[407,6632,3384],{"class":2201},[407,6634,6635,6637,6640,6642],{"class":409,"line":1685},[407,6636,5728],{"class":2201},[407,6638,6639],{"class":424},"`Read all my development notes and create a summary for the project \"${",[407,6641,6597],{"class":2201},[407,6643,6644],{"class":424},"}\". Group notes by topic, highlight open issues and action items, and note any decisions that were made.`\n",[407,6646,6647],{"class":409,"line":1690},[407,6648,3454],{"class":2201},[407,6650,6651],{"class":409,"line":1696},[407,6652,6653],{"class":2201},"    }]\n",[407,6655,6656],{"class":409,"line":1702},[407,6657,6658],{"class":2201},"  })\n",[407,6660,6661],{"class":409,"line":1708},[407,6662,5083],{"class":2201},[17,6664,6665],{},"In Claude Desktop, questo prompt appare nel menu comandi. L'utente seleziona \"summarize_project\", inserisce il nome del progetto, e il template viene iniettato nella conversazione. Standardizza workflow che altrimenti riscriveresti ogni volta.",[35,6667],{},[38,6669,6671],{"id":6670},"test-lmcp-inspector","Test: L'MCP Inspector",[17,6673,6674,6675,6678],{},"L'Inspector è il ",[24,6676,6677],{},"Postman di MCP"," — una UI web per testare il tuo server senza doverlo collegare a un client.",[346,6680,6682],{"className":401,"code":6681,"language":403,"meta":355,"style":355},"npx tsc && npx @modelcontextprotocol/inspector node build/index.js\n",[353,6683,6684],{"__ignoreMap":355},[407,6685,6686,6688,6691,6694,6696,6699,6702],{"class":409,"line":410},[407,6687,5858],{"class":420},[407,6689,6690],{"class":424}," tsc",[407,6692,6693],{"class":2201}," && ",[407,6695,5858],{"class":420},[407,6697,6698],{"class":424}," @modelcontextprotocol/inspector",[407,6700,6701],{"class":424}," node",[407,6703,6704],{"class":424}," build/index.js\n",[17,6706,6707,6708,6711],{},"Si apre su ",[353,6709,6710],{},"http://localhost:6274",". Da lì puoi:",[82,6713,6714,6720,6727,6734],{},[85,6715,6716,6717,6719],{},"Vedere la lista dei ",[24,6718,6330],{}," registrati e invocarli con parametri custom",[85,6721,6722,6723,6726],{},"Navigare le ",[24,6724,6725],{},"resources"," e leggerne il contenuto",[85,6728,6729,6730,6733],{},"Testare i ",[24,6731,6732],{},"prompts"," con diversi valori",[85,6735,6736,6737,6740],{},"Vedere i messaggi ",[24,6738,6739],{},"JSON-RPC"," scambiati in tempo reale",[17,6742,6743],{},"Prova ad aggiungere un appunto, poi cercalo. Se funziona nell'Inspector, funziona ovunque.",[1524,6745,6746],{},[17,6747,6748,6751,6752,6755],{},[24,6749,6750],{},"Nota sulla sicurezza dell'Inspector",": la versione precedente (CVE-2025-49596) ascoltava su ",[353,6753,6754],{},"0.0.0.0"," senza autenticazione. Ora è fixato: binding solo su localhost con token di sessione. Aggiorna sempre alla versione più recente.",[35,6757],{},[38,6759,6761],{"id":6760},"collegare-il-server-ai-client","Collegare il Server ai Client",[17,6763,6764],{},"Il server funziona. Ora lo colleghiamo ai tool che usi ogni giorno.",[58,6766,6768],{"id":6767},"claude-desktop","Claude Desktop",[17,6770,6771],{},"Modifica il file di configurazione:",[82,6773,6774,6782],{},[85,6775,6776,2225,6779],{},[24,6777,6778],{},"macOS",[353,6780,6781],{},"~/Library/Application Support/Claude/claude_desktop_config.json",[85,6783,6784,2225,6787],{},[24,6785,6786],{},"Windows",[353,6788,6789],{},"%APPDATA%\\Claude\\claude_desktop_config.json",[346,6791,6793],{"className":2192,"code":6792,"language":2194,"meta":355,"style":355},"{\n  \"mcpServers\": {\n    \"dev-notes\": {\n      \"command\": \"node\",\n      \"args\": [\"/path/assoluto/al/build/index.js\"]\n    }\n  }\n}\n",[353,6794,6795,6799,6805,6812,6823,6834,6838,6842],{"__ignoreMap":355},[407,6796,6797],{"class":409,"line":410},[407,6798,2202],{"class":2201},[407,6800,6801,6803],{"class":409,"line":417},[407,6802,3363],{"class":434},[407,6804,2210],{"class":2201},[407,6806,6807,6810],{"class":409,"line":441},[407,6808,6809],{"class":434},"    \"dev-notes\"",[407,6811,2210],{"class":2201},[407,6813,6814,6816,6818,6821],{"class":409,"line":448},[407,6815,2222],{"class":434},[407,6817,2225],{"class":2201},[407,6819,6820],{"class":424},"\"node\"",[407,6822,3384],{"class":2201},[407,6824,6825,6827,6829,6832],{"class":409,"line":454},[407,6826,3389],{"class":434},[407,6828,3392],{"class":2201},[407,6830,6831],{"class":424},"\"/path/assoluto/al/build/index.js\"",[407,6833,3398],{"class":2201},[407,6835,6836],{"class":409,"line":1667},[407,6837,2233],{"class":2201},[407,6839,6840],{"class":409,"line":1673},[407,6841,2238],{"class":2201},[407,6843,6844],{"class":409,"line":1679},[407,6845,2243],{"class":2201},[17,6847,6848,6849,688],{},"Riavvia Claude Desktop. Il server apparirà nell'icona MCP (il martello) in basso a sinistra. Se non lo vedi, controlla i log in ",[353,6850,6851],{},"~/Library/Logs/Claude/",[1524,6853,6854],{},[17,6855,6856,6859,6860,6863],{},[24,6857,6858],{},"Path assoluto obbligatorio."," Il path negli ",[353,6861,6862],{},"args"," deve essere assoluto. Path relativi non funzionano — il working directory del processo non è quello che ti aspetti.",[58,6865,1287],{"id":6866},"claude-code",[346,6868,6870],{"className":401,"code":6869,"language":403,"meta":355,"style":355},"# Aggiungi al progetto corrente\nclaude mcp add dev-notes node /path/assoluto/al/build/index.js\n\n# Oppure a livello utente (disponibile in tutti i progetti)\nclaude mcp add dev-notes --scope user node /path/assoluto/al/build/index.js\n\n# Verifica\nclaude mcp list\n",[353,6871,6872,6877,6895,6899,6904,6924,6928,6933],{"__ignoreMap":355},[407,6873,6874],{"class":409,"line":410},[407,6875,6876],{"class":413},"# Aggiungi al progetto corrente\n",[407,6878,6879,6882,6885,6887,6890,6892],{"class":409,"line":417},[407,6880,6881],{"class":420},"claude",[407,6883,6884],{"class":424}," mcp",[407,6886,428],{"class":424},[407,6888,6889],{"class":424}," dev-notes",[407,6891,6701],{"class":424},[407,6893,6894],{"class":424}," /path/assoluto/al/build/index.js\n",[407,6896,6897],{"class":409,"line":441},[407,6898,445],{"emptyLinePlaceholder":444},[407,6900,6901],{"class":409,"line":448},[407,6902,6903],{"class":413},"# Oppure a livello utente (disponibile in tutti i progetti)\n",[407,6905,6906,6908,6910,6912,6914,6917,6920,6922],{"class":409,"line":454},[407,6907,6881],{"class":420},[407,6909,6884],{"class":424},[407,6911,428],{"class":424},[407,6913,6889],{"class":424},[407,6915,6916],{"class":434}," --scope",[407,6918,6919],{"class":424}," user",[407,6921,6701],{"class":424},[407,6923,6894],{"class":424},[407,6925,6926],{"class":409,"line":1667},[407,6927,445],{"emptyLinePlaceholder":444},[407,6929,6930],{"class":409,"line":1673},[407,6931,6932],{"class":413},"# Verifica\n",[407,6934,6935,6937,6939],{"class":409,"line":1679},[407,6936,6881],{"class":420},[407,6938,6884],{"class":424},[407,6940,6941],{"class":424}," list\n",[17,6943,6944,6945,6948],{},"Dentro Claude Code, usa ",[353,6946,6947],{},"/mcp"," per controllare lo stato dei server connessi.",[58,6950,6952],{"id":6951},"vs-code-copilot","VS Code (Copilot)",[17,6954,6955,6956,6959],{},"Crea ",[353,6957,6958],{},".vscode/mcp.json"," nella root del progetto:",[346,6961,6963],{"className":2192,"code":6962,"language":2194,"meta":355,"style":355},"{\n  \"mcpServers\": {\n    \"dev-notes\": {\n      \"command\": \"node\",\n      \"args\": [\"./build/index.js\"]\n    }\n  }\n}\n",[353,6964,6965,6969,6975,6981,6991,7002,7006,7010],{"__ignoreMap":355},[407,6966,6967],{"class":409,"line":410},[407,6968,2202],{"class":2201},[407,6970,6971,6973],{"class":409,"line":417},[407,6972,3363],{"class":434},[407,6974,2210],{"class":2201},[407,6976,6977,6979],{"class":409,"line":441},[407,6978,6809],{"class":434},[407,6980,2210],{"class":2201},[407,6982,6983,6985,6987,6989],{"class":409,"line":448},[407,6984,2222],{"class":434},[407,6986,2225],{"class":2201},[407,6988,6820],{"class":424},[407,6990,3384],{"class":2201},[407,6992,6993,6995,6997,7000],{"class":409,"line":454},[407,6994,3389],{"class":434},[407,6996,3392],{"class":2201},[407,6998,6999],{"class":424},"\"./build/index.js\"",[407,7001,3398],{"class":2201},[407,7003,7004],{"class":409,"line":1667},[407,7005,2233],{"class":2201},[407,7007,7008],{"class":409,"line":1673},[407,7009,2238],{"class":2201},[407,7011,7012],{"class":409,"line":1679},[407,7013,2243],{"class":2201},[58,7015,2294],{"id":7016},"cursor",[17,7018,6955,7019,7022,7023,7026],{},[353,7020,7021],{},".cursor/mcp.json"," nella root del progetto (o ",[353,7024,7025],{},"~/.cursor/mcp.json"," per configurazione globale):",[346,7028,7030],{"className":2192,"code":7029,"language":2194,"meta":355,"style":355},"{\n  \"mcpServers\": {\n    \"dev-notes\": {\n      \"command\": \"node\",\n      \"args\": [\"/path/assoluto/al/build/index.js\"],\n      \"env\": {}\n    }\n  }\n}\n",[353,7031,7032,7036,7042,7048,7058,7068,7075,7079,7083],{"__ignoreMap":355},[407,7033,7034],{"class":409,"line":410},[407,7035,2202],{"class":2201},[407,7037,7038,7040],{"class":409,"line":417},[407,7039,3363],{"class":434},[407,7041,2210],{"class":2201},[407,7043,7044,7046],{"class":409,"line":441},[407,7045,6809],{"class":434},[407,7047,2210],{"class":2201},[407,7049,7050,7052,7054,7056],{"class":409,"line":448},[407,7051,2222],{"class":434},[407,7053,2225],{"class":2201},[407,7055,6820],{"class":424},[407,7057,3384],{"class":2201},[407,7059,7060,7062,7064,7066],{"class":409,"line":454},[407,7061,3389],{"class":434},[407,7063,3392],{"class":2201},[407,7065,6831],{"class":424},[407,7067,3432],{"class":2201},[407,7069,7070,7072],{"class":409,"line":1667},[407,7071,3437],{"class":434},[407,7073,7074],{"class":2201},": {}\n",[407,7076,7077],{"class":409,"line":1673},[407,7078,2233],{"class":2201},[407,7080,7081],{"class":409,"line":1679},[407,7082,2238],{"class":2201},[407,7084,7085],{"class":409,"line":1685},[407,7086,2243],{"class":2201},[35,7088],{},[38,7090,7092],{"id":7091},"la-versione-python-25-righe","La Versione Python (25 Righe)",[17,7094,7095,7096,7099],{},"Lo stesso server in Python con ",[24,7097,7098],{},"FastMCP"," — il framework ufficiale che alimenta il ~70% dei server MCP:",[346,7101,7103],{"className":401,"code":7102,"language":403,"meta":355,"style":355},"uv init dev-notes-mcp-py\ncd dev-notes-mcp-py\nuv add \"mcp[cli]\"\n",[353,7104,7105,7115,7121],{"__ignoreMap":355},[407,7106,7107,7110,7112],{"class":409,"line":410},[407,7108,7109],{"class":420},"uv",[407,7111,4733],{"class":424},[407,7113,7114],{"class":424}," dev-notes-mcp-py\n",[407,7116,7117,7119],{"class":409,"line":417},[407,7118,4723],{"class":434},[407,7120,7114],{"class":424},[407,7122,7123,7125,7127],{"class":409,"line":441},[407,7124,7109],{"class":420},[407,7126,428],{"class":424},[407,7128,7129],{"class":424}," \"mcp[cli]\"\n",[346,7131,7135],{"className":7132,"code":7133,"language":7134,"meta":355,"style":355},"language-python shiki shiki-themes github-light github-dark","import json\nfrom pathlib import Path\nfrom mcp.server.fastmcp import FastMCP\n\nmcp = FastMCP(\"Dev Notes\")\nNOTES_FILE = Path(\"notes.json\")\n\ndef _read():\n    return json.loads(NOTES_FILE.read_text()) if NOTES_FILE.exists() else []\n\ndef _write(notes):\n    NOTES_FILE.write_text(json.dumps(notes, indent=2))\n\n@mcp.tool()\ndef add_note(title: str, content: str, tags: list[str] | None = None) -> str:\n    \"\"\"Save a development note with optional tags\"\"\"\n    notes = _read()\n    notes.append({\"title\": title, \"content\": content, \"tags\": tags or []})\n    _write(notes)\n    return f\"Saved: {title}\"\n\n@mcp.tool()\ndef search_notes(query: str, tag: str | None = None) -> str:\n    \"\"\"Search notes by keyword, optionally filter by tag\"\"\"\n    notes = _read()\n    q = query.lower()\n    results = [n for n in notes\n               if q in n[\"title\"].lower() or q in n[\"content\"].lower()]\n    if tag:\n        results = [n for n in results if tag.lower() in\n                   [t.lower() for t in n[\"tags\"]]]\n    if not results:\n        return \"No notes found.\"\n    return \"\\n---\\n\".join(\n        f\"**{n['title']}** [{', '.join(n['tags'])}]\\n{n['content']}\"\n        for n in results\n    )\n\n@mcp.resource(\"notes://all\")\ndef list_all_notes() -> str:\n    \"\"\"List all saved development notes\"\"\"\n    return json.dumps(_read(), indent=2)\n\n@mcp.prompt()\ndef summarize_project(project_name: str) -> str:\n    \"\"\"Summarize all notes for a project\"\"\"\n    return f'Read all notes and summarize project \"{project_name}\". Group by topic, highlight open issues.'\n\nif __name__ == \"__main__\":\n    mcp.run()\n","python",[353,7136,7137,7142,7147,7152,7156,7161,7166,7170,7175,7180,7184,7189,7194,7198,7203,7208,7213,7218,7223,7228,7233,7237,7241,7246,7251,7255,7260,7265,7270,7275,7280,7285,7290,7295,7300,7305,7310,7315,7319,7324,7329,7334,7339,7343,7348,7353,7358,7363,7367,7372],{"__ignoreMap":355},[407,7138,7139],{"class":409,"line":410},[407,7140,7141],{},"import json\n",[407,7143,7144],{"class":409,"line":417},[407,7145,7146],{},"from pathlib import Path\n",[407,7148,7149],{"class":409,"line":441},[407,7150,7151],{},"from mcp.server.fastmcp import FastMCP\n",[407,7153,7154],{"class":409,"line":448},[407,7155,445],{"emptyLinePlaceholder":444},[407,7157,7158],{"class":409,"line":454},[407,7159,7160],{},"mcp = FastMCP(\"Dev Notes\")\n",[407,7162,7163],{"class":409,"line":1667},[407,7164,7165],{},"NOTES_FILE = Path(\"notes.json\")\n",[407,7167,7168],{"class":409,"line":1673},[407,7169,445],{"emptyLinePlaceholder":444},[407,7171,7172],{"class":409,"line":1679},[407,7173,7174],{},"def _read():\n",[407,7176,7177],{"class":409,"line":1685},[407,7178,7179],{},"    return json.loads(NOTES_FILE.read_text()) if NOTES_FILE.exists() else []\n",[407,7181,7182],{"class":409,"line":1690},[407,7183,445],{"emptyLinePlaceholder":444},[407,7185,7186],{"class":409,"line":1696},[407,7187,7188],{},"def _write(notes):\n",[407,7190,7191],{"class":409,"line":1702},[407,7192,7193],{},"    NOTES_FILE.write_text(json.dumps(notes, indent=2))\n",[407,7195,7196],{"class":409,"line":1708},[407,7197,445],{"emptyLinePlaceholder":444},[407,7199,7200],{"class":409,"line":1714},[407,7201,7202],{},"@mcp.tool()\n",[407,7204,7205],{"class":409,"line":1719},[407,7206,7207],{},"def add_note(title: str, content: str, tags: list[str] | None = None) -> str:\n",[407,7209,7210],{"class":409,"line":1725},[407,7211,7212],{},"    \"\"\"Save a development note with optional tags\"\"\"\n",[407,7214,7215],{"class":409,"line":1278},[407,7216,7217],{},"    notes = _read()\n",[407,7219,7220],{"class":409,"line":1736},[407,7221,7222],{},"    notes.append({\"title\": title, \"content\": content, \"tags\": tags or []})\n",[407,7224,7225],{"class":409,"line":1742},[407,7226,7227],{},"    _write(notes)\n",[407,7229,7230],{"class":409,"line":1748},[407,7231,7232],{},"    return f\"Saved: {title}\"\n",[407,7234,7235],{"class":409,"line":1753},[407,7236,445],{"emptyLinePlaceholder":444},[407,7238,7239],{"class":409,"line":1759},[407,7240,7202],{},[407,7242,7243],{"class":409,"line":1765},[407,7244,7245],{},"def search_notes(query: str, tag: str | None = None) -> str:\n",[407,7247,7248],{"class":409,"line":1771},[407,7249,7250],{},"    \"\"\"Search notes by keyword, optionally filter by tag\"\"\"\n",[407,7252,7253],{"class":409,"line":1777},[407,7254,7217],{},[407,7256,7257],{"class":409,"line":1782},[407,7258,7259],{},"    q = query.lower()\n",[407,7261,7262],{"class":409,"line":1788},[407,7263,7264],{},"    results = [n for n in notes\n",[407,7266,7267],{"class":409,"line":1794},[407,7268,7269],{},"               if q in n[\"title\"].lower() or q in n[\"content\"].lower()]\n",[407,7271,7272],{"class":409,"line":5348},[407,7273,7274],{},"    if tag:\n",[407,7276,7277],{"class":409,"line":5353},[407,7278,7279],{},"        results = [n for n in results if tag.lower() in\n",[407,7281,7282],{"class":409,"line":5358},[407,7283,7284],{},"                   [t.lower() for t in n[\"tags\"]]]\n",[407,7286,7287],{"class":409,"line":5364},[407,7288,7289],{},"    if not results:\n",[407,7291,7292],{"class":409,"line":5369},[407,7293,7294],{},"        return \"No notes found.\"\n",[407,7296,7297],{"class":409,"line":5388},[407,7298,7299],{},"    return \"\\n---\\n\".join(\n",[407,7301,7302],{"class":409,"line":5399},[407,7303,7304],{},"        f\"**{n['title']}** [{', '.join(n['tags'])}]\\n{n['content']}\"\n",[407,7306,7307],{"class":409,"line":5408},[407,7308,7309],{},"        for n in results\n",[407,7311,7312],{"class":409,"line":5414},[407,7313,7314],{},"    )\n",[407,7316,7317],{"class":409,"line":5419},[407,7318,445],{"emptyLinePlaceholder":444},[407,7320,7321],{"class":409,"line":5425},[407,7322,7323],{},"@mcp.resource(\"notes://all\")\n",[407,7325,7326],{"class":409,"line":5437},[407,7327,7328],{},"def list_all_notes() -> str:\n",[407,7330,7331],{"class":409,"line":5449},[407,7332,7333],{},"    \"\"\"List all saved development notes\"\"\"\n",[407,7335,7336],{"class":409,"line":5461},[407,7337,7338],{},"    return json.dumps(_read(), indent=2)\n",[407,7340,7341],{"class":409,"line":5470},[407,7342,445],{"emptyLinePlaceholder":444},[407,7344,7345],{"class":409,"line":5493},[407,7346,7347],{},"@mcp.prompt()\n",[407,7349,7350],{"class":409,"line":5512},[407,7351,7352],{},"def summarize_project(project_name: str) -> str:\n",[407,7354,7355],{"class":409,"line":5544},[407,7356,7357],{},"    \"\"\"Summarize all notes for a project\"\"\"\n",[407,7359,7360],{"class":409,"line":5549},[407,7361,7362],{},"    return f'Read all notes and summarize project \"{project_name}\". Group by topic, highlight open issues.'\n",[407,7364,7365],{"class":409,"line":5583},[407,7366,445],{"emptyLinePlaceholder":444},[407,7368,7369],{"class":409,"line":5600},[407,7370,7371],{},"if __name__ == \"__main__\":\n",[407,7373,7374],{"class":409,"line":5616},[407,7375,7376],{},"    mcp.run()\n",[17,7378,7379,7380,7383,7384,7387,7388,7391],{},"La magia di FastMCP: il ",[24,7381,7382],{},"nome della funzione"," diventa il nome del tool, il ",[24,7385,7386],{},"docstring"," diventa la descrizione per l'LLM, e i ",[24,7389,7390],{},"type hint"," generano automaticamente il JSON Schema. Zero boilerplate.",[17,7393,7394],{},"Per testarlo:",[346,7396,7398],{"className":401,"code":7397,"language":403,"meta":355,"style":355},"# Con l'Inspector\nmcp dev server.py\n\n# Installa in Claude Desktop con un comando\nmcp install server.py\n",[353,7399,7400,7405,7416,7420,7425],{"__ignoreMap":355},[407,7401,7402],{"class":409,"line":410},[407,7403,7404],{"class":413},"# Con l'Inspector\n",[407,7406,7407,7410,7413],{"class":409,"line":417},[407,7408,7409],{"class":420},"mcp",[407,7411,7412],{"class":424}," dev",[407,7414,7415],{"class":424}," server.py\n",[407,7417,7418],{"class":409,"line":441},[407,7419,445],{"emptyLinePlaceholder":444},[407,7421,7422],{"class":409,"line":448},[407,7423,7424],{"class":413},"# Installa in Claude Desktop con un comando\n",[407,7426,7427,7429,7431],{"class":409,"line":454},[407,7428,7409],{"class":420},[407,7430,4743],{"class":424},[407,7432,7415],{"class":424},[35,7434],{},[38,7436,7438],{"id":7437},"_5-trappole-che-ti-morderanno","5 Trappole che Ti Morderanno",[58,7440,7442,7443,7446],{"id":7441},"_1-consolelog-uccide-il-server","1. ",[353,7444,7445],{},"console.log()"," uccide il server",[17,7448,7449,7450,7453,7454,7457],{},"Il transport ",[24,7451,7452],{},"stdio"," usa stdout per i messaggi JSON-RPC. Se fai ",[353,7455,7456],{},"console.log(\"debug\")",", quel testo si mischia ai messaggi del protocollo e corrompe tutto. Il server muore senza errori chiari.",[17,7459,7460,7463,7464,7467,7468,7471,7472,688],{},[24,7461,7462],{},"Soluzione",": usa ",[353,7465,7466],{},"console.error()"," per il debug (va su stderr, che è separato). In Python, ",[353,7469,7470],{},"print(..., file=sys.stderr)"," o il modulo ",[353,7473,7474],{},"logging",[17,7476,7477],{},"Questa è la trappola numero uno. Ogni developer ci casca almeno una volta.",[58,7479,7481],{"id":7480},"_2-sse-è-deprecato","2. SSE è deprecato",[17,7483,7484,7485,7488,7489,7492,7493,7496],{},"Se trovi tutorial che usano ",[353,7486,7487],{},"SSEServerTransport",", sono outdated. Dal spec ",[24,7490,7491],{},"2025-06-18",", il transport remoto standard è ",[24,7494,7495],{},"Streamable HTTP"," — un singolo endpoint HTTP che supporta POST, GET e SSE opzionale per lo streaming.",[17,7498,7499],{},"SSE funziona ancora per backward compatibility, ma le nuove implementazioni devono usare Streamable HTTP.",[58,7501,7503],{"id":7502},"_3-le-descrizioni-dei-tool-contano-più-di-quanto-pensi","3. Le descrizioni dei tool contano più di quanto pensi",[17,7505,7506,7507,7510],{},"L'LLM decide ",[24,7508,7509],{},"quale tool usare e con quali parametri"," basandosi quasi interamente sulla descrizione e sullo schema. Una descrizione vaga porta a invocazioni sbagliate.",[17,7512,7513,7514,7517],{},"Cattivo: ",[353,7515,7516],{},"\"Search notes\""," — troppo generico.",[17,7519,7520,7521,7524],{},"Buono: ",[353,7522,7523],{},"\"Search notes by keyword in title/content, optionally filter by tag\""," — l'LLM sa esattamente cosa può fare e quali parametri sono opzionali.",[58,7526,7528],{"id":7527},"_4-mai-fidarsi-dellinput-generato-dallllm","4. Mai fidarsi dell'input generato dall'LLM",[17,7530,7531,7532,7535],{},"Il tuo server riceve input dal modello AI, non dall'utente. Questo significa che è vulnerabile a ",[24,7533,7534],{},"prompt injection indiretta",": un utente malintenzionato potrebbe inserire istruzioni nei dati che il modello elabora, manipolando i parametri che il modello invia al tuo tool.",[17,7537,7538,7539,7541,7542,7545,7546,7549],{},"Se il tuo tool esegue query SQL, usa ",[24,7540,2137],{}," query parametrizzate. Mai string concatenation. Mai ",[353,7543,7544],{},"eval()",". Mai ",[353,7547,7548],{},"exec()",". Tratta l'input come untrusted — perché lo è.",[58,7551,7553],{"id":7552},"_5-auto-approval-è-un-rischio-reale","5. Auto-approval è un rischio reale",[17,7555,7556,7557,7560],{},"Nei test di Invariant Labs, il ",[24,7558,7559],{},"tool poisoning"," — server malevoli che inseriscono istruzioni nascoste nei metadati dei tool — ha avuto un tasso di successo dell'84.2% quando l'auto-approval era attivo.",[17,7562,7563,7564,7567],{},"La regola: ",[24,7565,7566],{},"conferma manualmente"," le azioni dei server MCP che non hai scritto tu. Soprattutto quelli che toccano filesystem, database o API con credenziali.",[35,7569],{},[38,7571,7573],{"id":7572},"transport-locale-vs-remoto","Transport: Locale vs Remoto",[17,7575,7576,7577,7579],{},"Per il nostro server Dev Notes, il transport ",[24,7578,7452],{}," è perfetto: gira sulla tua macchina, un solo client alla volta, zero configurazione di rete.",[17,7581,7582,7583,1894],{},"Ma se vuoi esporre un server a più utenti o deployarlo in cloud, serve ",[24,7584,7495],{},[346,7586,7588],{"className":3850,"code":7587,"language":3852,"meta":355,"style":355},"import { StreamableHTTPServerTransport } from\n  \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport express from \"express\";\n\nconst app = express();\napp.use(express.json());\n\napp.post(\"/mcp\", async (req, res) => {\n  const transport = new StreamableHTTPServerTransport({\n    sessionIdGenerator: () => crypto.randomUUID()\n  });\n  await server.connect(transport);\n  await transport.handleRequest(req, res);\n});\n\napp.listen(3000, () => {\n  console.error(\"MCP server running on http://localhost:3000/mcp\");\n});\n",[353,7589,7590,7600,7607,7621,7625,7639,7655,7659,7691,7707,7724,7729,7739,7752,7756,7760,7779,7794],{"__ignoreMap":355},[407,7591,7592,7594,7597],{"class":409,"line":410},[407,7593,4974],{"class":3864},[407,7595,7596],{"class":2201}," { StreamableHTTPServerTransport } ",[407,7598,7599],{"class":3864},"from\n",[407,7601,7602,7605],{"class":409,"line":417},[407,7603,7604],{"class":424},"  \"@modelcontextprotocol/sdk/server/streamableHttp.js\"",[407,7606,4986],{"class":2201},[407,7608,7609,7611,7614,7616,7619],{"class":409,"line":441},[407,7610,4974],{"class":3864},[407,7612,7613],{"class":2201}," express ",[407,7615,4980],{"class":3864},[407,7617,7618],{"class":424}," \"express\"",[407,7620,4986],{"class":2201},[407,7622,7623],{"class":409,"line":448},[407,7624,445],{"emptyLinePlaceholder":444},[407,7626,7627,7629,7632,7634,7637],{"class":409,"line":454},[407,7628,5056],{"class":3864},[407,7630,7631],{"class":434}," app",[407,7633,5062],{"class":3864},[407,7635,7636],{"class":420}," express",[407,7638,5597],{"class":2201},[407,7640,7641,7644,7647,7650,7652],{"class":409,"line":1667},[407,7642,7643],{"class":2201},"app.",[407,7645,7646],{"class":420},"use",[407,7648,7649],{"class":2201},"(express.",[407,7651,2194],{"class":420},[407,7653,7654],{"class":2201},"());\n",[407,7656,7657],{"class":409,"line":1673},[407,7658,445],{"emptyLinePlaceholder":444},[407,7660,7661,7663,7666,7668,7671,7673,7675,7677,7680,7682,7685,7687,7689],{"class":409,"line":1679},[407,7662,7643],{"class":2201},[407,7664,7665],{"class":420},"post",[407,7667,5216],{"class":2201},[407,7669,7670],{"class":424},"\"/mcp\"",[407,7672,2078],{"class":2201},[407,7674,5164],{"class":3864},[407,7676,1486],{"class":2201},[407,7678,7679],{"class":3876},"req",[407,7681,2078],{"class":2201},[407,7683,7684],{"class":3876},"res",[407,7686,6395],{"class":2201},[407,7688,5574],{"class":3864},[407,7690,3871],{"class":2201},[407,7692,7693,7696,7698,7700,7702,7705],{"class":409,"line":1685},[407,7694,7695],{"class":3864},"  const",[407,7697,5787],{"class":434},[407,7699,5062],{"class":3864},[407,7701,5379],{"class":3864},[407,7703,7704],{"class":420}," StreamableHTTPServerTransport",[407,7706,5385],{"class":2201},[407,7708,7709,7712,7715,7717,7720,7722],{"class":409,"line":1690},[407,7710,7711],{"class":420},"    sessionIdGenerator",[407,7713,7714],{"class":2201},": () ",[407,7716,5574],{"class":3864},[407,7718,7719],{"class":2201}," crypto.",[407,7721,5622],{"class":420},[407,7723,5669],{"class":2201},[407,7725,7726],{"class":409,"line":1696},[407,7727,7728],{"class":2201},"  });\n",[407,7730,7731,7733,7735,7737],{"class":409,"line":1702},[407,7732,5312],{"class":3864},[407,7734,5805],{"class":2201},[407,7736,5808],{"class":420},[407,7738,5811],{"class":2201},[407,7740,7741,7743,7746,7749],{"class":409,"line":1708},[407,7742,5312],{"class":3864},[407,7744,7745],{"class":2201}," transport.",[407,7747,7748],{"class":420},"handleRequest",[407,7750,7751],{"class":2201},"(req, res);\n",[407,7753,7754],{"class":409,"line":1714},[407,7755,5411],{"class":2201},[407,7757,7758],{"class":409,"line":1719},[407,7759,445],{"emptyLinePlaceholder":444},[407,7761,7762,7764,7767,7769,7772,7775,7777],{"class":409,"line":1725},[407,7763,7643],{"class":2201},[407,7765,7766],{"class":420},"listen",[407,7768,5216],{"class":2201},[407,7770,7771],{"class":434},"3000",[407,7773,7774],{"class":2201},", () ",[407,7776,5574],{"class":3864},[407,7778,3871],{"class":2201},[407,7780,7781,7784,7787,7789,7792],{"class":409,"line":1278},[407,7782,7783],{"class":2201},"  console.",[407,7785,7786],{"class":420},"error",[407,7788,5216],{"class":2201},[407,7790,7791],{"class":424},"\"MCP server running on http://localhost:3000/mcp\"",[407,7793,5083],{"class":2201},[407,7795,7796],{"class":409,"line":1736},[407,7797,5411],{"class":2201},[17,7799,7800,7801,7803,7804,7806],{},"Notare: ",[353,7802,7466],{},", non ",[353,7805,7445],{},". Ormai lo sai.",[244,7808,7809,7819],{},[247,7810,7811],{},[250,7812,7813,7816],{},[253,7814,7815],{},"Transport",[253,7817,7818],{},"Quando usarlo",[260,7820,7821,7830],{},[250,7822,7823,7827],{},[265,7824,7825],{},[24,7826,7452],{},[265,7828,7829],{},"Server locale, tool personali, sviluppo",[250,7831,7832,7836],{},[265,7833,7834],{},[24,7835,7495],{},[265,7837,7838],{},"Server remoto, multi-client, cloud, team",[35,7840],{},[38,7842,7844],{"id":7843},"da-qui-in-poi","Da Qui in Poi",[17,7846,7847],{},"Hai un MCP server funzionante. Ecco dove andare:",[17,7849,7850],{},[24,7851,7852],{},"Estendi il server Dev Notes:",[82,7854,7855,7864,7867],{},[85,7856,7857,7858,4055,7861],{},"Aggiungi un tool ",[353,7859,7860],{},"delete_note",[353,7862,7863],{},"update_note",[85,7865,7866],{},"Usa SQLite invece di JSON per performance migliori",[85,7868,7869,7870,6250],{},"Aggiungi resource template con URI parametrici (",[353,7871,7872],{},"notes://tag/{tagName}",[17,7874,7875],{},[24,7876,7877],{},"Esplora l'ecosistema:",[82,7879,7880,7888,7896],{},[85,7881,7882,7887],{},[69,7883,7886],{"href":7884,"rel":7885},"https://github.com/modelcontextprotocol/servers",[1152],"Server ufficiali"," — filesystem, GitHub, PostgreSQL, Slack, Puppeteer e altri",[85,7889,7890,7895],{},[69,7891,7894],{"href":7892,"rel":7893},"https://www.pulsemcp.com/servers",[1152],"PulseMCP"," — directory di 8.600+ server community",[85,7897,7898,7903],{},[69,7899,7902],{"href":7900,"rel":7901},"https://registry.modelcontextprotocol.io/",[1152],"MCP Registry"," — il registry ufficiale per discovery e installazione",[17,7905,7906],{},[24,7907,7908],{},"Vai più a fondo:",[82,7910,7911,7919,7927],{},[85,7912,7913,7918],{},[69,7914,7917],{"href":7915,"rel":7916},"https://modelcontextprotocol.io/specification/2025-11-25",[1152],"Specifiche complete MCP"," — la versione più recente del protocollo",[85,7920,7921,7926],{},[69,7922,7925],{"href":7923,"rel":7924},"https://modelcontextprotocol.io/specification/draft/basic/security_best_practices",[1152],"Security best practices"," — autenticazione OAuth 2.1, PKCE, gestione credenziali",[85,7928,7929,4055,7934,7939],{},[69,7930,7933],{"href":7931,"rel":7932},"https://github.com/modelcontextprotocol/typescript-sdk",[1152],"SDK TypeScript",[69,7935,7938],{"href":7936,"rel":7937},"https://github.com/modelcontextprotocol/python-sdk",[1152],"SDK Python"," — documentazione completa",[17,7941,7942,7943,7946],{},"L'ecosistema MCP è esploso da 100 a 16.000 server in poco più di un anno. La curva di apprendimento per costruire un server è bassa — come hai visto, bastano 25 righe in Python. La parte difficile non è il codice: è capire ",[24,7944,7945],{},"quale problema risolvere"," e scrivere descrizioni che guidino il modello nel modo giusto.",[17,7948,7949,7950],{},"Il prossimo tool che ti trovi a usare manualmente — query al database, ricerca nei log, gestione di ticket — chiediti: ",[2128,7951,7952],{},"\"Potrebbe essere un MCP server?\"",[17,7954,7955],{},"La risposta, sempre più spesso, è sì.",[35,7957],{},[17,7959,7960,1894],{},[24,7961,2664],{},[82,7963,7964,7972,7980,7988,7996,8003,8009,8017,8025],{},[85,7965,7966,7971],{},[69,7967,7970],{"href":7968,"rel":7969},"https://modelcontextprotocol.io/",[1152],"Documentazione ufficiale MCP"," — Specifiche, tutorial, esempi",[85,7973,7974,7977,7978],{},[69,7975,7933],{"href":7931,"rel":7976},[1152]," — Il pacchetto ",[353,7979,4705],{},[85,7981,7982,7985,7986],{},[69,7983,7938],{"href":7936,"rel":7984},[1152]," — FastMCP e il pacchetto ",[353,7987,7409],{},[85,7989,7990,7995],{},[69,7991,7994],{"href":7992,"rel":7993},"https://modelcontextprotocol.io/docs/tools/inspector",[1152],"MCP Inspector"," — Lo strumento di debug per MCP",[85,7997,7998,8002],{},[69,7999,8001],{"href":7884,"rel":8000},[1152],"Server Repository"," — Server ufficiali di riferimento",[85,8004,8005,8008],{},[69,8006,7894],{"href":7892,"rel":8007},[1152]," — Directory di 8.600+ server community",[85,8010,8011,8016],{},[69,8012,8015],{"href":8013,"rel":8014},"https://invariantlabs.ai/blog/mcp-security-notification-tool-poisoning-attacks",[1152],"Invariant Labs - Tool Poisoning"," — Analisi sicurezza tool poisoning",[85,8018,8019,8024],{},[69,8020,8023],{"href":8021,"rel":8022},"https://modelcontextprotocol.io/specification/2025-06-18/basic/transports",[1152],"Transports Specification"," — stdio vs Streamable HTTP",[85,8026,8027,8030],{},[69,8028,8029],{"href":4545},"MCP: Cos'è e Come Ha Cambiato l'AI in 12 Mesi"," — Il nostro articolo teorico su MCP",[1218,8032,8033],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":355,"searchDepth":417,"depth":417,"links":8035},[8036,8037,8038,8039,8040,8041,8042,8043,8049,8050,8058,8059],{"id":4569,"depth":417,"text":4570},{"id":4698,"depth":417,"text":4699},{"id":4957,"depth":417,"text":4958},{"id":5866,"depth":417,"text":5867},{"id":6336,"depth":417,"text":6337},{"id":6552,"depth":417,"text":6553},{"id":6670,"depth":417,"text":6671},{"id":6760,"depth":417,"text":6761,"children":8044},[8045,8046,8047,8048],{"id":6767,"depth":441,"text":6768},{"id":6866,"depth":441,"text":1287},{"id":6951,"depth":441,"text":6952},{"id":7016,"depth":441,"text":2294},{"id":7091,"depth":417,"text":7092},{"id":7437,"depth":417,"text":7438,"children":8051},[8052,8054,8055,8056,8057],{"id":7441,"depth":441,"text":8053},"1. console.log() uccide il server",{"id":7480,"depth":441,"text":7481},{"id":7502,"depth":441,"text":7503},{"id":7527,"depth":441,"text":7528},{"id":7552,"depth":441,"text":7553},{"id":7572,"depth":417,"text":7573},{"id":7843,"depth":417,"text":7844},"Tutorial","Come costruire un MCP server in TypeScript e Python, testarlo con l'Inspector e collegarlo a Claude Desktop, Claude Code e Cursor. Step by step.","/images/guides/costruire-mcp-server-guida-pratica.webp",{},"/guides/costruire-mcp-server-guida-pratica","2026-02-26",{"title":4533,"description":8061},"guides/costruire-mcp-server-guida-pratica",[4528,8069,8070,8071,8060,1287],"Model Context Protocol","TypeScript","Python","JHOZOAPi3QbagVheS7arIUx7-P8_kNiESsFcOQz2n4c",[8074,13177,14251,15572,18355,19208,20020],{"id":8075,"title":8076,"author":8077,"body":8078,"category":8060,"contentType":1269,"description":13164,"difficulty":2768,"extension":1272,"featured":1273,"icon":1269,"image":13165,"meta":13166,"navigation":444,"path":13167,"publishedAt":13168,"readingTime":1736,"seo":13169,"stem":13170,"steps":1269,"tags":13171,"youtubeId":1269,"__hash__":13176},"guides/guides/_telegram-bot-assistente-personale-claude-api.md","Telegram Bot Assistente Personale con Claude API",{"name":7,"initials":8},{"type":10,"value":8079,"toc":13137},[8080,8083,8086,8089,8096,8098,8100,8103,8109,8112,8142,8149,8151,8155,8162,8206,8213,8224,8226,8230,8233,8290,8304,8309,8414,8420,8474,8479,8514,8517,8522,8528,8531,8537,8539,8543,8550,9358,9361,9376,9379,9382,9384,9388,9391,9394,9399,10809,10816,10823,10829,10831,10835,10838,10845,10851,11454,11457,11464,11466,11470,11473,11479,11486,12236,12246,12249,12261,12270,12272,12276,12279,12283,12289,12295,12302,12305,12369,12373,12418,12425,12429,12432,12504,12518,12520,12524,12527,12533,12537,12591,12665,12668,12672,12714,12718,12787,12790,12792,12796,12799,12802,12808,12815,12822,12824,12828,12831,12835,12844,13010,13014,13021,13025,13028,13045,13048,13052,13066,13070,13077,13079,13083,13134],[13,8081,8076],{"id":8082},"telegram-bot-assistente-personale-con-claude-api",[17,8084,8085],{},"ChatGPT Plus costa $20 al mese. Con $10-16 ti costruisci un assistente AI su Telegram che fa le stesse cose -- e anche di piu'. Analizzi immagini, personalizzi il system prompt, scegli il modello, tieni traccia dei costi. Tutto dal telefono, nella chat che usi gia' ogni giorno.",[17,8087,8088],{},"Non e' teoria. In questa guida costruiamo un bot funzionante, step by step, da zero al deploy. TypeScript, Telegraf, Claude API. Codice copiabile, pronto da far girare.",[17,8090,8091,8092,8095],{},"Telegram ha superato il miliardo di utenti mensili e ospita oltre 10 milioni di bot. Con la Bot API 9.5 di marzo 2026, lo streaming delle risposte AI e' diventato nativo -- niente piu' workaround con ",[353,8093,8094],{},"editMessageText",". Il timing per costruirsi il proprio assistente non e' mai stato migliore.",[35,8097],{},[38,8099,4570],{"id":4569},[17,8101,8102],{},"L'architettura e' volutamente semplice. Un file TypeScript, tre servizi esterni, zero infrastruttura da gestire.",[346,8104,8107],{"className":8105,"code":8106,"language":351},[349],"Telegram App (telefono/desktop)\n      |\n      v\nTelegram Bot API  \u003C-->  Il nostro bot (Node.js + Telegraf)\n                              |\n                              v\n                        Claude API (Anthropic SDK)\n                              |\n                              v\n                    Memoria conversazione (in-memory)\n",[353,8108,8106],{"__ignoreMap":355},[17,8110,8111],{},"Il bot fa quattro cose:",[517,8113,8114,8120,8126,8132],{},[85,8115,8116,8119],{},[24,8117,8118],{},"Risponde ai messaggi di testo"," usando Claude Haiku 4.5 come cervello",[85,8121,8122,8125],{},[24,8123,8124],{},"Mantiene la memoria"," della conversazione (contesto dei messaggi precedenti)",[85,8127,8128,8131],{},[24,8129,8130],{},"Analizza immagini"," che gli invii (Claude e' multimodale)",[85,8133,8134,8137,8138,8141],{},[24,8135,8136],{},"Fa streaming"," delle risposte grazie a ",[353,8139,8140],{},"sendMessageDraft"," (Bot API 9.5)",[17,8143,8144,8145,8148],{},"Tutto in un singolo file ",[353,8146,8147],{},"bot.ts",". Non stiamo costruendo un monorepo -- stiamo costruendo qualcosa che funziona e che puoi estendere dopo.",[35,8150],{},[38,8152,8154],{"id":8153},"step-1-creare-il-bot-su-telegram","Step 1: Creare il Bot su Telegram",[17,8156,8157,8158,8161],{},"Prima di scrivere codice, serve il bot. La procedura passa da ",[24,8159,8160],{},"@BotFather",", il bot ufficiale di Telegram per creare altri bot.",[517,8163,8164,8170,8176,8183,8200],{},[85,8165,8166,8167,8169],{},"Apri Telegram e cerca ",[24,8168,8160],{}," (ha la spunta blu di verifica)",[85,8171,8172,8173],{},"Invia ",[353,8174,8175],{},"/newbot",[85,8177,8178,8179,8182],{},"Scegli un ",[24,8180,8181],{},"nome display"," -- quello che vedono gli utenti (es. \"Jarvis AI\")",[85,8184,8178,8185,8188,8189,8192,8193,8196,8197,6250],{},[24,8186,8187],{},"username"," che finisca con ",[353,8190,8191],{},"bot"," o ",[353,8194,8195],{},"_bot"," (es. ",[353,8198,8199],{},"jarvis_ai_bot",[85,8201,8202,8203],{},"BotFather ti restituisce il ",[24,8204,8205],{},"token API",[17,8207,8208,8209,8212],{},"Il token ha questo formato: ",[353,8210,8211],{},"123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11",". Copialo e salvalo. Non condividerlo, non committarlo nel codice. Mai.",[17,8214,8215,8216,8219,8220,8223],{},"Opzionale ma consigliato: invia a BotFather anche ",[353,8217,8218],{},"/setdescription"," per aggiungere una descrizione e ",[353,8221,8222],{},"/setuserpic"," per dare un avatar al bot.",[35,8225],{},[38,8227,8229],{"id":8228},"step-2-setup-del-progetto","Step 2: Setup del Progetto",[17,8231,8232],{},"Creiamo il progetto Node.js con TypeScript e le dipendenze necessarie.",[346,8234,8236],{"className":401,"code":8235,"language":403,"meta":355,"style":355},"mkdir telegram-claude-bot\ncd telegram-claude-bot\nnpm init -y\nnpm install telegraf @anthropic-ai/sdk dotenv\nnpm install -D typescript @types/node tsx\n",[353,8237,8238,8245,8251,8259,8274],{"__ignoreMap":355},[407,8239,8240,8242],{"class":409,"line":410},[407,8241,4715],{"class":420},[407,8243,8244],{"class":424}," telegram-claude-bot\n",[407,8246,8247,8249],{"class":409,"line":417},[407,8248,4723],{"class":434},[407,8250,8244],{"class":424},[407,8252,8253,8255,8257],{"class":409,"line":441},[407,8254,4730],{"class":420},[407,8256,4733],{"class":424},[407,8258,4736],{"class":434},[407,8260,8261,8263,8265,8268,8271],{"class":409,"line":448},[407,8262,4730],{"class":420},[407,8264,4743],{"class":424},[407,8266,8267],{"class":424}," telegraf",[407,8269,8270],{"class":424}," @anthropic-ai/sdk",[407,8272,8273],{"class":424}," dotenv\n",[407,8275,8276,8278,8280,8282,8285,8287],{"class":409,"line":454},[407,8277,4730],{"class":420},[407,8279,4743],{"class":424},[407,8281,4758],{"class":434},[407,8283,8284],{"class":424}," typescript",[407,8286,4761],{"class":424},[407,8288,8289],{"class":424}," tsx\n",[17,8291,8292,8295,8296,8299,8300,8303],{},[24,8293,8294],{},"Telegraf"," e' la libreria Telegram piu' solida per Node.js: 9.1K stars su GitHub, TypeScript nativo, architettura a middleware tipo Express. ",[24,8297,8298],{},"@anthropic-ai/sdk"," e' l'SDK ufficiale di Anthropic. ",[24,8301,8302],{},"tsx"," ci permette di eseguire TypeScript direttamente senza compilazione.",[17,8305,8306,8307,1894],{},"Crea il file ",[353,8308,4770],{},[346,8310,8312],{"className":2192,"code":8311,"language":2194,"meta":355,"style":355},"{\n  \"compilerOptions\": {\n    \"target\": \"ES2022\",\n    \"module\": \"ES2022\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"outDir\": \"./dist\",\n    \"rootDir\": \"./src\"\n  },\n  \"include\": [\"src\"]\n}\n",[353,8313,8314,8318,8324,8334,8344,8355,8365,8375,8386,8395,8399,8410],{"__ignoreMap":355},[407,8315,8316],{"class":409,"line":410},[407,8317,2202],{"class":2201},[407,8319,8320,8322],{"class":409,"line":417},[407,8321,4784],{"class":434},[407,8323,2210],{"class":2201},[407,8325,8326,8328,8330,8332],{"class":409,"line":441},[407,8327,4791],{"class":434},[407,8329,2225],{"class":2201},[407,8331,4796],{"class":424},[407,8333,3384],{"class":2201},[407,8335,8336,8338,8340,8342],{"class":409,"line":448},[407,8337,4803],{"class":434},[407,8339,2225],{"class":2201},[407,8341,4796],{"class":424},[407,8343,3384],{"class":2201},[407,8345,8346,8348,8350,8353],{"class":409,"line":454},[407,8347,4815],{"class":434},[407,8349,2225],{"class":2201},[407,8351,8352],{"class":424},"\"bundler\"",[407,8354,3384],{"class":2201},[407,8356,8357,8359,8361,8363],{"class":409,"line":1667},[407,8358,4850],{"class":434},[407,8360,2225],{"class":2201},[407,8362,4855],{"class":434},[407,8364,3384],{"class":2201},[407,8366,8367,8369,8371,8373],{"class":409,"line":1673},[407,8368,4862],{"class":434},[407,8370,2225],{"class":2201},[407,8372,4855],{"class":434},[407,8374,3384],{"class":2201},[407,8376,8377,8379,8381,8384],{"class":409,"line":1679},[407,8378,4826],{"class":434},[407,8380,2225],{"class":2201},[407,8382,8383],{"class":424},"\"./dist\"",[407,8385,3384],{"class":2201},[407,8387,8388,8390,8392],{"class":409,"line":1685},[407,8389,4838],{"class":434},[407,8391,2225],{"class":2201},[407,8393,8394],{"class":424},"\"./src\"\n",[407,8396,8397],{"class":409,"line":1690},[407,8398,4872],{"class":2201},[407,8400,8401,8403,8405,8408],{"class":409,"line":1696},[407,8402,4877],{"class":434},[407,8404,3392],{"class":2201},[407,8406,8407],{"class":424},"\"src\"",[407,8409,3398],{"class":2201},[407,8411,8412],{"class":409,"line":1702},[407,8413,2243],{"class":2201},[17,8415,8416,8417,8419],{},"Aggiorna il ",[353,8418,4894],{}," aggiungendo lo script per avviare il bot:",[346,8421,8423],{"className":2192,"code":8422,"language":2194,"meta":355,"style":355},"{\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"tsx watch src/bot.ts\",\n    \"start\": \"tsx src/bot.ts\"\n  }\n}\n",[353,8424,8425,8429,8439,8445,8457,8466,8470],{"__ignoreMap":355},[407,8426,8427],{"class":409,"line":410},[407,8428,2202],{"class":2201},[407,8430,8431,8433,8435,8437],{"class":409,"line":417},[407,8432,4908],{"class":434},[407,8434,2225],{"class":2201},[407,8436,4913],{"class":424},[407,8438,3384],{"class":2201},[407,8440,8441,8443],{"class":409,"line":441},[407,8442,4920],{"class":434},[407,8444,2210],{"class":2201},[407,8446,8447,8450,8452,8455],{"class":409,"line":448},[407,8448,8449],{"class":434},"    \"dev\"",[407,8451,2225],{"class":2201},[407,8453,8454],{"class":424},"\"tsx watch src/bot.ts\"",[407,8456,3384],{"class":2201},[407,8458,8459,8461,8463],{"class":409,"line":454},[407,8460,4939],{"class":434},[407,8462,2225],{"class":2201},[407,8464,8465],{"class":424},"\"tsx src/bot.ts\"\n",[407,8467,8468],{"class":409,"line":1667},[407,8469,2238],{"class":2201},[407,8471,8472],{"class":409,"line":1673},[407,8473,2243],{"class":2201},[17,8475,8306,8476,6959],{},[353,8477,8478],{},".env",[346,8480,8482],{"className":401,"code":8481,"language":403,"meta":355,"style":355},"TELEGRAM_BOT_TOKEN=il-tuo-token-da-botfather\nANTHROPIC_API_KEY=sk-ant-api03-il-tuo-token\nALLOWED_USER_IDS=il-tuo-user-id-telegram\n",[353,8483,8484,8494,8504],{"__ignoreMap":355},[407,8485,8486,8489,8491],{"class":409,"line":410},[407,8487,8488],{"class":2201},"TELEGRAM_BOT_TOKEN",[407,8490,6014],{"class":3864},[407,8492,8493],{"class":424},"il-tuo-token-da-botfather\n",[407,8495,8496,8499,8501],{"class":409,"line":417},[407,8497,8498],{"class":2201},"ANTHROPIC_API_KEY",[407,8500,6014],{"class":3864},[407,8502,8503],{"class":424},"sk-ant-api03-il-tuo-token\n",[407,8505,8506,8509,8511],{"class":409,"line":441},[407,8507,8508],{"class":2201},"ALLOWED_USER_IDS",[407,8510,6014],{"class":3864},[407,8512,8513],{"class":424},"il-tuo-user-id-telegram\n",[17,8515,8516],{},"Per trovare il tuo user ID Telegram, usa un bot come @userinfobot -- gli scrivi e ti risponde con il tuo ID numerico.",[17,8518,8519,8520,1894],{},"E ovviamente, il ",[353,8521,1474],{},[346,8523,8526],{"className":8524,"code":8525,"language":351},[349],"node_modules/\n.env\ndist/\n",[353,8527,8525],{"__ignoreMap":355},[17,8529,8530],{},"Struttura del progetto:",[346,8532,8535],{"className":8533,"code":8534,"language":351},[349],"telegram-claude-bot/\n├── src/\n│   └── bot.ts\n├── .env\n├── .gitignore\n├── package.json\n└── tsconfig.json\n",[353,8536,8534],{"__ignoreMap":355},[35,8538],{},[38,8540,8542],{"id":8541},"step-3-il-bot-base-con-claude","Step 3: Il Bot Base con Claude",[17,8544,8545,8546,8549],{},"Ora il pezzo centrale. Creiamo ",[353,8547,8548],{},"src/bot.ts"," con la struttura base: il bot riceve un messaggio, lo manda a Claude, e risponde.",[346,8551,8553],{"className":3850,"code":8552,"language":3852,"meta":355,"style":355},"import \"dotenv/config\";\nimport { Telegraf } from \"telegraf\";\nimport Anthropic from \"@anthropic-ai/sdk\";\n\n// --- Configurazione ---\n\nconst bot = new Telegraf(process.env.TELEGRAM_BOT_TOKEN!);\nconst claude = new Anthropic(); // legge ANTHROPIC_API_KEY da env\n\nconst ALLOWED_USERS = new Set(\n  (process.env.ALLOWED_USER_IDS || \"\").split(\",\").map(Number)\n);\n\nconst SYSTEM_PROMPT = `Sei Jarvis, l'assistente personale di un developer.\n\nRUOLO: Assistente competente, conciso e proattivo.\n\nREGOLE:\n- Rispondi in italiano a meno che non ti si chieda diversamente\n- Sii conciso: Telegram non e' il posto per muri di testo\n- Usa formattazione Markdown quando aiuta la leggibilita'\n- Se non sai qualcosa, dillo chiaramente\n- Per il codice, usa i code block con il linguaggio specificato`;\n\nconst MODEL = \"claude-haiku-4-5-20251001\";\nconst MAX_TOKENS = 2048;\n\n// --- Sicurezza: whitelist utenti ---\n\nfunction isAllowed(userId: number): boolean {\n  if (ALLOWED_USERS.size === 0) return true; // nessun filtro se lista vuota\n  return ALLOWED_USERS.has(userId);\n}\n\n// --- Handler messaggi di testo ---\n\nbot.on(\"text\", async (ctx) => {\n  const userId = ctx.from.id;\n\n  if (!isAllowed(userId)) {\n    await ctx.reply(\"Non sei autorizzato a usare questo bot.\");\n    return;\n  }\n\n  const userMessage = ctx.message.text;\n\n  try {\n    // Indicatore \"sta scrivendo...\"\n    await ctx.sendChatAction(\"typing\");\n\n    const response = await claude.messages.create({\n      model: MODEL,\n      max_tokens: MAX_TOKENS,\n      system: SYSTEM_PROMPT,\n      messages: [{ role: \"user\", content: userMessage }],\n    });\n\n    const reply = response.content[0];\n    if (reply.type === \"text\") {\n      await ctx.reply(reply.text, { parse_mode: \"Markdown\" });\n    }\n  } catch (error) {\n    console.error(\"Errore Claude API:\", error);\n    await ctx.reply(\"Errore nella risposta. Riprova tra qualche secondo.\");\n  }\n});\n\n// --- Avvio ---\n\nbot.command(\"start\", (ctx) =>\n  ctx.reply(\"Ciao! Sono Jarvis, il tuo assistente AI. Scrivimi qualcosa.\")\n);\n\nbot.launch();\nconsole.log(\"Bot avviato!\");\n\n// Graceful shutdown\nprocess.once(\"SIGINT\", () => bot.stop(\"SIGINT\"));\nprocess.once(\"SIGTERM\", () => bot.stop(\"SIGTERM\"));\n",[353,8554,8555,8564,8578,8592,8596,8601,8605,8629,8649,8653,8669,8700,8704,8708,8720,8724,8729,8733,8738,8743,8748,8753,8758,8765,8769,8783,8797,8801,8806,8810,8837,8868,8883,8887,8891,8896,8900,8927,8939,8943,8957,8974,8980,8984,8988,9000,9004,9010,9015,9031,9035,9054,9064,9074,9084,9094,9099,9103,9121,9135,9153,9157,9166,9181,9196,9200,9204,9208,9213,9217,9240,9255,9260,9265,9275,9291,9296,9302,9332],{"__ignoreMap":355},[407,8556,8557,8559,8562],{"class":409,"line":410},[407,8558,4974],{"class":3864},[407,8560,8561],{"class":424}," \"dotenv/config\"",[407,8563,4986],{"class":2201},[407,8565,8566,8568,8571,8573,8576],{"class":409,"line":417},[407,8567,4974],{"class":3864},[407,8569,8570],{"class":2201}," { Telegraf } ",[407,8572,4980],{"class":3864},[407,8574,8575],{"class":424}," \"telegraf\"",[407,8577,4986],{"class":2201},[407,8579,8580,8582,8585,8587,8590],{"class":409,"line":441},[407,8581,4974],{"class":3864},[407,8583,8584],{"class":2201}," Anthropic ",[407,8586,4980],{"class":3864},[407,8588,8589],{"class":424}," \"@anthropic-ai/sdk\"",[407,8591,4986],{"class":2201},[407,8593,8594],{"class":409,"line":448},[407,8595,445],{"emptyLinePlaceholder":444},[407,8597,8598],{"class":409,"line":454},[407,8599,8600],{"class":413},"// --- Configurazione ---\n",[407,8602,8603],{"class":409,"line":1667},[407,8604,445],{"emptyLinePlaceholder":444},[407,8606,8607,8609,8612,8614,8616,8619,8622,8624,8627],{"class":409,"line":1673},[407,8608,5056],{"class":3864},[407,8610,8611],{"class":434}," bot",[407,8613,5062],{"class":3864},[407,8615,5379],{"class":3864},[407,8617,8618],{"class":420}," Telegraf",[407,8620,8621],{"class":2201},"(process.env.",[407,8623,8488],{"class":434},[407,8625,8626],{"class":3864},"!",[407,8628,5083],{"class":2201},[407,8630,8631,8633,8636,8638,8640,8643,8646],{"class":409,"line":1679},[407,8632,5056],{"class":3864},[407,8634,8635],{"class":434}," claude",[407,8637,5062],{"class":3864},[407,8639,5379],{"class":3864},[407,8641,8642],{"class":420}," Anthropic",[407,8644,8645],{"class":2201},"(); ",[407,8647,8648],{"class":413},"// legge ANTHROPIC_API_KEY da env\n",[407,8650,8651],{"class":409,"line":1685},[407,8652,445],{"emptyLinePlaceholder":444},[407,8654,8655,8657,8660,8662,8664,8667],{"class":409,"line":1690},[407,8656,5056],{"class":3864},[407,8658,8659],{"class":434}," ALLOWED_USERS",[407,8661,5062],{"class":3864},[407,8663,5379],{"class":3864},[407,8665,8666],{"class":420}," Set",[407,8668,5434],{"class":2201},[407,8670,8671,8674,8676,8679,8682,8685,8688,8690,8693,8695,8697],{"class":409,"line":1696},[407,8672,8673],{"class":2201},"  (process.env.",[407,8675,8508],{"class":434},[407,8677,8678],{"class":3864}," ||",[407,8680,8681],{"class":424}," \"\"",[407,8683,8684],{"class":2201},").",[407,8686,8687],{"class":420},"split",[407,8689,5216],{"class":2201},[407,8691,8692],{"class":424},"\",\"",[407,8694,8684],{"class":2201},[407,8696,6212],{"class":420},[407,8698,8699],{"class":2201},"(Number)\n",[407,8701,8702],{"class":409,"line":1702},[407,8703,5083],{"class":2201},[407,8705,8706],{"class":409,"line":1708},[407,8707,445],{"emptyLinePlaceholder":444},[407,8709,8710,8712,8715,8717],{"class":409,"line":1714},[407,8711,5056],{"class":3864},[407,8713,8714],{"class":434}," SYSTEM_PROMPT",[407,8716,5062],{"class":3864},[407,8718,8719],{"class":424}," `Sei Jarvis, l'assistente personale di un developer.\n",[407,8721,8722],{"class":409,"line":1719},[407,8723,445],{"emptyLinePlaceholder":444},[407,8725,8726],{"class":409,"line":1725},[407,8727,8728],{"class":424},"RUOLO: Assistente competente, conciso e proattivo.\n",[407,8730,8731],{"class":409,"line":1278},[407,8732,445],{"emptyLinePlaceholder":444},[407,8734,8735],{"class":409,"line":1736},[407,8736,8737],{"class":424},"REGOLE:\n",[407,8739,8740],{"class":409,"line":1742},[407,8741,8742],{"class":424},"- Rispondi in italiano a meno che non ti si chieda diversamente\n",[407,8744,8745],{"class":409,"line":1748},[407,8746,8747],{"class":424},"- Sii conciso: Telegram non e' il posto per muri di testo\n",[407,8749,8750],{"class":409,"line":1753},[407,8751,8752],{"class":424},"- Usa formattazione Markdown quando aiuta la leggibilita'\n",[407,8754,8755],{"class":409,"line":1759},[407,8756,8757],{"class":424},"- Se non sai qualcosa, dillo chiaramente\n",[407,8759,8760,8763],{"class":409,"line":1765},[407,8761,8762],{"class":424},"- Per il codice, usa i code block con il linguaggio specificato`",[407,8764,4986],{"class":2201},[407,8766,8767],{"class":409,"line":1771},[407,8768,445],{"emptyLinePlaceholder":444},[407,8770,8771,8773,8776,8778,8781],{"class":409,"line":1777},[407,8772,5056],{"class":3864},[407,8774,8775],{"class":434}," MODEL",[407,8777,5062],{"class":3864},[407,8779,8780],{"class":424}," \"claude-haiku-4-5-20251001\"",[407,8782,4986],{"class":2201},[407,8784,8785,8787,8790,8792,8795],{"class":409,"line":1782},[407,8786,5056],{"class":3864},[407,8788,8789],{"class":434}," MAX_TOKENS",[407,8791,5062],{"class":3864},[407,8793,8794],{"class":434}," 2048",[407,8796,4986],{"class":2201},[407,8798,8799],{"class":409,"line":1788},[407,8800,445],{"emptyLinePlaceholder":444},[407,8802,8803],{"class":409,"line":1794},[407,8804,8805],{"class":413},"// --- Sicurezza: whitelist utenti ---\n",[407,8807,8808],{"class":409,"line":5348},[407,8809,445],{"emptyLinePlaceholder":444},[407,8811,8812,8815,8818,8820,8823,8825,8828,8830,8832,8835],{"class":409,"line":5353},[407,8813,8814],{"class":3864},"function",[407,8816,8817],{"class":420}," isAllowed",[407,8819,5216],{"class":2201},[407,8821,8822],{"class":3876},"userId",[407,8824,1894],{"class":3864},[407,8826,8827],{"class":434}," number",[407,8829,6250],{"class":2201},[407,8831,1894],{"class":3864},[407,8833,8834],{"class":434}," boolean",[407,8836,3871],{"class":2201},[407,8838,8839,8842,8844,8847,8850,8852,8854,8856,8859,8862,8865],{"class":409,"line":5358},[407,8840,8841],{"class":3864},"  if",[407,8843,1486],{"class":2201},[407,8845,8846],{"class":434},"ALLOWED_USERS",[407,8848,8849],{"class":2201},".size ",[407,8851,6122],{"class":3864},[407,8853,6159],{"class":434},[407,8855,6395],{"class":2201},[407,8857,8858],{"class":3864},"return",[407,8860,8861],{"class":434}," true",[407,8863,8864],{"class":2201},"; ",[407,8866,8867],{"class":413},"// nessun filtro se lista vuota\n",[407,8869,8870,8873,8875,8877,8880],{"class":409,"line":5364},[407,8871,8872],{"class":3864},"  return",[407,8874,8659],{"class":434},[407,8876,688],{"class":2201},[407,8878,8879],{"class":420},"has",[407,8881,8882],{"class":2201},"(userId);\n",[407,8884,8885],{"class":409,"line":5369},[407,8886,2243],{"class":2201},[407,8888,8889],{"class":409,"line":5388},[407,8890,445],{"emptyLinePlaceholder":444},[407,8892,8893],{"class":409,"line":5399},[407,8894,8895],{"class":413},"// --- Handler messaggi di testo ---\n",[407,8897,8898],{"class":409,"line":5408},[407,8899,445],{"emptyLinePlaceholder":444},[407,8901,8902,8905,8908,8910,8912,8914,8916,8918,8921,8923,8925],{"class":409,"line":5414},[407,8903,8904],{"class":2201},"bot.",[407,8906,8907],{"class":420},"on",[407,8909,5216],{"class":2201},[407,8911,5720],{"class":424},[407,8913,2078],{"class":2201},[407,8915,5164],{"class":3864},[407,8917,1486],{"class":2201},[407,8919,8920],{"class":3876},"ctx",[407,8922,6395],{"class":2201},[407,8924,5574],{"class":3864},[407,8926,3871],{"class":2201},[407,8928,8929,8931,8934,8936],{"class":409,"line":5419},[407,8930,7695],{"class":3864},[407,8932,8933],{"class":434}," userId",[407,8935,5062],{"class":3864},[407,8937,8938],{"class":2201}," ctx.from.id;\n",[407,8940,8941],{"class":409,"line":5425},[407,8942,445],{"emptyLinePlaceholder":444},[407,8944,8945,8947,8949,8951,8954],{"class":409,"line":5437},[407,8946,8841],{"class":3864},[407,8948,1486],{"class":2201},[407,8950,8626],{"class":3864},[407,8952,8953],{"class":420},"isAllowed",[407,8955,8956],{"class":2201},"(userId)) {\n",[407,8958,8959,8961,8964,8967,8969,8972],{"class":409,"line":5449},[407,8960,5693],{"class":3864},[407,8962,8963],{"class":2201}," ctx.",[407,8965,8966],{"class":420},"reply",[407,8968,5216],{"class":2201},[407,8970,8971],{"class":424},"\"Non sei autorizzato a usare questo bot.\"",[407,8973,5083],{"class":2201},[407,8975,8976,8978],{"class":409,"line":5461},[407,8977,5231],{"class":3864},[407,8979,4986],{"class":2201},[407,8981,8982],{"class":409,"line":5470},[407,8983,2238],{"class":2201},[407,8985,8986],{"class":409,"line":5493},[407,8987,445],{"emptyLinePlaceholder":444},[407,8989,8990,8992,8995,8997],{"class":409,"line":5512},[407,8991,7695],{"class":3864},[407,8993,8994],{"class":434}," userMessage",[407,8996,5062],{"class":3864},[407,8998,8999],{"class":2201}," ctx.message.text;\n",[407,9001,9002],{"class":409,"line":5544},[407,9003,445],{"emptyLinePlaceholder":444},[407,9005,9006,9008],{"class":409,"line":5549},[407,9007,5192],{"class":3864},[407,9009,3871],{"class":2201},[407,9011,9012],{"class":409,"line":5583},[407,9013,9014],{"class":413},"    // Indicatore \"sta scrivendo...\"\n",[407,9016,9017,9019,9021,9024,9026,9029],{"class":409,"line":5600},[407,9018,5693],{"class":3864},[407,9020,8963],{"class":2201},[407,9022,9023],{"class":420},"sendChatAction",[407,9025,5216],{"class":2201},[407,9027,9028],{"class":424},"\"typing\"",[407,9030,5083],{"class":2201},[407,9032,9033],{"class":409,"line":5616},[407,9034,445],{"emptyLinePlaceholder":444},[407,9036,9037,9039,9042,9044,9046,9049,9052],{"class":409,"line":5628},[407,9038,5199],{"class":3864},[407,9040,9041],{"class":434}," response",[407,9043,5062],{"class":3864},[407,9045,5207],{"class":3864},[407,9047,9048],{"class":2201}," claude.messages.",[407,9050,9051],{"class":420},"create",[407,9053,5385],{"class":2201},[407,9055,9056,9059,9062],{"class":409,"line":5634},[407,9057,9058],{"class":2201},"      model: ",[407,9060,9061],{"class":434},"MODEL",[407,9063,3384],{"class":2201},[407,9065,9066,9069,9072],{"class":409,"line":5640},[407,9067,9068],{"class":2201},"      max_tokens: ",[407,9070,9071],{"class":434},"MAX_TOKENS",[407,9073,3384],{"class":2201},[407,9075,9076,9079,9082],{"class":409,"line":5652},[407,9077,9078],{"class":2201},"      system: ",[407,9080,9081],{"class":434},"SYSTEM_PROMPT",[407,9083,3384],{"class":2201},[407,9085,9086,9089,9091],{"class":409,"line":5672},[407,9087,9088],{"class":2201},"      messages: [{ role: ",[407,9090,6617],{"class":424},[407,9092,9093],{"class":2201},", content: userMessage }],\n",[407,9095,9096],{"class":409,"line":5678},[407,9097,9098],{"class":2201},"    });\n",[407,9100,9101],{"class":409,"line":5690},[407,9102,445],{"emptyLinePlaceholder":444},[407,9104,9105,9107,9110,9112,9115,9118],{"class":409,"line":5701},[407,9106,5199],{"class":3864},[407,9108,9109],{"class":434}," reply",[407,9111,5062],{"class":3864},[407,9113,9114],{"class":2201}," response.content[",[407,9116,9117],{"class":434},"0",[407,9119,9120],{"class":2201},"];\n",[407,9122,9123,9125,9128,9130,9133],{"class":409,"line":5708},[407,9124,6074],{"class":3864},[407,9126,9127],{"class":2201}," (reply.type ",[407,9129,6122],{"class":3864},[407,9131,9132],{"class":424}," \"text\"",[407,9134,6162],{"class":2201},[407,9136,9137,9140,9142,9144,9147,9150],{"class":409,"line":5714},[407,9138,9139],{"class":3864},"      await",[407,9141,8963],{"class":2201},[407,9143,8966],{"class":420},[407,9145,9146],{"class":2201},"(reply.text, { parse_mode: ",[407,9148,9149],{"class":424},"\"Markdown\"",[407,9151,9152],{"class":2201}," });\n",[407,9154,9155],{"class":409,"line":5725},[407,9156,2233],{"class":2201},[407,9158,9159,9161,9163],{"class":409,"line":5750},[407,9160,5247],{"class":2201},[407,9162,5250],{"class":3864},[407,9164,9165],{"class":2201}," (error) {\n",[407,9167,9168,9171,9173,9175,9178],{"class":409,"line":5756},[407,9169,9170],{"class":2201},"    console.",[407,9172,7786],{"class":420},[407,9174,5216],{"class":2201},[407,9176,9177],{"class":424},"\"Errore Claude API:\"",[407,9179,9180],{"class":2201},", error);\n",[407,9182,9183,9185,9187,9189,9191,9194],{"class":409,"line":5761},[407,9184,5693],{"class":3864},[407,9186,8963],{"class":2201},[407,9188,8966],{"class":420},[407,9190,5216],{"class":2201},[407,9192,9193],{"class":424},"\"Errore nella risposta. Riprova tra qualche secondo.\"",[407,9195,5083],{"class":2201},[407,9197,9198],{"class":409,"line":5766},[407,9199,2238],{"class":2201},[407,9201,9202],{"class":409,"line":5771},[407,9203,5411],{"class":2201},[407,9205,9206],{"class":409,"line":5776},[407,9207,445],{"emptyLinePlaceholder":444},[407,9209,9210],{"class":409,"line":5782},[407,9211,9212],{"class":413},"// --- Avvio ---\n",[407,9214,9215],{"class":409,"line":5799},[407,9216,445],{"emptyLinePlaceholder":444},[407,9218,9220,9222,9225,9227,9230,9233,9235,9237],{"class":409,"line":9219},70,[407,9221,8904],{"class":2201},[407,9223,9224],{"class":420},"command",[407,9226,5216],{"class":2201},[407,9228,9229],{"class":424},"\"start\"",[407,9231,9232],{"class":2201},", (",[407,9234,8920],{"class":3876},[407,9236,6395],{"class":2201},[407,9238,9239],{"class":3864},"=>\n",[407,9241,9243,9246,9248,9250,9253],{"class":409,"line":9242},71,[407,9244,9245],{"class":2201},"  ctx.",[407,9247,8966],{"class":420},[407,9249,5216],{"class":2201},[407,9251,9252],{"class":424},"\"Ciao! Sono Jarvis, il tuo assistente AI. Scrivimi qualcosa.\"",[407,9254,5541],{"class":2201},[407,9256,9258],{"class":409,"line":9257},72,[407,9259,5083],{"class":2201},[407,9261,9263],{"class":409,"line":9262},73,[407,9264,445],{"emptyLinePlaceholder":444},[407,9266,9268,9270,9273],{"class":409,"line":9267},74,[407,9269,8904],{"class":2201},[407,9271,9272],{"class":420},"launch",[407,9274,5597],{"class":2201},[407,9276,9278,9281,9284,9286,9289],{"class":409,"line":9277},75,[407,9279,9280],{"class":2201},"console.",[407,9282,9283],{"class":420},"log",[407,9285,5216],{"class":2201},[407,9287,9288],{"class":424},"\"Bot avviato!\"",[407,9290,5083],{"class":2201},[407,9292,9294],{"class":409,"line":9293},76,[407,9295,445],{"emptyLinePlaceholder":444},[407,9297,9299],{"class":409,"line":9298},77,[407,9300,9301],{"class":413},"// Graceful shutdown\n",[407,9303,9305,9308,9311,9313,9316,9318,9320,9323,9326,9328,9330],{"class":409,"line":9304},78,[407,9306,9307],{"class":2201},"process.",[407,9309,9310],{"class":420},"once",[407,9312,5216],{"class":2201},[407,9314,9315],{"class":424},"\"SIGINT\"",[407,9317,7774],{"class":2201},[407,9319,5574],{"class":3864},[407,9321,9322],{"class":2201}," bot.",[407,9324,9325],{"class":420},"stop",[407,9327,5216],{"class":2201},[407,9329,9315],{"class":424},[407,9331,5345],{"class":2201},[407,9333,9335,9337,9339,9341,9344,9346,9348,9350,9352,9354,9356],{"class":409,"line":9334},79,[407,9336,9307],{"class":2201},[407,9338,9310],{"class":420},[407,9340,5216],{"class":2201},[407,9342,9343],{"class":424},"\"SIGTERM\"",[407,9345,7774],{"class":2201},[407,9347,5574],{"class":3864},[407,9349,9322],{"class":2201},[407,9351,9325],{"class":420},[407,9353,5216],{"class":2201},[407,9355,9343],{"class":424},[407,9357,5345],{"class":2201},[17,9359,9360],{},"Avvia il bot:",[346,9362,9364],{"className":401,"code":9363,"language":403,"meta":355,"style":355},"npm run dev\n",[353,9365,9366],{"__ignoreMap":355},[407,9367,9368,9370,9373],{"class":409,"line":410},[407,9369,4730],{"class":420},[407,9371,9372],{"class":424}," run",[407,9374,9375],{"class":424}," dev\n",[17,9377,9378],{},"Vai su Telegram, apri la chat col tuo bot e scrivi qualcosa. Se tutto funziona, Claude risponde. Hai un assistente AI su Telegram. In 50 righe di codice.",[17,9380,9381],{},"Ma manca un pezzo fondamentale: la memoria.",[35,9383],{},[38,9385,9387],{"id":9386},"step-4-aggiungere-la-memoria","Step 4: Aggiungere la Memoria",[17,9389,9390],{},"Il bot dello step precedente e' smemorato. Ogni messaggio e' una conversazione nuova -- Claude non sa cosa gli hai detto 30 secondi fa. Per un assistente personale, e' inutilizzabile.",[17,9392,9393],{},"La soluzione: manteniamo un array di messaggi per ogni utente e lo passiamo a Claude a ogni richiesta.",[17,9395,9396,9397,1894],{},"Aggiungiamo la gestione della conversazione al nostro bot. Sostituisci il contenuto di ",[353,9398,8548],{},[346,9400,9402],{"className":3850,"code":9401,"language":3852,"meta":355,"style":355},"import \"dotenv/config\";\nimport { Telegraf } from \"telegraf\";\nimport Anthropic from \"@anthropic-ai/sdk\";\nimport type { MessageParam } from \"@anthropic-ai/sdk/resources/messages\";\n\n// --- Configurazione ---\n\nconst bot = new Telegraf(process.env.TELEGRAM_BOT_TOKEN!);\nconst claude = new Anthropic();\n\nconst ALLOWED_USERS = new Set(\n  (process.env.ALLOWED_USER_IDS || \"\").split(\",\").map(Number)\n);\n\nconst SYSTEM_PROMPT = `Sei Jarvis, l'assistente personale di un developer.\n\nRUOLO: Assistente competente, conciso e proattivo.\n\nREGOLE:\n- Rispondi in italiano a meno che non ti si chieda diversamente\n- Sii conciso: Telegram non e' il posto per muri di testo\n- Usa formattazione Markdown quando aiuta la leggibilita'\n- Se non sai qualcosa, dillo chiaramente\n- Per il codice, usa i code block con il linguaggio specificato\n- Ricorda il contesto della conversazione`;\n\nconst MODEL = \"claude-haiku-4-5-20251001\";\nconst MAX_TOKENS = 2048;\nconst MAX_HISTORY = 40; // ultimi 40 messaggi (20 scambi)\n\n// --- Memoria conversazioni ---\n\nconst conversations = new Map\u003Cnumber, MessageParam[]>();\n\nfunction getHistory(userId: number): MessageParam[] {\n  if (!conversations.has(userId)) {\n    conversations.set(userId, []);\n  }\n  return conversations.get(userId)!;\n}\n\nfunction addMessage(\n  userId: number,\n  role: \"user\" | \"assistant\",\n  content: string\n): void {\n  const history = getHistory(userId);\n  history.push({ role, content });\n\n  // Tieni solo gli ultimi N messaggi per evitare che il contesto esploda\n  if (history.length > MAX_HISTORY) {\n    // Rimuovi i messaggi piu' vecchi, mantenendo sempre coppie user/assistant\n    conversations.set(userId, history.slice(-MAX_HISTORY));\n  }\n}\n\n// --- Sicurezza ---\n\nfunction isAllowed(userId: number): boolean {\n  if (ALLOWED_USERS.size === 0) return true;\n  return ALLOWED_USERS.has(userId);\n}\n\n// --- Chat con Claude ---\n\nasync function chat(userId: number, userMessage: string): Promise\u003Cstring> {\n  addMessage(userId, \"user\", userMessage);\n\n  const response = await claude.messages.create({\n    model: MODEL,\n    max_tokens: MAX_TOKENS,\n    system: SYSTEM_PROMPT,\n    messages: getHistory(userId),\n  });\n\n  const reply = response.content[0];\n  const text = reply.type === \"text\" ? reply.text : \"Risposta non testuale.\";\n\n  addMessage(userId, \"assistant\", text);\n  return text;\n}\n\n// --- Comandi ---\n\nbot.command(\"start\", (ctx) =>\n  ctx.reply(\"Ciao! Sono Jarvis, il tuo assistente AI. Scrivimi qualcosa.\")\n);\n\nbot.command(\"reset\", (ctx) => {\n  conversations.delete(ctx.from.id);\n  ctx.reply(\"Conversazione resettata. Ricominciamo da zero.\");\n});\n\nbot.command(\"help\", (ctx) =>\n  ctx.reply(\n    [\n      \"*Comandi disponibili:*\",\n      \"/reset - Cancella la memoria della conversazione\",\n      \"/help - Mostra questo messaggio\",\n      \"\",\n      \"Puoi inviarmi testo o immagini. Rispondo a tutto.\",\n    ].join(\"\\n\"),\n    { parse_mode: \"Markdown\" }\n  )\n);\n\n// --- Handler messaggi di testo ---\n\nbot.on(\"text\", async (ctx) => {\n  if (!isAllowed(ctx.from.id)) {\n    return ctx.reply(\"Non sei autorizzato a usare questo bot.\");\n  }\n\n  try {\n    await ctx.sendChatAction(\"typing\");\n    const reply = await chat(ctx.from.id, ctx.message.text);\n    await ctx.reply(reply, { parse_mode: \"Markdown\" });\n  } catch (error) {\n    console.error(\"Errore:\", error);\n\n    // Gestione errori specifici di Claude\n    if (error instanceof Anthropic.RateLimitError) {\n      await ctx.reply(\"Troppe richieste. Aspetta qualche secondo e riprova.\");\n    } else if (error instanceof Anthropic.APIError) {\n      await ctx.reply(\n        `Errore API (${error.status}). Riprova tra qualche secondo.`\n      );\n    } else {\n      await ctx.reply(\"Qualcosa e' andato storto. Riprova.\");\n    }\n  }\n});\n\n// --- Avvio ---\n\nbot.launch();\nconsole.log(\"Bot avviato con memoria conversazioni!\");\n\nprocess.once(\"SIGINT\", () => bot.stop(\"SIGINT\"));\nprocess.once(\"SIGTERM\", () => bot.stop(\"SIGTERM\"));\n",[353,9403,9404,9412,9424,9436,9453,9457,9461,9465,9485,9499,9503,9517,9541,9545,9549,9559,9563,9567,9571,9575,9579,9583,9587,9591,9596,9603,9607,9619,9631,9648,9652,9657,9661,9688,9692,9717,9732,9743,9747,9764,9768,9772,9781,9792,9808,9816,9827,9840,9850,9854,9859,9875,9880,9902,9906,9910,9914,9919,9923,9945,9967,9979,9983,9987,9992,9996,10034,10047,10051,10067,10076,10085,10094,10105,10109,10113,10127,10156,10160,10172,10180,10185,10190,10196,10201,10220,10233,10238,10243,10265,10277,10291,10296,10301,10321,10330,10336,10344,10352,10360,10368,10376,10394,10405,10411,10416,10421,10426,10431,10456,10470,10485,10490,10495,10502,10517,10533,10549,10558,10572,10577,10583,10603,10619,10644,10655,10671,10676,10685,10701,10706,10711,10716,10721,10726,10731,10740,10754,10759,10784],{"__ignoreMap":355},[407,9405,9406,9408,9410],{"class":409,"line":410},[407,9407,4974],{"class":3864},[407,9409,8561],{"class":424},[407,9411,4986],{"class":2201},[407,9413,9414,9416,9418,9420,9422],{"class":409,"line":417},[407,9415,4974],{"class":3864},[407,9417,8570],{"class":2201},[407,9419,4980],{"class":3864},[407,9421,8575],{"class":424},[407,9423,4986],{"class":2201},[407,9425,9426,9428,9430,9432,9434],{"class":409,"line":441},[407,9427,4974],{"class":3864},[407,9429,8584],{"class":2201},[407,9431,4980],{"class":3864},[407,9433,8589],{"class":424},[407,9435,4986],{"class":2201},[407,9437,9438,9440,9443,9446,9448,9451],{"class":409,"line":448},[407,9439,4974],{"class":3864},[407,9441,9442],{"class":3864}," type",[407,9444,9445],{"class":2201}," { MessageParam } ",[407,9447,4980],{"class":3864},[407,9449,9450],{"class":424}," \"@anthropic-ai/sdk/resources/messages\"",[407,9452,4986],{"class":2201},[407,9454,9455],{"class":409,"line":454},[407,9456,445],{"emptyLinePlaceholder":444},[407,9458,9459],{"class":409,"line":1667},[407,9460,8600],{"class":413},[407,9462,9463],{"class":409,"line":1673},[407,9464,445],{"emptyLinePlaceholder":444},[407,9466,9467,9469,9471,9473,9475,9477,9479,9481,9483],{"class":409,"line":1679},[407,9468,5056],{"class":3864},[407,9470,8611],{"class":434},[407,9472,5062],{"class":3864},[407,9474,5379],{"class":3864},[407,9476,8618],{"class":420},[407,9478,8621],{"class":2201},[407,9480,8488],{"class":434},[407,9482,8626],{"class":3864},[407,9484,5083],{"class":2201},[407,9486,9487,9489,9491,9493,9495,9497],{"class":409,"line":1685},[407,9488,5056],{"class":3864},[407,9490,8635],{"class":434},[407,9492,5062],{"class":3864},[407,9494,5379],{"class":3864},[407,9496,8642],{"class":420},[407,9498,5597],{"class":2201},[407,9500,9501],{"class":409,"line":1690},[407,9502,445],{"emptyLinePlaceholder":444},[407,9504,9505,9507,9509,9511,9513,9515],{"class":409,"line":1696},[407,9506,5056],{"class":3864},[407,9508,8659],{"class":434},[407,9510,5062],{"class":3864},[407,9512,5379],{"class":3864},[407,9514,8666],{"class":420},[407,9516,5434],{"class":2201},[407,9518,9519,9521,9523,9525,9527,9529,9531,9533,9535,9537,9539],{"class":409,"line":1702},[407,9520,8673],{"class":2201},[407,9522,8508],{"class":434},[407,9524,8678],{"class":3864},[407,9526,8681],{"class":424},[407,9528,8684],{"class":2201},[407,9530,8687],{"class":420},[407,9532,5216],{"class":2201},[407,9534,8692],{"class":424},[407,9536,8684],{"class":2201},[407,9538,6212],{"class":420},[407,9540,8699],{"class":2201},[407,9542,9543],{"class":409,"line":1708},[407,9544,5083],{"class":2201},[407,9546,9547],{"class":409,"line":1714},[407,9548,445],{"emptyLinePlaceholder":444},[407,9550,9551,9553,9555,9557],{"class":409,"line":1719},[407,9552,5056],{"class":3864},[407,9554,8714],{"class":434},[407,9556,5062],{"class":3864},[407,9558,8719],{"class":424},[407,9560,9561],{"class":409,"line":1725},[407,9562,445],{"emptyLinePlaceholder":444},[407,9564,9565],{"class":409,"line":1278},[407,9566,8728],{"class":424},[407,9568,9569],{"class":409,"line":1736},[407,9570,445],{"emptyLinePlaceholder":444},[407,9572,9573],{"class":409,"line":1742},[407,9574,8737],{"class":424},[407,9576,9577],{"class":409,"line":1748},[407,9578,8742],{"class":424},[407,9580,9581],{"class":409,"line":1753},[407,9582,8747],{"class":424},[407,9584,9585],{"class":409,"line":1759},[407,9586,8752],{"class":424},[407,9588,9589],{"class":409,"line":1765},[407,9590,8757],{"class":424},[407,9592,9593],{"class":409,"line":1771},[407,9594,9595],{"class":424},"- Per il codice, usa i code block con il linguaggio specificato\n",[407,9597,9598,9601],{"class":409,"line":1777},[407,9599,9600],{"class":424},"- Ricorda il contesto della conversazione`",[407,9602,4986],{"class":2201},[407,9604,9605],{"class":409,"line":1782},[407,9606,445],{"emptyLinePlaceholder":444},[407,9608,9609,9611,9613,9615,9617],{"class":409,"line":1788},[407,9610,5056],{"class":3864},[407,9612,8775],{"class":434},[407,9614,5062],{"class":3864},[407,9616,8780],{"class":424},[407,9618,4986],{"class":2201},[407,9620,9621,9623,9625,9627,9629],{"class":409,"line":1794},[407,9622,5056],{"class":3864},[407,9624,8789],{"class":434},[407,9626,5062],{"class":3864},[407,9628,8794],{"class":434},[407,9630,4986],{"class":2201},[407,9632,9633,9635,9638,9640,9643,9645],{"class":409,"line":5348},[407,9634,5056],{"class":3864},[407,9636,9637],{"class":434}," MAX_HISTORY",[407,9639,5062],{"class":3864},[407,9641,9642],{"class":434}," 40",[407,9644,8864],{"class":2201},[407,9646,9647],{"class":413},"// ultimi 40 messaggi (20 scambi)\n",[407,9649,9650],{"class":409,"line":5353},[407,9651,445],{"emptyLinePlaceholder":444},[407,9653,9654],{"class":409,"line":5358},[407,9655,9656],{"class":413},"// --- Memoria conversazioni ---\n",[407,9658,9659],{"class":409,"line":5364},[407,9660,445],{"emptyLinePlaceholder":444},[407,9662,9663,9665,9668,9670,9672,9675,9677,9680,9682,9685],{"class":409,"line":5369},[407,9664,5056],{"class":3864},[407,9666,9667],{"class":434}," conversations",[407,9669,5062],{"class":3864},[407,9671,5379],{"class":3864},[407,9673,9674],{"class":420}," Map",[407,9676,5181],{"class":2201},[407,9678,9679],{"class":434},"number",[407,9681,2078],{"class":2201},[407,9683,9684],{"class":420},"MessageParam",[407,9686,9687],{"class":2201},"[]>();\n",[407,9689,9690],{"class":409,"line":5388},[407,9691,445],{"emptyLinePlaceholder":444},[407,9693,9694,9696,9699,9701,9703,9705,9707,9709,9711,9714],{"class":409,"line":5399},[407,9695,8814],{"class":3864},[407,9697,9698],{"class":420}," getHistory",[407,9700,5216],{"class":2201},[407,9702,8822],{"class":3876},[407,9704,1894],{"class":3864},[407,9706,8827],{"class":434},[407,9708,6250],{"class":2201},[407,9710,1894],{"class":3864},[407,9712,9713],{"class":420}," MessageParam",[407,9715,9716],{"class":2201},"[] {\n",[407,9718,9719,9721,9723,9725,9728,9730],{"class":409,"line":5408},[407,9720,8841],{"class":3864},[407,9722,1486],{"class":2201},[407,9724,8626],{"class":3864},[407,9726,9727],{"class":2201},"conversations.",[407,9729,8879],{"class":420},[407,9731,8956],{"class":2201},[407,9733,9734,9737,9740],{"class":409,"line":5414},[407,9735,9736],{"class":2201},"    conversations.",[407,9738,9739],{"class":420},"set",[407,9741,9742],{"class":2201},"(userId, []);\n",[407,9744,9745],{"class":409,"line":5419},[407,9746,2238],{"class":2201},[407,9748,9749,9751,9754,9757,9760,9762],{"class":409,"line":5425},[407,9750,8872],{"class":3864},[407,9752,9753],{"class":2201}," conversations.",[407,9755,9756],{"class":420},"get",[407,9758,9759],{"class":2201},"(userId)",[407,9761,8626],{"class":3864},[407,9763,4986],{"class":2201},[407,9765,9766],{"class":409,"line":5437},[407,9767,2243],{"class":2201},[407,9769,9770],{"class":409,"line":5449},[407,9771,445],{"emptyLinePlaceholder":444},[407,9773,9774,9776,9779],{"class":409,"line":5461},[407,9775,8814],{"class":3864},[407,9777,9778],{"class":420}," addMessage",[407,9780,5434],{"class":2201},[407,9782,9783,9786,9788,9790],{"class":409,"line":5470},[407,9784,9785],{"class":3876},"  userId",[407,9787,1894],{"class":3864},[407,9789,8827],{"class":434},[407,9791,3384],{"class":2201},[407,9793,9794,9796,9798,9801,9803,9806],{"class":409,"line":5493},[407,9795,3896],{"class":3876},[407,9797,1894],{"class":3864},[407,9799,9800],{"class":424}," \"user\"",[407,9802,3904],{"class":3864},[407,9804,9805],{"class":424}," \"assistant\"",[407,9807,3384],{"class":2201},[407,9809,9810,9812,9814],{"class":409,"line":5512},[407,9811,5123],{"class":3876},[407,9813,1894],{"class":3864},[407,9815,3882],{"class":434},[407,9817,9818,9820,9822,9825],{"class":409,"line":5544},[407,9819,6250],{"class":2201},[407,9821,1894],{"class":3864},[407,9823,9824],{"class":434}," void",[407,9826,3871],{"class":2201},[407,9828,9829,9831,9834,9836,9838],{"class":409,"line":5549},[407,9830,7695],{"class":3864},[407,9832,9833],{"class":434}," history",[407,9835,5062],{"class":3864},[407,9837,9698],{"class":420},[407,9839,8882],{"class":2201},[407,9841,9842,9845,9847],{"class":409,"line":5583},[407,9843,9844],{"class":2201},"  history.",[407,9846,5684],{"class":420},[407,9848,9849],{"class":2201},"({ role, content });\n",[407,9851,9852],{"class":409,"line":5600},[407,9853,445],{"emptyLinePlaceholder":444},[407,9855,9856],{"class":409,"line":5616},[407,9857,9858],{"class":413},"  // Tieni solo gli ultimi N messaggi per evitare che il contesto esploda\n",[407,9860,9861,9863,9866,9868,9871,9873],{"class":409,"line":5628},[407,9862,8841],{"class":3864},[407,9864,9865],{"class":2201}," (history.",[407,9867,6153],{"class":434},[407,9869,9870],{"class":3864}," >",[407,9872,9637],{"class":434},[407,9874,6162],{"class":2201},[407,9876,9877],{"class":409,"line":5634},[407,9878,9879],{"class":413},"    // Rimuovi i messaggi piu' vecchi, mantenendo sempre coppie user/assistant\n",[407,9881,9882,9884,9886,9889,9892,9894,9897,9900],{"class":409,"line":5640},[407,9883,9736],{"class":2201},[407,9885,9739],{"class":420},[407,9887,9888],{"class":2201},"(userId, history.",[407,9890,9891],{"class":420},"slice",[407,9893,5216],{"class":2201},[407,9895,9896],{"class":3864},"-",[407,9898,9899],{"class":434},"MAX_HISTORY",[407,9901,5345],{"class":2201},[407,9903,9904],{"class":409,"line":5652},[407,9905,2238],{"class":2201},[407,9907,9908],{"class":409,"line":5672},[407,9909,2243],{"class":2201},[407,9911,9912],{"class":409,"line":5678},[407,9913,445],{"emptyLinePlaceholder":444},[407,9915,9916],{"class":409,"line":5690},[407,9917,9918],{"class":413},"// --- Sicurezza ---\n",[407,9920,9921],{"class":409,"line":5701},[407,9922,445],{"emptyLinePlaceholder":444},[407,9924,9925,9927,9929,9931,9933,9935,9937,9939,9941,9943],{"class":409,"line":5708},[407,9926,8814],{"class":3864},[407,9928,8817],{"class":420},[407,9930,5216],{"class":2201},[407,9932,8822],{"class":3876},[407,9934,1894],{"class":3864},[407,9936,8827],{"class":434},[407,9938,6250],{"class":2201},[407,9940,1894],{"class":3864},[407,9942,8834],{"class":434},[407,9944,3871],{"class":2201},[407,9946,9947,9949,9951,9953,9955,9957,9959,9961,9963,9965],{"class":409,"line":5714},[407,9948,8841],{"class":3864},[407,9950,1486],{"class":2201},[407,9952,8846],{"class":434},[407,9954,8849],{"class":2201},[407,9956,6122],{"class":3864},[407,9958,6159],{"class":434},[407,9960,6395],{"class":2201},[407,9962,8858],{"class":3864},[407,9964,8861],{"class":434},[407,9966,4986],{"class":2201},[407,9968,9969,9971,9973,9975,9977],{"class":409,"line":5725},[407,9970,8872],{"class":3864},[407,9972,8659],{"class":434},[407,9974,688],{"class":2201},[407,9976,8879],{"class":420},[407,9978,8882],{"class":2201},[407,9980,9981],{"class":409,"line":5750},[407,9982,2243],{"class":2201},[407,9984,9985],{"class":409,"line":5756},[407,9986,445],{"emptyLinePlaceholder":444},[407,9988,9989],{"class":409,"line":5761},[407,9990,9991],{"class":413},"// --- Chat con Claude ---\n",[407,9993,9994],{"class":409,"line":5766},[407,9995,445],{"emptyLinePlaceholder":444},[407,9997,9998,10000,10002,10005,10007,10009,10011,10013,10015,10018,10020,10022,10024,10026,10028,10030,10032],{"class":409,"line":5771},[407,9999,5164],{"class":3864},[407,10001,5167],{"class":3864},[407,10003,10004],{"class":420}," chat",[407,10006,5216],{"class":2201},[407,10008,8822],{"class":3876},[407,10010,1894],{"class":3864},[407,10012,8827],{"class":434},[407,10014,2078],{"class":2201},[407,10016,10017],{"class":3876},"userMessage",[407,10019,1894],{"class":3864},[407,10021,5105],{"class":434},[407,10023,6250],{"class":2201},[407,10025,1894],{"class":3864},[407,10027,5178],{"class":420},[407,10029,5181],{"class":2201},[407,10031,5476],{"class":434},[407,10033,5307],{"class":2201},[407,10035,10036,10039,10042,10044],{"class":409,"line":5776},[407,10037,10038],{"class":420},"  addMessage",[407,10040,10041],{"class":2201},"(userId, ",[407,10043,6617],{"class":424},[407,10045,10046],{"class":2201},", userMessage);\n",[407,10048,10049],{"class":409,"line":5782},[407,10050,445],{"emptyLinePlaceholder":444},[407,10052,10053,10055,10057,10059,10061,10063,10065],{"class":409,"line":5799},[407,10054,7695],{"class":3864},[407,10056,9041],{"class":434},[407,10058,5062],{"class":3864},[407,10060,5207],{"class":3864},[407,10062,9048],{"class":2201},[407,10064,9051],{"class":420},[407,10066,5385],{"class":2201},[407,10068,10069,10072,10074],{"class":409,"line":9219},[407,10070,10071],{"class":2201},"    model: ",[407,10073,9061],{"class":434},[407,10075,3384],{"class":2201},[407,10077,10078,10081,10083],{"class":409,"line":9242},[407,10079,10080],{"class":2201},"    max_tokens: ",[407,10082,9071],{"class":434},[407,10084,3384],{"class":2201},[407,10086,10087,10090,10092],{"class":409,"line":9257},[407,10088,10089],{"class":2201},"    system: ",[407,10091,9081],{"class":434},[407,10093,3384],{"class":2201},[407,10095,10096,10099,10102],{"class":409,"line":9262},[407,10097,10098],{"class":2201},"    messages: ",[407,10100,10101],{"class":420},"getHistory",[407,10103,10104],{"class":2201},"(userId),\n",[407,10106,10107],{"class":409,"line":9267},[407,10108,7728],{"class":2201},[407,10110,10111],{"class":409,"line":9277},[407,10112,445],{"emptyLinePlaceholder":444},[407,10114,10115,10117,10119,10121,10123,10125],{"class":409,"line":9293},[407,10116,7695],{"class":3864},[407,10118,9109],{"class":434},[407,10120,5062],{"class":3864},[407,10122,9114],{"class":2201},[407,10124,9117],{"class":434},[407,10126,9120],{"class":2201},[407,10128,10129,10131,10134,10136,10139,10141,10143,10146,10149,10151,10154],{"class":409,"line":9298},[407,10130,7695],{"class":3864},[407,10132,10133],{"class":434}," text",[407,10135,5062],{"class":3864},[407,10137,10138],{"class":2201}," reply.type ",[407,10140,6122],{"class":3864},[407,10142,9132],{"class":424},[407,10144,10145],{"class":3864}," ?",[407,10147,10148],{"class":2201}," reply.text ",[407,10150,1894],{"class":3864},[407,10152,10153],{"class":424}," \"Risposta non testuale.\"",[407,10155,4986],{"class":2201},[407,10157,10158],{"class":409,"line":9304},[407,10159,445],{"emptyLinePlaceholder":444},[407,10161,10162,10164,10166,10169],{"class":409,"line":9334},[407,10163,10038],{"class":420},[407,10165,10041],{"class":2201},[407,10167,10168],{"class":424},"\"assistant\"",[407,10170,10171],{"class":2201},", text);\n",[407,10173,10175,10177],{"class":409,"line":10174},80,[407,10176,8872],{"class":3864},[407,10178,10179],{"class":2201}," text;\n",[407,10181,10183],{"class":409,"line":10182},81,[407,10184,2243],{"class":2201},[407,10186,10188],{"class":409,"line":10187},82,[407,10189,445],{"emptyLinePlaceholder":444},[407,10191,10193],{"class":409,"line":10192},83,[407,10194,10195],{"class":413},"// --- Comandi ---\n",[407,10197,10199],{"class":409,"line":10198},84,[407,10200,445],{"emptyLinePlaceholder":444},[407,10202,10204,10206,10208,10210,10212,10214,10216,10218],{"class":409,"line":10203},85,[407,10205,8904],{"class":2201},[407,10207,9224],{"class":420},[407,10209,5216],{"class":2201},[407,10211,9229],{"class":424},[407,10213,9232],{"class":2201},[407,10215,8920],{"class":3876},[407,10217,6395],{"class":2201},[407,10219,9239],{"class":3864},[407,10221,10223,10225,10227,10229,10231],{"class":409,"line":10222},86,[407,10224,9245],{"class":2201},[407,10226,8966],{"class":420},[407,10228,5216],{"class":2201},[407,10230,9252],{"class":424},[407,10232,5541],{"class":2201},[407,10234,10236],{"class":409,"line":10235},87,[407,10237,5083],{"class":2201},[407,10239,10241],{"class":409,"line":10240},88,[407,10242,445],{"emptyLinePlaceholder":444},[407,10244,10246,10248,10250,10252,10255,10257,10259,10261,10263],{"class":409,"line":10245},89,[407,10247,8904],{"class":2201},[407,10249,9224],{"class":420},[407,10251,5216],{"class":2201},[407,10253,10254],{"class":424},"\"reset\"",[407,10256,9232],{"class":2201},[407,10258,8920],{"class":3876},[407,10260,6395],{"class":2201},[407,10262,5574],{"class":3864},[407,10264,3871],{"class":2201},[407,10266,10268,10271,10274],{"class":409,"line":10267},90,[407,10269,10270],{"class":2201},"  conversations.",[407,10272,10273],{"class":420},"delete",[407,10275,10276],{"class":2201},"(ctx.from.id);\n",[407,10278,10280,10282,10284,10286,10289],{"class":409,"line":10279},91,[407,10281,9245],{"class":2201},[407,10283,8966],{"class":420},[407,10285,5216],{"class":2201},[407,10287,10288],{"class":424},"\"Conversazione resettata. Ricominciamo da zero.\"",[407,10290,5083],{"class":2201},[407,10292,10294],{"class":409,"line":10293},92,[407,10295,5411],{"class":2201},[407,10297,10299],{"class":409,"line":10298},93,[407,10300,445],{"emptyLinePlaceholder":444},[407,10302,10304,10306,10308,10310,10313,10315,10317,10319],{"class":409,"line":10303},94,[407,10305,8904],{"class":2201},[407,10307,9224],{"class":420},[407,10309,5216],{"class":2201},[407,10311,10312],{"class":424},"\"help\"",[407,10314,9232],{"class":2201},[407,10316,8920],{"class":3876},[407,10318,6395],{"class":2201},[407,10320,9239],{"class":3864},[407,10322,10324,10326,10328],{"class":409,"line":10323},95,[407,10325,9245],{"class":2201},[407,10327,8966],{"class":420},[407,10329,5434],{"class":2201},[407,10331,10333],{"class":409,"line":10332},96,[407,10334,10335],{"class":2201},"    [\n",[407,10337,10339,10342],{"class":409,"line":10338},97,[407,10340,10341],{"class":424},"      \"*Comandi disponibili:*\"",[407,10343,3384],{"class":2201},[407,10345,10347,10350],{"class":409,"line":10346},98,[407,10348,10349],{"class":424},"      \"/reset - Cancella la memoria della conversazione\"",[407,10351,3384],{"class":2201},[407,10353,10355,10358],{"class":409,"line":10354},99,[407,10356,10357],{"class":424},"      \"/help - Mostra questo messaggio\"",[407,10359,3384],{"class":2201},[407,10361,10363,10366],{"class":409,"line":10362},100,[407,10364,10365],{"class":424},"      \"\"",[407,10367,3384],{"class":2201},[407,10369,10371,10374],{"class":409,"line":10370},101,[407,10372,10373],{"class":424},"      \"Puoi inviarmi testo o immagini. Rispondo a tutto.\"",[407,10375,3384],{"class":2201},[407,10377,10379,10382,10384,10386,10388,10390,10392],{"class":409,"line":10378},102,[407,10380,10381],{"class":2201},"    ].",[407,10383,5068],{"class":420},[407,10385,5216],{"class":2201},[407,10387,6280],{"class":424},[407,10389,6256],{"class":434},[407,10391,6280],{"class":424},[407,10393,5490],{"class":2201},[407,10395,10397,10400,10402],{"class":409,"line":10396},103,[407,10398,10399],{"class":2201},"    { parse_mode: ",[407,10401,9149],{"class":424},[407,10403,10404],{"class":2201}," }\n",[407,10406,10408],{"class":409,"line":10407},104,[407,10409,10410],{"class":2201},"  )\n",[407,10412,10414],{"class":409,"line":10413},105,[407,10415,5083],{"class":2201},[407,10417,10419],{"class":409,"line":10418},106,[407,10420,445],{"emptyLinePlaceholder":444},[407,10422,10424],{"class":409,"line":10423},107,[407,10425,8895],{"class":413},[407,10427,10429],{"class":409,"line":10428},108,[407,10430,445],{"emptyLinePlaceholder":444},[407,10432,10434,10436,10438,10440,10442,10444,10446,10448,10450,10452,10454],{"class":409,"line":10433},109,[407,10435,8904],{"class":2201},[407,10437,8907],{"class":420},[407,10439,5216],{"class":2201},[407,10441,5720],{"class":424},[407,10443,2078],{"class":2201},[407,10445,5164],{"class":3864},[407,10447,1486],{"class":2201},[407,10449,8920],{"class":3876},[407,10451,6395],{"class":2201},[407,10453,5574],{"class":3864},[407,10455,3871],{"class":2201},[407,10457,10459,10461,10463,10465,10467],{"class":409,"line":10458},110,[407,10460,8841],{"class":3864},[407,10462,1486],{"class":2201},[407,10464,8626],{"class":3864},[407,10466,8953],{"class":420},[407,10468,10469],{"class":2201},"(ctx.from.id)) {\n",[407,10471,10473,10475,10477,10479,10481,10483],{"class":409,"line":10472},111,[407,10474,5231],{"class":3864},[407,10476,8963],{"class":2201},[407,10478,8966],{"class":420},[407,10480,5216],{"class":2201},[407,10482,8971],{"class":424},[407,10484,5083],{"class":2201},[407,10486,10488],{"class":409,"line":10487},112,[407,10489,2238],{"class":2201},[407,10491,10493],{"class":409,"line":10492},113,[407,10494,445],{"emptyLinePlaceholder":444},[407,10496,10498,10500],{"class":409,"line":10497},114,[407,10499,5192],{"class":3864},[407,10501,3871],{"class":2201},[407,10503,10505,10507,10509,10511,10513,10515],{"class":409,"line":10504},115,[407,10506,5693],{"class":3864},[407,10508,8963],{"class":2201},[407,10510,9023],{"class":420},[407,10512,5216],{"class":2201},[407,10514,9028],{"class":424},[407,10516,5083],{"class":2201},[407,10518,10520,10522,10524,10526,10528,10530],{"class":409,"line":10519},116,[407,10521,5199],{"class":3864},[407,10523,9109],{"class":434},[407,10525,5062],{"class":3864},[407,10527,5207],{"class":3864},[407,10529,10004],{"class":420},[407,10531,10532],{"class":2201},"(ctx.from.id, ctx.message.text);\n",[407,10534,10536,10538,10540,10542,10545,10547],{"class":409,"line":10535},117,[407,10537,5693],{"class":3864},[407,10539,8963],{"class":2201},[407,10541,8966],{"class":420},[407,10543,10544],{"class":2201},"(reply, { parse_mode: ",[407,10546,9149],{"class":424},[407,10548,9152],{"class":2201},[407,10550,10552,10554,10556],{"class":409,"line":10551},118,[407,10553,5247],{"class":2201},[407,10555,5250],{"class":3864},[407,10557,9165],{"class":2201},[407,10559,10561,10563,10565,10567,10570],{"class":409,"line":10560},119,[407,10562,9170],{"class":2201},[407,10564,7786],{"class":420},[407,10566,5216],{"class":2201},[407,10568,10569],{"class":424},"\"Errore:\"",[407,10571,9180],{"class":2201},[407,10573,10575],{"class":409,"line":10574},120,[407,10576,445],{"emptyLinePlaceholder":444},[407,10578,10580],{"class":409,"line":10579},121,[407,10581,10582],{"class":413},"    // Gestione errori specifici di Claude\n",[407,10584,10586,10588,10591,10594,10596,10598,10601],{"class":409,"line":10585},122,[407,10587,6074],{"class":3864},[407,10589,10590],{"class":2201}," (error ",[407,10592,10593],{"class":3864},"instanceof",[407,10595,8642],{"class":420},[407,10597,688],{"class":2201},[407,10599,10600],{"class":420},"RateLimitError",[407,10602,6162],{"class":2201},[407,10604,10606,10608,10610,10612,10614,10617],{"class":409,"line":10605},123,[407,10607,9139],{"class":3864},[407,10609,8963],{"class":2201},[407,10611,8966],{"class":420},[407,10613,5216],{"class":2201},[407,10615,10616],{"class":424},"\"Troppe richieste. Aspetta qualche secondo e riprova.\"",[407,10618,5083],{"class":2201},[407,10620,10622,10625,10628,10631,10633,10635,10637,10639,10642],{"class":409,"line":10621},124,[407,10623,10624],{"class":2201},"    } ",[407,10626,10627],{"class":3864},"else",[407,10629,10630],{"class":3864}," if",[407,10632,10590],{"class":2201},[407,10634,10593],{"class":3864},[407,10636,8642],{"class":420},[407,10638,688],{"class":2201},[407,10640,10641],{"class":420},"APIError",[407,10643,6162],{"class":2201},[407,10645,10647,10649,10651,10653],{"class":409,"line":10646},125,[407,10648,9139],{"class":3864},[407,10650,8963],{"class":2201},[407,10652,8966],{"class":420},[407,10654,5434],{"class":2201},[407,10656,10658,10661,10663,10665,10668],{"class":409,"line":10657},126,[407,10659,10660],{"class":424},"        `Errore API (${",[407,10662,7786],{"class":2201},[407,10664,688],{"class":424},[407,10666,10667],{"class":2201},"status",[407,10669,10670],{"class":424},"}). Riprova tra qualche secondo.`\n",[407,10672,10674],{"class":409,"line":10673},127,[407,10675,6135],{"class":2201},[407,10677,10679,10681,10683],{"class":409,"line":10678},128,[407,10680,10624],{"class":2201},[407,10682,10627],{"class":3864},[407,10684,3871],{"class":2201},[407,10686,10688,10690,10692,10694,10696,10699],{"class":409,"line":10687},129,[407,10689,9139],{"class":3864},[407,10691,8963],{"class":2201},[407,10693,8966],{"class":420},[407,10695,5216],{"class":2201},[407,10697,10698],{"class":424},"\"Qualcosa e' andato storto. Riprova.\"",[407,10700,5083],{"class":2201},[407,10702,10704],{"class":409,"line":10703},130,[407,10705,2233],{"class":2201},[407,10707,10709],{"class":409,"line":10708},131,[407,10710,2238],{"class":2201},[407,10712,10714],{"class":409,"line":10713},132,[407,10715,5411],{"class":2201},[407,10717,10719],{"class":409,"line":10718},133,[407,10720,445],{"emptyLinePlaceholder":444},[407,10722,10724],{"class":409,"line":10723},134,[407,10725,9212],{"class":413},[407,10727,10729],{"class":409,"line":10728},135,[407,10730,445],{"emptyLinePlaceholder":444},[407,10732,10734,10736,10738],{"class":409,"line":10733},136,[407,10735,8904],{"class":2201},[407,10737,9272],{"class":420},[407,10739,5597],{"class":2201},[407,10741,10743,10745,10747,10749,10752],{"class":409,"line":10742},137,[407,10744,9280],{"class":2201},[407,10746,9283],{"class":420},[407,10748,5216],{"class":2201},[407,10750,10751],{"class":424},"\"Bot avviato con memoria conversazioni!\"",[407,10753,5083],{"class":2201},[407,10755,10757],{"class":409,"line":10756},138,[407,10758,445],{"emptyLinePlaceholder":444},[407,10760,10762,10764,10766,10768,10770,10772,10774,10776,10778,10780,10782],{"class":409,"line":10761},139,[407,10763,9307],{"class":2201},[407,10765,9310],{"class":420},[407,10767,5216],{"class":2201},[407,10769,9315],{"class":424},[407,10771,7774],{"class":2201},[407,10773,5574],{"class":3864},[407,10775,9322],{"class":2201},[407,10777,9325],{"class":420},[407,10779,5216],{"class":2201},[407,10781,9315],{"class":424},[407,10783,5345],{"class":2201},[407,10785,10787,10789,10791,10793,10795,10797,10799,10801,10803,10805,10807],{"class":409,"line":10786},140,[407,10788,9307],{"class":2201},[407,10790,9310],{"class":420},[407,10792,5216],{"class":2201},[407,10794,9343],{"class":424},[407,10796,7774],{"class":2201},[407,10798,5574],{"class":3864},[407,10800,9322],{"class":2201},[407,10802,9325],{"class":420},[407,10804,5216],{"class":2201},[407,10806,9343],{"class":424},[407,10808,5345],{"class":2201},[17,10810,10811,10812,10815],{},"Adesso il bot ricorda. Puoi dirgli \"mi chiamo Marco\" e tre messaggi dopo chiedergli come ti chiami -- lo sa. Il comando ",[353,10813,10814],{},"/reset"," pulisce la memoria quando vuoi ricominciare da zero.",[17,10817,10818,10819,10822],{},"La ",[353,10820,10821],{},"Map"," in memoria funziona perfettamente per un bot personale. Se il processo si riavvia, la conversazione riparte pulita. Per la persistenza tra restart (SQLite, file JSON), vedi la sezione finale con le idee per estendere il progetto.",[17,10824,10825,10826,10828],{},"Il parametro ",[353,10827,9899],{}," a 40 messaggi (20 scambi user/assistant) e' un buon compromesso: abbastanza contesto per conversazioni lunghe, senza far esplodere i costi. Con Haiku 4.5 e 800 token medi di contesto per messaggio, 40 messaggi sono circa 32K token di input -- ancora lontani dal limite di 200K.",[35,10830],{},[38,10832,10834],{"id":10833},"step-5-analizzare-immagini","Step 5: Analizzare Immagini",[17,10836,10837],{},"Claude e' multimodale. Gli mandi una foto e la capisce: screenshot di errori, scontrini, documenti, diagrammi, meme. E' una delle funzionalita' piu' utili in un assistente personale.",[17,10839,10840,10841,10844],{},"Il flusso: Telegram ci da' il file ID della foto, noi la scarichiamo, la convertiamo in base64 e la passiamo a Claude nel blocco ",[353,10842,10843],{},"image"," del messaggio.",[17,10846,10847,10848,1894],{},"Aggiungi questo handler dopo quello per i messaggi di testo, prima di ",[353,10849,10850],{},"bot.launch()",[346,10852,10854],{"className":3850,"code":10853,"language":3852,"meta":355,"style":355},"// --- Handler immagini ---\n\nbot.on(\"photo\", async (ctx) => {\n  if (!isAllowed(ctx.from.id)) {\n    return ctx.reply(\"Non sei autorizzato a usare questo bot.\");\n  }\n\n  try {\n    await ctx.sendChatAction(\"typing\");\n\n    // Prendi la versione a risoluzione piu' alta\n    const photos = ctx.message.photo;\n    const fileId = photos[photos.length - 1].file_id;\n\n    // Scarica il file da Telegram\n    const fileLink = await ctx.telegram.getFileLink(fileId);\n    const response = await fetch(fileLink.toString());\n    const buffer = Buffer.from(await response.arrayBuffer());\n    const base64Image = buffer.toString(\"base64\");\n\n    // Testo accompagnatorio (caption della foto o default)\n    const caption = ctx.message.caption || \"Cosa vedi in questa immagine?\";\n\n    // Aggiungi il messaggio utente con immagine alla history\n    const history = getHistory(ctx.from.id);\n    history.push({\n      role: \"user\",\n      content: [\n        {\n          type: \"image\",\n          source: {\n            type: \"base64\",\n            media_type: \"image/jpeg\",\n            data: base64Image,\n          },\n        },\n        { type: \"text\", text: caption },\n      ],\n    });\n\n    // Taglia la history se troppo lunga\n    if (history.length > MAX_HISTORY) {\n      conversations.set(ctx.from.id, history.slice(-MAX_HISTORY));\n    }\n\n    const claudeResponse = await claude.messages.create({\n      model: MODEL,\n      max_tokens: MAX_TOKENS,\n      system: SYSTEM_PROMPT,\n      messages: getHistory(ctx.from.id),\n    });\n\n    const reply = claudeResponse.content[0];\n    const text = reply.type === \"text\" ? reply.text : \"Non riesco ad analizzare questa immagine.\";\n\n    addMessage(ctx.from.id, \"assistant\", text);\n    await ctx.reply(text, { parse_mode: \"Markdown\" });\n  } catch (error) {\n    console.error(\"Errore analisi immagine:\", error);\n    await ctx.reply(\"Errore nell'analisi dell'immagine. Riprova.\");\n  }\n});\n",[353,10855,10856,10861,10865,10890,10902,10916,10920,10924,10930,10944,10948,10953,10965,10988,10992,10997,11017,11038,11064,11085,11089,11094,11113,11117,11122,11134,11143,11151,11156,11161,11171,11176,11185,11195,11200,11205,11210,11220,11225,11229,11233,11238,11252,11272,11276,11280,11297,11305,11313,11321,11331,11335,11339,11354,11379,11383,11395,11410,11418,11431,11446,11450],{"__ignoreMap":355},[407,10857,10858],{"class":409,"line":410},[407,10859,10860],{"class":413},"// --- Handler immagini ---\n",[407,10862,10863],{"class":409,"line":417},[407,10864,445],{"emptyLinePlaceholder":444},[407,10866,10867,10869,10871,10873,10876,10878,10880,10882,10884,10886,10888],{"class":409,"line":441},[407,10868,8904],{"class":2201},[407,10870,8907],{"class":420},[407,10872,5216],{"class":2201},[407,10874,10875],{"class":424},"\"photo\"",[407,10877,2078],{"class":2201},[407,10879,5164],{"class":3864},[407,10881,1486],{"class":2201},[407,10883,8920],{"class":3876},[407,10885,6395],{"class":2201},[407,10887,5574],{"class":3864},[407,10889,3871],{"class":2201},[407,10891,10892,10894,10896,10898,10900],{"class":409,"line":448},[407,10893,8841],{"class":3864},[407,10895,1486],{"class":2201},[407,10897,8626],{"class":3864},[407,10899,8953],{"class":420},[407,10901,10469],{"class":2201},[407,10903,10904,10906,10908,10910,10912,10914],{"class":409,"line":454},[407,10905,5231],{"class":3864},[407,10907,8963],{"class":2201},[407,10909,8966],{"class":420},[407,10911,5216],{"class":2201},[407,10913,8971],{"class":424},[407,10915,5083],{"class":2201},[407,10917,10918],{"class":409,"line":1667},[407,10919,2238],{"class":2201},[407,10921,10922],{"class":409,"line":1673},[407,10923,445],{"emptyLinePlaceholder":444},[407,10925,10926,10928],{"class":409,"line":1679},[407,10927,5192],{"class":3864},[407,10929,3871],{"class":2201},[407,10931,10932,10934,10936,10938,10940,10942],{"class":409,"line":1685},[407,10933,5693],{"class":3864},[407,10935,8963],{"class":2201},[407,10937,9023],{"class":420},[407,10939,5216],{"class":2201},[407,10941,9028],{"class":424},[407,10943,5083],{"class":2201},[407,10945,10946],{"class":409,"line":1690},[407,10947,445],{"emptyLinePlaceholder":444},[407,10949,10950],{"class":409,"line":1696},[407,10951,10952],{"class":413},"    // Prendi la versione a risoluzione piu' alta\n",[407,10954,10955,10957,10960,10962],{"class":409,"line":1702},[407,10956,5199],{"class":3864},[407,10958,10959],{"class":434}," photos",[407,10961,5062],{"class":3864},[407,10963,10964],{"class":2201}," ctx.message.photo;\n",[407,10966,10967,10969,10972,10974,10977,10979,10982,10985],{"class":409,"line":1708},[407,10968,5199],{"class":3864},[407,10970,10971],{"class":434}," fileId",[407,10973,5062],{"class":3864},[407,10975,10976],{"class":2201}," photos[photos.",[407,10978,6153],{"class":434},[407,10980,10981],{"class":3864}," -",[407,10983,10984],{"class":434}," 1",[407,10986,10987],{"class":2201},"].file_id;\n",[407,10989,10990],{"class":409,"line":1714},[407,10991,445],{"emptyLinePlaceholder":444},[407,10993,10994],{"class":409,"line":1719},[407,10995,10996],{"class":413},"    // Scarica il file da Telegram\n",[407,10998,10999,11001,11004,11006,11008,11011,11014],{"class":409,"line":1725},[407,11000,5199],{"class":3864},[407,11002,11003],{"class":434}," fileLink",[407,11005,5062],{"class":3864},[407,11007,5207],{"class":3864},[407,11009,11010],{"class":2201}," ctx.telegram.",[407,11012,11013],{"class":420},"getFileLink",[407,11015,11016],{"class":2201},"(fileId);\n",[407,11018,11019,11021,11023,11025,11027,11030,11033,11036],{"class":409,"line":1278},[407,11020,5199],{"class":3864},[407,11022,9041],{"class":434},[407,11024,5062],{"class":3864},[407,11026,5207],{"class":3864},[407,11028,11029],{"class":420}," fetch",[407,11031,11032],{"class":2201},"(fileLink.",[407,11034,11035],{"class":420},"toString",[407,11037,7654],{"class":2201},[407,11039,11040,11042,11045,11047,11050,11052,11054,11056,11059,11062],{"class":409,"line":1736},[407,11041,5199],{"class":3864},[407,11043,11044],{"class":434}," buffer",[407,11046,5062],{"class":3864},[407,11048,11049],{"class":2201}," Buffer.",[407,11051,4980],{"class":420},[407,11053,5216],{"class":2201},[407,11055,5802],{"class":3864},[407,11057,11058],{"class":2201}," response.",[407,11060,11061],{"class":420},"arrayBuffer",[407,11063,7654],{"class":2201},[407,11065,11066,11068,11071,11073,11076,11078,11080,11083],{"class":409,"line":1742},[407,11067,5199],{"class":3864},[407,11069,11070],{"class":434}," base64Image",[407,11072,5062],{"class":3864},[407,11074,11075],{"class":2201}," buffer.",[407,11077,11035],{"class":420},[407,11079,5216],{"class":2201},[407,11081,11082],{"class":424},"\"base64\"",[407,11084,5083],{"class":2201},[407,11086,11087],{"class":409,"line":1748},[407,11088,445],{"emptyLinePlaceholder":444},[407,11090,11091],{"class":409,"line":1753},[407,11092,11093],{"class":413},"    // Testo accompagnatorio (caption della foto o default)\n",[407,11095,11096,11098,11101,11103,11106,11108,11111],{"class":409,"line":1759},[407,11097,5199],{"class":3864},[407,11099,11100],{"class":434}," caption",[407,11102,5062],{"class":3864},[407,11104,11105],{"class":2201}," ctx.message.caption ",[407,11107,5646],{"class":3864},[407,11109,11110],{"class":424}," \"Cosa vedi in questa immagine?\"",[407,11112,4986],{"class":2201},[407,11114,11115],{"class":409,"line":1765},[407,11116,445],{"emptyLinePlaceholder":444},[407,11118,11119],{"class":409,"line":1771},[407,11120,11121],{"class":413},"    // Aggiungi il messaggio utente con immagine alla history\n",[407,11123,11124,11126,11128,11130,11132],{"class":409,"line":1777},[407,11125,5199],{"class":3864},[407,11127,9833],{"class":434},[407,11129,5062],{"class":3864},[407,11131,9698],{"class":420},[407,11133,10276],{"class":2201},[407,11135,11136,11139,11141],{"class":409,"line":1782},[407,11137,11138],{"class":2201},"    history.",[407,11140,5684],{"class":420},[407,11142,5385],{"class":2201},[407,11144,11145,11147,11149],{"class":409,"line":1788},[407,11146,6614],{"class":2201},[407,11148,6617],{"class":424},[407,11150,3384],{"class":2201},[407,11152,11153],{"class":409,"line":1794},[407,11154,11155],{"class":2201},"      content: [\n",[407,11157,11158],{"class":409,"line":5348},[407,11159,11160],{"class":2201},"        {\n",[407,11162,11163,11166,11169],{"class":409,"line":5353},[407,11164,11165],{"class":2201},"          type: ",[407,11167,11168],{"class":424},"\"image\"",[407,11170,3384],{"class":2201},[407,11172,11173],{"class":409,"line":5358},[407,11174,11175],{"class":2201},"          source: {\n",[407,11177,11178,11181,11183],{"class":409,"line":5364},[407,11179,11180],{"class":2201},"            type: ",[407,11182,11082],{"class":424},[407,11184,3384],{"class":2201},[407,11186,11187,11190,11193],{"class":409,"line":5369},[407,11188,11189],{"class":2201},"            media_type: ",[407,11191,11192],{"class":424},"\"image/jpeg\"",[407,11194,3384],{"class":2201},[407,11196,11197],{"class":409,"line":5388},[407,11198,11199],{"class":2201},"            data: base64Image,\n",[407,11201,11202],{"class":409,"line":5399},[407,11203,11204],{"class":2201},"          },\n",[407,11206,11207],{"class":409,"line":5408},[407,11208,11209],{"class":2201},"        },\n",[407,11211,11212,11215,11217],{"class":409,"line":5414},[407,11213,11214],{"class":2201},"        { type: ",[407,11216,5720],{"class":424},[407,11218,11219],{"class":2201},", text: caption },\n",[407,11221,11222],{"class":409,"line":5419},[407,11223,11224],{"class":2201},"      ],\n",[407,11226,11227],{"class":409,"line":5425},[407,11228,9098],{"class":2201},[407,11230,11231],{"class":409,"line":5437},[407,11232,445],{"emptyLinePlaceholder":444},[407,11234,11235],{"class":409,"line":5449},[407,11236,11237],{"class":413},"    // Taglia la history se troppo lunga\n",[407,11239,11240,11242,11244,11246,11248,11250],{"class":409,"line":5461},[407,11241,6074],{"class":3864},[407,11243,9865],{"class":2201},[407,11245,6153],{"class":434},[407,11247,9870],{"class":3864},[407,11249,9637],{"class":434},[407,11251,6162],{"class":2201},[407,11253,11254,11257,11259,11262,11264,11266,11268,11270],{"class":409,"line":5470},[407,11255,11256],{"class":2201},"      conversations.",[407,11258,9739],{"class":420},[407,11260,11261],{"class":2201},"(ctx.from.id, history.",[407,11263,9891],{"class":420},[407,11265,5216],{"class":2201},[407,11267,9896],{"class":3864},[407,11269,9899],{"class":434},[407,11271,5345],{"class":2201},[407,11273,11274],{"class":409,"line":5493},[407,11275,2233],{"class":2201},[407,11277,11278],{"class":409,"line":5512},[407,11279,445],{"emptyLinePlaceholder":444},[407,11281,11282,11284,11287,11289,11291,11293,11295],{"class":409,"line":5544},[407,11283,5199],{"class":3864},[407,11285,11286],{"class":434}," claudeResponse",[407,11288,5062],{"class":3864},[407,11290,5207],{"class":3864},[407,11292,9048],{"class":2201},[407,11294,9051],{"class":420},[407,11296,5385],{"class":2201},[407,11298,11299,11301,11303],{"class":409,"line":5549},[407,11300,9058],{"class":2201},[407,11302,9061],{"class":434},[407,11304,3384],{"class":2201},[407,11306,11307,11309,11311],{"class":409,"line":5583},[407,11308,9068],{"class":2201},[407,11310,9071],{"class":434},[407,11312,3384],{"class":2201},[407,11314,11315,11317,11319],{"class":409,"line":5600},[407,11316,9078],{"class":2201},[407,11318,9081],{"class":434},[407,11320,3384],{"class":2201},[407,11322,11323,11326,11328],{"class":409,"line":5616},[407,11324,11325],{"class":2201},"      messages: ",[407,11327,10101],{"class":420},[407,11329,11330],{"class":2201},"(ctx.from.id),\n",[407,11332,11333],{"class":409,"line":5628},[407,11334,9098],{"class":2201},[407,11336,11337],{"class":409,"line":5634},[407,11338,445],{"emptyLinePlaceholder":444},[407,11340,11341,11343,11345,11347,11350,11352],{"class":409,"line":5640},[407,11342,5199],{"class":3864},[407,11344,9109],{"class":434},[407,11346,5062],{"class":3864},[407,11348,11349],{"class":2201}," claudeResponse.content[",[407,11351,9117],{"class":434},[407,11353,9120],{"class":2201},[407,11355,11356,11358,11360,11362,11364,11366,11368,11370,11372,11374,11377],{"class":409,"line":5652},[407,11357,5199],{"class":3864},[407,11359,10133],{"class":434},[407,11361,5062],{"class":3864},[407,11363,10138],{"class":2201},[407,11365,6122],{"class":3864},[407,11367,9132],{"class":424},[407,11369,10145],{"class":3864},[407,11371,10148],{"class":2201},[407,11373,1894],{"class":3864},[407,11375,11376],{"class":424}," \"Non riesco ad analizzare questa immagine.\"",[407,11378,4986],{"class":2201},[407,11380,11381],{"class":409,"line":5672},[407,11382,445],{"emptyLinePlaceholder":444},[407,11384,11385,11388,11391,11393],{"class":409,"line":5678},[407,11386,11387],{"class":420},"    addMessage",[407,11389,11390],{"class":2201},"(ctx.from.id, ",[407,11392,10168],{"class":424},[407,11394,10171],{"class":2201},[407,11396,11397,11399,11401,11403,11406,11408],{"class":409,"line":5690},[407,11398,5693],{"class":3864},[407,11400,8963],{"class":2201},[407,11402,8966],{"class":420},[407,11404,11405],{"class":2201},"(text, { parse_mode: ",[407,11407,9149],{"class":424},[407,11409,9152],{"class":2201},[407,11411,11412,11414,11416],{"class":409,"line":5701},[407,11413,5247],{"class":2201},[407,11415,5250],{"class":3864},[407,11417,9165],{"class":2201},[407,11419,11420,11422,11424,11426,11429],{"class":409,"line":5708},[407,11421,9170],{"class":2201},[407,11423,7786],{"class":420},[407,11425,5216],{"class":2201},[407,11427,11428],{"class":424},"\"Errore analisi immagine:\"",[407,11430,9180],{"class":2201},[407,11432,11433,11435,11437,11439,11441,11444],{"class":409,"line":5714},[407,11434,5693],{"class":3864},[407,11436,8963],{"class":2201},[407,11438,8966],{"class":420},[407,11440,5216],{"class":2201},[407,11442,11443],{"class":424},"\"Errore nell'analisi dell'immagine. Riprova.\"",[407,11445,5083],{"class":2201},[407,11447,11448],{"class":409,"line":5725},[407,11449,2238],{"class":2201},[407,11451,11452],{"class":409,"line":5750},[407,11453,5411],{"class":2201},[17,11455,11456],{},"Ora puoi mandare al bot una foto di uno scontrino con la caption \"Quanto ho speso?\" e Claude ti da' il totale. Oppure uno screenshot di un errore nel terminale con \"Come lo risolvo?\" e ti spiega il fix.",[17,11458,11459,11460,11463],{},"Un dettaglio: Telegram fornisce le foto in piu' risoluzioni. Con ",[353,11461,11462],{},"photos[photos.length - 1]"," prendiamo sempre quella piu' alta. Per immagini pesanti, potresti preferire una risoluzione intermedia per risparmiare token (Claude fattura anche i token delle immagini).",[35,11465],{},[38,11467,11469],{"id":11468},"step-6-streaming-delle-risposte","Step 6: Streaming delle Risposte",[17,11471,11472],{},"Fino a qui, il bot aspetta che Claude finisca di generare l'intera risposta prima di inviarla. Per risposte lunghe, l'utente fissa il \"sta scrivendo...\" per 5-10 secondi senza feedback. Non e' una gran esperienza.",[17,11474,11475,11476,11478],{},"La Bot API 9.3 (dicembre 2025) ha introdotto ",[353,11477,8140],{},", un metodo nativo per lo streaming dei messaggi, e la Bot API 9.5 (marzo 2026) lo ha reso disponibile a tutti i bot. Il bot invia frammenti incrementali e Telegram li anima nativamente sul client, senza flickering.",[17,11480,11481,11482,11485],{},"Sostituisci la funzione ",[353,11483,11484],{},"chat"," e l'handler dei messaggi di testo con questa versione con streaming:",[346,11487,11489],{"className":3850,"code":11488,"language":3852,"meta":355,"style":355},"// --- Chat con Claude (streaming) ---\n\nasync function chatStream(\n  userId: number,\n  userMessage: string,\n  ctx: any\n): Promise\u003Cvoid> {\n  addMessage(userId, \"user\", userMessage);\n\n  const stream = claude.messages.stream({\n    model: MODEL,\n    max_tokens: MAX_TOKENS,\n    system: SYSTEM_PROMPT,\n    messages: getHistory(userId),\n  });\n\n  let fullText = \"\";\n  let lastSentLength = 0;\n  const chatId = ctx.chat.id;\n  const draftId = Date.now(); // draft_id deve essere un intero non-zero\n\n  // Invia frammenti incrementali con sendMessageDraft\n  stream.on(\"text\", async (textDelta) => {\n    fullText += textDelta;\n\n    // Aggiorna ogni 80 caratteri o su newline per bilanciare\n    // fluidita' visiva e rate limit Telegram\n    if (\n      fullText.length - lastSentLength > 80 ||\n      textDelta.includes(\"\\n\")\n    ) {\n      try {\n        await ctx.telegram.callApi(\"sendMessageDraft\", {\n          chat_id: chatId,\n          draft_id: draftId,\n          text: fullText,\n        });\n        lastSentLength = fullText.length;\n      } catch {\n        // Rate limit Telegram -- skip questo aggiornamento\n      }\n    }\n  });\n\n  // Attendi la fine dello stream\n  const finalMessage = await stream.finalMessage();\n\n  const reply = finalMessage.content[0];\n  const text = reply.type === \"text\" ? reply.text : \"\";\n  fullText = text;\n\n  // Messaggio finale definitivo\n  await ctx.reply(fullText, { parse_mode: \"Markdown\" });\n\n  addMessage(userId, \"assistant\", fullText);\n}\n\n// --- Handler messaggi di testo (con streaming) ---\n\nbot.on(\"text\", async (ctx) => {\n  if (!isAllowed(ctx.from.id)) {\n    return ctx.reply(\"Non sei autorizzato a usare questo bot.\");\n  }\n\n  try {\n    await ctx.sendChatAction(\"typing\");\n    await chatStream(ctx.from.id, ctx.message.text, ctx);\n  } catch (error) {\n    console.error(\"Errore:\", error);\n\n    if (error instanceof Anthropic.RateLimitError) {\n      await ctx.reply(\"Troppe richieste. Aspetta qualche secondo e riprova.\");\n    } else if (error instanceof Anthropic.APIError) {\n      await ctx.reply(\n        `Errore API (${error.status}). Riprova tra qualche secondo.`\n      );\n    } else {\n      await ctx.reply(\"Qualcosa e' andato storto. Riprova.\");\n    }\n  }\n});\n",[353,11490,11491,11496,11500,11511,11521,11532,11542,11556,11566,11570,11586,11594,11602,11610,11618,11622,11626,11640,11653,11665,11685,11689,11694,11720,11731,11735,11740,11745,11752,11772,11789,11794,11801,11819,11824,11829,11834,11839,11853,11862,11867,11871,11875,11879,11883,11888,11907,11911,11926,11950,11959,11963,11968,11983,11987,11998,12002,12006,12011,12015,12039,12051,12065,12069,12073,12079,12093,12102,12110,12122,12126,12142,12156,12176,12186,12198,12202,12210,12224,12228,12232],{"__ignoreMap":355},[407,11492,11493],{"class":409,"line":410},[407,11494,11495],{"class":413},"// --- Chat con Claude (streaming) ---\n",[407,11497,11498],{"class":409,"line":417},[407,11499,445],{"emptyLinePlaceholder":444},[407,11501,11502,11504,11506,11509],{"class":409,"line":441},[407,11503,5164],{"class":3864},[407,11505,5167],{"class":3864},[407,11507,11508],{"class":420}," chatStream",[407,11510,5434],{"class":2201},[407,11512,11513,11515,11517,11519],{"class":409,"line":448},[407,11514,9785],{"class":3876},[407,11516,1894],{"class":3864},[407,11518,8827],{"class":434},[407,11520,3384],{"class":2201},[407,11522,11523,11526,11528,11530],{"class":409,"line":454},[407,11524,11525],{"class":3876},"  userMessage",[407,11527,1894],{"class":3864},[407,11529,5105],{"class":434},[407,11531,3384],{"class":2201},[407,11533,11534,11537,11539],{"class":409,"line":1667},[407,11535,11536],{"class":3876},"  ctx",[407,11538,1894],{"class":3864},[407,11540,11541],{"class":434}," any\n",[407,11543,11544,11546,11548,11550,11552,11554],{"class":409,"line":1673},[407,11545,6250],{"class":2201},[407,11547,1894],{"class":3864},[407,11549,5178],{"class":420},[407,11551,5181],{"class":2201},[407,11553,5304],{"class":434},[407,11555,5307],{"class":2201},[407,11557,11558,11560,11562,11564],{"class":409,"line":1679},[407,11559,10038],{"class":420},[407,11561,10041],{"class":2201},[407,11563,6617],{"class":424},[407,11565,10046],{"class":2201},[407,11567,11568],{"class":409,"line":1685},[407,11569,445],{"emptyLinePlaceholder":444},[407,11571,11572,11574,11577,11579,11581,11584],{"class":409,"line":1690},[407,11573,7695],{"class":3864},[407,11575,11576],{"class":434}," stream",[407,11578,5062],{"class":3864},[407,11580,9048],{"class":2201},[407,11582,11583],{"class":420},"stream",[407,11585,5385],{"class":2201},[407,11587,11588,11590,11592],{"class":409,"line":1696},[407,11589,10071],{"class":2201},[407,11591,9061],{"class":434},[407,11593,3384],{"class":2201},[407,11595,11596,11598,11600],{"class":409,"line":1702},[407,11597,10080],{"class":2201},[407,11599,9071],{"class":434},[407,11601,3384],{"class":2201},[407,11603,11604,11606,11608],{"class":409,"line":1708},[407,11605,10089],{"class":2201},[407,11607,9081],{"class":434},[407,11609,3384],{"class":2201},[407,11611,11612,11614,11616],{"class":409,"line":1714},[407,11613,10098],{"class":2201},[407,11615,10101],{"class":420},[407,11617,10104],{"class":2201},[407,11619,11620],{"class":409,"line":1719},[407,11621,7728],{"class":2201},[407,11623,11624],{"class":409,"line":1725},[407,11625,445],{"emptyLinePlaceholder":444},[407,11627,11628,11631,11634,11636,11638],{"class":409,"line":1278},[407,11629,11630],{"class":3864},"  let",[407,11632,11633],{"class":2201}," fullText ",[407,11635,6014],{"class":3864},[407,11637,8681],{"class":424},[407,11639,4986],{"class":2201},[407,11641,11642,11644,11647,11649,11651],{"class":409,"line":1736},[407,11643,11630],{"class":3864},[407,11645,11646],{"class":2201}," lastSentLength ",[407,11648,6014],{"class":3864},[407,11650,6159],{"class":434},[407,11652,4986],{"class":2201},[407,11654,11655,11657,11660,11662],{"class":409,"line":1742},[407,11656,7695],{"class":3864},[407,11658,11659],{"class":434}," chatId",[407,11661,5062],{"class":3864},[407,11663,11664],{"class":2201}," ctx.chat.id;\n",[407,11666,11667,11669,11672,11674,11677,11680,11682],{"class":409,"line":1748},[407,11668,7695],{"class":3864},[407,11670,11671],{"class":434}," draftId",[407,11673,5062],{"class":3864},[407,11675,11676],{"class":2201}," Date.",[407,11678,11679],{"class":420},"now",[407,11681,8645],{"class":2201},[407,11683,11684],{"class":413},"// draft_id deve essere un intero non-zero\n",[407,11686,11687],{"class":409,"line":1753},[407,11688,445],{"emptyLinePlaceholder":444},[407,11690,11691],{"class":409,"line":1759},[407,11692,11693],{"class":413},"  // Invia frammenti incrementali con sendMessageDraft\n",[407,11695,11696,11699,11701,11703,11705,11707,11709,11711,11714,11716,11718],{"class":409,"line":1765},[407,11697,11698],{"class":2201},"  stream.",[407,11700,8907],{"class":420},[407,11702,5216],{"class":2201},[407,11704,5720],{"class":424},[407,11706,2078],{"class":2201},[407,11708,5164],{"class":3864},[407,11710,1486],{"class":2201},[407,11712,11713],{"class":3876},"textDelta",[407,11715,6395],{"class":2201},[407,11717,5574],{"class":3864},[407,11719,3871],{"class":2201},[407,11721,11722,11725,11728],{"class":409,"line":1771},[407,11723,11724],{"class":2201},"    fullText ",[407,11726,11727],{"class":3864},"+=",[407,11729,11730],{"class":2201}," textDelta;\n",[407,11732,11733],{"class":409,"line":1777},[407,11734,445],{"emptyLinePlaceholder":444},[407,11736,11737],{"class":409,"line":1782},[407,11738,11739],{"class":413},"    // Aggiorna ogni 80 caratteri o su newline per bilanciare\n",[407,11741,11742],{"class":409,"line":1788},[407,11743,11744],{"class":413},"    // fluidita' visiva e rate limit Telegram\n",[407,11746,11747,11749],{"class":409,"line":1794},[407,11748,6074],{"class":3864},[407,11750,11751],{"class":2201}," (\n",[407,11753,11754,11757,11759,11761,11763,11766,11769],{"class":409,"line":5348},[407,11755,11756],{"class":2201},"      fullText.",[407,11758,6153],{"class":434},[407,11760,10981],{"class":3864},[407,11762,11646],{"class":2201},[407,11764,11765],{"class":3864},">",[407,11767,11768],{"class":434}," 80",[407,11770,11771],{"class":3864}," ||\n",[407,11773,11774,11777,11779,11781,11783,11785,11787],{"class":409,"line":5353},[407,11775,11776],{"class":2201},"      textDelta.",[407,11778,6040],{"class":420},[407,11780,5216],{"class":2201},[407,11782,6280],{"class":424},[407,11784,6256],{"class":434},[407,11786,6280],{"class":424},[407,11788,5541],{"class":2201},[407,11790,11791],{"class":409,"line":5358},[407,11792,11793],{"class":2201},"    ) {\n",[407,11795,11796,11799],{"class":409,"line":5364},[407,11797,11798],{"class":3864},"      try",[407,11800,3871],{"class":2201},[407,11802,11803,11806,11808,11811,11813,11816],{"class":409,"line":5369},[407,11804,11805],{"class":3864},"        await",[407,11807,11010],{"class":2201},[407,11809,11810],{"class":420},"callApi",[407,11812,5216],{"class":2201},[407,11814,11815],{"class":424},"\"sendMessageDraft\"",[407,11817,11818],{"class":2201},", {\n",[407,11820,11821],{"class":409,"line":5388},[407,11822,11823],{"class":2201},"          chat_id: chatId,\n",[407,11825,11826],{"class":409,"line":5399},[407,11827,11828],{"class":2201},"          draft_id: draftId,\n",[407,11830,11831],{"class":409,"line":5408},[407,11832,11833],{"class":2201},"          text: fullText,\n",[407,11835,11836],{"class":409,"line":5414},[407,11837,11838],{"class":2201},"        });\n",[407,11840,11841,11844,11846,11849,11851],{"class":409,"line":5419},[407,11842,11843],{"class":2201},"        lastSentLength ",[407,11845,6014],{"class":3864},[407,11847,11848],{"class":2201}," fullText.",[407,11850,6153],{"class":434},[407,11852,4986],{"class":2201},[407,11854,11855,11858,11860],{"class":409,"line":5425},[407,11856,11857],{"class":2201},"      } ",[407,11859,5250],{"class":3864},[407,11861,3871],{"class":2201},[407,11863,11864],{"class":409,"line":5437},[407,11865,11866],{"class":413},"        // Rate limit Telegram -- skip questo aggiornamento\n",[407,11868,11869],{"class":409,"line":5449},[407,11870,3454],{"class":2201},[407,11872,11873],{"class":409,"line":5461},[407,11874,2233],{"class":2201},[407,11876,11877],{"class":409,"line":5470},[407,11878,7728],{"class":2201},[407,11880,11881],{"class":409,"line":5493},[407,11882,445],{"emptyLinePlaceholder":444},[407,11884,11885],{"class":409,"line":5512},[407,11886,11887],{"class":413},"  // Attendi la fine dello stream\n",[407,11889,11890,11892,11895,11897,11899,11902,11905],{"class":409,"line":5544},[407,11891,7695],{"class":3864},[407,11893,11894],{"class":434}," finalMessage",[407,11896,5062],{"class":3864},[407,11898,5207],{"class":3864},[407,11900,11901],{"class":2201}," stream.",[407,11903,11904],{"class":420},"finalMessage",[407,11906,5597],{"class":2201},[407,11908,11909],{"class":409,"line":5549},[407,11910,445],{"emptyLinePlaceholder":444},[407,11912,11913,11915,11917,11919,11922,11924],{"class":409,"line":5583},[407,11914,7695],{"class":3864},[407,11916,9109],{"class":434},[407,11918,5062],{"class":3864},[407,11920,11921],{"class":2201}," finalMessage.content[",[407,11923,9117],{"class":434},[407,11925,9120],{"class":2201},[407,11927,11928,11930,11932,11934,11936,11938,11940,11942,11944,11946,11948],{"class":409,"line":5600},[407,11929,7695],{"class":3864},[407,11931,10133],{"class":434},[407,11933,5062],{"class":3864},[407,11935,10138],{"class":2201},[407,11937,6122],{"class":3864},[407,11939,9132],{"class":424},[407,11941,10145],{"class":3864},[407,11943,10148],{"class":2201},[407,11945,1894],{"class":3864},[407,11947,8681],{"class":424},[407,11949,4986],{"class":2201},[407,11951,11952,11955,11957],{"class":409,"line":5616},[407,11953,11954],{"class":2201},"  fullText ",[407,11956,6014],{"class":3864},[407,11958,10179],{"class":2201},[407,11960,11961],{"class":409,"line":5628},[407,11962,445],{"emptyLinePlaceholder":444},[407,11964,11965],{"class":409,"line":5634},[407,11966,11967],{"class":413},"  // Messaggio finale definitivo\n",[407,11969,11970,11972,11974,11976,11979,11981],{"class":409,"line":5640},[407,11971,5312],{"class":3864},[407,11973,8963],{"class":2201},[407,11975,8966],{"class":420},[407,11977,11978],{"class":2201},"(fullText, { parse_mode: ",[407,11980,9149],{"class":424},[407,11982,9152],{"class":2201},[407,11984,11985],{"class":409,"line":5652},[407,11986,445],{"emptyLinePlaceholder":444},[407,11988,11989,11991,11993,11995],{"class":409,"line":5672},[407,11990,10038],{"class":420},[407,11992,10041],{"class":2201},[407,11994,10168],{"class":424},[407,11996,11997],{"class":2201},", fullText);\n",[407,11999,12000],{"class":409,"line":5678},[407,12001,2243],{"class":2201},[407,12003,12004],{"class":409,"line":5690},[407,12005,445],{"emptyLinePlaceholder":444},[407,12007,12008],{"class":409,"line":5701},[407,12009,12010],{"class":413},"// --- Handler messaggi di testo (con streaming) ---\n",[407,12012,12013],{"class":409,"line":5708},[407,12014,445],{"emptyLinePlaceholder":444},[407,12016,12017,12019,12021,12023,12025,12027,12029,12031,12033,12035,12037],{"class":409,"line":5714},[407,12018,8904],{"class":2201},[407,12020,8907],{"class":420},[407,12022,5216],{"class":2201},[407,12024,5720],{"class":424},[407,12026,2078],{"class":2201},[407,12028,5164],{"class":3864},[407,12030,1486],{"class":2201},[407,12032,8920],{"class":3876},[407,12034,6395],{"class":2201},[407,12036,5574],{"class":3864},[407,12038,3871],{"class":2201},[407,12040,12041,12043,12045,12047,12049],{"class":409,"line":5725},[407,12042,8841],{"class":3864},[407,12044,1486],{"class":2201},[407,12046,8626],{"class":3864},[407,12048,8953],{"class":420},[407,12050,10469],{"class":2201},[407,12052,12053,12055,12057,12059,12061,12063],{"class":409,"line":5750},[407,12054,5231],{"class":3864},[407,12056,8963],{"class":2201},[407,12058,8966],{"class":420},[407,12060,5216],{"class":2201},[407,12062,8971],{"class":424},[407,12064,5083],{"class":2201},[407,12066,12067],{"class":409,"line":5756},[407,12068,2238],{"class":2201},[407,12070,12071],{"class":409,"line":5761},[407,12072,445],{"emptyLinePlaceholder":444},[407,12074,12075,12077],{"class":409,"line":5766},[407,12076,5192],{"class":3864},[407,12078,3871],{"class":2201},[407,12080,12081,12083,12085,12087,12089,12091],{"class":409,"line":5771},[407,12082,5693],{"class":3864},[407,12084,8963],{"class":2201},[407,12086,9023],{"class":420},[407,12088,5216],{"class":2201},[407,12090,9028],{"class":424},[407,12092,5083],{"class":2201},[407,12094,12095,12097,12099],{"class":409,"line":5776},[407,12096,5693],{"class":3864},[407,12098,11508],{"class":420},[407,12100,12101],{"class":2201},"(ctx.from.id, ctx.message.text, ctx);\n",[407,12103,12104,12106,12108],{"class":409,"line":5782},[407,12105,5247],{"class":2201},[407,12107,5250],{"class":3864},[407,12109,9165],{"class":2201},[407,12111,12112,12114,12116,12118,12120],{"class":409,"line":5799},[407,12113,9170],{"class":2201},[407,12115,7786],{"class":420},[407,12117,5216],{"class":2201},[407,12119,10569],{"class":424},[407,12121,9180],{"class":2201},[407,12123,12124],{"class":409,"line":9219},[407,12125,445],{"emptyLinePlaceholder":444},[407,12127,12128,12130,12132,12134,12136,12138,12140],{"class":409,"line":9242},[407,12129,6074],{"class":3864},[407,12131,10590],{"class":2201},[407,12133,10593],{"class":3864},[407,12135,8642],{"class":420},[407,12137,688],{"class":2201},[407,12139,10600],{"class":420},[407,12141,6162],{"class":2201},[407,12143,12144,12146,12148,12150,12152,12154],{"class":409,"line":9257},[407,12145,9139],{"class":3864},[407,12147,8963],{"class":2201},[407,12149,8966],{"class":420},[407,12151,5216],{"class":2201},[407,12153,10616],{"class":424},[407,12155,5083],{"class":2201},[407,12157,12158,12160,12162,12164,12166,12168,12170,12172,12174],{"class":409,"line":9262},[407,12159,10624],{"class":2201},[407,12161,10627],{"class":3864},[407,12163,10630],{"class":3864},[407,12165,10590],{"class":2201},[407,12167,10593],{"class":3864},[407,12169,8642],{"class":420},[407,12171,688],{"class":2201},[407,12173,10641],{"class":420},[407,12175,6162],{"class":2201},[407,12177,12178,12180,12182,12184],{"class":409,"line":9267},[407,12179,9139],{"class":3864},[407,12181,8963],{"class":2201},[407,12183,8966],{"class":420},[407,12185,5434],{"class":2201},[407,12187,12188,12190,12192,12194,12196],{"class":409,"line":9277},[407,12189,10660],{"class":424},[407,12191,7786],{"class":2201},[407,12193,688],{"class":424},[407,12195,10667],{"class":2201},[407,12197,10670],{"class":424},[407,12199,12200],{"class":409,"line":9293},[407,12201,6135],{"class":2201},[407,12203,12204,12206,12208],{"class":409,"line":9298},[407,12205,10624],{"class":2201},[407,12207,10627],{"class":3864},[407,12209,3871],{"class":2201},[407,12211,12212,12214,12216,12218,12220,12222],{"class":409,"line":9304},[407,12213,9139],{"class":3864},[407,12215,8963],{"class":2201},[407,12217,8966],{"class":420},[407,12219,5216],{"class":2201},[407,12221,10698],{"class":424},[407,12223,5083],{"class":2201},[407,12225,12226],{"class":409,"line":9334},[407,12227,2233],{"class":2201},[407,12229,12230],{"class":409,"line":10174},[407,12231,2238],{"class":2201},[407,12233,12234],{"class":409,"line":10182},[407,12235,5411],{"class":2201},[17,12237,12238,12239,12242,12243,12245],{},"Il metodo ",[353,12240,12241],{},"claude.messages.stream()"," dell'SDK Anthropic restituisce un oggetto che emette eventi ",[353,12244,351],{}," con ogni frammento generato. Noi li accumuliamo e aggiorniamo il draft ogni ~80 caratteri.",[17,12247,12248],{},"Il throttling a 80 caratteri e' un compromesso: troppo frequente e batti il rate limit di Telegram (1 richiesta/secondo per chat), troppo raro e perdi l'effetto streaming. Se preferisci, puoi anche usare un throttle basato sul tempo (es. 1500ms).",[17,12250,12251,2225,12254,12256,12257,12260],{},[24,12252,12253],{},"Nota",[353,12255,8140],{}," e' disponibile per tutti i bot dal 1 marzo 2026. Verifica che la tua versione di Telegraf lo supporti. Se non c'e' ancora il metodo wrapper, puoi usare ",[353,12258,12259],{},"ctx.telegram.callApi()"," come nell'esempio sopra per chiamare direttamente l'API.",[17,12262,12263,12266,12267,12269],{},[24,12264,12265],{},"Fallback senza streaming",": se preferisci non usare lo streaming (o la tua versione di Telegraf non supporta ancora ",[353,12268,8140],{},"), la versione dello Step 4 funziona benissimo. L'utente attende qualche secondo in piu', ma il risultato e' identico.",[35,12271],{},[38,12273,12275],{"id":12274},"step-7-deploy-su-railway","Step 7: Deploy su Railway",[17,12277,12278],{},"Il bot funziona in locale. Ora serve farlo girare 24/7 senza tenere il portatile acceso. Railway e' l'opzione piu' semplice: deploy da GitHub in due minuti, $5/mese per il piano Hobby.",[58,12280,12282],{"id":12281},"preparazione","Preparazione",[17,12284,12285,12286,6959],{},"Aggiungi un ",[353,12287,12288],{},"Procfile",[346,12290,12293],{"className":12291,"code":12292,"language":351},[349],"worker: npx tsx src/bot.ts\n",[353,12294,12292],{"__ignoreMap":355},[17,12296,12297,12298,12301],{},"Il tipo ",[353,12299,12300],{},"worker"," dice a Railway che e' un processo long-running, non un web server. Non serve esporre porte.",[17,12303,12304],{},"Committa tutto su un repository GitHub:",[346,12306,12308],{"className":401,"code":12307,"language":403,"meta":355,"style":355},"git init\ngit add .\ngit commit -m \"Telegram bot con Claude API\"\ngit remote add origin https://github.com/tuo-user/telegram-claude-bot.git\ngit push -u origin main\n",[353,12309,12310,12317,12326,12339,12354],{"__ignoreMap":355},[407,12311,12312,12314],{"class":409,"line":410},[407,12313,421],{"class":420},[407,12315,12316],{"class":424}," init\n",[407,12318,12319,12321,12323],{"class":409,"line":417},[407,12320,421],{"class":420},[407,12322,428],{"class":424},[407,12324,12325],{"class":424}," .\n",[407,12327,12328,12330,12333,12336],{"class":409,"line":441},[407,12329,421],{"class":420},[407,12331,12332],{"class":424}," commit",[407,12334,12335],{"class":434}," -m",[407,12337,12338],{"class":424}," \"Telegram bot con Claude API\"\n",[407,12340,12341,12343,12346,12348,12351],{"class":409,"line":448},[407,12342,421],{"class":420},[407,12344,12345],{"class":424}," remote",[407,12347,428],{"class":424},[407,12349,12350],{"class":424}," origin",[407,12352,12353],{"class":424}," https://github.com/tuo-user/telegram-claude-bot.git\n",[407,12355,12356,12358,12361,12364,12366],{"class":409,"line":454},[407,12357,421],{"class":420},[407,12359,12360],{"class":424}," push",[407,12362,12363],{"class":434}," -u",[407,12365,12350],{"class":424},[407,12367,12368],{"class":424}," main\n",[58,12370,12372],{"id":12371},"deploy","Deploy",[517,12374,12375,12384,12391,12394,12415],{},[85,12376,12377,12378,12383],{},"Vai su ",[69,12379,12382],{"href":12380,"rel":12381},"https://railway.com",[1152],"railway.com"," e accedi con GitHub",[85,12385,12386,12387,12390],{},"Clicca ",[24,12388,12389],{},"New Project"," e seleziona il repository",[85,12392,12393],{},"Railway rileva automaticamente il progetto Node.js",[85,12395,12396,12397,12400,12401],{},"Vai in ",[24,12398,12399],{},"Settings > Variables"," e aggiungi le tre variabili d'ambiente:\n",[82,12402,12403,12407,12411],{},[85,12404,12405],{},[353,12406,8488],{},[85,12408,12409],{},[353,12410,8498],{},[85,12412,12413],{},[353,12414,8508],{},[85,12416,12417],{},"Il deploy parte automaticamente",[17,12419,12420,12421,12424],{},"In 30 secondi il bot e' online. Ogni push su ",[353,12422,12423],{},"main"," triggera un nuovo deploy.",[58,12426,12428],{"id":12427},"alternative","Alternative",[17,12430,12431],{},"Se $5/mese per Railway ti sembra troppo per un progetto personale, le alternative non mancano:",[244,12433,12434,12446],{},[247,12435,12436],{},[250,12437,12438,12441,12444],{},[253,12439,12440],{},"Piattaforma",[253,12442,12443],{},"Costo/mese",[253,12445,5184],{},[260,12447,12448,12462,12476,12490],{},[250,12449,12450,12456,12459],{},[265,12451,12452,12455],{},[24,12453,12454],{},"Railway"," (Hobby)",[265,12457,12458],{},"$5",[265,12460,12461],{},"Setup piu' semplice in assoluto",[250,12463,12464,12470,12473],{},[265,12465,12466,12469],{},[24,12467,12468],{},"VPS Hetzner"," (CX22)",[265,12471,12472],{},"~$4.50",[265,12474,12475],{},"Controllo totale, setup manuale",[250,12477,12478,12484,12487],{},[265,12479,12480,12483],{},[24,12481,12482],{},"Oracle Cloud"," (ARM)",[265,12485,12486],{},"Gratis",[265,12488,12489],{},"Always Free tier, 4 CPU + 24GB RAM, setup complesso",[250,12491,12492,12498,12501],{},[265,12493,12494,12497],{},[24,12495,12496],{},"Raspberry Pi"," a casa",[265,12499,12500],{},"Una tantum ~$50",[265,12502,12503],{},"Zero costi ricorrenti, serve tunnel (Cloudflare)",[17,12505,12506,12507,12510,12511,1486,12514,12517],{},"Per un VPS o un Raspberry Pi, basta avere Node.js installato, clonare il repo, settare le variabili d'ambiente e avviare con ",[353,12508,12509],{},"npm start",". Un process manager come ",[24,12512,12513],{},"pm2",[353,12515,12516],{},"pm2 start npx -- tsx src/bot.ts",") lo tiene in vita dopo i crash.",[35,12519],{},[38,12521,12523],{"id":12522},"quanto-costa-davvero","Quanto Costa Davvero",[17,12525,12526],{},"Il momento della verita'. Mettiamo i numeri in fila.",[17,12528,12529,12532],{},[24,12530,12531],{},"Scenario",": uso personale, ~100 messaggi al giorno, conversazioni di lunghezza media.",[58,12534,12536],{"id":12535},"costi-claude-api-haiku-45","Costi Claude API (Haiku 4.5)",[244,12538,12539,12549],{},[247,12540,12541],{},[250,12542,12543,12546],{},[253,12544,12545],{},"Parametro",[253,12547,12548],{},"Valore",[260,12550,12551,12559,12567,12575,12583],{},[250,12552,12553,12556],{},[265,12554,12555],{},"Messaggi/giorno",[265,12557,12558],{},"100",[250,12560,12561,12564],{},[265,12562,12563],{},"Token input medi/messaggio",[265,12565,12566],{},"~800 (system prompt + history)",[250,12568,12569,12572],{},[265,12570,12571],{},"Token output medi/messaggio",[265,12573,12574],{},"~400",[250,12576,12577,12580],{},[265,12578,12579],{},"Token input/mese",[265,12581,12582],{},"~2.4M",[250,12584,12585,12588],{},[265,12586,12587],{},"Token output/mese",[265,12589,12590],{},"~1.2M",[244,12592,12593,12609],{},[247,12594,12595],{},[250,12596,12597,12600,12603,12606],{},[253,12598,12599],{},"Modello",[253,12601,12602],{},"Input/mese",[253,12604,12605],{},"Output/mese",[253,12607,12608],{},"Totale/mese",[260,12610,12611,12629,12646],{},[250,12612,12613,12618,12621,12624],{},[265,12614,12615],{},[24,12616,12617],{},"Haiku 4.5",[265,12619,12620],{},"$2.40",[265,12622,12623],{},"$6.00",[265,12625,12626],{},[24,12627,12628],{},"~$8.40",[250,12630,12631,12636,12639,12641],{},[265,12632,12633],{},[24,12634,12635],{},"Haiku 4.5 + prompt caching",[265,12637,12638],{},"~$0.50",[265,12640,12623],{},[265,12642,12643],{},[24,12644,12645],{},"~$6.50",[250,12647,12648,12654,12657,12660],{},[265,12649,12650,12653],{},[24,12651,12652],{},"Haiku 3"," (legacy, piu' economico)",[265,12655,12656],{},"$0.60",[265,12658,12659],{},"$1.50",[265,12661,12662],{},[24,12663,12664],{},"~$2.10",[17,12666,12667],{},"Il prompt caching di Anthropic riduce del 90% il costo dei token di input che si ripetono (system prompt, history cachata). Per un bot con system prompt fisso, il risparmio e' significativo.",[58,12669,12671],{"id":12670},"costo-totale-mensile","Costo totale mensile",[244,12673,12674,12684],{},[247,12675,12676],{},[250,12677,12678,12681],{},[253,12679,12680],{},"Voce",[253,12682,12683],{},"Costo",[260,12685,12686,12694,12702],{},[250,12687,12688,12691],{},[265,12689,12690],{},"Hosting (Railway Hobby)",[265,12692,12693],{},"$5.00",[250,12695,12696,12699],{},[265,12697,12698],{},"Claude API (Haiku 4.5 con cache, ~100 msg/giorno)",[265,12700,12701],{},"$5-10",[250,12703,12704,12709],{},[265,12705,12706],{},[24,12707,12708],{},"Totale",[265,12710,12711],{},[24,12712,12713],{},"$10-16/mese",[58,12715,12717],{"id":12716},"confronto-con-le-alternative","Confronto con le alternative",[244,12719,12720,12737],{},[247,12721,12722],{},[250,12723,12724,12726,12728,12731,12734],{},[253,12725,7462],{},[253,12727,12443],{},[253,12729,12730],{},"Personalizzabile",[253,12732,12733],{},"Dati tuoi",[253,12735,12736],{},"API access",[260,12738,12739,12758,12774],{},[250,12740,12741,12746,12749,12752,12755],{},[265,12742,12743],{},[24,12744,12745],{},"Bot Telegram + Claude",[265,12747,12748],{},"$10-16",[265,12750,12751],{},"Totalmente",[265,12753,12754],{},"Si' (tuo server)",[265,12756,12757],{},"Si'",[250,12759,12760,12763,12766,12769,12771],{},[265,12761,12762],{},"ChatGPT Plus",[265,12764,12765],{},"$20",[265,12767,12768],{},"No",[265,12770,12768],{},[265,12772,12773],{},"Solo via API separata",[250,12775,12776,12779,12781,12783,12785],{},[265,12777,12778],{},"Claude Pro",[265,12780,12765],{},[265,12782,12768],{},[265,12784,12768],{},[265,12786,12773],{},[17,12788,12789],{},"Con il bot ti costa meno e hai il controllo totale: system prompt personalizzato, scelta del modello per ogni richiesta, nessun limite di messaggi artificiale, accesso ai dati della conversazione. Il tradeoff e' che lo devi mantenere tu -- ma come hai visto, non c'e' molto da mantenere.",[35,12791],{},[38,12793,12795],{"id":12794},"system-prompt-rendilo-tuo","System Prompt: Rendilo Tuo",[17,12797,12798],{},"Il system prompt e' la personalita' del tuo assistente. Quello che abbiamo usato nella guida e' generico. In produzione, personalizzalo per le tue esigenze.",[17,12800,12801],{},"Qualche idea:",[346,12803,12806],{"className":12804,"code":12805,"language":351},[349],"Sei Jarvis, l'assistente personale di Marco, sviluppatore fullstack.\n\nCONTESTO:\n- Marco lavora con TypeScript, React, Node.js e PostgreSQL\n- Il suo progetto principale e' una SaaS per la gestione fatture\n- Preferisce risposte concise con code block quando serve\n\nREGOLE:\n- Rispondi in italiano\n- Per domande di codice, mostra sempre un esempio pratico\n- Se Marco chiede \"come si fa X\", dai la soluzione diretta prima, poi la spiegazione\n- Per domande generiche (meteo, curiosita'), rispondi in modo sintetico\n- Non iniziare mai con \"Certamente!\" o \"Ottima domanda!\"\n",[353,12807,12805],{"__ignoreMap":355},[17,12809,12810,12811,12814],{},"La best practice di Anthropic: metti il ruolo e le regole nel parametro ",[353,12812,12813],{},"system",", le istruzioni specifiche del task nel messaggio utente. Il system prompt resta stabile, il contesto cambia.",[17,12816,12817,12818,12821],{},"Puoi anche aggiungere un comando ",[353,12819,12820],{},"/prompt"," al bot che ti permette di cambiare il system prompt al volo da Telegram, senza rideploy. Basta una variabile in memoria.",[35,12823],{},[38,12825,12827],{"id":12826},"idee-per-estenderlo","Idee per Estenderlo",[17,12829,12830],{},"Il bot base funziona. Da qui puoi portarlo dove vuoi. Alcune idee concrete, dalla piu' semplice alla piu' ambiziosa.",[58,12832,12834],{"id":12833},"memoria-persistente-con-sqlite","Memoria persistente con SQLite",[17,12836,10818,12837,12839,12840,12843],{},[353,12838,10821],{}," in memoria si cancella a ogni restart. Con ",[24,12841,12842],{},"better-sqlite3"," aggiungi persistenza in 20 righe:",[346,12845,12847],{"className":3850,"code":12846,"language":3852,"meta":355,"style":355},"import Database from \"better-sqlite3\";\n\nconst db = new Database(\"conversations.db\");\ndb.exec(`\n  CREATE TABLE IF NOT EXISTS messages (\n    id INTEGER PRIMARY KEY AUTOINCREMENT,\n    user_id INTEGER NOT NULL,\n    role TEXT NOT NULL,\n    content TEXT NOT NULL,\n    created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n  )\n`);\n\n// Salva ogni messaggio\nconst insertStmt = db.prepare(\n  \"INSERT INTO messages (user_id, role, content) VALUES (?, ?, ?)\"\n);\n\n// Recupera la history\nconst historyStmt = db.prepare(\n  \"SELECT role, content FROM messages WHERE user_id = ? ORDER BY id DESC LIMIT ?\"\n);\n",[353,12848,12849,12863,12867,12888,12901,12906,12911,12916,12921,12926,12931,12935,12942,12946,12951,12968,12973,12977,12981,12986,13001,13006],{"__ignoreMap":355},[407,12850,12851,12853,12856,12858,12861],{"class":409,"line":410},[407,12852,4974],{"class":3864},[407,12854,12855],{"class":2201}," Database ",[407,12857,4980],{"class":3864},[407,12859,12860],{"class":424}," \"better-sqlite3\"",[407,12862,4986],{"class":2201},[407,12864,12865],{"class":409,"line":417},[407,12866,445],{"emptyLinePlaceholder":444},[407,12868,12869,12871,12874,12876,12878,12881,12883,12886],{"class":409,"line":441},[407,12870,5056],{"class":3864},[407,12872,12873],{"class":434}," db",[407,12875,5062],{"class":3864},[407,12877,5379],{"class":3864},[407,12879,12880],{"class":420}," Database",[407,12882,5216],{"class":2201},[407,12884,12885],{"class":424},"\"conversations.db\"",[407,12887,5083],{"class":2201},[407,12889,12890,12893,12896,12898],{"class":409,"line":448},[407,12891,12892],{"class":2201},"db.",[407,12894,12895],{"class":420},"exec",[407,12897,5216],{"class":2201},[407,12899,12900],{"class":424},"`\n",[407,12902,12903],{"class":409,"line":454},[407,12904,12905],{"class":424},"  CREATE TABLE IF NOT EXISTS messages (\n",[407,12907,12908],{"class":409,"line":1667},[407,12909,12910],{"class":424},"    id INTEGER PRIMARY KEY AUTOINCREMENT,\n",[407,12912,12913],{"class":409,"line":1673},[407,12914,12915],{"class":424},"    user_id INTEGER NOT NULL,\n",[407,12917,12918],{"class":409,"line":1679},[407,12919,12920],{"class":424},"    role TEXT NOT NULL,\n",[407,12922,12923],{"class":409,"line":1685},[407,12924,12925],{"class":424},"    content TEXT NOT NULL,\n",[407,12927,12928],{"class":409,"line":1690},[407,12929,12930],{"class":424},"    created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n",[407,12932,12933],{"class":409,"line":1696},[407,12934,10410],{"class":424},[407,12936,12937,12940],{"class":409,"line":1702},[407,12938,12939],{"class":424},"`",[407,12941,5083],{"class":2201},[407,12943,12944],{"class":409,"line":1708},[407,12945,445],{"emptyLinePlaceholder":444},[407,12947,12948],{"class":409,"line":1714},[407,12949,12950],{"class":413},"// Salva ogni messaggio\n",[407,12952,12953,12955,12958,12960,12963,12966],{"class":409,"line":1719},[407,12954,5056],{"class":3864},[407,12956,12957],{"class":434}," insertStmt",[407,12959,5062],{"class":3864},[407,12961,12962],{"class":2201}," db.",[407,12964,12965],{"class":420},"prepare",[407,12967,5434],{"class":2201},[407,12969,12970],{"class":409,"line":1725},[407,12971,12972],{"class":424},"  \"INSERT INTO messages (user_id, role, content) VALUES (?, ?, ?)\"\n",[407,12974,12975],{"class":409,"line":1278},[407,12976,5083],{"class":2201},[407,12978,12979],{"class":409,"line":1736},[407,12980,445],{"emptyLinePlaceholder":444},[407,12982,12983],{"class":409,"line":1742},[407,12984,12985],{"class":413},"// Recupera la history\n",[407,12987,12988,12990,12993,12995,12997,12999],{"class":409,"line":1748},[407,12989,5056],{"class":3864},[407,12991,12992],{"class":434}," historyStmt",[407,12994,5062],{"class":3864},[407,12996,12962],{"class":2201},[407,12998,12965],{"class":420},[407,13000,5434],{"class":2201},[407,13002,13003],{"class":409,"line":1753},[407,13004,13005],{"class":424},"  \"SELECT role, content FROM messages WHERE user_id = ? ORDER BY id DESC LIMIT ?\"\n",[407,13007,13008],{"class":409,"line":1759},[407,13009,5083],{"class":2201},[58,13011,13013],{"id":13012},"dual-model-routing","Dual-model routing",[17,13015,13016,13017,13020],{},"Idea presa da ",[24,13018,13019],{},"claudegram",": usa Haiku per domande semplici (chit-chat, traduzioni) e Sonnet per ragionamento complesso (codice, analisi). Un primo filtro puo' essere la lunghezza del messaggio o keyword specifiche. Un approccio piu' sofisticato: manda il messaggio prima a Haiku chiedendo \"questa domanda richiede ragionamento complesso? Rispondi solo si/no\" -- costa pochissimo e fa da router.",[58,13022,13024],{"id":13023},"tool-use","Tool use",[17,13026,13027],{},"Claude supporta il tool use (function calling). Puoi dare al bot la capacita' di:",[82,13029,13030,13033,13036,13039,13042],{},[85,13031,13032],{},"Cercare il meteo via API",[85,13034,13035],{},"Gestire una lista di todo",[85,13037,13038],{},"Interrogare un database",[85,13040,13041],{},"Mandare email",[85,13043,13044],{},"Controllare dispositivi smart home",[17,13046,13047],{},"Karpathy ha raccontato di aver costruito un setup simile -- il suo \"Dobby the Elf Claw\" -- per controllare luci, termostato, pool e tapparelle via WhatsApp con Claude. Il pattern e' semplice: definisci i tool nello schema, Claude decide quando usarli, tu esegui la funzione e restituisci il risultato.",[58,13049,13051],{"id":13050},"cost-tracking","Cost tracking",[17,13053,13054,13055,4055,13058,13061,13062,13065],{},"Ogni risposta di Claude include ",[353,13056,13057],{},"usage.input_tokens",[353,13059,13060],{},"usage.output_tokens",". Logga questi dati e saprai esattamente quanto stai spendendo. Puoi anche aggiungere un comando ",[353,13063,13064],{},"/costi"," che mostra il totale del mese.",[58,13067,13069],{"id":13068},"voice-to-text","Voice-to-text",[17,13071,13072,13073,13076],{},"Telegram supporta i messaggi vocali. Con l'handler ",[353,13074,13075],{},"bot.on(\"voice\", ...)"," puoi scaricare l'audio, trascriverlo (usando Whisper o un servizio di speech-to-text) e passare il testo a Claude. L'assistente che risponde anche quando non puoi digitare.",[35,13078],{},[17,13080,13081],{},[24,13082,1143],{},[517,13084,13085,13092,13099,13106,13113,13120,13127],{},[85,13086,13087],{},[69,13088,13091],{"href":13089,"rel":13090},"https://core.telegram.org/bots/api",[1152],"Telegram Bot API",[85,13093,13094],{},[69,13095,13098],{"href":13096,"rel":13097},"https://platform.claude.com/docs/en/about-claude/pricing",[1152],"Anthropic Pricing",[85,13100,13101],{},[69,13102,13105],{"href":13103,"rel":13104},"https://platform.claude.com/docs/en/api/client-sdks",[1152],"Anthropic Client SDKs (Node.js)",[85,13107,13108],{},[69,13109,13112],{"href":13110,"rel":13111},"https://platform.claude.com/docs/en/build-with-claude/vision",[1152],"Claude Vision",[85,13114,13115],{},[69,13116,13119],{"href":13117,"rel":13118},"https://github.com/telegraf/telegraf",[1152],"Telegraf su GitHub",[85,13121,13122],{},[69,13123,13126],{"href":13124,"rel":13125},"https://github.com/roombawulf/claudegram",[1152],"claudegram -- bot Telegram open source con Claude",[85,13128,13129],{},[69,13130,13133],{"href":13131,"rel":13132},"https://railway.com/pricing",[1152],"Railway Pricing",[1218,13135,13136],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":355,"searchDepth":417,"depth":417,"links":13138},[13139,13140,13141,13142,13143,13144,13145,13146,13151,13156,13157],{"id":4569,"depth":417,"text":4570},{"id":8153,"depth":417,"text":8154},{"id":8228,"depth":417,"text":8229},{"id":8541,"depth":417,"text":8542},{"id":9386,"depth":417,"text":9387},{"id":10833,"depth":417,"text":10834},{"id":11468,"depth":417,"text":11469},{"id":12274,"depth":417,"text":12275,"children":13147},[13148,13149,13150],{"id":12281,"depth":441,"text":12282},{"id":12371,"depth":441,"text":12372},{"id":12427,"depth":441,"text":12428},{"id":12522,"depth":417,"text":12523,"children":13152},[13153,13154,13155],{"id":12535,"depth":441,"text":12536},{"id":12670,"depth":441,"text":12671},{"id":12716,"depth":441,"text":12717},{"id":12794,"depth":417,"text":12795},{"id":12826,"depth":417,"text":12827,"children":13158},[13159,13160,13161,13162,13163],{"id":12833,"depth":441,"text":12834},{"id":13012,"depth":441,"text":13013},{"id":13023,"depth":441,"text":13024},{"id":13050,"depth":441,"text":13051},{"id":13068,"depth":441,"text":13069},"Costruisci un assistente AI personale su Telegram con Claude Haiku 4.5: streaming nativo, analisi immagini, memoria. Costa $10-16/mese, meno di ChatGPT Plus.","/images/guides/telegram-bot-assistente-personale-claude-api.webp",{},"/guides/_telegram-bot-assistente-personale-claude-api","2026-03-23",{"title":8076,"description":13164},"guides/_telegram-bot-assistente-personale-claude-api",[13172,13173,13174,8070,8060,13175],"Claude API","Telegram","Bot","Node.js","FS76m0O3rqijwzmKS8SIQPIABhO6XflctTzTU_si2zE",{"id":1291,"title":1292,"author":13178,"body":13179,"category":2766,"contentType":1269,"description":2767,"difficulty":2768,"extension":1272,"featured":444,"icon":1269,"image":2769,"meta":14248,"navigation":444,"path":2771,"publishedAt":2772,"readingTime":1714,"seo":14249,"stem":2774,"steps":1269,"tags":14250,"youtubeId":1269,"__hash__":2776},{"name":7,"initials":8},{"type":10,"value":13180,"toc":14216},[13181,13183,13187,13189,13193,13195,13197,13199,13201,13301,13307,13313,13315,13341,13343,13345,13347,13351,13353,13361,13363,13421,13423,13425,13541,13545,13547,13549,13551,13553,13569,13571,13573,13589,13595,13597,13605,13609,13617,13619,13621,13627,13629,13633,13637,13639,13641,13643,13667,13669,13671,13673,13675,13679,13684,13688,13732,13746,13752,13754,13756,13814,13820,13822,13862,13864,13866,13868,13870,13960,13962,13966,13970,13982,13984,13986,13998,14000,14002,14004,14008,14020,14022,14024,14044,14046,14048,14050,14052,14070,14072,14076,14080,14088,14092,14104,14106,14108,14110,14162,14166,14168,14172,14214],[13,13182,1292],{"id":1298},[17,13184,1301,13185,688],{},[24,13186,1304],{},[17,13188,1307],{},[17,13190,1310,13191,1314],{},[24,13192,1313],{},[17,13194,1317],{},[35,13196],{},[38,13198,1323],{"id":1322},[17,13200,1326],{},[244,13202,13203,13215],{},[247,13204,13205],{},[250,13206,13207,13209,13211,13213],{},[253,13208,1335],{},[253,13210,1338],{},[253,13212,1341],{},[253,13214,1344],{},[260,13216,13217,13231,13245,13259,13273,13287],{},[250,13218,13219,13223,13227,13229],{},[265,13220,13221],{},[24,13222,1353],{},[265,13224,13225],{},[353,13226,1358],{},[265,13228,1361],{},[265,13230,1364],{},[250,13232,13233,13237,13241,13243],{},[265,13234,13235],{},[24,13236,1371],{},[265,13238,13239],{},[353,13240,1376],{},[265,13242,1379],{},[265,13244,1382],{},[250,13246,13247,13251,13255,13257],{},[265,13248,13249],{},[24,13250,1389],{},[265,13252,13253,1395],{},[353,13254,1394],{},[265,13256,1398],{},[265,13258,1401],{},[250,13260,13261,13265,13269,13271],{},[265,13262,13263],{},[24,13264,1408],{},[265,13266,13267],{},[353,13268,1413],{},[265,13270,1416],{},[265,13272,1401],{},[250,13274,13275,13279,13283,13285],{},[265,13276,13277],{},[24,13278,1425],{},[265,13280,13281],{},[353,13282,1430],{},[265,13284,1433],{},[265,13286,1436],{},[250,13288,13289,13293,13297,13299],{},[265,13290,13291],{},[24,13292,1443],{},[265,13294,13295],{},[353,13296,1448],{},[265,13298,1451],{},[265,13300,1436],{},[17,13302,1456,13303,1460,13305,1464],{},[24,13304,1459],{},[24,13306,1463],{},[17,13308,1467,13309,1471,13311,1475],{},[353,13310,1470],{},[353,13312,1474],{},[58,13314,1479],{"id":1478},[82,13316,13317,13323,13329,13335],{},[85,13318,13319,1486,13321,1489],{},[24,13320,1371],{},[353,13322,1376],{},[85,13324,13325,1486,13327,1496],{},[24,13326,1389],{},[353,13328,1394],{},[85,13330,13331,1486,13333,1505],{},[24,13332,1501],{},[353,13334,1504],{},[85,13336,13337,1486,13339,1513],{},[24,13338,1510],{},[353,13340,1430],{},[35,13342],{},[38,13344,1519],{"id":1518},[17,13346,1522],{},[1524,13348,13349],{},[17,13350,1528],{},[58,13352,1532],{"id":1531},[17,13354,13355,1538,13357,1542,13359,1546],{},[24,13356,1537],{},[24,13358,1541],{},[24,13360,1545],{},[58,13362,1550],{"id":1549},[244,13364,13365,13373],{},[247,13366,13367],{},[250,13368,13369,13371],{},[253,13370,1559],{},[253,13372,1562],{},[260,13374,13375,13383,13391,13397,13403,13409,13415],{},[250,13376,13377,13379],{},[265,13378,1569],{},[265,13380,13381,1575],{},[353,13382,1574],{},[250,13384,13385,13389],{},[265,13386,1580,13387,1584],{},[24,13388,1583],{},[265,13390,1587],{},[250,13392,13393,13395],{},[265,13394,1592],{},[265,13396,1595],{},[250,13398,13399,13401],{},[265,13400,1600],{},[265,13402,1603],{},[250,13404,13405,13407],{},[265,13406,1608],{},[265,13408,1611],{},[250,13410,13411,13413],{},[265,13412,1616],{},[265,13414,1619],{},[250,13416,13417,13419],{},[265,13418,1624],{},[265,13420,1627],{},[58,13422,1631],{"id":1630},[17,13424,1634],{},[346,13426,13427],{"className":1637,"code":1638,"language":1639,"meta":355,"style":355},[353,13428,13429,13433,13437,13441,13445,13449,13453,13457,13461,13465,13469,13473,13477,13481,13485,13489,13493,13497,13501,13505,13509,13513,13517,13521,13525,13529,13533,13537],{"__ignoreMap":355},[407,13430,13431],{"class":409,"line":410},[407,13432,1646],{},[407,13434,13435],{"class":409,"line":417},[407,13436,445],{"emptyLinePlaceholder":444},[407,13438,13439],{"class":409,"line":441},[407,13440,1655],{},[407,13442,13443],{"class":409,"line":448},[407,13444,445],{"emptyLinePlaceholder":444},[407,13446,13447],{"class":409,"line":454},[407,13448,1664],{},[407,13450,13451],{"class":409,"line":1667},[407,13452,1670],{},[407,13454,13455],{"class":409,"line":1673},[407,13456,1676],{},[407,13458,13459],{"class":409,"line":1679},[407,13460,1682],{},[407,13462,13463],{"class":409,"line":1685},[407,13464,445],{"emptyLinePlaceholder":444},[407,13466,13467],{"class":409,"line":1690},[407,13468,1693],{},[407,13470,13471],{"class":409,"line":1696},[407,13472,1699],{},[407,13474,13475],{"class":409,"line":1702},[407,13476,1705],{},[407,13478,13479],{"class":409,"line":1708},[407,13480,1711],{},[407,13482,13483],{"class":409,"line":1714},[407,13484,445],{"emptyLinePlaceholder":444},[407,13486,13487],{"class":409,"line":1719},[407,13488,1722],{},[407,13490,13491],{"class":409,"line":1725},[407,13492,1728],{},[407,13494,13495],{"class":409,"line":1278},[407,13496,1733],{},[407,13498,13499],{"class":409,"line":1736},[407,13500,1739],{},[407,13502,13503],{"class":409,"line":1742},[407,13504,1745],{},[407,13506,13507],{"class":409,"line":1748},[407,13508,445],{"emptyLinePlaceholder":444},[407,13510,13511],{"class":409,"line":1753},[407,13512,1756],{},[407,13514,13515],{"class":409,"line":1759},[407,13516,1762],{},[407,13518,13519],{"class":409,"line":1765},[407,13520,1768],{},[407,13522,13523],{"class":409,"line":1771},[407,13524,1774],{},[407,13526,13527],{"class":409,"line":1777},[407,13528,445],{"emptyLinePlaceholder":444},[407,13530,13531],{"class":409,"line":1782},[407,13532,1785],{},[407,13534,13535],{"class":409,"line":1788},[407,13536,1791],{},[407,13538,13539],{"class":409,"line":1794},[407,13540,1797],{},[17,13542,13543,1803],{},[24,13544,1802],{},[35,13546],{},[38,13548,1809],{"id":1808},[17,13550,1812],{},[58,13552,1816],{"id":1815},[346,13554,13555],{"className":1637,"code":1819,"language":1639,"meta":355,"style":355},[353,13556,13557,13561,13565],{"__ignoreMap":355},[407,13558,13559],{"class":409,"line":410},[407,13560,1826],{},[407,13562,13563],{"class":409,"line":417},[407,13564,1831],{},[407,13566,13567],{"class":409,"line":441},[407,13568,1836],{},[17,13570,1839],{},[58,13572,1843],{"id":1842},[346,13574,13575],{"className":1637,"code":1846,"language":1639,"meta":355,"style":355},[353,13576,13577,13581,13585],{"__ignoreMap":355},[407,13578,13579],{"class":409,"line":410},[407,13580,1853],{},[407,13582,13583],{"class":409,"line":417},[407,13584,1858],{},[407,13586,13587],{"class":409,"line":441},[407,13588,1863],{},[17,13590,1866,13591,1870,13593,1874],{},[24,13592,1869],{},[24,13594,1873],{},[58,13596,1878],{"id":1877},[346,13598,13599],{"className":1637,"code":1881,"language":1639,"meta":355,"style":355},[353,13600,13601],{"__ignoreMap":355},[407,13602,13603],{"class":409,"line":410},[407,13604,1881],{},[17,13606,1890,13607,1894],{},[24,13608,1893],{},[346,13610,13611],{"className":1637,"code":1897,"language":1639,"meta":355,"style":355},[353,13612,13613],{"__ignoreMap":355},[407,13614,13615],{"class":409,"line":410},[407,13616,1897],{},[17,13618,1906],{},[58,13620,1910],{"id":1909},[17,13622,1913,13623,1917,13625,1920],{},[24,13624,1916],{},[353,13626,1470],{},[58,13628,1924],{"id":1923},[17,13630,1927,13631,1931],{},[24,13632,1930],{},[17,13634,13635,1937],{},[24,13636,1936],{},[35,13638],{},[38,13640,1943],{"id":1942},[17,13642,1946],{},[346,13644,13645],{"className":1637,"code":1949,"language":1639,"meta":355,"style":355},[353,13646,13647,13651,13655,13659,13663],{"__ignoreMap":355},[407,13648,13649],{"class":409,"line":410},[407,13650,1956],{},[407,13652,13653],{"class":409,"line":417},[407,13654,445],{"emptyLinePlaceholder":444},[407,13656,13657],{"class":409,"line":441},[407,13658,1965],{},[407,13660,13661],{"class":409,"line":448},[407,13662,1970],{},[407,13664,13665],{"class":409,"line":454},[407,13666,1975],{},[17,13668,1978],{},[17,13670,1981],{},[35,13672],{},[38,13674,1987],{"id":1986},[17,13676,1990,13677,1993],{},[353,13678,1504],{},[346,13680,13682],{"className":13681,"code":1997,"language":351},[349],[353,13683,1997],{"__ignoreMap":355},[17,13685,2002,13686,2006],{},[24,13687,2005],{},[346,13689,13690],{"className":1637,"code":2009,"language":1639,"meta":355,"style":355},[353,13691,13692,13696,13700,13704,13708,13712,13716,13720,13724,13728],{"__ignoreMap":355},[407,13693,13694],{"class":409,"line":410},[407,13695,2016],{},[407,13697,13698],{"class":409,"line":417},[407,13699,2021],{},[407,13701,13702],{"class":409,"line":441},[407,13703,2026],{},[407,13705,13706],{"class":409,"line":448},[407,13707,2031],{},[407,13709,13710],{"class":409,"line":454},[407,13711,2016],{},[407,13713,13714],{"class":409,"line":1667},[407,13715,445],{"emptyLinePlaceholder":444},[407,13717,13718],{"class":409,"line":1673},[407,13719,2044],{},[407,13721,13722],{"class":409,"line":1679},[407,13723,2049],{},[407,13725,13726],{"class":409,"line":1685},[407,13727,2054],{},[407,13729,13730],{"class":409,"line":1690},[407,13731,2059],{},[17,13733,2062,13734,2066,13736,2070,13738,2074,13740,2078,13742,2078,13744,688],{},[24,13735,2065],{},[353,13737,2069],{},[24,13739,2073],{},[353,13741,2077],{},[353,13743,2081],{},[353,13745,2084],{},[17,13747,2087,13748,2091,13750,2095],{},[24,13749,2090],{},[24,13751,2094],{},[35,13753],{},[38,13755,2101],{"id":2100},[244,13757,13758,13768],{},[247,13759,13760],{},[250,13761,13762,13764,13766],{},[253,13763],{},[253,13765,1304],{},[253,13767,2114],{},[260,13769,13770,13784,13794,13804],{},[250,13771,13772,13776,13780],{},[265,13773,13774],{},[24,13775,2123],{},[265,13777,2126,13778,2131],{},[2128,13779,2130],{},[265,13781,2134,13782],{},[2128,13783,2137],{},[250,13785,13786,13790,13792],{},[265,13787,13788],{},[24,13789,2144],{},[265,13791,2147],{},[265,13793,2150],{},[250,13795,13796,13800,13802],{},[265,13797,13798],{},[24,13799,2157],{},[265,13801,2160],{},[265,13803,2163],{},[250,13805,13806,13810,13812],{},[265,13807,13808],{},[24,13809,2170],{},[265,13811,2173],{},[265,13813,2176],{},[17,13815,13816,2182,13818,2186],{},[24,13817,2181],{},[24,13819,2185],{},[17,13821,2189],{},[346,13823,13824],{"className":2192,"code":2193,"language":2194,"meta":355,"style":355},[353,13825,13826,13830,13836,13842,13850,13854,13858],{"__ignoreMap":355},[407,13827,13828],{"class":409,"line":410},[407,13829,2202],{"class":2201},[407,13831,13832,13834],{"class":409,"line":417},[407,13833,2207],{"class":434},[407,13835,2210],{"class":2201},[407,13837,13838,13840],{"class":409,"line":441},[407,13839,2215],{"class":434},[407,13841,2210],{"class":2201},[407,13843,13844,13846,13848],{"class":409,"line":448},[407,13845,2222],{"class":434},[407,13847,2225],{"class":2201},[407,13849,2228],{"class":424},[407,13851,13852],{"class":409,"line":454},[407,13853,2233],{"class":2201},[407,13855,13856],{"class":409,"line":1667},[407,13857,2238],{"class":2201},[407,13859,13860],{"class":409,"line":1673},[407,13861,2243],{"class":2201},[17,13863,2246],{},[35,13865],{},[38,13867,2252],{"id":2251},[17,13869,2255],{},[244,13871,13872,13882],{},[247,13873,13874],{},[250,13875,13876,13878,13880],{},[253,13877,2264],{},[253,13879,2267],{},[253,13881,2270],{},[260,13883,13884,13898,13912,13924,13936,13948],{},[250,13885,13886,13890,13896],{},[265,13887,13888],{},[24,13889,1287],{},[265,13891,13892,2078,13894],{},[353,13893,1304],{},[353,13895,1504],{},[265,13897,2287],{},[250,13899,13900,13904,13910],{},[265,13901,13902],{},[24,13903,2294],{},[265,13905,13906,2078,13908,2303],{},[353,13907,2299],{},[353,13909,2302],{},[265,13911,2306],{},[250,13913,13914,13918,13922],{},[265,13915,13916],{},[24,13917,2313],{},[265,13919,13920],{},[353,13921,2318],{},[265,13923,2287],{},[250,13925,13926,13930,13934],{},[265,13927,13928],{},[24,13929,2327],{},[265,13931,13932],{},[353,13933,2332],{},[265,13935,2306],{},[250,13937,13938,13942,13946],{},[265,13939,13940],{},[24,13941,2341],{},[265,13943,13944],{},[353,13945,2346],{},[265,13947,2346],{},[250,13949,13950,13954,13958],{},[265,13951,13952],{},[24,13953,2355],{},[265,13955,13956],{},[353,13957,2360],{},[265,13959,2306],{},[58,13961,2366],{"id":2365},[17,13963,13964,2371],{},[24,13965,2346],{},[17,13967,2374,13968,2378],{},[24,13969,2377],{},[346,13971,13972],{"className":1637,"code":2381,"language":1639,"meta":355,"style":355},[353,13973,13974,13978],{"__ignoreMap":355},[407,13975,13976],{"class":409,"line":410},[407,13977,2388],{},[407,13979,13980],{"class":409,"line":417},[407,13981,2393],{},[58,13983,2397],{"id":2396},[17,13985,2400],{},[517,13987,13988,13992],{},[85,13989,2405,13990,2408],{},[24,13991,2346],{},[85,13993,2411,13994,2078,13996,2416],{},[353,13995,1304],{},[353,13997,2302],{},[17,13999,2419],{},[35,14001],{},[38,14003,2425],{"id":2424},[17,14005,2428,14006,2432],{},[24,14007,2431],{},[82,14009,14010,14012,14014,14016],{},[85,14011,2437],{},[85,14013,2440],{},[85,14015,2443],{},[85,14017,14018],{},[24,14019,2448],{},[17,14021,2451],{},[58,14023,2455],{"id":2454},[82,14025,14026,14030,14034,14038],{},[85,14027,14028,2463],{},[24,14029,2462],{},[85,14031,14032,2469],{},[24,14033,2468],{},[85,14035,14036,2475],{},[24,14037,2474],{},[85,14039,14040,2484],{},[24,14041,14042,2483],{},[353,14043,2482],{},[35,14045],{},[38,14047,2490],{"id":2489},[58,14049,2494],{"id":2493},[17,14051,2497],{},[82,14053,14054,14058,14062,14066],{},[85,14055,2502,14056,2506],{},[24,14057,2505],{},[85,14059,2509,14060],{},[2128,14061,2512],{},[85,14063,2515,14064,2519],{},[24,14065,2518],{},[85,14067,2522,14068,2526],{},[24,14069,2525],{},[58,14071,2530],{"id":2529},[17,14073,14074,2536],{},[24,14075,2535],{},[17,14077,14078,2542],{},[24,14079,2541],{},[17,14081,14082,2551,14086,2554],{},[24,14083,2547,14084,688],{},[353,14085,2550],{},[353,14087,2550],{},[17,14089,14090,2560],{},[24,14091,2559],{},[346,14093,14094],{"className":1637,"code":2563,"language":1639,"meta":355,"style":355},[353,14095,14096,14100],{"__ignoreMap":355},[407,14097,14098],{"class":409,"line":410},[407,14099,2570],{},[407,14101,14102],{"class":409,"line":417},[407,14103,2575],{},[35,14105],{},[38,14107,2581],{"id":2580},[17,14109,2584],{},[82,14111,14113,14120,14127,14134,14141,14148,14155],{"className":14112},[931],[85,14114,14116,940,14118,2596],{"className":14115},[935],[937,14117],{"disabled":444,"type":939},[24,14119,2595],{},[85,14121,14123,940,14125,2605],{"className":14122},[935],[937,14124],{"disabled":444,"type":939},[24,14126,2604],{},[85,14128,14130,940,14132,2614],{"className":14129},[935],[937,14131],{"disabled":444,"type":939},[24,14133,2613],{},[85,14135,14137,940,14139,2623],{"className":14136},[935],[937,14138],{"disabled":444,"type":939},[24,14140,2622],{},[85,14142,14144,940,14146,2632],{"className":14143},[935],[937,14145],{"disabled":444,"type":939},[24,14147,2631],{},[85,14149,14151,940,14153,2641],{"className":14150},[935],[937,14152],{"disabled":444,"type":939},[24,14154,2640],{},[85,14156,14158,940,14160,2650],{"className":14157},[935],[937,14159],{"disabled":444,"type":939},[24,14161,2649],{},[17,14163,2653,14164,2657],{},[24,14165,2656],{},[35,14167],{},[17,14169,14170,1894],{},[24,14171,2664],{},[82,14173,14174,14179,14184,14189,14194,14199,14204,14209],{},[85,14175,14176,2674],{},[69,14177,2673],{"href":2671,"rel":14178},[1152],[85,14180,14181,2682],{},[69,14182,2681],{"href":2679,"rel":14183},[1152],[85,14185,14186,2690],{},[69,14187,2689],{"href":2687,"rel":14188},[1152],[85,14190,14191,2698],{},[69,14192,2697],{"href":2695,"rel":14193},[1152],[85,14195,14196,2706],{},[69,14197,2705],{"href":2703,"rel":14198},[1152],[85,14200,14201,2714],{},[69,14202,2713],{"href":2711,"rel":14203},[1152],[85,14205,14206,2722],{},[69,14207,2721],{"href":2719,"rel":14208},[1152],[85,14210,14211,2730],{},[69,14212,2729],{"href":2727,"rel":14213},[1152],[1218,14215,2733],{},{"title":355,"searchDepth":417,"depth":417,"links":14217},[14218,14221,14226,14233,14234,14235,14236,14240,14243,14247],{"id":1322,"depth":417,"text":1323,"children":14219},[14220],{"id":1478,"depth":441,"text":1479},{"id":1518,"depth":417,"text":1519,"children":14222},[14223,14224,14225],{"id":1531,"depth":441,"text":1532},{"id":1549,"depth":441,"text":1550},{"id":1630,"depth":441,"text":1631},{"id":1808,"depth":417,"text":1809,"children":14227},[14228,14229,14230,14231,14232],{"id":1815,"depth":441,"text":1816},{"id":1842,"depth":441,"text":1843},{"id":1877,"depth":441,"text":1878},{"id":1909,"depth":441,"text":1910},{"id":1923,"depth":441,"text":1924},{"id":1942,"depth":417,"text":1943},{"id":1986,"depth":417,"text":1987},{"id":2100,"depth":417,"text":2101},{"id":2251,"depth":417,"text":2252,"children":14237},[14238,14239],{"id":2365,"depth":441,"text":2366},{"id":2396,"depth":441,"text":2397},{"id":2424,"depth":417,"text":2425,"children":14241},[14242],{"id":2454,"depth":441,"text":2455},{"id":2489,"depth":417,"text":2490,"children":14244},[14245,14246],{"id":2493,"depth":441,"text":2494},{"id":2529,"depth":441,"text":2530},{"id":2580,"depth":417,"text":2581},{},{"title":1292,"description":2767},[1287,1304,1285,2766,1268],{"id":2778,"title":2779,"author":14252,"body":14253,"category":2766,"contentType":1269,"description":4520,"difficulty":2768,"extension":1272,"featured":444,"icon":1269,"image":4521,"meta":15569,"navigation":444,"path":4523,"publishedAt":4524,"readingTime":1725,"seo":15570,"stem":4526,"steps":1269,"tags":15571,"youtubeId":1269,"__hash__":4530},{"name":7,"initials":8},{"type":10,"value":14254,"toc":15522},[14255,14257,14261,14263,14267,14269,14271,14273,14277,14281,14283,14285,14287,14289,14291,14389,14391,14397,14399,14401,14405,14407,14411,14483,14487,14515,14517,14519,14599,14601,14603,14605,14621,14623,14625,14627,14631,14633,14637,14643,14645,14651,14653,14655,14659,14663,14671,14675,14679,14681,14685,14785,14789,14791,14793,14857,14859,14861,14863,14867,14869,14871,14875,14877,14879,14889,14891,14893,14895,14900,14902,14907,14909,14911,14913,14931,14933,14935,14940,14942,14947,14951,14953,14955,14957,14959,14963,14965,14969,14971,14975,14981,15009,15015,15019,15021,15023,15028,15030,15032,15037,15041,15043,15045,15047,15049,15053,15121,15123,15125,15127,15132,15134,15136,15141,15143,15145,15149,15154,15156,15161,15163,15165,15169,15174,15176,15178,15180,15185,15187,15189,15191,15205,15210,15212,15214,15216,15220,15224,15228,15230,15234,15238,15242,15244,15248,15252,15256,15258,15262,15266,15270,15272,15276,15280,15284,15286,15288,15290,15378,15380,15382,15384,15386,15390,15454,15456,15458,15462,15464,15468,15520],[13,14256,2779],{"id":2785},[17,14258,2788,14259,2792],{},[69,14260,2791],{"href":71},[17,14262,2795],{},[17,14264,2798,14265,2802],{},[24,14266,2801],{},[35,14268],{},[38,14270,2808],{"id":2807},[17,14272,2811],{},[17,14274,2814,14275,688],{},[24,14276,2817],{},[17,14278,2820,14279,2824],{},[24,14280,2823],{},[17,14282,2827],{},[35,14284],{},[38,14286,2833],{"id":2832},[17,14288,2836],{},[58,14290,2840],{"id":2839},[244,14292,14293,14305],{},[247,14294,14295],{},[250,14296,14297,14299,14301,14303],{},[253,14298,2264],{},[253,14300,2851],{},[253,14302,2854],{},[253,14304,2857],{},[260,14306,14307,14327,14343,14359,14375],{},[250,14308,14309,14313,14317,14325],{},[265,14310,14311],{},[24,14312,1287],{},[265,14314,14315,1395],{},[353,14316,1304],{},[265,14318,14319,2874,14321,2078,14323],{},[353,14320,1376],{},[353,14322,1413],{},[353,14324,1470],{},[265,14326,2881],{},[250,14328,14329,14333,14337,14341],{},[265,14330,14331],{},[24,14332,2294],{},[265,14334,14335,1395],{},[353,14336,2302],{},[265,14338,14339,2897],{},[353,14340,2896],{},[265,14342,2900],{},[250,14344,14345,14349,14353,14357],{},[265,14346,14347],{},[24,14348,2907],{},[265,14350,14351,1395],{},[353,14352,2346],{},[265,14354,14355,2917],{},[353,14356,2916],{},[265,14358,2920],{},[250,14360,14361,14365,14369,14373],{},[265,14362,14363],{},[24,14364,2327],{},[265,14366,14367,1395],{},[353,14368,2332],{},[265,14370,14371,2936],{},[353,14372,2935],{},[265,14374,2920],{},[250,14376,14377,14381,14385,14387],{},[265,14378,14379],{},[24,14380,2313],{},[265,14382,14383],{},[353,14384,2318],{},[265,14386,2951],{},[265,14388,2954],{},[58,14390,2957],{"id":2365},[17,14392,14393,2962,14395,2966],{},[353,14394,2346],{},[24,14396,2965],{},[17,14398,2969],{},[58,14400,2973],{"id":2972},[17,14402,2976,14403,688],{},[24,14404,2979],{},[17,14406,2982],{},[17,14408,14409],{},[24,14410,2987],{},[346,14412,14413],{"className":1637,"code":2990,"language":1639,"meta":355,"style":355},[353,14414,14415,14419,14423,14427,14431,14435,14439,14443,14447,14451,14455,14459,14463,14467,14471,14475,14479],{"__ignoreMap":355},[407,14416,14417],{"class":409,"line":410},[407,14418,1664],{},[407,14420,14421],{"class":409,"line":417},[407,14422,3001],{},[407,14424,14425],{"class":409,"line":441},[407,14426,3006],{},[407,14428,14429],{"class":409,"line":448},[407,14430,3011],{},[407,14432,14433],{"class":409,"line":454},[407,14434,445],{"emptyLinePlaceholder":444},[407,14436,14437],{"class":409,"line":1667},[407,14438,1693],{},[407,14440,14441],{"class":409,"line":1673},[407,14442,3024],{},[407,14444,14445],{"class":409,"line":1679},[407,14446,3029],{},[407,14448,14449],{"class":409,"line":1685},[407,14450,445],{"emptyLinePlaceholder":444},[407,14452,14453],{"class":409,"line":1690},[407,14454,3038],{},[407,14456,14457],{"class":409,"line":1696},[407,14458,3043],{},[407,14460,14461],{"class":409,"line":1702},[407,14462,3048],{},[407,14464,14465],{"class":409,"line":1708},[407,14466,3053],{},[407,14468,14469],{"class":409,"line":1714},[407,14470,445],{"emptyLinePlaceholder":444},[407,14472,14473],{"class":409,"line":1719},[407,14474,3062],{},[407,14476,14477],{"class":409,"line":1725},[407,14478,3067],{},[407,14480,14481],{"class":409,"line":1278},[407,14482,3072],{},[17,14484,14485],{},[24,14486,3077],{},[346,14488,14489],{"className":1637,"code":3080,"language":1639,"meta":355,"style":355},[353,14490,14491,14495,14499,14503,14507,14511],{"__ignoreMap":355},[407,14492,14493],{"class":409,"line":410},[407,14494,3087],{},[407,14496,14497],{"class":409,"line":417},[407,14498,3092],{},[407,14500,14501],{"class":409,"line":441},[407,14502,3097],{},[407,14504,14505],{"class":409,"line":448},[407,14506,3102],{},[407,14508,14509],{"class":409,"line":454},[407,14510,3107],{},[407,14512,14513],{"class":409,"line":1667},[407,14514,3112],{},[58,14516,3116],{"id":3115},[17,14518,3119],{},[346,14520,14521],{"className":1637,"code":3122,"language":1639,"meta":355,"style":355},[353,14522,14523,14527,14531,14535,14539,14543,14547,14551,14555,14559,14563,14567,14571,14575,14579,14583,14587,14591,14595],{"__ignoreMap":355},[407,14524,14525],{"class":409,"line":410},[407,14526,2388],{},[407,14528,14529],{"class":409,"line":417},[407,14530,445],{"emptyLinePlaceholder":444},[407,14532,14533],{"class":409,"line":441},[407,14534,3137],{},[407,14536,14537],{"class":409,"line":448},[407,14538,3142],{},[407,14540,14541],{"class":409,"line":454},[407,14542,445],{"emptyLinePlaceholder":444},[407,14544,14545],{"class":409,"line":1667},[407,14546,3151],{},[407,14548,14549],{"class":409,"line":1673},[407,14550,3156],{},[407,14552,14553],{"class":409,"line":1679},[407,14554,445],{"emptyLinePlaceholder":444},[407,14556,14557],{"class":409,"line":1685},[407,14558,3165],{},[407,14560,14561],{"class":409,"line":1690},[407,14562,3170],{},[407,14564,14565],{"class":409,"line":1696},[407,14566,3175],{},[407,14568,14569],{"class":409,"line":1702},[407,14570,445],{"emptyLinePlaceholder":444},[407,14572,14573],{"class":409,"line":1708},[407,14574,3184],{},[407,14576,14577],{"class":409,"line":1714},[407,14578,3189],{},[407,14580,14581],{"class":409,"line":1719},[407,14582,3194],{},[407,14584,14585],{"class":409,"line":1725},[407,14586,445],{"emptyLinePlaceholder":444},[407,14588,14589],{"class":409,"line":1278},[407,14590,3203],{},[407,14592,14593],{"class":409,"line":1736},[407,14594,3208],{},[407,14596,14597],{"class":409,"line":1742},[407,14598,3213],{},[17,14600,3216],{},[58,14602,3220],{"id":3219},[17,14604,3223],{},[82,14606,14607,14611,14615],{},[85,14608,14609,3231],{},[24,14610,3230],{},[85,14612,14613,3237],{},[24,14614,3236],{},[85,14616,14617,3243,14619,3246],{},[24,14618,3242],{},[353,14620,1504],{},[17,14622,3249],{},[35,14624],{},[38,14626,3255],{"id":3254},[17,14628,3258,14629,3262],{},[24,14630,3261],{},[58,14632,3266],{"id":3265},[17,14634,3269,14635,3273],{},[24,14636,3272],{},[17,14638,3276,14639,3281,14641,688],{},[69,14640,3280],{"href":3279},[24,14642,3284],{},[58,14644,3288],{"id":3287},[17,14646,3291,14647,3295,14649,3299],{},[24,14648,3294],{},[24,14650,3298],{},[17,14652,3302],{},[58,14654,3306],{"id":3305},[17,14656,14657,3312],{},[24,14658,3311],{},[17,14660,14661],{},[24,14662,3317],{},[82,14664,14665,14667,14669],{},[85,14666,3322],{},[85,14668,3325],{},[85,14670,3328],{},[17,14672,14673],{},[24,14674,3333],{},[82,14676,14677],{},[85,14678,3338],{},[58,14680,3342],{"id":3341},[17,14682,3345,14683,3349],{},[353,14684,3348],{},[346,14686,14687],{"className":2192,"code":3352,"language":2194,"meta":355,"style":355},[353,14688,14689,14693,14699,14705,14715,14725,14729,14735,14745,14755,14761,14769,14773,14777,14781],{"__ignoreMap":355},[407,14690,14691],{"class":409,"line":410},[407,14692,2202],{"class":2201},[407,14694,14695,14697],{"class":409,"line":417},[407,14696,3363],{"class":434},[407,14698,2210],{"class":2201},[407,14700,14701,14703],{"class":409,"line":441},[407,14702,3370],{"class":434},[407,14704,2210],{"class":2201},[407,14706,14707,14709,14711,14713],{"class":409,"line":448},[407,14708,2222],{"class":434},[407,14710,2225],{"class":2201},[407,14712,3381],{"class":424},[407,14714,3384],{"class":2201},[407,14716,14717,14719,14721,14723],{"class":409,"line":454},[407,14718,3389],{"class":434},[407,14720,3392],{"class":2201},[407,14722,3395],{"class":424},[407,14724,3398],{"class":2201},[407,14726,14727],{"class":409,"line":1667},[407,14728,3403],{"class":2201},[407,14730,14731,14733],{"class":409,"line":1673},[407,14732,3408],{"class":434},[407,14734,2210],{"class":2201},[407,14736,14737,14739,14741,14743],{"class":409,"line":1679},[407,14738,2222],{"class":434},[407,14740,2225],{"class":2201},[407,14742,3381],{"class":424},[407,14744,3384],{"class":2201},[407,14746,14747,14749,14751,14753],{"class":409,"line":1685},[407,14748,3389],{"class":434},[407,14750,3392],{"class":2201},[407,14752,3429],{"class":424},[407,14754,3432],{"class":2201},[407,14756,14757,14759],{"class":409,"line":1690},[407,14758,3437],{"class":434},[407,14760,2210],{"class":2201},[407,14762,14763,14765,14767],{"class":409,"line":1696},[407,14764,3444],{"class":434},[407,14766,2225],{"class":2201},[407,14768,3449],{"class":424},[407,14770,14771],{"class":409,"line":1702},[407,14772,3454],{"class":2201},[407,14774,14775],{"class":409,"line":1708},[407,14776,2233],{"class":2201},[407,14778,14779],{"class":409,"line":1714},[407,14780,2238],{"class":2201},[407,14782,14783],{"class":409,"line":1719},[407,14784,2243],{"class":2201},[17,14786,3469,14787,688],{},[24,14788,3472],{},[58,14790,3476],{"id":3475},[17,14792,3479],{},[244,14794,14795,14805],{},[247,14796,14797],{},[250,14798,14799,14801,14803],{},[253,14800,3488],{},[253,14802,3491],{},[253,14804,3494],{},[260,14806,14807,14817,14827,14837,14847],{},[250,14808,14809,14813,14815],{},[265,14810,14811],{},[24,14812,3503],{},[265,14814,3506],{},[265,14816,3509],{},[250,14818,14819,14823,14825],{},[265,14820,14821],{},[24,14822,3516],{},[265,14824,3519],{},[265,14826,3522],{},[250,14828,14829,14833,14835],{},[265,14830,14831,3530],{},[24,14832,3529],{},[265,14834,3533],{},[265,14836,3536],{},[250,14838,14839,14843,14845],{},[265,14840,14841],{},[24,14842,3543],{},[265,14844,3546],{},[265,14846,3549],{},[250,14848,14849,14853,14855],{},[265,14850,14851],{},[24,14852,3556],{},[265,14854,3559],{},[265,14856,3562],{},[17,14858,3565],{},[35,14860],{},[38,14862,3571],{"id":3570},[17,14864,3574,14865,688],{},[24,14866,3577],{},[58,14868,3581],{"id":3580},[17,14870,3584],{},[17,14872,3587,14873,688],{},[24,14874,3590],{},[58,14876,3594],{"id":3593},[17,14878,3597],{},[517,14880,14881,14885],{},[85,14882,14883,3605],{},[24,14884,3604],{},[85,14886,14887,3611],{},[24,14888,3610],{},[17,14890,3614],{},[58,14892,3618],{"id":3617},[17,14894,3621],{},[346,14896,14898],{"className":14897,"code":3625,"language":351},[349],[353,14899,3625],{"__ignoreMap":355},[17,14901,3630],{},[346,14903,14905],{"className":14904,"code":3634,"language":351},[349],[353,14906,3634],{"__ignoreMap":355},[17,14908,3639],{},[58,14910,3643],{"id":3642},[17,14912,3646],{},[82,14914,14915,14919,14923,14927],{},[85,14916,14917,3654],{},[24,14918,3653],{},[85,14920,14921,3660],{},[24,14922,3659],{},[85,14924,14925,3666],{},[24,14926,3665],{},[85,14928,14929,3672],{},[24,14930,3671],{},[58,14932,3676],{"id":3675},[17,14934,3679],{},[346,14936,14938],{"className":14937,"code":3683,"language":351},[349],[353,14939,3683],{"__ignoreMap":355},[17,14941,3688],{},[346,14943,14945],{"className":14944,"code":3692,"language":351},[349],[353,14946,3692],{"__ignoreMap":355},[17,14948,3697,14949,3701],{},[353,14950,3700],{},[35,14952],{},[38,14954,3707],{"id":3706},[17,14956,3710],{},[58,14958,3714],{"id":3713},[17,14960,14961],{},[24,14962,3719],{},[17,14964,3722],{},[17,14966,14967],{},[24,14968,3727],{},[17,14970,3730],{},[17,14972,14973],{},[24,14974,3735],{},[17,14976,3738,14977,3742,14979,1894],{},[353,14978,3741],{},[353,14980,3745],{},[346,14982,14983],{"className":1637,"code":3748,"language":1639,"meta":355,"style":355},[353,14984,14985,14989,14993,14997,15001,15005],{"__ignoreMap":355},[407,14986,14987],{"class":409,"line":410},[407,14988,3755],{},[407,14990,14991],{"class":409,"line":417},[407,14992,3760],{},[407,14994,14995],{"class":409,"line":441},[407,14996,3765],{},[407,14998,14999],{"class":409,"line":448},[407,15000,3770],{},[407,15002,15003],{"class":409,"line":454},[407,15004,3775],{},[407,15006,15007],{"class":409,"line":1667},[407,15008,3780],{},[17,15010,3783,15011,3786,15013,688],{},[353,15012,2299],{},[24,15014,3789],{},[17,15016,15017],{},[24,15018,3794],{},[17,15020,3797],{},[58,15022,3801],{"id":3800},[346,15024,15026],{"className":15025,"code":3805,"language":351},[349],[353,15027,3805],{"__ignoreMap":355},[58,15029,3811],{"id":3810},[17,15031,3814],{},[346,15033,15035],{"className":15034,"code":3818,"language":351},[349],[353,15036,3818],{"__ignoreMap":355},[17,15038,3823,15039,3827],{},[24,15040,3826],{},[35,15042],{},[38,15044,3833],{"id":3832},[17,15046,3836],{},[58,15048,3840],{"id":3839},[17,15050,3843,15051,3847],{},[24,15052,3846],{},[346,15054,15055],{"className":3850,"code":3851,"language":3852,"meta":355,"style":355},[353,15056,15057,15061,15069,15077,15085,15097,15105,15109,15113,15117],{"__ignoreMap":355},[407,15058,15059],{"class":409,"line":410},[407,15060,3859],{"class":413},[407,15062,15063,15065,15067],{"class":409,"line":417},[407,15064,3865],{"class":3864},[407,15066,3868],{"class":420},[407,15068,3871],{"class":2201},[407,15070,15071,15073,15075],{"class":409,"line":441},[407,15072,3877],{"class":3876},[407,15074,1894],{"class":3864},[407,15076,3882],{"class":434},[407,15078,15079,15081,15083],{"class":409,"line":448},[407,15080,3887],{"class":3876},[407,15082,1894],{"class":3864},[407,15084,3882],{"class":434},[407,15086,15087,15089,15091,15093,15095],{"class":409,"line":454},[407,15088,3896],{"class":3876},[407,15090,1894],{"class":3864},[407,15092,3901],{"class":424},[407,15094,3904],{"class":3864},[407,15096,3907],{"class":424},[407,15098,15099,15101,15103],{"class":409,"line":1667},[407,15100,3912],{"class":3876},[407,15102,1894],{"class":3864},[407,15104,3917],{"class":420},[407,15106,15107],{"class":409,"line":1673},[407,15108,2243],{"class":2201},[407,15110,15111],{"class":409,"line":1679},[407,15112,445],{"emptyLinePlaceholder":444},[407,15114,15115],{"class":409,"line":1685},[407,15116,3930],{"class":413},[407,15118,15119],{"class":409,"line":1690},[407,15120,3935],{"class":413},[17,15122,3938],{},[58,15124,3942],{"id":3941},[17,15126,3945],{},[346,15128,15130],{"className":15129,"code":3949,"language":351},[349],[353,15131,3949],{"__ignoreMap":355},[17,15133,3954],{},[58,15135,3958],{"id":3957},[346,15137,15139],{"className":15138,"code":3962,"language":351},[349],[353,15140,3962],{"__ignoreMap":355},[17,15142,3967],{},[58,15144,3971],{"id":3970},[17,15146,3974,15147,1894],{},[24,15148,3977],{},[346,15150,15152],{"className":15151,"code":3981,"language":351},[349],[353,15153,3981],{"__ignoreMap":355},[17,15155,3630],{},[346,15157,15159],{"className":15158,"code":3989,"language":351},[349],[353,15160,3989],{"__ignoreMap":355},[17,15162,3994],{},[58,15164,3998],{"id":3997},[17,15166,4001,15167,4005],{},[24,15168,4004],{},[346,15170,15172],{"className":15171,"code":4009,"language":351},[349],[353,15173,4009],{"__ignoreMap":355},[17,15175,4014],{},[58,15177,4018],{"id":4017},[17,15179,4021],{},[346,15181,15183],{"className":15182,"code":4025,"language":351},[349],[353,15184,4025],{"__ignoreMap":355},[17,15186,4030],{},[58,15188,4034],{"id":4033},[17,15190,4037],{},[82,15192,15193,15195,15197,15199],{},[85,15194,4042],{},[85,15196,4045],{},[85,15198,4048],{},[85,15200,4051,15201,4055,15203,4059],{},[353,15202,4054],{},[353,15204,4058],{},[346,15206,15208],{"className":15207,"code":4063,"language":351},[349],[353,15209,4063],{"__ignoreMap":355},[35,15211],{},[38,15213,4071],{"id":4070},[58,15215,4075],{"id":4074},[17,15217,15218,4081],{},[24,15219,4080],{},[17,15221,15222,4087],{},[24,15223,4086],{},[17,15225,15226,4093],{},[24,15227,4092],{},[58,15229,4097],{"id":4096},[17,15231,15232,4102],{},[24,15233,4080],{},[17,15235,15236,4107],{},[24,15237,4086],{},[17,15239,15240,4112],{},[24,15241,4092],{},[58,15243,4116],{"id":4115},[17,15245,15246,4121],{},[24,15247,4080],{},[17,15249,15250,4126],{},[24,15251,4086],{},[17,15253,15254,4131],{},[24,15255,4092],{},[58,15257,4135],{"id":4134},[17,15259,15260,4140],{},[24,15261,4080],{},[17,15263,15264,4145],{},[24,15265,4086],{},[17,15267,15268,4150],{},[24,15269,4092],{},[58,15271,4154],{"id":4153},[17,15273,15274,4159],{},[24,15275,4080],{},[17,15277,15278,4164],{},[24,15279,4086],{},[17,15281,15282,4169],{},[24,15283,4092],{},[35,15285],{},[38,15287,4175],{"id":4174},[17,15289,4178],{},[346,15291,15292],{"className":1637,"code":4181,"language":1639,"meta":355,"style":355},[353,15293,15294,15298,15302,15306,15310,15314,15318,15322,15326,15330,15334,15338,15342,15346,15350,15354,15358,15362,15366,15370,15374],{"__ignoreMap":355},[407,15295,15296],{"class":409,"line":410},[407,15297,2388],{},[407,15299,15300],{"class":409,"line":417},[407,15301,445],{"emptyLinePlaceholder":444},[407,15303,15304],{"class":409,"line":441},[407,15305,4196],{},[407,15307,15308],{"class":409,"line":448},[407,15309,4201],{},[407,15311,15312],{"class":409,"line":454},[407,15313,445],{"emptyLinePlaceholder":444},[407,15315,15316],{"class":409,"line":1667},[407,15317,1693],{},[407,15319,15320],{"class":409,"line":1673},[407,15321,4214],{},[407,15323,15324],{"class":409,"line":1679},[407,15325,4219],{},[407,15327,15328],{"class":409,"line":1685},[407,15329,4224],{},[407,15331,15332],{"class":409,"line":1690},[407,15333,4229],{},[407,15335,15336],{"class":409,"line":1696},[407,15337,445],{"emptyLinePlaceholder":444},[407,15339,15340],{"class":409,"line":1702},[407,15341,4238],{},[407,15343,15344],{"class":409,"line":1708},[407,15345,4243],{},[407,15347,15348],{"class":409,"line":1714},[407,15349,445],{"emptyLinePlaceholder":444},[407,15351,15352],{"class":409,"line":1719},[407,15353,4252],{},[407,15355,15356],{"class":409,"line":1725},[407,15357,4257],{},[407,15359,15360],{"class":409,"line":1278},[407,15361,4262],{},[407,15363,15364],{"class":409,"line":1736},[407,15365,4267],{},[407,15367,15368],{"class":409,"line":1742},[407,15369,445],{"emptyLinePlaceholder":444},[407,15371,15372],{"class":409,"line":1748},[407,15373,3062],{},[407,15375,15376],{"class":409,"line":1753},[407,15377,4280],{},[17,15379,4283],{},[17,15381,4286],{},[35,15383],{},[38,15385,4292],{"id":4291},[17,15387,4295,15388,1894],{},[24,15389,4298],{},[244,15391,15392,15404],{},[247,15393,15394],{},[250,15395,15396,15398,15400,15402],{},[253,15397,1335],{},[253,15399,4309],{},[253,15401,4312],{},[253,15403,4315],{},[260,15405,15406,15418,15430,15442],{},[250,15407,15408,15412,15414,15416],{},[265,15409,15410],{},[24,15411,4324],{},[265,15413,4327],{},[265,15415,4330],{},[265,15417,4333],{},[250,15419,15420,15424,15426,15428],{},[265,15421,15422],{},[24,15423,4340],{},[265,15425,4343],{},[265,15427,4330],{},[265,15429,4348],{},[250,15431,15432,15436,15438,15440],{},[265,15433,15434],{},[24,15435,4355],{},[265,15437,4358],{},[265,15439,4361],{},[265,15441,4361],{},[250,15443,15444,15448,15450,15452],{},[265,15445,15446],{},[24,15447,4370],{},[265,15449,4373],{},[265,15451,4376],{},[265,15453,4379],{},[17,15455,4382],{},[17,15457,4385],{},[17,15459,4388,15460,4392],{},[24,15461,4391],{},[35,15463],{},[17,15465,15466,1894],{},[24,15467,4399],{},[82,15469,15470,15475,15480,15485,15490,15495,15500,15505,15510,15515],{},[85,15471,15472],{},[69,15473,4407],{"href":2679,"rel":15474},[1152],[85,15476,15477],{},[69,15478,4414],{"href":4412,"rel":15479},[1152],[85,15481,15482],{},[69,15483,4420],{"href":2695,"rel":15484},[1152],[85,15486,15487],{},[69,15488,4427],{"href":4425,"rel":15489},[1152],[85,15491,15492],{},[69,15493,4434],{"href":4432,"rel":15494},[1152],[85,15496,15497],{},[69,15498,4441],{"href":4439,"rel":15499},[1152],[85,15501,15502],{},[69,15503,4448],{"href":4446,"rel":15504},[1152],[85,15506,15507],{},[69,15508,4455],{"href":4453,"rel":15509},[1152],[85,15511,15512],{},[69,15513,4462],{"href":4460,"rel":15514},[1152],[85,15516,15517],{},[69,15518,4469],{"href":4467,"rel":15519},[1152],[1218,15521,4472],{},{"title":355,"searchDepth":417,"depth":417,"links":15523},[15524,15525,15532,15539,15546,15551,15560,15567,15568],{"id":2807,"depth":417,"text":2808},{"id":2832,"depth":417,"text":2833,"children":15526},[15527,15528,15529,15530,15531],{"id":2839,"depth":441,"text":2840},{"id":2365,"depth":441,"text":2957},{"id":2972,"depth":441,"text":2973},{"id":3115,"depth":441,"text":3116},{"id":3219,"depth":441,"text":3220},{"id":3254,"depth":417,"text":3255,"children":15533},[15534,15535,15536,15537,15538],{"id":3265,"depth":441,"text":3266},{"id":3287,"depth":441,"text":3288},{"id":3305,"depth":441,"text":3306},{"id":3341,"depth":441,"text":3342},{"id":3475,"depth":441,"text":3476},{"id":3570,"depth":417,"text":3571,"children":15540},[15541,15542,15543,15544,15545],{"id":3580,"depth":441,"text":3581},{"id":3593,"depth":441,"text":3594},{"id":3617,"depth":441,"text":3618},{"id":3642,"depth":441,"text":3643},{"id":3675,"depth":441,"text":3676},{"id":3706,"depth":417,"text":3707,"children":15547},[15548,15549,15550],{"id":3713,"depth":441,"text":3714},{"id":3800,"depth":441,"text":3801},{"id":3810,"depth":441,"text":3811},{"id":3832,"depth":417,"text":3833,"children":15552},[15553,15554,15555,15556,15557,15558,15559],{"id":3839,"depth":441,"text":3840},{"id":3941,"depth":441,"text":3942},{"id":3957,"depth":441,"text":3958},{"id":3970,"depth":441,"text":3971},{"id":3997,"depth":441,"text":3998},{"id":4017,"depth":441,"text":4018},{"id":4033,"depth":441,"text":4034},{"id":4070,"depth":417,"text":4071,"children":15561},[15562,15563,15564,15565,15566],{"id":4074,"depth":441,"text":4075},{"id":4096,"depth":441,"text":4097},{"id":4115,"depth":441,"text":4116},{"id":4134,"depth":441,"text":4135},{"id":4153,"depth":441,"text":4154},{"id":4174,"depth":417,"text":4175},{"id":4291,"depth":417,"text":4292},{},{"title":2779,"description":4520},[1285,1304,4528,4529,2766,1287,2294,1268],{"id":4532,"title":4533,"author":15573,"body":15574,"category":8060,"contentType":1269,"description":8061,"difficulty":2768,"extension":1272,"featured":444,"icon":1269,"image":8062,"meta":18352,"navigation":444,"path":8064,"publishedAt":8065,"readingTime":1719,"seo":18353,"stem":8067,"steps":1269,"tags":18354,"youtubeId":1269,"__hash__":8072},{"name":7,"initials":8},{"type":10,"value":15575,"toc":18327},[15576,15578,15582,15584,15590,15592,15594,15596,15600,15614,15616,15678,15688,15690,15692,15696,15742,15746,15846,15850,15900,15902,15904,15908,16560,16562,16582,16584,16594,16596,16598,16602,16986,16990,16992,16994,17000,17114,17116,17120,17166,17168,17170,17174,17262,17264,17266,17268,17272,17292,17296,17314,17316,17324,17326,17328,17330,17332,17334,17348,17400,17404,17412,17414,17478,17482,17484,17488,17540,17542,17548,17606,17608,17610,17614,17640,17844,17852,17854,17886,17888,17890,17894,17900,17910,17912,17914,17922,17924,17926,17930,17934,17938,17940,17944,17952,17954,17958,17962,17964,17966,17970,17974,18156,18162,18190,18192,18194,18196,18200,18214,18218,18235,18239,18259,18263,18267,18269,18271,18275,18325],[13,15577,4533],{"id":4539},[17,15579,4542,15580,4547],{},[69,15581,4546],{"href":4545},[17,15583,4550],{},[17,15585,4553,15586,4557,15588,4561],{},[24,15587,4556],{},[24,15589,4560],{},[17,15591,4564],{},[35,15593],{},[38,15595,4570],{"id":4569},[17,15597,4573,15598,4577],{},[24,15599,4576],{},[82,15601,15602,15606,15610],{},[85,15603,4582,15604,4586],{},[24,15605,4585],{},[85,15607,4589,15608,4593],{},[24,15609,4592],{},[85,15611,4582,15612,4599],{},[24,15613,4598],{},[17,15615,4602],{},[244,15617,15618,15628],{},[247,15619,15620],{},[250,15621,15622,15624,15626],{},[253,15623,4611],{},[253,15625,4614],{},[253,15627,4617],{},[260,15629,15630,15642,15654,15666],{},[250,15631,15632,15636,15640],{},[265,15633,15634],{},[24,15635,2264],{},[265,15637,15638],{},[353,15639,4630],{},[265,15641,4633],{},[250,15643,15644,15648,15652],{},[265,15645,15646],{},[24,15647,2264],{},[265,15649,15650],{},[353,15651,4644],{},[265,15653,4647],{},[250,15655,15656,15660,15664],{},[265,15657,15658],{},[24,15659,4654],{},[265,15661,15662],{},[353,15663,4659],{},[265,15665,4662],{},[250,15667,15668,15672,15676],{},[265,15669,15670],{},[24,15671,4669],{},[265,15673,15674],{},[353,15675,4674],{},[265,15677,4677],{},[17,15679,4680,15680,4684,15682,4687,15684,4691,15686,688],{},[2128,15681,4683],{},[353,15683,4630],{},[2128,15685,4690],{},[353,15687,4644],{},[35,15689],{},[38,15691,4699],{"id":4698},[17,15693,4702,15694,688],{},[353,15695,4705],{},[346,15697,15698],{"className":401,"code":4708,"language":403,"meta":355,"style":355},[353,15699,15700,15706,15712,15720,15730],{"__ignoreMap":355},[407,15701,15702,15704],{"class":409,"line":410},[407,15703,4715],{"class":420},[407,15705,4718],{"class":424},[407,15707,15708,15710],{"class":409,"line":417},[407,15709,4723],{"class":434},[407,15711,4718],{"class":424},[407,15713,15714,15716,15718],{"class":409,"line":441},[407,15715,4730],{"class":420},[407,15717,4733],{"class":424},[407,15719,4736],{"class":434},[407,15721,15722,15724,15726,15728],{"class":409,"line":448},[407,15723,4730],{"class":420},[407,15725,4743],{"class":424},[407,15727,4746],{"class":424},[407,15729,4749],{"class":424},[407,15731,15732,15734,15736,15738,15740],{"class":409,"line":454},[407,15733,4730],{"class":420},[407,15735,4743],{"class":424},[407,15737,4758],{"class":434},[407,15739,4761],{"class":424},[407,15741,4764],{"class":424},[17,15743,4767,15744,1894],{},[353,15745,4770],{},[346,15747,15748],{"className":2192,"code":4773,"language":2194,"meta":355,"style":355},[353,15749,15750,15754,15760,15770,15780,15790,15800,15810,15820,15828,15832,15842],{"__ignoreMap":355},[407,15751,15752],{"class":409,"line":410},[407,15753,2202],{"class":2201},[407,15755,15756,15758],{"class":409,"line":417},[407,15757,4784],{"class":434},[407,15759,2210],{"class":2201},[407,15761,15762,15764,15766,15768],{"class":409,"line":441},[407,15763,4791],{"class":434},[407,15765,2225],{"class":2201},[407,15767,4796],{"class":424},[407,15769,3384],{"class":2201},[407,15771,15772,15774,15776,15778],{"class":409,"line":448},[407,15773,4803],{"class":434},[407,15775,2225],{"class":2201},[407,15777,4808],{"class":424},[407,15779,3384],{"class":2201},[407,15781,15782,15784,15786,15788],{"class":409,"line":454},[407,15783,4815],{"class":434},[407,15785,2225],{"class":2201},[407,15787,4808],{"class":424},[407,15789,3384],{"class":2201},[407,15791,15792,15794,15796,15798],{"class":409,"line":1667},[407,15793,4826],{"class":434},[407,15795,2225],{"class":2201},[407,15797,4831],{"class":424},[407,15799,3384],{"class":2201},[407,15801,15802,15804,15806,15808],{"class":409,"line":1673},[407,15803,4838],{"class":434},[407,15805,2225],{"class":2201},[407,15807,4843],{"class":424},[407,15809,3384],{"class":2201},[407,15811,15812,15814,15816,15818],{"class":409,"line":1679},[407,15813,4850],{"class":434},[407,15815,2225],{"class":2201},[407,15817,4855],{"class":434},[407,15819,3384],{"class":2201},[407,15821,15822,15824,15826],{"class":409,"line":1685},[407,15823,4862],{"class":434},[407,15825,2225],{"class":2201},[407,15827,4867],{"class":434},[407,15829,15830],{"class":409,"line":1690},[407,15831,4872],{"class":2201},[407,15833,15834,15836,15838,15840],{"class":409,"line":1696},[407,15835,4877],{"class":434},[407,15837,3392],{"class":2201},[407,15839,4882],{"class":424},[407,15841,3398],{"class":2201},[407,15843,15844],{"class":409,"line":1702},[407,15845,2243],{"class":2201},[17,15847,4891,15848,1894],{},[353,15849,4894],{},[346,15851,15852],{"className":2192,"code":4897,"language":2194,"meta":355,"style":355},[353,15853,15854,15858,15868,15874,15884,15892,15896],{"__ignoreMap":355},[407,15855,15856],{"class":409,"line":410},[407,15857,2202],{"class":2201},[407,15859,15860,15862,15864,15866],{"class":409,"line":417},[407,15861,4908],{"class":434},[407,15863,2225],{"class":2201},[407,15865,4913],{"class":424},[407,15867,3384],{"class":2201},[407,15869,15870,15872],{"class":409,"line":441},[407,15871,4920],{"class":434},[407,15873,2210],{"class":2201},[407,15875,15876,15878,15880,15882],{"class":409,"line":448},[407,15877,4927],{"class":434},[407,15879,2225],{"class":2201},[407,15881,4932],{"class":424},[407,15883,3384],{"class":2201},[407,15885,15886,15888,15890],{"class":409,"line":454},[407,15887,4939],{"class":434},[407,15889,2225],{"class":2201},[407,15891,4944],{"class":424},[407,15893,15894],{"class":409,"line":1667},[407,15895,2238],{"class":2201},[407,15897,15898],{"class":409,"line":1673},[407,15899,2243],{"class":2201},[35,15901],{},[38,15903,4958],{"id":4957},[17,15905,4961,15906,1894],{},[353,15907,4964],{},[346,15909,15910],{"className":3850,"code":4967,"language":3852,"meta":355,"style":355},[353,15911,15912,15924,15936,15948,15960,15972,15976,15980,16002,16006,16014,16024,16034,16044,16054,16064,16068,16072,16092,16098,16122,16134,16142,16150,16154,16158,16162,16190,16220,16224,16228,16232,16236,16250,16258,16264,16268,16272,16276,16284,16292,16300,16306,16322,16338,16362,16366,16390,16404,16418,16426,16430,16434,16442,16456,16460,16468,16476,16482,16486,16494,16512,16516,16520,16524,16528,16532,16536,16550],{"__ignoreMap":355},[407,15913,15914,15916,15918,15920,15922],{"class":409,"line":410},[407,15915,4974],{"class":3864},[407,15917,4977],{"class":2201},[407,15919,4980],{"class":3864},[407,15921,4983],{"class":424},[407,15923,4986],{"class":2201},[407,15925,15926,15928,15930,15932,15934],{"class":409,"line":417},[407,15927,4974],{"class":3864},[407,15929,4993],{"class":2201},[407,15931,4980],{"class":3864},[407,15933,4998],{"class":424},[407,15935,4986],{"class":2201},[407,15937,15938,15940,15942,15944,15946],{"class":409,"line":441},[407,15939,4974],{"class":3864},[407,15941,5007],{"class":2201},[407,15943,4980],{"class":3864},[407,15945,5012],{"class":424},[407,15947,4986],{"class":2201},[407,15949,15950,15952,15954,15956,15958],{"class":409,"line":448},[407,15951,4974],{"class":3864},[407,15953,5021],{"class":2201},[407,15955,4980],{"class":3864},[407,15957,5026],{"class":424},[407,15959,4986],{"class":2201},[407,15961,15962,15964,15966,15968,15970],{"class":409,"line":454},[407,15963,4974],{"class":3864},[407,15965,5035],{"class":2201},[407,15967,4980],{"class":3864},[407,15969,5040],{"class":424},[407,15971,4986],{"class":2201},[407,15973,15974],{"class":409,"line":1667},[407,15975,445],{"emptyLinePlaceholder":444},[407,15977,15978],{"class":409,"line":1673},[407,15979,5051],{"class":413},[407,15981,15982,15984,15986,15988,15990,15992,15994,15996,15998,16000],{"class":409,"line":1679},[407,15983,5056],{"class":3864},[407,15985,5059],{"class":434},[407,15987,5062],{"class":3864},[407,15989,5065],{"class":2201},[407,15991,5068],{"class":420},[407,15993,5071],{"class":2201},[407,15995,5074],{"class":420},[407,15997,5077],{"class":2201},[407,15999,5080],{"class":424},[407,16001,5083],{"class":2201},[407,16003,16004],{"class":409,"line":1685},[407,16005,445],{"emptyLinePlaceholder":444},[407,16007,16008,16010,16012],{"class":409,"line":1690},[407,16009,3865],{"class":3864},[407,16011,5094],{"class":420},[407,16013,3871],{"class":2201},[407,16015,16016,16018,16020,16022],{"class":409,"line":1696},[407,16017,3877],{"class":3876},[407,16019,1894],{"class":3864},[407,16021,5105],{"class":434},[407,16023,4986],{"class":2201},[407,16025,16026,16028,16030,16032],{"class":409,"line":1702},[407,16027,5112],{"class":3876},[407,16029,1894],{"class":3864},[407,16031,5105],{"class":434},[407,16033,4986],{"class":2201},[407,16035,16036,16038,16040,16042],{"class":409,"line":1708},[407,16037,5123],{"class":3876},[407,16039,1894],{"class":3864},[407,16041,5105],{"class":434},[407,16043,4986],{"class":2201},[407,16045,16046,16048,16050,16052],{"class":409,"line":1714},[407,16047,5134],{"class":3876},[407,16049,1894],{"class":3864},[407,16051,5105],{"class":434},[407,16053,5141],{"class":2201},[407,16055,16056,16058,16060,16062],{"class":409,"line":1719},[407,16057,3912],{"class":3876},[407,16059,1894],{"class":3864},[407,16061,5105],{"class":434},[407,16063,4986],{"class":2201},[407,16065,16066],{"class":409,"line":1725},[407,16067,2243],{"class":2201},[407,16069,16070],{"class":409,"line":1278},[407,16071,445],{"emptyLinePlaceholder":444},[407,16073,16074,16076,16078,16080,16082,16084,16086,16088,16090],{"class":409,"line":1736},[407,16075,5164],{"class":3864},[407,16077,5167],{"class":3864},[407,16079,5170],{"class":420},[407,16081,5173],{"class":2201},[407,16083,1894],{"class":3864},[407,16085,5178],{"class":420},[407,16087,5181],{"class":2201},[407,16089,5184],{"class":420},[407,16091,5187],{"class":2201},[407,16093,16094,16096],{"class":409,"line":1742},[407,16095,5192],{"class":3864},[407,16097,3871],{"class":2201},[407,16099,16100,16102,16104,16106,16108,16110,16112,16114,16116,16118,16120],{"class":409,"line":1748},[407,16101,5199],{"class":3864},[407,16103,5202],{"class":434},[407,16105,5062],{"class":3864},[407,16107,5207],{"class":3864},[407,16109,5210],{"class":2201},[407,16111,5213],{"class":420},[407,16113,5216],{"class":2201},[407,16115,5219],{"class":434},[407,16117,2078],{"class":2201},[407,16119,5224],{"class":424},[407,16121,5083],{"class":2201},[407,16123,16124,16126,16128,16130,16132],{"class":409,"line":1753},[407,16125,5231],{"class":3864},[407,16127,5234],{"class":434},[407,16129,688],{"class":2201},[407,16131,5239],{"class":420},[407,16133,5242],{"class":2201},[407,16135,16136,16138,16140],{"class":409,"line":1759},[407,16137,5247],{"class":2201},[407,16139,5250],{"class":3864},[407,16141,3871],{"class":2201},[407,16143,16144,16146,16148],{"class":409,"line":1765},[407,16145,5231],{"class":3864},[407,16147,5259],{"class":2201},[407,16149,5262],{"class":413},[407,16151,16152],{"class":409,"line":1771},[407,16153,2238],{"class":2201},[407,16155,16156],{"class":409,"line":1777},[407,16157,2243],{"class":2201},[407,16159,16160],{"class":409,"line":1782},[407,16161,445],{"emptyLinePlaceholder":444},[407,16163,16164,16166,16168,16170,16172,16174,16176,16178,16180,16182,16184,16186,16188],{"class":409,"line":1788},[407,16165,5164],{"class":3864},[407,16167,5167],{"class":3864},[407,16169,5283],{"class":420},[407,16171,5216],{"class":2201},[407,16173,5288],{"class":3876},[407,16175,1894],{"class":3864},[407,16177,5094],{"class":420},[407,16179,5295],{"class":2201},[407,16181,1894],{"class":3864},[407,16183,5178],{"class":420},[407,16185,5181],{"class":2201},[407,16187,5304],{"class":434},[407,16189,5307],{"class":2201},[407,16191,16192,16194,16196,16198,16200,16202,16204,16206,16208,16210,16212,16214,16216,16218],{"class":409,"line":1794},[407,16193,5312],{"class":3864},[407,16195,5210],{"class":2201},[407,16197,5317],{"class":420},[407,16199,5216],{"class":2201},[407,16201,5219],{"class":434},[407,16203,2078],{"class":2201},[407,16205,5326],{"class":434},[407,16207,688],{"class":2201},[407,16209,5331],{"class":420},[407,16211,5334],{"class":2201},[407,16213,5337],{"class":434},[407,16215,2078],{"class":2201},[407,16217,5342],{"class":434},[407,16219,5345],{"class":2201},[407,16221,16222],{"class":409,"line":5348},[407,16223,2243],{"class":2201},[407,16225,16226],{"class":409,"line":5353},[407,16227,445],{"emptyLinePlaceholder":444},[407,16229,16230],{"class":409,"line":5358},[407,16231,5361],{"class":413},[407,16233,16234],{"class":409,"line":5364},[407,16235,445],{"emptyLinePlaceholder":444},[407,16237,16238,16240,16242,16244,16246,16248],{"class":409,"line":5369},[407,16239,5056],{"class":3864},[407,16241,5374],{"class":434},[407,16243,5062],{"class":3864},[407,16245,5379],{"class":3864},[407,16247,5382],{"class":420},[407,16249,5385],{"class":2201},[407,16251,16252,16254,16256],{"class":409,"line":5388},[407,16253,5391],{"class":2201},[407,16255,5394],{"class":424},[407,16257,3384],{"class":2201},[407,16259,16260,16262],{"class":409,"line":5399},[407,16261,5402],{"class":2201},[407,16263,5405],{"class":424},[407,16265,16266],{"class":409,"line":5408},[407,16267,5411],{"class":2201},[407,16269,16270],{"class":409,"line":5414},[407,16271,445],{"emptyLinePlaceholder":444},[407,16273,16274],{"class":409,"line":5419},[407,16275,5422],{"class":413},[407,16277,16278,16280,16282],{"class":409,"line":5425},[407,16279,5428],{"class":2201},[407,16281,5431],{"class":420},[407,16283,5434],{"class":2201},[407,16285,16286,16288,16290],{"class":409,"line":5437},[407,16287,5440],{"class":424},[407,16289,5443],{"class":2201},[407,16291,5446],{"class":413},[407,16293,16294,16296,16298],{"class":409,"line":5449},[407,16295,5452],{"class":424},[407,16297,5455],{"class":2201},[407,16299,5458],{"class":413},[407,16301,16302,16304],{"class":409,"line":5461},[407,16303,5464],{"class":2201},[407,16305,5467],{"class":413},[407,16307,16308,16310,16312,16314,16316,16318,16320],{"class":409,"line":5470},[407,16309,5473],{"class":2201},[407,16311,5476],{"class":420},[407,16313,5479],{"class":2201},[407,16315,5482],{"class":420},[407,16317,5216],{"class":2201},[407,16319,5487],{"class":424},[407,16321,5490],{"class":2201},[407,16323,16324,16326,16328,16330,16332,16334,16336],{"class":409,"line":5493},[407,16325,5496],{"class":2201},[407,16327,5476],{"class":420},[407,16329,5479],{"class":2201},[407,16331,5482],{"class":420},[407,16333,5216],{"class":2201},[407,16335,5507],{"class":424},[407,16337,5490],{"class":2201},[407,16339,16340,16342,16344,16346,16348,16350,16352,16354,16356,16358,16360],{"class":409,"line":5512},[407,16341,5515],{"class":2201},[407,16343,5518],{"class":420},[407,16345,5521],{"class":2201},[407,16347,5476],{"class":420},[407,16349,5526],{"class":2201},[407,16351,5529],{"class":420},[407,16353,5479],{"class":2201},[407,16355,5482],{"class":420},[407,16357,5216],{"class":2201},[407,16359,5538],{"class":424},[407,16361,5541],{"class":2201},[407,16363,16364],{"class":409,"line":5544},[407,16365,4872],{"class":2201},[407,16367,16368,16370,16372,16374,16376,16378,16380,16382,16384,16386,16388],{"class":409,"line":5549},[407,16369,5552],{"class":3864},[407,16371,5555],{"class":2201},[407,16373,5558],{"class":3876},[407,16375,2078],{"class":2201},[407,16377,5563],{"class":3876},[407,16379,2078],{"class":2201},[407,16381,5568],{"class":3876},[407,16383,5571],{"class":2201},[407,16385,5574],{"class":3864},[407,16387,5577],{"class":2201},[407,16389,5580],{"class":413},[407,16391,16392,16394,16396,16398,16400,16402],{"class":409,"line":5583},[407,16393,5199],{"class":3864},[407,16395,5588],{"class":434},[407,16397,5062],{"class":3864},[407,16399,5207],{"class":3864},[407,16401,5170],{"class":420},[407,16403,5597],{"class":2201},[407,16405,16406,16408,16410,16412,16414,16416],{"class":409,"line":5600},[407,16407,5199],{"class":3864},[407,16409,5605],{"class":434},[407,16411,1894],{"class":3864},[407,16413,5094],{"class":420},[407,16415,5062],{"class":3864},[407,16417,3871],{"class":2201},[407,16419,16420,16422,16424],{"class":409,"line":5616},[407,16421,5619],{"class":2201},[407,16423,5622],{"class":420},[407,16425,5625],{"class":2201},[407,16427,16428],{"class":409,"line":5628},[407,16429,5631],{"class":2201},[407,16431,16432],{"class":409,"line":5634},[407,16433,5637],{"class":2201},[407,16435,16436,16438,16440],{"class":409,"line":5640},[407,16437,5643],{"class":2201},[407,16439,5646],{"class":3864},[407,16441,5649],{"class":2201},[407,16443,16444,16446,16448,16450,16452,16454],{"class":409,"line":5652},[407,16445,5655],{"class":2201},[407,16447,5658],{"class":3864},[407,16449,5661],{"class":420},[407,16451,5479],{"class":2201},[407,16453,5666],{"class":420},[407,16455,5669],{"class":2201},[407,16457,16458],{"class":409,"line":5672},[407,16459,5675],{"class":2201},[407,16461,16462,16464,16466],{"class":409,"line":5678},[407,16463,5681],{"class":2201},[407,16465,5684],{"class":420},[407,16467,5687],{"class":2201},[407,16469,16470,16472,16474],{"class":409,"line":5690},[407,16471,5693],{"class":3864},[407,16473,5283],{"class":420},[407,16475,5698],{"class":2201},[407,16477,16478,16480],{"class":409,"line":5701},[407,16479,5231],{"class":3864},[407,16481,3871],{"class":2201},[407,16483,16484],{"class":409,"line":5708},[407,16485,5711],{"class":2201},[407,16487,16488,16490,16492],{"class":409,"line":5714},[407,16489,5717],{"class":2201},[407,16491,5720],{"class":424},[407,16493,3384],{"class":2201},[407,16495,16496,16498,16500,16502,16504,16506,16508,16510],{"class":409,"line":5725},[407,16497,5728],{"class":2201},[407,16499,5731],{"class":424},[407,16501,5558],{"class":2201},[407,16503,5736],{"class":424},[407,16505,5739],{"class":2201},[407,16507,688],{"class":424},[407,16509,5744],{"class":2201},[407,16511,5747],{"class":424},[407,16513,16514],{"class":409,"line":5750},[407,16515,5753],{"class":2201},[407,16517,16518],{"class":409,"line":5756},[407,16519,5675],{"class":2201},[407,16521,16522],{"class":409,"line":5761},[407,16523,2238],{"class":2201},[407,16525,16526],{"class":409,"line":5766},[407,16527,5083],{"class":2201},[407,16529,16530],{"class":409,"line":5771},[407,16531,445],{"emptyLinePlaceholder":444},[407,16533,16534],{"class":409,"line":5776},[407,16535,5779],{"class":413},[407,16537,16538,16540,16542,16544,16546,16548],{"class":409,"line":5782},[407,16539,5056],{"class":3864},[407,16541,5787],{"class":434},[407,16543,5062],{"class":3864},[407,16545,5379],{"class":3864},[407,16547,5794],{"class":420},[407,16549,5597],{"class":2201},[407,16551,16552,16554,16556,16558],{"class":409,"line":5799},[407,16553,5802],{"class":3864},[407,16555,5805],{"class":2201},[407,16557,5808],{"class":420},[407,16559,5811],{"class":2201},[17,16561,5814],{},[517,16563,16564,16568,16576],{},[85,16565,16566,5822],{},[24,16567,5821],{},[85,16569,16570,5828,16572,5832,16574,688],{},[24,16571,5827],{},[353,16573,5831],{},[353,16575,5835],{},[85,16577,16578,5841,16580,5845],{},[24,16579,5840],{},[353,16581,5844],{},[17,16583,5848],{},[346,16585,16586],{"className":401,"code":5851,"language":403,"meta":355,"style":355},[353,16587,16588],{"__ignoreMap":355},[407,16589,16590,16592],{"class":409,"line":410},[407,16591,5858],{"class":420},[407,16593,5861],{"class":424},[35,16595],{},[38,16597,5867],{"id":5866},[17,16599,5870,16600,1894],{},[353,16601,4630],{},[346,16603,16604],{"className":3850,"code":5875,"language":3852,"meta":355,"style":355},[353,16605,16606,16614,16620,16626,16630,16646,16666,16670,16688,16702,16716,16720,16738,16752,16764,16768,16772,16778,16794,16820,16824,16828,16832,16846,16852,16864,16868,16872,16876,16894,16936,16956,16960,16966,16974,16978,16982],{"__ignoreMap":355},[407,16607,16608,16610,16612],{"class":409,"line":410},[407,16609,5428],{"class":2201},[407,16611,5431],{"class":420},[407,16613,5434],{"class":2201},[407,16615,16616,16618],{"class":409,"line":417},[407,16617,5890],{"class":424},[407,16619,3384],{"class":2201},[407,16621,16622,16624],{"class":409,"line":441},[407,16623,5897],{"class":424},[407,16625,3384],{"class":2201},[407,16627,16628],{"class":409,"line":448},[407,16629,5904],{"class":2201},[407,16631,16632,16634,16636,16638,16640,16642,16644],{"class":409,"line":454},[407,16633,5909],{"class":2201},[407,16635,5476],{"class":420},[407,16637,5479],{"class":2201},[407,16639,5482],{"class":420},[407,16641,5216],{"class":2201},[407,16643,5920],{"class":424},[407,16645,5490],{"class":2201},[407,16647,16648,16650,16652,16654,16656,16658,16660,16662,16664],{"class":409,"line":1667},[407,16649,5927],{"class":2201},[407,16651,5476],{"class":420},[407,16653,5479],{"class":2201},[407,16655,5529],{"class":420},[407,16657,5479],{"class":2201},[407,16659,5482],{"class":420},[407,16661,5216],{"class":2201},[407,16663,5942],{"class":424},[407,16665,5541],{"class":2201},[407,16667,16668],{"class":409,"line":1673},[407,16669,4872],{"class":2201},[407,16671,16672,16674,16676,16678,16680,16682,16684,16686],{"class":409,"line":1679},[407,16673,5552],{"class":3864},[407,16675,5555],{"class":2201},[407,16677,5957],{"class":3876},[407,16679,2078],{"class":2201},[407,16681,5962],{"class":3876},[407,16683,5571],{"class":2201},[407,16685,5574],{"class":3864},[407,16687,3871],{"class":2201},[407,16689,16690,16692,16694,16696,16698,16700],{"class":409,"line":1685},[407,16691,5199],{"class":3864},[407,16693,5588],{"class":434},[407,16695,5062],{"class":3864},[407,16697,5207],{"class":3864},[407,16699,5170],{"class":420},[407,16701,5597],{"class":2201},[407,16703,16704,16706,16708,16710,16712,16714],{"class":409,"line":1690},[407,16705,5199],{"class":3864},[407,16707,5989],{"class":434},[407,16709,5062],{"class":3864},[407,16711,5994],{"class":2201},[407,16713,5997],{"class":420},[407,16715,5597],{"class":2201},[407,16717,16718],{"class":409,"line":1696},[407,16719,445],{"emptyLinePlaceholder":444},[407,16721,16722,16724,16726,16728,16730,16732,16734,16736],{"class":409,"line":1702},[407,16723,6008],{"class":3864},[407,16725,6011],{"class":2201},[407,16727,6014],{"class":3864},[407,16729,6017],{"class":2201},[407,16731,6020],{"class":420},[407,16733,5216],{"class":2201},[407,16735,6025],{"class":3876},[407,16737,6028],{"class":3864},[407,16739,16740,16742,16744,16746,16748,16750],{"class":409,"line":1708},[407,16741,6033],{"class":2201},[407,16743,5997],{"class":420},[407,16745,5479],{"class":2201},[407,16747,6040],{"class":420},[407,16749,6043],{"class":2201},[407,16751,6046],{"class":3864},[407,16753,16754,16756,16758,16760,16762],{"class":409,"line":1714},[407,16755,6051],{"class":2201},[407,16757,5997],{"class":420},[407,16759,5479],{"class":2201},[407,16761,6040],{"class":420},[407,16763,6060],{"class":2201},[407,16765,16766],{"class":409,"line":1719},[407,16767,6065],{"class":2201},[407,16769,16770],{"class":409,"line":1725},[407,16771,445],{"emptyLinePlaceholder":444},[407,16773,16774,16776],{"class":409,"line":1278},[407,16775,6074],{"class":3864},[407,16777,6077],{"class":2201},[407,16779,16780,16782,16784,16786,16788,16790,16792],{"class":409,"line":1736},[407,16781,6082],{"class":2201},[407,16783,6014],{"class":3864},[407,16785,6087],{"class":2201},[407,16787,6020],{"class":420},[407,16789,5216],{"class":2201},[407,16791,6025],{"class":3876},[407,16793,6028],{"class":3864},[407,16795,16796,16798,16800,16802,16804,16806,16808,16810,16812,16814,16816,16818],{"class":409,"line":1742},[407,16797,6100],{"class":2201},[407,16799,6103],{"class":420},[407,16801,5216],{"class":2201},[407,16803,6108],{"class":3876},[407,16805,6111],{"class":3864},[407,16807,6114],{"class":2201},[407,16809,5997],{"class":420},[407,16811,6119],{"class":2201},[407,16813,6122],{"class":3864},[407,16815,6125],{"class":2201},[407,16817,5997],{"class":420},[407,16819,6130],{"class":2201},[407,16821,16822],{"class":409,"line":1748},[407,16823,6135],{"class":2201},[407,16825,16826],{"class":409,"line":1753},[407,16827,2233],{"class":2201},[407,16829,16830],{"class":409,"line":1759},[407,16831,445],{"emptyLinePlaceholder":444},[407,16833,16834,16836,16838,16840,16842,16844],{"class":409,"line":1765},[407,16835,6074],{"class":3864},[407,16837,6150],{"class":2201},[407,16839,6153],{"class":434},[407,16841,6156],{"class":3864},[407,16843,6159],{"class":434},[407,16845,6162],{"class":2201},[407,16847,16848,16850],{"class":409,"line":1771},[407,16849,6167],{"class":3864},[407,16851,3871],{"class":2201},[407,16853,16854,16856,16858,16860,16862],{"class":409,"line":1777},[407,16855,6174],{"class":2201},[407,16857,5720],{"class":424},[407,16859,6179],{"class":2201},[407,16861,6182],{"class":424},[407,16863,6185],{"class":2201},[407,16865,16866],{"class":409,"line":1782},[407,16867,6190],{"class":2201},[407,16869,16870],{"class":409,"line":1788},[407,16871,2233],{"class":2201},[407,16873,16874],{"class":409,"line":1794},[407,16875,445],{"emptyLinePlaceholder":444},[407,16877,16878,16880,16882,16884,16886,16888,16890,16892],{"class":409,"line":5348},[407,16879,5199],{"class":3864},[407,16881,6205],{"class":434},[407,16883,5062],{"class":3864},[407,16885,6087],{"class":2201},[407,16887,6212],{"class":420},[407,16889,5216],{"class":2201},[407,16891,6025],{"class":3876},[407,16893,6028],{"class":3864},[407,16895,16896,16898,16900,16902,16904,16906,16908,16910,16912,16914,16916,16918,16920,16922,16924,16926,16928,16930,16932,16934],{"class":409,"line":5353},[407,16897,6223],{"class":424},[407,16899,6025],{"class":2201},[407,16901,688],{"class":424},[407,16903,5558],{"class":2201},[407,16905,6232],{"class":424},[407,16907,6025],{"class":2201},[407,16909,688],{"class":424},[407,16911,5568],{"class":2201},[407,16913,688],{"class":424},[407,16915,5068],{"class":420},[407,16917,5216],{"class":424},[407,16919,6247],{"class":424},[407,16921,6250],{"class":424},[407,16923,6253],{"class":424},[407,16925,6256],{"class":434},[407,16927,6259],{"class":424},[407,16929,6025],{"class":2201},[407,16931,688],{"class":424},[407,16933,5563],{"class":2201},[407,16935,6268],{"class":424},[407,16937,16938,16940,16942,16944,16946,16948,16950,16952,16954],{"class":409,"line":5358},[407,16939,6273],{"class":2201},[407,16941,5068],{"class":420},[407,16943,5216],{"class":2201},[407,16945,6280],{"class":424},[407,16947,6283],{"class":434},[407,16949,6286],{"class":424},[407,16951,6283],{"class":434},[407,16953,6280],{"class":424},[407,16955,5083],{"class":2201},[407,16957,16958],{"class":409,"line":5364},[407,16959,445],{"emptyLinePlaceholder":444},[407,16961,16962,16964],{"class":409,"line":5369},[407,16963,5231],{"class":3864},[407,16965,3871],{"class":2201},[407,16967,16968,16970,16972],{"class":409,"line":5388},[407,16969,6307],{"class":2201},[407,16971,5720],{"class":424},[407,16973,6312],{"class":2201},[407,16975,16976],{"class":409,"line":5399},[407,16977,5675],{"class":2201},[407,16979,16980],{"class":409,"line":5408},[407,16981,2238],{"class":2201},[407,16983,16984],{"class":409,"line":5414},[407,16985,5083],{"class":2201},[17,16987,6327,16988,6331],{},[24,16989,6330],{},[35,16991],{},[38,16993,6337],{"id":6336},[17,16995,6340,16996,6344,16998,6348],{},[24,16997,6343],{},[24,16999,6347],{},[346,17001,17002],{"className":3850,"code":6351,"language":3852,"meta":355,"style":355},[353,17003,17004,17012,17020,17028,17042,17056,17062,17066,17070,17078,17098,17102,17106,17110],{"__ignoreMap":355},[407,17005,17006,17008,17010],{"class":409,"line":410},[407,17007,5428],{"class":2201},[407,17009,6343],{"class":420},[407,17011,5434],{"class":2201},[407,17013,17014,17016,17018],{"class":409,"line":417},[407,17015,6366],{"class":424},[407,17017,6369],{"class":2201},[407,17019,6372],{"class":413},[407,17021,17022,17024,17026],{"class":409,"line":441},[407,17023,6377],{"class":424},[407,17025,6380],{"class":2201},[407,17027,6383],{"class":413},[407,17029,17030,17032,17034,17036,17038,17040],{"class":409,"line":448},[407,17031,5552],{"class":3864},[407,17033,1486],{"class":2201},[407,17035,6392],{"class":3876},[407,17037,6395],{"class":2201},[407,17039,5574],{"class":3864},[407,17041,3871],{"class":2201},[407,17043,17044,17046,17048,17050,17052,17054],{"class":409,"line":454},[407,17045,5199],{"class":3864},[407,17047,5588],{"class":434},[407,17049,5062],{"class":3864},[407,17051,5207],{"class":3864},[407,17053,5170],{"class":420},[407,17055,5597],{"class":2201},[407,17057,17058,17060],{"class":409,"line":1667},[407,17059,5231],{"class":3864},[407,17061,3871],{"class":2201},[407,17063,17064],{"class":409,"line":1673},[407,17065,6424],{"class":2201},[407,17067,17068],{"class":409,"line":1679},[407,17069,6429],{"class":2201},[407,17071,17072,17074,17076],{"class":409,"line":1685},[407,17073,6434],{"class":2201},[407,17075,6437],{"class":424},[407,17077,3384],{"class":2201},[407,17079,17080,17082,17084,17086,17088,17090,17092,17094,17096],{"class":409,"line":1690},[407,17081,5728],{"class":2201},[407,17083,5326],{"class":434},[407,17085,688],{"class":2201},[407,17087,5331],{"class":420},[407,17089,5334],{"class":2201},[407,17091,5337],{"class":434},[407,17093,2078],{"class":2201},[407,17095,5342],{"class":434},[407,17097,5541],{"class":2201},[407,17099,17100],{"class":409,"line":1696},[407,17101,5753],{"class":2201},[407,17103,17104],{"class":409,"line":1702},[407,17105,5675],{"class":2201},[407,17107,17108],{"class":409,"line":1708},[407,17109,2238],{"class":2201},[407,17111,17112],{"class":409,"line":1714},[407,17113,5083],{"class":2201},[17,17115,6478],{},[17,17117,17118],{},[24,17119,6483],{},[244,17121,17122,17134],{},[247,17123,17124],{},[250,17125,17126,17130],{},[253,17127,6492,17128,6495],{},[24,17129,5431],{},[253,17131,6498,17132,6495],{},[24,17133,6343],{},[260,17135,17136,17146,17156],{},[250,17137,17138,17142],{},[265,17139,6507,17140,6511],{},[24,17141,6510],{},[265,17143,6514,17144,6518],{},[24,17145,6517],{},[250,17147,17148,17152],{},[265,17149,6523,17150],{},[24,17151,6526],{},[265,17153,6529,17154],{},[24,17155,6532],{},[250,17157,17158,17162],{},[265,17159,6537,17160,6541],{},[24,17161,6540],{},[265,17163,6544,17164,6547],{},[24,17165,6540],{},[35,17167],{},[38,17169,6553],{"id":6552},[17,17171,2502,17172,6559],{},[24,17173,6558],{},[346,17175,17176],{"className":3850,"code":6562,"language":3852,"meta":355,"style":355},[353,17177,17178,17186,17192,17200,17212,17216,17224,17228,17236,17246,17250,17254,17258],{"__ignoreMap":355},[407,17179,17180,17182,17184],{"class":409,"line":410},[407,17181,5428],{"class":2201},[407,17183,6558],{"class":420},[407,17185,5434],{"class":2201},[407,17187,17188,17190],{"class":409,"line":417},[407,17189,6577],{"class":424},[407,17191,3384],{"class":2201},[407,17193,17194,17196,17198],{"class":409,"line":441},[407,17195,6584],{"class":2201},[407,17197,5476],{"class":420},[407,17199,6589],{"class":2201},[407,17201,17202,17204,17206,17208,17210],{"class":409,"line":448},[407,17203,6594],{"class":2201},[407,17205,6597],{"class":3876},[407,17207,5571],{"class":2201},[407,17209,5574],{"class":3864},[407,17211,6604],{"class":2201},[407,17213,17214],{"class":409,"line":454},[407,17215,6609],{"class":2201},[407,17217,17218,17220,17222],{"class":409,"line":1667},[407,17219,6614],{"class":2201},[407,17221,6617],{"class":424},[407,17223,3384],{"class":2201},[407,17225,17226],{"class":409,"line":1673},[407,17227,6624],{"class":2201},[407,17229,17230,17232,17234],{"class":409,"line":1679},[407,17231,5717],{"class":2201},[407,17233,5720],{"class":424},[407,17235,3384],{"class":2201},[407,17237,17238,17240,17242,17244],{"class":409,"line":1685},[407,17239,5728],{"class":2201},[407,17241,6639],{"class":424},[407,17243,6597],{"class":2201},[407,17245,6644],{"class":424},[407,17247,17248],{"class":409,"line":1690},[407,17249,3454],{"class":2201},[407,17251,17252],{"class":409,"line":1696},[407,17253,6653],{"class":2201},[407,17255,17256],{"class":409,"line":1702},[407,17257,6658],{"class":2201},[407,17259,17260],{"class":409,"line":1708},[407,17261,5083],{"class":2201},[17,17263,6665],{},[35,17265],{},[38,17267,6671],{"id":6670},[17,17269,6674,17270,6678],{},[24,17271,6677],{},[346,17273,17274],{"className":401,"code":6681,"language":403,"meta":355,"style":355},[353,17275,17276],{"__ignoreMap":355},[407,17277,17278,17280,17282,17284,17286,17288,17290],{"class":409,"line":410},[407,17279,5858],{"class":420},[407,17281,6690],{"class":424},[407,17283,6693],{"class":2201},[407,17285,5858],{"class":420},[407,17287,6698],{"class":424},[407,17289,6701],{"class":424},[407,17291,6704],{"class":424},[17,17293,6707,17294,6711],{},[353,17295,6710],{},[82,17297,17298,17302,17306,17310],{},[85,17299,6716,17300,6719],{},[24,17301,6330],{},[85,17303,6722,17304,6726],{},[24,17305,6725],{},[85,17307,6729,17308,6733],{},[24,17309,6732],{},[85,17311,6736,17312,6740],{},[24,17313,6739],{},[17,17315,6743],{},[1524,17317,17318],{},[17,17319,17320,6751,17322,6755],{},[24,17321,6750],{},[353,17323,6754],{},[35,17325],{},[38,17327,6761],{"id":6760},[17,17329,6764],{},[58,17331,6768],{"id":6767},[17,17333,6771],{},[82,17335,17336,17342],{},[85,17337,17338,2225,17340],{},[24,17339,6778],{},[353,17341,6781],{},[85,17343,17344,2225,17346],{},[24,17345,6786],{},[353,17347,6789],{},[346,17349,17350],{"className":2192,"code":6792,"language":2194,"meta":355,"style":355},[353,17351,17352,17356,17362,17368,17378,17388,17392,17396],{"__ignoreMap":355},[407,17353,17354],{"class":409,"line":410},[407,17355,2202],{"class":2201},[407,17357,17358,17360],{"class":409,"line":417},[407,17359,3363],{"class":434},[407,17361,2210],{"class":2201},[407,17363,17364,17366],{"class":409,"line":441},[407,17365,6809],{"class":434},[407,17367,2210],{"class":2201},[407,17369,17370,17372,17374,17376],{"class":409,"line":448},[407,17371,2222],{"class":434},[407,17373,2225],{"class":2201},[407,17375,6820],{"class":424},[407,17377,3384],{"class":2201},[407,17379,17380,17382,17384,17386],{"class":409,"line":454},[407,17381,3389],{"class":434},[407,17383,3392],{"class":2201},[407,17385,6831],{"class":424},[407,17387,3398],{"class":2201},[407,17389,17390],{"class":409,"line":1667},[407,17391,2233],{"class":2201},[407,17393,17394],{"class":409,"line":1673},[407,17395,2238],{"class":2201},[407,17397,17398],{"class":409,"line":1679},[407,17399,2243],{"class":2201},[17,17401,6848,17402,688],{},[353,17403,6851],{},[1524,17405,17406],{},[17,17407,17408,6859,17410,6863],{},[24,17409,6858],{},[353,17411,6862],{},[58,17413,1287],{"id":6866},[346,17415,17416],{"className":401,"code":6869,"language":403,"meta":355,"style":355},[353,17417,17418,17422,17436,17440,17444,17462,17466,17470],{"__ignoreMap":355},[407,17419,17420],{"class":409,"line":410},[407,17421,6876],{"class":413},[407,17423,17424,17426,17428,17430,17432,17434],{"class":409,"line":417},[407,17425,6881],{"class":420},[407,17427,6884],{"class":424},[407,17429,428],{"class":424},[407,17431,6889],{"class":424},[407,17433,6701],{"class":424},[407,17435,6894],{"class":424},[407,17437,17438],{"class":409,"line":441},[407,17439,445],{"emptyLinePlaceholder":444},[407,17441,17442],{"class":409,"line":448},[407,17443,6903],{"class":413},[407,17445,17446,17448,17450,17452,17454,17456,17458,17460],{"class":409,"line":454},[407,17447,6881],{"class":420},[407,17449,6884],{"class":424},[407,17451,428],{"class":424},[407,17453,6889],{"class":424},[407,17455,6916],{"class":434},[407,17457,6919],{"class":424},[407,17459,6701],{"class":424},[407,17461,6894],{"class":424},[407,17463,17464],{"class":409,"line":1667},[407,17465,445],{"emptyLinePlaceholder":444},[407,17467,17468],{"class":409,"line":1673},[407,17469,6932],{"class":413},[407,17471,17472,17474,17476],{"class":409,"line":1679},[407,17473,6881],{"class":420},[407,17475,6884],{"class":424},[407,17477,6941],{"class":424},[17,17479,6944,17480,6948],{},[353,17481,6947],{},[58,17483,6952],{"id":6951},[17,17485,6955,17486,6959],{},[353,17487,6958],{},[346,17489,17490],{"className":2192,"code":6962,"language":2194,"meta":355,"style":355},[353,17491,17492,17496,17502,17508,17518,17528,17532,17536],{"__ignoreMap":355},[407,17493,17494],{"class":409,"line":410},[407,17495,2202],{"class":2201},[407,17497,17498,17500],{"class":409,"line":417},[407,17499,3363],{"class":434},[407,17501,2210],{"class":2201},[407,17503,17504,17506],{"class":409,"line":441},[407,17505,6809],{"class":434},[407,17507,2210],{"class":2201},[407,17509,17510,17512,17514,17516],{"class":409,"line":448},[407,17511,2222],{"class":434},[407,17513,2225],{"class":2201},[407,17515,6820],{"class":424},[407,17517,3384],{"class":2201},[407,17519,17520,17522,17524,17526],{"class":409,"line":454},[407,17521,3389],{"class":434},[407,17523,3392],{"class":2201},[407,17525,6999],{"class":424},[407,17527,3398],{"class":2201},[407,17529,17530],{"class":409,"line":1667},[407,17531,2233],{"class":2201},[407,17533,17534],{"class":409,"line":1673},[407,17535,2238],{"class":2201},[407,17537,17538],{"class":409,"line":1679},[407,17539,2243],{"class":2201},[58,17541,2294],{"id":7016},[17,17543,6955,17544,7022,17546,7026],{},[353,17545,7021],{},[353,17547,7025],{},[346,17549,17550],{"className":2192,"code":7029,"language":2194,"meta":355,"style":355},[353,17551,17552,17556,17562,17568,17578,17588,17594,17598,17602],{"__ignoreMap":355},[407,17553,17554],{"class":409,"line":410},[407,17555,2202],{"class":2201},[407,17557,17558,17560],{"class":409,"line":417},[407,17559,3363],{"class":434},[407,17561,2210],{"class":2201},[407,17563,17564,17566],{"class":409,"line":441},[407,17565,6809],{"class":434},[407,17567,2210],{"class":2201},[407,17569,17570,17572,17574,17576],{"class":409,"line":448},[407,17571,2222],{"class":434},[407,17573,2225],{"class":2201},[407,17575,6820],{"class":424},[407,17577,3384],{"class":2201},[407,17579,17580,17582,17584,17586],{"class":409,"line":454},[407,17581,3389],{"class":434},[407,17583,3392],{"class":2201},[407,17585,6831],{"class":424},[407,17587,3432],{"class":2201},[407,17589,17590,17592],{"class":409,"line":1667},[407,17591,3437],{"class":434},[407,17593,7074],{"class":2201},[407,17595,17596],{"class":409,"line":1673},[407,17597,2233],{"class":2201},[407,17599,17600],{"class":409,"line":1679},[407,17601,2238],{"class":2201},[407,17603,17604],{"class":409,"line":1685},[407,17605,2243],{"class":2201},[35,17607],{},[38,17609,7092],{"id":7091},[17,17611,7095,17612,7099],{},[24,17613,7098],{},[346,17615,17616],{"className":401,"code":7102,"language":403,"meta":355,"style":355},[353,17617,17618,17626,17632],{"__ignoreMap":355},[407,17619,17620,17622,17624],{"class":409,"line":410},[407,17621,7109],{"class":420},[407,17623,4733],{"class":424},[407,17625,7114],{"class":424},[407,17627,17628,17630],{"class":409,"line":417},[407,17629,4723],{"class":434},[407,17631,7114],{"class":424},[407,17633,17634,17636,17638],{"class":409,"line":441},[407,17635,7109],{"class":420},[407,17637,428],{"class":424},[407,17639,7129],{"class":424},[346,17641,17642],{"className":7132,"code":7133,"language":7134,"meta":355,"style":355},[353,17643,17644,17648,17652,17656,17660,17664,17668,17672,17676,17680,17684,17688,17692,17696,17700,17704,17708,17712,17716,17720,17724,17728,17732,17736,17740,17744,17748,17752,17756,17760,17764,17768,17772,17776,17780,17784,17788,17792,17796,17800,17804,17808,17812,17816,17820,17824,17828,17832,17836,17840],{"__ignoreMap":355},[407,17645,17646],{"class":409,"line":410},[407,17647,7141],{},[407,17649,17650],{"class":409,"line":417},[407,17651,7146],{},[407,17653,17654],{"class":409,"line":441},[407,17655,7151],{},[407,17657,17658],{"class":409,"line":448},[407,17659,445],{"emptyLinePlaceholder":444},[407,17661,17662],{"class":409,"line":454},[407,17663,7160],{},[407,17665,17666],{"class":409,"line":1667},[407,17667,7165],{},[407,17669,17670],{"class":409,"line":1673},[407,17671,445],{"emptyLinePlaceholder":444},[407,17673,17674],{"class":409,"line":1679},[407,17675,7174],{},[407,17677,17678],{"class":409,"line":1685},[407,17679,7179],{},[407,17681,17682],{"class":409,"line":1690},[407,17683,445],{"emptyLinePlaceholder":444},[407,17685,17686],{"class":409,"line":1696},[407,17687,7188],{},[407,17689,17690],{"class":409,"line":1702},[407,17691,7193],{},[407,17693,17694],{"class":409,"line":1708},[407,17695,445],{"emptyLinePlaceholder":444},[407,17697,17698],{"class":409,"line":1714},[407,17699,7202],{},[407,17701,17702],{"class":409,"line":1719},[407,17703,7207],{},[407,17705,17706],{"class":409,"line":1725},[407,17707,7212],{},[407,17709,17710],{"class":409,"line":1278},[407,17711,7217],{},[407,17713,17714],{"class":409,"line":1736},[407,17715,7222],{},[407,17717,17718],{"class":409,"line":1742},[407,17719,7227],{},[407,17721,17722],{"class":409,"line":1748},[407,17723,7232],{},[407,17725,17726],{"class":409,"line":1753},[407,17727,445],{"emptyLinePlaceholder":444},[407,17729,17730],{"class":409,"line":1759},[407,17731,7202],{},[407,17733,17734],{"class":409,"line":1765},[407,17735,7245],{},[407,17737,17738],{"class":409,"line":1771},[407,17739,7250],{},[407,17741,17742],{"class":409,"line":1777},[407,17743,7217],{},[407,17745,17746],{"class":409,"line":1782},[407,17747,7259],{},[407,17749,17750],{"class":409,"line":1788},[407,17751,7264],{},[407,17753,17754],{"class":409,"line":1794},[407,17755,7269],{},[407,17757,17758],{"class":409,"line":5348},[407,17759,7274],{},[407,17761,17762],{"class":409,"line":5353},[407,17763,7279],{},[407,17765,17766],{"class":409,"line":5358},[407,17767,7284],{},[407,17769,17770],{"class":409,"line":5364},[407,17771,7289],{},[407,17773,17774],{"class":409,"line":5369},[407,17775,7294],{},[407,17777,17778],{"class":409,"line":5388},[407,17779,7299],{},[407,17781,17782],{"class":409,"line":5399},[407,17783,7304],{},[407,17785,17786],{"class":409,"line":5408},[407,17787,7309],{},[407,17789,17790],{"class":409,"line":5414},[407,17791,7314],{},[407,17793,17794],{"class":409,"line":5419},[407,17795,445],{"emptyLinePlaceholder":444},[407,17797,17798],{"class":409,"line":5425},[407,17799,7323],{},[407,17801,17802],{"class":409,"line":5437},[407,17803,7328],{},[407,17805,17806],{"class":409,"line":5449},[407,17807,7333],{},[407,17809,17810],{"class":409,"line":5461},[407,17811,7338],{},[407,17813,17814],{"class":409,"line":5470},[407,17815,445],{"emptyLinePlaceholder":444},[407,17817,17818],{"class":409,"line":5493},[407,17819,7347],{},[407,17821,17822],{"class":409,"line":5512},[407,17823,7352],{},[407,17825,17826],{"class":409,"line":5544},[407,17827,7357],{},[407,17829,17830],{"class":409,"line":5549},[407,17831,7362],{},[407,17833,17834],{"class":409,"line":5583},[407,17835,445],{"emptyLinePlaceholder":444},[407,17837,17838],{"class":409,"line":5600},[407,17839,7371],{},[407,17841,17842],{"class":409,"line":5616},[407,17843,7376],{},[17,17845,7379,17846,7383,17848,7387,17850,7391],{},[24,17847,7382],{},[24,17849,7386],{},[24,17851,7390],{},[17,17853,7394],{},[346,17855,17856],{"className":401,"code":7397,"language":403,"meta":355,"style":355},[353,17857,17858,17862,17870,17874,17878],{"__ignoreMap":355},[407,17859,17860],{"class":409,"line":410},[407,17861,7404],{"class":413},[407,17863,17864,17866,17868],{"class":409,"line":417},[407,17865,7409],{"class":420},[407,17867,7412],{"class":424},[407,17869,7415],{"class":424},[407,17871,17872],{"class":409,"line":441},[407,17873,445],{"emptyLinePlaceholder":444},[407,17875,17876],{"class":409,"line":448},[407,17877,7424],{"class":413},[407,17879,17880,17882,17884],{"class":409,"line":454},[407,17881,7409],{"class":420},[407,17883,4743],{"class":424},[407,17885,7415],{"class":424},[35,17887],{},[38,17889,7438],{"id":7437},[58,17891,7442,17892,7446],{"id":7441},[353,17893,7445],{},[17,17895,7449,17896,7453,17898,7457],{},[24,17897,7452],{},[353,17899,7456],{},[17,17901,17902,7463,17904,7467,17906,7471,17908,688],{},[24,17903,7462],{},[353,17905,7466],{},[353,17907,7470],{},[353,17909,7474],{},[17,17911,7477],{},[58,17913,7481],{"id":7480},[17,17915,7484,17916,7488,17918,7492,17920,7496],{},[353,17917,7487],{},[24,17919,7491],{},[24,17921,7495],{},[17,17923,7499],{},[58,17925,7503],{"id":7502},[17,17927,7506,17928,7510],{},[24,17929,7509],{},[17,17931,7513,17932,7517],{},[353,17933,7516],{},[17,17935,7520,17936,7524],{},[353,17937,7523],{},[58,17939,7528],{"id":7527},[17,17941,7531,17942,7535],{},[24,17943,7534],{},[17,17945,7538,17946,7541,17948,7545,17950,7549],{},[24,17947,2137],{},[353,17949,7544],{},[353,17951,7548],{},[58,17953,7553],{"id":7552},[17,17955,7556,17956,7560],{},[24,17957,7559],{},[17,17959,7563,17960,7567],{},[24,17961,7566],{},[35,17963],{},[38,17965,7573],{"id":7572},[17,17967,7576,17968,7579],{},[24,17969,7452],{},[17,17971,7582,17972,1894],{},[24,17973,7495],{},[346,17975,17976],{"className":3850,"code":7587,"language":3852,"meta":355,"style":355},[353,17977,17978,17986,17992,18004,18008,18020,18032,18036,18064,18078,18092,18096,18106,18116,18120,18124,18140,18152],{"__ignoreMap":355},[407,17979,17980,17982,17984],{"class":409,"line":410},[407,17981,4974],{"class":3864},[407,17983,7596],{"class":2201},[407,17985,7599],{"class":3864},[407,17987,17988,17990],{"class":409,"line":417},[407,17989,7604],{"class":424},[407,17991,4986],{"class":2201},[407,17993,17994,17996,17998,18000,18002],{"class":409,"line":441},[407,17995,4974],{"class":3864},[407,17997,7613],{"class":2201},[407,17999,4980],{"class":3864},[407,18001,7618],{"class":424},[407,18003,4986],{"class":2201},[407,18005,18006],{"class":409,"line":448},[407,18007,445],{"emptyLinePlaceholder":444},[407,18009,18010,18012,18014,18016,18018],{"class":409,"line":454},[407,18011,5056],{"class":3864},[407,18013,7631],{"class":434},[407,18015,5062],{"class":3864},[407,18017,7636],{"class":420},[407,18019,5597],{"class":2201},[407,18021,18022,18024,18026,18028,18030],{"class":409,"line":1667},[407,18023,7643],{"class":2201},[407,18025,7646],{"class":420},[407,18027,7649],{"class":2201},[407,18029,2194],{"class":420},[407,18031,7654],{"class":2201},[407,18033,18034],{"class":409,"line":1673},[407,18035,445],{"emptyLinePlaceholder":444},[407,18037,18038,18040,18042,18044,18046,18048,18050,18052,18054,18056,18058,18060,18062],{"class":409,"line":1679},[407,18039,7643],{"class":2201},[407,18041,7665],{"class":420},[407,18043,5216],{"class":2201},[407,18045,7670],{"class":424},[407,18047,2078],{"class":2201},[407,18049,5164],{"class":3864},[407,18051,1486],{"class":2201},[407,18053,7679],{"class":3876},[407,18055,2078],{"class":2201},[407,18057,7684],{"class":3876},[407,18059,6395],{"class":2201},[407,18061,5574],{"class":3864},[407,18063,3871],{"class":2201},[407,18065,18066,18068,18070,18072,18074,18076],{"class":409,"line":1685},[407,18067,7695],{"class":3864},[407,18069,5787],{"class":434},[407,18071,5062],{"class":3864},[407,18073,5379],{"class":3864},[407,18075,7704],{"class":420},[407,18077,5385],{"class":2201},[407,18079,18080,18082,18084,18086,18088,18090],{"class":409,"line":1690},[407,18081,7711],{"class":420},[407,18083,7714],{"class":2201},[407,18085,5574],{"class":3864},[407,18087,7719],{"class":2201},[407,18089,5622],{"class":420},[407,18091,5669],{"class":2201},[407,18093,18094],{"class":409,"line":1696},[407,18095,7728],{"class":2201},[407,18097,18098,18100,18102,18104],{"class":409,"line":1702},[407,18099,5312],{"class":3864},[407,18101,5805],{"class":2201},[407,18103,5808],{"class":420},[407,18105,5811],{"class":2201},[407,18107,18108,18110,18112,18114],{"class":409,"line":1708},[407,18109,5312],{"class":3864},[407,18111,7745],{"class":2201},[407,18113,7748],{"class":420},[407,18115,7751],{"class":2201},[407,18117,18118],{"class":409,"line":1714},[407,18119,5411],{"class":2201},[407,18121,18122],{"class":409,"line":1719},[407,18123,445],{"emptyLinePlaceholder":444},[407,18125,18126,18128,18130,18132,18134,18136,18138],{"class":409,"line":1725},[407,18127,7643],{"class":2201},[407,18129,7766],{"class":420},[407,18131,5216],{"class":2201},[407,18133,7771],{"class":434},[407,18135,7774],{"class":2201},[407,18137,5574],{"class":3864},[407,18139,3871],{"class":2201},[407,18141,18142,18144,18146,18148,18150],{"class":409,"line":1278},[407,18143,7783],{"class":2201},[407,18145,7786],{"class":420},[407,18147,5216],{"class":2201},[407,18149,7791],{"class":424},[407,18151,5083],{"class":2201},[407,18153,18154],{"class":409,"line":1736},[407,18155,5411],{"class":2201},[17,18157,7800,18158,7803,18160,7806],{},[353,18159,7466],{},[353,18161,7445],{},[244,18163,18164,18172],{},[247,18165,18166],{},[250,18167,18168,18170],{},[253,18169,7815],{},[253,18171,7818],{},[260,18173,18174,18182],{},[250,18175,18176,18180],{},[265,18177,18178],{},[24,18179,7452],{},[265,18181,7829],{},[250,18183,18184,18188],{},[265,18185,18186],{},[24,18187,7495],{},[265,18189,7838],{},[35,18191],{},[38,18193,7844],{"id":7843},[17,18195,7847],{},[17,18197,18198],{},[24,18199,7852],{},[82,18201,18202,18208,18210],{},[85,18203,7857,18204,4055,18206],{},[353,18205,7860],{},[353,18207,7863],{},[85,18209,7866],{},[85,18211,7869,18212,6250],{},[353,18213,7872],{},[17,18215,18216],{},[24,18217,7877],{},[82,18219,18220,18225,18230],{},[85,18221,18222,7887],{},[69,18223,7886],{"href":7884,"rel":18224},[1152],[85,18226,18227,7895],{},[69,18228,7894],{"href":7892,"rel":18229},[1152],[85,18231,18232,7903],{},[69,18233,7902],{"href":7900,"rel":18234},[1152],[17,18236,18237],{},[24,18238,7908],{},[82,18240,18241,18246,18251],{},[85,18242,18243,7918],{},[69,18244,7917],{"href":7915,"rel":18245},[1152],[85,18247,18248,7926],{},[69,18249,7925],{"href":7923,"rel":18250},[1152],[85,18252,18253,4055,18256,7939],{},[69,18254,7933],{"href":7931,"rel":18255},[1152],[69,18257,7938],{"href":7936,"rel":18258},[1152],[17,18260,7942,18261,7946],{},[24,18262,7945],{},[17,18264,7949,18265],{},[2128,18266,7952],{},[17,18268,7955],{},[35,18270],{},[17,18272,18273,1894],{},[24,18274,2664],{},[82,18276,18277,18282,18289,18296,18301,18306,18311,18316,18321],{},[85,18278,18279,7971],{},[69,18280,7970],{"href":7968,"rel":18281},[1152],[85,18283,18284,7977,18287],{},[69,18285,7933],{"href":7931,"rel":18286},[1152],[353,18288,4705],{},[85,18290,18291,7985,18294],{},[69,18292,7938],{"href":7936,"rel":18293},[1152],[353,18295,7409],{},[85,18297,18298,7995],{},[69,18299,7994],{"href":7992,"rel":18300},[1152],[85,18302,18303,8002],{},[69,18304,8001],{"href":7884,"rel":18305},[1152],[85,18307,18308,8008],{},[69,18309,7894],{"href":7892,"rel":18310},[1152],[85,18312,18313,8016],{},[69,18314,8015],{"href":8013,"rel":18315},[1152],[85,18317,18318,8024],{},[69,18319,8023],{"href":8021,"rel":18320},[1152],[85,18322,18323,8030],{},[69,18324,8029],{"href":4545},[1218,18326,8033],{},{"title":355,"searchDepth":417,"depth":417,"links":18328},[18329,18330,18331,18332,18333,18334,18335,18336,18342,18343,18350,18351],{"id":4569,"depth":417,"text":4570},{"id":4698,"depth":417,"text":4699},{"id":4957,"depth":417,"text":4958},{"id":5866,"depth":417,"text":5867},{"id":6336,"depth":417,"text":6337},{"id":6552,"depth":417,"text":6553},{"id":6670,"depth":417,"text":6671},{"id":6760,"depth":417,"text":6761,"children":18337},[18338,18339,18340,18341],{"id":6767,"depth":441,"text":6768},{"id":6866,"depth":441,"text":1287},{"id":6951,"depth":441,"text":6952},{"id":7016,"depth":441,"text":2294},{"id":7091,"depth":417,"text":7092},{"id":7437,"depth":417,"text":7438,"children":18344},[18345,18346,18347,18348,18349],{"id":7441,"depth":441,"text":8053},{"id":7480,"depth":441,"text":7481},{"id":7502,"depth":441,"text":7503},{"id":7527,"depth":441,"text":7528},{"id":7552,"depth":441,"text":7553},{"id":7572,"depth":417,"text":7573},{"id":7843,"depth":417,"text":7844},{},{"title":4533,"description":8061},[4528,8069,8070,8071,8060,1287],{"id":4,"title":5,"author":18356,"body":18357,"category":1268,"contentType":1269,"description":1270,"difficulty":1271,"extension":1272,"featured":1273,"icon":1269,"image":1274,"meta":19205,"navigation":444,"path":1276,"publishedAt":1277,"readingTime":1278,"seo":19206,"stem":1280,"steps":1269,"tags":19207,"youtubeId":1269,"__hash__":1288},{"name":7,"initials":8},{"type":10,"value":18358,"toc":19158},[18359,18361,18363,18367,18369,18371,18373,18375,18377,18381,18383,18385,18387,18389,18395,18397,18411,18413,18415,18417,18419,18421,18423,18425,18429,18431,18433,18435,18439,18441,18463,18465,18467,18469,18471,18473,18475,18479,18481,18483,18485,18489,18491,18495,18497,18499,18535,18537,18539,18541,18545,18547,18551,18555,18557,18559,18563,18565,18570,18572,18574,18578,18580,18582,18586,18588,18590,18592,18594,18596,18630,18632,18634,18636,18641,18643,18645,18647,18649,18663,18665,18667,18669,18683,18685,18689,18691,18693,18695,18697,18699,18701,18703,18713,18715,18717,18725,18727,18729,18731,18733,18735,18737,18739,18741,18755,18757,18759,18763,18767,18771,18773,18779,18781,18825,18827,18829,18831,18833,18837,18839,18841,18843,18845,18847,18849,18863,18865,18867,18869,18871,18873,18877,18879,18881,18883,18885,18887,18901,18905,18907,18909,18911,18913,18923,18925,18927,18931,18935,18937,18939,18941,18943,18976,18978,19002,19004,19028,19030,19054,19056,19080,19082,19084,19086,19088,19090,19092,19094,19096,19098,19100,19104,19156],[13,18360,5],{"id":15},[17,18362,19],{},[17,18364,22,18365,27],{},[24,18366,26],{},[17,18368,30],{},[17,18370,33],{},[35,18372],{},[38,18374,41],{"id":40},[17,18376,44],{},[17,18378,47,18379],{},[24,18380,50],{},[17,18382,53],{},[17,18384,56],{},[58,18386,61],{"id":60},[17,18388,64],{},[17,18390,67,18391,73,18393,77],{},[69,18392,72],{"href":71},[24,18394,76],{},[17,18396,80],{},[82,18398,18399,18403,18407],{},[85,18400,18401,90],{},[24,18402,89],{},[85,18404,18405,96],{},[24,18406,95],{},[85,18408,18409,102],{},[24,18410,101],{},[17,18412,105],{},[17,18414,108],{},[35,18416],{},[38,18418,114],{"id":113},[17,18420,117],{},[58,18422,121],{"id":120},[17,18424,124],{},[17,18426,127,18427,132],{},[69,18428,131],{"href":130},[17,18430,135],{},[17,18432,138],{},[58,18434,142],{"id":141},[17,18436,145,18437,149],{},[24,18438,148],{},[17,18440,152],{},[82,18442,18443,18447,18451,18455,18459],{},[85,18444,18445,160],{},[24,18446,159],{},[85,18448,18449,166],{},[24,18450,165],{},[85,18452,18453,172],{},[24,18454,171],{},[85,18456,18457,178],{},[24,18458,177],{},[85,18460,18461,184],{},[24,18462,183],{},[17,18464,187],{},[17,18466,190],{},[58,18468,194],{"id":193},[17,18470,197],{},[17,18472,200],{},[17,18474,203],{},[17,18476,18477],{},[207,18478],{"alt":209,"src":210},[35,18480],{},[38,18482,216],{"id":215},[17,18484,219],{},[17,18486,222,18487,226],{},[24,18488,225],{},[17,18490,229],{},[17,18492,232,18493,236],{},[24,18494,235],{},[17,18496,239],{},[17,18498,242],{},[244,18500,18501,18509],{},[247,18502,18503],{},[250,18504,18505,18507],{},[253,18506,255],{},[253,18508,258],{},[260,18510,18511,18519,18527],{},[250,18512,18513,18517],{},[265,18514,18515],{},[24,18516,269],{},[265,18518,272],{},[250,18520,18521,18525],{},[265,18522,18523],{},[24,18524,279],{},[265,18526,282],{},[250,18528,18529,18533],{},[265,18530,18531],{},[24,18532,289],{},[265,18534,292],{},[17,18536,295],{},[35,18538],{},[38,18540,301],{"id":300},[17,18542,304,18543,308],{},[69,18544,307],{"href":130},[58,18546,312],{"id":311},[17,18548,315,18549,319],{},[24,18550,318],{},[17,18552,322,18553,326],{},[24,18554,325],{},[58,18556,330],{"id":329},[17,18558,333],{},[17,18560,336,18561,341],{},[69,18562,340],{"href":339},[17,18564,344],{},[346,18566,18568],{"className":18567,"code":350,"language":351},[349],[353,18569,350],{"__ignoreMap":355},[17,18571,358],{},[58,18573,362],{"id":361},[17,18575,365,18576,369],{},[24,18577,368],{},[17,18579,372],{},[17,18581,375],{},[17,18583,378,18584,382],{},[24,18585,381],{},[35,18587],{},[38,18589,388],{"id":387},[17,18591,391],{},[58,18593,395],{"id":394},[17,18595,398],{},[346,18597,18598],{"className":401,"code":402,"language":403,"meta":355,"style":355},[353,18599,18600,18604,18618,18622,18626],{"__ignoreMap":355},[407,18601,18602],{"class":409,"line":410},[407,18603,414],{"class":413},[407,18605,18606,18608,18610,18612,18614,18616],{"class":409,"line":417},[407,18607,421],{"class":420},[407,18609,425],{"class":424},[407,18611,428],{"class":424},[407,18613,431],{"class":424},[407,18615,435],{"class":434},[407,18617,438],{"class":424},[407,18619,18620],{"class":409,"line":441},[407,18621,445],{"emptyLinePlaceholder":444},[407,18623,18624],{"class":409,"line":448},[407,18625,451],{"class":413},[407,18627,18628],{"class":409,"line":454},[407,18629,457],{"class":413},[17,18631,460],{},[58,18633,464],{"id":463},[17,18635,467],{},[346,18637,18639],{"className":18638,"code":471,"language":351},[349],[353,18640,471],{"__ignoreMap":355},[17,18642,476],{},[17,18644,479],{},[58,18646,483],{"id":482},[17,18648,486],{},[82,18650,18651,18655,18659],{},[85,18652,18653,494],{},[24,18654,493],{},[85,18656,18657,499],{},[24,18658,183],{},[85,18660,18661,505],{},[24,18662,504],{},[17,18664,508],{},[58,18666,512],{"id":511},[17,18668,515],{},[517,18670,18671,18679],{},[85,18672,18673,524,18675,528,18677],{},[24,18674,523],{},[353,18676,527],{},[353,18678,531],{},[85,18680,18681,537],{},[24,18682,536],{},[17,18684,540],{},[17,18686,543,18687,548],{},[69,18688,547],{"href":546},[35,18690],{},[38,18692,554],{"id":553},[17,18694,557],{},[58,18696,561],{"id":560},[17,18698,564],{},[58,18700,568],{"id":567},[17,18702,571],{},[82,18704,18705,18709],{},[85,18706,18707,579],{},[24,18708,578],{},[85,18710,18711,585],{},[24,18712,584],{},[58,18714,589],{"id":588},[17,18716,592],{},[82,18718,18719,18721,18723],{},[85,18720,597],{},[85,18722,600],{},[85,18724,603],{},[17,18726,606],{},[17,18728,609],{},[58,18730,613],{"id":612},[17,18732,616],{},[17,18734,619],{},[35,18736],{},[38,18738,625],{"id":624},[17,18740,628],{},[517,18742,18743,18747,18751],{},[85,18744,18745,636],{},[24,18746,635],{},[85,18748,18749,642],{},[24,18750,641],{},[85,18752,18753,648],{},[24,18754,647],{},[17,18756,651],{},[58,18758,655],{"id":654},[17,18760,18761,661],{},[24,18762,660],{},[17,18764,18765,667],{},[24,18766,666],{},[17,18768,18769,673],{},[24,18770,672],{},[58,18772,677],{"id":676},[17,18774,680,18775,684,18777,688],{},[24,18776,683],{},[24,18778,687],{},[17,18780,344],{},[244,18782,18783,18791],{},[247,18784,18785],{},[250,18786,18787,18789],{},[253,18788,699],{},[253,18790,702],{},[260,18792,18793,18801,18809,18817],{},[250,18794,18795,18799],{},[265,18796,18797],{},[24,18798,711],{},[265,18800,714],{},[250,18802,18803,18807],{},[265,18804,18805],{},[24,18806,721],{},[265,18808,724],{},[250,18810,18811,18815],{},[265,18812,18813],{},[24,18814,731],{},[265,18816,734],{},[250,18818,18819,18823],{},[265,18820,18821],{},[24,18822,741],{},[265,18824,744],{},[17,18826,747],{},[35,18828],{},[38,18830,753],{"id":752},[17,18832,756],{},[17,18834,759,18835,763],{},[24,18836,762],{},[58,18838,767],{"id":766},[17,18840,770],{},[58,18842,774],{"id":773},[17,18844,777],{},[58,18846,781],{"id":780},[17,18848,784],{},[82,18850,18851,18855,18859],{},[85,18852,18853,792],{},[24,18854,791],{},[85,18856,18857,798],{},[24,18858,797],{},[85,18860,18861,803],{},[24,18862,613],{},[17,18864,806],{},[17,18866,809],{},[17,18868,812],{},[35,18870],{},[38,18872,818],{"id":817},[17,18874,821,18875,825],{},[24,18876,824],{},[17,18878,828],{},[17,18880,831],{},[17,18882,834],{},[17,18884,837],{},[17,18886,840],{},[82,18888,18889,18891,18893,18895,18897,18899],{},[85,18890,845],{},[85,18892,848],{},[85,18894,851],{},[85,18896,854],{},[85,18898,857],{},[85,18900,860],{},[17,18902,863,18903,868],{},[69,18904,867],{"href":866},[35,18906],{},[38,18908,874],{"id":873},[17,18910,877],{},[17,18912,880],{},[82,18914,18915,18919],{},[85,18916,18917,888],{},[24,18918,887],{},[85,18920,18921,894],{},[24,18922,893],{},[17,18924,897],{},[17,18926,900],{},[17,18928,903,18929,907],{},[24,18930,906],{},[17,18932,910,18933,914],{},[69,18934,913],{"href":130},[35,18936],{},[38,18938,920],{"id":919},[17,18940,923],{},[58,18942,927],{"id":926},[82,18944,18946,18953,18960,18967],{"className":18945},[931],[85,18947,18949,940,18951,944],{"className":18948},[935],[937,18950],{"disabled":444,"type":939},[24,18952,943],{},[85,18954,18956,940,18958,953],{"className":18955},[935],[937,18957],{"disabled":444,"type":939},[24,18959,952],{},[85,18961,18963,940,18965,962],{"className":18962},[935],[937,18964],{"disabled":444,"type":939},[24,18966,961],{},[85,18968,18970,940,18972,971,18974,974],{"className":18969},[935],[937,18971],{"disabled":444,"type":939},[24,18973,970],{},[353,18975,531],{},[58,18977,978],{"id":977},[82,18979,18981,18988,18995],{"className":18980},[931],[85,18982,18984,940,18986,990],{"className":18983},[935],[937,18985],{"disabled":444,"type":939},[24,18987,989],{},[85,18989,18991,940,18993,999],{"className":18990},[935],[937,18992],{"disabled":444,"type":939},[24,18994,998],{},[85,18996,18998,940,19000,1007],{"className":18997},[935],[937,18999],{"disabled":444,"type":939},[24,19001,741],{},[58,19003,1011],{"id":1010},[82,19005,19007,19014,19021],{"className":19006},[931],[85,19008,19010,940,19012,1023],{"className":19009},[935],[937,19011],{"disabled":444,"type":939},[24,19013,1022],{},[85,19015,19017,940,19019,1032],{"className":19016},[935],[937,19018],{"disabled":444,"type":939},[24,19020,1031],{},[85,19022,19024,940,19026,1041],{"className":19023},[935],[937,19025],{"disabled":444,"type":939},[24,19027,1040],{},[58,19029,1045],{"id":1044},[82,19031,19033,19040,19047],{"className":19032},[931],[85,19034,19036,940,19038,1057],{"className":19035},[935],[937,19037],{"disabled":444,"type":939},[24,19039,1056],{},[85,19041,19043,940,19045,1066],{"className":19042},[935],[937,19044],{"disabled":444,"type":939},[24,19046,1065],{},[85,19048,19050,940,19052,1075],{"className":19049},[935],[937,19051],{"disabled":444,"type":939},[24,19053,1074],{},[58,19055,1079],{"id":1078},[82,19057,19059,19066,19073],{"className":19058},[931],[85,19060,19062,940,19064,1091],{"className":19061},[935],[937,19063],{"disabled":444,"type":939},[24,19065,1090],{},[85,19067,19069,940,19071,1100],{"className":19068},[935],[937,19070],{"disabled":444,"type":939},[24,19072,1099],{},[85,19074,19076,940,19078,1109],{"className":19075},[935],[937,19077],{"disabled":444,"type":939},[24,19079,1108],{},[35,19081],{},[38,19083,1115],{"id":1114},[17,19085,1118],{},[17,19087,1121],{},[17,19089,1124],{},[17,19091,1127],{},[17,19093,1130],{},[17,19095,1133],{},[17,19097,1136],{},[35,19099],{},[17,19101,19102],{},[24,19103,1143],{},[517,19105,19106,19111,19116,19121,19126,19131,19136,19141,19146,19151],{},[85,19107,19108],{},[69,19109,1153],{"href":1150,"rel":19110},[1152],[85,19112,19113],{},[69,19114,1160],{"href":1158,"rel":19115},[1152],[85,19117,19118],{},[69,19119,1167],{"href":1165,"rel":19120},[1152],[85,19122,19123],{},[69,19124,1174],{"href":1172,"rel":19125},[1152],[85,19127,19128],{},[69,19129,1181],{"href":1179,"rel":19130},[1152],[85,19132,19133],{},[69,19134,1188],{"href":1186,"rel":19135},[1152],[85,19137,19138],{},[69,19139,1195],{"href":1193,"rel":19140},[1152],[85,19142,19143],{},[69,19144,1202],{"href":1200,"rel":19145},[1152],[85,19147,19148],{},[69,19149,1209],{"href":1207,"rel":19150},[1152],[85,19152,19153],{},[69,19154,1216],{"href":1214,"rel":19155},[1152],[1218,19157,1220],{},{"title":355,"searchDepth":417,"depth":417,"links":19159},[19160,19163,19168,19169,19174,19180,19186,19190,19195,19196,19197,19204],{"id":40,"depth":417,"text":41,"children":19161},[19162],{"id":60,"depth":441,"text":61},{"id":113,"depth":417,"text":114,"children":19164},[19165,19166,19167],{"id":120,"depth":441,"text":121},{"id":141,"depth":441,"text":142},{"id":193,"depth":441,"text":194},{"id":215,"depth":417,"text":216},{"id":300,"depth":417,"text":301,"children":19170},[19171,19172,19173],{"id":311,"depth":441,"text":312},{"id":329,"depth":441,"text":330},{"id":361,"depth":441,"text":362},{"id":387,"depth":417,"text":388,"children":19175},[19176,19177,19178,19179],{"id":394,"depth":441,"text":395},{"id":463,"depth":441,"text":464},{"id":482,"depth":441,"text":483},{"id":511,"depth":441,"text":512},{"id":553,"depth":417,"text":554,"children":19181},[19182,19183,19184,19185],{"id":560,"depth":441,"text":561},{"id":567,"depth":441,"text":568},{"id":588,"depth":441,"text":589},{"id":612,"depth":441,"text":613},{"id":624,"depth":417,"text":625,"children":19187},[19188,19189],{"id":654,"depth":441,"text":655},{"id":676,"depth":441,"text":677},{"id":752,"depth":417,"text":753,"children":19191},[19192,19193,19194],{"id":766,"depth":441,"text":767},{"id":773,"depth":441,"text":774},{"id":780,"depth":441,"text":781},{"id":817,"depth":417,"text":818},{"id":873,"depth":417,"text":874},{"id":919,"depth":417,"text":920,"children":19198},[19199,19200,19201,19202,19203],{"id":926,"depth":441,"text":927},{"id":977,"depth":441,"text":978},{"id":1010,"depth":441,"text":1011},{"id":1044,"depth":441,"text":1045},{"id":1078,"depth":441,"text":1079},{"id":1114,"depth":417,"text":1115},{},{"title":5,"description":1270},[1282,1283,1284,1285,1286,1287],{"id":19209,"title":19210,"author":19211,"body":19212,"category":8060,"contentType":1269,"description":20009,"difficulty":2768,"extension":1272,"featured":444,"icon":1269,"image":20010,"meta":20011,"navigation":444,"path":20012,"publishedAt":20013,"readingTime":1714,"seo":20014,"stem":20015,"steps":1269,"tags":20016,"youtubeId":1269,"__hash__":20019},"guides/guides/ricrea-tetris-20-minuti-claude-code.md","Ricrea Tetris in 20 Minuti con Claude Code",{"name":7,"initials":8},{"type":10,"value":19213,"toc":19974},[19214,19217,19224,19231,19242,19255,19261,19263,19267,19270,19314,19317,19319,19323,19326,19343,19346,19350,19356,19363,19365,19369,19375,19378,19382,19388,19395,19399,19405,19408,19410,19414,19420,19427,19441,19448,19452,19455,19461,19464,19468,19471,19477,19480,19482,19486,19489,19493,19496,19513,19528,19535,19598,19604,19611,19613,19617,19624,19631,19634,19636,19640,19647,19651,19654,19660,19671,19675,19709,19715,19719,19722,19728,19730,19734,19740,19743,19763,19770,19777,19779,19783,19786,19790,19793,19797,19800,19804,19807,19811,19814,19818,19821,19825,19828,19830,19834,19841,19850,19860,19866,19872,19874,19878,19907,19910,19912,19915,19964,19966,19971],[17,19215,19216],{},"\"Fammi un Tetris in JavaScript.\"",[17,19218,19219,19220,19223],{},"Cinque parole. Claude Code ti genera un file da 800 righe, tutto in un unico ",[353,19221,19222],{},"tetris.js",". Funziona? Sì. E per un Tetris, probabilmente basta.",[17,19225,19226,19227,19230],{},"Ecco il problema: ",[24,19228,19229],{},"il Tetris funziona comunque",". È un progetto abbastanza semplice che anche con il prompt più pigro del mondo ottieni qualcosa di giocabile. Ed è proprio per questo che è il progetto perfetto per costruire buone abitudini — perché la posta in gioco è bassa, ma il metodo che impari scala su tutto il resto.",[17,19232,19233,19234,19237,19238,19241],{},"Una nota onesta: un Tetris funzionante si può fare in ",[24,19235,19236],{},"3 minuti",". \"Fammi un Tetris\", invio, e Claude te lo genera. I 20 minuti del titolo sono una provocazione — è il tempo che ci vuole per farlo ",[24,19239,19240],{},"bene",". Per ottenere codice organizzato, effetti, musica, e soprattutto per costruire un metodo di lavoro che su un progetto vero ti ripagherà cento volte.",[17,19243,19244,19245,19248,19249,19254],{},"Questo tutorial è il dietro le quinte di come abbiamo costruito ",[24,19246,19247],{},"Blocchi che Cadono",", il gioco che puoi ",[69,19250,19253],{"href":19251,"target":19252},"/demos/tetris/index.html","_blank","provare qui",". Non per dimostrare che senza queste tecniche non si può fare — si può, in un decimo del tempo. Ma per mostrare un approccio che, quando il progetto diventa serio, fa la differenza tra codice che puoi evolvere e codice che devi buttare via.",[17,19256,19257],{},[207,19258],{"alt":19259,"src":19260},"Splash screen di Blocchi che Cadono","/images/body/tetris1.webp",[35,19262],{},[38,19264,19266],{"id":19265},"il-risultato-finale","Il Risultato Finale",[17,19268,19269],{},"Prima di smontare il processo, ecco cosa abbiamo ottenuto:",[82,19271,19272,19278,19284,19290,19296,19302,19308],{},[85,19273,19274,19277],{},[24,19275,19276],{},"Codice organizzato"," in file separati per responsabilità — niente monolite da 800 righe",[85,19279,19280,19283],{},[24,19281,19282],{},"10 livelli"," con velocità crescente",[85,19285,19286,19289],{},[24,19287,19288],{},"Effetti visivi",": particelle esplosive, flash sulle righe, popup punteggio, ghost piece",[85,19291,19292,19295],{},[24,19293,19294],{},"Stile arcade anni '90",": font Press Start 2P, bordi neon, glow su tutto",[85,19297,19298,19301],{},[24,19299,19300],{},"Due tracce musicali"," che si alternano in loop (generate con AI — ne parliamo tra poco)",[85,19303,19304,19307],{},[24,19305,19306],{},"Splash screen animata"," con blocchi che cadono sullo sfondo",[85,19309,19310,19313],{},[24,19311,19312],{},"Controlli mobile"," e canvas responsive",[17,19315,19316],{},"Tutto vanilla JavaScript, zero dipendenze. Non è un progetto complesso — è un gioco semplice, organizzato in modo che si possa capire e modificare.",[35,19318],{},[38,19320,19322],{"id":19321},"lezione-1-non-chiedere-fammi-un-tetris","Lezione 1: Non Chiedere \"Fammi un Tetris\"",[17,19324,19325],{},"\"Fammi un Tetris\" funziona. Ottieni un gioco giocabile. Ma ottieni anche un monolite da 800 righe che non puoi toccare senza rompere qualcosa. Per un Tetris va bene — per il prossimo progetto, no.",[17,19327,19328,19329,19331,19332,19335,19336,19339,19340,19342],{},"Tobi Lutke, CEO di Shopify, ha reso popolare un termine che spiega la differenza: ",[24,19330,72],{}," — ",[2128,19333,19334],{},"\"the art of providing all the context for the task to be plausibly solvable by the LLM\"",". Non è prompt engineering — non si tratta di trovare la frase magica. Si tratta di dare all'agente il contesto giusto su ",[24,19337,19338],{},"come"," vuoi che lavori, non solo ",[24,19341,76],{}," vuoi che faccia.",[17,19344,19345],{},"Il bello è che non serve molto. Bastano due righe in più.",[58,19347,19349],{"id":19348},"il-prompt-che-ha-fatto-la-differenza","Il prompt che ha fatto la differenza",[346,19351,19354],{"className":19352,"code":19353,"language":351},[349],"Costruisci un gioco Tetris in vanilla JS con Canvas.\nNon mettere tutto in un unico file. Separa logica di gioco,\nrendering, input, effetti e audio.\nOgni file fa una cosa sola. Tienili corti.\n",[353,19355,19353],{"__ignoreMap":355},[17,19357,19358,19359,19362],{},"Non serve elencare dieci file — basta dare una ",[24,19360,19361],{},"direzione",". Claude è bravo a decidere come dividere, se gli dici che deve dividere. Il prompt non descrive cosa è un Tetris (lo sa), ma come organizzare il codice. Ci vuole un minuto in più a scriverlo, e ti abitua a pensare all'architettura prima di scrivere codice — con o senza AI.",[35,19364],{},[38,19366,19368],{"id":19367},"lezione-2-dai-vincoli-non-libertà","Lezione 2: Dai Vincoli, Non Libertà",[17,19370,19371,19372,19374],{},"Anche su un progetto semplice, i vincoli migliorano il risultato. Non perché senza Claude non ce la fa — ce la fa benissimo. Ma perché ti abituano a ragionare su ",[24,19373,19338],{}," vuoi il codice prima che esista. Ed è un'abitudine che su un progetto vero ti salva settimane.",[17,19376,19377],{},"Ecco i vincoli che abbiamo dato progressivamente:",[58,19379,19381],{"id":19380},"vincolo-strutturale","Vincolo strutturale",[346,19383,19386],{"className":19384,"code":19385,"language":351},[349],"Non mettere tutto in un file. Separa logica, rendering, input, audio.\nNessun file oltre 150 righe.\n",[353,19387,19385],{"__ignoreMap":355},[17,19389,19390,19391,19394],{},"Sembra poco, ma cambia tutto. Senza questa indicazione, Claude infila audio, rendering, input ed effetti tutti dentro ",[353,19392,19393],{},"game.js",". Con il vincolo, separa spontaneamente e ogni pezzo resta gestibile.",[58,19396,19398],{"id":19397},"vincolo-di-stile","Vincolo di stile",[346,19400,19403],{"className":19401,"code":19402,"language":351},[349],"Stile arcade anni '90, tipo cabinato. Font pixel, sfondo scuro,\nbordi neon, colori vivaci. Niente gradienti moderni sui bottoni.\n",[353,19404,19402],{"__ignoreMap":355},[17,19406,19407],{},"Non serve dare hex code — basta una direzione chiara. Claude conosce benissimo l'estetica arcade e sceglie colori coerenti. Se poi il risultato non ti convince, correggi iterando (e qui entra Playwright, come vedremo).",[35,19409],{},[38,19411,19413],{"id":19412},"lezione-3-iterazione-con-feedback-visivo","Lezione 3: Iterazione con Feedback Visivo",[17,19415,19416,19417,688],{},"Questa è la tecnica che cambia tutto: ",[24,19418,19419],{},"non leggere il codice, guarda il risultato",[17,19421,19422,19423,19426],{},"Abbiamo usato ",[24,19424,19425],{},"Playwright MCP"," (il server MCP di Microsoft per l'automazione del browser) integrato in Claude Code per verificare visivamente ogni modifica. Il workflow:",[517,19428,19429,19432,19435,19438],{},[85,19430,19431],{},"Claude genera/modifica il codice",[85,19433,19434],{},"Playwright apre il browser e naviga alla pagina",[85,19436,19437],{},"Prende uno screenshot",[85,19439,19440],{},"Claude analizza lo screenshot e corregge",[17,19442,19443,19444,19447],{},"Non stai facendo code review — stai facendo ",[24,19445,19446],{},"visual review",". Ed è enormemente più efficace per la UI.",[58,19449,19451],{"id":19450},"esempio-concreto-i-font-troppo-piccoli","Esempio concreto: i font troppo piccoli",[17,19453,19454],{},"Dopo il primo rendering, i panel laterali con punteggio e livello erano illeggibili. Non abbiamo aperto il CSS per misurare i rem — abbiamo semplicemente detto:",[346,19456,19459],{"className":19457,"code":19458,"language":351},[349],"Le scritte dei panel sono troppo piccole, quasi illeggibili. Aumenta.\n",[353,19460,19458],{"__ignoreMap":355},[17,19462,19463],{},"Claude ha aumentato. Ancora troppo piccole. \"Ancora più grandi.\" Terzo tentativo, finalmente leggibili. Tre iterazioni, nessuna in cui abbiamo dovuto guardare il codice.",[58,19465,19467],{"id":19466},"esempio-il-bottone-non-è-arcade","Esempio: il bottone non è arcade",[17,19469,19470],{},"Il bottone \"GIOCA\" che Claude ha generato al primo tentativo sembrava un pulsante di una SaaS — gradiente, bordi arrotondati. Il feedback:",[346,19472,19475],{"className":19473,"code":19474,"language":351},[349],"Lo stile del bottone non sembra arcade come il resto del gioco.\n",[353,19476,19474],{"__ignoreMap":355},[17,19478,19479],{},"Un'unica frase. Claude lo ha trasformato in un bottone con bordo neon su sfondo scuro, font pixel, glow sottile. Non abbiamo specificato colori o font — abbiamo detto cosa non andava, e lui ha capito il contesto.",[35,19481],{},[38,19483,19485],{"id":19484},"lezione-4-gestisci-i-problemi-del-browser","Lezione 4: Gestisci i Problemi del Browser",[17,19487,19488],{},"Questa è la parte che nessun tutorial \"vibe coding\" ti racconta: i problemi reali.",[58,19490,19492],{"id":19491},"il-caso-dellaudio-che-non-parte","Il caso dell'audio che non parte",[17,19494,19495],{},"Volevamo la musica sullo splash screen — un'ambient track che parte quando arrivi alla pagina. Il codice era perfetto:",[346,19497,19501],{"className":19498,"code":19499,"language":19500,"meta":355,"style":355},"language-javascript shiki shiki-themes github-light github-dark","const splashTrack = new Audio('/Blocchi%20che%20Cadono.mp3');\nsplashTrack.play();\n","javascript",[353,19502,19503,19508],{"__ignoreMap":355},[407,19504,19505],{"class":409,"line":410},[407,19506,19507],{},"const splashTrack = new Audio('/Blocchi%20che%20Cadono.mp3');\n",[407,19509,19510],{"class":409,"line":417},[407,19511,19512],{},"splashTrack.play();\n",[17,19514,19515,19516,19519,19520,19523,19524,19527],{},"Non funzionava. Mai. Motivo: le ",[24,19517,19518],{},"autoplay policy"," del browser. Chrome, Firefox, Safari — tutti bloccano la riproduzione audio finché l'utente non fa un ",[24,19521,19522],{},"gesto reale"," (click, keydown, touchstart). ",[353,19525,19526],{},"mousemove"," non basta.",[17,19529,19530,19531,19534],{},"La soluzione arcade: ",[24,19532,19533],{},"\"PREMI UN TASTO PER INIZIARE\"",". Un testo lampeggiante in stile insert coin che aspetta un qualsiasi input dell'utente. Al primo tasto, la musica parte e appare il bottone GIOCA.",[346,19536,19538],{"className":19498,"code":19537,"language":19500,"meta":355,"style":355},"// Qualsiasi gesto reale sblocca l'audio del browser\nfunction insertCoin() {\n  if (coinInserted) return;\n  coinInserted = true;\n  music.start(); // Ora funziona: è dentro un gesto utente\n  $insertCoin.classList.add('hidden');\n  $playArea.classList.remove('hidden');\n}\n\ndocument.addEventListener('keydown', insertCoin);\ndocument.addEventListener('click', insertCoin);\ndocument.addEventListener('touchstart', insertCoin);\n",[353,19539,19540,19545,19550,19555,19560,19565,19570,19575,19579,19583,19588,19593],{"__ignoreMap":355},[407,19541,19542],{"class":409,"line":410},[407,19543,19544],{},"// Qualsiasi gesto reale sblocca l'audio del browser\n",[407,19546,19547],{"class":409,"line":417},[407,19548,19549],{},"function insertCoin() {\n",[407,19551,19552],{"class":409,"line":441},[407,19553,19554],{},"  if (coinInserted) return;\n",[407,19556,19557],{"class":409,"line":448},[407,19558,19559],{},"  coinInserted = true;\n",[407,19561,19562],{"class":409,"line":454},[407,19563,19564],{},"  music.start(); // Ora funziona: è dentro un gesto utente\n",[407,19566,19567],{"class":409,"line":1667},[407,19568,19569],{},"  $insertCoin.classList.add('hidden');\n",[407,19571,19572],{"class":409,"line":1673},[407,19573,19574],{},"  $playArea.classList.remove('hidden');\n",[407,19576,19577],{"class":409,"line":1679},[407,19578,2243],{},[407,19580,19581],{"class":409,"line":1685},[407,19582,445],{"emptyLinePlaceholder":444},[407,19584,19585],{"class":409,"line":1690},[407,19586,19587],{},"document.addEventListener('keydown', insertCoin);\n",[407,19589,19590],{"class":409,"line":1696},[407,19591,19592],{},"document.addEventListener('click', insertCoin);\n",[407,19594,19595],{"class":409,"line":1702},[407,19596,19597],{},"document.addEventListener('touchstart', insertCoin);\n",[17,19599,19600,19601,19603],{},"Elegante? Molto. Ma ci siamo arrivati dopo aver provato autoplay diretto, listener su ",[353,19602,19526],{}," (che non è un user activation event), e un sistema a due fasi con fade.",[17,19605,19606,19607,19610],{},"Il punto: l'AI non conosce sempre le restrizioni del browser. Tu sì, o le scopri testandolo. Il ",[24,19608,19609],{},"testing con Playwright"," ci ha fatto trovare il problema immediatamente.",[35,19612],{},[38,19614,19616],{"id":19615},"lezione-5-separa-quel-che-ha-senso-separare","Lezione 5: Separa Quel Che Ha Senso Separare",[17,19618,19619,19620,19623],{},"Non serve un'architettura enterprise per un Tetris. E un Tetris funziona anche tutto in un file. Ma quando hai cambiato il sistema audio ",[24,19621,19622],{},"tre volte"," in una sessione (da due tracce separate a playlist alternata), apprezzi il fatto che ogni modifica tocca solo il file dell'audio e l'entry point. Il resto del gioco non ha sentito nulla.",[17,19625,19626,19627,19630],{},"Non è overengineering — è che Claude ha diviso il codice in file separati perché gliel'abbiamo chiesto in una riga del prompt iniziale. Non ha richiesto più tempo. E il vantaggio è che se qualcosa non funziona, sai ",[24,19628,19629],{},"dove"," guardare.",[17,19632,19633],{},"Su un Tetris la differenza è piccola. Su un progetto reale, è la differenza tra \"riscrivo tutto\" e \"cambio un file\".",[35,19635],{},[38,19637,19639],{"id":19638},"lezione-6-gli-effetti-fanno-il-gioco","Lezione 6: Gli Effetti Fanno il Gioco",[17,19641,19642,19643,19646],{},"Un Tetris senza effetti è una griglia con quadrati che cadono. Gli effetti sono ciò che lo rende ",[24,19644,19645],{},"un'esperienza",". Ed è un'area dove l'AI brilla, se la guidi bene.",[58,19648,19650],{"id":19649},"particelle-esplosive","Particelle esplosive",[17,19652,19653],{},"Quando completi una riga, ogni cella esplode in particelle colorate che seguono la gravità e svaniscono. Il prompt:",[346,19655,19658],{"className":19656,"code":19657,"language":351},[349],"Quando completo una riga voglio un'esplosione di particelle.\nOgni blocco esplode nel suo colore originale.\n",[353,19659,19657],{"__ignoreMap":355},[17,19661,19662,19663,19666,19667,19670],{},"Due righe. Il dettaglio chiave è ",[24,19664,19665],{},"\"nel suo colore originale\"",". Senza questa specifica, Claude usa un colore generico. Con questa, fa uno snapshot della board ",[24,19668,19669],{},"prima"," del clear e usa quei colori per le particelle. Un piccolo prompt che produce un effetto molto più ricco.",[58,19672,19674],{"id":19673},"score-popup","Score popup",[346,19676,19678],{"className":19498,"code":19677,"language":19500,"meta":355,"style":355},"// +100 per una riga, +800 per un TETRIS (4 righe)\nif (linesCleared >= 4) {\n  el.textContent = `TETRIS! +${points}`;\n  el.style.color = '#a855f7';  // viola neon\n  el.style.fontSize = '2.2rem';\n}\n",[353,19679,19680,19685,19690,19695,19700,19705],{"__ignoreMap":355},[407,19681,19682],{"class":409,"line":410},[407,19683,19684],{},"// +100 per una riga, +800 per un TETRIS (4 righe)\n",[407,19686,19687],{"class":409,"line":417},[407,19688,19689],{},"if (linesCleared >= 4) {\n",[407,19691,19692],{"class":409,"line":441},[407,19693,19694],{},"  el.textContent = `TETRIS! +${points}`;\n",[407,19696,19697],{"class":409,"line":448},[407,19698,19699],{},"  el.style.color = '#a855f7';  // viola neon\n",[407,19701,19702],{"class":409,"line":454},[407,19703,19704],{},"  el.style.fontSize = '2.2rem';\n",[407,19706,19707],{"class":409,"line":1667},[407,19708,2243],{},[17,19710,19711,19712,688],{},"Il popup galleggia verso l'alto e svanisce. Per un Tetris (4 righe), è più grande, viola, con glow intenso. Un piccolo dettaglio che rende il completamento di 4 righe ",[24,19713,19714],{},"emozionante",[58,19716,19718],{"id":19717},"flash-sulle-righe","Flash sulle righe",[17,19720,19721],{},"Un lampo bianco orizzontale che attraversa la riga completata in 350ms. Tre righe di CSS, impatto visivo enorme.",[17,19723,19724],{},[207,19725],{"alt":19726,"src":19727},"La schermata di gioco con pezzi, panel laterali e controlli","/images/body/tetris2.webp",[35,19729],{},[38,19731,19733],{"id":19732},"lezione-7-testa-tu-non-solo-lai","Lezione 7: Testa Tu, Non Solo l'AI",[17,19735,19736,19737,688],{},"C'è un momento in cui Playwright e gli screenshot automatici non bastano: ",[24,19738,19739],{},"devi giocare",[17,19741,19742],{},"Dopo aver dichiarato il gioco \"finito\", abbiamo fatto una sessione di test manuale. In pochi minuti sono emersi bug che nessun test automatizzato avrebbe trovato:",[82,19744,19745,19751,19757],{},[85,19746,19747,19750],{},[24,19748,19749],{},"Input che si accumulava",": premendo un tasto mentre il pezzo precedente si stava posando, il comando passava al pezzo successivo. Il timer di auto-drop e l'input manuale non erano sincronizzati — il pezzo scendeva due volte di fila.",[85,19752,19753,19756],{},[24,19754,19755],{},"Listener duplicati",": ogni volta che premevi \"GIOCA ANCORA\", veniva aggiunto un nuovo handler per la tastiera. Alla terza partita, ogni tasto muoveva il pezzo di tre posizioni.",[85,19758,19759,19762],{},[24,19760,19761],{},"Pausa rotta",": un riferimento a un modulo audio rimosso durante un refactoring causava un crash silenzioso quando riprendevi dalla pausa.",[17,19764,19765,19766,19769],{},"Tre bug, tre categorie diverse, tutti invisibili a un test automatizzato perché richiedono ",[24,19767,19768],{},"interazione umana reale"," — timing, sequenze, sessioni prolungate.",[17,19771,19772,19773,19776],{},"La lezione: l'AI genera il codice, Playwright verifica che si veda giusto, ma ",[24,19774,19775],{},"il test finale sei tu",". Gioca, rompi, correggi.",[35,19778],{},[38,19780,19782],{"id":19781},"lezione-8-il-workflow-completo","Lezione 8: Il Workflow Completo",[17,19784,19785],{},"Ricapitoliamo il processo in ordine cronologico:",[58,19787,19789],{"id":19788},"minuti-0-3-architettura","Minuti 0-3: Architettura",[17,19791,19792],{},"Prompt iniziale con struttura modulare, vincoli di dimensione, stack tecnologico.",[58,19794,19796],{"id":19795},"minuti-3-10-core-gameplay","Minuti 3-10: Core gameplay",[17,19798,19799],{},"Board, pezzi, collisioni, rotazione con wall kicks, sistema di livelli, calcolo punteggio. La parte \"logica\" che Claude fa bene al primo tentativo.",[58,19801,19803],{"id":19802},"minuti-10-15-stile-e-feedback-visivo","Minuti 10-15: Stile e feedback visivo",[17,19805,19806],{},"Qui entra il loop visivo con Playwright. Splash screen, font arcade, colori neon, panel laterali. Ogni modifica verificata con screenshot.",[58,19808,19810],{"id":19809},"minuti-15-18-effetti-e-polish","Minuti 15-18: Effetti e polish",[17,19812,19813],{},"Particelle, flash, popup, ghost piece, countdown 3-2-1-GO. Il layer che trasforma un prototipo in un prodotto.",[58,19815,19817],{"id":19816},"minuti-18-20-audio-e-fix-browser","Minuti 18-20: Audio e fix browser",[17,19819,19820],{},"La parte più insidiosa. Autoplay policy, gestione pause/resume, playlist alternata.",[58,19822,19824],{"id":19823},"bonus-iterazione-post-20-minuti","Bonus: iterazione post-20 minuti",[17,19826,19827],{},"Background e logo generati con AI, fine-tuning dei font size, controlli mobile, toggle ghost piece, test umano e bug fixing. La differenza tra \"funziona\" e \"è bello da usare\".",[35,19829],{},[38,19831,19833],{"id":19832},"i-prompt-che-non-hanno-funzionato","I Prompt che Non Hanno Funzionato",[17,19835,19836,19837,19840],{},"Sarebbe disonesto mostrare solo i successi. Ecco cosa ",[24,19838,19839],{},"non"," ha funzionato:",[17,19842,19843,19846,19847,19849],{},[24,19844,19845],{},"\"Rendilo più bello\""," — troppo vago. Claude cambia colori a caso, aggiunge ombre dove non servono, e rimuove cose che funzionavano. Specifica ",[24,19848,76],{}," non ti piace.",[17,19851,19852,19855,19856,19859],{},[24,19853,19854],{},"\"Aggiungi musica allo splash\""," — Claude ha generato un ",[353,19857,19858],{},"new Audio().play()"," diretto, che il browser blocca. Serviva il contesto delle autoplay policy.",[17,19861,19862,19865],{},[24,19863,19864],{},"\"Stile arcade\""," — senza specifiche sui colori, Claude interpreta \"arcade\" come \"pixel art con colori pastello\". Servono hex code esatti.",[17,19867,19868,19871],{},[24,19869,19870],{},"Logo con sfondo scuro"," — al primo tentativo di generare immagini con AI, lo sfondo era bianco nonostante \"dark background\" nel prompt. Serviva un prompt molto più aggressivo: \"Black background. Neon-colored blocks floating in space. No white. No light backgrounds.\"",[35,19873],{},[38,19875,19877],{"id":19876},"cosa-puoi-fare-tu-adesso","Cosa Puoi Fare Tu Adesso",[517,19879,19880,19889,19895,19901],{},[85,19881,19882,19885,19886,19888],{},[24,19883,19884],{},"Gioca"," a ",[69,19887,19247],{"href":19251,"target":19252}," e guarda il codice sorgente — è tutto leggibile",[85,19890,19891,19894],{},[24,19892,19893],{},"Forka il pattern",": la stessa architettura modulare funziona per Snake, Breakout, Space Invaders",[85,19896,19897,19900],{},[24,19898,19899],{},"Sperimenta con i vincoli",": prova a dare a Claude lo stesso prompt senza la struttura modulare e confronta i risultati",[85,19902,19903,19906],{},[24,19904,19905],{},"Usa Playwright MCP",": se non l'hai ancora configurato, è il singolo tool che migliora di più la qualità dell'output AI per qualsiasi progetto frontend",[17,19908,19909],{},"Un Tetris si fa anche senza niente di tutto questo. Ma il prossimo progetto non sarà un Tetris — e le abitudini che costruisci adesso sono quelle che userai allora.",[35,19911],{},[38,19913,4399],{"id":19914},"fonti",[517,19916,19917,19925,19933,19940,19948,19956],{},[85,19918,19919,19924],{},[69,19920,19923],{"href":19921,"rel":19922},"https://x.com/tobi/status/1935533422589399127",[1152],"Tobi Lutke — \"Context Engineering\""," — il tweet che ha reso popolare il termine",[85,19926,19927,19932],{},[69,19928,19931],{"href":19929,"rel":19930},"https://x.com/karpathy/status/1937902205765607626",[1152],"Andrej Karpathy su Context Engineering"," — conferma e amplifica il concetto",[85,19934,19935,19939],{},[69,19936,19938],{"href":2679,"rel":19937},[1152],"Anthropic — Claude Code Best Practices"," — documentazione ufficiale su rules file e CLAUDE.md",[85,19941,19942,19947],{},[69,19943,19946],{"href":19944,"rel":19945},"https://github.com/microsoft/playwright-mcp",[1152],"Microsoft Playwright MCP Server"," — repository ufficiale per testing visivo con AI",[85,19949,19950,19955],{},[69,19951,19954],{"href":19952,"rel":19953},"https://til.simonwillison.net/claude-code/playwright-mcp-claude-code",[1152],"Simon Willison — Playwright MCP con Claude Code"," — setup e uso pratico",[85,19957,19958,19963],{},[69,19959,19962],{"href":19960,"rel":19961},"https://developer.mozilla.org/en-US/docs/Web/Media/Autoplay_guide",[1152],"MDN Web Docs — Autoplay Policy"," — le restrizioni browser sull'audio",[35,19965],{},[17,19967,19968],{},[2128,19969,19970],{},"Se hai giocato a Blocchi che Cadono, avrai notato che senza la colonna sonora sarebbe stato un esercizio tecnico — con la musica è diventato un'esperienza. Quelle due tracce le abbiamo generate con Suno AI, in pochi minuti, senza sapere una nota. Nei prossimi giorni ti mostriamo come.",[1218,19972,19973],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":355,"searchDepth":417,"depth":417,"links":19975},[19976,19977,19980,19984,19988,19991,19992,19997,19998,20006,20007,20008],{"id":19265,"depth":417,"text":19266},{"id":19321,"depth":417,"text":19322,"children":19978},[19979],{"id":19348,"depth":441,"text":19349},{"id":19367,"depth":417,"text":19368,"children":19981},[19982,19983],{"id":19380,"depth":441,"text":19381},{"id":19397,"depth":441,"text":19398},{"id":19412,"depth":417,"text":19413,"children":19985},[19986,19987],{"id":19450,"depth":441,"text":19451},{"id":19466,"depth":441,"text":19467},{"id":19484,"depth":417,"text":19485,"children":19989},[19990],{"id":19491,"depth":441,"text":19492},{"id":19615,"depth":417,"text":19616},{"id":19638,"depth":417,"text":19639,"children":19993},[19994,19995,19996],{"id":19649,"depth":441,"text":19650},{"id":19673,"depth":441,"text":19674},{"id":19717,"depth":441,"text":19718},{"id":19732,"depth":417,"text":19733},{"id":19781,"depth":417,"text":19782,"children":19999},[20000,20001,20002,20003,20004,20005],{"id":19788,"depth":441,"text":19789},{"id":19795,"depth":441,"text":19796},{"id":19802,"depth":441,"text":19803},{"id":19809,"depth":441,"text":19810},{"id":19816,"depth":441,"text":19817},{"id":19823,"depth":441,"text":19824},{"id":19832,"depth":417,"text":19833},{"id":19876,"depth":417,"text":19877},{"id":19914,"depth":417,"text":4399},"Tutorial pratico: come guidare un AI agent a produrre un gioco completo, modulare e con effetti arcade. Prompt engineering, context engineering e testing visivo.","/images/guides/ricrea-tetris-20-minuti-claude-code.webp",{},"/guides/ricrea-tetris-20-minuti-claude-code","2026-03-13",{"title":19210,"description":20009},"guides/ricrea-tetris-20-minuti-claude-code",[1287,8060,20017,1285,20018,4528,3503],"Game Dev","Prompt Engineering","dC_dTEXcKBxY9EZcFu9_eVni9MtrKSON0-BV69c3V0M",{"id":20021,"title":20022,"author":20023,"body":20024,"category":2766,"contentType":1269,"description":20480,"difficulty":1269,"extension":1272,"featured":444,"icon":1269,"image":20481,"meta":20482,"navigation":444,"path":20483,"publishedAt":20484,"readingTime":1690,"seo":20485,"stem":20486,"steps":1269,"tags":20487,"youtubeId":1269,"__hash__":20492},"guides/guides/tre-cose-che-nessuno-fa.md","3 Cose che (Quasi) Nessuno Fa",{"name":7,"initials":8},{"type":10,"value":20025,"toc":20458},[20026,20029,20032,20035,20038,20044,20047,20050,20052,20056,20059,20062,20066,20069,20072,20077,20080,20083,20087,20090,20095,20101,20104,20109,20115,20118,20121,20125,20128,20131,20134,20137,20140,20144,20147,20157,20171,20174,20181,20184,20190,20193,20195,20199,20202,20206,20218,20227,20230,20234,20237,20240,20246,20249,20252,20256,20259,20262,20265,20268,20270,20274,20277,20280,20283,20287,20290,20293,20297,20300,20303,20306,20309,20323,20326,20330,20333,20336,20342,20346,20349,20352,20355,20358,20360,20364,20367,20370,20381,20384,20387,20390,20393,20395,20399,20402,20405,20408,20411,20417,20423,20428,20431,20434,20440,20442,20446,20449,20452,20455],[13,20027,20022],{"id":20028},"_3-cose-che-quasi-nessuno-fa",[17,20030,20031],{},"Siamo a febbraio 2026. Il termine \"vibe coding\" è stato coniato un anno fa. L'agent coding esiste da poco più di un anno.",[17,20033,20034],{},"Un anno.",[17,20036,20037],{},"Questo significa una cosa importante: quasi nessuno sa ancora usarlo bene. Non perché sia difficile — ma perché è nuovo. Non c'è una generazione di developer esperti da cui imparare. Non ci sono best practice consolidate. Siamo tutti pionieri che scoprono strada facendo.",[17,20039,20040,20043],{},[24,20041,20042],{},"L'agent coding non è un bottone che premi e funziona."," È una skill. Va masterata. Richiede mesi di pratica, errori, aggiustamenti. E la maggior parte dei developer è ancora all'inizio di questo percorso.",[17,20045,20046],{},"Questo blog esiste per accelerare quel percorso. Per condividere quello che funziona e quello che no.",[17,20048,20049],{},"Queste tre abitudini? Sono tra le prime cose che ho scoperto fare la differenza. Semplici. Controintuitive. Che quasi nessuno fa.",[35,20051],{},[38,20053,20055],{"id":20054},"_1-parla-non-scrivere","1. Parla. Non Scrivere.",[17,20057,20058],{},"Questa è la cosa più ovvia e meno praticata.",[17,20060,20061],{},"Gli agenti non hanno bisogno che tu scriva. Hanno bisogno di testo. E il testo può arrivare dalla tua voce.",[58,20063,20065],{"id":20064},"perché-nessuno-lo-fa","Perché nessuno lo fa",[17,20067,20068],{},"C'è un bias strano contro il parlare. Siamo developer. Scriviamo codice. Scriviamo prompt. Parlare sembra... sbagliato? Poco professionale? Strano se sei in ufficio?",[17,20070,20071],{},"Ma pensa a cosa succede quando scrivi: editi, cancelli, riformuli, cerchi la parola giusta, ti autocensuri prima ancora di finire il pensiero.",[1524,20073,20074],{},[17,20075,20076],{},"Ogni prompt scritto è una versione compressa e filtrata di quello che volevi dire.",[17,20078,20079],{},"Quando parli, pensi ad alta voce. Il flusso è diverso. Più naturale. Più completo.",[17,20081,20082],{},"I miei prompt vocali sono sempre più lunghi e più dettagliati di quelli scritti. Non perché mi sforzi — anzi, è il contrario. Parlare richiede meno sforzo che scrivere. E il contesto extra che aggiungo \"senza pensarci\" spesso è esattamente quello che serve all'agente per capire cosa voglio.",[58,20084,20086],{"id":20085},"lesempio-pratico","L'esempio pratico",[17,20088,20089],{},"Guarda la differenza. Stesso task, due approcci.",[17,20091,20092],{},[24,20093,20094],{},"Prompt scritto tipico:",[346,20096,20099],{"className":20097,"code":20098,"language":351},[349],"Aggiungi validazione al form di login\n",[353,20100,20098],{"__ignoreMap":355},[17,20102,20103],{},"Risultato: l'agente fa assunzioni. Magari usa una libreria che non hai. Magari valida in modo diverso da come vuoi. Devi correggere, iterare, perdere tempo.",[17,20105,20106],{},[24,20107,20108],{},"Prompt parlato (trascritto):",[346,20110,20113],{"className":20111,"code":20112,"language":351},[349],"Ok allora, ho questo form di login che funziona ma non ha validazione.\nL'email deve essere una email valida, la password almeno 8 caratteri\ncon un numero. Ah, e mostra gli errori sotto ogni campo, in rosso,\nsolo dopo che l'utente ha provato a submittare. Usiamo già Zod nel\nprogetto quindi usa quello.\n",[353,20114,20112],{"__ignoreMap":355},[17,20116,20117],{},"Risultato: l'agente ha tutto. Fa il lavoro giusto al primo colpo.",[17,20119,20120],{},"La differenza? Il secondo prompt ha contesto, specifiche, UX, stack tecnico. Tutto questo esce naturalmente quando parli. Quando scrivi, ti sembra \"troppo lungo\" e tagli.",[58,20122,20124],{"id":20123},"prova-tu-stesso","Prova tu stesso",[17,20126,20127],{},"Sentiti libero di sperimentare la differenza.",[17,20129,20130],{},"Prendi lo stesso task e fallo due volte: una scritta, una parlata. Puoi farlo su due branch diverse così non rovini quello che stai facendo. Poi confronta i risultati.",[17,20132,20133],{},"Il trucco per parlare bene all'agente? Immaginati il tuo nuovo collega junior, appena entrato. Devi spiegargli cosa fare, ma non hai voglia di tornare lì a rispiegarglielo tre volte. Quindi gli dai tutto: il contesto, i dettagli, le eccezioni, lo stack che usate.",[17,20135,20136],{},"Ecco. Parla all'agente così.",[17,20138,20139],{},"Non perché l'agente sia più intelligente quando parli. Perché tu gli dai più contesto, più velocemente, con meno sforzo. E non devi tornare a rispiegare.",[58,20141,20143],{"id":20142},"i-tool-per-farlo","I tool per farlo",[17,20145,20146],{},"Non hai bisogno di nulla di speciale. Hai già tutto.",[17,20148,20149,20152,20153,20156],{},[24,20150,20151],{},"Su Windows",": Premi ",[353,20154,20155],{},"Win + H"," e inizia a parlare. È la dettatura integrata nel sistema, gratuita, funziona ovunque. Non è perfetta, ma è più che sufficiente per i prompt.",[17,20158,20159,20162,20163,20166,20167,20170],{},[24,20160,20161],{},"Su Mac",": Premi due volte il tasto ",[353,20164,20165],{},"Fn"," (o ",[353,20168,20169],{},"Ctrl + Cmd + D"," nelle versioni precedenti). Stessa cosa: dettatura di sistema, gratuita, integrata.",[17,20172,20173],{},"Questi tool di accessibilità esistono da anni. Quasi nessuno li usa per programmare.",[17,20175,20176,20177,20180],{},"Se vuoi qualcosa di più potente, ci sono tool dedicati. Io uso ",[24,20178,20179],{},"Wispr Flow"," — è a pagamento, ma la qualità di trascrizione è superiore e funziona ovunque sul sistema. Ci sono alternative gratuite e open source, ma per l'uso quotidiano intensivo, un buon tool a pagamento si ripaga in tempo risparmiato.",[17,20182,20183],{},"Il punto non è quale tool usi. Il punto è che inizi a parlare invece di scrivere.",[17,20185,20186,20189],{},[24,20187,20188],{},"Non stai dettando una lettera. Stai scaricando un'architettura mentale."," Non preoccuparti della grammatica — l'agente pulirà il rumore. Preoccupati del segnale.",[17,20191,20192],{},"I primi giorni ti sembrerà strano. Poi non tornerai più indietro.",[35,20194],{},[38,20196,20198],{"id":20197},"_2-non-è-un-essere-umano-smettila-di-trattarlo-come-tale","2. Non È un Essere Umano. Smettila di Trattarlo Come Tale.",[17,20200,20201],{},"Questa è sottile ma importante. E ha due facce.",[58,20203,20205],{"id":20204},"gli-insulti","Gli insulti",[17,20207,20208,20209,20214,20217],{},"Ho visto di tutto. Developer che scrivono cose che non ripeterei neanche censurate. \"Sei un c",[2128,20210,20211],{},[24,20212,20213],{},"o di i",[24,20215,20216],{},"a\", \"Ma quanto c","*o sei stupido\", \"F*****o te e chi ti ha programmato\".",[17,20219,20220,20221,20223,20224,20226],{},"L'agente non si offende. Non può offendersi. Ma tu stai sprecando token di contesto con contenuto emotivo che non aggiunge nulla. Quel prompt pieno di rabbia occupa spazio che potresti usare per spiegare ",[2128,20222,76],{}," è sbagliato e ",[2128,20225,19338],{}," vuoi che venga corretto.",[17,20228,20229],{},"E c'è un effetto collaterale: quando sei frustrato, i tuoi prompt diventano vaghi. \"Rifallo bene questa volta\" non dice nulla. L'agente non sa cosa intendi per \"bene\". Risultato: altro output sbagliato, altra frustrazione, spirale negativa.",[58,20231,20233],{"id":20232},"il-mio-codice-è-meglio","\"Il mio codice è meglio\"",[17,20235,20236],{},"L'altra trappola è la competizione. Soprattutto tra developer senior.",[17,20238,20239],{},"\"Questo codice fa schifo, io l'avrei scritto meglio.\" Ok. Ma l'hai scritto tu il prompt? Perché se hai scritto tre parole e ti aspettavi cinque pagine di codice perfetto, il problema non è l'agente. È il tuo prompt.",[17,20241,20242,20245],{},[24,20243,20244],{},"Non siamo più nel mondo del single-shot."," Il prompt engineering \"scrivo una frase perfetta e ottengo il risultato perfetto\" non esiste nell'agent coding. Questo è un processo. Un'iterazione. Dai contesto, vedi l'output, correggi, iteri.",[17,20247,20248],{},"Se dopo tre iterazioni non arrivi al risultato, la domanda non è \"perché l'agente è stupido?\" La domanda è: \"cosa non sto comunicando bene?\"",[17,20250,20251],{},"È collegato al punto 1: se parli, dai più contesto. Se dai più contesto, l'output è migliore. Se scrivi tre parole, non lamentarti che l'output non è quello che volevi.",[58,20253,20255],{"id":20254},"il-mindset-giusto","Il mindset giusto",[17,20257,20258],{},"L'agente è uno strumento. Non si offende se lo insulti, e non ha bisogno che tu sia gentile. Ma funziona meglio se gli dai istruzioni chiare.",[17,20260,20261],{},"Dall'altro lato, scusarsi è inutile. \"Scusa se ti disturbo ancora, ma potresti gentilmente...\" è rumore. L'agente non ha bisogno di convenevoli.",[17,20263,20264],{},"Il tuo lavoro è dare istruzioni chiare, specifiche, con il contesto necessario. Niente di più, niente di meno.",[17,20266,20267],{},"E se non funziona? Itera. Cambia approccio. Dai più contesto. Ma non dare la colpa allo strumento.",[35,20269],{},[38,20271,20273],{"id":20272},"_3-sbaglia-tanto-di-proposito","3. Sbaglia. Tanto. Di Proposito.",[17,20275,20276],{},"Questa è la più controintuitiva.",[17,20278,20279],{},"La maggior parte dei developer tratta l'agent coding come un esame. Devi fare il prompt giusto al primo colpo. Se sbagli, hai perso.",[17,20281,20282],{},"È l'approccio sbagliato.",[58,20284,20286],{"id":20285},"perché-gli-errori-sono-preziosi","Perché gli errori sono preziosi",[17,20288,20289],{},"Ogni errore ti insegna qualcosa sui limiti dell'agente. Ti insegna come pensa (o non pensa). Ti insegna cosa funziona e cosa no.",[17,20291,20292],{},"Ho imparato più sull'agent coding dai prompt falliti che da quelli riusciti. Perché il fallimento ti costringe ad analizzare: cosa è andato storto? Come posso riformulare? Cosa mancava nel mio contesto?",[58,20294,20296],{"id":20295},"lesperimento-che-dovresti-fare","L'esperimento che dovresti fare",[17,20298,20299],{},"Prendi un'ora. Un'ora dedicata a rompere cose.",[17,20301,20302],{},"Chiedi all'agente cose impossibili. Chiedi cose vaghe. Chiedi cose contraddittorie. Chiedi senza contesto. Chiedi con troppo contesto.",[17,20304,20305],{},"Guarda cosa succede. Non per ottenere output utile — per capire i pattern di fallimento.",[17,20307,20308],{},"Alcune cose che ho scoperto così:",[82,20310,20311,20314,20317,20320],{},[85,20312,20313],{},"Se chiedi qualcosa di troppo vago, l'agente fa assunzioni. Spesso sbagliate.",[85,20315,20316],{},"Se chiedi qualcosa di contraddittorio, a volte lo nota, a volte no.",[85,20318,20319],{},"Se il contesto è troppo lungo, perde pezzi. Ha priorità implicite.",[85,20321,20322],{},"Se chiedi \"miglioralo\" senza dire come, fa cambiamenti random.",[17,20324,20325],{},"Queste sono informazioni preziose. Non le trovi nei tutorial. Le trovi sbagliando.",[58,20327,20329],{"id":20328},"il-costo-dellerrore-è-basso","Il costo dell'errore è basso",[17,20331,20332],{},"Questo è il punto chiave: sbagliare costa poco.",[17,20334,20335],{},"Un prompt fallito ti costa qualche secondo e qualche centesimo di API. Non rompe nulla. Non offende nessuno. Non finisce nel tuo git history (a meno che tu non faccia commit senza guardare — e quello è un altro problema).",[17,20337,20338,20339,20341],{},"Confrontalo con il costo di ",[2128,20340,19839],{}," sperimentare: mesi di utilizzo subottimale, prompt inefficienti, frustrazione accumulata.",[58,20343,20345],{"id":20344},"lapproccio-iterativo","L'approccio iterativo",[17,20347,20348],{},"I developer migliori con l'agent coding non sono quelli che fanno prompt perfetti. Sono quelli che iterano velocemente.",[17,20350,20351],{},"Primo prompt: vago, veloce, per vedere dove va.\nSecondo prompt: correggo la direzione in base all'output.\nTerzo prompt: affino i dettagli.",[17,20353,20354],{},"È come scolpire. Non parti dal dettaglio. Parti dalla forma grezza e affini.",[17,20356,20357],{},"Questo approccio richiede che tu sia a tuo agio con l'errore. Che lo veda come parte del processo, non come fallimento.",[35,20359],{},[38,20361,20363],{"id":20362},"il-pattern-comune","Il Pattern Comune",[17,20365,20366],{},"Hai notato cosa hanno in comune queste tre abitudini?",[17,20368,20369],{},"Tutte richiedono di lasciare andare qualcosa:",[82,20371,20372,20375,20378],{},[85,20373,20374],{},"Lasciare andare il perfezionismo del prompt scritto → parla",[85,20376,20377],{},"Lasciare andare l'antropomorfizzazione → trattalo come strumento",[85,20379,20380],{},"Lasciare andare la paura di sbagliare → sperimenta",[17,20382,20383],{},"L'agent coding è uno skill. Come tutti gli skill, si sviluppa con la pratica. Ma la pratica efficace richiede un mindset diverso da quello che la maggior parte dei developer porta.",[17,20385,20386],{},"Non sei a scuola. Non c'è un voto. L'unica metrica che conta è: stai ottenendo quello che ti serve?",[17,20388,20389],{},"Se sì, continua.\nSe no, cambia approccio.",[17,20391,20392],{},"Queste tre abitudini sono il punto di partenza.",[35,20394],{},[38,20396,20398],{"id":20397},"bonus-le-allucinazioni-non-sono-solo-un-problema","Bonus: Le Allucinazioni Non Sono (Solo) un Problema",[17,20400,20401],{},"Tutti ne parlano come di un difetto. \"L'AI allucina\", \"inventa cose\", \"non ci si può fidare\".",[17,20403,20404],{},"Ma aspetta un attimo.",[17,20406,20407],{},"Gli LLM navigano in uno spazio vettoriale multidimensionale. Uno spazio che noi umani non riusciamo nemmeno a visualizzare — il nostro cervello si ferma a tre dimensioni, forse quattro se ci sforziamo. Quando l'agente \"allucina\", sta esplorando connessioni in quello spazio che noi non vedremmo mai.",[17,20409,20410],{},"E a volte, quelle connessioni sono oro.",[17,20412,20413,20416],{},[24,20414,20415],{},"Nella fase creativa"," — planning, brainstorming, esplorazione — chiedere cose che oggi non esistono può aprire strade nuove. L'agente può combinare concetti in modi che a te non verrebbero in mente. Può suggerire approcci che sembrano assurdi ma che, guardandoli meglio, hanno senso.",[17,20418,20419,20422],{},[24,20420,20421],{},"Nella fase di esecuzione"," — scrivere codice, implementare, deployare — le allucinazioni sono pericolose. Qui vuoi precisione, non creatività.",[1524,20424,20425],{},[17,20426,20427],{},"L'allucinazione è un eccellente architetto visionario, ma un pessimo ingegnere strutturale.",[17,20429,20430],{},"Il problema non è l'allucinazione in sé. Il problema è prendere tutto per buono senza verificare. Ma quello è lo stesso problema di un prompt fatto male che dà output sbagliato: non è colpa dello strumento, è colpa di come lo usi.",[17,20432,20433],{},"Se verifichi, se controlli, se usi il tuo giudizio — le allucinazioni diventano esplorazioni. Un modo per vedere connessioni che il tuo cervello tridimensionale non può fare.",[17,20435,20436,20437],{},"Non trattarle solo come bug. ",[24,20438,20439],{},"Nella fase giusta, sono feature.",[35,20441],{},[38,20443,20445],{"id":20444},"prossimi-passi","Prossimi Passi",[17,20447,20448],{},"Prova una di queste tre cose oggi. Solo una. Per una settimana.",[17,20450,20451],{},"Poi passa alla prossima.",[17,20453,20454],{},"Non devi cambiare tutto insieme. Devi cambiare abbastanza da vedere la differenza.",[17,20456,20457],{},"La differenza la vedrai.",{"title":355,"searchDepth":417,"depth":417,"links":20459},[20460,20466,20471,20477,20478,20479],{"id":20054,"depth":417,"text":20055,"children":20461},[20462,20463,20464,20465],{"id":20064,"depth":441,"text":20065},{"id":20085,"depth":441,"text":20086},{"id":20123,"depth":441,"text":20124},{"id":20142,"depth":441,"text":20143},{"id":20197,"depth":417,"text":20198,"children":20467},[20468,20469,20470],{"id":20204,"depth":441,"text":20205},{"id":20232,"depth":441,"text":20233},{"id":20254,"depth":441,"text":20255},{"id":20272,"depth":417,"text":20273,"children":20472},[20473,20474,20475,20476],{"id":20285,"depth":441,"text":20286},{"id":20295,"depth":441,"text":20296},{"id":20328,"depth":441,"text":20329},{"id":20344,"depth":441,"text":20345},{"id":20362,"depth":417,"text":20363},{"id":20397,"depth":417,"text":20398},{"id":20444,"depth":417,"text":20445},"Le tre abitudini per usare meglio l'agent coding che quasi nessuno pratica. Parla invece di scrivere, non umanizzare l'agente, sbaglia di più.","/images/guides/tre-cose-che-nessuno-fa.webp",{},"/guides/tre-cose-che-nessuno-fa","2026-02-03",{"title":20022,"description":20480},"guides/tre-cose-che-nessuno-fa",[20488,2766,20489,20490,20491],"Agent Coding","Best Practice","Voice","Mindset","RK2QVl1-jLb6-TplxNiZshzBvUE2jbxxYzGgWu825R8",1790146470570]