SSH tunnel
The SSH Tunnel toggle reaches a database behind a bastion with Calíope’s own SSH client, and the profile’s host and port become the database as seen from the bastion.
Every capability, verified against the source code.
Calíope ships as a single application with the capabilities below available on Mac, iPad, iPhone and Apple Vision Pro. Every entry corresponds to code that exists today — this is a catalogue, not a wish list. Use the shortcuts to jump to a category, or scroll through the full list.
This page describes Calíope 1.8, the version I am building right now. 1.7 is on the App Store for the Mac, iPad, iPhone, Apple Watch, Apple TV and Apple Vision Pro. The changelog says which version each feature landed in.
The SSH Tunnel toggle reaches a database behind a bastion with Calíope’s own SSH client, and the profile’s host and port become the database as seen from the bastion.
Before trusting a bastion, Calíope shows its SHA256 fingerprint, says whether it is new or has changed since the last time, and waits for you to trust it or update it.
The SSL / TLS toggle encrypts the connection, verifies the server against the system authorities or a CA file, and takes an optional client certificate and key.
Passwords, SSH passphrases and API keys live in the Keychain, never in a file, and they go to iCloud Keychain only if I turn on that separate switch.
With the switch in Settings on, Connect first asks for Touch ID, Face ID or Optic ID, and if it fails the connection does not go ahead.
When the main host does not answer, the alternate address is tried with the same port and credentials, and the session says it came in that way.
A catalog of tags with your own name and color, started from Local, Staging or Production if you like, marks each connection with the environment it belongs to.
Each tag carries a protection, none, confirm what writes or read only, that the session guard applies to every statement that writes, whichever tool sends it.
With this toggle on, changing the active database over a cut connection reopens the whole session, SSH tunnel included, and repeats the change.
Offers keywords, functions, databases, tables and columns of the session while I type, with the vocabulary of its dialect.
Underlines unclosed strings, comments and parentheses while I type, and warns of a full-width space, without sending anything to the server.
Re-indents the SQL in the editor with the dialect of the session.
Blocks statements that change data, structure or privileges until I turn it off; it is on by default.
Builds a WHERE clause for a table from its columns, operators and values, without writing it by hand.
Writes the JOIN between the tables on the canvas from the foreign keys the server declares, and where there is none it adds the table as a CROSS JOIN with a comment.
Renames an alias, CTE or variable and every reference to it in the script.
Jumps to any table, view or routine of the active schema by typing part of its name.
The first time you open it connected to an engine, I add that engine's sample snippets, once per engine.
Shows the DDL of a table, view, routine or trigger when the pointer rests on its name.
Shows the card of the engine's function under the cursor, with its signature and an example that runs on that engine.
Edits a long, JSON, binary or spatial value in a sheet with text, tree, hex, Base64 and image tabs.
Runs the script one statement at a time with play, pause and step controls.
Opens a terminal-style panel with a prompt and its own history to run SQL interactively.
Draws the result as a bar, line or pie chart, choosing the label and value columns.
Connects a second database and runs each query on both, showing the two results side by side with the differences marked cell by cell.
Reorders the button groups of the editor, results and main toolbars, and resets them.
I type a text and press Find, and every text column of the ticked tables is scanned with live progress by table and a final count of matches.
Draws the result's spatial column on a map, and moves, adds or clears a geometry by proposing the UPDATE before applying it.
In the output sheet I hide, reorder and retitle columns and give each a format and an alignment, without rewriting the query.
In a sheet I declare each parameter with name, type, label, whether it is required and its default, and it offers me the placeholders the query already uses so I add them with the exact name.
Before the final SELECT I can set session variables and build and fill temporary tables, all on one connection; anything outside that closed list is rejected with its statement number before anything runs, and the temporaries are dropped at the end.
I export what the output declares to CSV, TSV, JSON, XML, Excel, HTML, Markdown, text or a paginated PDF, always through the system save panel.
I schedule a report daily, weekly, on weekdays, monthly or every N hours; it runs even with the app closed wherever the system allows it, catches up once if its time passed without it being able to run, uses each parameter’s default, and records a skipped run with its reason.
Every run leaves its row with status, trigger, parameters, rows, duration, device and address; I filter, search, copy, delete or clear it, it stays on this device and rows older than 180 days are deleted.
Shows the DDL the server returns for the chosen object in the bottom panel, with syntax colouring.
Copies the whole script that turns the source into the target, with tables first, foreign keys in their own block and the other objects ordered by dependency, to run in the SQL Editor.
Lists the structure changes (CREATE, ALTER, DROP) run from Calíope, with when and where.
Creates each checked object in the target over a single connection, with progress and a stop between one object and the next, writes one log line per object and creates the foreign keys at the end.
Creates or replaces a procedure or function from a form with its parameters, return type, options and body, and shows the DDL it will run.
Shows, with syntax highlighting, the CREATE TABLE or ALTER TABLE my changes produce, follows each edit and says in a comment what the engine cannot do.
Rebuilds or compacts each checked table with the server's own operation and reports what it did.
Shows each scope as a card with its privileges grouped by what they allow, an ALL PRIVILEGES switch and WITH GRANT OPTION, and on Save runs the REVOKE and GRANT needed, with the server's rejections next to the button.
Reads the plan of the selected query, detects full scans that filter by a column, and proposes the CREATE INDEX to copy or insert.
Creates or rebuilds an index on the chosen table with its kind, method and ordered columns, and shows the DDL it will run.
Computes the statistics of a result column: minimum, maximum, average, NULLs, distinct values and the most frequent ones.
Draws every base table of the chosen database as a node with its columns, types and key glyphs, joined by the foreign keys the server declares, and reloads when I pick another database here or in the schema tree.
Draws each document as a card with its _id and number of fields, and each field with its key, its value and its type, unfolding nested documents and arrays.
The pencil opens the whole document as extended JSON, Format reindents it and checks that it reads, and saving replaces it on the server by its _id.
In Aggregate mode I write the whole pipeline as a list of stages, and a pipeline that isn't a list, or a stage that isn't a document, is caught before anything is sent.
New index opens a sheet with the name, the keys written as a document, the switches for no repeated values, sparse, expiry and hidden from the planner, an optional partial filter and a collation with its strength, and if the server refuses it its message stays in the open sheet.
Operations lists each operation in progress with its type, its namespace, the seconds it has been running and the connection it comes from, and marks the ones waiting for a lock.
Run (⌘↩) sends the document as it is and the reply arrives as a tree, folded each time, so I can ask for statistics, validate a collection, change a server parameter or set a validator without opening mongosh.
The list shows the last 200 operations of system.profile, newest first, with time, operation, namespace and milliseconds and, when the server records them, the plan, the documents and keys examined, the documents returned and the client; the footer says when the batch reached its ceiling.
I ask the server for the keys with SCAN, a batch at a time and never with KEYS, and the footer says how many I have walked and whether the walk finished.
I show the value according to its type and read a large one in chunks with a button for the next one, always saying how much of how much is on screen.
Analyze walks the keys of the database with SCAN, measures each one with MEMORY USAGE and adds up what it measured by prefix, splitting the names by the same separator as the key browser.
I show used_memory with its maxmemory limit and the percentage, or that there is no limit, plus the eviction policy and the peak.
KEYS, MONITOR, the subscriptions, SHUTDOWN, DEBUG, the protocol switches, SELECT and the transactions are not sent: the output gives the reason of each one, and below it What not to do opens the DBA Handbook topic.
I list what the server logged: when it started by the server’s clock, with its time zone, how long it ran, the command on one line with an AUTH masked, and the client when the server sends it.
Every open connection shows its name, id, address, time connected, time idle, database, last command, flags and memory. On the Mac it is a grid; outside the Mac each client is a row with the same data labelled, stacked at accessibility sizes.
Diagram draws one box per node, grouped by shard: the primary on top with its slot range, an arrow, and its replicas underneath with their lag. A node that hangs from no known primary goes alone, without guessing whom it follows.
I send the statement at the consistency level you pick, LOCAL_ONE unless you change it. Without a selection ⌘↩ runs the whole text statement by statement (a BATCH goes whole); with one, only the selection. Writes pass the session’s environment guard first, and a write says it was applied: CQL doesn’t count rows. If the server answers with an error the DBA Handbook explains, View solution opens its chapter: consistency for Unavailable or a timeout, roles and permissions for Unauthorized, common errors for the rest it covers, syntax included.
With Trace on, the server records the statement’s trace and I show its id, which opens it in Traces.
I show the most recent slow queries ScyllaDB recorded, with their duration, tables, user and node, and open the trace of each one.
From the table's rows I insert a row, change its regular columns or delete it, always by the whole key, with a lightweight transaction that says whether it was applied, and through the session's environment guard.
I list every node with its data center, rack, status, version and tokens, and say whether they all agree on the schema.
For the user’s tables I show how much each takes up, its largest partitions and, in Cassandra, its read and write latency as seen by this node.
I list the connections open on the node with address, user, driver, protocol and TLS, and mark the one Calíope is using.
I grant a permission on all keyspaces, a keyspace, a table, all roles, a role or all functions, and revoke one of the role’s own permissions.
I send your search to the indices you choose, in Query DSL or in SQL, and in ES|QL on Elasticsearch or PPL on OpenSearch, and show the hits as documents or as a table.
On Elasticsearch I ask the server to translate your SQL into Query DSL and open it in the Query DSL mode, with the index of its FROM.
I write a document as JSON, with your _id or one from the server; editing replaces the whole document, and only if nobody changed it since it was read. Deleting asks first and names the _id. Every write goes through the session’s guard, and in a read-only session I don’t offer it.
Restore… on a complete snapshot opens a sheet that picks its indices, proposes restored_ in front of each name and leaves the global state off; the server refuses to restore over an open index with the same name, and the sheet shows its text.
I show the cluster health with its glyph and name, how many nodes answer, where the shards are and why one is left unassigned.
For the node you pick I show the JVM heap with its maximum, the young and old garbage collections, the machine’s and the node’s CPU, the disk the node can still use, and the search and indexing rates over the last interval, read every five seconds while the tab is in front.
On a task the server marks cancellable, I ask it to cancel after a confirmation that names the action and the node; a task that had already finished says so, and the cluster’s own persistent tasks and this very list are not offered.
I list your API keys that are still valid, create one with a name and an expiration and show it once with a copy button, and invalidate one after a confirmation.
I open a local database file without any server, also when it arrives from outside the app, and I mark it read-only when it cannot be modified.
I create one view per chosen CSV, JSON or Parquet file, read on the fly each time you query it without copying its data into the database, and I open an in-memory database first if none is open; a Parquet file opened from the Finder or shared from the Files app also arrives here, with its query written in Execute SQL.
Shows a local file interpreted by its extension without editing, saving or running anything, and opens even when no server is connected.
The system’s Quick Look shows a SQLite or DuckDB database, a Parquet file and, on the Mac, a TSV file as tables with their first 20 rows, without opening Calíope and without writing anything next to the file.
The system's language model answers on the device itself, with no key and without the question leaving it, and is offered only where the system says it is available.
Talks to an Ollama server at the address I write —this Mac or one on my network—, with no key, and says so when nothing answers there or the address is not valid.
The settings panel chooses among OpenAI, Google Gemini, Anthropic Claude, Apple Intelligence and Ollama, and draws only what the chosen one needs: the key for the cloud ones, kept in the Keychain.
With the switch on and a database chosen in the header, the names of its tables, columns and foreign keys travel with the question —never rows—, and the panel says which of three states applies.
The microphone transcribes the question on the device itself, in a language I can choose beside it, and says when that language's model has to be downloaded first.
A side panel keeps each conversation from its first question, searchable over every turn, to resume, copy or delete one by one or all at once, up to the 200 most recent.
A switch in Settings starts or stops the MCP server at once; it is off until you turn it on, and it starts again with Calíope while it stays on.
Before touching the server, run_query rejects anything that is not one reading statement, and also SELECT … FOR UPDATE and LOCK IN SHARE MODE.
Dumps the checked objects to a .sql or .sql.gz file in the background, object by object and with bounded memory, with a log, a progress bar, the estimated time left and a Cancel button that removes the partial file.
Gives a backup its name, its connection (required in a new one), its frequency (daily, weekly, weekdays, monthly, every N hours or on demand) with its hour, and the destination folder chosen with a persistent permission.
Keeps only the last N files of each scheduled backup in its folder, from 1 to 30 or all of them, and deletes the oldest after each run.
Runs a .sql or .sql.gz file against the server in a single session, after a summary with the statements found, the databases affected and a warning if it drops objects, stopping at the first error and naming the statement that failed; meanwhile it says how many statements it has run and which table it is on, and at the end it leaves a system message and, with the app in the background, a notification.
Imports a CSV, JSON or Excel file into a table in three steps, mapping columns and choosing the insertion mode.
Keeps every statement I run, from this session and earlier ones, in a file on disk, with its number, date, connection, status, statement and what the server answered.
Shares the log between my devices through iCloud when I turn it on with the cloud button, warning that the statements travel as written.
«Sync Calíope with iCloud» moves my connections, editor tabs, monitoring, reports, snippets and preferences to iCloud after asking, and turning it off asks too.
«Export…» writes a JSON file with what I choose —connections, editor state, preferences, history— and passwords only if I tick them, encrypted with a key I type.
On a narrow screen the first tools of my order go in the system bar at the bottom, and the rest under More.
Calíope on the watch reads from iCloud the messages your devices publish, with a list and a detail, works without an iPhone nearby and writes nothing anywhere.
Calíope on the Apple TV shows as tiles the servers your devices publish, with a summary by severity, each state with its own shape, and it opens no connection and runs no query.
On Apple Vision Pro the tool navigator, the open tabs and each tool’s bar float outside the window in their own glass, so the whole window stays for the content.
On Apple Vision Pro, opens the diagram in an immersive space around you, with the Calíope window still in view, and closes it from the same button. Each table is a card with its columns and keys, and each schema has its own layer, behind the previous one. Each foreign key is a line from its column on one card to its column on the other, and a line between schemas crosses from one layer to the next. Save layout keeps the 3D layout on this device, one per database (it is not synced), and the space opens with it next time; what has no saved place comes from the 2D diagram. + DB with the space open adds its layer without closing it, and the space closes by itself when its session disconnects or closes, which the tab then says; opening it from another session closes that one first. While it is being built, the tab and the space's panel say “Loading 120 tables…” with the time so far. With many tables the cards are stacked in rows so none covers another, and above 200 tables the space opens without lines and shows only the selected card's. The cards and the panels grow with the text size, and the stack follows; VoiceOver reads each card as its table, database, number of columns and relationships, says which one is selected and which are related to it, and reads each column with its full type and its key.
Picks which saved connection holds the history and creates its schema and tables there, saying whether it worked.
Draws the plan the server gives for the query, without running it, as a tree of cards with the object, the access type, the estimated rows and the detail the engine adds.
Breaks the last query down into the server's internal phases, with the time spent in each.
Lists the executions the server recorded, from the slowest down, with time, user, database, duration and rows, plus the columns this engine publishes.
From a row's menu, ends the whole connection or cancels only its running query after asking me, and says it when the server refuses and why.
Shows four cards for the server I'm connected to: the IO thread and the SQL thread with the word the server reports, the lag in seconds coloured by threshold (and «No reading» when the server has no figure), and the source server it reads from.
I name the group and pick, from my saved connections, the primary and its replicas in the order I want to see them, with its polling interval; only connections whose replication the tool can poll are offered, and it needs at least two.
Shows each event with its type, start and end position, its class and the Info field, which I can select and copy.
Line card with the rate of statements the server runs, or of transactions where the engine counts those instead, each under its own name.
The Info tab gathers what identifies the server and my connection: version, host, port, data directory, character set and collation, connection limit, and my connection's id and user.
Runs the query N times and reports the minimum, average and maximum time.
The bell opens Server alerts, where system notifications are turned on and thresholds are set for connections against the maximum, cache hit rate and replication lag.
Lists each rule with its query, column, condition, the value measured in this session and its state, and the footer counts how many are on alert.
A panel shows what is running in every session, the active modes and the latest finished operations with how each ended (a failure with the server’s reason), with Go to and, when the operation allows it, Stop.
When the error has a help topic of its own, takes you from the row or its detail straight to that topic.
Shows connections, throughput, uptime, threads, slow queries and cache hits of one server on the desktop, the Home Screen, the Lock Screen or a wall, in the sizes each place offers.
Shows the worst state of the servers the health monitor watches and how many need attention, in three sizes, and opens the health monitor when tapped.
Each placed widget has its own Server parameter, filled from a minimal catalogue of profiles that Calíope writes to the shared container, so several widgets can watch different servers.
Tapping or clicking the metrics widget opens Calíope on the dashboard of the server that widget has chosen, connecting first if there was no session.
A green, red or amber badge with its own symbol says whether the data is current, the server stopped answering, or more than three times the write cadence has passed with a floor of 90 seconds.
Settings › Widget keeps a pinned profile refreshed without the dashboard open, every 30 seconds or 1, 5 or 15 minutes, opening a short connection on each turn.
The four actions come ready to use, without building a shortcut: Siri recognizes their phrases in each language, and Spotlight and the Shortcuts app suggest them.
Loads a .sql file into the SQL Editor, from the File menu with ⌘O or by opening the file from Finder or Files.
Puts a cylinder in the macOS menu bar with Open window, which brings Calíope to the front, and Quit.
Each time I open a tool, at most one help bubble appears next to the control it explains, in an order that puts first the ones that prevent a mistake; once shown it is spent.
Answers a click, a double click, a long press or a right click on a cell or a column header with its own action: see the value, generate the UPDATE, the cell menu, sort or resize.
I capture the Calíope window at a preset or custom size, fitting or filling a different aspect ratio, with a timer, and save it or copy it.
The first time a new version opens, the What’s New window lists what it brings and the earlier versions; on the Mac it reopens from the Help menu, and everywhere from its Help topic.
Opens in the system browser, in the language of the app, the page I made for people coming from it —what’s new, the Help, the DBA Handbook, data to practise with, the videos and the blog, with a search across the Help, the Handbook and the blog—, without opening a tab and without sending the version.
General tells me which of the six languages Calíope is in and takes me to the system setting where I choose it per app, because there is no picker inside the app.
«Delete All My Data» asks first, erases what Calíope keeps on this device, in the Keychain and in iCloud, and then shows place by place what was deleted and what failed.
Never stores a password, not even truncated, and names the server by its profile alias instead of host, port and user.
Calíope records nothing until I turn on «Keep a usage report on this device», and then counts events, errors and tool openings in a file that stays here and that I can clear.
Every code block carries at its foot that it was generated by AI and must be checked before running, and the name of the provider it was sent to.
Starts the 30-day trial with everything unlocked on every device with the same Apple ID; it asks for no card, never turns into a charge and can only start once per Apple ID, and an account that already has the 60-day trial does not start another.
The purchase screen lists what the purchase unlocks —the engines, unlimited connections, SSH and TLS, the editor, the assistant, backups, monitoring and diagrams— with the “?” that opens its Help topic.
Every capability on this page ships with the one-time purchase. Thirty days free, then buy once and keep it forever.