# Harlequin Documentation > Harlequin is the SQL IDE for your terminal, and hsql is your agent's favorite SQL client: two interfaces to one query engine, for any database. `harlequin` is the full-screen TUI: a data catalog, a query editor and a results viewer, for a person at a keyboard. `hsql` is the command-line client for scripts and agents: one statement or a file of them, several output formats, compact results and safe defaults. They share adapters, config files, profiles and a query engine, so you, your scripts and your agents can share one tool. Below is every page of https://harlequin.sh/docs, as markdown, in the order the site lists them. 71 pages, each introduced by a `Source:` line naming the URL it is also served at on its own, and separated by a `---` rule. For an index of titles and one-line descriptions — which is the cheaper way in — see https://harlequin.sh/llms.txt. --- Source: https://harlequin.sh/docs/getting-started # Installing Harlequin ## Installing Harlequin Harlequin is a Python program, and there are many ways to install and run it. We strongly recommend using [uv](https://docs.astral.sh/uv): 1. [Install uv](https://docs.astral.sh/uv/getting-started/installation/#standalone-installer). From a POSIX shell, run: ```bash curl -LsSf https://astral.sh/uv/install.sh | sh ``` Or using Windows Powershell: ```powershell powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" ``` 2. Install Harlequin as a tool using `uv`: ```bash uv tool install harlequin ``` This command will install Harlequin into an isolated environment and add it to your PATH so you can easily run the executable. ### Other Installation Methods Alternatively, if you know what you're doing, after installing Python 3.10-3.14, install Harlequin using `pip`, `pipx`, `poetry`, or any other program that can install Python packages from PyPI: ```bash python -m pip install harlequin ``` There is also a [Homebrew formula](https://formulae.brew.sh/formula/harlequin) for Harlequin, although this is maintained by the community and is not as rigorously tested as the Python installations. Note that the formula includes several Harlequin adapter packages (Postgres, MySQL, and ODBC) and their dependencies, which is convenient but increases the application size. ```bash brew install harlequin ``` Finally, there is a [Nix Package](https://search.nixos.org/packages?channel=25.05&show=harlequin&query=harlequin), which carries the same caveats as Homebrew. ## Installing Database Adapters Harlequin can connect to dozens of databases using adapter plug-ins. Adapters are distributed as their own Python packages that need to be installed into the same environment as Harlequin. For a list of known adapters provided either by the Harlequin maintainers or the broader community, see the [adapters](https://harlequin.sh/docs/adapters) page. The adapter docs also include installation instructions. Some adapters can be installed as Harlequin extras, like `postgres`. If you used `uv` to install Harlequin: ```bash uv tool install 'harlequin[postgres]' ``` You can install multiple extras: ```bash uv tool install 'harlequin[postgres,mysql,s3]' ``` > **Tip:** Depending on your shell, you may or may not need to place single or double quotes around the package name with extras: `% uv tool install 'harlequin[postgres,mysql,s3]'` Some adapters are not available as extras, and have to be installed manually. You may also wish to do this to control the version of the adapter that Harlequin uses. You can add adapters to your installation using uv's `--with` option: ```bash uv tool install harlequin --with harlequin-odbc ``` --- Source: https://harlequin.sh/docs/getting-started/running # Running Harlequin Once Harlequin is installed, you run it from the command line. The arguments and options you pass in at the command line affect Harlequin's behavior, like what database adapter it uses, which database it connects to, whether or not the file picker is visible, and more. Assuming you have installed Harlequin so that it is on your [PATH]() (`uv tool install harlequin` does this automatically), you run Harlequin by typing a command of this form into your shell: ```bash harlequin [OPTIONS] [CONN_STR] ``` where `[OPTIONS]` is 0 or more pairs of the form `--[option-name] [option-value]`, and `[CONN_STR]` is 0 or more connection strings. `[OPTIONS]` are composed of both Harlequin options and adapter options. For a full list of options, run Harlequin with the `--help` option: ```bash harlequin --help ``` ## Using Harlequin with DuckDB Harlequin defaults to using its DuckDB database adapter, which ships with Harlequin and includes the full DuckDB in-process database. To open an in-memory DuckDB session, run Harlequin with no arguments: ```bash harlequin ``` To open one or more DuckDB database files, pass in relative or absolute paths as connection strings (Harlequin will create DuckDB databases if they do not exist): ```bash harlequin "path/to/duck.db" "another_duck.db" ``` If you want to control the version of DuckDB that Harlequin uses, see the [Troubleshooting](https://harlequin.sh/docs/troubleshooting/duckdb-version-mismatch) page. ## Using Harlequin with SQLite and Other Adapters Harlequin also ships with a SQLite3 adapter. To use that adapter, you specify the `--adapter sqlite` option. Like DuckDB, you can open an in-memory SQLite database by omitting the connection string: ```bash harlequin --adapter sqlite ``` You can open one or more SQLite database files by passing in their paths as connection strings; note that the `--adapter` option has a short alias, `-a`: ```bash harlequin -a sqlite "path/to/sqlite.db" "another_sqlite.db" ``` Other adapters can be installed as plug-ins; for more information, see the [installation guide](https://harlequin.sh/docs/getting-started#installing-database-adapters), and the guides for individual [adapters](https://harlequin.sh/docs/adapters). Each adapter can define its own options, which you can view using `harlequin --help`. ## Configuring Harlequin Harlequin contains a large number of options that allow you to [set the theme](https://harlequin.sh/docs/themes), [customize key bindings](https://harlequin.sh/docs/keymaps), [show remote and local files](https://harlequin.sh/docs/files), set the locale for number formatting, and much more. These can always be entered at the command line, but it can be convenient to define a configuration as a profile instead. For more information on configuring Harlequin, see [Using Config Files](https://harlequin.sh/docs/config-file). ## Running Queries From the Command Line Harlequin also installs a second command, `hsql`, which runs queries headlessly: it connects using the same profiles and adapters, prints the results to stdout, and exits. It's designed specifically for agents, but also works great for scripts and other automations. For more information, see [Using hsql](https://harlequin.sh/docs/getting-started/hsql). ## Using Harlequin with Django [django-harlequin](https://pypi.org/project/django-harlequin/) provides a command to launch Harlequin using Django’s database configuration, like: ```bash ./manage.py harlequin ``` --- Source: https://harlequin.sh/docs/getting-started/usage # Using Harlequin To follow this tutorial, simply run Harlequin with no arguments to open an in-memory DuckDB database: ```bash harlequin ``` ## Getting Oriented Once you run Harlequin from the command line, it will open in your terminal in "application mode". This means that instead of showing your shell, your terminal will display Harlequin's interface, and Harlequin will receive all input into your terminal, including clicks. Immediately, it should look like this: ![A screenshot of Harlequin connected to an in-memory (empty) DuckDB database.](https://harlequin.sh/_app/immutable/assets/init.ewZC1UOW.png) *A blank slate.* Harlequin's interface has 5 main components: 1. **Data Catalog:** The left-hand pane is a data catalog. It shows the objects in the currently-connected database(s) in an interactive tree. 2. **Query Editor:** The top pane on the right side of the screen in the Query Editor. It is a full-featured text editor with syntax highlighting for SQL, autocomplete, and support for multiple buffers in tabs. 3. **Results Viewer:** Under the Query Editor is the Results Viewer. The results viewer displays the results of `select` statements in a high-performance data table powered by Apache Arrow. 4. **Run Query Bar:** Between the Query Editor and Results Viewer, the Run Query Bar houses a few useful interactive elements for running queries, limiting results, and managing transactions. 5. **Footer:** At the bottom of the screen is the Footer, which displays a subset of currently-active key bindings and their actions. These actions are clickable. ## Executing a Query The Query Editor should already have the focus of the keyboard, which is why it is outlined in yellow. Type or copy-paste the following SQL into the Query Editor, and then press `ctrl+enter`. ```sql select * from duckdb_functions() ``` This should execute the query, and the results should be shown in the Results Viewer. ![A screenshot of Harlequin with data in the Results Viewer.](https://harlequin.sh/_app/immutable/assets/first-query.4OlZFrvM.png) > **Tip:** If that didn't happen, your terminal may be intercepting the `ctrl+enter` keypress. You can try `ctrl+j` instead, or just click the yellow Run Query button. See the [troubleshooting guide](https://harlequin.sh/docs/troubleshooting/key-bindings) for more info. The Results Viewer now has the keyboard's focus. You can scroll through the results using the arrow keys, `tab`, `ctrl+right`, `pgDn`, `end`, and [more](https://harlequin.sh/docs/bindings#results-viewer-bindings). There is a lot of data here, so press `F10` to enter full-screen mode. ![A screenshot of Harlequin with data in full screen mode.](https://harlequin.sh/_app/immutable/assets/full-screen.BSTiwsWJ.png) When you are finished in full-screen mode, press `F10` again to return to the original view. > **Tip:** Full-screen mode also works for the Query Editor. You can also press `ctrl+b` to hide and show the Data Catalog sidebar. ## Using the Data Catalog Our Catalog is currently empty; let's put something in it by executing another query. Press `F2` to focus the Query Editor, then `ctrl+w` to clear the old query, and then type or paste the following query, and run it with `ctrl+enter`: ```sql create table foo as select * from duckdb_functions() ``` Now focus on the Data Catalog by pressing `F6`. `memory` is the name of our database; press `enter` or `space` to expand this item and show its only schema, called `main` (these are both DuckDB defaults for in-memory databases). Press `down` and `enter` again to expand the `main` schema, and do that one more time to expand the table `foo` we just created, showing its columns. ![A screenshot of Harlequin with items in the Data Catalog expanded.](https://harlequin.sh/_app/immutable/assets/catalog.CQTbnJEc.png) Next to the names of objects, in dimmed text you can see an indication of their types. These types are defined by each adapter; typically `s` is for string, `#` is for int, `##` is for big int, and so forth. The DuckDB adapter even labels complex types, like arrays of strings (`[s]`), maps (`{m}`), and more. With the table `foo` still selected, press `.` to open the Interactions context menu. ![A screenshot of Harlequin with the interactions menu expanded for the foo table.](https://harlequin.sh/_app/immutable/assets/interactions.CjezhD1g.png) Interactions are scripts that execute in the context of the current selection in the Data Catalog. They are available on all types of objects, not just tables. Press `down` until the `Describe` interaction is highlighted, then press `enter` to execute it. You should see a `describe` query inserted into a new tab in the Query Editor. Press `ctrl+enter` to execute the query, which will display the schema of `foo` in the Results Viewer. ![A screenshot of Harlequin with the describe query executed.](https://harlequin.sh/_app/immutable/assets/describe.DGugQ0TY.png) ## Using the Query Editor Press `F2` to return the focus to the Query Editor. Now press `ctrl+n` to open a new buffer in a third tab. Type `sel`, and notice that an autocomplete menu appears, including exact and fuzzy matches. ![A screenshot of Harlequin with an autocomplete modal.](https://harlequin.sh/_app/immutable/assets/autocomplete.xzSsGtxe.png) You can use the arrow keys to select different options, and then press `tab` or `enter` to accept the completion. Keep typing if you want, or press `ctrl+o` to open a text file in the Query Editor. > **Tip:** Don't have a big .sql file? Try [this one](https://raw.githubusercontent.com/tconbeer/http_archive_almanac/refs/tags/unformatted/sql/2020/accessibility/common_alt_text_length.sql) from the HTTP Archive! Format the file you just opened by pressing `F4`. It's a long query, but you can use `ctrl+f` to find a keyword or `ctrl+g` to go to a line. ![A screenshot of Harlequin with an autocomplete modal.](https://harlequin.sh/_app/immutable/assets/find.CE0U1Q8I.png) *Finding all instances of alt_* When you're finished editing the query, you can use `ctrl+s` to save it back to disk. Now you know the basics, but there is One More Thing: you quit Harlequin using `ctrl+q`. ## More Features This was just a quick introduction to some of Harlequin's features, but many more await. Keep reading these docs for an overview of all features, or skip ahead to the [Key Bindings Reference](https://harlequin.sh/docs/bindings) for a cheat-sheet (and a hint of what is possible). --- Source: https://harlequin.sh/docs/getting-started/hsql # Using hsql `hsql` is your agent's favorite SQL client. It's the headless CLI for [Harlequin](https://harlequin.sh), and shares the same config and query engine, with an interface optimized for agents, scripts, and automations. hsql is packaged with Harlequin, so you install it by [installing Harlequin](https://harlequin.sh/docs/getting-started#installing-harlequin). hsql can connect to dozens of databases using the same adapter plug-ins as Harlequin. ## Running hsql Once hsql is installed, you run it from the command line. If you have used psql or the duckdb CLI, hsql will feel familiar, but hsql has the major advantage that it works with most databases and provides the same interface and produces the same output, regardless of the connected database. This means you (and your agent) can learn one tool, instead of several. In your shell, all hsql commands take the same form: ```bash hsql [OPTIONS] [CONN_STR] ``` where `[OPTIONS]` is 0 or more pairs of the form `--[option-name] [option-value]`, and `[CONN_STR]` is 0 or more connection strings. `[OPTIONS]` are composed of both hsql options and adapter options. For a full list of options, run hsql with the `--help` option: ```bash hsql --help ``` Every option, with its type, default and help text, is also on one page: [Reference: hsql CLI](https://harlequin.sh/docs/hsql/reference). ## Database Adapters > **Tip:** hsql and Harlequin use the same options for defining adapters, connection strings, and adapter options. If you can connect > to your database with Harlequin, just replace `harlequin` with `hsql`. If you are new to Harlequin, see [Running Harlequin](https://harlequin.sh/docs/getting-started/running) for more information. Like Harlequin, hsql defaults to using its DuckDB database adapter, which ships with hsql and includes the full DuckDB in-process database. Run a query against an in-memory DuckDB session, run hsql and pass in a query with the `-c` option: ```bash hsql -c "select 1" ``` ``` 1 --- 1 (1 row) ``` To connect to a local DuckDB or SQLite database file, pass the path as a connection string; note that the `--adapter` option has a short alias, `-a`: ```bash hsql -a sqlite "path/to/sqlite.db" -c "select * from users" ``` ``` id | name ----+--------- 1 | Ted 2 | Patrick (2 rows) ``` Other adapters take URIs or DSNs as connection strings; for example, Postgres: ```bash hsql -a postgres "postgresql://example.com/postgres:5432" -c "select * from invoices" ``` > **Tip:** You should use [profiles](https://harlequin.sh/docs/config-file) to keep credentials out of your shell > history. ## Configuring hsql and Using Profiles hsql supports a number of options for setting the query limit, configuring output formats, and defining connection parameters. Options can be passed as command-line flags, or read from [config files](https://harlequin.sh/docs/config-file). Config files store configurations under separate profiles, so you can easily switch between databases by reading from different profiles with the `-P` option: ```bash hsql -P prod -c "select count(*) from orders" --csv hsql -P dev -c "select * from users" --vertical --limit 5 hsql -P warehouse -c "..." --format parquet -o invoices.pq ``` hsql can also inspect, validate and write those files without running any SQL; see [Config Modes](https://harlequin.sh/docs/hsql/config). ## Data Layouts and File Formats hsql supports all of the following formats for displaying and writing data: - table - markdown (alias: md) - vertical - csv - tsv - json - jsonl (alias: ndjson) - parquet - orc - feather (alias: arrow) - none (suppresses output) You can select a format with the `--format `. Some formats have a shorthand `--`, so these are equivalent: `--format csv`, `--csv`. Some layouts can present the results from multiple queries. Others will raise an error and exit with code 2 if multiple queries are executed. [Formats and Layouts](https://harlequin.sh/docs/hsql/formats) covers all of them, the switches that shape a text layout, and `-o`. Additionally, for any layout, pass `--stats` to print summary info as JSON to stderr: ```bash hsql -c "select 1" --format none --stats ``` ``` {"status":"ok","statements":1,"rows":1,"truncated":false,"limit":500,"elapsed_ms":1,"columns":[{"name":"1","type":"#"}]} ``` Every key in that summary, and what to do about `truncated`, is on [Exit Codes and Streams](https://harlequin.sh/docs/hsql/exit-codes). ## Scripting with hsql > **Warning:** To make hsql safe and efficient for agents, by default hsql applies a 500-row > limit to all queries. To remove this limit, use `--limit -1` or set > `limit = -1` in your profile. If limits truncate data, hsql will print > a warning on stderr; we recommend that you do NOT suppress or redirect > that message so do NOT use hsql with `2>/dev/null`. hsql can write data to files, either with the `-o` option or by piping output (hsql only writes data to stdout; other messages go to stderr): ```bash hsql -P prod --limit -1 -c "select * from users" --format parquet -o "users.pq" hsql -P prod --limit -1 -c "select * from users" --csv > users.csv ``` hsql can execute multiple statements in one invocation, and supports several methods for doing so: - Pass `-c` multiple times - Include multiple queries, separated by `;`, in one `-c` option - Pass one or more .sql files with `-f`, with multiple statements in each - Use `--result` to define which queries output data to stdout - Use `--on-error` to either `stop` or `continue` if one or more queries produces an error. In other words, this works: ```bash hsql -P prod --limit -1 --format md --result all --on-error stop \ -f ./setup.sql \ -c "select count(*) from raw_table" \ -f ./build-models.sql \ -c "select count(*) from modeled_table" ``` hsql's [exit codes](https://harlequin.sh/docs/hsql/exit-codes) are meaningful and stable. You can also use `--stats` and `jq` together to error on a truncated query: ```bash hsql --limit 100 -c "select * from orders" --csv -o data.csv --stats 2>&1 | jq -e '.truncated | not' > /dev/null ``` --- Source: https://harlequin.sh/docs/getting-started/help # Getting Help To view all command-line options for Harlequin and all installed adapters, after installation, simply type: ```bash harlequin --help ``` To view a subset of these docs (and a link back here) from within the app, press `F1`. See the [Troubleshooting](https://harlequin.sh/docs/troubleshooting) guide for help with key bindings, appearance issues, copy-paste, etc. [GitHub Discussions](https://github.com/tconbeer/harlequin/discussions) are a good place to ask questions, request features, and say hello. [GitHub Issues](https://github.com/tconbeer/harlequin/issues) are the best place to report bugs. --- Source: https://harlequin.sh/docs/hsql # The hsql CLI `hsql` runs SQL against any database Harlequin has an adapter for, with one set of flags and one output contract. It reads the same config files as the IDE, so one profile serves both. For a tutorial, see [Using hsql](https://harlequin.sh/docs/getting-started/hsql). For more detailed information on hsql and its features, keep reading. ## Pages | Page | What it covers | | ----------------------------------------------- | -------------------------------------------------------------- | | [Exit Codes and Streams](https://harlequin.sh/docs/hsql/exit-codes) | The six codes, stdout and stderr, `--stats`, `--on-error` | | [Exploring the Catalog](https://harlequin.sh/docs/hsql/catalog) | `--catalog`, `--path`, `--catalog-search` | | [Formats and Layouts](https://harlequin.sh/docs/hsql/formats) | Every format, the layout switches, `-o`, `--result` | | [Config Modes](https://harlequin.sh/docs/hsql/config) | `--config list-profiles`, `show`, `validate`, `schema`, `init` | | [Running Safely](https://harlequin.sh/docs/hsql/safety) | `--limit`, `--read-only`, `--timeout`, adapter capabilities | | [Differences from psql](https://harlequin.sh/docs/hsql/psql) | What carries over, and what does not | | [Reference: hsql CLI](https://harlequin.sh/docs/hsql/reference) | Every option, generated from hsql itself | | [The hsql Agent Skill](https://harlequin.sh/docs/hsql/skill) | What the skill says, and how to install it | --- Source: https://harlequin.sh/docs/hsql/exit-codes # Exit Codes and Streams stdout carries result sets and nothing else. Every error, warning and note goes to stderr. The exit code is the verdict, and stdout is empty whenever it is non-zero — so read the code before the output. ## The Codes | Code | Meaning | | ----- | ---------------------------------------------------------------- | | `0` | Success. | | `1` | The database rejected the SQL. | | `2` | A bad flag, a bad profile, or a config file hsql could not read. | | `3` | hsql could not connect. | | `4` | `--timeout` ran out, and hsql stopped the run. | | `130` | Interrupted. | A `2` means hsql never opened a connection. It covers a flag that does not exist, a `-P` naming a profile no file defines, an unset `${VAR}` in a config file, and a single-result format asked to print three result sets. A `1` means the connection was fine and the database said no. ```bash if ! hsql -P prod --read-only -c "select 1" --format none; then echo "database is not reachable" >&2 exit 1 fi ``` ## Errors and Notes Errors are one line, prefixed `hsql: error:`. Notes — the files `-o` wrote, a warning that a limit truncated a result — are prefixed `note:`. > **Warning:** `2>/dev/null` hides truncation warnings and errors alike. Redirect stderr to a > log if it is noisy, but keep it. `hsql --info` connects to nothing, redacts the profile it reports, and answers even when the config is broken, so it is safe to paste into a bug report. [Troubleshooting](https://harlequin.sh/docs/troubleshooting) covers hsql and the IDE together. ## `--stats` For any format, `--stats` writes a one-line JSON summary of the run to stderr: ```bash hsql -c "select 1" --format none --stats ``` ``` {"status":"ok","statements":1,"rows":1,"truncated":false,"limit":500,"elapsed_ms":1,"columns":[{"name":"1","type":"#"}]} ``` The keys are `status`, `statements`, `rows`, `truncated`, `limit`, `elapsed_ms` and `columns`. `truncated` is `true` when the [row limit](https://harlequin.sh/docs/hsql/safety) cut a result set short, which means anything computed from those rows is wrong. ```bash hsql --limit -1 -c "select * from orders" --csv -o data.csv --stats 2>&1 \ | jq -e '.truncated | not' > /dev/null ``` ## `--on-error` hsql runs every statement you pass it — repeated `-c` and `-f`, and several statements separated by `;` inside either — in the order typed, on one connection. - `--on-error stop` (the default) stops at the first failure. - `--on-error continue` runs the rest. Either way a failed statement makes the exit code non-zero. `continue` changes what runs, not what hsql reports. Which result sets reach stdout is a separate question: [`--result`](https://harlequin.sh/docs/hsql/formats). --- Source: https://harlequin.sh/docs/hsql/catalog # Exploring the Catalog `--catalog` lists the objects one level below `--path`, and exits without running SQL. `--catalog-search` finds objects by name at every level at once. Neither runs a query, and both produce ordinary result sets. ```bash hsql "path/to/duck.db" --catalog ``` ``` path | name | query_name | type | type_label ------+------+------------+----------+------------ duck | duck | "duck" | database | db (1 row) ``` Every row has five columns: | Column | What it is | | ------------ | ----------------------------------------------------------------------- | | `path` | What to pass to `--path` to list this object's children. | | `name` | The object's name, unquoted. | | `query_name` | The name already quoted for this database. Paste this into SQL. | | `type` | The database's own word for it: `database`, `schema`, `VIEW`, `BIGINT`. | | `type_label` | The short label Harlequin shows in its data catalog. | ## Navigating the Catalog Pass a row's `path` back to `--path`: ```bash hsql "path/to/duck.db" --catalog --path duck ``` ``` path | name | query_name | type | type_label ----------------+-----------+--------------------+--------+------------ duck.analytics | analytics | "duck"."analytics" | schema | sch duck.main | main | "duck"."main" | schema | sch (2 rows) ``` ```bash hsql "path/to/duck.db" --catalog --path duck.analytics ``` ``` path | name | query_name | type | type_label -----------------------------+--------------+----------------------------+------------+------------ duck.analytics.customers | customers | "analytics"."customers" | BASE TABLE | t duck.analytics.order_totals | order_totals | "analytics"."order_totals" | VIEW | v duck.analytics.orders | orders | "analytics"."orders" | BASE TABLE | t (3 rows) ``` One level further down is the columns, with their types: ```bash hsql "path/to/duck.db" --catalog --path duck.analytics.orders ``` ``` path | name | query_name | type | type_label -----------------------------------+-------------+---------------+---------------+------------ duck.analytics.orders.customer_id | customer_id | "customer_id" | BIGINT | ## duck.analytics.orders.id | id | "id" | BIGINT | ## duck.analytics.orders.placed_at | placed_at | "placed_at" | TIMESTAMP | ts duck.analytics.orders.total | total | "total" | DECIMAL(18,2) | #.# (4 rows) ``` The adapter names the segments, so how deep the catalog goes and what each level is called varies by database. A trailing `*` filters a listing. Quote it, or the shell expands it against the working directory: ```bash hsql "path/to/duck.db" --catalog --path 'duck.analytics.ord*' ``` ## Searching `--catalog-search TERM` searches every level at once, for objects whose name contains TERM: ```bash hsql "path/to/duck.db" --catalog-search customer_id ``` ``` path | name | query_name | type | type_label -----------------------------------------+-------------+---------------+--------+------------ duck.analytics.order_totals.customer_id | customer_id | "customer_id" | BIGINT | ## duck.analytics.orders.customer_id | customer_id | "customer_id" | BIGINT | ## duck.main.staging_events.customer_id | customer_id | "customer_id" | BIGINT | ## (3 rows) ``` `--path` narrows a search to one subtree: ```bash hsql "path/to/duck.db" --catalog-search order --path duck.analytics -tA ``` ``` duck.analytics.order_totals|order_totals|"analytics"."order_totals"|VIEW|v duck.analytics.orders|orders|"analytics"."orders"|BASE TABLE|t ``` > **Note:** Not every adapter can search. `hsql --info -a NAME` reports > `implements_catalog_search`; see [Running Safely](https://harlequin.sh/docs/hsql/safety). ## Formats and Files A listing is a result set, so every [format and output option](https://harlequin.sh/docs/hsql/formats) applies: ```bash hsql "path/to/duck.db" --catalog --path duck.analytics -tA --csv ``` ``` duck.analytics.customers,customers,"""analytics"".""customers""",BASE TABLE,t duck.analytics.order_totals,order_totals,"""analytics"".""order_totals""",VIEW,v duck.analytics.orders,orders,"""analytics"".""orders""",BASE TABLE,t ``` ```bash hsql -P prod --catalog --path prod.public --json -o ./schema.json ``` They are modes rather than options: hsql either reads the catalog or runs SQL. Passing `-c` or `-f` beside `--catalog` [exits `2`](https://harlequin.sh/docs/hsql/exit-codes). Use two invocations. For the same catalog as a tree you can click through, use the Harlequin IDE. --- Source: https://harlequin.sh/docs/hsql/formats # Formats and Layouts `--format NAME` picks how results are laid out, or what file format they are written in. Five formats also have a shorthand flag: `--csv`, `--json`, `--jsonl`, `--markdown`, and `--vertical` (also `-x`, as in psql). ```bash hsql -c "select 1" --format csv hsql -c "select 1" --csv ``` ## The Formats Text layouts, which draw chrome and are meant to be read: - `table` — the default: aligned columns, a header, a row-count footer. - `markdown` (alias `md`) — a markdown table. - `vertical` — one field per line, for a row too wide to read across. File formats, meant for another program: - `csv`, `tsv` - `json`, `jsonl` (alias `ndjson`) - `parquet`, `orc`, `feather` (alias `arrow`) And `none`, which runs the SQL and writes nothing. > **Note:** Only the text layouts, `jsonl` and `none` carry more than one result set. > `csv`, `json`, `parquet` and the rest hold exactly one and exit > [`2`](https://harlequin.sh/docs/hsql/exit-codes) rather than concatenating, unless `-o` names a > directory, which gets one file per result set. Otherwise a run with several > result sets wants `--result last` or `--jsonl`. The [CLI > reference](https://harlequin.sh/docs/hsql/reference) has the table, suffix by suffix. ## Choosing One | What you want | What to use | | ---------------------------------------- | --------------------------------- | | One value, for a shell variable | `-tAc "select …"` | | A few rows to read | the default `table` | | Rows to paste into a document or a reply | `--markdown` | | A wide row, read field by field | `-x` | | Input for another program | `--csv`, or `--jsonl` | | More rows than belong in a terminal | `--format parquet -o out.parquet` | | The run's side effects, not its rows | `--format none` | `-t` drops the header and footer, `-A` drops the alignment padding, so `-tAc` prints a bare value with a newline after it: ```bash row_count=$(hsql -P prod -tAc "select count(*) from orders") ``` ## Layout Switches These shape the text layouts, independently of `--format`. A file format ignores the ones that do not apply to it. | Option | What it does | | ----------------------------- | --------------------------------------------------------------------------------------------------------------- | | `-t`, `--tuples-only` | Rows only: no header, no footer. As in psql. | | `-A`, `--no-align` | Unaligned output. As in psql. | | `--no-header` | Drop the header row, keep the rest. | | `--no-footer` | Drop the row-count footer, keep the rest. | | `--null-string TEXT` | Render NULL as TEXT. Text layouts default to `NULL`, csv to empty. | | `--display-rows N` | How many rows a text layout prints; `-1` for all. Defaults to 40 for `table` and `markdown`, 10 for `vertical`. | | `--color auto\|always\|never` | Color text output. `never` by default; `auto` follows the terminal and `NO_COLOR`. | `--display-rows` is not a limit: the rows were fetched, and this is how many print. [`--limit`](https://harlequin.sh/docs/hsql/safety) is the one that changes what the database returns. ## Writing to a File or Directory `-o PATH` writes results to a file instead of stdout, in the same bytes a redirect would produce: ```bash hsql -P prod --limit -1 -c "select * from users" --format parquet -o users.parquet hsql -P prod --limit -1 -c "select * from users" --csv > users.csv ``` `-o` also takes a directory, and then writes one file per result set, named with the format's suffix and reported on stderr: ```bash hsql -P prod --limit -1 --csv -o ./out/ -f ./three_reports.sql ``` ## `--result` `--result` picks which result sets reach stdout when a run produced more than one: - `--result all` (the default) — every one. - `--result last` — the final one. The usual choice for a script that sets things up and ends in a `select`. - `--result N` — the Nth. ```bash hsql -P prod --limit -1 --format md --result last --on-error stop \ -f ./setup.sql \ -c "select count(*) from raw_table" \ -f ./build-models.sql \ -c "select count(*) from modeled_table" ``` Every statement still runs. What happens after one of them fails is [`--on-error`](https://harlequin.sh/docs/hsql/exit-codes). Harlequin writes the same formats from its results viewer; see [Exporting Data](https://harlequin.sh/docs/export). --- Source: https://harlequin.sh/docs/hsql/config # Config Modes hsql reads the same config files as Harlequin, and [Configuring Harlequin](https://harlequin.sh/docs/config-file) covers them: [where they are found](https://harlequin.sh/docs/config-file/discovery), [how to write one](https://harlequin.sh/docs/config-file/creating-config), and [how a profile is selected](https://harlequin.sh/docs/config-file/profiles). `-P NAME`, `-P None` and `--config-path PATH` mean the same thing to hsql that they mean to the IDE. What hsql adds is five modes that work on those files instead of running SQL. None of them connects to a database. ```bash hsql --config list-profiles hsql --config show hsql --config show --json hsql --config validate hsql --config schema hsql --config init -P prod -a sqlite ./app.db --read-only --limit -1 ``` ## `list-profiles` The names `-P` takes, each one's adapter, and which one is the default. ## `show` The merged config, with the file each value came from beside it. `--json` for a parser. Values an adapter declares as secret are masked here, as they are everywhere else hsql prints them. ## `validate` Every problem in every discovered file, exiting [`2`](https://harlequin.sh/docs/hsql/exit-codes) if it found any. It names the file and the key, including a misspelled key an adapter would otherwise ignore, and an environment variable a `${VAR}` needs and does not have. Two commands are the whole check that a profile works: ```bash hsql --config validate hsql -P prod --catalog ``` ## `schema` A JSON Schema for a config file, covering the adapters installed here. > **Tip:** Point an editor at it for completion as you type: > `hsql --config schema -o ./schema.json`. The published copy, which generated > config files already name, is at > [harlequin.sh/schemas/config/v1.json](https://harlequin.sh/schemas/config/v1.json). ## `init` Writes a profile from the options passed — hsql's and the adapter's alike — into the nearest config file: ```bash hsql --config init -P prod -a postgres --host db.example.com --read-only ``` It prompts for nothing, and leaves other profiles and the file's comments untouched, so it is the mode for a script or an agent. `harlequin --config` is the interactive wizard. ## Output `list-profiles` and `validate` are result sets, so every [format and output option](https://harlequin.sh/docs/hsql/formats) applies: ```bash hsql --config list-profiles --csv hsql --config validate -tA ``` Like [`--catalog`](https://harlequin.sh/docs/hsql/catalog), these are modes rather than options: passing `-c` or `-f` beside one exits `2`. --- Source: https://harlequin.sh/docs/hsql/safety # Running Safely Three options bound a run: how many rows it fetches, whether it can write, and how long it can take. hsql refuses to connect when the adapter cannot enforce the last two, rather than running unbounded. ## `--limit` hsql fetches 500 rows per result set by default, and the database applies the limit. ```bash hsql -P prod --limit 100 -c "select * from orders" hsql -P prod --limit -1 -c "select * from orders" --format parquet -o orders.parquet ``` `--limit -1` runs the query as written, with no limit applied. > **Warning:** A truncated result looks like a complete one. When a limit cuts a result set > short, hsql says so on stderr and [`--stats`](https://harlequin.sh/docs/hsql/exit-codes) reports > `"truncated": true`. [`--display-rows`](https://harlequin.sh/docs/hsql/formats) is the softer knob: it caps what a text layout prints without changing what was fetched. ## `--read-only` `-r` (or `--read-only`) instructs the database to prohibit writes: ```bash hsql -r "path/to/duck.db" -c "insert into orders values (1)" ``` ``` hsql: error: Invalid Input Error: Cannot execute statement of type "INSERT" on database "duck" which is attached in read-only mode! ``` An adapter that cannot connect read-only makes hsql exit [`2`](https://harlequin.sh/docs/hsql/exit-codes) instead of connecting writable. ## `--timeout` `--timeout SECONDS` bounds executing and fetching together, and exits [`4`](https://harlequin.sh/docs/hsql/exit-codes) when it runs out: ```bash hsql --timeout 0.5 -c "select count(*) from range(100000000000) t(i)" ``` ``` hsql: error: timed out after 0.5s ``` As with `--read-only`, hsql refuses to start when the adapter cannot cancel a query. ## Adapter Capabilities `hsql --info` reports what each installed adapter declares it supports, and connects to nothing. `-a NAME` narrows it to one adapter, which is faster than importing them all: ```bash hsql --info -a sqlite | jq '.adapters.sqlite' ``` ``` { "distribution": "harlequin", "version": "2.10.0", "capabilities": { "implements_cancel": true, "implements_catalog_search": true, "implements_read_only": true, "implements_validate_sql": false }, "error": null } ``` | Capability | What depends on it | | --------------------------- | ---------------------------------------- | | `implements_read_only` | `-r`, `--read-only` | | `implements_cancel` | `--timeout` | | `implements_catalog_search` | [`--catalog-search`](https://harlequin.sh/docs/hsql/catalog) | | `implements_validate_sql` | Checking a statement without running it | > **Note:** An adapter that is installed but will not import is reported with its > capabilities unknown and the import error beside it. That is a broken > installation rather than a broken config; see > [Troubleshooting](https://harlequin.sh/docs/troubleshooting). ## A Profile for Automation `read_only`, `timeout` and `limit` are [profile keys](https://harlequin.sh/docs/config-file), so no invocation has to remember them: ```toml [profiles.agent] adapter = "postgres" host = "${PGHOST}" password = "${PGPASSWORD}" read_only = true timeout = 30 limit = -1 ``` ```bash hsql -P agent -tAc "select count(*) from orders" ``` --- Source: https://harlequin.sh/docs/hsql/psql # Differences from psql `-c`, `-f`, `-t`, `-A` and `-x` mean what they mean in psql, so this prints a bare number in either program: ```bash hsql -tAc "select count(*) from orders" ``` It prints it the same way against every [adapter](https://harlequin.sh/docs/adapters), which is the part psql cannot do. ## What Is Different | | psql | hsql | | --------------------------- | --------------------------------------------------- | --------------------------------------------------------------------------------------- | | `-P` | `--pset`, an output setting | `--profile`, a [config-file profile](https://harlequin.sh/docs/config-file) | | Field separator | `-F` | `--csv`, `--format tsv`, or any other [`--format`](https://harlequin.sh/docs/hsql/formats) | | Listing databases | `-l` | [`--catalog`](https://harlequin.sh/docs/hsql/catalog) | | Describing an object | `\d`, `\dt` | `--catalog --path`, `--catalog-search` | | Stopping on the first error | `-v ON_ERROR_STOP=1` | `--on-error stop`, the default | | One transaction | `-1` | write `begin` and `commit` in your script | | `-o` | a file for query output | a file, or a directory that gets one file per result set | | Connection flags | `-h`, `-p`, `-U`, built in | the adapter's, so `hsql --help -a postgres` lists them | | Row limits | none | [500 rows by default](https://harlequin.sh/docs/hsql/safety); `--limit -1` removes it | | Suppressing chatter | `-q` | nothing to suppress: stdout is only ever results | | Exit codes | `1` its own error, `2` connection, `3` script error | [`1` query error, `2` usage/config, `3` connection, `4` timeout](https://harlequin.sh/docs/hsql/exit-codes) | > **Warning:** `-t` is _tuples only_, as in psql, not Harlequin's theme flag. Connection > strings are positional, so `hsql -t nord -c "..."` parses, `nord` becomes a > connection string, and hsql says so on stderr. ## No Backslash Commands hsql has no meta-commands. What they do, options do: - `\d`, `\dt`, `\l` — [`--catalog` and `--catalog-search`](https://harlequin.sh/docs/hsql/catalog), which produce ordinary result sets. - `\copy` — [`--csv` and `-o`](https://harlequin.sh/docs/hsql/formats), or `--format parquet`. - `\timing` — `--stats`, which reports `elapsed_ms` on stderr. - `\c` — a different profile: `-P NAME`. - `\set` — the profile, or the command line. One invocation, no session variables. ## No Interactive Session hsql executes what it was passed and exits; there is no prompt. For an interactive session, [Harlequin](https://harlequin.sh/docs/getting-started/usage) uses the same adapters, config files and profiles: `harlequin -P prod`. --- Source: https://harlequin.sh/docs/hsql/reference # Reference: hsql CLI This page is generated from `hsql --spec` with no adapters loaded, in [Harlequin's repository](https://github.com/tconbeer/harlequin), and published with the release it describes. It does not cover any adapter's connection options. Four commands answer that, and none of them connects to a database: ```bash hsql --help hsql --help -a postgres hsql --spec hsql --info ``` `--help` is this list for a person, `--help -a NAME` adds one adapter's options to it, and `--spec` is the whole surface as JSON. `--info` describes the installation: versions, config files, the active profile, and what each adapter supports. What the options are _for_ is on the other pages under [The hsql CLI](https://harlequin.sh/docs/hsql). *Generated from hsql 2.13.0, and served verbatim at [harlequin.sh/artifacts/hsql-reference.md](https://harlequin.sh/artifacts/hsql-reference.md).* # hsql Execute SQL and exit. CONN_STR: one or more connection strings, or paths to local db files. Generated from the bare `hsql` command, with no adapters loaded. An adapter contributes its own options on top of these: `hsql --help -a NAME` shows one adapter's, and `hsql --spec` reports every installed adapter's as JSON. ## Usage ``` hsql [OPTIONS] [CONN_STR]... ``` ## Arguments | Argument | Type | Accepts | | --- | --- | --- | | `CONN_STR` | text | zero or more | ## Options Alphabetical by name. Flags are off by default. | Option | Type | Values | Default | Env var | Description | | --- | --- | --- | --- | --- | --- | | `-a`, `--adapter` | choice | `NAME` | `duckdb` | | The installed adapter plug-in to connect with. | | `--catalog` | boolean | | | | List the catalog objects one level below --path, and exit without running SQL. | | `--catalog-search` | text | `TERM` | | | Search the whole catalog, at every level, for objects whose name contains TERM, and exit without running SQL. Not every adapter can; see --info. | | `--color` | choice | `auto`, `always`, `never` | `never` | | Color text output. `auto` follows the terminal and NO_COLOR. | | `-c`, `--command` | text | | | | Execute SQL. Repeatable. | | `--config` | choice | `show`, `list-profiles`, `validate`, `schema`, `init` | | | Report on the config files hsql found, or write a profile into one, and exit without running SQL. One of: show, list-profiles, validate, schema, init. | | `--config-path` | path | `PATH` | | `HARLEQUIN_CONFIG_PATH` | Use this config file instead of the ones hsql discovers. | | `--csv` | boolean | | | | Shorthand for --format csv. | | `--display-rows` | integer | `N` | | | Rows printed per result set by the text layouts. -1 for all rows. [default: 40 for table, markdown, md; 10 for vertical] | | `-f`, `--file` | text | `PATH` | | | Execute SQL from a file, or from stdin for `-`. Repeatable. | | `--format` | choice | `table`, `markdown`, `md`, `vertical`, `csv`, `tsv`, `json`, `jsonl`, `ndjson`, `parquet`, `orc`, `feather`, `arrow`, `none` | `table` | | Output format. See below for the list. | | `--help` | boolean | | | | Show this message and exit. | | `--info` | boolean | | | | Versions, config files, the active profile, and what each installed adapter declares it supports, as JSON. Connects to nothing. -a narrows it to one adapter. | | `--json` | boolean | | | | Shorthand for --format json. | | `--jsonl` | boolean | | | | Shorthand for --format jsonl. | | `--limit` | integer | `N` | `500` | | Maximum rows fetched per result set. -1 for no limit. | | `--markdown` | boolean | | | | Shorthand for --format markdown. | | `-A`, `--no-align` | boolean | | | | Unaligned output. As in psql. | | `--no-footer` | boolean | | | | Omit the row-count footer, keeping other chrome. | | `--no-header` | boolean | | | | Omit the header row, keeping other chrome. | | `--null-string` | text | `TEXT` | | | Render NULL as TEXT. Defaults to NULL for text formats, empty for csv. | | `--on-error` | choice | `stop`, `continue` | `stop` | | What to do when a statement fails. | | `-o`, `--output` | text | `PATH` | | | Write results to PATH instead of stdout. Accepts a file or directory. | | `--path` | text | `TEXT` | | | Where in the catalog --catalog looks, and what --catalog-search searches under. Dotted segments, named by the adapter; the top of the catalog by default. A trailing * filters a --catalog listing. | | `-P`, `--profile` | text | | | | Load a profile from an available config file. Options passed here take precedence over the profile's. Use the profile named None for Harlequin's defaults instead of the config file's default profile. | | `-r`, `--read-only` | boolean | | | | Connect read-only, and refuse to run at all if the adapter cannot. To check an adapter's capabilities, use --info. | | `--result` | text | `all\|last\|N` | `all` | | Which result set(s) to emit. | | `--skill` | boolean | | | | Write the Agent Skill for driving hsql, as markdown. -o installs it: 'hsql --skill -o ~/.claude/skills/hsql/'. | | `--spec` | boolean | | | | Every option here, plus every installed adapter's, as JSON. -a narrows it to one adapter. | | `--ssh-allow-reuse` | boolean | | | | When the local port is already bound, warn and connect through the listener that has it instead of failing. | | `--ssh-batch-mode` | boolean | | | | Fail rather than prompt for a passphrase, a password or a host key. ssh's own BatchMode; set it in scripts, CI and cron. | | `--ssh-forward` | text | `TEXT` | | | A local forward, spelled as ssh -L takes one: LOCAL:HOST:REMOTE. Repeatable. Omit it when your ssh config has the LocalForward. | | `--ssh-host` | text | `TEXT` | | | Open an SSH tunnel to this destination first, and connect through it. A Host alias, host, user@host or ssh://user@host:port, passed to ssh verbatim. | | `--ssh-timeout` | number | `SECONDS` | | | Seconds to wait for the tunnel's forwards. [default: 60] | | `--stats` | boolean | | | | Write a one-line JSON summary to stderr. | | `--timeout` | number | `SECONDS` | | | Cancel the run after SECONDS and exit 4. Refused if the adapter cannot cancel a query; to check, use --info. | | `-t`, `--tuples-only` | boolean | | | | Rows only: no header, no footer. As in psql. | | `--version` | boolean | | | | Show the version and exit. | | `-x`, `--vertical` | boolean | | | | Shorthand for --format vertical. As in psql. | `-a`/`--adapter` names an installed adapter plug-in. `hsql --info` reports adapters installed in your environment. ## Formats `--format` takes one of these names, which affect the layout of data in stdout. Modify output further with options above (e.g., `-t`, `-A`, `--display-rows`). `none` runs the SQL but generates no output. The suffix is what `-o DIRECTORY` names a file with. | Format | Kind | Suffix | Holds several result sets | | --- | --- | --- | --- | | `table` | text layout | `.txt` | yes | | `markdown` | text layout | `.md` | yes | | `md` | text layout | `.md` | yes | | `vertical` | text layout | `.txt` | yes | | `csv` | file | `.csv` | no | | `tsv` | file | `.tsv` | no | | `json` | file | `.json` | no | | `jsonl` | file | `.jsonl` | yes | | `ndjson` | file | `.ndjson` | yes | | `parquet` | file | `.parquet` | no | | `orc` | file | `.orc` | no | | `feather` | file | `.feather` | no | | `arrow` | file | `.arrow` | no | | `none` | writes nothing | | yes | ## Exit codes | Code | Meaning | | --- | --- | | `0` | Success. | | `1` | The database rejected the SQL. | | `2` | A bad flag, a bad profile, or a config file hsql could not read. | | `3` | hsql could not connect. | | `4` | `--timeout` ran out, and hsql stopped the run. | | `130` | Interrupted. | --- Source: https://harlequin.sh/docs/hsql/skill # The hsql Agent Skill hsql ships an [Agent Skill](https://agentskills.io): a markdown file an agent loads when the work involves a database, and keeps in context for the rest of the session. ```bash hsql --skill -o ~/.claude/skills/hsql/ ``` ``` note: wrote 5 files to /home/user/.claude/skills/hsql: SKILL.md, references/config.md, references/queries.md, references/scripting.md, references/troubleshooting.md ``` ## What It Says Nine short sections of standing guidance: 1. **Ask before you assume** — `hsql --info` for versions, config files and capabilities; `hsql --help -a NAME` for one adapter's options. 2. **Keep credentials off the command line** — a [profile](https://harlequin.sh/docs/config-file) and `-P`, with an environment variable for the secret. 3. **Read the [catalog](https://harlequin.sh/docs/hsql/catalog) before writing SQL** — `--catalog`, `--path`, `--catalog-search`, and the `query_name` column rather than an identifier quoted by hand. 4. **Run it** — `-c` and `-f`, `--result`, `--on-error`. 5. **Pick a [format](https://harlequin.sh/docs/hsql/formats) on purpose** — `-tAc` for one value, `--csv` for a pipe, `--markdown` for a reply, parquet for anything large. 6. **[The row limit](https://harlequin.sh/docs/hsql/safety) is real** — 500 by default; read `--stats`, and do not use `2>/dev/null`. 7. **Branch on the [exit code](https://harlequin.sh/docs/hsql/exit-codes)** — `2` is the caller's, `1` is the SQL's, `3` is the environment's. 8. **Ask before you write** — prefer `--read-only`, and say what a DDL or DML statement will change first. 9. **Know when to hand off** — anything destructive, or anything a human will want to iterate on: `harlequin -P `. Four reference files sit beside it, read when the job calls for one: `queries.md`, `config.md`, `scripting.md` and `troubleshooting.md`. > **Note:** `allowed-tools` pre-approves the read-only modes only — `hsql --info`, > `--spec`, `--catalog` and `--catalog-search` — so orienting costs no permission > prompt. Running a query is still a decision somebody makes. ## Installing It ### From the hsql You Have ```bash hsql --skill -o ~/.claude/skills/hsql/ # for you, in every project hsql --skill -o .claude/skills/hsql/ # for this repo, committed with it ``` No network, and the skill matches the hsql on that machine. It works in any harness that reads a skills directory. With no `-o`, `hsql --skill` writes `SKILL.md` to stdout. ### As a Claude Code Plugin The same skill is a plugin in Harlequin's repository: ``` /plugin marketplace add tconbeer/harlequin /plugin install hsql@harlequin ``` The marketplace is added once. After that, updates come with the repository rather than with your Python environment. ### From This Site [harlequin.sh/artifacts/SKILL.md](https://harlequin.sh/artifacts/SKILL.md) is the copy vendored from the latest release, with its reference files beside it at `/artifacts/references/queries.md` and its siblings. Useful when hsql is not installed on the machine doing the reading. When it is installed, prefer `hsql --skill`: that copy cannot describe a different version than the one it is driving. The skill covers habits rather than options. For a flag it does not mention, the [CLI reference](https://harlequin.sh/docs/hsql/reference) is one page, and `hsql --spec` is the same thing as JSON. --- Source: https://harlequin.sh/docs/agent-docs # Agent Docs Every page of these docs is also published as markdown and as JSON, for agents and other programs that read them. Add `.md` to any docs URL for the raw page: `/docs/hsql/exit-codes.md`. The two buttons beside a page title do the same thing. - [llms.txt](https://harlequin.sh/llms.txt) — every page on this site, with a one-line description. - [llms-full.txt](https://harlequin.sh/llms-full.txt) — the whole corpus in one file. - [/api/docs/v1.json](https://harlequin.sh/api/docs/v1.json) — the same index as JSON. `/api/docs/v1/.json` is one page, with its markdown. An agent driving [hsql](https://harlequin.sh/docs/hsql) does not have to read any of it: `hsql --skill` installs an [Agent Skill](https://harlequin.sh/docs/hsql/skill) that covers the same ground, matched to the version installed. --- Source: https://harlequin.sh/docs/adapters # Database Adapters Harlequin uses adapter plug-ins as a generic interface to any database. Harlequin ships with adapters for DuckDB (the default) and SQLite; additional adapters are distributed as their own Python packages that need to be [installed](https://harlequin.sh/docs/getting-started#installing-database-adapters) into the same environment as Harlequin. Once it is installed, to select an adapter other than DuckDB, you use the `--adapter` option (alias `-a`) at the command-line: ```bash harlequin -a sqlite ``` Each adapter has its own configuration options, detailed in their own section in these docs. Running Harlequin with the `--help` option will dynamically include the options for all installed adapters so you can easily reference them. ## Core Adapters Core adapters are created and maintained by the maintainer of Harlequin, Ted Conbeer. - [DuckDB](https://harlequin.sh/docs/duckdb) - [SQLite](https://harlequin.sh/docs/sqlite) - [Postgres](https://harlequin.sh/docs/postgres) - [Redshift](https://harlequin.sh/docs/redshift) (Amazon Redshift and Redshift Serverless) - [Snowflake](https://harlequin.sh/docs/snowflake) - [MySQL/MariaDB](https://harlequin.sh/docs/mysql) - [ODBC](https://harlequin.sh/docs/odbc) (supports MS SQL Server, Oracle, and others) ## Community Adapters Community adapters are created and maintained by other members of the Harlequin community. To add your adapter to this list, please [open a PR](https://github.com/tconbeer/harlequin-web). - [BigQuery](https://harlequin.sh/docs/bigquery), contributed by [Josh Temple](https://github.com/joshtemple) - [Trino](https://harlequin.sh/docs/trino), contributed by [Tyler Hillery](https://github.com/TylerHillery) - [Databricks](https://harlequin.sh/docs/databricks), contributed by [Zach Shirah](https://github.com/zashirah) and [Alex Malins](https://github.com/alexmalins) - [ADBC](https://harlequin.sh/docs/adbc), contributed by [Tyler Hillery](https://github.com/TylerHillery). Supports any database with an Arrow Database Connectivity driver. - [RisingWave](https://harlequin.sh/docs/risingwave), contributed by [ZhengYu Xu](https://github.com/zen-xu) - [Wherobots](https://harlequin.sh/docs/wherobots), contributed by [Wherobots](https://github.com/wherobots) - [Cassandra](https://harlequin.sh/docs/cassandra), contributed by [Vadim Khitrin](https://github.com/vkhitrin) - [NebulaGraph](https://harlequin.sh/docs/nebulagraph), contributed by [Wey Gu](https://github.com/wey-gu) - [Exasol](https://harlequin.sh/docs/exasol), contributed by [Nicola Coretti](https://github.com/Nicoretti) - [H2](https://harlequin.sh/docs/h2), contributed by [clang-engineer](https://github.com/clang-engineer) --- Source: https://harlequin.sh/docs/duckdb # DuckDB Basic Usage ## Installation The DuckDB adapter ships with Harlequin; you do not need to do anything else to install it. If you want to control the version of DuckDB that Harlequin uses, see the [Troubleshooting](https://harlequin.sh/docs/troubleshooting/duckdb-version-mismatch) page. ## Using Harlequin with DuckDB To open an in-memory DuckDB session, run Harlequin with no arguments: ```bash harlequin ``` To open one or more DuckDB database files, pass in relative or absolute paths as connection strings (Harlequin will create DuckDB databases if they do not exist): ```bash harlequin "path/to/duck.db" "another_duck.db" ``` ## Connection Options ### Read-Only You can open a database in read-only mode using the `--read-only` or `-r` flag: ```bash harlequin -r "path/to/duck.db" ``` --- Source: https://harlequin.sh/docs/duckdb/initialization # Initialization Scripts Each time you start Harlequin, it will execute commands from a DuckDB [initialization script](https://duckdb.org/docs/api/cli#configuring-the-cli). Such a script can contain both SQL and DuckDB CLI [dot commands](https://duckdb.org/docs/api/cli#special-commands-dot-commands). For example: ```sql INSTALL httpfs; LOAD httpfs; SET s3_region='us-west-2'; .open './my-database.db' ``` Multi-line SQL is allowed, but must be terminated by a semicolon. Dot commands must be newline-terminated. ## Configuring the Script Location By default, Harlequin will execute the script found at `~/.duckdbrc`. However, you can provide a different path using the `--init-path` option (aliased to `-i` or `-init`): ```bash harlequin --init-path path/to/my/script.sql ``` ## Disabling Initialization If you would like to open Harlequin without running the script you have at `~/.duckdbrc`, you can either pass a nonexistent path to the option above, or start Harlequin with the `--no-init` option: ```bash harlequin --no-init ``` ## Supported Dot Commands Most DuckDB CLI dot commands affect the behavior of the CLI, like the format of its output. Since these are irrelevant to Harlequin, they are ignored. Currently Harlequin rewrites the following dot commands to SQL and executes the SQL: - `.open` is rewritten to `attach` and `use` statements. To request additional dot command support in Harlequin, [open an issue](https://github.com/tconbeer/harlequin/issues/new/choose). --- Source: https://harlequin.sh/docs/duckdb/extensions # Loading Extensions You can install and load [DuckDB extensions](https://duckdb.org/docs/extensions/overview.html) when starting Harlequin, by passing the `-e` or `--extension` flag one or more times: ```bash harlequin -e spatial -e httpfs ``` If you need to load a custom or otherwise unsigned extension, you can use the `-unsigned` flag just as you would with the DuckDB CLI, or `-u` for convenience: ```bash harlequin -u ``` You can also install extensions from custom repos, using the `--custom-extension-repo` option. For example, this combines the options above to load the unsigned `prql` extension: ```bash harlequin -u -e prql --custom-extension-repo http://welsch.lu/duckdb/prql/latest ``` Alternatively, you can use DuckDB's SQL API for loading and installing extensions, either in Harlequin's Query Editor or in an [initialization script](https://harlequin.sh/docs/duckdb/initialization). --- Source: https://harlequin.sh/docs/duckdb/transactions # Transaction Handling In DuckDB, statements are auto-committed by default. That means, for example, a standalone `create table` statement will be committed as soon as the statement finishes executing. To combine multiple statements in a transaction, you must explicitly `begin` a transaction, as in this [example from the DuckDB docs](https://duckdb.org/docs/sql/statements/transactions.html#example): ```sql CREATE TABLE person (name VARCHAR, age BIGINT); -- auto-committed BEGIN TRANSACTION; INSERT INTO person VALUES ('Ada', 52); COMMIT; BEGIN TRANSACTION; DELETE FROM person WHERE name = 'Ada'; INSERT INTO person VALUES ('Bruce', 39); ROLLBACK; SELECT * FROM person; ``` This behavior is not configurable in Harlequin. --- Source: https://harlequin.sh/docs/duckdb/motherduck # MotherDuck You can use Harlequin with [MotherDuck](https://motherduck.com/), just as you would use the DuckDB CLI: ```bash harlequin "md:" ``` You can attach local databases as additional arguments (`md:` has to be first:) ```bash harlequin "md:" "local_duck.db" ``` ## Authentication Options 1. Web browser: Run `harlequin "md:"`, and Harlequin will attempt to open a web browser where you can log in. 2. Environment variable: Set the `motherduck_token` variable before running `harlequin "md:"`, and Harlequin will authenticate with MotherDuck using your service token. 3. CLI option: You can pass a service token to Harlequin with `harlequin "md:" --md_token ` ## SaaS Mode You can run Harlequin in ["SaaS Mode"](https://motherduck.com/docs/authenticating-to-motherduck#authentication-using-saas-mode) by passing the `md_saas` option: `harlequin "md:" --md_saas`. --- Source: https://harlequin.sh/docs/sqlite # SQLite Basic Usage ## Installation The SQLite adapter ships with Harlequin; you do not need to do anything else to install it. ## Using Harlequin with SQLite To open an in-memory SQLite session, run Harlequin with the `-a sqlite` option but no arguments: ```bash harlequin -a sqlite ``` Open one or more SQLite database files by passing in their paths as arguments: ```bash harlequin -a sqlite "path/to/sqlite.db" "another_sqlite.db" ``` ## Connection Options ### Connection Modes Open databases in read-only mode using `-r`: ```bash harlequin -a sqlite -r "path/to/sqlite.db" ``` As an alternative to the `-r` flag, specify a mode parameter directly using the `--mode` option: ```bash harlequin -a sqlite --mode rw ``` ### Lock Timeout Specify a maximum number of seconds Harlequin should wait to read from a table that is locked: ```bash harlequin -a sqlite --lock-timeout 60 ``` ### Statement Caching Specify the number of statements that SQLite should cache, to avoid parsing overhead: ```bash harlequin -a sqlite --cached-statements 256 ``` --- Source: https://harlequin.sh/docs/sqlite/initialization # Initialization Scripts Each time you start Harlequin, it will execute commands from a SQLite [initialization script](https://sqlite.org/cli.html). Such a script can contain both SQL and SQLite CLI [dot commands](https://sqlite.org/cli.html#special_commands_to_sqlite3_dot_commands_). For example: ```sql .open './my-database.sqlite' create table foo as select 1; ``` Multi-line SQL is allowed, but must be terminated by a semicolon. Dot commands must be newline-terminated. ## Configuring the Script Location By default, Harlequin will execute the script found at `~/.sqliterc`. However, you can provide a different path using the `--init-path` option (aliased to `-i` or `-init`): ```bash harlequin -a sqlite --init-path path/to/my/script.sql ``` ## Disabling Initialization If you would like to open Harlequin without running the script you have at `~/.sqliterc`, you can either pass a nonexistent path (or `/dev/null`) to the option above, or start Harlequin with the `--no-init` option: ```bash harlequin -a sqlite --no-init ``` ## Supported Dot Commands Most SQLite CLI dot commands affect the behavior of the CLI, like the format of its output. Since these are irrelevant to Harlequin, they are ignored. Currently Harlequin rewrites the following dot commands to SQL and executes the SQL: - `.open` is rewritten to an `attach ...` statement. - `.load` is rewritten to a `select load_extension(...)` statement. Note: Loading extensions may not be possible with your Python's SQLite distribution. See [extensions](https://harlequin.sh/docs/sqlite/extensions) for more info. To request additional dot command support in Harlequin, [open an issue](https://github.com/tconbeer/harlequin/issues/new/choose). --- Source: https://harlequin.sh/docs/sqlite/extensions # Loading Extensions ## Warning: May not work on your platform! Harlequin uses Python's distribution of SQLite, via its built-in `sqlite3` library. On some (most?) platforms, including MacOS and Ubuntu, this library [disables support for extensions](https://docs.python.org/3/library/sqlite3.html#sqlite3.Connection.enable_load_extension). Windows is the notable exception where this should "just work." To allow Harlequin to load SQLite extensions, you may have to rebuild your Python from source, passing specific [config](https://docs.python.org/3/using/configure.html#cmdoption-enable-loadable-sqlite-extensions) during the Python build process. ## Loading Extensions Using CLI Option You can install and load [SQLite extensions](https://www.sqlite.org/loadext.html) when starting Harlequin, by invoking the `-e` or `--extension` option one or more times: ```bash harlequin -e ./fts5 -e ./json1 ``` The argument to the option should be a path to a SQLite extension executable. Loading specific entrypoints is not supported via the CLI option. ## Loading Extensions via Init Script or SQL API You can use a `.load` command in an [initialization script](https://harlequin.sh/docs/sqlite/initialization) to load an extension (optionally specifying an entrypoint). Or you can execute a `select load_extension(...)` statement in Harlequin's Query Editor. --- Source: https://harlequin.sh/docs/sqlite/transactions # Transaction Handling In SQLite, statements are auto-committed by default. That means, for example, a standalone `create table` statement will be committed as soon as the statement finishes executing. To combine multiple statements in a transaction, you must explicitly `begin` a transaction, or use "Manual" transaction mode (see notes below). ## Manual Transaction Mode ### Pre-requisites To use Manual mode with the SQLite adapter, you must be running **Harlequin v1.20.0** or higher using **Python 3.12** or higher. ### Using Manual Mode In Manual mode, you do not explicitly need to `begin` a transaction: one will be opened for you. You can commit that transaction either by executing a `commit;` query, or pressing the "🡅" button in the Run Query bar. Analogously, you can roll back a transaction by executing `rollback;` or pressing the "⮌" button. --- Source: https://harlequin.sh/docs/postgres # Postgres Basic Usage ## Installation You must install the `harlequin-postgres` package into the same environment as `harlequin`. The best and easiest way to do this is to use `uv` to install Harlequin with the `postgres` extra: ```bash uv tool install 'harlequin[postgres]' ``` ## Using Harlequin with Postgres > **Note:** This adapter uses `psycopg`, which cannot connect to Amazon Redshift. To connect to Redshift, use the [Redshift adapter](https://harlequin.sh/docs/redshift) instead. To connect to a Postgres database, run Harlequin with the `-a postgres` option and pass a [Posgres DSN](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING) as an argument: ```bash harlequin -a postgres "postgres://my-user:my-pass@localhost:5432/my-database" ``` ## Connection Options You can also pass all or parts of the connection string as separate options. The following is equivalent to the above DSN: ```bash harlequin -a postgres -h localhost -p 5432 -U my-user --password my-pass -d my-database ``` The supported connection options are: ``` host port dbname user password passfile require_auth channel_binding connect_timeout sslmode sslcert sslkey ``` For descriptions of each option, run: ``` harlequin --help ``` ## Environment Variables Harlequin's Postgres driver will load connection information from the standard `PG*` environment variables. Any options supplied at the command-line will override environment variables. --- Source: https://harlequin.sh/docs/postgres/multiple # Multiple Databases Currently, the Postgres adapter only supports connections to a single database at a time. To connect to a different database, exit Harlequin and restart it, passing a different DSN, or using the `-d` option to pass a different database name (the `-d` option overrides the database name in the DSN if it is provided). --- Source: https://harlequin.sh/docs/postgres/transactions # Transaction Handling `harlequin-postgres` v0.3 and higher defines two transaction modes: Auto and Manual. You can toggle between these modes using the button in the Run Query Bar. ## Auto Mode In Auto mode, statements are auto-committed by default. That means, for example, a standalone `create table` statement will be committed as soon as the statement finishes executing. ## Manual Mode In Manual mode, new transactions will be automatically opened, but not committed. You can commit that transaction either by executing a `commit;` query, or pressing the "🡅" button in the Run Query bar. Analogously, you can roll back a transaction by executing `rollback;` or pressing the "⮌" button. In Manual Mode, the Data Catalog will not reflect uncommitted changes, since it uses a separate database connection. --- Source: https://harlequin.sh/docs/redshift # Redshift Basic Usage The Redshift adapter is built on [`redshift_connector`](https://github.com/aws/amazon-redshift-python-driver), Amazon's own Python driver. > **Note:** Harlequin's [Postgres adapter](https://harlequin.sh/docs/postgres) uses `psycopg`, which [cannot talk to Redshift](https://github.com/tconbeer/harlequin-postgres/issues/43). Use this adapter instead: it leans on what the official driver and the server offer, including cross-database catalog metadata, `CANCEL`, `SHOW TABLE` / `SHOW VIEW` DDL, the `SVV_*` tuning views, IAM and Redshift Serverless authentication, and federated identity providers. ## Installation You must install the `harlequin-redshift` package into the same environment as `harlequin`. The best and easiest way to do this is to use `uv`: ```bash uv tool install harlequin --with harlequin-redshift ``` To add the adapter to an existing Harlequin installation: ```bash uv tool install --upgrade harlequin --with harlequin-redshift ``` ## Using Harlequin with Redshift To connect to a Redshift cluster, run Harlequin with the `-a redshift` option and pass a connection string as an argument: ```bash harlequin -a redshift "redshift://my-user:my-pass@my-cluster.abc123.us-east-1.redshift.amazonaws.com:5439/dev" ``` A connection string may be a URL, with a `redshift://`, `postgres://`, or `postgresql://` scheme, or a libpq-style keyword string: ```bash harlequin -a redshift "host=localhost port=5439 dbname=dev user=awsuser" ``` ## Connection Options You can also pass all or part of the connection string as separate options. The following is equivalent to the URL above: ```bash harlequin -a redshift -h my-cluster.abc123.us-east-1.redshift.amazonaws.com -p 5439 -d dev -u my-user --password my-pass ``` Options set at the command line, in a [profile](https://harlequin.sh/docs/config-file/profiles), or in the environment override the same setting in the connection string. Extra driver options can also ride along in a URL's query string: ```bash harlequin -a redshift "redshift://my-cluster:5439/dev?iam=true®ion=us-east-1" ``` For descriptions of each option, run: ``` harlequin --help ``` For IAM, Redshift Serverless, and federated identity providers, see [Authentication](https://harlequin.sh/docs/redshift/auth). ## Cancelling a Query Press `ctrl+c` while a query is running. The adapter sends Redshift's `CANCEL ` statement on a second connection, and the cancelled query returns no result instead of raising an error. ## Transaction Modes Click the `Tx:` label in the Run Query Bar to switch between `Auto` and `Manual`. In `Manual`, one transaction stays open across statements, and Harlequin shows Commit and Rollback buttons. See [Managing Transactions](https://harlequin.sh/docs/transactions) for more. ## Read-Only Mode ```bash harlequin --read-only -a redshift "redshift://my-cluster:5439/dev" ``` The adapter asks the server for a session-wide read-only default first, and confirms that the server reports it as on. If the server has no such setting, it opens every transaction with `BEGIN READ ONLY` instead, and confirms that the server reports `transaction_read_only` as on inside one. If neither holds, Harlequin refuses to start rather than hand back a connection that would happily write. Read-only mode applies to both Auto and Manual transaction modes. --- Source: https://harlequin.sh/docs/redshift/auth # Redshift Authentication Besides a database user name and password, the Redshift adapter supports every authentication method that `redshift_connector` does. ## IAM Authentication ```bash harlequin -a redshift --iam --cluster-identifier my-cluster --region us-east-1 --db-user analyst -d dev ``` Credentials come from `--profile`, from `--access-key-id` and `--secret-access-key` (plus `--session-token`), or from the environment, in the driver's usual order. Add `--auto-create` to create `--db-user` if it does not exist, and `--db-groups` to join groups for the session. ## Redshift Serverless ```bash harlequin -a redshift --iam --is-serverless --serverless-work-group my-workgroup --region us-east-1 -d dev ``` ## Federated Identity Providers Set `--credentials-provider` to a plugin that the driver ships, such as `AzureCredentialsProvider`, `OktaCredentialsProvider`, `BrowserSamlCredentialsProvider`, or `BrowserAzureCredentialsProvider`, along with that plugin's options (`--idp-host`, `--login-url`, `--preferred-role`, and so on). For descriptions of each option, run: ``` harlequin --help ``` --- Source: https://harlequin.sh/docs/redshift/catalog # Redshift Data Catalog The catalog is four levels deep: database, schema, relation, column. Each level is loaded only when you open the one above it, so a cluster with thousands of relations costs nothing until you go looking for one. Every level is read through the driver's own metadata calls, so a cluster answers with whichever path it supports: server-side `SHOW` discovery on current clusters, the cross-database `SVV_ALL_*` views, or the driver's legacy `pg_catalog` queries on older ones. That means datashare databases and external (Spectrum) schemas appear in the tree wherever the cluster exposes them. System schemas (`pg_*` and `information_schema`) are not shown. ## Showing Every Database By default, the catalog shows the connected database. Pass `--all-databases` to show every database the cluster exposes metadata for, including the ones a datashare brings in. That flag is off by default because it is not free. It asks the server for cross-database catalog metadata, which is answered by the `SVV_ALL_*` views and is markedly slower, and on some clusters the driver's server-side metadata path cannot serve it at all. With it off, the catalog is read through the fast path, and every level is a single round trip. Relations in another database are given three-part query names, which is how Redshift's cross-database queries address them; relations in the connected database get two-part names. ## Interactions Right-click (or press the context-menu key on) an item in the Data Catalog: | Item | Actions | | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Database | List Schemas, List Relations, Show Storage Summary, Drop Database | | Schema | Set Search Path, List Relations, Show Storage Summary, Drop Schema | | Table | Insert Columns at Cursor, Preview Data, Describe Columns, Show DDL (`SHOW TABLE`), Describe Design (dist key, sort key, encoding), Show Table Info (`SVV_TABLE_INFO`), Describe Constraints, Drop Table | | View | ... plus Show DDL (`SHOW VIEW`), Drop View | | Materialized view | ... plus Show DDL, Show Refresh Info (`SVV_MV_INFO`), Drop Materialized View | | External table | ... plus Show DDL (`SHOW EXTERNAL TABLE`), Show Location & Format, Drop External Table | Most of these write SQL into a new buffer rather than running it, so you see what will hit the cluster before it does. The `Show DDL` actions run their `SHOW` statement, because the DDL is what they return. The drops go through Harlequin's confirmation modal. ## Catalog Search This adapter implements `search_catalog()`, so you can find an object without walking the catalog a level at a time: ```bash hsql -a redshift "redshift://my-cluster:5439/dev" --catalog-search orders ``` A term matches a database, schema, relation, or column whose name contains it. Each level is matched with the same metadata call that builds it in the tree, so a result is the item you would have reached by opening nodes, and it can be used the same way. See [Exploring the Catalog](https://harlequin.sh/docs/hsql/catalog) for more on searching from the command line. Schemas, relations, and columns come from the connected database. The other databases on the cluster are matched by name, which is all the catalog's top level shows for them: searching every database's columns would mean a cross-database scan of `SVV_ALL_COLUMNS`, which does not finish quickly enough to sit behind a search box. > **Tip:** Redshift folds unquoted identifiers to lower case unless the cluster sets `enable_case_sensitive_identifier`, and the server matches these names with `LIKE`, which is case-sensitive. A search therefore tries both the term as typed and its lower-cased form. On a cluster that does use case-sensitive identifiers, a term must match the stored case. ## Autocomplete Beyond the catalog objects Harlequin completes on its own, this adapter provides Redshift's reserved and non-reserved keywords, and the functions and stored procedures the connected cluster reports. --- Source: https://harlequin.sh/docs/snowflake # Snowflake Basic Usage The Snowflake adapter is built on the official [snowflake-connector-python](https://docs.snowflake.com/en/developer-guide/python-connector/python-connector) driver, so everything the connector can do, the adapter can do: every authenticator, `connections.toml`, session parameters, proxies, and Arrow result sets. ## Installation You must install the `harlequin-snowflake` package into the same environment as `harlequin`. The best and easiest way to do this is to use `uv`: ```bash uv tool install harlequin --with harlequin-snowflake ``` To add the adapter to an existing Harlequin installation: ```bash uv tool install --upgrade harlequin --with harlequin-snowflake ``` Harlequin finds the adapter through its `harlequin.adapter` entry point; there is nothing else to configure. ## Using Harlequin with Snowflake To connect to Snowflake, run Harlequin with the `-a snowflake` option: ```bash harlequin -a snowflake ``` There are three ways to say which account to connect to, and they can be mixed; an option always overrides what the connection string said. ### A connections.toml Entry, by Name This is the recommended way, and it uses the same file that the Snowflake CLI and every other Snowflake tool reads. Put this in `~/.snowflake/connections.toml`: ``` [my_account] account = "myorg-myaccount" user = "me@example.com" authenticator = "externalbrowser" warehouse = "COMPUTE_WH" role = "ANALYST" database = "ANALYTICS" schema = "PUBLIC" ``` then: ```bash harlequin -a snowflake my_account ``` A connection string with no `://` in it names an entry this way. The `--connection-name` option does the same thing, and `--connections-file-path` points at a file somewhere other than `~/.snowflake/connections.toml`. ### The Default Connection With no connection string and no account options, the adapter uses the connector's own default connection — the entry named by `default_connection_name` in `config.toml`, or by the `SNOWFLAKE_DEFAULT_CONNECTION_NAME` environment variable: ```bash harlequin -a snowflake ``` ### A Connection String Connection strings are spelled the way `snowflake-sqlalchemy` spells them: ```bash harlequin -a snowflake "snowflake://me:my-password@myorg-myaccount/ANALYTICS/PUBLIC?warehouse=COMPUTE_WH&role=ANALYST" ``` The path is `/database/schema`, and any connector parameter can go in the query string. ## Connection Options Every connection parameter is also a CLI option, which Harlequin will also read from `HARLEQUIN_*` environment variables: ```bash harlequin -a snowflake --account myorg-myaccount --user me --warehouse COMPUTE_WH ``` For descriptions of each option, run: ``` harlequin --help ``` ## Using a Profile Anything you would pass at the command line can live in a [profile](https://harlequin.sh/docs/config-file/profiles) instead, in `~/.config/harlequin/config.toml` or in a `.harlequin.toml` beside the project you are working in. With a `default_profile`, `harlequin` on its own is the whole command: ``` default_profile = "dev" [profiles.dev] adapter = "snowflake" theme = "harlequin" keymap_name = ["vscode"] viewer_max_rows = 100_000 account = "myorg-myaccount" user = "me@example.com" role = "ANALYST" warehouse = "COMPUTE_WH" database = "ANALYTICS" schema = "PUBLIC" # key-pair auth; private_key_file selects it on its own private_key_file = "~/.snowflake/rsa_key.p8" private_key_file_pwd = "..." [profiles.sso] adapter = "snowflake" account = "myorg-myaccount" user = "me@example.com" authenticator = "externalbrowser" client_store_temporary_credential = true warehouse = "COMPUTE_WH" ``` ```bash harlequin # the default profile harlequin -P sso # a named one ``` ## Interactions Right-click (or press `.`) on an item in the Data Catalog to run an interaction against it: - **Database** — Use Database, List Objects, Show DDL, Show Grants, Drop Database - **Schema** — Use Schema, List Objects, Show DDL, Show Grants, Drop Schema - **Relation** — Insert Columns at Cursor, Preview Data, Describe Relation, Show Grants, plus per-kind items: Sample Data, Count Rows, Show DDL, Show View Definition, Show Refresh History (dynamic tables), and the matching Drop - **Column** — Show Value Counts --- Source: https://harlequin.sh/docs/snowflake/auth # Snowflake Authentication Set `--authenticator` (or `authenticator` in `connections.toml`, or in a Harlequin profile) to any of the values the Snowflake connector supports: | Authenticator | What it needs | | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `snowflake` (default) | `--user` and `--password` | | `externalbrowser` | `--user`; opens a browser for SSO. Add `--client-store-temporary-credential` so it does not open one every time. | | `snowflake_jwt` (key pair) | `--user` and `--private-key-file` (plus `--private-key-file-pwd` if the key is encrypted). Passing `--private-key-file` selects this authenticator on its own. | | `oauth` | `--token`, or `--token-file-path` | | `oauth_authorization_code` | `--oauth-client-id`, `--oauth-client-secret`, and optionally the URL options | | `oauth_client_credentials` | `--oauth-client-id`, `--oauth-client-secret`, and `--oauth-token-request-url` | | `programmatic_access_token` | `--user` and the PAT in `--token` | | `username_password_mfa` | `--user`, `--password`, and `--passcode` (or `--passcode-in-password`). Add `--client-request-mfa-token` to cache the token. | | `workload_identity` | `--workload-identity-provider` (`AWS`, `AZURE`, `GCP`, or `OIDC`) | | `https://myorg.okta.com` | `--user` and `--password`, for native Okta | ## Secrets The `--password`, `--token`, `--passcode`, `--private-key-file-pwd`, `--oauth-client-secret`, and `--proxy-password` options are marked as secrets, so Harlequin never prints them back. ## Read-Only Mode > **Note:** Snowflake has no server-enforced read-only session or transaction, so this adapter does not offer Harlequin's `--read-only` option: it would be a promise it could not keep. Connect with a role that only has the privileges you want instead. --- Source: https://harlequin.sh/docs/mysql # Adapter: MySQL/MariaDB ## Installation You must install the `harlequin-mysql` package into the same environment as `harlequin`. The best and easiest way to do this is to use `uv` to install Harlequin with the `mysql` extra: ```bash uv tool install 'harlequin[mysql]' ``` ## Using Harlequin with MySQL or MariaDB To connect to a MySQL or MariaDB database, run Harlequin with the `-a mysql` option and pass connection parameters as CLI options: ```bash harlequin -a mysql -h localhost -p 3306 -U root --password example --database dev ``` The MySQL/MariaDB adapter does not accept a connection string or DSN. ## Connection Options The supported connection options are: ``` host port unix_socket database user password password2 password3 connection_timeout ssl-ca ssl-cert ssl-disabled ssl-key openid-token-file pool-size ``` For descriptions of each option, run: ``` harlequin --help ``` --- Source: https://harlequin.sh/docs/odbc # Adapter: ODBC The ODBC adapter allows Harlequin to work with most databases that support an Open Database Connect driver, including Microsoft SQL Server, Oracle, Teradata, Vertica, and even the best database of all time, Microsoft Excel. ## Installation ### Pre-requisites You will need an ODBC driver manager installed on your OS. Windows has one built-in, but for Unix-based OSes, you will need to download and install one before installing `harlequin-odbc`. You can install unixODBC with `brew install unixodbc` or `sudo apt install unixodbc`. See the [pyodbc docs](https://github.com/mkleehammer/pyodbc/wiki/Install) for more info. Additionally, you will need to install the ODBC driver for your specific database (e.g., `ODBC Driver 18 for SQL Server` for MS SQL Server). For more information, see the docs for your specific database. ### Installing harlequin-odbc You must install the `harlequin-odbc` package into the same environment as `harlequin`. The best and easiest way to do this is to use `uv` to install Harlequin with the `odbc` extra: ```bash uv tool install 'harlequin[odbc]' ``` ## Using Harlequin with an ODBC Driver Run Harlequin with the `-a odbc` option and pass an ODBC connection string as an argument: ```bash harlequin -a odbc 'Driver={ODBC Driver 18 for SQL Server};Server=tcp:harlequin-example.database.windows.net,1433;Database=dev;Uid=harlequin;Pwd=my_secret;Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30;' ``` The ODBC adapter does not accept other options. --- Source: https://harlequin.sh/docs/bigquery # BQ Installation and Configuration The BigQuery adapter was contributed by community member Josh Temple. ## Installation You must install the `harlequin-bigquery` package into the same environment as `harlequin`. The best and easiest way to do this is to use `uv` to install Harlequin with the `bigquery` extra: ```bash uv tool install 'harlequin[bigquery]' ``` ## Using Harlequin with BigQuery Run Harlequin with the `-a bigquery` option; you must also specify values for the `--project` and `--location` options: ```bash harlequin -a bigquery --project my-gcp-project --location us-west1 ``` > **Tip:** See the [next page](https://harlequin.sh/docs/bigquery/auth) for information on authentication and authorization for BigQuery. ## Connection Options This adapter supports the following options: - `project`: The ID of the Google Cloud project to run Harlequin against. Defaults to whatever it can infer from the user's environment, i.e. `gcloud config list project`. - `location`: The [location](https://cloud.google.com/compute/docs/regions-zones#available) used to run the catalog queries, which [must be region-qualified](https://cloud.google.com/bigquery/docs/information-schema-intro#syntax). Defaults to `US`. --- Source: https://harlequin.sh/docs/bigquery/auth # Auth and Permissions ## Authentication This adapter will use [Application Default Credentials](https://cloud.google.com/docs/authentication/application-default-credentials) to authenticate with BigQuery and run queries, including both the queries necessary to populate the data catalog and the queries you type into Harlequin. You can use the `gcloud` CLI to pass user credentials to ADC by running: ```bash gcloud auth application-default login ``` Alternatively, you can authenticate `gcloud` and the ADC toolchain with: ```bash gcloud auth login --update-adc ``` To install the `gcloud` CLI, see [here](https://cloud.google.com/sdk/docs/install). ## Authorization The user will need the permission to query both [`INFORMATION_SCHEMA.TABLES`](https://cloud.google.com/bigquery/docs/information-schema-tables) and [`INFORMATION_SCHEMA.COLUMNS`](https://cloud.google.com/bigquery/docs/information-schema-columns) to load the data catalog. To query these views, you need the following Identity and Access Management (IAM) permissions: - `bigquery.tables.get` - `bigquery.tables.list` - `bigquery.routines.get` - `bigquery.routines.list` Each of the following predefined IAM roles includes the necessary permissions: - `roles/bigquery.admin` - `roles/bigquery.dataViewer` - `roles/bigquery.metadataViewer` For more information about BigQuery permissions, see [Access control with IAM](https://cloud.google.com/bigquery/docs/access-control). --- Source: https://harlequin.sh/docs/trino # Adapter: Trino The Trino adapter was contributed by community member Tyler Hillery. ## Installation You must install the `harlequin-trino` package into the same environment as `harlequin`. The best and easiest way to do this is to use `uv` to install Harlequin with the `trino` extra: ```bash uv tool install 'harlequin[trino]' ``` ## Using Harlequin with Trino For a minimum connection you are going to need: - host - port - user ```bash harlequin -a trino -h localhost -p 8080 -U my_user ``` If your trino instance requires a password you can set the `--require_auth` flag to password and use the `--password` flag for your password ```bash harlequin -a trino -h localhost -p 8080 -U my_user --password my-pass --require_auth password ``` Many more options are available; to see the full list, run: ```bash harlequin --help ``` --- Source: https://harlequin.sh/docs/databricks # Installation and Basic Usage The Databricks adapter was contributed by community member Alex Malins. ## Installation You must install the `harlequin-databricks` package into the same environment as `harlequin`. The best and easiest way to do this is to use `uv` to install Harlequin with the `databricks` extra: ```bash uv tool install 'harlequin[databricks]' ``` ## Using Harlequin with Databricks To connect to Databricks you are going to need to provide as CLI arguments: - server-hostname - http-path - credentials for one of the following authentication methods: - a personal access token (PAT) - a username and password - an OAuth U2M type - a service principle client ID and secret for OAuth M2M ### Personal Access Token (PAT) authentication: ```bash harlequin -a databricks --server-hostname ***.cloud.databricks.com --http-path /sql/1.0/endpoints/*** --access-token dabpi*** ``` ### Username and password (basic) authentication: ```bash harlequin -a databricks --server-hostname ***.cloud.databricks.com --http-path /sql/1.0/endpoints/*** --username *** --password *** ``` ### OAuth U2M authentication: For [OAuth user-to-machine (U2M) authentication](https://docs.databricks.com/en/dev-tools/python-sql-connector.html#auth-u2m) supply either `databricks-oauth` or `azure-oauth` to the `--auth-type` CLI argument: ```bash harlequin -a databricks --server-hostname ***.cloud.databricks.com --http-path /sql/1.0/endpoints/*** --auth-type databricks-oauth ``` ### OAuth M2M authentication: For [OAuth machine-to-machine (M2M) authentication](https://docs.databricks.com/en/dev-tools/python-sql-connector.html#oauth-machine-to-machine-m2m-authentication) you need to `pip install databricks-sdk` as an additional dependency ([databricks-sdk](https://github.com/databricks/databricks-sdk-py) is an optional dependency of `harlequin-databricks`) and supply `--client-id` and `--client-secret` CLI arguments: ```bash harlequin -a databricks --server-hostname ***.cloud.databricks.com --http-path /sql/1.0/endpoints/*** --client-id *** --client-secret *** ``` ## Store an alias for your connection string We recommend you include an alias for your connection string in your `.bash_profile`/`.zprofile` so you can launch harlequin-databricks with a short command like `hdb` each time. Run this command (once) to create the alias: ```bash echo 'alias hdb="harlequin -a databricks --server-hostname ***.cloud.databricks.com --http-path /sql/1.0/endpoints/1234567890abcdef --access-token dabpi***"' >> .bash_profile ``` ## Using Unity Catalog and want fast Data Catalog indexing? Supply the `--skip-legacy-indexing` command line flag if you do not care about legacy metastores (e.g. `hive_metastore`) being indexed in Harlequin's Data Catalog pane. This flag will skip indexing of old non-Unity Catalog metastores (i.e. they won't appear in the Data Catalog pane with this flag). Because of the way legacy Databricks metastores works, a separate SQL query is required to fetch the metadata of each table in a legacy metastore. This means indexing them for Harlequin's Data Catalog pane is slow. Databricks's Unity Catalog upgrade brought [Information Schema](https://docs.databricks.com/en/sql/language-manual/sql-ref-information-schema.html), which allows harlequin-databricks to fetch metadata for all Unity Catalog assets with only two SQL queries. So if your Databricks instance is running Unity Catalog, and you no longer care about the legacy metastores, setting the `--skip-legacy-indexing` CLI flag is recommended as it will mean much faster indexing & refreshing of the assets in the Data Catalog pane. ## Other CLI options: For more details on other command line options, run: ```bash harlequin --help ``` ## Issues, Contributions and Feature Requests Please report bugs/issues with the harlequin-databricks adapter via its GitHub [issues](https://github.com/alexmalins/harlequin-databricks/issues) page. You are welcome to attempt fixes yourself by forking that repo then opening a [PR](https://github.com/alexmalins/harlequin-databricks/pulls). For feature suggestions, please post in the harlequin-databricks repo [discussions](https://github.com/alexmalins/harlequin-databricks/discussions). --- Source: https://harlequin.sh/docs/databricks/initialization # Initialization Scripts Each time you start Harlequin, it will execute SQL commands from a Databricks initialization script. For example: ```sql USE CATALOG my_catalog; SET TIME ZONE 'Asia/Tokyo'; DECLARE yesterday DATE DEFAULT CURRENT_DATE - INTERVAL '1' DAY; ``` Multi-line SQL is allowed, but must be terminated by a semicolon. ## Configuring the Script Location By default, Harlequin will execute the script found at `~/.databricksrc`. However, you can provide a different path using the `--init-path` option (aliased to `-i` or `-init`): ```bash harlequin -a databricks --init-path /path/to/my/script.sql ``` ## Disabling Initialization If you would like to open Harlequin without running the script you have at `~/.databricksrc`, you can either pass a nonexistent path (or `/dev/null`) to the option above, or start Harlequin with the `--no-init` option: ```bash harlequin -a databricks --no-init ``` --- Source: https://harlequin.sh/docs/adbc # Adapter: ADBC The ADBC adapter was contributed by community member Tyler Hillery. _This documentation is Copyright 2024 Tyler Hillery, reproduced here under an [MIT License](https://github.com/TylerHillery/harlequin-adbc/blob/main/LICENSE). See the [repository](https://github.com/TylerHillery/harlequin-adbc) for the most up-to-date documentation._ ## Warning ADBC is a very new database connectivity method compared to ODBC, JDBC that aims at providing a more efficient way to transfer columnar data over the wire. Due to the recency of its development, there is various level of functionality across drivers which may cause issues. ## Installation `harlequin-adbc` depends on `adbc_driver_manager`, `harlequin` and `pyarrow`, so installing this package with also install these dependencies. You should also install the adbc driver(s) for the database(s) you plan on connecting to, otherwise you will have to download the driver yourself from another place and provide the `--driver-path` cli option. The following drivers are available as Python packages: - adbc-driver-flightsql - adbc-driver-postgresql - adbc-driver-snowflake - adbc-driver-sqlite > **Note:** If you don't install the driver but provide a `--drive-type` cli argument you will get an `ImportError` when you run Harlequin. Example usage: ```bash uv tool install 'harlequin[adbc]' --with adbc-driver-snowflake ``` ## Usage and Configuration Run Harlequin with the `-a adbc` option and pass in a connection string as an argument. The format of the connection string will depend on the driver you are using. You will also need to provide either the `--driver-type` option or the `--driver-path`. ### Driver Type (preferred) When you use the --driver-type option it will try to dynamically use the driver package of the type selected `adbc-driver-{driver type}`. That is why it's crucial to also have that package also install in the virtual environment where Harlequin is installed. - `--driver-type` with one of the following options - `flightsql`, `postgresql`, `snowflake`, `sqlite`, `duckdb` ### Driver Path The other option is to pass the file path location of the adbc driver that you are using. Note this method is not well tested. - `--driver-path` ### DB Kwargs String (Optional) Since the drivers implement so many different options to pass through when you connect to the database this is a way to pass through these options. The format of the string is key=value separated by ; - `--db-kwargs-str` Example: ```bash `--db-kwargs-str "username=flight_username;password=flight_password;adbc.flight.sql.client_option.tls_skip_verify=true"` ``` This will parse the string and pass through these values into the `db_kwargs` value in the `dbapi.connect()` method. Note the parser relies on the ; and = so if any of of the parameters in the string contain either of these characters it's not going to work. This is a known limitation and something being worked on. ### Snowflake Driver The Snowflake URI should be of one of the following formats: - `user[:password]@account/database/schema[?param1=value1¶mN=valueN]` - `user[:password]@account/database[?param1=value1¶mN=valueN]` - `user[:password]@host:port/database/schema?account=user_account[¶m1=value1¶mN=valueN]` - `host:port/database/schema?account=user_account[¶m1=value1¶mN=valueN]` Check the [Snowflake ADBC Driver Docs](https://arrow.apache.org/adbc/main/driver/snowflake.html) for more details. Example usage: ```bash harlequin -a adbc "$SNOWFLAKE_URI" --driver-type snowflake ``` ### FlightSQL Driver Example usage: ```bash harlequin -a adbc "grpc+tls://localhost:31337" --driver-type flightsql --db-kwargs-str "username=flight_username;password=flight_password;adbc.flight.sql.client_option.tls_skip_verify=true" ``` Check the [FlightSQL ADBC Driver Docs](https://arrow.apache.org/adbc/main/driver/flight_sql.html) for more details. ### Postgres Driver > **Tip:** Harlequin also has a Postgres adapter, which connects using Psycopg, instead of ADBC. For more information, see [this page](https://harlequin.sh/docs/postgres). The Postgres URI should be in the format of a [Postgres DSN](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING): ```bash harlequin -a adbc --driver-type postgresql "postgres://my-user:my-pass@localhost:5432/my-database" ``` ### DuckDB and SQLite While DuckDB and SQLite both have ADBC drivers it's not recommend to use them. Harlequin natively supports both of the databases without having to install any other dependencies. ## Known Issues - Snowflake adbc driver seems to be the only driver that returns the `xdbc_data_type` from `adbc_get_objects()` - Snowflake adbc driver has a bug with `adbc_get_table_schema()` that returns `adbc_driver_manager.OperationalError: IO: sql: expected 12 destination arguments in Scan, not 11` - The PostgreSQL adbc driver is overall buggy and when executing queries you might get the error `IO: [libpq] Fetch header failed: no COPY in progress` - SQLite and DuckDB don't have the same level of `depth` for `adbc_get_objects()` compared to other dbs which causes weird issues. - DuckDB driver uses different names for the `adbc_get_objects()` which causes things to break. --- Source: https://harlequin.sh/docs/risingwave # Adapter: RisingWave _This documentation is Copyright 2024 ZhengYu, Xu, reproduced here under an [MIT License](https://github.com/zen-xu/harlequin-risingwave/blob/main/LICENSE). See the [repository](https://github.com/zen-xu/harlequin-risingwave) for the most up-to-date documentation._ ## Installation You must install the `harlequin-risingwave` package into the same environment as `harlequin`. The best and easiest way to do this is to use `uv` to install Harlequin with the additional package: ```bash uv tool install harlequin --with harlequin-risingwave ``` ## Usage and Configuration Run Harlequin with the `-a risingwave` option and pass a [Posgres DSN](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING) as an argument: ```bash harlequin -a risingwave "postgres://my-user:my-pass@localhost:5432/my-database" ``` You can also pass all or parts of the connection string as separate options. The following is equivalent to the above DSN: ```bash harlequin -a risingwave -h localhost -p 5432 -U my-user --password my-pass -d my-database ``` Many more options are available; to see the full list, run: ```bash harlequin --help ``` For more information, see the [Postgres docs](https://harlequin.sh/docs/postgres). --- Source: https://harlequin.sh/docs/wherobots # Adapter: Wherobots _This documentation is Copyright Wherobots, reproduced here under an [Apache 2.0 License](https://github.com/wherobots/harlequin-wherobots/blob/main/LICENSE). See the [repository](https://github.com/wherobots/harlequin-wherobots) for the most up-to-date documentation._ This repository provides the Harlequin adapter for WherobotsDB, using the Wherobots Spatial SQL API and its [wherobots-python-dbapi-driver](https://github.com/wherobots/wherobots-python-dbapi-driver). ## Installation You must install the `harlequin-wherobots` package into the same environment as `harlequin`. The best and easiest way to do this is to use `uv` to install Harlequin with the additional package: ```bash uv tool install harlequin --with harlequin-wherobots ``` ## Usage Procure an API key from Wherobots, and start Harlequin with the required parameters: ```bash harlequin -a wherobots --api-key ``` Alternatively, you can use your session token: ```bash harlequin -a wherobots --token ``` The Harlequin adapter for Wherobots will automatically start a Wherobots SQL session with the default runtime (Tiny, 4 executors) in the default Wherobots public compute region (AWS `us-west-2`). You can override those defaults with the `--runtime` and `--region` options, respectively: ```bash harlequin -a wherobots --api-key --runtime MEDIUM --region AWS_US_WEST_2 ``` > **Tip:** Community Edition users of Wherobots Cloud are restricted to the "Tiny" runtime size. See Wherobots > [Pricing](https://www.wherobots.com/pricing) for more information. ## Advanced options If your SQL session is already provisioned and running, you can force the driver to directly connect to it via its WebSocket URL (without protocol version): ```bash harlequin -a wherobots --api-key --ws-url ``` You can also specify the base hostname of the Wherobots stack to interact with as the first positional parameter. By default, the driver connects to `cloud.wherobots.com`, the official public Wherobots service. ```bash harlequin -a wherobots --api-key [host] ``` --- Source: https://harlequin.sh/docs/cassandra # Adapter: Cassandra The Cassandra adapter was contributed by community member Vadim Khitrin. > **Warning:** This adapter is unstable and experimental. Some quirks are to be expected. > > Python 3.14 is not supported by this adapter, underlying DataStax Cassandra python driver. > **Note:** This adapter does not aim to support [Scylla](https://www.scylladb.com). ## Integration With Harlequin Cassandra doesn't use cursor(s), thus `HarlequinCursor` and `HarlequinConnection` behave differently in this adapter. A manual translation of `cassandra-driver` objects types to Python types is required for Apache Arrow to work correctly. In this adapter, [`Transaction Modes`](https://harlequin.sh/docs/transactions) refers to Cassandra's consistency levels. ## Installation You must install the `harlequin-cassandra` package into the same environment as `harlequin`. The best and easiest way to do this is to use `uv` to install Harlequin with the `cassandra` extra: ```bash uv tool install 'harlequin[cassandra]' ``` ## Connection Options - `--host` - Specifies the initial host to connect to. After the driver successfully connects to the node, it will auto discoverthe rest of the nodes in the cluster and will connect to them. - `--port` - Port number to connect to at the server host. - `--keyspace` - The keyspace name to use when connecting with the Cassandra server. - `--username` - Cassandra user name to connect as. - `--password` - Password to be used if the server demands password authentication. - `--protocol-version` - The maximum version of the native protocol to use. If not specified, will be auto-discovered by the driver. - `--consistency-level` - Specifies how many replicas must respond for an operation to be considered asuccess. To see the full list of options, run: ```bash harlequin --help ``` --- Source: https://harlequin.sh/docs/nebulagraph # Adapter: NebulaGraph The NebulaGraph adapter was contributed by community member Wey Gu. ## Installation You must install the `harlequin-nebulagraph` package into the same environment as `harlequin`. The best and easiest way to do this is to use `uv` to install Harlequin with the additional package: ```bash uv tool install harlequin --with harlequin-nebulagraph ``` ## Usage and Configuration Run Harlequin with the `-a nebulagraph` option and pass connection parameters as CLI options: ```bash harlequin -a nebulagraph -h 127.0.0.1 -p 9669 -u root --password password ``` ## Demo [Watch the video](https://github.com/wey-gu/harlequin-nebulagraph/assets/1651790/b27c0ea2-4080-4313-9607-285e477d1898) Many more options are available; to see the full list, run: ```bash harlequin --help ``` --- Source: https://harlequin.sh/docs/exasol # Adapter: Exasol The Exasol adapter was contributed by community member Nicola Coretti. _This documentation is Copyright Exasol, reproduced and adapted here under an [MIT License](https://github.com/Nicoretti/harlequin-exasol/blob/main/LICENSE). See the [repository](https://github.com/Nicoretti/harlequin-exasol) for the most up-to-date documentation._ > **Warning:** The current state of this project is a spike—an initial evaluation of what is possible and how much effort specific tasks will require. It should only be used for evaluating Exasol usage via Harlequin. > > Below, you will find information if you are interested in trying it out and getting an idea of it. While issues reported beyond the mentioned limitations are welcome for tracking purposes, addressing these issues is unlikely at any point. However, having a list of issues may be helpful to other evaluators. ## 🚀 Features - Basic Catalog - Basic Query Completion - Basic Query Support, including DDL ## Installation You must install the `harlequin-exasol` package into the same environment as `harlequin`. The best and easiest way to do this is to use `uv` to install Harlequin with the additional package: ```bash uv tool install harlequin --with 'harlequin-exasol' ``` ## Using Harlequin with Exasol To connect to a Postgres database, run Harlequin with the `-a exasol` option and pass connection parameters as options: ```bash harlequin -a exasol --schema 'foo' --host '8.9.10.1' --port 8563 ... ``` For connecting to a standard [Exasol Docker DB](https://hub.docker.com/r/exasol/docker-db/), most defaults should work just fine: ```bash harlequin -a exasol --disable-certificate-validation ``` ## 💥 Known Issues - Queries cannot be sent while metadata is loading. (@exaSR) - Only empty error windows will be shown. (Multiple Reports) --- Source: https://harlequin.sh/docs/h2 # Adapter: H2 The H2 adapter was contributed by community member [clang-engineer](https://github.com/clang-engineer). See the [harlequin-h2 repository](https://github.com/clang-engineer/harlequin-h2) for the most up-to-date documentation. ## Installation Install the adapter into the same environment as Harlequin: ```bash uv tool install harlequin --with harlequin-h2 ``` The adapter requires a Java runtime compatible with your H2 version and an H2 2.x JDBC driver JAR. If the adapter does not discover the JAR automatically, provide its path with `--jar` or the `H2_JAR` environment variable. ## Usage Select the adapter with `-a h2` and pass an H2 JDBC URL. ### Embedded file database ```bash harlequin -a h2 -U sa \ "jdbc:h2:file:/path/to/database;AUTO_SERVER=TRUE;IFEXISTS=TRUE" ``` `AUTO_SERVER=TRUE` allows Harlequin and another JVM process to share the file. `IFEXISTS=TRUE` prevents a mistyped path from creating a new empty database. ### Embedded memory database ```bash harlequin -a h2 "jdbc:h2:mem:demo" ``` The named database normally exists until its last connection closes. Add `;DB_CLOSE_DELAY=-1` only when it must survive connection closure; H2 then retains it until `SHUTDOWN` or process exit. ### TCP server ```bash harlequin -a h2 -U sa "jdbc:h2:tcp://localhost/~/demo" ``` ## Options - `--jar PATH`: Path to the H2 JDBC driver JAR. - `-U, --user USER`: H2 username; defaults to `sa`. - `--password PASSWORD`: H2 password; defaults to an empty string. Prefer a protected Harlequin profile or an environment-variable reference for passwords because command-line arguments may be visible to other local processes. --- Source: https://harlequin.sh/docs/config-file # Config Overview Typing in command-line options with every invocation of Harlequin can get tiring. Instead, you can create profiles (sets of configurations that specify adapter and database connection options). Those profiles are saved in config files, which Harlequin will discover and load automatically. Selecting a profile is a simple command-line flag, or config files can define a default. Config files are simple text files, written in TOML. Harlequin provides a wizard for creating and editing config files. Harlequin searches for config files in several different locations, merging multiple files if many are found. When you run Harlequin, you select a specific profile to use. These three elements are detailed on the following pages. --- Source: https://harlequin.sh/docs/config-file/creating-config # Creating Config Files You can create config files manually, using any text editor. However, Harlequin can help make that process easier with its config wizard. To launch the wizard, run Harlequin with the `--config` option: ```bash harlequin --config ``` Harlequin will then prompt you for the path to the config file to generate or edit, the name of the profile to create or update, and to provide values for all available options. ![Example of the config wizard.](https://harlequin.sh/_app/immutable/assets/config-wizard.Bkr02qsx.png) *Example of the config wizard.* ## Config File Schema Config files are written in [TOML](https://toml.io/en/). Config files define one or more profiles, which contain keys that map to Harlequin options or adapter options. Each profile is a TOML table with the key `[profiles.]`. Config files may also define a default profile, which Harlequin will automatically load if invoked without the `--profile` option. For example, this is a valid config file: ```toml default_profile = "my-duckdb-profile" [profiles.my-duckdb-profile] limit = 200_000 adapter = "duckdb" conn_str = ["my-database.db"] read_only = true extension = ["httpfs", "spatial"] init_path = "~/.duckdbrc" [profiles.local-postgres] theme = "gruvbox" limit = 10_000 adapter = "postgres" host = "localhost" user = "postgres" password = "secretadminpassword" dbname = "postgres" port = 5432 ``` ### Using pyproject.toml If configuring Harlequin using `pyproject.toml`, you must nest the above config under the `tool.harlequin` table. An example `pyproject.toml` file: ```toml [tool.harlequin] default_profile = "my-duckdb-profile" [tool.harlequin.profiles.my-duckdb-profile] limit = 200_000 conn_str = ["my-database.db"] [tool.harlequin.profiles.local-postgres] theme = "gruvbox" limit = 10_000 ... ``` ### Option names To view a list of available options (including options for your installed adapters), run `harlequin --help`. The names of options in the config file are the `snake_case` version of the command-line option. For example, the command-line option `--read-only` becomes `read_only` in the config file. --- Source: https://harlequin.sh/docs/config-file/discovery # Discovering Config Files Harlequin loads config files from the following locations. If it finds multiple files, it merges them, with items listed first taking priority: 1. The file located at the path provided by the `--config-path` CLI option (see below). 2. Files named `harlequin.toml`, `.harlequin.toml`, or `pyproject.toml` in the current working directory. 3. Files named `harlequin.toml`, `.harlequin.toml`, or `config.toml` in the user's default config directory, in the `harlequin` subdirectory. For example: - Linux: `$XDG_CONFIG_HOME/harlequin/config.toml` or `~/.config/harlequin/config.toml` - Mac: `~/Library/Application Support/harlequin/config.toml` - Windows: `~\AppData\Local\harlequin\config.toml` 4. Files named `harlequin.toml`, `.harlequin.toml`, or `pyproject.toml` in the user's home directory (`~`). ### Custom Config Path You can specify a custom path to a config file by invoking Harlequin with the `--config-path` option: ```bash harlequin --config-path /path/to/my/file.toml ``` You can also use the `$HARLEQUIN_CONFIG_PATH` environment variable as an alternative way to specify a custom config file path. ```bash export HARLEQUIN_CONFIG_PATH=/path/to/my/file.toml harlequin ``` If both are provided, the CLI option takes precedence over the environment variable. --- Source: https://harlequin.sh/docs/config-file/profiles # Selecting a Profile All configs are nested within profiles. You may wish to use distinct profiles for connecting to different databases, or just to change the theme from time to time. Config files can also specify a default profile. In this case, invoking Harlequin without the `--profile` option will cause it to load the configuration from the default profile. To load Harlequin with the config from a specific profile, invoke Harlequin with the `--profile` option (alias `-P`): ```bash harlequin --profile my-profile ``` If a default profile is specified, but you wish to run Harlequin without the config from the default profile, invoke Harlequin with the special profile named `None`: ```bash harlequin --profile None ``` Alternatively, any options given at the command-line will override their counterparts in config files. --- Source: https://harlequin.sh/docs/files # Files Overview Harlequin's Data Catalog optionally displays file trees for either local files or remote objects stored in Amazon S3 (or another object storage service that provides an S3-compatible API.) To view the file tree, use your mouse to select the "Files" tab, or focus on the Data Catalog with `F6` and then switch tabs with `k` or `j`. Insert file paths into the query editor with `ctrl+enter` or `ctrl+j`, or copy them to the clipboard with `ctrl+c`. ![Example of the file tree.](https://harlequin.sh/_app/immutable/assets/file-tree.3lRp44pm.png) *Example of the file tree.* Keep reading for: 1. [Local Files](https://harlequin.sh/docs/files/local) 2. [Remote Objects (S3)](https://harlequin.sh/docs/files/remote) --- Source: https://harlequin.sh/docs/files/local # Local Files Harlequin's Data Catalog will show local files in a second tab in the Data Catalog if Harlequin is initialized with the `--show-files` option (alias `-f`). `--show-files` takes an absolute or relative file path to a directory as its argument: For example, an absolute path: ```bash harlequin --show-files /path/to/my/data ``` For the current working directory: ```bash harlequin -f . ``` --- Source: https://harlequin.sh/docs/files/remote # Remote Objects (S3) ## Installation Before viewing remote objects, you must install the `boto3` package in the same environment as Harlequin. You can do this by installing Harlequin with the `s3` extra: ```bash uv tool install 'harlequin[s3]' ``` ## Compatibility Harlequin works with any object storage system that provides an S3-compatible API, including Amazon S3, Google Cloud Storage, and Minio; basically, if you can query the storage with `boto3` and manage credentials with the AWS CLI, Harlequin can display your files. ## Authentication Harlequin relies on the AWS CLI credential toolchain for authentication. Specifically, it will attempt to connect to your storage using whatever credentials are currently active (or default) in your AWS CLI config, **including the region**. You can use the credentials from another profile by setting the `AWS_PROFILE` environment variable. For Google Cloud Storage please see [the docs](https://cloud.google.com/storage/docs/authentication/hmackeys) on the XML API and HMAC authentication. After generating HMAC Keys, you can use the AWS CLI (`aws configure`) to store these keys in a profile accessible to Harlequin. Your user must have `ListObjects` or the equivalent permission to view a bucket's objects in Harlequin. Currently this is not configurable; if that doesn't work for you, please [open an issue](https://github.com/tconbeer/harlequin/issues/new/choose). ## Usage Harlequin will display the remote tree if it is initialized with the `--show-s3` option (alias `--s3`). This option takes a reference to remote object storage. ### Displaying All Buckets Use Harlequin with `--show-s3 all` to display all Amazon S3 buckets that the authenticated user has access to. (This is not advised if you have access to millions of objects in S3): ```bash harlequin --show-s3 all ``` For GCS or another endpoint that supports `ListBuckets`, provide the endpoint url without a path: ```bash harlequin --show-s3 "https://storage.googleapis.com" ``` ### Displaying a Single Bucket Use `--show-s3` with an argument that represents a bucket and (optionally) an endpoint url and key prefix: ```bash harlequin --show-s3 my-bucket ``` ```bash harlequin --show-s3 my-bucket/my-prefix ``` A one-liner to set the AWS Profile and connect to a GCS bucket, filtering for a prefix: ```bash AWS_PROFILE=gcs harlequin --s3 "https://storage.googleapis.com/my-gcs-bucket/my-prefix" ``` Harlequin takes any of the following formats as a value for the `--s3` option (you likely have to wrap these in single or double quotes, depending on your shell): ``` # Amazon S3 Formats all my-bucket my-bucket/my-prefix s3://my-bucket s3://my-bucket/my-prefix https://s3.amazonaws.com/my-bucket https://s3.amazonaws.com/my-bucket/my-prefix https://my-bucket.s3.amazonaws.com https://my-bucket.s3.amazonaws.com/my-prefix # Google Cloud Storage Formats https://storage.googleapis.com https://storage.googleapis.com/my-bucket https://storage.googleapis.com/my-bucket/my-prefix https://my-bucket.storage.googleapis.com https://my-bucket.storage.googleapis.com/my-prefix # Minio, AWS PrivateLink, etc. https://my-storage.com/my-bucket/ https://my-storage.com/my-bucket/my-prefix ``` --- Source: https://harlequin.sh/docs/themes # Choosing a Theme You can set a theme for Harlequin, passing the name of any Textual Theme to the `--theme` or `-t` option. ```bash harlequin --theme gruvbox ``` Depending on the number of colors supported by your terminal and shell, some themes [may not look great](https://harlequin.sh/docs/troubleshooting/appearance#colors). For any terminal, we can recommend `harlequin` (the default). To see a list of theme names, run `harlequin --help`. [See the themes rendered on harlequin.sh](https://harlequin.sh/docs/themes) --- Source: https://harlequin.sh/docs/keymaps # About Key Bindings ## About Key Bindings and Keymaps A **key binding** associates a key press, within a context, to an action. A **keymap** is a named set of key bindings. Harlequin gets all of its key bindings from the keymaps it discovers and loads when it starts. These keymaps are loaded either from plug-ins (installed Python packages) or TOML config files. Harlequin ships with a single keymap plug-in that defines all of its default bindings. That default keymap is called `vscode`, since many of its bindings mimic those in the popular text editor. ## Changing Key Bindings Changing key bindings in Harlequin is a two-step process: 1. Install a keymap plug-in or [create](https://harlequin.sh/docs/keymaps/config) a new keymap in a config file. 2. [Select](https://harlequin.sh/docs/keymaps/usage) the keymap when starting Harlequin. --- Source: https://harlequin.sh/docs/keymaps/config # Creating a Keymap Keymaps can be defined in Harlequin [config files](https://harlequin.sh/docs/config-file), under the `keymaps` key. You can create these keymaps manually in a text editor, or by using the [Harlequin Keys App](#keys-app). ## What is a Keymap? In a config file, a keymap is an ["array of tables"](https://toml.io/en/v1.0.0#array-of-tables), where each table defines a key binding. A simple keymap looks like this: ```toml [[keymaps.more_arrows]] keys="w" action="results_viewer.cursor_up" key_display="⬆/w" [[keymaps.more_arrows]] keys="a" action="results_viewer.cursor_left" key_display="⬅/a" [[keymaps.more_arrows]] keys="s,j" action="results_viewer.cursor_down" key_display="⬇/s/j" [[keymaps.more_arrows]] keys="d" action="results_viewer.cursor_right" key_display="➡/d" ``` This keymap is named `more_arrows`, and it maps the keys `w`, `a`, `s`, `j`, and `d` to actions that move the cursor in the Results Viewer. The arrow keys are already mapped to these actions in the default keymap, so this keymap is a good example of [extending the default keymap](https://harlequin.sh/docs/keymaps/usage#extending-a-keymap). The items in each table are as follows: ### Keys The `keys` item is a string that must be a comma-separated list of Textual virtual key names. These are usually intuitive names like `enter` and `ctrl+f`, but depending on your terminal and shell, many keypresses will be aliased to different key names by the time they reach Harlequin. The best way to ensure the correct key name is to use the [Keys App](#keys-app). ### Action The `action` item is a string that must be equal to the name of a Harlequin Action. A full list of action names can be found in the Harlequin [source code](https://github.com/tconbeer/harlequin/blob/main/src/harlequin/actions.py). All actions are also listed (with aliased/formatted names) in the [Keys App](#keys-app). Actions are context-specific, so they are already scoped to either the entire app or a specific widget. Those that are scoped to a widget have names that take the form `.`. ### Key Display Harlequin's Footer can display currently-active (in-scope) key bindings. Many bindings are hidden by default. By including a `key_display` item in each table, Harlequin will show the binding, optionally with a custom symbol. ## Keys App Harlequin ships with an app that makes it easy to create your own custom keymap. To start the app, start harlequin with the `--keys` option: ```bash harlequin --keys ``` The app will load the currently-active config (from discovered TOML files, in the same manner as Harlequin) and show a list of all configured key bindings (using the default profile and its specified keymaps). You can load the Keys App with options that specify a config file, profile, and/or keymap name if you would like, using command-line options: ```bash harlequin --config-path ~/my-config.toml --profile Foo --keys ``` > **Tip:** The `--config-path`, `--profile`, `--keymap-name`, and `--theme` options must be declared before the `--keys` option for this to work. ![Screenshot of the main screen of the Keys App.](https://harlequin.sh/_app/immutable/assets/keys-app.Br97XlBL.png) *The main screen of the Keys App.* In the app, you can use the arrow keys to scroll up and down the list of bindings, then press `enter` to edit a binding. You can replace an existing key, or add or remove keys that are bound to each action by using the buttons in the Edit modal. ![Screenshot of the Edit modal of the Keys App.](https://harlequin.sh/_app/immutable/assets/keys-app-edit.J7C2b_Rb.png) *The Edit modal of the Keys App.* After editing bindings, press `ctrl+q` to quit the Keys App. You will be prompted for a config file location and a keymap name. Remember this name -- you will need it in the next step, when configuring Harlequin to use your keymap. If you select "Save + Quit," Harlequin will write the full keymap to the location you specify. --- Source: https://harlequin.sh/docs/keymaps/usage # Selecting Keymaps After you have [created a keymap](https://harlequin.sh/docs/keymaps/config) or installed a keymap plug-in, you need to configure Harlequin to use that keymap. ## Replacing the Default Keymap If you create a keymap with the [Keys App](https://harlequin.sh/docs/keymaps/config#keys-app), or if you install a plug-in that defines a complete keymap, then you should specify **only** that keymap when you start Harlequin. You can select a keymap using the `--keymap-name` CLI option (or in your config file, see below): ```bash harlequin --keymap-name "my-complete-keymap" ``` ## Extending a Keymap Alternatively, you can create a partial keymap that only specifies a subset of bindings. Harlequin can load multiple keymaps and merge them by unioning the bindings found in all the configured keymaps (this may cause some conflicts and undesired behavior). To extend a keymap, specify multiple keymaps by repeating the command-line option. For example, to extend the default `vscode` keymap with the `more_arrows` keymap example from the previous page: ```bash harlequin --keymap-name "vscode" --keymap-name "more_arrows" ``` ## Using Config Files and Profiles You can also use a Profile to define the keymaps loaded by Harlequin, instead of repeating the CLI option every time. See [config file](https://harlequin.sh/docs/config-file) for more information. An example of a config file with two profiles, equivalent to the options above: ```toml default_profile = "my-first-profile" [profiles.my-first-profile] keymap_name = ["my-complete-keymap"] [profiles.my-second-profile] keymap_name = ["vscode", "more_arrows"] ``` --- Source: https://harlequin.sh/docs/export # Exporting Data Harlequin's Results Viewer is a great way to see query results, but sometimes you need to export data to use it in a different tool. Harlequin provides two easy options for this. ## Using the Clipboard The Results Viewer can copy selected data to the clipboard. First, select a range of cells using `ctrl+a` (to select all), holding `shift` while using arrows or other keys to move the cursor, or by clicking and dragging. Then press `ctrl+c` to copy the data to the clipboard. Data is copied in a tab-separated-values format. This format is compatible with many other applications, and pastes nicely into Excel, Google Sheets, and the Harlequin Query Editor. > **Tip:** Copying works best when Harlequin has access to the system clipboard. If it doesn't work out of the box, see the [troubleshooting guide](https://harlequin.sh/docs/troubleshooting/copying-and-pasting) for more information. ## Exporting Files Copying and Pasting is quick and easy, but often it is better to export he results of a query as a file. Harlequin provides a utility to export data in common formats, including CSV, Parquet, JSON, ORC, and Feather. First, execute your query. Then, with the results visible, press `ctrl+e` to open the Data Exporter screen. Enter a file path, then select a format. Harlequin will then display the relevant options for that format. ![A screenshot of Harlequin's Data Exporter screen, after selecting the CSV format.](https://harlequin.sh/_app/immutable/assets/export-csv.D-zJKYZj.png) *Adding a header row to a CSV export.* Press `enter` or click the "Export" button, and Harlequin will write the file with all of the data from your query. --- Source: https://harlequin.sh/docs/transactions # Managing Transactions Different adapters handle transactions differently; many choose to auto-commit each executed query. However, some adapters define multiple Transaction Modes that allow you to fine-tune the transaction handling of the commands you run in Harlequin. ## Switching Transaction Modes If the adapter supports multiple transaction modes, you should see a button labeled "Tx: [Mode Name]" in the Run Query bar in Harlequin. For example, this button is shown when the SQLite adapter is in Autocommit mode: ![Screenshot of the Run Query bar with transaction mode support enabled.](https://harlequin.sh/_app/immutable/assets/tx-auto.BHmR5z2w.png) *Screenshot of the Run Query bar with transaction mode support enabled.* Clicking "Tx: [Mode Name]" button will toggle to the adapter's next transaction mode. For SQLite, clicking the button above toggles to "Tx: Manual", and the UI grows two new buttons: ![Screenshot of the Run Query bar with manual transaction mode enabled.](https://harlequin.sh/_app/immutable/assets/tx-manual.DZ-J9Y7-.png) *Screenshot of the Run Query bar with manual transaction mode enabled.* ## Committing Transactions If supported by the adapter and appropriate for the transaction mode, next to the "Tx: [Mode Name]" button will appear a button labeled "🡅". Clicking this button will commit the current open transaction. ## Rolling Back Transactions As with committing, if supported by the adapter and appropriate for the transaction mode, next to the "Tx: [Mode Name]" button will appear a button labeled "⮌". Clicking this button will roll back the current open transaction. --- Source: https://harlequin.sh/docs/bindings # Reference: Default Bindings Harlequin uses keymaps to define sets of key bindings in the app. Below is a reference for the bindings from the default keymap (called `vscode`). For more information on customizing key bindings, see the [keymaps](https://harlequin.sh/docs/keymaps) page. ## General Bindings - `ctrl+q` Quit Harlequin - `F1` Show the help screen. - `F2` Focus on the Query Editor. - `F5` Focus on the Results Viewer. - `F6` Focus on the Data Catalog. - `F8` Show the Query History Viewer. - `F9`, `ctrl+b` Toggle the sidebar. - `F10` Toggle full screen mode for the current widget. - `ctrl+e` Export the returned data to a CSV, Parquet, or JSON file. - `ctrl+r` Refresh the Data Catalog. ## Query Editor Bindings ### Actions - `F4` Format the query. - `ctrl+enter`, `ctrl+j` Run the query. - `ctrl+o` Open a text file in the Query Editor. - `ctrl+s` Save the contents of the Query Editor to a file. - `ctrl+n` Create a new buffer (editor tab). - `ctrl+w` Close the current buffer (editor tab). - `ctrl+k` View the next buffer (editor tab). - `ctrl+g` Go to line - `ctrl+f` Find - `F3` Find next (like Find, but uses previous value). ### Editing Text - `ctrl+a` Select all, move the cursor to the end of the query. - `ctrl+x` Cut selected text. - `ctrl+c` Copy selected text. - `ctrl+v`, `ctrl+u`, `shift+insert`, `Right Click` Paste selected text. - `ctrl+z` Undo. - `ctrl+y` Redo. - `ctrl+/`, `ctrl+\_` Toggle comments on selected line(s). - `tab` Insert spaces at cursor to move the cursor to the next tab stop, or indent the selected line(s) to the next tab stop. - `shift+tab` Dedent the selected line(s) to the next tab stop. - `shift+delete` Delete the current line. ### Using Autocomplete _With the autocomplete list open:_ - `up`, `down`, `pgUp`, `pgDn` Select a different item in the list. - `tab`, `enter` Place the current selection in the Query Editor. - `escape` Dismiss the autocomplete list. ### Moving the Cursor - `up`,`down`,`left`,`right`,`tab`,`shift+tab` Move the cursor one position. - `home` Move the cursor to the start of the line. - `end` Move the cursor to the end of the line. - `ctrl+home` Move the cursor to the start of the query. - `ctrl+end` Move the cursor to the end of the query. - `pgUp` Move the cursor up one screen. - `pgDn` Move the cursor down one screen. - `ctrl+up` Scroll up one line. - `ctrl+down` Scroll down one line. - `ctrl+left` Move the cursor to the start of the current token. - `ctrl+right` Move the cursor to the end of the current token. - `shift+[any]` Select text while moving the cursor. ## Results Viewer Bindings ### Actions - `ctrl+c` Copy selected cells. ### Switching Tabs - `j` Switch to the previous tab. - `k` Switch to the next tab. ### Moving the Cursor - `up`,`down`,`left`,`right` Move the cursor one cell. - `home` Move the cursor to the top of the current column. - `end` Move the cursor to the bottom of the current column. - `ctrl+home` Move the cursor to the first cell. - `ctrl+end` Move the cursor to the last cell. - `pgUp` Move the cursor up one screen. - `pgDn` Move the cursor down one screen. - `ctrl+up`,`ctrl+down` Move the cursor to the start/end of the column. - `ctrl+left`,`ctrl+right` Move the cursor to the start/end of the row. - `shift+[any]` Select cells while moving the cursor. ## Data Catalog Bindings - `ctrl+enter`,`ctrl+j` Insert the current name into the Query Editor. - `ctrl+c` Copy the current name to the clipboard. - `.` Open the Interactions context menu for the selected item. ### Switching Tabs - `j` Switch to the previous tab. - `k` Switch to the next tab. ### Moving the Cursor - `up`,`down` Move the cursor one row. - `enter`,`space` Toggle the expand/collapsed state of the current item. ## Query History Viewer Bindings - `up`,`down`,`pgUp`,`pgDn` Change selection and scroll. - `tab` Change focus between the history list and the query preview pane. - `enter` Create a new Editor buffer and insert the highlighted query. - `escape` Return to the main screen. --- Source: https://harlequin.sh/docs/troubleshooting # Common Problems Sorry to see you here. Terminals can be finicky. ## Common Problems 1. [Key Bindings](https://harlequin.sh/docs/troubleshooting/key-bindings) 1. [Copy-Paste](https://harlequin.sh/docs/troubleshooting/copying-and-pasting) 1. [Appearance (Colors and Fonts)](https://harlequin.sh/docs/troubleshooting/appearance) 1. [Locale (Number formatting)](https://harlequin.sh/docs/troubleshooting/locale) 1. [Windows Timezone Database](https://harlequin.sh/docs/troubleshooting/timezone-windows) 1. [DuckDB Version Mismatch](https://harlequin.sh/docs/troubleshooting/duckdb-version-mismatch) While Harlequin aims to work in every terminal, some do provide better support for Harlequin's features. Our recommended terminals can be found [here](https://harlequin.sh/docs/troubleshooting/terminal-recommendations). --- Source: https://harlequin.sh/docs/troubleshooting/key-bindings # Key Bindings Harlequin can only react to key presses that are sent to it from the Terminal it is running in. Some common key presses, like `ctrl+enter`, aren't forwarded correctly by some terminals, or may be aliased to a different key or even a different sort of event. If you don't want to [upgrade your terminal](https://harlequin.sh/docs/troubleshooting/terminal-recommendations), you can use the following aliases, which should be supported everywhere (if not, [open an issue](https://github.com/tconbeer/harlequin/issues)): - Run query: use `ctrl+j`, not `ctrl+enter`. - Comment line: use `ctrl+\_` (underscore), not `ctrl+/`. - On a Mac: For all bindings, use `^ Control`, not `⌘ Command`. - On MacOs >= 15.0.0 , the key binding `^+enter` is mapped to "Show contextual menu" by default. This interferes with the "Run Query" key binding of Harlequin. Instead of setting up alternative key bindings, you can disable this shortcut in MacOS by navigating to: System Settings -> Keyboard -> Keyboard Shortcuts... -> Keyboard -> turn "Show contextual menu" off. > **Tip:** [See here](https://harlequin.sh/docs/troubleshooting/copying-and-pasting) for help with copy and paste. Finally, Harlequin's footer, which lists some of the currently-active key bindings, is clickable. If a binding isn't working, you can click it in the footer to take the same action. ### Enabling Key Bindings in VS Code Terminal VS Code intercepts a large number of key presses before they make it to the terminal, even when the terminal is focused. This includes `ctrl+j` (which hides or shows the VS Code terminal!). Fortunately, you can change this behavior in the VS Code settings. If you use a `settings.json` file, you can add this snippet: ```json { "terminal.integrated.allowChords": false, "terminal.integrated.sendKeybindingsToShell": true, } ``` Otherwise, you can press `F1` to open the command palette, then type and select "Terminal: Configure Terminal Settings". Then make the following changes: 1. Uncheck the option "Terminal > Integrated: Allow Chords" 2. Check the option "Terminal > Integrated: Send Keybindings to Shell" (you may have to scroll down nearly all the way). --- Source: https://harlequin.sh/docs/troubleshooting/copying-and-pasting # Copying and Pasting Harlequin's Query Editor, Data Catalog, and Results Viewer support cut and copy, and its Query Editor supports paste. However, this is more complex than it seems. If these features are not working for you, there could be a number of root causes. This section walks through how copy-paste works in Harlequin, and offers some solutions for common problems. ### Internal Copy and Paste Harlequin's Query Editor implements its own internal clipboard, so copying and pasting within the Query Editor should always work. To test the internal clipboard, select text in the Query Editor and press `ctrl+c` to copy it. Paste it with `ctrl+u` (`u`, not `v` for this step!). If that doesn't work, Harlequin isn't receiving those key presses from your terminal. Please [open an issue](https://github.com/tconbeer/harlequin/issues). ### Copying outside Harlequin, Pasting inside Harlequin There are two mechanisms for Harlequin to receive clipboard data when you initiate a paste. 1. Harlequin receives a key press that it interprets as a paste command. This happens when you press `ctrl+u`, and depending on your terminal, may or may not happen when you press `ctrl+v`. When Harlequin interprets a key press as a paste command, it attempts to access the system clipboard and paste its contents. If it cannot access the system clipboard, Harlequin will paste the contents of its internal clipboard. To determine if Harlequin can access the system clipboard: - Copy some text outside of Harlequin. - Focus on the Harlequin Query Editor, then press `ctrl+u` (`u`, not `v` for this step!). - If Harlequin does not paste anything, or if it pastes something different from what you just copied, Harlequin cannot access the system clipboard. You can work around this by pasting using your terminal's built-in paste functionality, or by fixing its access to the system clipboard (keep reading). - Starting in Harlequin v1.1, you should see a notification pop-up if Harlequin cannot access your system clipboard. 2. Harlequin receives a native `Paste` message from the terminal. To trigger a `Paste` message, you want to use the same keys that you would to paste into your shell. This might be `ctrl+v`, `shift+insert`, or a right click of your mouse. When Harlequin receives a `Paste` message, it will insert the contents of that message into the Query Editor. Since this doesn't rely on the clipboard, this should work on nearly any terminal, whether Harlequin and the terminal share a host or not. Many terminals allow you to configure the key or mouse bindings for `Paste`. If Harlequin cannot access the system clipboard, there may be a couple of causes: 1. If Harlequin is installed on Linux, you may be missing a clipboard library. Try `sudo apt install xclip` or `sudo apt install xsel` to install a library that will allow Harlequin to access the system clipboard. 2. Harlequin's host (the operating system where Harlequin is running) may have its clipboard disabled. This is common in GitHub Codespaces, CI runners, and other servers that don't typically support user input or a display. If you control the server, you can install or start an X Server (like X11) to enable the clipboard. As a workaround, try triggering a native `Paste` event in your terminal instead. 3. If your terminal is attaching to a remote host to run Harlequin, e.g., via SSH, the terminal or SSH client may or may not support clipboard "redirection" (sharing the clipboard between the machines). In this case, Harlequin may be able to access its host's clipboard, but that clipboard won't be the same as the one you use for everything else. As a workaround, try triggering a native `Paste` event in your terminal instead (sadly this might also be disabled). If all is lost, you can open a text file with Harlequin with `ctrl+o` or by clicking "Open Query" in the footer. ### Copying inside Harlequin, Pasting outside Harlequin If you've made it this far, I'm so sorry. I hope you've learned something today. The same dynamics from above apply, but we don't have the `Paste` event to move the data for us. The workarounds are: 1. You can try to use your terminal's native copy functionality. This is unlikely to do what you want, since it'll copy Harlequin's UI (borders, whitespace, etc), alongside your query. But if you want to try: - In your terminal's settings, enable "Copy on Selection." You can test this in your shell -- if you select (highlight) text with your mouse, it should get copied to your clipboard. - In Harlequin, hold `Shift` while using your mouse to select the text you want to copy (on most terminals, this triggers selection when the terminal is in "app mode"). You'll know you're doing this right if the highlight color is different from what you normally see when highlighting text in Harlequin. Your selection should get copied to the clipboard (whitespace, `|`'s, and all). 2. You can save your query to a file and open it in another program. Press `ctrl+s` or click "Save Query" in the footer. --- Source: https://harlequin.sh/docs/troubleshooting/appearance # Appearance Harlequin should look great in your terminal. If it doesn't, it may be because we depend on your terminal and shell for rendering, and those may require some configuration on your machine. ### Colors Modern terminal emulators can display millions of colors, in a scheme called "truecolor." Older terminals could only display 256 colors, or even as few as 8. Some themes look terrible with only 256 colors. For example, `nord`: ![Screenshot of the Nord theme in 256 colors](https://harlequin.sh/_app/immutable/assets/nord-256.DUb_fvFb.png) *Nord in 256 Colors* ![Screenshot of the Nord theme in truecolor](https://harlequin.sh/_app/immutable/assets/nord.z5ZehJHi.png) *Nord in Truecolor* For Harlequin to display in truecolor, both the terminal and shell need to support it. If you are seeing only 256 colors, there could be a few causes: 1. Your terminal and shell may support truecolor, but the terminal may be rendering your shell in 256 colors for backwards-compatibility reasons (e.g., bash in WSL2 on Windows Terminal). Try setting the environment variable `COLORTERM` to `truecolor` to instruct your terminal to render truecolor. You can test this by launching Harlequin with `COLORTERM=truecolor harlequin`, and if that works, you should set the environment variable more durably (Google instructions for your OS). As an example (bash in WSL2 on Windows Terminal), I added this line to my `.bashrc` file: `export COLORTERM=truecolor`. 1. Your terminal may support truecolor, but your shell may not. Some implementations of some shells don't support truecolor, even if the terminal they are running in does. You can try a different shell, like [fish](https://fishshell.com/), [zsh](https://www.zsh.org/), or [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-7.3). 1. Your terminal may only support 256 colors. You should [upgrade your terminal](https://harlequin.sh/docs/troubleshooting/terminal-recommendations). If none of those work, some themes still look good in 256 colors. We recommend `harlequin` (the default), `textual-light`, `gruvbox`, `catppuccin-mocha`, and `tokyo-night`. ### Fonts Modern terminals can display different fonts. Harlequin looks great in a number of fixed-width fonts, but may have odd artifacts in others. We especially like [Nerd Fonts](https://www.nerdfonts.com/), which contain ligatures for symbols common in programming. Popular options include FiraCode, Meslo, Cascadia, and JetBrainsMono. To use a different font with Harlequin, download and install the font, and then configure your terminal to use that font. > **Note for Mac Terminal.app Users:** Only some fonts render right with the default Terminal app. You may need to adjust your line spacing. [See here](https://textual.textualize.io/FAQ/#why-doesnt-textual-look-good-on-macos) for instructions. > **Note for WSL2 and Windows Terminal Users:** Windows Terminal runs in Windows and attaches your Linux shell over the WSL network. You need to install your font in Windows for this to work. --- Source: https://harlequin.sh/docs/troubleshooting/locale # Locale Harlequin uses your system's locale (the language, region, and other country-specific settings) to format numbers (for example, to set the thousands separator). If the system's locale is not set properly, Harlequin's numbers may look strange to you. ## The Special "C" Locale Some computers have their locale set to `C` (or `C.UTF-8`), which is the POSIX standard for "Computer" -- it is optimized for servers or other environments that should not localize values. Using Harlequin with the `C` locale shows numbers unformatted, wihout a thousands separator. This probably isn't what you want. If Harlequin finds itself running in the `C` locale, it attempts to set the locale to `en_US.UTF-8` and prints a warning that is viewable on exiting Harlequin. If you do want to use Harlequin with the `C` locale, you can either uninstall the `en_US.UTF-8` locale from your OS, or just run Harlequin with the `--locale C` option. ## Setting The System Locale - Mac: See [Mac Help](https://support.apple.com/guide/mac-help/change-language-region-settings-on-mac-intl163/mac). tldr: Apple > System Settings > General > Language & Region; set Number Format. - Ubuntu: See [Ubuntu Help](https://help.ubuntu.com/community/Locale). tldr: `sudo nano /etc/default/locale` - Windows: See [this blog](https://www.windowscentral.com/how-properly-change-system-default-language-windows-10). Update the Language and/or Region. ## Overriding the System Locale You can also just pass a `--locale` option to Harlequin, like this: ```bash harlequin --locale en_US.UTF-8 ``` If the passed locale is not installed on your system, Harlequin will exit with an error. As with other options, this value can be saved to a profile in a config file. You can create a profile with `harlequin --config`. See [the help on config](https://harlequin.sh/docs/config-file) for more information. --- Source: https://harlequin.sh/docs/troubleshooting/timezone-windows # Windows Timezone Database Unlike other operating systems, Windows does not ship with an IANA-format timezone database. Harlequin uses the Apache Arrow data format to power its results viewer, and Arrow needs a timezone database to operate on "timestamp with timezone" (`timestamptz`) data types, even to cast them to strings! See the [Arrow Docs](https://arrow.apache.org/docs/python/install.html#tzdata-on-windows) for more information. At startup on Windows, Harlequin tries to find an IANA timezone database. If it cannot, it will attempt to download one to a Harlequin-specific location. If the download fails, Harlequin will print an error message and exit. To prevent Harlequin from downloading the timezone database, launch Harlequin with the `--no-download-tzdata` option: ```bash harlequin --no-download-tzdata ``` > **Warning:** When using Harlequin with this option, attempting to load a `timestamptz` column into the Results Viewer may cause Harlequin to crash. --- Source: https://harlequin.sh/docs/troubleshooting/duckdb-version-mismatch # DuckDB Version Mismatch Harlequin depends on DuckDB, and installing it in an isolated environment (e.g., using `pipx` or in a fresh virtual environment) will cause it to install DuckDB. If you have DuckDB installed elsewhere (e.g., if you already installed DuckDB with `pipx` or Homebrew), you may want to pin the version of DuckDB that Harlequin uses. For example, attempting to open a DuckDB database file with different versions of DuckDB will result in an error that looks like this: IO Error: Trying to read a database file with version number 64, but we can only read version 51. The database file was created with an newer version of DuckDB. The storage of DuckDB is not yet stable; newer versions of DuckDB cannot read old database files and vice versa. The storage will be stabilized when version 1.0 releases. For now, we recommend that you load the database file in a supported version of DuckDB, and use the EXPORT DATABASE command followed by IMPORT DATABASE on the current version of DuckDB. See the storage page for more information: https://duckdb.org/internals/storage ### Determining the Version of the DuckDB CLI on your Path First, determine what version of DuckDB you are running outside of Harlequin, and how it was installed. You can find the path to the executable with `which duckdb` on Unix systems, or `get-command duckdb` in Windows Powershell. This path should give you a hint about how it was installed; you could also try `pipx list` or `brew list` to see if DuckDB was installed by either of those tools. Next, run `duckdb --version`, which should display the version number and commit SHA, like `v0.9.0 0d84ccf478`. Alternatively, the [storage page](https://duckdb.org/internals/storage) linked to in the error message provides a mapping of storage versions to DuckDB versions (e.g., we can see that storage version 64 maps to DuckDB 0.9.0, and 51 maps to DuckDB 0.8.0). ### Determining the Version of DuckDB Used by Harlequin Open Harlequin, then in the query editor, type or paste `select version()`. In the Results Viewer, the version number should be displayed. ### Changing the Version of DuckDB Used by Harlequin > **Note:** Harlequin requires DuckDB >= 0.8.0 due to changes in the Python API in that version. You can add an explicit pin to a DuckDB version alongside Harlequin's installation. The following example assumes you would like to pin the version to `1.1.3`. ```bash uv tool install harlequin --with 'duckdb==1.1.3' ``` --- Source: https://harlequin.sh/docs/troubleshooting/terminal-recommendations # Terminal Recommendations If you are using the default Mac Terminal or Windows Command Prompt, you may want to switch to a more modern terminal. The following terminals are free and come highly recommended: - Windows (native or WSL2): [Windows Terminal](https://apps.microsoft.com/store/detail/windows-terminal/9N0DX20HK701) - Mac: [iTerm2](https://iterm2.com/) - Linux: [Gnome](https://help.gnome.org/users/gnome-terminal/stable/), [Alacritty](https://snapcraft.io/alacritty) --- Source: https://harlequin.sh/docs/contributing # Ways to Contribute Thanks for your interest in Harlequin! Harlequin is primarily maintained by [Ted Conbeer](https://tedconbeer.com), but he welcomes all contributions! ## Sponsoring Harlequin Please consider [sponsoring Ted](https://github.com/sponsors/tconbeer), so he can continue to dedicate time to developing and supporting Harlequin. ## Providing Feedback We'd love to hear from you! [Start a Discussion](https://github.com/tconbeer/harlequin/discussions) or [open an Issue](https://github.com/tconbeer/harlequin/issues/new) to request new features, report bugs, or say hello. ## Contributing Code If you would like to contribute code to Harlequin, that is fantastic! Ted would love to support you. Please reach out by opening or commenting on an Issue so we can provide more tactical guidance. If you'd like to create a database adapter for Harlequin, the [next page](https://harlequin.sh/docs/contributing/adapter-guide) provides a guide. **Watch this video** for an overview of the end-to-end process for contributing to Harlequin, from clone to PR: [Video: Contributing to Harlequin](https://www.tella.tv/video/cls3nmne700000gl4bcp91arr/embed?b=0&title=1&a=1&loop=0&t=0&muted=0) General advice is below: ### Opening PRs 1. PRs should be motivated by an open issue. If there isn't already an issue describing the feature or bug, [open one](https://github.com/tconbeer/harlequin/issues/new). Do this before you write code, so you don't waste time on something that won't get merged. 2. Ideally new features and bug fixes would be tested, to prevent future regressions. Textual provides a test harness that we use to test features of Harlequin. You can find some examples in the `tests` directory of this project. Please include a test in your PR, but if you can't figure it out, open a PR to ask for help. 3. Please include an entry in CHANGELOG.md that explains the change and links to the open issue that this change closes. Feel free to credit yourself as a contributor. 4. Open a PR from your fork to the `main` branch of `tconbeer/harlequin`. In the PR description, link to the open issue, and then write a few sentences about **why** you wrote the code you did: explain your design, etc. 5. Ted may ask you to make changes, or he may make them for you. Don't take this the wrong way -- he values your contributions, but he knows this isn't your job, either, so if it's faster for him, he may push a commit to your branch or create a new branch from your commits. ### Setting up Your Dev Environment and Running Tests 1. Install [uv](https://docs.astral.sh/uv/getting-started/installation/) v0.9 or higher if you don't have it already. You may also want to install `make`. 1. Fork this repo, and then clone the fork into a directory (let's call it `harlequin`), then `cd harlequin`. 1. Use `uv sync` to install the project (editable) and its dependencies (including all test and dev dependencies) into a new virtual env. 1. Run `pre-commit install` to install pre-commit hooks. 1. Type `make` to run all tests and linters, or run `uv run pytest`, `uv run ruff format .`, `uv run ruff check --fix .`, and `uv run mypy` individually. ### Inspecting and Updating Snapshot Tests Many changes to Harlequin will cause snapshot tests to fail. You will need to inspect the failures and update the "ground truth" snapshots in order for tests to pass (see the video for more info). The steps are: 1. Run `pytest` to generate test failures. If snapshots do not match, a file called `snapshot_report.html` will be generated in the root of the project directory. 2. Open `snapshot_report.html` in a browser and inspect the before and after for each failing snapshot. The "Show Difference" toggle is especially handy to quickly find the change that caused the failure. Note: sometimes invisible changes (like changes to class names in the SVG) can cause test failures. In this case, after toggling "Show Difference", you should see a blank, black square. 3. If all of the new snapshots are showing the expected result, run `pytest --snapshot-update`, and confirm the result of that command. 4. Check in any changes to the data files in the `tests/functional_tests/__snapshots__` directory. 5. Including a screenshot of any changes in your PR description is much appreciated! --- Source: https://harlequin.sh/docs/contributing/adapter-guide # Creating an Adapter Database adapters enable Harlequin to work with any relational database by abstracting the actual interface into a standard that Harlequin can use. The interface is minimal: adapters were designed to be easy to implement and maintain. Adapter authors only need familiarity with Python and the database they wish to use; no knowledge of Textual, user interfaces, or async programming is required. ## What, Exactly, Is an Adapter? An adapter is a Python package that declares an [entry point](https://packaging.python.org/en/latest/specifications/entry-points/) in the `harlequin.adapters` group. That entry point should reference a subclass of the `HarlequinAdapter` abstract base class. This allows Harlequin to discover installed adapters and instantiate a selected adapter at run-time. Harlequin has two built-in adapters that are distributed with the `harlequin` package. All other adapters should be distributed as their own packages. They may be named `harlequin_`, but the naming convention is not necessary. ## Interfaces There are three interfaces defined as abstract base classes in the [`harlequin.adapter`](https://github.com/tconbeer/harlequin/blob/main/src/harlequin/adapter.py) module. You will have to implement each of them. ### HarlequinAdapter The first is the `HarlequinAdapter`, which is initialized with `conn_str` (a tuple of connection strings) and any options passed into Harlequin at the command line or through a config file. The adapter declares its options via the `ADAPTER_OPTIONS` class variable (more info [below](#adapter-options)). The primary purpose of an adapter is to provide its `connect()` method, which creates and returns an instance of `HarlequinConnection`. Optionally, adapters may implement a `connection_id` property that uniquely identifies the connection in a manner that is stable between Harlequin invocations. Harlequin uses this `connection_id` to persist and retrieve the data catalog and query history across invocations of Harlequin. ### HarlequinConnection A connection must provide two methods: `get_catalog` and `execute`. - `get_catalog()` introspects the connection and returns a `Catalog`, whose items represent each database, relation, column, etc. available through the connection. The information in the `Catalog` is displayed to users in the Data Catalog sidebar in Harlequin, and is made available as autocomplete options. The schema for `Catalog` and `CatalogItem` are found in the [`harlequin.catalog`](https://github.com/tconbeer/harlequin/blob/main/src/harlequin/catalog.py) module. - `execute(query)` runs a query in the connected database. If the query returns data (like a select statement), `execute` returns a `HarlequinCursor`. Otherwise, it returns `None`. > **Note:** `get_catalog` and `execute` are called by Harlequin in different threads, and those calls may overlap. If multiple queries are run by the user, `execute` may be called many times serially, in a single thread, before any of the cursors' results are fetched (currently there are no plans to execute queries in parallel using multiple threads). A connection may also provide `close`, `cancel`, `get_completions`, and `validate_sql` methods; to support multiple transaction modes, it may also implement the `toggle_transaction_mode` method and the `transaction_mode` property. - `close()` can be implemented by an adapter to gracefully close the connection to the underlying database when Harlequin quits, if necessary. - `cancel()` should cancel any in-progress queries; it may also be necessary to handle any raised exceptions caused by cancelling queries, either during query execution or results fetching. After implementing this method, set the adapter class variable `IMPLEMENTS_CANCEL` to `True` to show the cancel button in the Harlequin UI. See the DuckDB adapter for a reference implementation. - `get_completions()` should return a list of [`HarlequinCompletion`](https://github.com/tconbeer/harlequin/blob/main/src/harlequin/autocomplete/completion.py) instances, which represent additional, adapter-specific keywords, functions, or other strings for editor autocomplete (Harlequin automatically builds completions for each `CatalogItem`, so they should not be included). - `validate_sql(query)` should very quickly parse the passed query: it is used to validate the selected text in Harlequin and determine whether the selection or entire query should be executed. If it is implemented, Harlequin will not attempt to execute the selected text if it is not a valid query; otherwise, Harlequin will always execute the selected text. The transaction behavior of an adapter is undefined, and is up to the adapter author. Optionally, an adapter can declare one or more transaction modes, which will cause Harlequin to display buttons to toggle the modes (and optionally) commit and roll back transactions. ![Screenshot of the Run Query bar with manual transaction mode enabled.](https://harlequin.sh/_app/immutable/assets/tx-manual.DZ-J9Y7-.png) *Screenshot of the Run Query bar with manual transaction mode enabled.* To enable this, you must implement the `transaction_mode` property and the `toggle_transaction_mode()` method on the connection. Both return a `HarlequinTransactionMode` data class with a string `label` and optional callables to `commit` and `rollback` a transaction, which will be invoked by Harlequin if the user clicks those buttons. ### HarlequinCursor A cursor must provide three methods: `columns`, `set_limit`, and `fetchall`. - `columns()` returns a list of tuples; each tuple is a `(column_name, column_type)` pair. The name and type will be printed in the column header in Harlequin's Results Viewer. The column type should be abbreviated to 1-3 characters: for example, the built-in adapters use `s` for string/varchar fields, `##` for integer fields, and `#.#` for floating-point fields. - `set_limit(limit)` should limit the number of records returned by a subsequent call to `fetchall()`. It is used by Harlequin to implement the limit checkbox on the Run Query Bar. - `fetchall()` should return all of the data returned by the query, in one of several accepted formats. It will be called exactly once on each cursor. The acceptable formats are declared by the `AutoBackendType` of Harlequin's Data Table widget (source [here](https://github.com/tconbeer/textual-fastdatatable/blob/a64308ea7e2e6de24df2f1d9c6cc1d024b2a6395/src/textual_fastdatatable/backend.py#L20-L27)). They are: 1. A PyArrow [`Table`](https://arrow.apache.org/docs/python/generated/pyarrow.Table.html) or [`RecordBatch`](https://arrow.apache.org/docs/python/generated/pyarrow.RecordBatch.html). 1. A `Mapping` of `str` to `Sequence`, where keys represent column names and the sequences are the data in each column. For example: `{"col_a": [1, 2, 3], "col_b": ["a", "b", "c"]}` 1. A `Sequence` of `Iterable`s, like a `list` of `tuple`s, representing rows of data (or records). Such a sequence **MUST NOT** contain a header row. 1. A `pathlib.Path` or `str` path to a local Parquet file. ### Adapter Options Adapters will be initialized with `conn_str`, a sequence of connection strings. Adapters may interpret these strings however they like; Harlequin neither imposes constraints nor performs validation on them. Beyond that, adapters can declare CLI options by setting the `ADAPTER_OPTIONS` class variable on their subclass of `HarlequinAdapter`. The class variable should be a list of instances of subclasses of [`AbstractOption`](https://github.com/tconbeer/harlequin/blob/main/src/harlequin/options.py), like `TextOption`, `FlagOption`, `SelectOption`, etc. Each `Option` instance must have a name and description. See the [`harlequin.options`](https://github.com/tconbeer/harlequin/blob/main/src/harlequin/options.py) module or the implementations by the [DuckDB](https://github.com/tconbeer/harlequin/blob/main/src/harlequin_duckdb/cli_options.py) and [SQLite](https://github.com/tconbeer/harlequin/blob/main/src/harlequin_sqlite/cli_options.py) adapters for more information. ## Packaging and Distributing Adapters You can use the [harlequin-adapter-template](https://github.com/tconbeer/harlequin-adapter-template) repo as a starting point for your adapter. It uses `MyAdapter` as a placeholder class name (along with `MyConnection` and `MyCursor`) and creates a plugin registered as `my-adapter`. Your adapter should require a compatible version of Harlequin as a dependency. We suggest using `harlequin = ">=1.4,<3"` as the dependency specification for a basic adapter; those implementing Lazy Catalogs or Interactions should use `harlequin = ">=1.25,<3"`. ### Making Your Adapter Discoverable as a Plug-in Your adapter must register an [entry point](https://packaging.python.org/en/latest/specifications/entry-points/) in the `harlequin.adapters` group, using the packaging software you use to build your project. We recommned uv. If you use uv, you can define the entry point in your `pyproject.toml` file: ```toml [project.entry-points."harlequin.adapter"] my-adapter = "my_package_name:MyAdapter" ``` In this example, `my-adapter` is the _name_ of the plugin. Harlequin users will select this adapter with `harlequin --adapter my-adapter`. `my_package_name` is the import name of your package (which may or may not be the same name as your _distribution_ or PyPI name). Finally, `MyAdapter` is a subclass of `HarlequinAdapter` that is available in the `my_package_name` namespace, probably because it was imported into the top-level `__init__.py` file. The template repo includes a test to ensure that your adapter is discoverable as a plug-in. ### Adding Your Adapter a Harlequin Extra If you would like your adapter installable as a Harlequin extra (e.g., `pip install harlequin[my-adapter]`), open a PR against [`tconbeer/harlequin`](https://github.com/tconbeer/harlequin) that adds the extra **and** the optional dependency to Harlequin's `pyproject.toml` file. ```toml [project.optional-dependencies] ... my-adapter = ["my-adapter-pypi-distribution"] ``` After updating `pyproject.toml`, you must run `uv sync` to regenerate the lockfile so it includes the new dependencies. Both `pyproject.toml` and `uv.lock` should be included in your PR. ## Testing Adapters The [harlequin-adapter-template](https://github.com/tconbeer/harlequin-adapter-template) repo provides a small set of tests that cover the basic functionality of an adapter. You will need to replace references to `MyAdapter`, `MyConnection`, and `MyCursor` with imports of your actual classes. Then you can run the tests with `pytest`. You are encouraged to add tests that are specific to the functionality of your adapter. ## Documenting Adapters You should add basic docs for your adapter (installation and usage) in the README of your adapter's project. See [`harlequin-postgres`](https://github.com/tconbeer/harlequin-postgres) as an example. In addition, if you would like your adapter to appear in these docs, open a PR against [`tconbeer/harlequin-web`](https://github.com/tconbeer/harlequin-web) that makes the following changes: 1. Add a directory with your adapter's name to `/src/docs/`. 1. Add a file called `index.md` inside that new directory. Add basic installation and usage info in that file (you can probably copy-paste this from your README). Link to your project's repo at the top of the page (see `/src/docs/bigquery/index.md` for an example). This file needs frontmatter that defines the page's title: ```md --- title: "Adapter: BigQuery" --- ``` 1. Add your adapter to the sidebar by adding an entry to `docsMenu` in `/src/lib/docs_menu.ts`, inside the `items` of the "Database Adapters" topic. Put it with the other adapters; the order of that array is the order of the menu. Setting `repo` puts a stars-and-forks badge at the top of your pages: ```ts { topic: "Adapter: BigQuery", slug: "bigquery", repo: "joshtemple/harlequin-bigquery", items: [{ title: "BQ Installation and Configuration", slug: "bigquery" }], }, ``` If your adapter is a single page, a plain entry alongside them does the job: ```ts { title: "Adapter: Trino", slug: "trino", repo: "rogerioguicampos/harlequin-trino" }, ``` The build fails if a page is missing from the menu or an entry points at a file that isn't there, so the two stay in step. 1. Add your adapter to the list of community adapters in `/src/docs/adapters.md`. Give yourself credit there. Link to the docs page you just created — links between docs pages are absolute, like `/docs/bigquery`. 1. (Optional) Add more pages of docs under the `/src/docs//` directory. Each needs its own `title` frontmatter and its own entry in the topic's `items` array, in the order you want them read. 1. (Optional) Add your database's icon to the front page of this site. Find or create a PNG icon with a transparent background. Then resize it to 50x50 and convert it to greyscale, and place it in the `/src/lib/assets/databases/` directory. On Linux, using ImageMagick, that looks like this: ```bash convert my_db_icon.png -resize 50x50 -colorspace gray ./src/lib/assets/databases/my_db_icon.png ```