Query Editor
Table of contents
Overview
The query editor provides SQL editing with syntax highlighting, auto-completion, bracket matching, code folding, query variables, and multiple tabs. Each editor tab is a stack of query cards, one statement per card. The editor occupies the top portion of the content area, above the results.
Editor Toolbar
The editor toolbar is the row above the cards. It starts with the tab’s context row: its connection › schema, the connection’s state and the transaction chip. After it come Format (SQL formatter), Describe the query… (see Apple Intelligence), a Save dropdown (Save / Save As… / Export as SQL File…) and New Card. Pinned to the right are the Filter Cards search field, the error badge and the Collapse All Cards / Expand All Cards button. The window toolbar above holds only window-wide items: the navigator selector (a grouped set of three icons over the sidebar) and the inspector toggle. To run and cancel queries, use each card’s Run and Cancel buttons or the Query menu (see Query Execution); choose View > Customize Toolbar… to add Format, New Tab, Save Session, Connections (opens the Connections Manager), a sidebar filter field or a plain sidebar toggle to the window toolbar. A contextual Format as SQL list button appears after pasting a bare list of values (see below).
The context row
The context row says which database and schema this tab uses, and what its connection is doing. It belongs to the tab: changing it changes no other tab. From left to right:
- the Connection pop-up button. It lists the files this tab and other tabs opened (Open Files), then the saved PostgreSQL and DuckDB connections, each with its state, where it is, and an SSH or Read-only badge (see Connections); its last item is Manage Connections…. Choosing a connection that is not connected connects it at once. When the tab has an open transaction, choosing another connection asks first: Roll Back and Switch or Cancel. A tab with no connection shows Choose Connection and “Choose a database for this tab.”;
- ›, then the Schema pop-up button. It opens the searchable schema list, with All Schemas and Set as Default Schema (see Schema Selector);
- the connection’s state: Connected; Not connected with a Connect button; Connecting… with a spinner; or Could not connect with a Try Again button. Rest the pointer on Could not connect to see the reason;
- the transaction chip, while the tab has an open or failed transaction, or after its connection was reset (see Transactions).
Query variables are edited in the Variable Manager window, not in the editor.
Query Cards
Each editor tab is a stack of query cards. A card holds one statement and owns that statement’s results. The results area below the editor shows one card’s results at a time (see Results Grid).
The name row
Each card has a name row above its SQL. From left to right it shows:
- the card’s name — click it to rename the card inline, or choose Rename… from the card’s ⋯ menu or its right-click menu. A card with no name reads “Untitled query”;
- a version chip (v2, v3…) when the card has earlier versions;
- the metadata of its last run: when it ran, how long it took, and how many rows it returned;
- a large View Results button. It reads Showing Results · N rows, and is filled, while that card’s results are on screen;
- Run, and Run and Replace Results (shown only after you edit a card that has results). Both are greyed out while the tab has no connected database. Rest the pointer on a greyed-out button, or click it, to see why and how to connect;
- Cancel, while the card runs;
- the Notes button (see Notes);
- the ⋯ menu.
With Apple Intelligence on, a card with no name gets a suggested name at its first run. A name you type always wins.
Notes
Every card can keep notes: why the query exists, how to read its results, what to compare them with. Click the Notes button, left of ⋯, or choose Show Notes from the ⋯ menu. The notes open to the right of the SQL; click the button again to close them. The button’s icon is filled when the card has notes and hollow when it has none.
- Notes belong to the query, so every version of it shows the same notes, and a new version keeps them.
- Drag the line between the SQL and the notes to make the notes wider or narrower; double-click the line to go back to the default width. Each card keeps its own width, saved with the tab and with Sessions. The notes stay at least 180 pt wide, and the SQL at least 240 pt.
- The card grows to fit its notes, as it grows to fit its SQL.
- Notes are saved with the tab, with Sessions and with each run in Results History, and the history filter finds text in them.
- Notes are plain text. When you save or export the tab as a
.sqlfile, they are written as a comment above the query.
Size and scrolling
A card grows to fit its text and its notes, so you never scroll inside a card vertically: only the stack scrolls. With Wrap long lines off (the default, in Settings > Editor), a long line makes the card scroll sideways on its own.
To give a card more room (for example to write long notes beside a short query), drag its bottom edge down. The card keeps that height, and grows past it when its SQL or notes need more. Dragging the edge up never makes a card shorter than its content. Double-click the bottom edge to fit the content again. With VoiceOver, the bottom edge is a splitter: increment and decrement change the height by 24 points.
Versions
Running a card that has results after you edited it keeps the old results:
- The old card is locked with its SQL and its results.
- The edited SQL goes into a new version card below it (v2, v3…), and that card runs.
- Older versions fold into one row above the newest (“2 earlier versions of name”). Click the row, or its chevron button, to show them. The row then stays above them as their header; click it again to fold them. A run that makes a new version folds the older ones again.
A run with no edit replaces the card’s results in place. A failed or cancelled run never locks the card; the next run tries again in place. Run and Replace Results (Cmd+Shift+Return) replaces the results in place even after an edit, and makes no new version.
“Edited” compares the SQL after `` substitution. So a locked card run again with different variable values also makes a new version.
Adding, moving and deleting cards
- New Card (Ctrl+Cmd+N, Query > New Card, or the toolbar button) adds a card below the focused one. New Query Card at the end of the stack adds one at the end.
- To add a card between two cards, move the pointer into the gap between them and click the + that appears. A card’s More (⋯) menu also has New Card Above and New Card Below.
- To move a card, drag it by the grip (≡) at the start of its name row; a line shows where it will go. Press Escape during the drag to cancel. You can also choose Move Up / Move Down in the card’s ⋯ menu, or Query > Move Card Up / Move Card Down (Option+Ctrl+Cmd+Up / Down) for the focused card. A query’s earlier versions move with it.
- Moving and inserting are off while a filter is typed.
- Ctrl+Cmd+Up / Ctrl+Cmd+Down (Query > Previous Card / Next Card) move the focus to the previous or next card.
- The chevron button at the start of a card’s name row folds the card to its name row (chevron points right), which then shows the start of the card’s SQL on one line or opens it again (chevron points down). If an opened card reaches past the bottom of the editor area, the cards scroll so its top is at the top of the area.
- Query > Collapse All Cards / Expand All Cards, or the toolbar button, collapses or expands every card.
- Cmd+Z undoes adding, moving, deleting or renaming a card. Because of this, deleting a card asks no confirmation.
Other actions also add a card to the active tab:
- Select part of a card’s SQL and press Cmd+Return: with ⌘↩ runs set to The selection, else the statement in Settings > Query, the selection runs as a new, generated card (see Running Cards).
- View All Contents and View Contents (Limit…) in the schema browser, and the drill-down of a server-aggregated chart, add a new card.
- A draft from Describe the query… goes into the focused card when it is empty, otherwise into a new card (see Draft SQL).
Filtering cards
Type in the Filter Cards field in the editor toolbar to show only the cards whose name or SQL contains the text. While a filter is typed, the text to the left of the field shows how many cards it shows out of all the tab’s cards (“6 of 9 cards”; every version counts). Each tab keeps its own filter.
Find
With a card focused, Edit > Find (Cmd+F, Cmd+G, Cmd+Shift+G, Cmd+E) searches all cards of the tab, with one find bar at the top of the cards. To find in the results instead, click into the grid first (see Find in Results).
- The bar searches every card the editor shows, collapsed cards too (a collapsed card opens when a match in it becomes current). It does not search cards that Filter Cards hides, or older versions folded into their row.
- Every match is highlighted in its card, and the current match is highlighted more strongly. The highlights are drawn with the text, so they stay on it while you scroll.
- The magnifier menu in the search field sets how text matches: Contains, Whole word or Regular expression, and Match Case. An invalid regular expression shows Invalid pattern in red.
- Return goes to the next match and Shift+Return to the previous one. Done or Escape closes the bar and selects the current match in its card.
Find and Replace
Edit > Find > Find and Replace… (Cmd+Option+F), or Replace in the bar’s pop-up, adds a second row:
- Replace (or Return in the replace field) replaces the current match and goes to the next one.
- Replace All replaces every match in All Cards or in This Card (the pop-up beside the field). The bar then shows how many it replaced.
- With Regular expression, the replacement can use
$1,$2… for the pattern’s groups. In the other modes, the replacement is put in as typed. - A locked version (a version that holds results) keeps the SQL its results came from: Replace and Replace All leave it as it is, and say how many versions they skipped.
- One Edit > Undo (Cmd+Z) in the focused card takes back the whole Replace All, in every card. Click into a card first: with the keyboard in the find bar, Cmd+Z undoes typing in the bar.
VoiceOver
A Query Cards rotor moves card by card. Each card has the actions Move Up, Move Down, New Card Above and New Card Below (VO-Command-Space).
Syntax Highlighting
The editor highlights SQL in real time:
| Element | Color | Examples |
|---|---|---|
| Keywords | Blue | SELECT, FROM, WHERE, JOIN |
| Functions | Teal | count(), avg(), now() |
| Strings | Green | 'hello', $$body$$ |
| Numbers | Orange | 42, 3.14 |
| Comments | Gray | -- comment, /* block */ |
| Types | Purple | INTEGER, TEXT, BOOLEAN |
| Variables | Indigo (defined), Red (undefined) | `` |
Auto-Completion
The editor provides context-aware auto-completion for database objects:
- Trigger with Ctrl+Space to open the completion list at any time
- Type a dot (e.g.,
public.) to automatically trigger completion with objects from that schema - Navigate the list with Up/Down, accept with Return or Tab, dismiss with Escape
Suggestions come from the connected database’s schema metadata: schema, table, and column names.
Brackets and Quotes
- Matching: placing the cursor next to
(,),[,],{, or}highlights the matching bracket, skipping brackets inside strings and comments. - Context-aware auto-close: typing
(,[, or'inserts the closing character — but only when the cursor is at the end of a line or before whitespace or a closing delimiter, so typing in front of existing text doesn’t inject stray pairs. An apostrophe typed after a letter or digit stays a single'. - Selection wrapping: with text selected, typing
(,[, or'wraps the selection instead of replacing it. - Skip-over: typing a closing character that’s already under the cursor steps over it; Backspace on an opening bracket removes both characters when the close is adjacent.
Opening and Saving SQL Files
- File > Open… (Cmd+O) opens
.sqlor plain-text files; you can also double-click SQL files in Finder, drop them on the Dock icon, or drop them onto the editor. Each file opens in its own tab (see Where opened items go). Files over 50 MB prompt before opening. - Opening a file splits it into one card per statement. A
-- name: Xcomment line gives the card below it the name X. - A comment block between two lines of
=(the form Pharos writes, below) right before a statement becomes that card’s notes. - Other comments before a statement stay in the SQL. The card’s Notes button then reads Import Comments to Note: click it to move those comments into the notes, without their
--,/* */and=border lines. Choose Keep Comments in Query from the ⋯ menu to leave them where they are. - psql meta-commands (such as
\set …) and the data of aCOPY … FROM STDINbecome cards that Pharos shows but does not run. - A tab opened from a file stays linked to it: Cmd+S writes straight back to the file, and the tab shows a dirty indicator for unsaved edits.
- Saving writes each card as a
-- name: Xline followed by its statement. Locked earlier versions are kept as comments (-- version: 1 locked), so psql runs only the current versions and nothing is lost. -
A card’s notes are written between its
-- name:line and its statement, as a/* … */comment with a line of=above and below them:-- name: New JA4T Fingerprints /* ===================================================================== Q8. NEW TCP CLIENT FINGERPRINTS (JA4T) FROM THE HONEYPOT Compare first_seen with the times from Q2 and Q5. ===================================================================== */ WITH params AS (A
/*or*/inside the notes is written as/ *or* /, so it cannot end the comment early. - File > Export Query as SQL File… (Cmd+Opt+S) saves any tab’s SQL to a new
.sqlfile (with query variables rendered into the output). Variables are rendered in the SQL only: `` tokens in notes are written as you typed them, and stay as they are when you open the file or import comments into notes.
The “Run in Pharos” Service
Select SQL in any app that offers macOS Services — a text editor, a browser, Mail — and choose Services > Run in Pharos from that app’s menu (or from the right-click menu). Pharos comes forward and opens the selected text in an editor tab (see Where opened items go). The name is the macOS convention for the item; Pharos does not run the query. Read it, pick the connection, then press Run as usual. An empty selection does nothing.
Tab Management
Every editor tab is a native macOS window tab, grouped the way Safari and Finder group theirs. The system tab bar appears when a window has two or more tabs; View > Show Tab Bar shows it always. Its + button and File > New Tab (Cmd+T) add a new, empty tab beside the current one, with the same sidebar and inspector layout. The new tab has no connection: choose its database in the tab’s Connection pop-up.
| Action | Shortcut |
|---|---|
| New Tab | Cmd+T |
| Close Tab | Cmd+W |
| Reopen Closed Tab | Cmd+Shift+T |
| Rename Tab… | Cmd+Opt+R |
| Switch to Tab 1–9 | Cmd+1 through Cmd+9 |
| Show Next Tab / Show Previous Tab | Cmd+Shift+] / Cmd+Shift+[ (or Ctrl+Tab / Ctrl+Shift+Tab) |
| Show All Tabs | Cmd+Shift+\ |
Cmd+1 to Cmd+9 show the first to ninth tab of the window’s group. Reopen Closed Tab works across every window and remembers up to 20 closed tabs.
To rename a tab, right-click (or Control-click) the tab and choose Rename Tab…, choose File > Rename Tab… (Cmd+Opt+R), or right-click the tab’s context row (the connection and schema above the cards) and choose Rename Tab…. Renaming a tab that is not in front brings it to the front first. The rest of the tab’s right-click menu is the system’s own: Close Tab, Close Other Tabs, Move Tab to New Window and Show All Tabs. File > Duplicate Tab (also on the context row’s right-click menu) puts a copy of its cards in a new tab beside it, without their results. Double-clicking a tab does not rename it.
Tab names
A new tab is called New Tab 1, New Tab 2 and so on, with the lowest number no open tab uses. When the tab gets a connection, its name becomes the connection’s name and the schema, for example Prod - public, and it follows the tab from then on: pick another schema or another connection and the name changes with it. A connection without a schema shows its name alone. Rename a connection in the Connections Manager and its tabs take the new name.
When two tabs are on the same connection and schema, the second is Prod - public (2), the third Prod - public (3), with the lowest number free. A tab keeps its number until its connection or schema changes, so a name never changes while you type.
A name you give the tab is kept: it no longer follows the connection or schema, and it comes back when Pharos reopens. To go back to the automatic name, rename the tab and leave the name empty. These tabs keep their names the same way:
- A tab saved as a Session takes the Session’s name. Reopening the Session gives the tab that name, and renaming the Session in the Sessions navigator renames its open tab.
- A tab opened from a
.sqlfile is named after the file. - A workspace you renamed in Results History reopens with that name.
A tab opened from a Session template, a history entry, a DuckDB file or Duplicate Tab (of a tab with an automatic name) gets an automatic name. Apple Intelligence does not name tabs; it can name query cards.
Each tab keeps its own cards, connection, and results, and gets its own database connection; query variables are shared by every tab.
The window title is the tab’s name. Under it, the subtitle reads “connection · schema”, or “No connection”. Each tab shows a small dot for its connection: green when connected, orange while connecting, red when the connection failed, and an empty ring when the tab is not connected or has no connection. The dot pulses while the tab runs queries. Rest the pointer on a tab to read its name, its connection and schema, and its state. A tab with unsaved edits shows the system’s edited dot.
Where opened items go
Opening a saved Session, a history entry, a workspace from Results History, a .sql file, Run in Pharos text, a Shortcuts action or a Dock menu item puts it in the current tab when that tab is untouched. Untouched means blank, never typed in, never renamed, with no file, saved Session or workspace, and nothing running. Otherwise it opens in a new tab beside the current one. A saved Session or workspace that is already open in any window is brought to the front instead.
Windows
File > New Window (Cmd+N) opens a second main window. Each window has its own tabs, so you can put two databases side by side. A new window starts blank, like a new tab: one empty tab with no connection. It does not copy the front window’s tabs or its connection.
Cmd+W closes the tab, Cmd+Shift+W (File > Close Window) closes every tab of the window, asking about each. Closing a tab cancels the queries that tab started.
A tab with an open transaction asks before it closes, and so does a window or Pharos itself: Roll Back and Close (or Roll Back and Quit) or Cancel. Pharos always rolls back and never commits for you. See Transactions.
Unsaved changes
Closing a tab, closing a window or quitting Pharos asks first when a tab holds edits that have not been written back:
- Save writes each tab back to its saved Session or to its file, then closes. A tab that has never been saved gets the Save Session sheet; cancelling that sheet cancels the close.
- Don’t Save closes and loses the edits.
- Cancel leaves every tab open, exactly as it was.
A tab bound to a saved Session or to a file always counts as unsaved once you edit it. A Session tab also counts once its results change (a run, Load More Rows, Load All Rows). A tab that has never been saved counts only while Restore open tabs is off — with it on, that tab comes back at the next launch with its text, so there is nothing to warn about. An empty tab never counts. Turn the whole warning off with Warn before closing unsaved tabs in Settings > General.
Windows tab together the way the system does everywhere else. Window > Merge All Windows makes one window with a tab for each; Window > Move Tab to New Window takes one back out. You can also drag a tab out of the tab bar to make a window of it, or drag it into another window’s tab bar. Whether Cmd+N opens a window or a tab follows your own setting in System Settings > Desktop & Dock > Prefer tabs when opening documents.
Pharos reopens the windows you left open, each at the size and position you left it, with the same tabs in the same order and the selected tab in front. Turn this off in Settings > General with Restore open tabs.
Indentation
- Tab inserts spaces (2, 4, or 8, configurable in Settings)
- Shift+Tab removes one indent level from the current or selected lines
- Tab with a multi-line selection indents all selected lines
- Return auto-indents to match the previous line
- Backspace at an indent boundary removes a full indent level
- Pasting multi-line text re-indents the block to match the cursor position while preserving its internal structure
Font Size
Pinch on the editor with the trackpad to zoom the font in or out, or use View > Increase Editor Font (Cmd++) and View > Decrease Editor Font (Cmd+-) to step it by one point at a time. The size ranges from 9 to 24 points and applies to the whole app (the same setting as Settings > Editor); a pinch tracks your fingers live and only saves once you lift them.
Format as SQL List (Smart Paste)
Paste a bare list of values (e.g., a column of IDs copied from a spreadsheet) and Pharos offers to convert it: a Format as SQL list button appears in the toolbar. Press Tab or click it to turn the lines into a quoted, comma-separated list ready for an IN (...) clause — numeric, boolean, and NULL values stay unquoted; strings are quoted with apostrophes escaped. Press Esc or keep typing to dismiss; the conversion is a single undo step. You can also select any lines and choose Format as SQL list from the right-click menu.
Code Folding
The editor supports collapsing regions of SQL that span at least 3 lines:
| Region | Example |
|---|---|
| Parenthetical blocks | Multi-line VALUES lists, IN (...), column definitions |
| Subqueries | ( SELECT ... ) |
| CTEs | WITH name AS ( ... ) |
| CASE blocks | CASE ... END |
| BEGIN/END blocks | BEGIN ... END |
| CREATE bodies | CREATE FUNCTION ... AS $$ ... $$ |
Click the fold indicator in the line-number gutter to collapse or expand a region. Collapsed regions render as an inline pill showing the hidden line count (e.g., “ ▸ 4 lines “); the underlying text is untouched. Folds survive edits elsewhere in the document and are removed automatically if an edit overlaps them.
Format SQL
Press Ctrl+I, choose Query > Format SQL, or click the toolbar Format button to format the SQL in the focused card.
Error Markers
When a query fails with a PostgreSQL error that includes a character position, the card underlines the error location in red and marks the line in its line-number gutter.
The message is on the marker. Hover the gutter marker for a moment — or click it — and a popover opens beside it with the failure text in full, wrapped and selectable, plus a Go to Error button that puts the caret on the offending SQL and scrolls it into view. Move the pointer away and the popover closes itself; you have a moment to travel into it and press the button. With VoiceOver, the marker is a control on the line (“Error on line 4”) and pressing it opens the same popover.