Chi passa la giornata davanti a una tastiera ripete le stesse sequenze di caratteri decine di volte al giorno, ovvero l’indirizzo email, l’IBAN aziendale, la formula di chiusura di una mail, il blocco di codice che serve sempre identico. Espanso affronta il problema nel modo più diretto possibile. Resta in ascolto di quello che digiti e, appena riconosce una sigla definita in precedenza, la cancella e la sostituisce con il testo completo.
Funziona in qualsiasi applicazione, dal browser al client di posta, dall’editor di codice alle chat, perché lavora a livello di sistema operativo e non come estensione del singolo programma.
Fin qui si tratta di un normale espansore di testo. La parte interessante viene dopo, perché uno snippet può contenere date calcolate sul momento, moduli con campi da compilare, il contenuto degli appunti e persino l’output di un comando eseguito dal sistema. Questo sposta lo strumento da semplice scorciatoia di scrittura a piccolo motore di automazione. Con un po’ di fantasia si arriva a far riscrivere un paragrafo da un modello linguistico in esecuzione sul proprio PC, senza mai lasciare la finestra in cui stai scrivendo.
Il progetto è scritto in Rust, è gratuito e open source, e gira su Windows, macOS e Linux. Dopo un paio d’anni di sviluppo quasi fermo, nel 2025 nuovi manutentori hanno ripreso in mano il repository. La versione 2.4.0, pubblicata il 21 luglio 2026, porta compatibilità migliore con i compositor Wayland, il ritorno del pacchetto Snap, correzioni per macOS e l’aggiornamento di alcune dipendenze con vulnerabilità note.
Installazione: pochi minuti su Windows, qualche attenzione in più su Linux
Su Windows la strada più rapida passa dai gestori di pacchetti. Il programma richiede Windows 10 o successivo su architettura x64, quindi i portatili con processore ARM per ora restano esclusi.
# Winget (preinstallato su Windows 11)
winget install --id=Espanso.Espanso -e
# In alternativa, Chocolatey
choco install espanso
# Oppure Scoop
scoop bucket add main
scoop install main/espanso
Se preferisci l’installer grafico scaricato dal sito, tieni presente che Windows SmartScreen potrebbe mostrare un avviso, dato che la firma digitale del progetto è recente e il filtro reputazionale di Microsoft non la considera ancora affidabile. In quel caso basta cliccare su “Ulteriori informazioni” e poi su “Esegui comunque”. Su macOS l’installazione avviene tramite Homebrew ed è la più lineare delle tre.
Su Linux la procedura cambia a seconda del server grafico in uso, ed è il primo controllo da fare.
echo $XDG_SESSION_TYPE
Se il comando risponde x11, su Ubuntu e derivate si installa il pacchetto DEB dedicato. Se invece risponde wayland, serve il pacchetto compilato con il supporto specifico, più un passaggio aggiuntivo sui permessi.
# Sessione X11 su Ubuntu/Debian
wget https://github.com/espanso/espanso/releases/latest/download/espanso-debian-x11-amd64.deb
sudo apt install ./espanso-debian-x11-amd64.deb
# Sessione Wayland su Ubuntu/Debian
wget https://github.com/espanso/espanso/releases/latest/download/espanso-debian-wayland-amd64.deb
sudo apt install ./espanso-debian-wayland-amd64.deb
sudo setcap "cap_dac_override+p" $(which espanso)
# In entrambi i casi, registrazione come servizio e avvio
espanso service register
espanso start
Il comando setcap merita una spiegazione, perché a prima vista sembra una concessione generosa. Su Wayland il programma deve leggere direttamente dai dispositivi di input del kernel (/dev/input) e scrivere su /dev/uinput per simulare la digitazione, operazioni normalmente riservate a root.
Invece di girare con privilegi elevati per tutta la sessione, il binario riceve la capability CAP_DAC_OVERRIDE nel set permitted, la attiva solo per il tempo necessario ad aprire quei dispositivi all’avvio, poi la rimuove dai propri set e non può più riacquisirla. È un compromesso ragionevole, ma vale la pena saperlo prima di lanciare il comando.
Sulle altre distribuzioni le strade sono queste.
- Su Fedora conviene il repository di terze parti Terra, con
sudo dnf install espanso-x11oppureespanso-wayland. - Su Arch e Manjaro la via consigliata resta l’AppImage per X11, mentre su Wayland serve la compilazione da sorgenti.
- Su qualsiasi altra distribuzione vale lo stesso schema, ovvero AppImage per X11 e compilazione per Wayland.
Un’ultima nota riguarda direttamente chi scrive in italiano. Su Wayland i layout di tastiera non statunitensi vanno dichiarati a mano, altrimenti alcuni caratteri accentati escono sbagliati. Bastano due righe nel file config/default.yml.
keyboard_layout:
layout: "it"
Espanso: due cartelle e config in YAML
Il programma non ha un’interfaccia grafica per la configurazione. Tutto si definisce in file YAML, un formato di testo strutturato in cui l’indentazione conta come in Python.
Chi arriva da strumenti commerciali come TextExpander troverà scomoda l’assenza di un pannello di controllo. Chi è abituato a versionare i propri file la considererà invece un vantaggio, perché l’intera configurazione è testo semplice, si copia da una macchina all’altra e si tiene in un repository Git. La cartella di configurazione si trova con un comando.
espanso path
I percorsi predefiniti sono %AppData%\espanso su Windows, ~/.config/espanso su Linux e ~/Library/Application Support/espanso su macOS. All’interno ci sono due directory con ruoli distinti.
- La cartella config/ stabilisce come il programma si comporta, cioè velocità di digitazione, scorciatoie e applicazioni in cui restare in silenzio.
- La cartella match/ stabilisce cosa deve scrivere, cioè l’elenco degli snippet.
Per iniziare servono solo due file, ovvero config/default.yml e match/base.yml. Per aprirli senza cercarli nel file manager esiste una scorciatoia comoda.
espanso edit # apre match/base.yml
espanso edit config/default.yml
L’editor usato è quello indicato dalla variabile d’ambiente EDITOR o VISUAL, quindi conviene impostarla sul proprio editor preferito invece di ritrovarsi dentro Nano o Blocco note. Il file base.yml in versione minima ha questo aspetto.
matches:
- trigger: ":mail"
replace: "[email protected]"
- trigger: ":sig"
replace: |
Cordiali saluti,
Mario Rossi
Responsabile tecnico, 333 1234567
Il carattere | dice a YAML di prendere il blocco successivo così com’è, andate a capo comprese. Non serve riavviare nulla, perché il programma si accorge delle modifiche al file e ricarica le regole da solo dopo qualche istante. Se qualcosa non funziona, espanso log mostra gli errori, che nella maggior parte dei casi sono indentazioni sbagliate o virgolette mancanti.
Una convenzione utile riguarda il prefisso dei trigger. Iniziare ogni sigla con i due punti (:mail, :sig, :oggi) riduce quasi a zero il rischio di espansioni indesiderate mentre scrivi normalmente, perché è una sequenza che nella lingua corrente non compare mai. Chi preferisce può usare un altro carattere, o nessuno, ma in quel caso conviene leggere la sezione successiva sui word trigger.
Snippet: date, cursore e maiuscole
Il testo fisso risolve metà del problema. L’altra metà riguarda tutto ciò che cambia ogni volta, a partire dalle date. L’estensione dedicata calcola il valore al momento dell’espansione e accetta un offset in secondi per spostarsi avanti o indietro nel tempo.
matches:
- trigger: ":oggi"
replace: "{{data}}"
vars:
- name: data
type: date
params:
format: "%d/%m/%Y"
locale: "it-IT"
- trigger: ":dom"
label: "Data di domani in formato esteso"
replace: "{{data}}"
vars:
- name: data
type: date
params:
format: "%A %d %B %Y"
locale: "it-IT"
offset: 86400
Gli 86400 secondi corrispondono a ventiquattro ore, mentre un valore negativo produce la data di ieri. Dalla versione 2.3.0 è disponibile anche il parametro tz, che accetta i nomi standard dei fusi orari (Europe/Rome, America/New_York) e torna utile a chi coordina call con colleghi in altri continenti.
Il campo label serve invece alla barra di ricerca interna. Richiamandola con la scorciatoia di sistema puoi cercare uno snippet per descrizione, comodo quando la sigla esatta non ti viene in mente, e senza etichetta vedresti solo un poco leggibile {{data}}.
Tre opzioni meno note fanno la differenza nell’uso quotidiano. La prima è il segnaposto $|$, che indica dove deve finire il cursore dopo l’espansione, utile per i tag HTML, le parentesi o qualsiasi struttura in cui devi scrivere in mezzo.
- trigger: ":div"
replace: "<div>$|$</div>"
- trigger: "perche"
replace: "perché"
word: true
propagate_case: true
La seconda è word: true, che limita la sostituzione ai casi in cui la sigla è una parola isolata, delimitata da spazi o punteggiatura. Senza questa opzione, correggere perche in perché significherebbe rovinare qualsiasi altra parola che contenga quella sequenza di lettere.
La terza è propagate_case: true, che riprende il modo in cui hai scritto la sigla. Digitando Perche ottieni Perché con l’iniziale maiuscola, digitandola tutta in maiuscolo ottieni la versione tutta maiuscola.
Messe insieme, queste due opzioni trasformano il programma in un correttore automatico personalizzato, che funziona anche nei campi di testo dove il controllo ortografico non arriva mai, come le caselle di ricerca o i terminali web.
Se assegni lo stesso trigger a più snippet, il programma apre un menu di selezione e ti fa scegliere, il che è un modo elegante per gestire più varianti della stessa firma.
Se invece in una certa applicazione le espansioni escono monche o compaiono caratteri strani, quasi sempre la causa è il metodo di inserimento. Aggiungendo force_mode: clipboard allo snippet il testo viene incollato invece che digitato, e nella maggior parte dei casi il problema sparisce.
Moduli con campi da compilare al posto dei segnaposto
I moduli sono una funzione utile per chi prova o usa questo strumento per lavoro. L’idea è semplice, perché invece di espandere un testo fisso la sigla apre una finestrella con dei campi da riempire, e i valori inseriti finiscono nel punto giusto del testo finale. La sintassi breve usa le doppie parentesi quadre.
- trigger: ":preventivo"
form: |
Gentile [[cliente]],
in allegato il preventivo n. [[numero]] relativo a [[oggetto]].
Il documento è valido [[validita]] giorni dalla data di emissione.
Restiamo a disposizione per qualsiasi chiarimento.
form_fields:
oggetto:
multiline: true
validita:
type: choice
values:
- "15"
- "30"
- "60"
default: "30"
Digitando :preventivo compare il modulo, si compilano i campi (il tasto Tab passa da uno all’altro, Ctrl+Invio conferma) e il testo completo viene inserito dove si trovava il cursore. I controlli disponibili sono quattro, tra cui caselle di testo su una riga, aree di testo multilinea, menu a tendina con type: choice e liste con type: list, e ognuno accetta un valore predefinito.
Per chi gestisce assistenza clienti, risposte standard o documenti ripetitivi, questo elimina il passaggio più fastidioso, cioè recuperare il modello da qualche parte, incollarlo e poi rileggerlo per sostituire i segnaposto uno a uno.
Esiste anche una sintassi estesa, più verbosa ma più potente, in cui il modulo diventa una variabile come le altre. Serve nel caso in cui i valori raccolti non debbano solo finire nel testo, ma essere passati a un comando, che è esattamente quello che vedremo nella sezione seguente.
Snippet che eseguono comandi
L’estensione shell permette a uno snippet di lanciare un comando e usarne l’output come testo di sostituzione. Per impostazione predefinita usa PowerShell su Windows e bash su Linux, mentre su macOS adotta la shell configurata nel sistema. Il parametro shell consente di forzarne un’altra, incluso wsl per eseguire comandi Linux da Windows e nu per chi usa Nushell.
- trigger: ":ip"
label: "Indirizzo IP pubblico"
replace: "{{output}}"
vars:
- name: output
type: shell
params:
cmd: "curl -s https://api.ipify.org"
- trigger: ":pwd"
label: "Password casuale in base64"
replace: "{{output}}"
vars:
- name: output
type: shell
params:
shell: bash
cmd: "openssl rand -base64 18"
L’output viene ripulito da spazi e a capo in eccesso, comportamento disattivabile con trim: false. Se qualcosa non torna, debug: true scrive nel log il comando eseguito e l’eventuale messaggio d’errore.
La documentazione avverte, giustamente, di limitarsi a comandi rapidi. L’espansione resta in attesa finché il processo non termina, quindi un comando lento si traduce in una manciata di secondi con il cursore bloccato.
Il pezzo più curioso nasce combinando appunti e shell. Se hai già Ollama installato con un modello locale, puoi selezionare un testo, copiarlo e farlo riscrivere senza aprire nessuna interfaccia.
- trigger: ":riscrivi"
label: "Riscrive il testo negli appunti con un modello locale"
replace: "{{risultato}}"
vars:
- name: testo
type: clipboard
- name: risultato
type: shell
params:
shell: bash
trim: true
cmd: >
ollama run llama3.2 "Riscrivi il testo seguente in italiano corretto,
chiaro e conciso. Rispondi soltanto con il testo riscritto, senza
commenti. Testo: {{testo}}"
Il funzionamento è lineare, dato che la variabile testo legge gli appunti, il comando la passa al modello e l’output prende il posto della sigla. Su Windows la stessa cosa si ottiene sostituendo shell: bash con la sintassi PowerShell equivalente.
Due avvertenze, però. La prima è la latenza, perché anche un modello piccolo su una macchina discreta impiega qualche secondo, e in quel lasso di tempo non puoi digitare altro. La seconda riguarda le virgolette, dato che un testo copiato con apici o caratteri speciali può rompere il comando. Per un uso serio conviene spostare la logica in uno script esterno richiamato con l’estensione script, mettendolo nella cartella scripts/ accanto a match/ e riferendolo con il segnaposto %CONFIG%.
Uno snippet che esegue comandi è, a tutti gli effetti, codice arbitrario che parte quando digiti una sigla. I pacchetti pubblicati sull’hub ufficiale, installabili con espanso install lorem e aggiornabili con espanso package update all, passano da una verifica manuale. Quelli presi da fonti esterne no, quindi prima di aggiungerne uno alla propria configurazione vale la pena aprirlo e leggerlo, esattamente come si farebbe con uno script scaricato da internet.
Espanso: disabilitarlo dove serve
Un espansore attivo ovunque è utile finché non diventa un problema. Dentro un gestore di password, un terminale o un videogioco, una sostituzione inattesa può fare danni, e il programma prevede una soluzione, cioè le configurazioni per singola applicazione. Basta creare un nuovo file nella cartella config/, indicare la condizione di attivazione e cosa cambiare rispetto al comportamento predefinito.
# config/keepass.yml
filter_exec: "KeePass"
enable: false
# config/browser.yml
filter_title: "Mozilla Firefox|Google Chrome"
backend: clipboard
I filtri disponibili sono tre.
- Il filtro filter_exec lavora sul percorso dell’eseguibile.
- Il filtro filter_title lavora sul titolo della finestra, che nei browser coincide spesso con la pagina aperta.
- Il filtro filter_class lavora sulla classe della finestra ed è il più affidabile su Linux.
Tutti e tre interpretano il valore come espressione regolare, quindi la barra verticale funziona da “oppure”, come nel secondo esempio. Per scoprire cosa vede il programma nella finestra attiva basta digitarci dentro #detect#, che apre un riquadro con titolo, eseguibile e classe rilevati, da cui copiare il valore corretto.
Ci sono due limiti da tenere a mente. Solo una configurazione per applicazione può essere attiva alla volta, e in caso di conflitto vince la prima in ordine alfabetico di nome file. Su Wayland, inoltre, questa funzione non è ancora supportata, salvo il caso di KDE Plasma con kdotool installato.
Dato che tutto è testo, sincronizzare la propria libreria di snippet tra più computer richiede solo di trasformare la cartella di configurazione in un repository Git, oppure di collocarla in una cartella gestita da Syncthing o da un servizio cloud. Aggiungere uno snippet significa modificare un file di testo, e questo si integra con qualsiasi flusso di lavoro basato su versionamento. Chi condivide la stessa configurazione tra sistemi diversi può usare il filtro filter_os per separare le parti che valgono solo su Windows da quelle che valgono solo su Linux.
Vediamo il confronto con le alternative
| Strumento | Piattaforme | Costo | Limite principale |
|---|---|---|---|
| Espanso | Windows, macOS, Linux | Gratuito | Configurazione solo in YAML |
| AutoHotkey | Solo Windows | Gratuito | Richiede un linguaggio di scripting proprietario |
| Sostituzione testo di macOS | Solo macOS | Incluso | Si ferma al testo statico |
| TextExpander | Windows, macOS | Abbonamento | Snippet archiviati su server altrui |
Lo spazio occupato da Espanso è quindi abbastanza preciso, ovvero multipiattaforma, gratuito, tutto in locale, con una curva d’apprendimento iniziale che si misura in una mezz’ora di lettura.
Espanso: un investimento che ripaga in fretta
Espanso non è uno di quei programmi che si installano e si dimenticano. Chiede un impegno iniziale, ovvero capire la struttura delle cartelle, prendere confidenza con l’indentazione YAML e sbagliare due o tre volte prima che uno snippet complesso funzioni. In cambio restituisce qualcosa che cresce nel tempo. Dopo un mese la libreria personale contiene trenta o quaranta sigle.
Per ora il supporto Wayland resta sperimentale, con le configurazioni per applicazione fuori gioco e qualche attenzione in più sui layout di tastiera. L’assenza di un pannello grafico esclude una fetta di persone che non vogliono vedere un file di configurazione in vita loro. Inoltre su Windows manca ancora il supporto ad ARM.
Il consiglio pratico è di partire in piccolo, con cinque snippet per le cose che scrivi ogni giorno, un modulo per il testo ripetitivo che ti pesa di più, e solo dopo l’estensione shell. Le automazioni più creative arrivano da sole, nel momento in cui ti accorgi di aver appena digitato a mano qualcosa che avresti potuto richiamare con tre lettere.













