{"id":13466520,"url":"https://github.com/danvergara/dblab","last_synced_at":"2026-10-19T01:04:28.386Z","repository":{"id":37292086,"uuid":"352879222","full_name":"danvergara/dblab","owner":"danvergara","description":"The database client every command line junkie deserves.","archived":false,"fork":false,"pushed_at":"2026-09-09T04:06:30.000Z","size":29986,"stargazers_count":3233,"open_issues_count":12,"forks_count":89,"subscribers_count":11,"default_branch":"main","last_synced_at":"2026-09-21T00:44:16.197Z","etag":null,"topics":["cli","client","developer-tools","development","golang","mysql","oracle","postgresql","sqlite","sqlserver","tui","tview"],"latest_commit_sha":null,"homepage":"https://dblab.app","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/danvergara.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"claude":null,"gemini":null,"cursor":null,"copilot":null,"dco":null,"cla":null,"disclosure":null}},"created_at":"2021-03-30T05:20:36.000Z","updated_at":"2026-09-18T05:49:46.000Z","dependencies_parsed_at":"2026-09-09T06:03:16.695Z","dependency_job_id":"c681b1b7-b79e-47e0-845d-bf75d3d0f5ea","html_url":"https://github.com/danvergara/dblab","commit_stats":{"total_commits":406,"total_committers":11,"mean_commits":36.90909090909091,"dds":0.06650246305418717,"last_synced_commit":"a0a6fdc747dc569e397a9b91f642dfb07fa9d985"},"previous_names":[],"tags_count":94,"template":false,"template_full_name":null,"purl":"pkg:github/danvergara/dblab","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danvergara%2Fdblab","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danvergara%2Fdblab/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danvergara%2Fdblab/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danvergara%2Fdblab/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danvergara","download_url":"https://codeload.github.com/danvergara/dblab/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danvergara%2Fdblab/sbom","scorecard":{"id":321887,"data":{"date":"2025-08-11","repo":{"name":"github.com/danvergara/dblab","commit":"333307ce2077b61a688b568a7f12d4ec82f39a52"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":3,"reason":"Found 11/30 approved changesets -- score normalized to 3","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":4,"reason":"2 commit(s) and 3 issue activity found in the last 90 days -- score normalized to 4","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/check-goreleaser.yml:1","Warn: no topLevel permission defined: .github/workflows/ci.yaml:1","Warn: topLevel 'contents' permission set to 'write': .github/workflows/docs.yml:8","Warn: topLevel 'contents' permission set to 'write': .github/workflows/release.yml:10","Warn: no topLevel permission defined: .github/workflows/test.yaml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/check-goreleaser.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/danvergara/dblab/check-goreleaser.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/check-goreleaser.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/danvergara/dblab/check-goreleaser.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/check-goreleaser.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/danvergara/dblab/check-goreleaser.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:43: update your workflow using https://app.stepsecurity.io/secureworkflow/danvergara/dblab/ci.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:47: update your workflow using https://app.stepsecurity.io/secureworkflow/danvergara/dblab/ci.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/docs.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/danvergara/dblab/docs.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/docs.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/danvergara/dblab/docs.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/docs.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/danvergara/dblab/docs.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/danvergara/dblab/release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/danvergara/dblab/release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/danvergara/dblab/release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yaml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/danvergara/dblab/test.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yaml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/danvergara/dblab/test.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yaml:35: update your workflow using https://app.stepsecurity.io/secureworkflow/danvergara/dblab/test.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yaml:39: update your workflow using https://app.stepsecurity.io/secureworkflow/danvergara/dblab/test.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test.yaml:44: update your workflow using https://app.stepsecurity.io/secureworkflow/danvergara/dblab/test.yaml/main?enable=pin","Warn: containerImage not pinned by hash: Dockerfile:1","Warn: pipCommand not pinned by hash: .github/workflows/docs.yml:24","Warn: pipCommand not pinned by hash: .github/workflows/docs.yml:25","Info:   0 out of  13 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   3 third-party GitHubAction dependencies pinned","Info:   0 out of   2 pipCommand dependencies pinned","Info:   0 out of   1 containerImage dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v0.33.0 not signed: https://api.github.com/repos/danvergara/dblab/releases/225048881","Warn: release artifact v0.32.0 not signed: https://api.github.com/repos/danvergara/dblab/releases/215007964","Warn: release artifact v0.31.0 not signed: https://api.github.com/repos/danvergara/dblab/releases/214262822","Warn: release artifact v0.30.1 not signed: https://api.github.com/repos/danvergara/dblab/releases/193420838","Warn: release artifact v0.30.0 not signed: https://api.github.com/repos/danvergara/dblab/releases/193345538","Warn: release artifact v0.33.0 does not have provenance: https://api.github.com/repos/danvergara/dblab/releases/225048881","Warn: release artifact v0.32.0 does not have provenance: https://api.github.com/repos/danvergara/dblab/releases/215007964","Warn: release artifact v0.31.0 does not have provenance: https://api.github.com/repos/danvergara/dblab/releases/214262822","Warn: release artifact v0.30.1 does not have provenance: https://api.github.com/repos/danvergara/dblab/releases/193420838","Warn: release artifact v0.30.0 does not have provenance: https://api.github.com/repos/danvergara/dblab/releases/193345538"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/check-goreleaser.yml:9"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Vulnerabilities","score":9,"reason":"1 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2025-3553 / GHSA-mh63-6h87-95cp"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-18T01:34:44.647Z","repository_id":37292086,"created_at":"2025-08-18T01:34:44.647Z","updated_at":"2025-08-18T01:34:44.647Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":344872684,"owners_count":38344170,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-10-03T21:59:58.778Z","status":"online","status_checked_at":"2026-10-18T02:00:06.448Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","client","developer-tools","development","golang","mysql","oracle","postgresql","sqlite","sqlserver","tui","tview"],"created_at":"2024-07-31T15:00:45.513Z","updated_at":"2026-10-19T01:04:28.376Z","avatar_url":"https://github.com/danvergara.png","language":"Go","funding_links":[],"categories":["Go","\u003ca name=\"data-management-tabular\"\u003e\u003c/a\u003eData management - Tabular data","Databases / Log management","Table of Contents"],"sub_categories":["Screen Sharing"],"readme":"# dblab \n![integration tests](https://github.com/danvergara/dblab/actions/workflows/ci.yaml/badge.svg)\n![unit tests](https://github.com/danvergara/dblab/actions/workflows/test.yaml/badge.svg)\n[![Release](https://img.shields.io/github/release/danvergara/dblab.svg?label=Release)](https://github.com/danvergara/dblab/releases)\n\n\u003cp align=\"center\"\u003e\n  \u003cimg style=\"float: right;\" src=\"assets/gopher-dblab.png\" alt=\"dblab logo\"/  width=200\u003e\n\u003c/p\u003e\n\n__Interactive client for PostgreSQL, MySQL, SQLite3, Oracle and SQL Server.__\n\n\u003cimg src=\"screenshots/dblab-cover.png\" /\u003e\n\n---\n\n**Documentation**: \u003ca href=\"https://dblab.app\" target=\"_blank\"\u003ehttps://dblab.app\u003c/a\u003e\n\n---\n\n## Table of contents\n\n- [Overview](#overview)\n- [Features](#features)\n- [Installation](#installation)\n    - [Homebrew](#homebrew)\n    - [Binary Release](#binary-release-linuxmacoswindows)\n    - [Automated installation/update](#automated-installationupdate)\n- [Help Command](#help)\n- [Usage](#usage)\n    - [SSH Tunnel](#ssh-tunnel)\n    - [Configuration](#configuration)\n        - [Key bindings configuration](#key-bindings-configuration)\n    - [Connection Profiles](#connection-profiles)\n- [Navigation](#navigation)\n    - [Panels and the sidebar tree](#panels-and-the-sidebar-tree)\n    - [Result sets](#result-sets)\n    - [Active schema](#active-schema)\n- [Query editor](#query-editor)\n    - [Modes](#modes)\n    - [Editing and motions](#editing-and-motions)\n    - [Executing queries](#executing-queries)\n    - [Query history](#query-history)\n- [Help modal](#help-modal)\n- [Key bindings](#key-bindings)\n- [Contribute](#contribute)\n- [License](#license)\n\n## Overview\n\ndblab is a fast and lightweight interactive terminal-based UI application for PostgreSQL, MySQL, and SQLite3,\nwritten in Go and works on macOS, Linux, and Windows machines. The main idea behind using Go for backend development\nis to utilize the ability of the compiler to produce zero-dependency binaries for\nmultiple platforms. dblab was created as an attempt to build a very simple and portable\napplication to work with local or remote PostgreSQL/MySQL/SQLite3/Oracle/SQL Server databases.\n\n## Features\n\n- Cross-platform support for macOS/Linux/Windows (32/64-bit)\n- Simple installation (distributed as a single binary)\n- Zero dependencies.\n- Vim-style query editor backed by a real modal-editing engine ([goeditor](https://github.com/ionut-t/goeditor)): normal/insert modes, word and line motions, undo/redo, visual mode selection, and in-buffer search, on top of the line-oriented editing commands.\n- Multi-query execution: write multiple SQL statements separated by `;` and run them concurrently with results displayed in separate tabs.\n- Single-query execution: press \u003ckbd\u003ectrl+r\u003c/kbd\u003e to execute only the query on the current cursor line, without running other statements in the editor.\n- Connection profiles with secure credential storage in the OS keyring.\n- Query history: executed queries are persisted across sessions and can be browsed/re-used via a filterable list.\n- Read-only mode: use `--readonly` to prevent accidental writes by forcing the database session into read-only mode (supported for PostgreSQL, MySQL, SQLite, Oracle, and SQL Server).\n- Schema switching: press \u003ckbd\u003ectrl+s\u003c/kbd\u003e to pick the active schema from a filterable list without restarting the app (PostgreSQL and Oracle, when no schema was pinned at startup); the active schema is always shown in the status bar.\n- Built-in help modal: press \u003ckbd\u003e?\u003c/kbd\u003e to display a help overlay showing all available key bindings; press \u003ckbd\u003eEsc\u003c/kbd\u003e to dismiss it.\n- Full-screen mode: press \u003ckbd\u003ealt+f\u003c/kbd\u003e to expand the focused query editor or result set panel to fill the terminal; press \u003ckbd\u003eEsc\u003c/kbd\u003e to exit.\n- Per-panel key bindings: the query editor, the sidebar tree, the result set panel and the panel navigation each have their own section in `.dblab.yaml`, so every panel can be rebound independently.\n\n## Installation\n\n### Homebrew\n\nIt works with Linux, too.\n\n```\nbrew install --cask danvergara/tools/dblab\n```\n\nOr\n\n```\nbrew tap danvergara/tools\nbrew install --cask dblab\n```\n\n### Binary Release (Linux/macOS/Windows)\nYou can manually download a binary release from [the release page](https://github.com/danvergara/dblab/releases).\n\n### Automated installation/update\n\u003e Don't forget to always verify what you're piping into bash\n\nInstall the binary using our bash script:\n\n```sh\ncurl https://raw.githubusercontent.com/danvergara/dblab/master/scripts/install_update_linux.sh | bash\n```\n\n## Help\n\n```\ndblab is a terminal UI-based interactive database client\n\nUsage:\n  dblab [flags]\n  dblab [command]\n\nAvailable Commands:\n  connect     Re-use saved connection profiles\n  help        Help about any command\n  version     The version of the project\n\nFlags:\n      --cfg-name string                   Database config name section\n      --config                            Get the connection data from a config file (default locations are: current directory, $HOME/.dblab.yaml or $XDG_CONFIG_HOME/.dblab.yaml)\n      --keybindings, -k                   Get the keybindings configuration from the config file (default locations are: current directory, $HOME/.dblab.yaml or $XDG_CONFIG_HOME/.dblab.yaml)\n      --db string                         Database name\n      --driver string                     Database driver\n      --encrypt string                    [strict|disable|false|true] whether data sent between client and server is encrypted\n  -h, --help                              help for dblab\n      --host string                       Server host name or IP\n      --limit uint                        Size of the result set for the table content query (should be greater than zero, otherwise the app will error out) (default 100)\n      --pass string                       Password for user\n      --port string                       Server port\n      --save-as string                    Save the connection as a named profile for later reuse\n      --schema string                     Database schema (optional for postgres and oracle only)\n      --socket string                     Path to a Unix socket file\n      --ssh-host string                   SSH Server Hostname/IP\n      --ssh-key string                    File with private key for SSH authentication\n      --ssh-key-pass string               Supports connections with protected private keys with passphrase\n      --ssh-pass string                   SSH Password (Empty string for no password)\n      --ssh-port string                   SSH Port\n      --ssh-user string                   SSH User\n      --ssl string                        SSL mode\n      --ssl-verify string                 [enable|disable] or [true|false] enable ssl verify for the server\n      --sslcert string                    This parameter specifies the file name of the client SSL certificate, replacing the default ~/.postgresql/postgresql.crt\n      --sslkey string                     This parameter specifies the location for the secret key used for the client certificate. It can either specify a file name that will be used instead of the default ~/.postgresql/postgresql.key, or it can specify a key obtained from an external “engine”\n      --sslpassword string                This parameter specifies the password for the secret key specified in sslkey\n      --sslrootcert string                This parameter specifies the name of a file containing SSL certificate authority (CA) certificate(s). The default is ~/.postgresql/root.crt\n      --timeout string                    in seconds (default is 0 for no timeout), set to 0 for no timeout. Recommended to set to 0 and use context to manage query and connection timeouts\n      --trace-file string                 File name for trace log\n      --trust-server-certificate string   [false|true] whether the server certificate is checked\n  -u, --url string                        Database connection string\n      --user string                       Database user\n  -v, --version                           version for dblab\n      --readonly                            Forces a read-only connection with the target database\n      --wallet string                     Path for auto-login oracle wallet\n\nUse \"dblab [command] --help\" for more information about a command.\n```\n\n## Usage\n\nYou can start the app without passing flags or parameters; you'll be asked for connection data instead.\n![dblab-demo](screenshots/dblab-demo.gif)\n\n\n```sh\n$ dblab --host localhost --user myuser --db users --pass password --ssl disable --port 5432 --driver postgres --limit 50\n$ dblab --db path/to/file.sqlite3 --driver sqlite\n$ dblab --host localhost --user system --db FREEPDB1 --pass password --port 1521 --driver oracle --limit 50\n$ dblab --host localhost --user SA --db msdb --pass '5@klkbN#ABC' --port 1433 --driver sqlserver --limit 50\n```\n\nConnection URL scheme is also supported:\n\n```sh\n$ dblab --url 'postgres://user:password@host:port/database?sslmode=[mode]'\n$ dblab --url 'mysql://user:password@tcp(host:port)/db'\n$ dblab --url 'file:test.db?_pragma=foreign_keys(1)\u0026_time_format=sqlite'\n$ dblab --url 'oracle://user:password@localhost:1521/db'\n$ dblab --url 'sqlserver://SA:myStrong(!)Password@localhost:1433?database=tempdb\u0026encrypt=true\u0026trustservercertificate=false\u0026connection+timeout=30'\n```\n\nIf you're using PostgreSQL or Oracle, you have the option to define the schema you want to work with. The `--schema` flag is optional: if omitted, dblab will display all schemas the connected user has access to in the sidebar tree. If provided, only that specific schema will be shown.\n\n```sh\n# Postgres\n$ dblab --host localhost --user myuser --db users --pass password --schema myschema --ssl disable --port 5432 --driver postgres --limit 50\n$ dblab --url postgres://user:password@host:port/database?sslmode=[mode] --schema myschema\n\n# Oracle\n$ dblab --host localhost --user user2 --db FREEPDB1 --pass password --port 1521 --driver oracle --limit 50 --schema user1\n$ dblab --url 'oracle://user2:password@localhost:1521/FREEPDB1' --schema user1\n```\n\nFor PostgreSQL, the schema can also be set directly in the connection URL with the `search_path` query parameter, instead of passing `--schema` alongside it. Both forms are equivalent:\n\n```sh\n$ dblab --url 'postgres://user:password@localhost:5432/database?sslmode=disable\u0026search_path=myschema'\n```\n\nThe schema the session is currently using is shown in the status bar. If you don't pin a schema — no `--schema` flag, no `schema` field in the config file and no `search_path` in the URL — you can also change it at any time with \u003ckbd\u003ectrl+s\u003c/kbd\u003e; see [Active schema](#active-schema).\n\nYou can use the `--readonly` flag to open a connection in read-only mode. This prevents any write operations (INSERT, UPDATE, DELETE, etc.) from being executed, which is useful when you want to safely browse a production database. The same can be achieved via the configuration file by setting `readonly: true` on a database profile (see [Configuration](#configuration)).\n\n```sh\n# Postgres\n$ dblab --host localhost --user myuser --db users --pass password --ssl disable --port 5432 --driver postgres --limit 50 --readonly\n\n# MySQL\n$ dblab --host localhost --user myuser --db mydb --pass password --ssl disable --port 3306 --driver mysql --limit 50 --readonly\n\n# SQLite\n$ dblab --db path/to/file.sqlite3 --driver sqlite --readonly\n\n# Oracle\n$ dblab --host localhost --user system --db FREEPDB1 --pass password --port 1521 --driver oracle --limit 50 --readonly\n\n# SQL Server\n$ dblab --host localhost --user SA --db msdb --pass '5@klkbN#ABC' --port 1433 --driver sqlserver --limit 50 --readonly\n```\n\n\u003cimg src=\"screenshots/dblab-read-only.png\" /\u003e\n\nAs requested in [#125](https://github.com/danvergara/dblab/issues/125), support for MySQL/MariaDB sockets was integrated.\n\n```sh\n$ dblab --url \"mysql://user:password@unix(/path/to/socket/mysql.sock)/dbname?charset=utf8\"\n$ dblab --socket /path/to/socket/mysql.sock --user user --db dbname --pass password --ssl disable --port 5432 --driver mysql --limit 50\n```\n\nPostgres connection through Unix sockets:\n\n```sh\n$ dblab --url \"postgres://user:password@/dbname?host=/path/to/socket\"\n$ dblab --socket /path/to/socket --user user --db dbname --pass password --ssl disable --port 5432 --driver postgres --limit 50\n```\n\nNow, it is possible to ensure SSL connections with `PostgreSQL` databases. SSL-related parameters have been added, such as `--sslcert`, `--sslkey`, `--sslpassword`, and `--sslrootcert`. More information on how to use such connection flags can be found [here](https://www.postgresql.org/docs/current/libpq-connect.html).\n\n```{ .sh .copy }\ndblab --host  db-postgresql-nyc3-56456-do-user-foo-0.fake.db.ondigitalocean.com --user myuser --db users --pass password --schema myschema --port 5432 --driver postgres --limit 50 --ssl require --sslrootcert ~/Downloads/foo.crt\n```\n\n### SSH Tunnel\n\nNow, it's possible to connect to Postgres or MySQL (more to come later) databases on a server via SSH using a password or SSH key files.\n\nTo do so, 6 new flags have been added to the dblab command:\n\n| Flag                 | Description                                                       |\n|----------------------|-------------------------------------------------------------------|\n|  --ssh-host          |  SSH Server Hostname/IP                                           |\n|  --ssh-port          |  SSH Port                                                         |\n|  --ssh-user          |  SSH User                                                         |\n|  --ssh-pass          |  SSH Password (Empty string for no password)                      |\n|  --ssh-key           |  File with private key for SSH authentication                     |\n|  --ssh-key-pass      | Passphrase for protected private key files                        |\n\n#### Examples\n\nPostgres connection via SSH tunnel using a password:\n\n```{ .sh .copy }\ndblab --host localhost --user postgres --pass password --schema public --ssl disable --port 5432 --driver postgres --limit 50 --ssh-host example.com --ssh-port 22 --ssh-user root --ssh-pass root\n```\n\nPostgres connection via SSH tunnel using an SSH private key file:\n\n```{ .sh .copy }\ndblab --host localhost --user postgres --pass password --schema public --ssl disable --port 5432 --driver postgres --limit 50 --ssh-host example.com --ssh-port 22 --ssh-user root --ssh-key my_ssh_key --ssh-key-pass password\n```\n\nPostgres connection using the url parameter via SSH tunnel using a password:\n\n```{ .sh .copy }\ndblab --url postgres://postgres:password@localhost:5432/users?sslmode=disable --schema public --ssh-host example.com --ssh-port 22 --ssh-user root --ssh-pass root\n```\n\nMySQL connection via SSH tunnel using a password:\n\n```{ .sh .copy }\ndblab --host localhost --user myuser --db mydb --pass 5@klkbN#ABC --ssl enable --port 3306 --driver mysql --limit 50 --ssh-host example.com --ssh-port 22 --ssh-user root --ssh-pass root\n```\n\nMySQL connection via SSH tunnel using an SSH private key file:\n\n```{ .sh .copy }\ndblab --host localhost --user postgres --pass password --ssl enable --port 3306 --driver mysql --limit 50 --ssh-host example.com --ssh-port 22 --ssh-user root --ssh-key my_ssh_key --ssh-key-pass passphrase\n```\n\nMySQL connection using the url parameter via SSH tunnel using a password:\n\n```{ .sh .copy }\ndblab --url \"mysql://myuser:5@klkbN#ABC@mysql+tcp(localhost:3306)/mydb\" --driver mysql --ssh-host example.com --ssh-port 22 --ssh-user root --ssh-pass root\n```\n\n### Configuration\n\nEntering these flags every time is tedious, so `dblab` provides a couple of flags to help with it: `--config` and `--cfg-name`.\n\n`dblab` is going to look for a file called `.dblab.yaml`. Currently, there are three places where you can drop a config file:\n\n- $XDG_CONFIG_HOME ($XDG_CONFIG_HOME/.dblab.yaml)\n- $HOME ($HOME/.dblab.yaml)\n- . (the current directory where you run the command line tool)\n\nIf you want to use this feature, `--config` is mandatory and `--cfg-name` may be omitted. The config file can store one or multiple database connection sections under the `database` field. `database` is an array; previously it was an object only able to store a single connection section at a time. \n\nWe strongly encourage you to adopt the new format as of `v0.18.0`. `--cfg-name` takes the name of the desired database section to connect with. It can be omitted and its default value will be the first item in the array. \n\nAs of `v0.21.0`, SSL connection options are supported in the config file.\n\n```sh\n# default: test\n$ dblab --config\n\n$ dblab --config --cfg-name \"prod\"\n```\n\n#### Key bindings configuration\n\nKey bindings can be configured through the `.dblab.yaml` file. There is a field called `keybindings` where key bindings can be modified. By default, the keybindings are not loaded, so you need to use the `--keybindings` or `-k` flag to load them.\n\nBindings are grouped by the part of the UI they belong to, so every panel can be rebound independently of the others:\n\n| Section | What it controls |\n| --------- | ------------------ |\n| `keybindings` (top level) | `help`, `quit`, `history`, `fullscreen` and `schemas`, which are global |\n| `keybindings.navigation` | moving focus between the three panels |\n| `keybindings.editor` | the Vim-style query editor: cursor motion in normal mode, mode switching, and query execution |\n| `keybindings.sidebar` | jumping to the top / bottom of the sidebar tree |\n| `keybindings.resultset` | tab switching and horizontal motion in the result set panel |\n\nEvery field has a default value, so you only need to list the ones you want to change; anything you leave out falls back to the default shown in the [example below](#dblabyaml-example). The list of the available key bindings belongs to the [bubbletea](https://github.com/charmbracelet/bubbletea) library. Specifically, see the [KeyNames map](https://github.com/charmbracelet/bubbletea/blob/1ed724a2d1316ace504f87a2f0bbbcc189d280f6/key.go#L15) for an accurate reference.\n\n##### Migrating from the flat layout\n\nKey bindings used to be partly flat: `next-tab`, `prev-tab`, `page-top`, `page-bottom`, `end-of-line` and `beginning-of-line` sat at the top level of `keybindings` and were shared by more than one panel. They now live under the panel that uses them:\n\n| Old (top level) | New |\n|-----------------|-----|\n| `next-tab` | `resultset.next-tab` |\n| `prev-tab` | `resultset.prev-tab` |\n| `beginning-of-line` | `resultset.line-start` and `editor.line-start` |\n| `end-of-line` | `resultset.line-end` and `editor.line-end` |\n| `page-top` | `sidebar.go-top` (plus `editor.go-top` and `resultset.go-top`) |\n| `page-bottom` | `sidebar.go-bottom` (plus `editor.go-bottom` and `resultset.go-bottom`) |\n\nThe old top-level fields are no longer read: if your config still sets them, those bindings silently fall back to their defaults. Two things to be aware of while migrating:\n\n- The sidebar's jump-to-top / jump-to-bottom defaults changed from \u003ckbd\u003eg\u003c/kbd\u003e / \u003ckbd\u003eG\u003c/kbd\u003e to \u003ckbd\u003ealt+k\u003c/kbd\u003e / \u003ckbd\u003ealt+j\u003c/kbd\u003e, which leaves \u003ckbd\u003eg\u003c/kbd\u003e / \u003ckbd\u003eG\u003c/kbd\u003e free for the editor and the result set.\n- The editor gained `line-start`, `line-end`, `go-top` and `go-bottom`. These motions already worked, but were hardcoded to \u003ckbd\u003e0\u003c/kbd\u003e, \u003ckbd\u003e$\u003c/kbd\u003e, \u003ckbd\u003eg\u003c/kbd\u003e and \u003ckbd\u003eG\u003c/kbd\u003e; they are now configurable.\n\nThe previously deprecated top-level `execute-query` field is gone as well — use `execute-query` under `keybindings.editor`.\n\n#### .dblab.yaml example\n\n```yaml\ndatabase:\n  - name: \"test\"\n    host: \"localhost\"\n    port: 5432\n    db: \"users\"\n    password: \"password\"\n    user: \"postgres\"\n    driver: \"postgres\"\n    # optional for postgres and oracle\n    # if omitted, all accessible schemas are shown\n    schema: \"myschema\"\n    # optional: set to true to force a read-only session\n    readonly: true\n  - name: \"prod\"\n    # example endpoint\n    host: \"mydb.123456789012.us-east-1.rds.amazonaws.com\"\n    port: 5432\n    db: \"users\"\n    password: \"password\"\n    user: \"postgres\"\n    schema: \"public\"\n    driver: \"postgres\"\n    ssl: \"require\"\n    sslrootcert: \"~/.postgresql/root.crt.\"\n  - name: \"oracle\"\n    host: \"localhost\"\n    port: 1521\n    db: \"FREEPDB1\"\n    schema: \"user1\"\n    password: \"password\"\n    user: \"user2\"\n    driver: \"oracle\"\n    ssl: \"enable\"\n    wallet: \"path/to/wallet\"\n    ssl-verify: true\n  - name: \"sqlserver\"\n    driver: \"sqlserver\"\n    host: \"localhost\"\n    port: 1433\n    db: \"msdb\"\n    password: \"5@klkbN#ABC\"\n    user: \"SA\"\n  - name: \"ssh-tunnel\"\n    host: \"localhost\"\n    port: 5432\n    db: \"users\"\n    password: \"password\"\n    user: \"postgres\"\n    schema: \"public\"\n    driver: \"postgres\"\n    ssh-host: \"example.com\"\n    ssh-port: 22\n    ssh-user: \"ssh-user\"\n    ssh-pass: \"password\"\n  - name: \"realistic-ssh-example\"\n    host: \"rds-endpoint.region.rds.amazonaws.com\"\n    port: 5432\n    db: \"database_name\"\n    user: \"db_user\"\n    password: \"password\"\n    schema: \"schema_name\"\n    driver: \"postgres\"\n    ssl: \"require\"\n    ssh-host: \"bastion.host.ip\"\n    ssh-port: 22\n    ssh-user: \"ec2-user\"\n    ssh-key-file: \"/path/to/ssh/key.pem\"\n    ssh-key-pass: \"hiuwiewnc092\"\n# should be greater than 0, otherwise the app will error out\nlimit: 50\nkeybindings:\n  help: '?'\n  quit: 'ctrl+c'\n  history: 'alt+h'\n  fullscreen: 'alt+f'\n  # opens the active schema picker (postgres and oracle only)\n  schemas: 'ctrl+s'\n  # moving focus between the three panels\n  navigation:\n    up: 'ctrl+k'\n    down: 'ctrl+j'\n    left: 'ctrl+h'\n    right: 'ctrl+l'\n  # the query editor, in normal mode\n  editor:\n    up: 'k'\n    down: 'j'\n    left: 'h'\n    right: 'l'\n    line-start: '0'\n    line-end: '$'\n    go-top: 'g'\n    go-bottom: 'G'\n    word-forward: 'w'\n    word-end: 'e'\n    word-backward: 'b'\n    insert: 'i'\n    normal: 'esc'\n    append: 'a'\n    append-line-end: 'A'\n    insert-line-start: 'I'\n    open-line-below: 'o'\n    open-line-above: 'O'\n    undo: 'u'\n    redo: 'U'\n    execute-query: 'ctrl+e'\n    execute-single-query: 'ctrl+r'\n  # the database tree on the left\n  sidebar:\n    go-top: 'alt+k'\n    go-bottom: 'alt+j'\n  # the result set panel and its metadata tabs\n  resultset:\n    next-tab: 'tab'\n    prev-tab: 'shift+tab'\n    line-start: '0'\n    line-end: '$'\n    go-top: 'g'\n    go-bottom: 'G'\n```\n\nOr for SQLite:\n\n```yaml\ndatabase:\n  - name: \"prod\"\n    db: \"path/to/file.sqlite3\"\n    driver: \"sqlite\"\n```\n\nOnly the `host`, `ssl`, and `schema` fields are optional. `host` defaults to `127.0.0.1`, `ssl` defaults to `disable`. The `schema` field is only applicable to PostgreSQL and Oracle; if omitted, all accessible schemas are shown.\n\n### Connection Profiles\n\n\u003cimg src=\"screenshots/dblab-connect.png\" /\u003e\n\ndblab supports saving and reusing database connection profiles. When you successfully connect to a database, you can store the connection parameters as a named profile using the `--save-as` flag. Both the database password and the SSH tunnel password (when using SSH connections) are stored securely in your operating system's keyring (e.g., GNOME Keyring, macOS Keychain, or Windows Credential Manager) rather than in plain text.\n\n#### Saving a profile\n\nUse the `--save-as` flag with any connection to save it as a named profile:\n\n```sh\n$ dblab --host localhost --user myuser --db users --pass password --ssl disable --port 5432 --driver postgres --limit 50 --save-as myprofile\n```\n\nThe connection parameters are saved to `$XDG_CONFIG_HOME/dblab/dblab.json` (excluding passwords), while the database password and SSH password (if provided) are stored in the OS keyring.\n\n#### Using saved profiles\n\nUse the `connect` command to launch an interactive menu that lists all saved profiles:\n\n```sh\n$ dblab connect\n```\n\nThis opens a TUI selector where you can:\n\n- Browse saved database profiles\n- Press \u003ckbd\u003eEnter\u003c/kbd\u003e to connect to the selected profile\n- Press \u003ckbd\u003eCtrl+D\u003c/kbd\u003e to delete a profile\n- Press \u003ckbd\u003eCtrl+C\u003c/kbd\u003e to quit\n\nThe password is automatically retrieved from the OS keyring when connecting.\n\n#### Profile storage format\n\nProfiles are stored in `$XDG_CONFIG_HOME/dblab/dblab.json`:\n\n```json\n{\n  \"profiles\": {\n    \"myprofile\": {\n      \"host\": \"localhost\",\n      \"port\": \"5432\",\n      \"db\": \"users\",\n      \"user\": \"postgres\",\n      \"schema\": \"public\",\n      \"driver\": \"postgres\"\n    }\n  }\n}\n```\n\n## Navigation\n\nThe UI is split into three panels: the **sidebar tree** on the left, the **query editor** on the top right, and the **result set** panel below it. Move focus between them with \u003ckbd\u003eCtrl+H\u003c/kbd\u003e, \u003ckbd\u003eCtrl+J\u003c/kbd\u003e, \u003ckbd\u003eCtrl+K\u003c/kbd\u003e and \u003ckbd\u003eCtrl+L\u003c/kbd\u003e.\n\nEvery key binding in this README is the default. All of them can be replaced through the `.dblab.yaml` configuration file — there are no flags for it — so if you've customized a binding, substitute yours for the default shown here. See [Key bindings configuration](#key-bindings-configuration).\n\n### Panels and the sidebar tree\n\ndblab connects to a single database (the `--db` flag is mandatory) and displays its catalog as a tree in the sidebar. For PostgreSQL and Oracle, the tree shows the database, its schemas, and the tables under each schema. For MySQL, SQLite, and SQL Server, the tree shows the database and its tables directly. If the `--schema` flag is provided for PostgreSQL or Oracle, only that schema is shown; otherwise, all accessible schemas are listed.\n\n\u003cimg src=\"screenshots/tree-view.png\" /\u003e\n\nNavigate the tree with \u003ckbd\u003eUp\u003c/kbd\u003e and \u003ckbd\u003eDown\u003c/kbd\u003e (or \u003ckbd\u003ek\u003c/kbd\u003e and \u003ckbd\u003ej\u003c/kbd\u003e), and press \u003ckbd\u003eEnter\u003c/kbd\u003e on a table to load its rows into the result set panel. Jump straight to the first or last visible node with \u003ckbd\u003ealt+k\u003c/kbd\u003e and \u003ckbd\u003ealt+j\u003c/kbd\u003e (`keybindings.sidebar.go-top` and `keybindings.sidebar.go-bottom`), and scroll the tree sideways with \u003ckbd\u003eh\u003c/kbd\u003e and \u003ckbd\u003el\u003c/kbd\u003e when a name is wider than the panel.\n\nPress \u003ckbd\u003e/\u003c/kbd\u003e to search the tree by name and \u003ckbd\u003eEsc\u003c/kbd\u003e to leave the search. While a search is active every character you type — including \u003ckbd\u003eh\u003c/kbd\u003e and \u003ckbd\u003el\u003c/kbd\u003e — goes to the search box instead of scrolling the tree.\n\n### Result sets\n\nSelecting a table populates the result set panel, which has one tab per view of the table. Press \u003ckbd\u003etab\u003c/kbd\u003e and \u003ckbd\u003eshift+tab\u003c/kbd\u003e to move between them:\n\n- **Data** — the rows of the table, or the result of the query you executed\n- **Columns** — the schema of the table\n- **Indexes** — the indexes on the table\n- **Constraints** — the constraints on the table\n\n\u003cimg src=\"screenshots/rows-view.png\" /\u003e\n\u003cimg src=\"screenshots/structure-view.png\" /\u003e\n\u003cimg src=\"screenshots/indexes-view.png\" /\u003e\n\u003cimg src=\"screenshots/constraints-view.png\" /\u003e\n\nMove around a result set with the arrow keys or \u003ckbd\u003eh\u003c/kbd\u003e/\u003ckbd\u003ej\u003c/kbd\u003e/\u003ckbd\u003ek\u003c/kbd\u003e/\u003ckbd\u003el\u003c/kbd\u003e. The selected cell is highlighted so you can see where you are; press \u003ckbd\u003eEnter\u003c/kbd\u003e on a cell to copy its content.\n\nThere are no pagination controls — they proved too slow to page through a table effectively. To work through a large table, write a `SELECT` with explicit `OFFSET` and `LIMIT` instead.\n\n### Active schema\n\nThe right-hand side of the status bar shows the schema the session is currently using, as `active schema: \u003cname\u003e`. On startup that's whatever schema you pinned — via `--schema`, the `schema` field in `.dblab.yaml`, or the `search_path` query parameter of a PostgreSQL connection URL — or the session default (`current_schema()` on PostgreSQL, `SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA')` on Oracle) when you pinned none.\n\nIf you pinned a schema, that's the schema for the whole session and the picker below is disabled: \u003ckbd\u003ectrl+s\u003c/kbd\u003e does nothing. Omit the schema to be able to switch it from the app.\n\nPress \u003ckbd\u003ectrl+s\u003c/kbd\u003e (`schemas`) from any panel to open the schema picker, a filterable list of the schemas the connected user can see. Type to narrow the list, press \u003ckbd\u003eEnter\u003c/kbd\u003e to make the highlighted schema the active one, or press \u003ckbd\u003eEsc\u003c/kbd\u003e to close the picker without changing anything. Focus returns to the query editor either way.\n\nSwitching the active schema changes the database session — `set search_path` on PostgreSQL, `ALTER SESSION SET CURRENT_SCHEMA` on Oracle — so unqualified table names in the queries you execute resolve against the new schema. The sidebar tree is left as it is: it keeps listing the schemas it was built with, and selecting a table there still reads that table's own schema, so browsing the catalog is unaffected.\n\nThe picker is only available for PostgreSQL and Oracle, the two drivers where dblab tracks an active schema. On MySQL, SQLite and SQL Server \u003ckbd\u003ectrl+s\u003c/kbd\u003e does nothing and the status bar has no schema segment.\n\n### Full-screen mode\n\nFocus the query editor or the result set panel and press \u003ckbd\u003ealt+f\u003c/kbd\u003e (`fullscreen`) to expand it to fill the entire terminal, hiding the title, status bar and the other panels. Press \u003ckbd\u003eEsc\u003c/kbd\u003e to return to the split layout. Full-screen mode is also left automatically if you navigate focus away from the editor or result set panel — it isn't available for the sidebar tree.\n\n\u003cimg src=\"screenshots/fullscreen-editor.png\" /\u003e\n\u003cimg src=\"screenshots/fullscreen-resultset.png\" /\u003e\n\n## Query editor\n\n### Modes\n\nThe query editor uses **normal** and **insert** modes, similar to Vim. When you focus the editor it starts in **normal** mode. Press \u003ckbd\u003ei\u003c/kbd\u003e to enter insert mode and type or edit SQL; press \u003ckbd\u003eEscape\u003c/kbd\u003e to return to normal mode. You can also enter insert mode with \u003ckbd\u003ea\u003c/kbd\u003e (after the cursor), \u003ckbd\u003eA\u003c/kbd\u003e (at the end of the line), \u003ckbd\u003eI\u003c/kbd\u003e (at the first non-blank character), \u003ckbd\u003eo\u003c/kbd\u003e (open a new line below) or \u003ckbd\u003eO\u003c/kbd\u003e (open a new line above) — `editor.append`, `editor.append-line-end`, `editor.insert-line-start`, `editor.open-line-below` and `editor.open-line-above`.\n\nCursor movement depends on the mode: in insert mode use the arrow keys, in normal mode use \u003ckbd\u003eh\u003c/kbd\u003e, \u003ckbd\u003ej\u003c/kbd\u003e, \u003ckbd\u003ek\u003c/kbd\u003e and \u003ckbd\u003el\u003c/kbd\u003e.\n\nThe status bar's left-hand badge shows which panel is focused rather than the editor's current mode; the editor itself still shows `-- NORMAL --` / `-- INSERT --` in its own status line.\n\n### Editing and motions\n\nIn normal mode:\n\n- \u003ckbd\u003edd\u003c/kbd\u003e deletes the current line, \u003ckbd\u003eyy\u003c/kbd\u003e yanks it into an internal register, and \u003ckbd\u003ep\u003c/kbd\u003e pastes the yanked or deleted line after the current line\n- \u003ckbd\u003ex\u003c/kbd\u003e deletes the character under the cursor\n- \u003ckbd\u003ew\u003c/kbd\u003e, \u003ckbd\u003ee\u003c/kbd\u003e and \u003ckbd\u003eb\u003c/kbd\u003e move forward a word, to the end of a word and backward a word (`keybindings.editor.word-forward`, `keybindings.editor.word-end` and `keybindings.editor.word-backward`)\n- \u003ckbd\u003e0\u003c/kbd\u003e and \u003ckbd\u003e$\u003c/kbd\u003e move to the beginning and end of the current line (`keybindings.editor.line-start` and `keybindings.editor.line-end`)\n- \u003ckbd\u003eg\u003c/kbd\u003e and \u003ckbd\u003eG\u003c/kbd\u003e jump to the first and last line of the buffer (`keybindings.editor.go-top` and `keybindings.editor.go-bottom`)\n- \u003ckbd\u003eu\u003c/kbd\u003e undoes the last change and \u003ckbd\u003eU\u003c/kbd\u003e redoes it (`keybindings.editor.undo` and `keybindings.editor.redo`)\n- \u003ckbd\u003ev\u003c/kbd\u003e / \u003ckbd\u003eV\u003c/kbd\u003e enter visual / visual-line mode to select text, and \u003ckbd\u003e/\u003c/kbd\u003e / \u003ckbd\u003e?\u003c/kbd\u003e search the buffer forward / backward (\u003ckbd\u003en\u003c/kbd\u003e / \u003ckbd\u003eN\u003c/kbd\u003e repeat the last search)\n- \u003ckbd\u003eCtrl+D\u003c/kbd\u003e / \u003ckbd\u003eCtrl+U\u003c/kbd\u003e scroll the view down / up by half a page\n\nThis is a full Vim emulation, so plenty of other standard commands (text objects, `J`, `~`, `r`, registers, and so on) work as well; the list above only covers what shows up in `keybindings.editor`.\n\nThe cursor motions, the mode switches and the execute shortcuts are all configurable under `keybindings.editor`; the line-oriented commands (\u003ckbd\u003edd\u003c/kbd\u003e, \u003ckbd\u003eyy\u003c/kbd\u003e, \u003ckbd\u003ep\u003c/kbd\u003e, \u003ckbd\u003ex\u003c/kbd\u003e), visual mode, search and \u003ckbd\u003eCtrl+D\u003c/kbd\u003e / \u003ckbd\u003eCtrl+U\u003c/kbd\u003e are fixed.\n\n### Executing queries\n\nPress \u003ckbd\u003ectrl+e\u003c/kbd\u003e to execute the contents of the editor (`keybindings.editor.execute-query`). Whitespace-only queries are ignored.\n\nPress \u003ckbd\u003ectrl+r\u003c/kbd\u003e to execute only the query on the current cursor line (`keybindings.editor.execute-single-query`), leaving the other statements in the editor untouched. Both bindings work from either mode.\n\n#### Multiple statements\n\n\u003cimg src=\"screenshots/dblab-multi-query.png\" /\u003e\n\nYou can write multiple SQL statements separated by semicolons (`;`) and execute them all at once with \u003ckbd\u003ectrl+e\u003c/kbd\u003e:\n\n```sql\nSELECT * FROM users; SELECT * FROM orders; SELECT count(*) FROM products;\n```\n\nThe statements run concurrently and each result is displayed in its own tab (\"query #1\", \"query #2\", and so on) — three tabs, for the example above. If a statement fails, its tab shows the error message while the successful ones still show their results. A maximum of 5 statements can be executed per batch.\n\nWhile a batch is running, press \u003ckbd\u003eCtrl+c\u003c/kbd\u003e to cancel it; press \u003ckbd\u003eCtrl+c\u003c/kbd\u003e again to quit dblab.\n\n### Query history\n\n\u003cimg src=\"screenshots/query-history.png\" /\u003e\n\ndblab automatically saves every executed query to a local history file (`$XDG_CONFIG_HOME/dblab/dblab.gob`). Press \u003ckbd\u003ealt+h\u003c/kbd\u003e (see [Key bindings configuration](#key-bindings-configuration) to configure it) to open the query history view, which displays past queries sorted newest-first in a filterable list. Use the built-in search to narrow results, press \u003ckbd\u003eEnter\u003c/kbd\u003e to load the selected query back into the editor, or press \u003ckbd\u003eEsc\u003c/kbd\u003e to return without selecting anything.\n\n\n## Help modal\n\n\u003cimg src=\"screenshots/dblab-help-modal.png\" /\u003e\n\nPress \u003ckbd\u003e?\u003c/kbd\u003e at any time to open the help modal, which displays all available key bindings in a centered overlay. Press \u003ckbd\u003eEsc\u003c/kbd\u003e to dismiss it; focus returns to the query editor.\n\n## Key bindings\n\nThese are the defaults; see [Key bindings configuration](#key-bindings-configuration) to change them. The **Config field** column gives the `.dblab.yaml` key for the bindings that can be customized — the rest are fixed.\n\n### Panel navigation\n\n| Key | Description | Config field |\n|-----|-------------|--------------|\n| \u003ckbd\u003eCtrl+H\u003c/kbd\u003e | Toggle to the panel on the left | `navigation.left` |\n| \u003ckbd\u003eCtrl+J\u003c/kbd\u003e | Toggle to the panel below | `navigation.down` |\n| \u003ckbd\u003eCtrl+K\u003c/kbd\u003e | Toggle to the panel above | `navigation.up` |\n| \u003ckbd\u003eCtrl+L\u003c/kbd\u003e | Toggle to the panel on the right | `navigation.right` |\n\n### Query editor (both modes)\n\n| Key | Description | Config field |\n|-----|-------------|--------------|\n| \u003ckbd\u003ectrl+e\u003c/kbd\u003e | Execute the contents of the editor | `editor.execute-query` |\n| \u003ckbd\u003ectrl+r\u003c/kbd\u003e | Execute only the query on the current cursor line | `editor.execute-single-query` |\n\n### Query editor (normal mode)\n\n| Key | Description | Config field |\n|-----|-------------|--------------|\n| \u003ckbd\u003ei\u003c/kbd\u003e | Enter insert mode before the cursor | `editor.insert` |\n| \u003ckbd\u003ea\u003c/kbd\u003e | Enter insert mode after the cursor | `editor.append` |\n| \u003ckbd\u003eA\u003c/kbd\u003e | Enter insert mode at the end of the line | `editor.append-line-end` |\n| \u003ckbd\u003eI\u003c/kbd\u003e | Enter insert mode at the first non-blank character | `editor.insert-line-start` |\n| \u003ckbd\u003eo\u003c/kbd\u003e | Open a new line below and enter insert mode | `editor.open-line-below` |\n| \u003ckbd\u003eO\u003c/kbd\u003e | Open a new line above and enter insert mode | `editor.open-line-above` |\n| \u003ckbd\u003eh\u003c/kbd\u003e \u003ckbd\u003ej\u003c/kbd\u003e \u003ckbd\u003ek\u003c/kbd\u003e \u003ckbd\u003el\u003c/kbd\u003e | Move the cursor left, down, up, right | `editor.left` / `editor.down` / `editor.up` / `editor.right` |\n| \u003ckbd\u003ew\u003c/kbd\u003e / \u003ckbd\u003ee\u003c/kbd\u003e / \u003ckbd\u003eb\u003c/kbd\u003e | Move forward a word / to the end of a word / back a word | `editor.word-forward` / `editor.word-end` / `editor.word-backward` |\n| \u003ckbd\u003edd\u003c/kbd\u003e | Delete the current line | — |\n| \u003ckbd\u003eyy\u003c/kbd\u003e | Yank the current line | — |\n| \u003ckbd\u003ep\u003c/kbd\u003e | Paste the yanked or deleted line after the current line | — |\n| \u003ckbd\u003ex\u003c/kbd\u003e | Delete the character under the cursor | — |\n| \u003ckbd\u003e0\u003c/kbd\u003e / \u003ckbd\u003e$\u003c/kbd\u003e | Move to the start / end of the current line | `editor.line-start` / `editor.line-end` |\n| \u003ckbd\u003eg\u003c/kbd\u003e / \u003ckbd\u003eG\u003c/kbd\u003e | Jump to the first / last line of the buffer | `editor.go-top` / `editor.go-bottom` |\n| \u003ckbd\u003eu\u003c/kbd\u003e | Undo the last change | `editor.undo` |\n| \u003ckbd\u003eU\u003c/kbd\u003e | Redo the last undone change | `editor.redo` |\n| \u003ckbd\u003ev\u003c/kbd\u003e / \u003ckbd\u003eV\u003c/kbd\u003e | Enter visual / visual-line mode | — |\n| \u003ckbd\u003e/\u003c/kbd\u003e / \u003ckbd\u003e?\u003c/kbd\u003e | Search the buffer forward / backward | — |\n| \u003ckbd\u003en\u003c/kbd\u003e / \u003ckbd\u003eN\u003c/kbd\u003e | Repeat the last search, forward / backward | — |\n| \u003ckbd\u003eCtrl+D\u003c/kbd\u003e / \u003ckbd\u003eCtrl+U\u003c/kbd\u003e | Scroll the view down / up by half a page | — |\n\n### Query editor (insert mode)\n\n| Key | Description | Config field |\n|-----|-------------|--------------|\n| \u003ckbd\u003eEscape\u003c/kbd\u003e | Return to normal mode | `editor.normal` |\n| \u003ckbd\u003eArrow keys\u003c/kbd\u003e | Move the cursor | — |\n\n### Sidebar tree\n\n| Key | Description | Config field |\n|-----|-------------|--------------|\n| \u003ckbd\u003eArrow Up\u003c/kbd\u003e / \u003ckbd\u003ek\u003c/kbd\u003e | Move up the tree | — |\n| \u003ckbd\u003eArrow Down\u003c/kbd\u003e / \u003ckbd\u003ej\u003c/kbd\u003e | Move down the tree | — |\n| \u003ckbd\u003ealt+k\u003c/kbd\u003e | Jump to the first visible node | `sidebar.go-top` |\n| \u003ckbd\u003ealt+j\u003c/kbd\u003e | Jump to the last visible node | `sidebar.go-bottom` |\n| \u003ckbd\u003eh\u003c/kbd\u003e / \u003ckbd\u003el\u003c/kbd\u003e | Scroll the tree left / right | — |\n| \u003ckbd\u003e/\u003c/kbd\u003e | Search the tree by name | — |\n| \u003ckbd\u003eEsc\u003c/kbd\u003e | Leave the search | — |\n| \u003ckbd\u003eEnter\u003c/kbd\u003e | List all rows of the selected table and display its structure | — |\n\n### Result set panel\n\nApplies to all tabs of the result set panel.\n\n| Key | Description | Config field |\n|-----|-------------|--------------|\n| \u003ckbd\u003etab\u003c/kbd\u003e / \u003ckbd\u003eshift+tab\u003c/kbd\u003e | Navigate to the next / previous metadata tab | `resultset.next-tab` / `resultset.prev-tab` |\n| \u003ckbd\u003eArrow Up\u003c/kbd\u003e / \u003ckbd\u003ek\u003c/kbd\u003e | Navigate the table upward | — |\n| \u003ckbd\u003eArrow Down\u003c/kbd\u003e / \u003ckbd\u003ej\u003c/kbd\u003e | Navigate the table downward | — |\n| \u003ckbd\u003eArrow Left\u003c/kbd\u003e / \u003ckbd\u003eh\u003c/kbd\u003e | Navigate the table to the left | — |\n| \u003ckbd\u003eArrow Right\u003c/kbd\u003e / \u003ckbd\u003el\u003c/kbd\u003e | Navigate the table to the right | — |\n| \u003ckbd\u003eg\u003c/kbd\u003e / \u003ckbd\u003eG\u003c/kbd\u003e | Move to the top / bottom of the dataset | — |\n| \u003ckbd\u003e0\u003c/kbd\u003e / \u003ckbd\u003e$\u003c/kbd\u003e | Move to the left / right edge of the row | `resultset.line-start` / `resultset.line-end` |\n| \u003ckbd\u003eEnter\u003c/kbd\u003e | Copy the content of the selected cell | — |\n\n\n### Global\n\n| Key | Description | Config field |\n|-----|-------------|--------------|\n| \u003ckbd\u003eAlt+h\u003c/kbd\u003e  | Open the query history view | `history` |\n| \u003ckbd\u003eAlt+f\u003c/kbd\u003e | Expand the focused query editor or result set panel to full screen | `fullscreen` |\n| \u003ckbd\u003eCtrl+s\u003c/kbd\u003e | Open the schema picker to change the active schema (PostgreSQL and Oracle, when no schema was pinned at startup) | `schemas` |\n| \u003ckbd\u003e?\u003c/kbd\u003e | Open the help modal showing all key bindings | `help` |\n| \u003ckbd\u003eEsc\u003c/kbd\u003e | Dismiss the help modal, the query history or the schema picker, exit full-screen mode (or return to normal mode in the query editor) | — |\n| \u003ckbd\u003eCtrl+c\u003c/kbd\u003e | Cancel running queries if any; otherwise quit the application | `quit` |\n\n## Contribute\n\n- Fork this repository\n- Create a new feature branch for a new functionality or bugfix\n- Commit your changes\n- Execute test suite\n- Push your code and open a new pull request\n- Use [issues](https://github.com/danvergara/dblab/issues) for any questions\n- Check [wiki](https://github.com/danvergara/dblab/wiki) for extra documentation\n\n## License\n\nThe MIT License (MIT). See [LICENSE](LICENSE) file for more details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanvergara%2Fdblab","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanvergara%2Fdblab","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanvergara%2Fdblab/lists"}