Icona dell'app Calíope

Com’è fatta Calíope

Lo stack, i confini e ciò che è stato lasciato fuori di proposito.

Questa pagina racconta com’è assemblata Calíope: su quali framework poggia, dove passa il confine con il motore, cosa permette la sandbox e cosa l’app non fa di proposito. Ogni cifra viene dall’albero dei sorgenti, a settembre 2026.

Un’app, tre binari

Calíope si distribuisce come una sola app, org.caliope.caliope, con acquisto universale: un acquisto copre tutti i dispositivi Apple su cui gira. Dietro quella sola app ci sono tre binari: uno per macOS, uno per iPhone e iPad (lo stesso binario serve entrambi, e l’app per Apple Watch viaggia incorporata al suo interno) e uno per Apple TV.

La maggior parte del codice non si scrive tre volte. Sources/Shared contiene 268 file Swift e 234 view SwiftUI che compilano sia nel binario per Mac sia in quello per iOS. I widget sono estensioni della stessa app e leggono ciò che l’app pubblica attraverso un App Group; l’app scrive, il widget legge soltanto.

SwiftUI da cima a fondo

Ogni finestra è SwiftUI nativo — nessuna web view, nessuna emulazione multipiattaforma. Quella frase è nella home page ed è letteralmente vera: le 234 view condivise sono SwiftUI, e dove un Mac e un iPad devono comportarsi in modo diverso, la differenza si decide in compilazione, nello stesso file, non in uno strato di compatibilità a tempo di esecuzione.

Il confine con il motore

Tutto ciò che parla con un motore di database vive dietro 15 protocolli in Sources/Models/Database/Protocols/, uno per sotto-area. Ogni motore ha un’implementazione di quei protocolli, e nulla sopra il confine — né una view, né l’orchestratore — scrive SQL o conosce i codici di errore di un motore. Aggiungere un motore significa implementare i protocolli, non modificare chi li chiama.

MySQL e MariaDB passano per MySQLKit 4.10.1, e PostgreSQL per PostgresKit 2.16.1 su PostgresNIO 1.33.1, tutto su SwiftNIO 2.101.0 (versioni a settembre 2026). Le query con parametri usano i binding nativi dei prepared statement di MySQLNIO: i valori viaggiano nel protocollo di rete e non vengono mai concatenati nell’SQL.

SQLite è diverso: l’editor SQLite parla con la libreria di sistema attraverso la sua API C, senza alcun driver in mezzo. MongoDB è diverso ancora. È supportato tramite MongoKitten 7.16.3, un driver della comunità, e resta fuori dal confine con il motore di proposito: nessuna view importa MongoKitten, e l’intero strato MongoDB è progettato per poter essere rimosso senza toccare il lato relazionale.

SSH senza ssh

Il tunnel SSH è scritto dentro l’app, su SwiftNIO SSH 0.13.0 e swift-crypto 3.15.1. Nessuna dipendenza dall’ssh di sistema. Le chiavi decifrate non vengono mai scritte su disco.

Calíope legge da sé le chiavi private OpenSSH, accetta ed25519 ed ECDSA P-256, P-384 e P-521, verifica la chiave dell’host prima di inviare qualsiasi altra cosa e apre un canale direct-tcpip fino al database. Dal tuo lato ascolta su 127.0.0.1, su una porta scelta all’apertura del tunnel, e la connessione al database passa per quel proxy locale. Una chiave protetta da passphrase viene decifrata in memoria, e lì resta.

Dentro la sandbox

Calíope gira con l’App Sandbox attiva, come richiede il Mac App Store, e Caliope.entitlements chiede esattamente questo:

  • com.apple.security.app-sandbox
  • com.apple.security.network.client — le connessioni in uscita verso i tuoi server
  • com.apple.security.network.server — i listener locali: il proxy del tunnel e il server MCP
  • com.apple.security.device.audio-input — la dettatura, che gira sul dispositivo
  • com.apple.security.files.user-selected.read-write — i file .sql che apri e le cartelle che scegli per i backup
  • com.apple.security.application-groups — il contenitore condiviso da cui leggono i widget
  • iCloud: CloudDocuments, CloudKit e l’archivio chiave-valore, per la sincronizzazione che puoi attivare

E ciò che non c’è: nessun accesso all’intero file system, nessuna eccezione alla validazione delle librerie, nessun JIT.

IA e MCP alle tue condizioni

L’assistente IA ha tre tipi di provider. Apple Intelligence passa per il framework FoundationModels di Apple, sul dispositivo, senza chiave e senza account. Ollama gira sulla tua macchina, con i modelli che ci hai installato. I provider cloud funzionano con la tua chiave. L’app decide come parlare con un provider in base alle capacità che dichiara, non al suo nome. È un assistente, non un agente.

Il server MCP, su macOS, capovolge il verso e lascia che un client IA esterno — Cursor, Claude Desktop, qualunque cosa parli MCP — interroghi Calíope sui tuoi database, entro dei limiti. È spento di fabbrica. Ascolta solo su 127.0.0.1, sulla porta 41500 a meno che tu non la cambi, e quell’indirizzo non è configurabile. Ogni richiesta ha bisogno di un token Bearer che Calíope genera (32 byte casuali) e conserva nel Portachiavi. Il client vede solo le connessioni che esponi esplicitamente, e quella lista nasce vuota. È in sola lettura: un’istruzione per chiamata, controllata da una porta che rifiuta anche FOR UPDATE e LOCK IN SHARE MODE, e i risultati sono limitati a 200 righe. Cinque strumenti, JSON-RPC 2.0 su una sola rotta POST /mcp, versione di protocollo 2025-06-18. Nessuno dei due consensi — né l’interruttore né la lista esposta — si sincronizza su un altro dispositivo né viaggia in un backup delle impostazioni. La pagina del server MCP elenca i cinque strumenti e spiega come puntarci un client.

Ciò che di proposito non fa

  • Né Windows né Linux. Calíope è scritta per le piattaforme Apple e lì resta.
  • Né SQL Server, né Oracle, né Redis. I motori sono MySQL, MariaDB, PostgreSQL, SQLite e MongoDB.
  • Né spazi di squadra. Non c’è un nostro server né account; i tuoi profili e la tua cronologia sono tuoi, e la sincronizzazione iCloud è un’opzione tra i tuoi dispositivi.

Se hai bisogno di una di queste tre cose, il confronto nella home page nomina gli strumenti che la fanno bene.