Repository files navigation

πŸš€ Orbit.nvim

A database IDE for Neovim

Your database revolves around your editor, not the other way around.

Orbit runs statements through your existing database CLI, retains one connection per profile where the CLI supports it, keeps profiles per query buffer, browses schemas, completes cached objects, and renders JSON results in a navigable grid.

preview

What It Does

  • Open one dedicated workspace tab with a searchable profile and schema browser.
  • Run a whole statement or a visual selection asynchronously without leaving Neovim.
  • Bind each query buffer to its own connection profile.
  • Browse tables, views, and columns; run connector-specific object actions; create a bound sample statement; copy qualified object names.
  • Inspect and copy raw result values, including structured JSON values.
  • Confirm potentially mutating statements before they run.
  • Complete cached tables, views, columns, and table aliases, clause-aware, with Neovim's built-in omnifunc or an optional blink.cmp source.
  • Browse reusable SQL files from multiple named saved-query locations.

Requirements

  • Neovim 0.10 or later.
  • No required third-party Neovim plugins.
  • The CLI required by each connection profile:
Profile kindCLINotes
trinotrinoOrbit requests JSON output.
sqlitesqlite3Requires a build that supports -json.
postgrespsqlRequires a version that supports --csv.

Installation

With lazy.nvim:

{
"mrpbennett/orbit.nvim",
opts= {},
}

Or call setup from your Neovim configuration:

require("orbit").setup()

Quick Start

  1. Run :OrbitProfiles. This creates ~/.local/share/orbit.nvim/profiles.json with owner-only (0600) permissions and opens it for editing.
  2. Add a connection profile using the format below.
  3. Open :OrbitWorkspace or a SQL buffer.
  4. Bind a profile with :OrbitProfile, or press <CR> on a profile in the workspace.
  5. Run :OrbitExecute, or use <leader>E in Normal or Visual mode in a SQL buffer.

If a query buffer has no profile, executing it opens profile selection and retries after you choose one.

Supported Connectors

KindRequired optionsOptional optionsSchema support
trinoserver, user, catalogschema, schema_patterns, executable, arguments, confirm_mutationsTables, views, and columns from information_schema. Omitting schema browses the catalog except information_schema.
sqlitepathschema_patterns, executable, arguments, confirm_mutationsTables and views from sqlite_master, plus columns from PRAGMA table_info, under main.
postgresdatabaseschema_patterns, host, port, user, password, sslmode, executable, arguments, confirm_mutationsTables and views outside PostgreSQL system schemas, plus columns, primary keys, foreign keys, and indexes.

executable replaces the CLI binary and arguments adds an array of string arguments before Orbit's generated arguments. This is useful for wrappers or CLI-specific authentication flags. For SQLite and PostgreSQL, Orbit retains one interactive CLI connection per profile; statements, schema browsing, and completion prewarming share it and are serialized per profile. A changed profile definition, failed CLI, :OrbitDisconnect, or Neovim exit closes the connection; the next request reconnects automatically. Trino statements instead run one trino CLI invocation per statement, serialized per profile, because the trino CLI does not flush its output while held open on a retained connection.

Schema browsing and completion cache rows only while the connection profile's kind and options are unchanged. Updating a profile clears its prior schema rows before Orbit acquires replacements. Connector metadata that is unavailable for an object, such as Trino primary keys, is shown as unavailable rather than treated as a statement failure. Explicit Workspace refreshes run after pending acquisitions and coalesce with other refresh requests.

schema_patterns restricts the tables and views shown by Orbit's Workspace schema browser, but does not change database permissions or restrict statements you run manually. For Trino, it maps each catalog to an array of exact schema names; use an empty array to include every non-system schema from that catalog. PostgreSQL and SQLite use a non-empty array of exact schema names instead. SQLite's only available schema is main.

Connection Profiles

The profile file is the source of truth for named connection profiles. Its default location is ~/.local/share/orbit.nvim/profiles.json; set profile_path in setup() to use another location. Orbit refuses to load a file that is not mode 0600.

Profiles are JSON, versioned at 1, and names must be unique:

PostgreSQL
{
"version": 1,
"profiles": [
{
"name": "app-db",
"kind": "postgres",
"options": {
"database": "postgres",
"host": "postgres.example.com",
"port": 5432,
"user": "postr",
"password": "somePassword",
"sslmode": "require"
}
}
]
}
SQLite
{
"version": 1,
"profiles": [
{
"name": "local",
"kind": "sqlite",
"options": {
"path": "/home/projects/data.db"
}
}
]
}
Trino
{
"version": 1,
"profiles": [
{
"name": "analytics",
"kind": "trino",
"arguments": ["--password"]
"options": {
"server": "https://trino.example.com:8443",
"user": "alice",
"catalog": "hive",
"schema": "analytics",
"schema_patterns": {
"hive": ["analytics", "reporting"],
"iceberg": []
// add more catalogs as needed...// see Trino Multi-Catalog Schema Browser
},
}
}
]
}

Trino Multi-Catalog Schema Browser

Trino profiles still require catalog as the CLI's default catalog, but schema_patterns can browse schemas from multiple catalogs. Orbit retains each object's catalog for column inspection, copied names, and generated sample statements:

{
"catalog": "gridhive",
"schema_patterns": {
"catalog_1": ["data_v2"],
"catalog_2": ["aggr", "cleanroom", "report"],
"iceberg": ["cleanroom"],
"sqlserver_rep": ["dbo"]
}
}

An empty array, such as "catalog_1": [], includes every non-system schema from that catalog. Omit a catalog entirely to hide it.

Authentication

PostgreSQL profiles may include options.password. Orbit passes it only to psql as PGPASSWORD, never as a command-line argument. The profile file is owner-protected (0600), but a password remains sensitive; use your system's credential management or a ~/.pgpass file if you prefer not to store it in JSON.

Configure Trino authentication exactly as you do for the Trino CLI, including its --password flag, environment variables, tokens, keyrings, or credential providers it uses.

Orbit passes profile values to the CLI as literal arguments. It does not expand $VAR or ${VAR} inside JSON. Other Trino CLI authentication mechanisms, such as tokens or external credential providers, continue to work through their normal CLI configuration.

Note

Connection profiles can contain sensitive settings, including PostgreSQL passwords. Orbit requires the profile file to be mode 0600; do not copy it into a repository or share it.

Workspace Workflow

:OrbitWorkspace opens a dedicated Orbit tabpage with a profile/schema browser and a normal SQL editing window. Run it again to toggle that browser. :OrbitWorkspaceClose closes only that tabpage.

  1. Press <CR> on a profile to select it and bind it to the active query buffer.
  2. Optionally press l to load its schema for browsing and completion.
  3. Press n to open a new SQL buffer already bound to the selected profile.
  4. Execute a statement. Results appear in the reusable bottom result grid.

Set saved_query_dirs to add ordered, named recursive trees of .sql files to the sidebar:

saved_query_dirs= {
{ Work="~/queries/work" },
{ Personal="~/queries/personal" },
}

Each entry must contain one unique display name and directory. Orbit preserves the configured order, expands paths such as ~, and shows each location as a separate top-level tree collapsed by default. Select a profile, then press <CR> on a saved query to open it in the Workspace query window bound to that profile; loading the schema is not required. Press r on any saved-query directory to rescan only its top-level location.

From a workspace query buffer, / focuses the workspace filter. Elsewhere, / retains normal Neovim search behavior.

Commands

CommandDescription
:OrbitProfilesCreate, protect, and edit the profile file.
:OrbitProfileSearch profiles and bind one to the current query buffer.
:OrbitSelectProfileAlias for :OrbitProfile.
:OrbitExecuteExecute the single unambiguous statement in the current buffer.
:'<,'>OrbitExecuteExecute the selected line range.
:OrbitCancelCancel the statement running in the current buffer.
:OrbitDisconnectClose the connection for the current buffer's profile.
:OrbitWorkspaceOpen the workspace or toggle its profile/schema browser.
:OrbitWorkspaceCloseClose the Orbit workspace tabpage.

Whole-buffer execution rejects ambiguous multi-statement content. Select the exact statement in Visual mode, then run :OrbitExecute or <leader>E.

Keybindings

Configurable Mappings

Orbit installs the following defaults:

Mode and scopeMappingAction
Normal, global<leader>DOpen the workspace or toggle its profile/schema browser.
Normal, SQL buffer<leader>EExecute the buffer statement.
Visual, SQL buffer<leader>EExecute the visual selection.
Normal, SQL buffer<leader>PSelect a connection profile.
Normal, SQL buffer<leader>XCancel the running statement.

Configure action mappings through keymaps. execute, browse, cancel, and select_profile are buffer-local in SQL buffers; workspace is global. Set an action to false to disable its default mapping.

require("orbit").setup({
keymaps= {
execute="<leader>E",
workspace="<leader>D",
select_profile="<leader>P",
cancel="<leader>X",
},
})

Workspace Sidebar

KeyAction
lExpand the selected profile, schema, object group, table metadata folder, or object.
hCollapse the selected node.
<CR>Select and bind a profile to the current query buffer, or open a saved query bound to the selected profile.
nCreate a query buffer bound to the selected profile.
sOpen a bound sample statement for the selected table or view.
aSelect a connector-supported action for the selected table or view.
yCopy the qualified selected table or view name.
PPreview the selected saved query without opening or binding it.
/Filter profiles, schema objects, and saved queries.
rReload the profile file and refresh the selected profile schema, or rescan saved queries.
ZCollapse the open profile schema tree.
?Show help.
qClose the workspace.

Expanding a table reveals its available metadata folders. SQLite provides columns, primary keys, foreign keys, and indexes; each folder loads on demand. Views remain under the schema's views group and expose their columns.

Result Grid

KeyAction
h, j, k, lMove between cells.
<CR>Inspect the raw value in a floating window.
yCopy the raw selected value.
qClose the standalone grid, or return to the query editor in a workspace.

Workspace sample statements for PostgreSQL and SQLite base tables become editable when Orbit can load a primary key. Ad-hoc statements, views, Trino, and tables without a primary key remain read-only.

Key / commandAction
o, OInsert a local row below or above the current row.
i, <CR>Enter Insert mode in the focused cell; press Esc to keep the local edit.
ddMark the current row for local deletion.
V, j / k, dSelect complete rows and delete the selection.
uUndo the most recent local edit.
:wConfirm, transactionally save, and reload pending changes.
:wqSave successfully, then close the Result grid.
:q!Discard local changes and close.
:e!Discard local changes and reload the table.

Edits are never sent to the database until :w. A failed write leaves the local Result grid unchanged. Type NULL as the complete cell value to write a SQL NULL value.

Normal Neovim scrolling remains available, including <C-d>, <C-u>, zh, and zl.

Schema Object Actions

Press a on a table or view in the Workspace schema browser to select an action supplied by its connection profile kind. Actions that inspect metadata open in the Result grid; sample actions create a bound query buffer instead.

  • SQLite: sample statement, columns, primary keys, indexes, foreign keys, and object definition.
  • PostgreSQL: sample statement, columns, primary keys, indexes, foreign keys, and view definition.
  • Trino: sample statement and columns.

Available actions are intentionally connector-specific. Orbit does not present metadata actions that the selected CLI or database cannot support reliably.

Completion

Binding a connection profile attaches Orbit's native omnifunc to the query buffer. Use <C-x><C-o> in Insert mode for cached schema objects. Completion is clause-aware: it parses the statement around your cursor (not just the current line) with a small dependency-free SQL tokenizer, so suggestions depend on where you are:

  • Tables and views after any FROM-family clause (FROM, JOIN, UPDATE, INTO), and after schema./catalog.schema. qualifiers on connectors that support them (PostgreSQL, Trino).
  • Columns in the SELECT list, WHERE, ON, GROUP BY, ORDER BY, INSERT INTO t (...), and UPDATE t SET ....
  • Table aliases: SELECT u.| FROM users u resolves u to users's columns, including old-style comma joins (FROM a, b). With more than one table in scope, unqualified columns are offered from every table, each annotated with its source alias.
  • The alias/table scope is limited to the statement your cursor is in; other statements in the same buffer (separated by ;) never leak into it. CTEs and derived tables (FROM (SELECT ...) sub) are recognized so they don't break parsing, but don't offer column completion.

Selecting a profile preloads tables and views in the background; expanding it in the Workspace schema browser fills more of the cache. Completion never runs the CLI while you type. SQL keywords and functions, formatting, and highlighting remain the responsibility of your existing SQL tooling.

blink.cmp

Orbit also ships an optional blink.cmp source (orbit.blink) with the same clause-aware suggestions. blink.cmp has no API for a plugin to register itself as a source at runtime, so add it to your own blink.cmp config:

{
"saghen/blink.cmp",
opts= {
sources= {
default= { "lsp", "path", "snippets", "buffer", "orbit" },
providers= {
orbit= { name="orbit", module="orbit.blink" },
},
},
},
}

Set completion = false in Orbit's setup() to disable both the native omnifunc attachment and the blink source.

Execution And Results

Orbit runs statements asynchronously through the selected profile's CLI. For SQLite and PostgreSQL, schema work and statements share one retained connection and execute one at a time; failures notify you and open a diagnostic window, and the next request starts a new connection. Trino statements each run their own trino CLI invocation, still serialized per profile. One running statement is allowed per query buffer; :OrbitCancel terminates the current CLI invocation (and, for SQLite/PostgreSQL, the retained connection) and pending work fails rather than running against an uncertain session.

Potentially mutating statements require confirmation by default. A single SELECT, SHOW, DESCRIBE, EXPLAIN, USE, or VALUES statement runs without confirmation; everything else requires it. This is a convenience guardrail, not a security boundary.

Result grids are reused per tabpage. They show up to result_limit rows and truncate displayed cell text to max_cell_width characters while retaining the raw value for copy and inspection.

Configuration

require("orbit").setup({
completion=true,
confirm_mutations=true,
focus_results=false,
profile_path=vim.fn.expand("~/.local/share/orbit.nvim/profiles.json"),
result_limit=200,
result_height=15,
saved_query_dirs= {
{ Work="~/queries/work" },
{ Personal="~/queries/personal" },
},
max_cell_width=48,
workspace_sidebar_width=32,
workspace_result_ratio=0.30,
winbar=false,
icons= {
collapsed=">",
column="σ° ΅",
expanded="σ°˜–",
folder="󰉋",
index="",
key="",
profile="σ°†Ό",
query="󰆋",
result="󰎟",
saved_query="σ°†Ό",
table="σ°“«",
view="󰈈",
workspace="σ±“ž",
},
})
OptionDefaultDescription
completiontrueEnable clause-aware completion: both the native omnifunc attachment and the optional blink.cmp source's enabled().
confirm_mutationstrueAsk before statements that are not recognised as read-only. A profile can override this with options.confirm_mutations.
focus_resultsfalseFocus a completed standalone result grid instead of keeping focus in the query buffer.
profile_path~/.local/share/orbit.nvim/profiles.jsonLocation of the profile file.
result_limit200Maximum returned rows displayed in the result grid.
result_height15Height of a standalone result grid.
saved_query_dirs{}Ordered named directories of recursively discovered .sql files shown in the Workspace sidebar.
max_cell_width48Maximum displayed width of a result cell.
workspace_sidebar_width32Width of the workspace sidebar.
workspace_result_ratio0.30Fraction of editor height used by workspace results, with a six-line minimum.
winbarfalseShow Orbit status in SQL-window winbars.
keymapsSee aboveConfigurable action mappings.
iconsNerd Font glyphsOverride collapsed, expanded, folder, index, key, profile, query, result, saved_query, table, view, column, and workspace.

For a custom statusline, call require("orbit").status(). It reports the bound profile and shows elapsed time while a statement is running.

About

πŸš€ A database IDE for Neovim. Yes Another One...query, browse schemas, autocomplete tables and columns, and inspect results without leaving your editor.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

πŸš€ Orbit.nvim

A database IDE for Neovim

Your database revolves around your editor, not the other way around.

Orbit runs statements through your existing database CLI, retains one connection per profile where the CLI supports it, keeps profiles per query buffer, browses schemas, completes cached objects, and renders JSON results in a navigable grid.

preview

What It Does

  • Open one dedicated workspace tab with a searchable profile and schema browser.
  • Run a whole statement or a visual selection asynchronously without leaving Neovim.
  • Bind each query buffer to its own connection profile.
  • Browse tables, views, and columns; run connector-specific object actions; create a bound sample statement; copy qualified object names.
  • Inspect and copy raw result values, including structured JSON values.
  • Confirm potentially mutating statements before they run.
  • Complete cached tables, views, columns, and table aliases, clause-aware, with Neovim's built-in omnifunc or an optional blink.cmp source.
  • Browse reusable SQL files from multiple named saved-query locations.

Requirements

  • Neovim 0.10 or later.
  • No required third-party Neovim plugins.
  • The CLI required by each connection profile:
Profile kindCLINotes
trinotrinoOrbit requests JSON output.
sqlitesqlite3Requires a build that supports -json.
postgrespsqlRequires a version that supports --csv.

Installation

With lazy.nvim:

{
"mrpbennett/orbit.nvim",
opts= {},
}

Or call setup from your Neovim configuration:

require("orbit").setup()

Quick Start

  1. Run :OrbitProfiles. This creates ~/.local/share/orbit.nvim/profiles.json with owner-only (0600) permissions and opens it for editing.
  2. Add a connection profile using the format below.
  3. Open :OrbitWorkspace or a SQL buffer.
  4. Bind a profile with :OrbitProfile, or press <CR> on a profile in the workspace.
  5. Run :OrbitExecute, or use <leader>E in Normal or Visual mode in a SQL buffer.

If a query buffer has no profile, executing it opens profile selection and retries after you choose one.

Supported Connectors

KindRequired optionsOptional optionsSchema support
trinoserver, user, catalogschema, schema_patterns, executable, arguments, confirm_mutationsTables, views, and columns from information_schema. Omitting schema browses the catalog except information_schema.
sqlitepathschema_patterns, executable, arguments, confirm_mutationsTables and views from sqlite_master, plus columns from PRAGMA table_info, under main.
postgresdatabaseschema_patterns, host, port, user, password, sslmode, executable, arguments, confirm_mutationsTables and views outside PostgreSQL system schemas, plus columns, primary keys, foreign keys, and indexes.

executable replaces the CLI binary and arguments adds an array of string arguments before Orbit's generated arguments. This is useful for wrappers or CLI-specific authentication flags. For SQLite and PostgreSQL, Orbit retains one interactive CLI connection per profile; statements, schema browsing, and completion prewarming share it and are serialized per profile. A changed profile definition, failed CLI, :OrbitDisconnect, or Neovim exit closes the connection; the next request reconnects automatically. Trino statements instead run one trino CLI invocation per statement, serialized per profile, because the trino CLI does not flush its output while held open on a retained connection.

Schema browsing and completion cache rows only while the connection profile's kind and options are unchanged. Updating a profile clears its prior schema rows before Orbit acquires replacements. Connector metadata that is unavailable for an object, such as Trino primary keys, is shown as unavailable rather than treated as a statement failure. Explicit Workspace refreshes run after pending acquisitions and coalesce with other refresh requests.

schema_patterns restricts the tables and views shown by Orbit's Workspace schema browser, but does not change database permissions or restrict statements you run manually. For Trino, it maps each catalog to an array of exact schema names; use an empty array to include every non-system schema from that catalog. PostgreSQL and SQLite use a non-empty array of exact schema names instead. SQLite's only available schema is main.

Connection Profiles

The profile file is the source of truth for named connection profiles. Its default location is ~/.local/share/orbit.nvim/profiles.json; set profile_path in setup() to use another location. Orbit refuses to load a file that is not mode 0600.

Profiles are JSON, versioned at 1, and names must be unique:

PostgreSQL
{
"version": 1,
"profiles": [
{
"name": "app-db",
"kind": "postgres",
"options": {
"database": "postgres",
"host": "postgres.example.com",
"port": 5432,
"user": "postr",
"password": "somePassword",
"sslmode": "require"
}
}
]
}
SQLite
{
"version": 1,
"profiles": [
{
"name": "local",
"kind": "sqlite",
"options": {
"path": "/home/projects/data.db"
}
}
]
}
Trino
{
"version": 1,
"profiles": [
{
"name": "analytics",
"kind": "trino",
"arguments": ["--password"]
"options": {
"server": "https://trino.example.com:8443",
"user": "alice",
"catalog": "hive",
"schema": "analytics",
"schema_patterns": {
"hive": ["analytics", "reporting"],
"iceberg": []
// add more catalogs as needed...// see Trino Multi-Catalog Schema Browser
},
}
}
]
}

Trino Multi-Catalog Schema Browser

Trino profiles still require catalog as the CLI's default catalog, but schema_patterns can browse schemas from multiple catalogs. Orbit retains each object's catalog for column inspection, copied names, and generated sample statements:

{
"catalog": "gridhive",
"schema_patterns": {
"catalog_1": ["data_v2"],
"catalog_2": ["aggr", "cleanroom", "report"],
"iceberg": ["cleanroom"],
"sqlserver_rep": ["dbo"]
}
}

An empty array, such as "catalog_1": [], includes every non-system schema from that catalog. Omit a catalog entirely to hide it.

Authentication

PostgreSQL profiles may include options.password. Orbit passes it only to psql as PGPASSWORD, never as a command-line argument. The profile file is owner-protected (0600), but a password remains sensitive; use your system's credential management or a ~/.pgpass file if you prefer not to store it in JSON.

Configure Trino authentication exactly as you do for the Trino CLI, including its --password flag, environment variables, tokens, keyrings, or credential providers it uses.

Orbit passes profile values to the CLI as literal arguments. It does not expand $VAR or ${VAR} inside JSON. Other Trino CLI authentication mechanisms, such as tokens or external credential providers, continue to work through their normal CLI configuration.

Note

Connection profiles can contain sensitive settings, including PostgreSQL passwords. Orbit requires the profile file to be mode 0600; do not copy it into a repository or share it.

Workspace Workflow

:OrbitWorkspace opens a dedicated Orbit tabpage with a profile/schema browser and a normal SQL editing window. Run it again to toggle that browser. :OrbitWorkspaceClose closes only that tabpage.

  1. Press <CR> on a profile to select it and bind it to the active query buffer.
  2. Optionally press l to load its schema for browsing and completion.
  3. Press n to open a new SQL buffer already bound to the selected profile.
  4. Execute a statement. Results appear in the reusable bottom result grid.

Set saved_query_dirs to add ordered, named recursive trees of .sql files to the sidebar:

saved_query_dirs= {
{ Work="~/queries/work" },
{ Personal="~/queries/personal" },
}

Each entry must contain one unique display name and directory. Orbit preserves the configured order, expands paths such as ~, and shows each location as a separate top-level tree collapsed by default. Select a profile, then press <CR> on a saved query to open it in the Workspace query window bound to that profile; loading the schema is not required. Press r on any saved-query directory to rescan only its top-level location.

From a workspace query buffer, / focuses the workspace filter. Elsewhere, / retains normal Neovim search behavior.

Commands

CommandDescription
:OrbitProfilesCreate, protect, and edit the profile file.
:OrbitProfileSearch profiles and bind one to the current query buffer.
:OrbitSelectProfileAlias for :OrbitProfile.
:OrbitExecuteExecute the single unambiguous statement in the current buffer.
:'<,'>OrbitExecuteExecute the selected line range.
:OrbitCancelCancel the statement running in the current buffer.
:OrbitDisconnectClose the connection for the current buffer's profile.
:OrbitWorkspaceOpen the workspace or toggle its profile/schema browser.
:OrbitWorkspaceCloseClose the Orbit workspace tabpage.

Whole-buffer execution rejects ambiguous multi-statement content. Select the exact statement in Visual mode, then run :OrbitExecute or <leader>E.

Keybindings

Configurable Mappings

Orbit installs the following defaults:

Mode and scopeMappingAction
Normal, global<leader>DOpen the workspace or toggle its profile/schema browser.
Normal, SQL buffer<leader>EExecute the buffer statement.
Visual, SQL buffer<leader>EExecute the visual selection.
Normal, SQL buffer<leader>PSelect a connection profile.
Normal, SQL buffer<leader>XCancel the running statement.

Configure action mappings through keymaps. execute, browse, cancel, and select_profile are buffer-local in SQL buffers; workspace is global. Set an action to false to disable its default mapping.

require("orbit").setup({
keymaps= {
execute="<leader>E",
workspace="<leader>D",
select_profile="<leader>P",
cancel="<leader>X",
},
})

Workspace Sidebar

KeyAction
lExpand the selected profile, schema, object group, table metadata folder, or object.
hCollapse the selected node.
<CR>Select and bind a profile to the current query buffer, or open a saved query bound to the selected profile.
nCreate a query buffer bound to the selected profile.
sOpen a bound sample statement for the selected table or view.
aSelect a connector-supported action for the selected table or view.
yCopy the qualified selected table or view name.
PPreview the selected saved query without opening or binding it.
/Filter profiles, schema objects, and saved queries.
rReload the profile file and refresh the selected profile schema, or rescan saved queries.
ZCollapse the open profile schema tree.
?Show help.
qClose the workspace.

Expanding a table reveals its available metadata folders. SQLite provides columns, primary keys, foreign keys, and indexes; each folder loads on demand. Views remain under the schema's views group and expose their columns.

Result Grid

KeyAction
h, j, k, lMove between cells.
<CR>Inspect the raw value in a floating window.
yCopy the raw selected value.
qClose the standalone grid, or return to the query editor in a workspace.

Workspace sample statements for PostgreSQL and SQLite base tables become editable when Orbit can load a primary key. Ad-hoc statements, views, Trino, and tables without a primary key remain read-only.

Key / commandAction
o, OInsert a local row below or above the current row.
i, <CR>Enter Insert mode in the focused cell; press Esc to keep the local edit.
ddMark the current row for local deletion.
V, j / k, dSelect complete rows and delete the selection.
uUndo the most recent local edit.
:wConfirm, transactionally save, and reload pending changes.
:wqSave successfully, then close the Result grid.
:q!Discard local changes and close.
:e!Discard local changes and reload the table.

Edits are never sent to the database until :w. A failed write leaves the local Result grid unchanged. Type NULL as the complete cell value to write a SQL NULL value.

Normal Neovim scrolling remains available, including <C-d>, <C-u>, zh, and zl.

Schema Object Actions

Press a on a table or view in the Workspace schema browser to select an action supplied by its connection profile kind. Actions that inspect metadata open in the Result grid; sample actions create a bound query buffer instead.

  • SQLite: sample statement, columns, primary keys, indexes, foreign keys, and object definition.
  • PostgreSQL: sample statement, columns, primary keys, indexes, foreign keys, and view definition.
  • Trino: sample statement and columns.

Available actions are intentionally connector-specific. Orbit does not present metadata actions that the selected CLI or database cannot support reliably.

Completion

Binding a connection profile attaches Orbit's native omnifunc to the query buffer. Use <C-x><C-o> in Insert mode for cached schema objects. Completion is clause-aware: it parses the statement around your cursor (not just the current line) with a small dependency-free SQL tokenizer, so suggestions depend on where you are:

  • Tables and views after any FROM-family clause (FROM, JOIN, UPDATE, INTO), and after schema./catalog.schema. qualifiers on connectors that support them (PostgreSQL, Trino).
  • Columns in the SELECT list, WHERE, ON, GROUP BY, ORDER BY, INSERT INTO t (...), and UPDATE t SET ....
  • Table aliases: SELECT u.| FROM users u resolves u to users's columns, including old-style comma joins (FROM a, b). With more than one table in scope, unqualified columns are offered from every table, each annotated with its source alias.
  • The alias/table scope is limited to the statement your cursor is in; other statements in the same buffer (separated by ;) never leak into it. CTEs and derived tables (FROM (SELECT ...) sub) are recognized so they don't break parsing, but don't offer column completion.

Selecting a profile preloads tables and views in the background; expanding it in the Workspace schema browser fills more of the cache. Completion never runs the CLI while you type. SQL keywords and functions, formatting, and highlighting remain the responsibility of your existing SQL tooling.

blink.cmp

Orbit also ships an optional blink.cmp source (orbit.blink) with the same clause-aware suggestions. blink.cmp has no API for a plugin to register itself as a source at runtime, so add it to your own blink.cmp config:

{
"saghen/blink.cmp",
opts= {
sources= {
default= { "lsp", "path", "snippets", "buffer", "orbit" },
providers= {
orbit= { name="orbit", module="orbit.blink" },
},
},
},
}

Set completion = false in Orbit's setup() to disable both the native omnifunc attachment and the blink source.

Execution And Results

Orbit runs statements asynchronously through the selected profile's CLI. For SQLite and PostgreSQL, schema work and statements share one retained connection and execute one at a time; failures notify you and open a diagnostic window, and the next request starts a new connection. Trino statements each run their own trino CLI invocation, still serialized per profile. One running statement is allowed per query buffer; :OrbitCancel terminates the current CLI invocation (and, for SQLite/PostgreSQL, the retained connection) and pending work fails rather than running against an uncertain session.

Potentially mutating statements require confirmation by default. A single SELECT, SHOW, DESCRIBE, EXPLAIN, USE, or VALUES statement runs without confirmation; everything else requires it. This is a convenience guardrail, not a security boundary.

Result grids are reused per tabpage. They show up to result_limit rows and truncate displayed cell text to max_cell_width characters while retaining the raw value for copy and inspection.

Configuration

require("orbit").setup({
completion=true,
confirm_mutations=true,
focus_results=false,
profile_path=vim.fn.expand("~/.local/share/orbit.nvim/profiles.json"),
result_limit=200,
result_height=15,
saved_query_dirs= {
{ Work="~/queries/work" },
{ Personal="~/queries/personal" },
},
max_cell_width=48,
workspace_sidebar_width=32,
workspace_result_ratio=0.30,
winbar=false,
icons= {
collapsed=">",
column="σ° ΅",
expanded="σ°˜–",
folder="󰉋",
index="",
key="",
profile="σ°†Ό",
query="󰆋",
result="󰎟",
saved_query="σ°†Ό",
table="σ°“«",
view="󰈈",
workspace="σ±“ž",
},
})
OptionDefaultDescription
completiontrueEnable clause-aware completion: both the native omnifunc attachment and the optional blink.cmp source's enabled().
confirm_mutationstrueAsk before statements that are not recognised as read-only. A profile can override this with options.confirm_mutations.
focus_resultsfalseFocus a completed standalone result grid instead of keeping focus in the query buffer.
profile_path~/.local/share/orbit.nvim/profiles.jsonLocation of the profile file.
result_limit200Maximum returned rows displayed in the result grid.
result_height15Height of a standalone result grid.
saved_query_dirs{}Ordered named directories of recursively discovered .sql files shown in the Workspace sidebar.
max_cell_width48Maximum displayed width of a result cell.
workspace_sidebar_width32Width of the workspace sidebar.
workspace_result_ratio0.30Fraction of editor height used by workspace results, with a six-line minimum.
winbarfalseShow Orbit status in SQL-window winbars.
keymapsSee aboveConfigurable action mappings.
iconsNerd Font glyphsOverride collapsed, expanded, folder, index, key, profile, query, result, saved_query, table, view, column, and workspace.

For a custom statusline, call require("orbit").status(). It reports the bound profile and shows elapsed time while a statement is running.

About

πŸš€ A database IDE for Neovim. Yes Another One...query, browse schemas, autocomplete tables and columns, and inspect results without leaving your editor.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

πŸš€ Orbit.nvim

A database IDE for Neovim

Your database revolves around your editor, not the other way around.

Orbit runs statements through your existing database CLI, retains one connection per profile where the CLI supports it, keeps profiles per query buffer, browses schemas, completes cached objects, and renders JSON results in a navigable grid.

preview

What It Does

  • Open one dedicated workspace tab with a searchable profile and schema browser.
  • Run a whole statement or a visual selection asynchronously without leaving Neovim.
  • Bind each query buffer to its own connection profile.
  • Browse tables, views, and columns; run connector-specific object actions; create a bound sample statement; copy qualified object names.
  • Inspect and copy raw result values, including structured JSON values.
  • Confirm potentially mutating statements before they run.
  • Complete cached tables, views, columns, and table aliases, clause-aware, with Neovim's built-in omnifunc or an optional blink.cmp source.
  • Browse reusable SQL files from multiple named saved-query locations.

Requirements

  • Neovim 0.10 or later.
  • No required third-party Neovim plugins.
  • The CLI required by each connection profile:
Profile kindCLINotes
trinotrinoOrbit requests JSON output.
sqlitesqlite3Requires a build that supports -json.
postgrespsqlRequires a version that supports --csv.

Installation

With lazy.nvim:

{
"mrpbennett/orbit.nvim",
opts= {},
}

Or call setup from your Neovim configuration:

require("orbit").setup()

Quick Start

  1. Run :OrbitProfiles. This creates ~/.local/share/orbit.nvim/profiles.json with owner-only (0600) permissions and opens it for editing.
  2. Add a connection profile using the format below.
  3. Open :OrbitWorkspace or a SQL buffer.
  4. Bind a profile with :OrbitProfile, or press <CR> on a profile in the workspace.
  5. Run :OrbitExecute, or use <leader>E in Normal or Visual mode in a SQL buffer.

If a query buffer has no profile, executing it opens profile selection and retries after you choose one.

Supported Connectors

KindRequired optionsOptional optionsSchema support
trinoserver, user, catalogschema, schema_patterns, executable, arguments, confirm_mutationsTables, views, and columns from information_schema. Omitting schema browses the catalog except information_schema.
sqlitepathschema_patterns, executable, arguments, confirm_mutationsTables and views from sqlite_master, plus columns from PRAGMA table_info, under main.
postgresdatabaseschema_patterns, host, port, user, password, sslmode, executable, arguments, confirm_mutationsTables and views outside PostgreSQL system schemas, plus columns, primary keys, foreign keys, and indexes.

executable replaces the CLI binary and arguments adds an array of string arguments before Orbit's generated arguments. This is useful for wrappers or CLI-specific authentication flags. For SQLite and PostgreSQL, Orbit retains one interactive CLI connection per profile; statements, schema browsing, and completion prewarming share it and are serialized per profile. A changed profile definition, failed CLI, :OrbitDisconnect, or Neovim exit closes the connection; the next request reconnects automatically. Trino statements instead run one trino CLI invocation per statement, serialized per profile, because the trino CLI does not flush its output while held open on a retained connection.

Schema browsing and completion cache rows only while the connection profile's kind and options are unchanged. Updating a profile clears its prior schema rows before Orbit acquires replacements. Connector metadata that is unavailable for an object, such as Trino primary keys, is shown as unavailable rather than treated as a statement failure. Explicit Workspace refreshes run after pending acquisitions and coalesce with other refresh requests.

schema_patterns restricts the tables and views shown by Orbit's Workspace schema browser, but does not change database permissions or restrict statements you run manually. For Trino, it maps each catalog to an array of exact schema names; use an empty array to include every non-system schema from that catalog. PostgreSQL and SQLite use a non-empty array of exact schema names instead. SQLite's only available schema is main.

Connection Profiles

The profile file is the source of truth for named connection profiles. Its default location is ~/.local/share/orbit.nvim/profiles.json; set profile_path in setup() to use another location. Orbit refuses to load a file that is not mode 0600.

Profiles are JSON, versioned at 1, and names must be unique:

PostgreSQL
{
"version": 1,
"profiles": [
{
"name": "app-db",
"kind": "postgres",
"options": {
"database": "postgres",
"host": "postgres.example.com",
"port": 5432,
"user": "postr",
"password": "somePassword",
"sslmode": "require"
}
}
]
}
SQLite
{
"version": 1,
"profiles": [
{
"name": "local",
"kind": "sqlite",
"options": {
"path": "/home/projects/data.db"
}
}
]
}
Trino
{
"version": 1,
"profiles": [
{
"name": "analytics",
"kind": "trino",
"arguments": ["--password"]
"options": {
"server": "https://trino.example.com:8443",
"user": "alice",
"catalog": "hive",
"schema": "analytics",
"schema_patterns": {
"hive": ["analytics", "reporting"],
"iceberg": []
// add more catalogs as needed...// see Trino Multi-Catalog Schema Browser
},
}
}
]
}

Trino Multi-Catalog Schema Browser

Trino profiles still require catalog as the CLI's default catalog, but schema_patterns can browse schemas from multiple catalogs. Orbit retains each object's catalog for column inspection, copied names, and generated sample statements:

{
"catalog": "gridhive",
"schema_patterns": {
"catalog_1": ["data_v2"],
"catalog_2": ["aggr", "cleanroom", "report"],
"iceberg": ["cleanroom"],
"sqlserver_rep": ["dbo"]
}
}

An empty array, such as "catalog_1": [], includes every non-system schema from that catalog. Omit a catalog entirely to hide it.

Authentication

PostgreSQL profiles may include options.password. Orbit passes it only to psql as PGPASSWORD, never as a command-line argument. The profile file is owner-protected (0600), but a password remains sensitive; use your system's credential management or a ~/.pgpass file if you prefer not to store it in JSON.

Configure Trino authentication exactly as you do for the Trino CLI, including its --password flag, environment variables, tokens, keyrings, or credential providers it uses.

Orbit passes profile values to the CLI as literal arguments. It does not expand $VAR or ${VAR} inside JSON. Other Trino CLI authentication mechanisms, such as tokens or external credential providers, continue to work through their normal CLI configuration.

Note

Connection profiles can contain sensitive settings, including PostgreSQL passwords. Orbit requires the profile file to be mode 0600; do not copy it into a repository or share it.

Workspace Workflow

:OrbitWorkspace opens a dedicated Orbit tabpage with a profile/schema browser and a normal SQL editing window. Run it again to toggle that browser. :OrbitWorkspaceClose closes only that tabpage.

  1. Press <CR> on a profile to select it and bind it to the active query buffer.
  2. Optionally press l to load its schema for browsing and completion.
  3. Press n to open a new SQL buffer already bound to the selected profile.
  4. Execute a statement. Results appear in the reusable bottom result grid.

Set saved_query_dirs to add ordered, named recursive trees of .sql files to the sidebar:

saved_query_dirs= {
{ Work="~/queries/work" },
{ Personal="~/queries/personal" },
}

Each entry must contain one unique display name and directory. Orbit preserves the configured order, expands paths such as ~, and shows each location as a separate top-level tree collapsed by default. Select a profile, then press <CR> on a saved query to open it in the Workspace query window bound to that profile; loading the schema is not required. Press r on any saved-query directory to rescan only its top-level location.

From a workspace query buffer, / focuses the workspace filter. Elsewhere, / retains normal Neovim search behavior.

Commands

CommandDescription
:OrbitProfilesCreate, protect, and edit the profile file.
:OrbitProfileSearch profiles and bind one to the current query buffer.
:OrbitSelectProfileAlias for :OrbitProfile.
:OrbitExecuteExecute the single unambiguous statement in the current buffer.
:'<,'>OrbitExecuteExecute the selected line range.
:OrbitCancelCancel the statement running in the current buffer.
:OrbitDisconnectClose the connection for the current buffer's profile.
:OrbitWorkspaceOpen the workspace or toggle its profile/schema browser.
:OrbitWorkspaceCloseClose the Orbit workspace tabpage.

Whole-buffer execution rejects ambiguous multi-statement content. Select the exact statement in Visual mode, then run :OrbitExecute or <leader>E.

Keybindings

Configurable Mappings

Orbit installs the following defaults:

Mode and scopeMappingAction
Normal, global<leader>DOpen the workspace or toggle its profile/schema browser.
Normal, SQL buffer<leader>EExecute the buffer statement.
Visual, SQL buffer<leader>EExecute the visual selection.
Normal, SQL buffer<leader>PSelect a connection profile.
Normal, SQL buffer<leader>XCancel the running statement.

Configure action mappings through keymaps. execute, browse, cancel, and select_profile are buffer-local in SQL buffers; workspace is global. Set an action to false to disable its default mapping.

require("orbit").setup({
keymaps= {
execute="<leader>E",
workspace="<leader>D",
select_profile="<leader>P",
cancel="<leader>X",
},
})

Workspace Sidebar

KeyAction
lExpand the selected profile, schema, object group, table metadata folder, or object.
hCollapse the selected node.
<CR>Select and bind a profile to the current query buffer, or open a saved query bound to the selected profile.
nCreate a query buffer bound to the selected profile.
sOpen a bound sample statement for the selected table or view.
aSelect a connector-supported action for the selected table or view.
yCopy the qualified selected table or view name.
PPreview the selected saved query without opening or binding it.
/Filter profiles, schema objects, and saved queries.
rReload the profile file and refresh the selected profile schema, or rescan saved queries.
ZCollapse the open profile schema tree.
?Show help.
qClose the workspace.

Expanding a table reveals its available metadata folders. SQLite provides columns, primary keys, foreign keys, and indexes; each folder loads on demand. Views remain under the schema's views group and expose their columns.

Result Grid

KeyAction
h, j, k, lMove between cells.
<CR>Inspect the raw value in a floating window.
yCopy the raw selected value.
qClose the standalone grid, or return to the query editor in a workspace.

Workspace sample statements for PostgreSQL and SQLite base tables become editable when Orbit can load a primary key. Ad-hoc statements, views, Trino, and tables without a primary key remain read-only.

Key / commandAction
o, OInsert a local row below or above the current row.
i, <CR>Enter Insert mode in the focused cell; press Esc to keep the local edit.
ddMark the current row for local deletion.
V, j / k, dSelect complete rows and delete the selection.
uUndo the most recent local edit.
:wConfirm, transactionally save, and reload pending changes.
:wqSave successfully, then close the Result grid.
:q!Discard local changes and close.
:e!Discard local changes and reload the table.

Edits are never sent to the database until :w. A failed write leaves the local Result grid unchanged. Type NULL as the complete cell value to write a SQL NULL value.

Normal Neovim scrolling remains available, including <C-d>, <C-u>, zh, and zl.

Schema Object Actions

Press a on a table or view in the Workspace schema browser to select an action supplied by its connection profile kind. Actions that inspect metadata open in the Result grid; sample actions create a bound query buffer instead.

  • SQLite: sample statement, columns, primary keys, indexes, foreign keys, and object definition.
  • PostgreSQL: sample statement, columns, primary keys, indexes, foreign keys, and view definition.
  • Trino: sample statement and columns.

Available actions are intentionally connector-specific. Orbit does not present metadata actions that the selected CLI or database cannot support reliably.

Completion

Binding a connection profile attaches Orbit's native omnifunc to the query buffer. Use <C-x><C-o> in Insert mode for cached schema objects. Completion is clause-aware: it parses the statement around your cursor (not just the current line) with a small dependency-free SQL tokenizer, so suggestions depend on where you are:

  • Tables and views after any FROM-family clause (FROM, JOIN, UPDATE, INTO), and after schema./catalog.schema. qualifiers on connectors that support them (PostgreSQL, Trino).
  • Columns in the SELECT list, WHERE, ON, GROUP BY, ORDER BY, INSERT INTO t (...), and UPDATE t SET ....
  • Table aliases: SELECT u.| FROM users u resolves u to users's columns, including old-style comma joins (FROM a, b). With more than one table in scope, unqualified columns are offered from every table, each annotated with its source alias.
  • The alias/table scope is limited to the statement your cursor is in; other statements in the same buffer (separated by ;) never leak into it. CTEs and derived tables (FROM (SELECT ...) sub) are recognized so they don't break parsing, but don't offer column completion.

Selecting a profile preloads tables and views in the background; expanding it in the Workspace schema browser fills more of the cache. Completion never runs the CLI while you type. SQL keywords and functions, formatting, and highlighting remain the responsibility of your existing SQL tooling.

blink.cmp

Orbit also ships an optional blink.cmp source (orbit.blink) with the same clause-aware suggestions. blink.cmp has no API for a plugin to register itself as a source at runtime, so add it to your own blink.cmp config:

{
"saghen/blink.cmp",
opts= {
sources= {
default= { "lsp", "path", "snippets", "buffer", "orbit" },
providers= {
orbit= { name="orbit", module="orbit.blink" },
},
},
},
}

Set completion = false in Orbit's setup() to disable both the native omnifunc attachment and the blink source.

Execution And Results

Orbit runs statements asynchronously through the selected profile's CLI. For SQLite and PostgreSQL, schema work and statements share one retained connection and execute one at a time; failures notify you and open a diagnostic window, and the next request starts a new connection. Trino statements each run their own trino CLI invocation, still serialized per profile. One running statement is allowed per query buffer; :OrbitCancel terminates the current CLI invocation (and, for SQLite/PostgreSQL, the retained connection) and pending work fails rather than running against an uncertain session.

Potentially mutating statements require confirmation by default. A single SELECT, SHOW, DESCRIBE, EXPLAIN, USE, or VALUES statement runs without confirmation; everything else requires it. This is a convenience guardrail, not a security boundary.

Result grids are reused per tabpage. They show up to result_limit rows and truncate displayed cell text to max_cell_width characters while retaining the raw value for copy and inspection.

Configuration

require("orbit").setup({
completion=true,
confirm_mutations=true,
focus_results=false,
profile_path=vim.fn.expand("~/.local/share/orbit.nvim/profiles.json"),
result_limit=200,
result_height=15,
saved_query_dirs= {
{ Work="~/queries/work" },
{ Personal="~/queries/personal" },
},
max_cell_width=48,
workspace_sidebar_width=32,
workspace_result_ratio=0.30,
winbar=false,
icons= {
collapsed=">",
column="σ° ΅",
expanded="σ°˜–",
folder="󰉋",
index="",
key="",
profile="σ°†Ό",
query="󰆋",
result="󰎟",
saved_query="σ°†Ό",
table="σ°“«",
view="󰈈",
workspace="σ±“ž",
},
})
OptionDefaultDescription
completiontrueEnable clause-aware completion: both the native omnifunc attachment and the optional blink.cmp source's enabled().
confirm_mutationstrueAsk before statements that are not recognised as read-only. A profile can override this with options.confirm_mutations.
focus_resultsfalseFocus a completed standalone result grid instead of keeping focus in the query buffer.
profile_path~/.local/share/orbit.nvim/profiles.jsonLocation of the profile file.
result_limit200Maximum returned rows displayed in the result grid.
result_height15Height of a standalone result grid.
saved_query_dirs{}Ordered named directories of recursively discovered .sql files shown in the Workspace sidebar.
max_cell_width48Maximum displayed width of a result cell.
workspace_sidebar_width32Width of the workspace sidebar.
workspace_result_ratio0.30Fraction of editor height used by workspace results, with a six-line minimum.
winbarfalseShow Orbit status in SQL-window winbars.
keymapsSee aboveConfigurable action mappings.
iconsNerd Font glyphsOverride collapsed, expanded, folder, index, key, profile, query, result, saved_query, table, view, column, and workspace.

For a custom statusline, call require("orbit").status(). It reports the bound profile and shows elapsed time while a statement is running.

About

πŸš€ A database IDE for Neovim. Yes Another One...query, browse schemas, autocomplete tables and columns, and inspect results without leaving your editor.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

πŸš€ Orbit.nvim

A database IDE for Neovim

Your database revolves around your editor, not the other way around.

Orbit runs statements through your existing database CLI, retains one connection per profile where the CLI supports it, keeps profiles per query buffer, browses schemas, completes cached objects, and renders JSON results in a navigable grid.

preview

What It Does

  • Open one dedicated workspace tab with a searchable profile and schema browser.
  • Run a whole statement or a visual selection asynchronously without leaving Neovim.
  • Bind each query buffer to its own connection profile.
  • Browse tables, views, and columns; run connector-specific object actions; create a bound sample statement; copy qualified object names.
  • Inspect and copy raw result values, including structured JSON values.
  • Confirm potentially mutating statements before they run.
  • Complete cached tables, views, columns, and table aliases, clause-aware, with Neovim's built-in omnifunc or an optional blink.cmp source.
  • Browse reusable SQL files from multiple named saved-query locations.

Requirements

  • Neovim 0.10 or later.
  • No required third-party Neovim plugins.
  • The CLI required by each connection profile:
Profile kindCLINotes
trinotrinoOrbit requests JSON output.
sqlitesqlite3Requires a build that supports -json.
postgrespsqlRequires a version that supports --csv.

Installation

With lazy.nvim:

{
"mrpbennett/orbit.nvim",
opts= {},
}

Or call setup from your Neovim configuration:

require("orbit").setup()

Quick Start

  1. Run :OrbitProfiles. This creates ~/.local/share/orbit.nvim/profiles.json with owner-only (0600) permissions and opens it for editing.
  2. Add a connection profile using the format below.
  3. Open :OrbitWorkspace or a SQL buffer.
  4. Bind a profile with :OrbitProfile, or press <CR> on a profile in the workspace.
  5. Run :OrbitExecute, or use <leader>E in Normal or Visual mode in a SQL buffer.

If a query buffer has no profile, executing it opens profile selection and retries after you choose one.

Supported Connectors

KindRequired optionsOptional optionsSchema support
trinoserver, user, catalogschema, schema_patterns, executable, arguments, confirm_mutationsTables, views, and columns from information_schema. Omitting schema browses the catalog except information_schema.
sqlitepathschema_patterns, executable, arguments, confirm_mutationsTables and views from sqlite_master, plus columns from PRAGMA table_info, under main.
postgresdatabaseschema_patterns, host, port, user, password, sslmode, executable, arguments, confirm_mutationsTables and views outside PostgreSQL system schemas, plus columns, primary keys, foreign keys, and indexes.

executable replaces the CLI binary and arguments adds an array of string arguments before Orbit's generated arguments. This is useful for wrappers or CLI-specific authentication flags. For SQLite and PostgreSQL, Orbit retains one interactive CLI connection per profile; statements, schema browsing, and completion prewarming share it and are serialized per profile. A changed profile definition, failed CLI, :OrbitDisconnect, or Neovim exit closes the connection; the next request reconnects automatically. Trino statements instead run one trino CLI invocation per statement, serialized per profile, because the trino CLI does not flush its output while held open on a retained connection.

Schema browsing and completion cache rows only while the connection profile's kind and options are unchanged. Updating a profile clears its prior schema rows before Orbit acquires replacements. Connector metadata that is unavailable for an object, such as Trino primary keys, is shown as unavailable rather than treated as a statement failure. Explicit Workspace refreshes run after pending acquisitions and coalesce with other refresh requests.

schema_patterns restricts the tables and views shown by Orbit's Workspace schema browser, but does not change database permissions or restrict statements you run manually. For Trino, it maps each catalog to an array of exact schema names; use an empty array to include every non-system schema from that catalog. PostgreSQL and SQLite use a non-empty array of exact schema names instead. SQLite's only available schema is main.

Connection Profiles

The profile file is the source of truth for named connection profiles. Its default location is ~/.local/share/orbit.nvim/profiles.json; set profile_path in setup() to use another location. Orbit refuses to load a file that is not mode 0600.

Profiles are JSON, versioned at 1, and names must be unique:

PostgreSQL
{
"version": 1,
"profiles": [
{
"name": "app-db",
"kind": "postgres",
"options": {
"database": "postgres",
"host": "postgres.example.com",
"port": 5432,
"user": "postr",
"password": "somePassword",
"sslmode": "require"
}
}
]
}
SQLite
{
"version": 1,
"profiles": [
{
"name": "local",
"kind": "sqlite",
"options": {
"path": "/home/projects/data.db"
}
}
]
}
Trino
{
"version": 1,
"profiles": [
{
"name": "analytics",
"kind": "trino",
"arguments": ["--password"]
"options": {
"server": "https://trino.example.com:8443",
"user": "alice",
"catalog": "hive",
"schema": "analytics",
"schema_patterns": {
"hive": ["analytics", "reporting"],
"iceberg": []
// add more catalogs as needed...// see Trino Multi-Catalog Schema Browser
},
}
}
]
}

Trino Multi-Catalog Schema Browser

Trino profiles still require catalog as the CLI's default catalog, but schema_patterns can browse schemas from multiple catalogs. Orbit retains each object's catalog for column inspection, copied names, and generated sample statements:

{
"catalog": "gridhive",
"schema_patterns": {
"catalog_1": ["data_v2"],
"catalog_2": ["aggr", "cleanroom", "report"],
"iceberg": ["cleanroom"],
"sqlserver_rep": ["dbo"]
}
}

An empty array, such as "catalog_1": [], includes every non-system schema from that catalog. Omit a catalog entirely to hide it.

Authentication

PostgreSQL profiles may include options.password. Orbit passes it only to psql as PGPASSWORD, never as a command-line argument. The profile file is owner-protected (0600), but a password remains sensitive; use your system's credential management or a ~/.pgpass file if you prefer not to store it in JSON.

Configure Trino authentication exactly as you do for the Trino CLI, including its --password flag, environment variables, tokens, keyrings, or credential providers it uses.

Orbit passes profile values to the CLI as literal arguments. It does not expand $VAR or ${VAR} inside JSON. Other Trino CLI authentication mechanisms, such as tokens or external credential providers, continue to work through their normal CLI configuration.

Note

Connection profiles can contain sensitive settings, including PostgreSQL passwords. Orbit requires the profile file to be mode 0600; do not copy it into a repository or share it.

Workspace Workflow

:OrbitWorkspace opens a dedicated Orbit tabpage with a profile/schema browser and a normal SQL editing window. Run it again to toggle that browser. :OrbitWorkspaceClose closes only that tabpage.

  1. Press <CR> on a profile to select it and bind it to the active query buffer.
  2. Optionally press l to load its schema for browsing and completion.
  3. Press n to open a new SQL buffer already bound to the selected profile.
  4. Execute a statement. Results appear in the reusable bottom result grid.

Set saved_query_dirs to add ordered, named recursive trees of .sql files to the sidebar:

saved_query_dirs= {
{ Work="~/queries/work" },
{ Personal="~/queries/personal" },
}

Each entry must contain one unique display name and directory. Orbit preserves the configured order, expands paths such as ~, and shows each location as a separate top-level tree collapsed by default. Select a profile, then press <CR> on a saved query to open it in the Workspace query window bound to that profile; loading the schema is not required. Press r on any saved-query directory to rescan only its top-level location.

From a workspace query buffer, / focuses the workspace filter. Elsewhere, / retains normal Neovim search behavior.

Commands

CommandDescription
:OrbitProfilesCreate, protect, and edit the profile file.
:OrbitProfileSearch profiles and bind one to the current query buffer.
:OrbitSelectProfileAlias for :OrbitProfile.
:OrbitExecuteExecute the single unambiguous statement in the current buffer.
:'<,'>OrbitExecuteExecute the selected line range.
:OrbitCancelCancel the statement running in the current buffer.
:OrbitDisconnectClose the connection for the current buffer's profile.
:OrbitWorkspaceOpen the workspace or toggle its profile/schema browser.
:OrbitWorkspaceCloseClose the Orbit workspace tabpage.

Whole-buffer execution rejects ambiguous multi-statement content. Select the exact statement in Visual mode, then run :OrbitExecute or <leader>E.

Keybindings

Configurable Mappings

Orbit installs the following defaults:

Mode and scopeMappingAction
Normal, global<leader>DOpen the workspace or toggle its profile/schema browser.
Normal, SQL buffer<leader>EExecute the buffer statement.
Visual, SQL buffer<leader>EExecute the visual selection.
Normal, SQL buffer<leader>PSelect a connection profile.
Normal, SQL buffer<leader>XCancel the running statement.

Configure action mappings through keymaps. execute, browse, cancel, and select_profile are buffer-local in SQL buffers; workspace is global. Set an action to false to disable its default mapping.

require("orbit").setup({
keymaps= {
execute="<leader>E",
workspace="<leader>D",
select_profile="<leader>P",
cancel="<leader>X",
},
})

Workspace Sidebar

KeyAction
lExpand the selected profile, schema, object group, table metadata folder, or object.
hCollapse the selected node.
<CR>Select and bind a profile to the current query buffer, or open a saved query bound to the selected profile.
nCreate a query buffer bound to the selected profile.
sOpen a bound sample statement for the selected table or view.
aSelect a connector-supported action for the selected table or view.
yCopy the qualified selected table or view name.
PPreview the selected saved query without opening or binding it.
/Filter profiles, schema objects, and saved queries.
rReload the profile file and refresh the selected profile schema, or rescan saved queries.
ZCollapse the open profile schema tree.
?Show help.
qClose the workspace.

Expanding a table reveals its available metadata folders. SQLite provides columns, primary keys, foreign keys, and indexes; each folder loads on demand. Views remain under the schema's views group and expose their columns.

Result Grid

KeyAction
h, j, k, lMove between cells.
<CR>Inspect the raw value in a floating window.
yCopy the raw selected value.
qClose the standalone grid, or return to the query editor in a workspace.

Workspace sample statements for PostgreSQL and SQLite base tables become editable when Orbit can load a primary key. Ad-hoc statements, views, Trino, and tables without a primary key remain read-only.

Key / commandAction
o, OInsert a local row below or above the current row.
i, <CR>Enter Insert mode in the focused cell; press Esc to keep the local edit.
ddMark the current row for local deletion.
V, j / k, dSelect complete rows and delete the selection.
uUndo the most recent local edit.
:wConfirm, transactionally save, and reload pending changes.
:wqSave successfully, then close the Result grid.
:q!Discard local changes and close.
:e!Discard local changes and reload the table.

Edits are never sent to the database until :w. A failed write leaves the local Result grid unchanged. Type NULL as the complete cell value to write a SQL NULL value.

Normal Neovim scrolling remains available, including <C-d>, <C-u>, zh, and zl.

Schema Object Actions

Press a on a table or view in the Workspace schema browser to select an action supplied by its connection profile kind. Actions that inspect metadata open in the Result grid; sample actions create a bound query buffer instead.

  • SQLite: sample statement, columns, primary keys, indexes, foreign keys, and object definition.
  • PostgreSQL: sample statement, columns, primary keys, indexes, foreign keys, and view definition.
  • Trino: sample statement and columns.

Available actions are intentionally connector-specific. Orbit does not present metadata actions that the selected CLI or database cannot support reliably.

Completion

Binding a connection profile attaches Orbit's native omnifunc to the query buffer. Use <C-x><C-o> in Insert mode for cached schema objects. Completion is clause-aware: it parses the statement around your cursor (not just the current line) with a small dependency-free SQL tokenizer, so suggestions depend on where you are:

  • Tables and views after any FROM-family clause (FROM, JOIN, UPDATE, INTO), and after schema./catalog.schema. qualifiers on connectors that support them (PostgreSQL, Trino).
  • Columns in the SELECT list, WHERE, ON, GROUP BY, ORDER BY, INSERT INTO t (...), and UPDATE t SET ....
  • Table aliases: SELECT u.| FROM users u resolves u to users's columns, including old-style comma joins (FROM a, b). With more than one table in scope, unqualified columns are offered from every table, each annotated with its source alias.
  • The alias/table scope is limited to the statement your cursor is in; other statements in the same buffer (separated by ;) never leak into it. CTEs and derived tables (FROM (SELECT ...) sub) are recognized so they don't break parsing, but don't offer column completion.

Selecting a profile preloads tables and views in the background; expanding it in the Workspace schema browser fills more of the cache. Completion never runs the CLI while you type. SQL keywords and functions, formatting, and highlighting remain the responsibility of your existing SQL tooling.

blink.cmp

Orbit also ships an optional blink.cmp source (orbit.blink) with the same clause-aware suggestions. blink.cmp has no API for a plugin to register itself as a source at runtime, so add it to your own blink.cmp config:

{
"saghen/blink.cmp",
opts= {
sources= {
default= { "lsp", "path", "snippets", "buffer", "orbit" },
providers= {
orbit= { name="orbit", module="orbit.blink" },
},
},
},
}

Set completion = false in Orbit's setup() to disable both the native omnifunc attachment and the blink source.

Execution And Results

Orbit runs statements asynchronously through the selected profile's CLI. For SQLite and PostgreSQL, schema work and statements share one retained connection and execute one at a time; failures notify you and open a diagnostic window, and the next request starts a new connection. Trino statements each run their own trino CLI invocation, still serialized per profile. One running statement is allowed per query buffer; :OrbitCancel terminates the current CLI invocation (and, for SQLite/PostgreSQL, the retained connection) and pending work fails rather than running against an uncertain session.

Potentially mutating statements require confirmation by default. A single SELECT, SHOW, DESCRIBE, EXPLAIN, USE, or VALUES statement runs without confirmation; everything else requires it. This is a convenience guardrail, not a security boundary.

Result grids are reused per tabpage. They show up to result_limit rows and truncate displayed cell text to max_cell_width characters while retaining the raw value for copy and inspection.

Configuration

require("orbit").setup({
completion=true,
confirm_mutations=true,
focus_results=false,
profile_path=vim.fn.expand("~/.local/share/orbit.nvim/profiles.json"),
result_limit=200,
result_height=15,
saved_query_dirs= {
{ Work="~/queries/work" },
{ Personal="~/queries/personal" },
},
max_cell_width=48,
workspace_sidebar_width=32,
workspace_result_ratio=0.30,
winbar=false,
icons= {
collapsed=">",
column="σ° ΅",
expanded="σ°˜–",
folder="󰉋",
index="",
key="",
profile="σ°†Ό",
query="󰆋",
result="󰎟",
saved_query="σ°†Ό",
table="σ°“«",
view="󰈈",
workspace="σ±“ž",
},
})
OptionDefaultDescription
completiontrueEnable clause-aware completion: both the native omnifunc attachment and the optional blink.cmp source's enabled().
confirm_mutationstrueAsk before statements that are not recognised as read-only. A profile can override this with options.confirm_mutations.
focus_resultsfalseFocus a completed standalone result grid instead of keeping focus in the query buffer.
profile_path~/.local/share/orbit.nvim/profiles.jsonLocation of the profile file.
result_limit200Maximum returned rows displayed in the result grid.
result_height15Height of a standalone result grid.
saved_query_dirs{}Ordered named directories of recursively discovered .sql files shown in the Workspace sidebar.
max_cell_width48Maximum displayed width of a result cell.
workspace_sidebar_width32Width of the workspace sidebar.
workspace_result_ratio0.30Fraction of editor height used by workspace results, with a six-line minimum.
winbarfalseShow Orbit status in SQL-window winbars.
keymapsSee aboveConfigurable action mappings.
iconsNerd Font glyphsOverride collapsed, expanded, folder, index, key, profile, query, result, saved_query, table, view, column, and workspace.

For a custom statusline, call require("orbit").status(). It reports the bound profile and shows elapsed time while a statement is running.

About

πŸš€ A database IDE for Neovim. Yes Another One...query, browse schemas, autocomplete tables and columns, and inspect results without leaving your editor.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

πŸš€ Orbit.nvim

A database IDE for Neovim

Your database revolves around your editor, not the other way around.

Orbit runs statements through your existing database CLI, retains one connection per profile where the CLI supports it, keeps profiles per query buffer, browses schemas, completes cached objects, and renders JSON results in a navigable grid.

preview

What It Does

  • Open one dedicated workspace tab with a searchable profile and schema browser.
  • Run a whole statement or a visual selection asynchronously without leaving Neovim.
  • Bind each query buffer to its own connection profile.
  • Browse tables, views, and columns; run connector-specific object actions; create a bound sample statement; copy qualified object names.
  • Inspect and copy raw result values, including structured JSON values.
  • Confirm potentially mutating statements before they run.
  • Complete cached tables, views, columns, and table aliases, clause-aware, with Neovim's built-in omnifunc or an optional blink.cmp source.
  • Browse reusable SQL files from multiple named saved-query locations.

Requirements

  • Neovim 0.10 or later.
  • No required third-party Neovim plugins.
  • The CLI required by each connection profile:
Profile kindCLINotes
trinotrinoOrbit requests JSON output.
sqlitesqlite3Requires a build that supports -json.
postgrespsqlRequires a version that supports --csv.

Installation

With lazy.nvim:

{
"mrpbennett/orbit.nvim",
opts= {},
}

Or call setup from your Neovim configuration:

require("orbit").setup()

Quick Start

  1. Run :OrbitProfiles. This creates ~/.local/share/orbit.nvim/profiles.json with owner-only (0600) permissions and opens it for editing.
  2. Add a connection profile using the format below.
  3. Open :OrbitWorkspace or a SQL buffer.
  4. Bind a profile with :OrbitProfile, or press <CR> on a profile in the workspace.
  5. Run :OrbitExecute, or use <leader>E in Normal or Visual mode in a SQL buffer.

If a query buffer has no profile, executing it opens profile selection and retries after you choose one.

Supported Connectors

KindRequired optionsOptional optionsSchema support
trinoserver, user, catalogschema, schema_patterns, executable, arguments, confirm_mutationsTables, views, and columns from information_schema. Omitting schema browses the catalog except information_schema.
sqlitepathschema_patterns, executable, arguments, confirm_mutationsTables and views from sqlite_master, plus columns from PRAGMA table_info, under main.
postgresdatabaseschema_patterns, host, port, user, password, sslmode, executable, arguments, confirm_mutationsTables and views outside PostgreSQL system schemas, plus columns, primary keys, foreign keys, and indexes.

executable replaces the CLI binary and arguments adds an array of string arguments before Orbit's generated arguments. This is useful for wrappers or CLI-specific authentication flags. For SQLite and PostgreSQL, Orbit retains one interactive CLI connection per profile; statements, schema browsing, and completion prewarming share it and are serialized per profile. A changed profile definition, failed CLI, :OrbitDisconnect, or Neovim exit closes the connection; the next request reconnects automatically. Trino statements instead run one trino CLI invocation per statement, serialized per profile, because the trino CLI does not flush its output while held open on a retained connection.

Schema browsing and completion cache rows only while the connection profile's kind and options are unchanged. Updating a profile clears its prior schema rows before Orbit acquires replacements. Connector metadata that is unavailable for an object, such as Trino primary keys, is shown as unavailable rather than treated as a statement failure. Explicit Workspace refreshes run after pending acquisitions and coalesce with other refresh requests.

schema_patterns restricts the tables and views shown by Orbit's Workspace schema browser, but does not change database permissions or restrict statements you run manually. For Trino, it maps each catalog to an array of exact schema names; use an empty array to include every non-system schema from that catalog. PostgreSQL and SQLite use a non-empty array of exact schema names instead. SQLite's only available schema is main.

Connection Profiles

The profile file is the source of truth for named connection profiles. Its default location is ~/.local/share/orbit.nvim/profiles.json; set profile_path in setup() to use another location. Orbit refuses to load a file that is not mode 0600.

Profiles are JSON, versioned at 1, and names must be unique:

PostgreSQL
{
"version": 1,
"profiles": [
{
"name": "app-db",
"kind": "postgres",
"options": {
"database": "postgres",
"host": "postgres.example.com",
"port": 5432,
"user": "postr",
"password": "somePassword",
"sslmode": "require"
}
}
]
}
SQLite
{
"version": 1,
"profiles": [
{
"name": "local",
"kind": "sqlite",
"options": {
"path": "/home/projects/data.db"
}
}
]
}
Trino
{
"version": 1,
"profiles": [
{
"name": "analytics",
"kind": "trino",
"arguments": ["--password"]
"options": {
"server": "https://trino.example.com:8443",
"user": "alice",
"catalog": "hive",
"schema": "analytics",
"schema_patterns": {
"hive": ["analytics", "reporting"],
"iceberg": []
// add more catalogs as needed...// see Trino Multi-Catalog Schema Browser
},
}
}
]
}

Trino Multi-Catalog Schema Browser

Trino profiles still require catalog as the CLI's default catalog, but schema_patterns can browse schemas from multiple catalogs. Orbit retains each object's catalog for column inspection, copied names, and generated sample statements:

{
"catalog": "gridhive",
"schema_patterns": {
"catalog_1": ["data_v2"],
"catalog_2": ["aggr", "cleanroom", "report"],
"iceberg": ["cleanroom"],
"sqlserver_rep": ["dbo"]
}
}

An empty array, such as "catalog_1": [], includes every non-system schema from that catalog. Omit a catalog entirely to hide it.

Authentication

PostgreSQL profiles may include options.password. Orbit passes it only to psql as PGPASSWORD, never as a command-line argument. The profile file is owner-protected (0600), but a password remains sensitive; use your system's credential management or a ~/.pgpass file if you prefer not to store it in JSON.

Configure Trino authentication exactly as you do for the Trino CLI, including its --password flag, environment variables, tokens, keyrings, or credential providers it uses.

Orbit passes profile values to the CLI as literal arguments. It does not expand $VAR or ${VAR} inside JSON. Other Trino CLI authentication mechanisms, such as tokens or external credential providers, continue to work through their normal CLI configuration.

Note

Connection profiles can contain sensitive settings, including PostgreSQL passwords. Orbit requires the profile file to be mode 0600; do not copy it into a repository or share it.

Workspace Workflow

:OrbitWorkspace opens a dedicated Orbit tabpage with a profile/schema browser and a normal SQL editing window. Run it again to toggle that browser. :OrbitWorkspaceClose closes only that tabpage.

  1. Press <CR> on a profile to select it and bind it to the active query buffer.
  2. Optionally press l to load its schema for browsing and completion.
  3. Press n to open a new SQL buffer already bound to the selected profile.
  4. Execute a statement. Results appear in the reusable bottom result grid.

Set saved_query_dirs to add ordered, named recursive trees of .sql files to the sidebar:

saved_query_dirs= {
{ Work="~/queries/work" },
{ Personal="~/queries/personal" },
}

Each entry must contain one unique display name and directory. Orbit preserves the configured order, expands paths such as ~, and shows each location as a separate top-level tree collapsed by default. Select a profile, then press <CR> on a saved query to open it in the Workspace query window bound to that profile; loading the schema is not required. Press r on any saved-query directory to rescan only its top-level location.

From a workspace query buffer, / focuses the workspace filter. Elsewhere, / retains normal Neovim search behavior.

Commands

CommandDescription
:OrbitProfilesCreate, protect, and edit the profile file.
:OrbitProfileSearch profiles and bind one to the current query buffer.
:OrbitSelectProfileAlias for :OrbitProfile.
:OrbitExecuteExecute the single unambiguous statement in the current buffer.
:'<,'>OrbitExecuteExecute the selected line range.
:OrbitCancelCancel the statement running in the current buffer.
:OrbitDisconnectClose the connection for the current buffer's profile.
:OrbitWorkspaceOpen the workspace or toggle its profile/schema browser.
:OrbitWorkspaceCloseClose the Orbit workspace tabpage.

Whole-buffer execution rejects ambiguous multi-statement content. Select the exact statement in Visual mode, then run :OrbitExecute or <leader>E.

Keybindings

Configurable Mappings

Orbit installs the following defaults:

Mode and scopeMappingAction
Normal, global<leader>DOpen the workspace or toggle its profile/schema browser.
Normal, SQL buffer<leader>EExecute the buffer statement.
Visual, SQL buffer<leader>EExecute the visual selection.
Normal, SQL buffer<leader>PSelect a connection profile.
Normal, SQL buffer<leader>XCancel the running statement.

Configure action mappings through keymaps. execute, browse, cancel, and select_profile are buffer-local in SQL buffers; workspace is global. Set an action to false to disable its default mapping.

require("orbit").setup({
keymaps= {
execute="<leader>E",
workspace="<leader>D",
select_profile="<leader>P",
cancel="<leader>X",
},
})

Workspace Sidebar

KeyAction
lExpand the selected profile, schema, object group, table metadata folder, or object.
hCollapse the selected node.
<CR>Select and bind a profile to the current query buffer, or open a saved query bound to the selected profile.
nCreate a query buffer bound to the selected profile.
sOpen a bound sample statement for the selected table or view.
aSelect a connector-supported action for the selected table or view.
yCopy the qualified selected table or view name.
PPreview the selected saved query without opening or binding it.
/Filter profiles, schema objects, and saved queries.
rReload the profile file and refresh the selected profile schema, or rescan saved queries.
ZCollapse the open profile schema tree.
?Show help.
qClose the workspace.

Expanding a table reveals its available metadata folders. SQLite provides columns, primary keys, foreign keys, and indexes; each folder loads on demand. Views remain under the schema's views group and expose their columns.

Result Grid

KeyAction
h, j, k, lMove between cells.
<CR>Inspect the raw value in a floating window.
yCopy the raw selected value.
qClose the standalone grid, or return to the query editor in a workspace.

Workspace sample statements for PostgreSQL and SQLite base tables become editable when Orbit can load a primary key. Ad-hoc statements, views, Trino, and tables without a primary key remain read-only.

Key / commandAction
o, OInsert a local row below or above the current row.
i, <CR>Enter Insert mode in the focused cell; press Esc to keep the local edit.
ddMark the current row for local deletion.
V, j / k, dSelect complete rows and delete the selection.
uUndo the most recent local edit.
:wConfirm, transactionally save, and reload pending changes.
:wqSave successfully, then close the Result grid.
:q!Discard local changes and close.
:e!Discard local changes and reload the table.

Edits are never sent to the database until :w. A failed write leaves the local Result grid unchanged. Type NULL as the complete cell value to write a SQL NULL value.

Normal Neovim scrolling remains available, including <C-d>, <C-u>, zh, and zl.

Schema Object Actions

Press a on a table or view in the Workspace schema browser to select an action supplied by its connection profile kind. Actions that inspect metadata open in the Result grid; sample actions create a bound query buffer instead.

  • SQLite: sample statement, columns, primary keys, indexes, foreign keys, and object definition.
  • PostgreSQL: sample statement, columns, primary keys, indexes, foreign keys, and view definition.
  • Trino: sample statement and columns.

Available actions are intentionally connector-specific. Orbit does not present metadata actions that the selected CLI or database cannot support reliably.

Completion

Binding a connection profile attaches Orbit's native omnifunc to the query buffer. Use <C-x><C-o> in Insert mode for cached schema objects. Completion is clause-aware: it parses the statement around your cursor (not just the current line) with a small dependency-free SQL tokenizer, so suggestions depend on where you are:

  • Tables and views after any FROM-family clause (FROM, JOIN, UPDATE, INTO), and after schema./catalog.schema. qualifiers on connectors that support them (PostgreSQL, Trino).
  • Columns in the SELECT list, WHERE, ON, GROUP BY, ORDER BY, INSERT INTO t (...), and UPDATE t SET ....
  • Table aliases: SELECT u.| FROM users u resolves u to users's columns, including old-style comma joins (FROM a, b). With more than one table in scope, unqualified columns are offered from every table, each annotated with its source alias.
  • The alias/table scope is limited to the statement your cursor is in; other statements in the same buffer (separated by ;) never leak into it. CTEs and derived tables (FROM (SELECT ...) sub) are recognized so they don't break parsing, but don't offer column completion.

Selecting a profile preloads tables and views in the background; expanding it in the Workspace schema browser fills more of the cache. Completion never runs the CLI while you type. SQL keywords and functions, formatting, and highlighting remain the responsibility of your existing SQL tooling.

blink.cmp

Orbit also ships an optional blink.cmp source (orbit.blink) with the same clause-aware suggestions. blink.cmp has no API for a plugin to register itself as a source at runtime, so add it to your own blink.cmp config:

{
"saghen/blink.cmp",
opts= {
sources= {
default= { "lsp", "path", "snippets", "buffer", "orbit" },
providers= {
orbit= { name="orbit", module="orbit.blink" },
},
},
},
}

Set completion = false in Orbit's setup() to disable both the native omnifunc attachment and the blink source.

Execution And Results

Orbit runs statements asynchronously through the selected profile's CLI. For SQLite and PostgreSQL, schema work and statements share one retained connection and execute one at a time; failures notify you and open a diagnostic window, and the next request starts a new connection. Trino statements each run their own trino CLI invocation, still serialized per profile. One running statement is allowed per query buffer; :OrbitCancel terminates the current CLI invocation (and, for SQLite/PostgreSQL, the retained connection) and pending work fails rather than running against an uncertain session.

Potentially mutating statements require confirmation by default. A single SELECT, SHOW, DESCRIBE, EXPLAIN, USE, or VALUES statement runs without confirmation; everything else requires it. This is a convenience guardrail, not a security boundary.

Result grids are reused per tabpage. They show up to result_limit rows and truncate displayed cell text to max_cell_width characters while retaining the raw value for copy and inspection.

Configuration

require("orbit").setup({
completion=true,
confirm_mutations=true,
focus_results=false,
profile_path=vim.fn.expand("~/.local/share/orbit.nvim/profiles.json"),
result_limit=200,
result_height=15,
saved_query_dirs= {
{ Work="~/queries/work" },
{ Personal="~/queries/personal" },
},
max_cell_width=48,
workspace_sidebar_width=32,
workspace_result_ratio=0.30,
winbar=false,
icons= {
collapsed=">",
column="σ° ΅",
expanded="σ°˜–",
folder="󰉋",
index="",
key="",
profile="σ°†Ό",
query="󰆋",
result="󰎟",
saved_query="σ°†Ό",
table="σ°“«",
view="󰈈",
workspace="σ±“ž",
},
})
OptionDefaultDescription
completiontrueEnable clause-aware completion: both the native omnifunc attachment and the optional blink.cmp source's enabled().
confirm_mutationstrueAsk before statements that are not recognised as read-only. A profile can override this with options.confirm_mutations.
focus_resultsfalseFocus a completed standalone result grid instead of keeping focus in the query buffer.
profile_path~/.local/share/orbit.nvim/profiles.jsonLocation of the profile file.
result_limit200Maximum returned rows displayed in the result grid.
result_height15Height of a standalone result grid.
saved_query_dirs{}Ordered named directories of recursively discovered .sql files shown in the Workspace sidebar.
max_cell_width48Maximum displayed width of a result cell.
workspace_sidebar_width32Width of the workspace sidebar.
workspace_result_ratio0.30Fraction of editor height used by workspace results, with a six-line minimum.
winbarfalseShow Orbit status in SQL-window winbars.
keymapsSee aboveConfigurable action mappings.
iconsNerd Font glyphsOverride collapsed, expanded, folder, index, key, profile, query, result, saved_query, table, view, column, and workspace.

For a custom statusline, call require("orbit").status(). It reports the bound profile and shows elapsed time while a statement is running.

About

πŸš€ A database IDE for Neovim. Yes Another One...query, browse schemas, autocomplete tables and columns, and inspect results without leaving your editor.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

πŸš€ Orbit.nvim

A database IDE for Neovim

Your database revolves around your editor, not the other way around.

Orbit runs statements through your existing database CLI, retains one connection per profile where the CLI supports it, keeps profiles per query buffer, browses schemas, completes cached objects, and renders JSON results in a navigable grid.

preview

What It Does

  • Open one dedicated workspace tab with a searchable profile and schema browser.
  • Run a whole statement or a visual selection asynchronously without leaving Neovim.
  • Bind each query buffer to its own connection profile.
  • Browse tables, views, and columns; run connector-specific object actions; create a bound sample statement; copy qualified object names.
  • Inspect and copy raw result values, including structured JSON values.
  • Confirm potentially mutating statements before they run.
  • Complete cached tables, views, columns, and table aliases, clause-aware, with Neovim's built-in omnifunc or an optional blink.cmp source.
  • Browse reusable SQL files from multiple named saved-query locations.

Requirements

  • Neovim 0.10 or later.
  • No required third-party Neovim plugins.
  • The CLI required by each connection profile:
Profile kindCLINotes
trinotrinoOrbit requests JSON output.
sqlitesqlite3Requires a build that supports -json.
postgrespsqlRequires a version that supports --csv.

Installation

With lazy.nvim:

{
"mrpbennett/orbit.nvim",
opts= {},
}

Or call setup from your Neovim configuration:

require("orbit").setup()

Quick Start

  1. Run :OrbitProfiles. This creates ~/.local/share/orbit.nvim/profiles.json with owner-only (0600) permissions and opens it for editing.
  2. Add a connection profile using the format below.
  3. Open :OrbitWorkspace or a SQL buffer.
  4. Bind a profile with :OrbitProfile, or press <CR> on a profile in the workspace.
  5. Run :OrbitExecute, or use <leader>E in Normal or Visual mode in a SQL buffer.

If a query buffer has no profile, executing it opens profile selection and retries after you choose one.

Supported Connectors

KindRequired optionsOptional optionsSchema support
trinoserver, user, catalogschema, schema_patterns, executable, arguments, confirm_mutationsTables, views, and columns from information_schema. Omitting schema browses the catalog except information_schema.
sqlitepathschema_patterns, executable, arguments, confirm_mutationsTables and views from sqlite_master, plus columns from PRAGMA table_info, under main.
postgresdatabaseschema_patterns, host, port, user, password, sslmode, executable, arguments, confirm_mutationsTables and views outside PostgreSQL system schemas, plus columns, primary keys, foreign keys, and indexes.

executable replaces the CLI binary and arguments adds an array of string arguments before Orbit's generated arguments. This is useful for wrappers or CLI-specific authentication flags. For SQLite and PostgreSQL, Orbit retains one interactive CLI connection per profile; statements, schema browsing, and completion prewarming share it and are serialized per profile. A changed profile definition, failed CLI, :OrbitDisconnect, or Neovim exit closes the connection; the next request reconnects automatically. Trino statements instead run one trino CLI invocation per statement, serialized per profile, because the trino CLI does not flush its output while held open on a retained connection.

Schema browsing and completion cache rows only while the connection profile's kind and options are unchanged. Updating a profile clears its prior schema rows before Orbit acquires replacements. Connector metadata that is unavailable for an object, such as Trino primary keys, is shown as unavailable rather than treated as a statement failure. Explicit Workspace refreshes run after pending acquisitions and coalesce with other refresh requests.

schema_patterns restricts the tables and views shown by Orbit's Workspace schema browser, but does not change database permissions or restrict statements you run manually. For Trino, it maps each catalog to an array of exact schema names; use an empty array to include every non-system schema from that catalog. PostgreSQL and SQLite use a non-empty array of exact schema names instead. SQLite's only available schema is main.

Connection Profiles

The profile file is the source of truth for named connection profiles. Its default location is ~/.local/share/orbit.nvim/profiles.json; set profile_path in setup() to use another location. Orbit refuses to load a file that is not mode 0600.

Profiles are JSON, versioned at 1, and names must be unique:

PostgreSQL
{
"version": 1,
"profiles": [
{
"name": "app-db",
"kind": "postgres",
"options": {
"database": "postgres",
"host": "postgres.example.com",
"port": 5432,
"user": "postr",
"password": "somePassword",
"sslmode": "require"
}
}
]
}
SQLite
{
"version": 1,
"profiles": [
{
"name": "local",
"kind": "sqlite",
"options": {
"path": "/home/projects/data.db"
}
}
]
}
Trino
{
"version": 1,
"profiles": [
{
"name": "analytics",
"kind": "trino",
"arguments": ["--password"]
"options": {
"server": "https://trino.example.com:8443",
"user": "alice",
"catalog": "hive",
"schema": "analytics",
"schema_patterns": {
"hive": ["analytics", "reporting"],
"iceberg": []
// add more catalogs as needed...// see Trino Multi-Catalog Schema Browser
},
}
}
]
}

Trino Multi-Catalog Schema Browser

Trino profiles still require catalog as the CLI's default catalog, but schema_patterns can browse schemas from multiple catalogs. Orbit retains each object's catalog for column inspection, copied names, and generated sample statements:

{
"catalog": "gridhive",
"schema_patterns": {
"catalog_1": ["data_v2"],
"catalog_2": ["aggr", "cleanroom", "report"],
"iceberg": ["cleanroom"],
"sqlserver_rep": ["dbo"]
}
}

An empty array, such as "catalog_1": [], includes every non-system schema from that catalog. Omit a catalog entirely to hide it.

Authentication

PostgreSQL profiles may include options.password. Orbit passes it only to psql as PGPASSWORD, never as a command-line argument. The profile file is owner-protected (0600), but a password remains sensitive; use your system's credential management or a ~/.pgpass file if you prefer not to store it in JSON.

Configure Trino authentication exactly as you do for the Trino CLI, including its --password flag, environment variables, tokens, keyrings, or credential providers it uses.

Orbit passes profile values to the CLI as literal arguments. It does not expand $VAR or ${VAR} inside JSON. Other Trino CLI authentication mechanisms, such as tokens or external credential providers, continue to work through their normal CLI configuration.

Note

Connection profiles can contain sensitive settings, including PostgreSQL passwords. Orbit requires the profile file to be mode 0600; do not copy it into a repository or share it.

Workspace Workflow

:OrbitWorkspace opens a dedicated Orbit tabpage with a profile/schema browser and a normal SQL editing window. Run it again to toggle that browser. :OrbitWorkspaceClose closes only that tabpage.

  1. Press <CR> on a profile to select it and bind it to the active query buffer.
  2. Optionally press l to load its schema for browsing and completion.
  3. Press n to open a new SQL buffer already bound to the selected profile.
  4. Execute a statement. Results appear in the reusable bottom result grid.

Set saved_query_dirs to add ordered, named recursive trees of .sql files to the sidebar:

saved_query_dirs= {
{ Work="~/queries/work" },
{ Personal="~/queries/personal" },
}

Each entry must contain one unique display name and directory. Orbit preserves the configured order, expands paths such as ~, and shows each location as a separate top-level tree collapsed by default. Select a profile, then press <CR> on a saved query to open it in the Workspace query window bound to that profile; loading the schema is not required. Press r on any saved-query directory to rescan only its top-level location.

From a workspace query buffer, / focuses the workspace filter. Elsewhere, / retains normal Neovim search behavior.

Commands

CommandDescription
:OrbitProfilesCreate, protect, and edit the profile file.
:OrbitProfileSearch profiles and bind one to the current query buffer.
:OrbitSelectProfileAlias for :OrbitProfile.
:OrbitExecuteExecute the single unambiguous statement in the current buffer.
:'<,'>OrbitExecuteExecute the selected line range.
:OrbitCancelCancel the statement running in the current buffer.
:OrbitDisconnectClose the connection for the current buffer's profile.
:OrbitWorkspaceOpen the workspace or toggle its profile/schema browser.
:OrbitWorkspaceCloseClose the Orbit workspace tabpage.

Whole-buffer execution rejects ambiguous multi-statement content. Select the exact statement in Visual mode, then run :OrbitExecute or <leader>E.

Keybindings

Configurable Mappings

Orbit installs the following defaults:

Mode and scopeMappingAction
Normal, global<leader>DOpen the workspace or toggle its profile/schema browser.
Normal, SQL buffer<leader>EExecute the buffer statement.
Visual, SQL buffer<leader>EExecute the visual selection.
Normal, SQL buffer<leader>PSelect a connection profile.
Normal, SQL buffer<leader>XCancel the running statement.

Configure action mappings through keymaps. execute, browse, cancel, and select_profile are buffer-local in SQL buffers; workspace is global. Set an action to false to disable its default mapping.

require("orbit").setup({
keymaps= {
execute="<leader>E",
workspace="<leader>D",
select_profile="<leader>P",
cancel="<leader>X",
},
})

Workspace Sidebar

KeyAction
lExpand the selected profile, schema, object group, table metadata folder, or object.
hCollapse the selected node.
<CR>Select and bind a profile to the current query buffer, or open a saved query bound to the selected profile.
nCreate a query buffer bound to the selected profile.
sOpen a bound sample statement for the selected table or view.
aSelect a connector-supported action for the selected table or view.
yCopy the qualified selected table or view name.
PPreview the selected saved query without opening or binding it.
/Filter profiles, schema objects, and saved queries.
rReload the profile file and refresh the selected profile schema, or rescan saved queries.
ZCollapse the open profile schema tree.
?Show help.
qClose the workspace.

Expanding a table reveals its available metadata folders. SQLite provides columns, primary keys, foreign keys, and indexes; each folder loads on demand. Views remain under the schema's views group and expose their columns.

Result Grid

KeyAction
h, j, k, lMove between cells.
<CR>Inspect the raw value in a floating window.
yCopy the raw selected value.
qClose the standalone grid, or return to the query editor in a workspace.

Workspace sample statements for PostgreSQL and SQLite base tables become editable when Orbit can load a primary key. Ad-hoc statements, views, Trino, and tables without a primary key remain read-only.

Key / commandAction
o, OInsert a local row below or above the current row.
i, <CR>Enter Insert mode in the focused cell; press Esc to keep the local edit.
ddMark the current row for local deletion.
V, j / k, dSelect complete rows and delete the selection.
uUndo the most recent local edit.
:wConfirm, transactionally save, and reload pending changes.
:wqSave successfully, then close the Result grid.
:q!Discard local changes and close.
:e!Discard local changes and reload the table.

Edits are never sent to the database until :w. A failed write leaves the local Result grid unchanged. Type NULL as the complete cell value to write a SQL NULL value.

Normal Neovim scrolling remains available, including <C-d>, <C-u>, zh, and zl.

Schema Object Actions

Press a on a table or view in the Workspace schema browser to select an action supplied by its connection profile kind. Actions that inspect metadata open in the Result grid; sample actions create a bound query buffer instead.

  • SQLite: sample statement, columns, primary keys, indexes, foreign keys, and object definition.
  • PostgreSQL: sample statement, columns, primary keys, indexes, foreign keys, and view definition.
  • Trino: sample statement and columns.

Available actions are intentionally connector-specific. Orbit does not present metadata actions that the selected CLI or database cannot support reliably.

Completion

Binding a connection profile attaches Orbit's native omnifunc to the query buffer. Use <C-x><C-o> in Insert mode for cached schema objects. Completion is clause-aware: it parses the statement around your cursor (not just the current line) with a small dependency-free SQL tokenizer, so suggestions depend on where you are:

  • Tables and views after any FROM-family clause (FROM, JOIN, UPDATE, INTO), and after schema./catalog.schema. qualifiers on connectors that support them (PostgreSQL, Trino).
  • Columns in the SELECT list, WHERE, ON, GROUP BY, ORDER BY, INSERT INTO t (...), and UPDATE t SET ....
  • Table aliases: SELECT u.| FROM users u resolves u to users's columns, including old-style comma joins (FROM a, b). With more than one table in scope, unqualified columns are offered from every table, each annotated with its source alias.
  • The alias/table scope is limited to the statement your cursor is in; other statements in the same buffer (separated by ;) never leak into it. CTEs and derived tables (FROM (SELECT ...) sub) are recognized so they don't break parsing, but don't offer column completion.

Selecting a profile preloads tables and views in the background; expanding it in the Workspace schema browser fills more of the cache. Completion never runs the CLI while you type. SQL keywords and functions, formatting, and highlighting remain the responsibility of your existing SQL tooling.

blink.cmp

Orbit also ships an optional blink.cmp source (orbit.blink) with the same clause-aware suggestions. blink.cmp has no API for a plugin to register itself as a source at runtime, so add it to your own blink.cmp config:

{
"saghen/blink.cmp",
opts= {
sources= {
default= { "lsp", "path", "snippets", "buffer", "orbit" },
providers= {
orbit= { name="orbit", module="orbit.blink" },
},
},
},
}

Set completion = false in Orbit's setup() to disable both the native omnifunc attachment and the blink source.

Execution And Results

Orbit runs statements asynchronously through the selected profile's CLI. For SQLite and PostgreSQL, schema work and statements share one retained connection and execute one at a time; failures notify you and open a diagnostic window, and the next request starts a new connection. Trino statements each run their own trino CLI invocation, still serialized per profile. One running statement is allowed per query buffer; :OrbitCancel terminates the current CLI invocation (and, for SQLite/PostgreSQL, the retained connection) and pending work fails rather than running against an uncertain session.

Potentially mutating statements require confirmation by default. A single SELECT, SHOW, DESCRIBE, EXPLAIN, USE, or VALUES statement runs without confirmation; everything else requires it. This is a convenience guardrail, not a security boundary.

Result grids are reused per tabpage. They show up to result_limit rows and truncate displayed cell text to max_cell_width characters while retaining the raw value for copy and inspection.

Configuration

require("orbit").setup({
completion=true,
confirm_mutations=true,
focus_results=false,
profile_path=vim.fn.expand("~/.local/share/orbit.nvim/profiles.json"),
result_limit=200,
result_height=15,
saved_query_dirs= {
{ Work="~/queries/work" },
{ Personal="~/queries/personal" },
},
max_cell_width=48,
workspace_sidebar_width=32,
workspace_result_ratio=0.30,
winbar=false,
icons= {
collapsed=">",
column="σ° ΅",
expanded="σ°˜–",
folder="󰉋",
index="",
key="",
profile="σ°†Ό",
query="󰆋",
result="󰎟",
saved_query="σ°†Ό",
table="σ°“«",
view="󰈈",
workspace="σ±“ž",
},
})
OptionDefaultDescription
completiontrueEnable clause-aware completion: both the native omnifunc attachment and the optional blink.cmp source's enabled().
confirm_mutationstrueAsk before statements that are not recognised as read-only. A profile can override this with options.confirm_mutations.
focus_resultsfalseFocus a completed standalone result grid instead of keeping focus in the query buffer.
profile_path~/.local/share/orbit.nvim/profiles.jsonLocation of the profile file.
result_limit200Maximum returned rows displayed in the result grid.
result_height15Height of a standalone result grid.
saved_query_dirs{}Ordered named directories of recursively discovered .sql files shown in the Workspace sidebar.
max_cell_width48Maximum displayed width of a result cell.
workspace_sidebar_width32Width of the workspace sidebar.
workspace_result_ratio0.30Fraction of editor height used by workspace results, with a six-line minimum.
winbarfalseShow Orbit status in SQL-window winbars.
keymapsSee aboveConfigurable action mappings.
iconsNerd Font glyphsOverride collapsed, expanded, folder, index, key, profile, query, result, saved_query, table, view, column, and workspace.

For a custom statusline, call require("orbit").status(). It reports the bound profile and shows elapsed time while a statement is running.

About

πŸš€ A database IDE for Neovim. Yes Another One...query, browse schemas, autocomplete tables and columns, and inspect results without leaving your editor.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

πŸš€ Orbit.nvim

A database IDE for Neovim

Your database revolves around your editor, not the other way around.

Orbit runs statements through your existing database CLI, retains one connection per profile where the CLI supports it, keeps profiles per query buffer, browses schemas, completes cached objects, and renders JSON results in a navigable grid.

preview

What It Does

  • Open one dedicated workspace tab with a searchable profile and schema browser.
  • Run a whole statement or a visual selection asynchronously without leaving Neovim.
  • Bind each query buffer to its own connection profile.
  • Browse tables, views, and columns; run connector-specific object actions; create a bound sample statement; copy qualified object names.
  • Inspect and copy raw result values, including structured JSON values.
  • Confirm potentially mutating statements before they run.
  • Complete cached tables, views, columns, and table aliases, clause-aware, with Neovim's built-in omnifunc or an optional blink.cmp source.
  • Browse reusable SQL files from multiple named saved-query locations.

Requirements

  • Neovim 0.10 or later.
  • No required third-party Neovim plugins.
  • The CLI required by each connection profile:
Profile kindCLINotes
trinotrinoOrbit requests JSON output.
sqlitesqlite3Requires a build that supports -json.
postgrespsqlRequires a version that supports --csv.

Installation

With lazy.nvim:

{
"mrpbennett/orbit.nvim",
opts= {},
}

Or call setup from your Neovim configuration:

require("orbit").setup()

Quick Start

  1. Run :OrbitProfiles. This creates ~/.local/share/orbit.nvim/profiles.json with owner-only (0600) permissions and opens it for editing.
  2. Add a connection profile using the format below.
  3. Open :OrbitWorkspace or a SQL buffer.
  4. Bind a profile with :OrbitProfile, or press <CR> on a profile in the workspace.
  5. Run :OrbitExecute, or use <leader>E in Normal or Visual mode in a SQL buffer.

If a query buffer has no profile, executing it opens profile selection and retries after you choose one.

Supported Connectors

KindRequired optionsOptional optionsSchema support
trinoserver, user, catalogschema, schema_patterns, executable, arguments, confirm_mutationsTables, views, and columns from information_schema. Omitting schema browses the catalog except information_schema.
sqlitepathschema_patterns, executable, arguments, confirm_mutationsTables and views from sqlite_master, plus columns from PRAGMA table_info, under main.
postgresdatabaseschema_patterns, host, port, user, password, sslmode, executable, arguments, confirm_mutationsTables and views outside PostgreSQL system schemas, plus columns, primary keys, foreign keys, and indexes.

executable replaces the CLI binary and arguments adds an array of string arguments before Orbit's generated arguments. This is useful for wrappers or CLI-specific authentication flags. For SQLite and PostgreSQL, Orbit retains one interactive CLI connection per profile; statements, schema browsing, and completion prewarming share it and are serialized per profile. A changed profile definition, failed CLI, :OrbitDisconnect, or Neovim exit closes the connection; the next request reconnects automatically. Trino statements instead run one trino CLI invocation per statement, serialized per profile, because the trino CLI does not flush its output while held open on a retained connection.

Schema browsing and completion cache rows only while the connection profile's kind and options are unchanged. Updating a profile clears its prior schema rows before Orbit acquires replacements. Connector metadata that is unavailable for an object, such as Trino primary keys, is shown as unavailable rather than treated as a statement failure. Explicit Workspace refreshes run after pending acquisitions and coalesce with other refresh requests.

schema_patterns restricts the tables and views shown by Orbit's Workspace schema browser, but does not change database permissions or restrict statements you run manually. For Trino, it maps each catalog to an array of exact schema names; use an empty array to include every non-system schema from that catalog. PostgreSQL and SQLite use a non-empty array of exact schema names instead. SQLite's only available schema is main.

Connection Profiles

The profile file is the source of truth for named connection profiles. Its default location is ~/.local/share/orbit.nvim/profiles.json; set profile_path in setup() to use another location. Orbit refuses to load a file that is not mode 0600.

Profiles are JSON, versioned at 1, and names must be unique:

PostgreSQL
{
"version": 1,
"profiles": [
{
"name": "app-db",
"kind": "postgres",
"options": {
"database": "postgres",
"host": "postgres.example.com",
"port": 5432,
"user": "postr",
"password": "somePassword",
"sslmode": "require"
}
}
]
}
SQLite
{
"version": 1,
"profiles": [
{
"name": "local",
"kind": "sqlite",
"options": {
"path": "/home/projects/data.db"
}
}
]
}
Trino
{
"version": 1,
"profiles": [
{
"name": "analytics",
"kind": "trino",
"arguments": ["--password"]
"options": {
"server": "https://trino.example.com:8443",
"user": "alice",
"catalog": "hive",
"schema": "analytics",
"schema_patterns": {
"hive": ["analytics", "reporting"],
"iceberg": []
// add more catalogs as needed...// see Trino Multi-Catalog Schema Browser
},
}
}
]
}

Trino Multi-Catalog Schema Browser

Trino profiles still require catalog as the CLI's default catalog, but schema_patterns can browse schemas from multiple catalogs. Orbit retains each object's catalog for column inspection, copied names, and generated sample statements:

{
"catalog": "gridhive",
"schema_patterns": {
"catalog_1": ["data_v2"],
"catalog_2": ["aggr", "cleanroom", "report"],
"iceberg": ["cleanroom"],
"sqlserver_rep": ["dbo"]
}
}

An empty array, such as "catalog_1": [], includes every non-system schema from that catalog. Omit a catalog entirely to hide it.

Authentication

PostgreSQL profiles may include options.password. Orbit passes it only to psql as PGPASSWORD, never as a command-line argument. The profile file is owner-protected (0600), but a password remains sensitive; use your system's credential management or a ~/.pgpass file if you prefer not to store it in JSON.

Configure Trino authentication exactly as you do for the Trino CLI, including its --password flag, environment variables, tokens, keyrings, or credential providers it uses.

Orbit passes profile values to the CLI as literal arguments. It does not expand $VAR or ${VAR} inside JSON. Other Trino CLI authentication mechanisms, such as tokens or external credential providers, continue to work through their normal CLI configuration.

Note

Connection profiles can contain sensitive settings, including PostgreSQL passwords. Orbit requires the profile file to be mode 0600; do not copy it into a repository or share it.

Workspace Workflow

:OrbitWorkspace opens a dedicated Orbit tabpage with a profile/schema browser and a normal SQL editing window. Run it again to toggle that browser. :OrbitWorkspaceClose closes only that tabpage.

  1. Press <CR> on a profile to select it and bind it to the active query buffer.
  2. Optionally press l to load its schema for browsing and completion.
  3. Press n to open a new SQL buffer already bound to the selected profile.
  4. Execute a statement. Results appear in the reusable bottom result grid.

Set saved_query_dirs to add ordered, named recursive trees of .sql files to the sidebar:

saved_query_dirs= {
{ Work="~/queries/work" },
{ Personal="~/queries/personal" },
}

Each entry must contain one unique display name and directory. Orbit preserves the configured order, expands paths such as ~, and shows each location as a separate top-level tree collapsed by default. Select a profile, then press <CR> on a saved query to open it in the Workspace query window bound to that profile; loading the schema is not required. Press r on any saved-query directory to rescan only its top-level location.

From a workspace query buffer, / focuses the workspace filter. Elsewhere, / retains normal Neovim search behavior.

Commands

CommandDescription
:OrbitProfilesCreate, protect, and edit the profile file.
:OrbitProfileSearch profiles and bind one to the current query buffer.
:OrbitSelectProfileAlias for :OrbitProfile.
:OrbitExecuteExecute the single unambiguous statement in the current buffer.
:'<,'>OrbitExecuteExecute the selected line range.
:OrbitCancelCancel the statement running in the current buffer.
:OrbitDisconnectClose the connection for the current buffer's profile.
:OrbitWorkspaceOpen the workspace or toggle its profile/schema browser.
:OrbitWorkspaceCloseClose the Orbit workspace tabpage.

Whole-buffer execution rejects ambiguous multi-statement content. Select the exact statement in Visual mode, then run :OrbitExecute or <leader>E.

Keybindings

Configurable Mappings

Orbit installs the following defaults:

Mode and scopeMappingAction
Normal, global<leader>DOpen the workspace or toggle its profile/schema browser.
Normal, SQL buffer<leader>EExecute the buffer statement.
Visual, SQL buffer<leader>EExecute the visual selection.
Normal, SQL buffer<leader>PSelect a connection profile.
Normal, SQL buffer<leader>XCancel the running statement.

Configure action mappings through keymaps. execute, browse, cancel, and select_profile are buffer-local in SQL buffers; workspace is global. Set an action to false to disable its default mapping.

require("orbit").setup({
keymaps= {
execute="<leader>E",
workspace="<leader>D",
select_profile="<leader>P",
cancel="<leader>X",
},
})

Workspace Sidebar

KeyAction
lExpand the selected profile, schema, object group, table metadata folder, or object.
hCollapse the selected node.
<CR>Select and bind a profile to the current query buffer, or open a saved query bound to the selected profile.
nCreate a query buffer bound to the selected profile.
sOpen a bound sample statement for the selected table or view.
aSelect a connector-supported action for the selected table or view.
yCopy the qualified selected table or view name.
PPreview the selected saved query without opening or binding it.
/Filter profiles, schema objects, and saved queries.
rReload the profile file and refresh the selected profile schema, or rescan saved queries.
ZCollapse the open profile schema tree.
?Show help.
qClose the workspace.

Expanding a table reveals its available metadata folders. SQLite provides columns, primary keys, foreign keys, and indexes; each folder loads on demand. Views remain under the schema's views group and expose their columns.

Result Grid

KeyAction
h, j, k, lMove between cells.
<CR>Inspect the raw value in a floating window.
yCopy the raw selected value.
qClose the standalone grid, or return to the query editor in a workspace.

Workspace sample statements for PostgreSQL and SQLite base tables become editable when Orbit can load a primary key. Ad-hoc statements, views, Trino, and tables without a primary key remain read-only.

Key / commandAction
o, OInsert a local row below or above the current row.
i, <CR>Enter Insert mode in the focused cell; press Esc to keep the local edit.
ddMark the current row for local deletion.
V, j / k, dSelect complete rows and delete the selection.
uUndo the most recent local edit.
:wConfirm, transactionally save, and reload pending changes.
:wqSave successfully, then close the Result grid.
:q!Discard local changes and close.
:e!Discard local changes and reload the table.

Edits are never sent to the database until :w. A failed write leaves the local Result grid unchanged. Type NULL as the complete cell value to write a SQL NULL value.

Normal Neovim scrolling remains available, including <C-d>, <C-u>, zh, and zl.

Schema Object Actions

Press a on a table or view in the Workspace schema browser to select an action supplied by its connection profile kind. Actions that inspect metadata open in the Result grid; sample actions create a bound query buffer instead.

  • SQLite: sample statement, columns, primary keys, indexes, foreign keys, and object definition.
  • PostgreSQL: sample statement, columns, primary keys, indexes, foreign keys, and view definition.
  • Trino: sample statement and columns.

Available actions are intentionally connector-specific. Orbit does not present metadata actions that the selected CLI or database cannot support reliably.

Completion

Binding a connection profile attaches Orbit's native omnifunc to the query buffer. Use <C-x><C-o> in Insert mode for cached schema objects. Completion is clause-aware: it parses the statement around your cursor (not just the current line) with a small dependency-free SQL tokenizer, so suggestions depend on where you are:

  • Tables and views after any FROM-family clause (FROM, JOIN, UPDATE, INTO), and after schema./catalog.schema. qualifiers on connectors that support them (PostgreSQL, Trino).
  • Columns in the SELECT list, WHERE, ON, GROUP BY, ORDER BY, INSERT INTO t (...), and UPDATE t SET ....
  • Table aliases: SELECT u.| FROM users u resolves u to users's columns, including old-style comma joins (FROM a, b). With more than one table in scope, unqualified columns are offered from every table, each annotated with its source alias.
  • The alias/table scope is limited to the statement your cursor is in; other statements in the same buffer (separated by ;) never leak into it. CTEs and derived tables (FROM (SELECT ...) sub) are recognized so they don't break parsing, but don't offer column completion.

Selecting a profile preloads tables and views in the background; expanding it in the Workspace schema browser fills more of the cache. Completion never runs the CLI while you type. SQL keywords and functions, formatting, and highlighting remain the responsibility of your existing SQL tooling.

blink.cmp

Orbit also ships an optional blink.cmp source (orbit.blink) with the same clause-aware suggestions. blink.cmp has no API for a plugin to register itself as a source at runtime, so add it to your own blink.cmp config:

{
"saghen/blink.cmp",
opts= {
sources= {
default= { "lsp", "path", "snippets", "buffer", "orbit" },
providers= {
orbit= { name="orbit", module="orbit.blink" },
},
},
},
}

Set completion = false in Orbit's setup() to disable both the native omnifunc attachment and the blink source.

Execution And Results

Orbit runs statements asynchronously through the selected profile's CLI. For SQLite and PostgreSQL, schema work and statements share one retained connection and execute one at a time; failures notify you and open a diagnostic window, and the next request starts a new connection. Trino statements each run their own trino CLI invocation, still serialized per profile. One running statement is allowed per query buffer; :OrbitCancel terminates the current CLI invocation (and, for SQLite/PostgreSQL, the retained connection) and pending work fails rather than running against an uncertain session.

Potentially mutating statements require confirmation by default. A single SELECT, SHOW, DESCRIBE, EXPLAIN, USE, or VALUES statement runs without confirmation; everything else requires it. This is a convenience guardrail, not a security boundary.

Result grids are reused per tabpage. They show up to result_limit rows and truncate displayed cell text to max_cell_width characters while retaining the raw value for copy and inspection.

Configuration

require("orbit").setup({
completion=true,
confirm_mutations=true,
focus_results=false,
profile_path=vim.fn.expand("~/.local/share/orbit.nvim/profiles.json"),
result_limit=200,
result_height=15,
saved_query_dirs= {
{ Work="~/queries/work" },
{ Personal="~/queries/personal" },
},
max_cell_width=48,
workspace_sidebar_width=32,
workspace_result_ratio=0.30,
winbar=false,
icons= {
collapsed=">",
column="σ° ΅",
expanded="σ°˜–",
folder="󰉋",
index="",
key="",
profile="σ°†Ό",
query="󰆋",
result="󰎟",
saved_query="σ°†Ό",
table="σ°“«",
view="󰈈",
workspace="σ±“ž",
},
})
OptionDefaultDescription
completiontrueEnable clause-aware completion: both the native omnifunc attachment and the optional blink.cmp source's enabled().
confirm_mutationstrueAsk before statements that are not recognised as read-only. A profile can override this with options.confirm_mutations.
focus_resultsfalseFocus a completed standalone result grid instead of keeping focus in the query buffer.
profile_path~/.local/share/orbit.nvim/profiles.jsonLocation of the profile file.
result_limit200Maximum returned rows displayed in the result grid.
result_height15Height of a standalone result grid.
saved_query_dirs{}Ordered named directories of recursively discovered .sql files shown in the Workspace sidebar.
max_cell_width48Maximum displayed width of a result cell.
workspace_sidebar_width32Width of the workspace sidebar.
workspace_result_ratio0.30Fraction of editor height used by workspace results, with a six-line minimum.
winbarfalseShow Orbit status in SQL-window winbars.
keymapsSee aboveConfigurable action mappings.
iconsNerd Font glyphsOverride collapsed, expanded, folder, index, key, profile, query, result, saved_query, table, view, column, and workspace.

For a custom statusline, call require("orbit").status(). It reports the bound profile and shows elapsed time while a statement is running.

About

πŸš€ A database IDE for Neovim. Yes Another One...query, browse schemas, autocomplete tables and columns, and inspect results without leaving your editor.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

πŸš€ Orbit.nvim

A database IDE for Neovim

Your database revolves around your editor, not the other way around.

Orbit runs statements through your existing database CLI, retains one connection per profile where the CLI supports it, keeps profiles per query buffer, browses schemas, completes cached objects, and renders JSON results in a navigable grid.

preview

What It Does

  • Open one dedicated workspace tab with a searchable profile and schema browser.
  • Run a whole statement or a visual selection asynchronously without leaving Neovim.
  • Bind each query buffer to its own connection profile.
  • Browse tables, views, and columns; run connector-specific object actions; create a bound sample statement; copy qualified object names.
  • Inspect and copy raw result values, including structured JSON values.
  • Confirm potentially mutating statements before they run.
  • Complete cached tables, views, columns, and table aliases, clause-aware, with Neovim's built-in omnifunc or an optional blink.cmp source.
  • Browse reusable SQL files from multiple named saved-query locations.

Requirements

  • Neovim 0.10 or later.
  • No required third-party Neovim plugins.
  • The CLI required by each connection profile:
Profile kindCLINotes
trinotrinoOrbit requests JSON output.
sqlitesqlite3Requires a build that supports -json.
postgrespsqlRequires a version that supports --csv.

Installation

With lazy.nvim:

{
"mrpbennett/orbit.nvim",
opts= {},
}

Or call setup from your Neovim configuration:

require("orbit").setup()

Quick Start

  1. Run :OrbitProfiles. This creates ~/.local/share/orbit.nvim/profiles.json with owner-only (0600) permissions and opens it for editing.
  2. Add a connection profile using the format below.
  3. Open :OrbitWorkspace or a SQL buffer.
  4. Bind a profile with :OrbitProfile, or press <CR> on a profile in the workspace.
  5. Run :OrbitExecute, or use <leader>E in Normal or Visual mode in a SQL buffer.

If a query buffer has no profile, executing it opens profile selection and retries after you choose one.

Supported Connectors

KindRequired optionsOptional optionsSchema support
trinoserver, user, catalogschema, schema_patterns, executable, arguments, confirm_mutationsTables, views, and columns from information_schema. Omitting schema browses the catalog except information_schema.
sqlitepathschema_patterns, executable, arguments, confirm_mutationsTables and views from sqlite_master, plus columns from PRAGMA table_info, under main.
postgresdatabaseschema_patterns, host, port, user, password, sslmode, executable, arguments, confirm_mutationsTables and views outside PostgreSQL system schemas, plus columns, primary keys, foreign keys, and indexes.

executable replaces the CLI binary and arguments adds an array of string arguments before Orbit's generated arguments. This is useful for wrappers or CLI-specific authentication flags. For SQLite and PostgreSQL, Orbit retains one interactive CLI connection per profile; statements, schema browsing, and completion prewarming share it and are serialized per profile. A changed profile definition, failed CLI, :OrbitDisconnect, or Neovim exit closes the connection; the next request reconnects automatically. Trino statements instead run one trino CLI invocation per statement, serialized per profile, because the trino CLI does not flush its output while held open on a retained connection.

Schema browsing and completion cache rows only while the connection profile's kind and options are unchanged. Updating a profile clears its prior schema rows before Orbit acquires replacements. Connector metadata that is unavailable for an object, such as Trino primary keys, is shown as unavailable rather than treated as a statement failure. Explicit Workspace refreshes run after pending acquisitions and coalesce with other refresh requests.

schema_patterns restricts the tables and views shown by Orbit's Workspace schema browser, but does not change database permissions or restrict statements you run manually. For Trino, it maps each catalog to an array of exact schema names; use an empty array to include every non-system schema from that catalog. PostgreSQL and SQLite use a non-empty array of exact schema names instead. SQLite's only available schema is main.

Connection Profiles

The profile file is the source of truth for named connection profiles. Its default location is ~/.local/share/orbit.nvim/profiles.json; set profile_path in setup() to use another location. Orbit refuses to load a file that is not mode 0600.

Profiles are JSON, versioned at 1, and names must be unique:

PostgreSQL
{
"version": 1,
"profiles": [
{
"name": "app-db",
"kind": "postgres",
"options": {
"database": "postgres",
"host": "postgres.example.com",
"port": 5432,
"user": "postr",
"password": "somePassword",
"sslmode": "require"
}
}
]
}
SQLite
{
"version": 1,
"profiles": [
{
"name": "local",
"kind": "sqlite",
"options": {
"path": "/home/projects/data.db"
}
}
]
}
Trino
{
"version": 1,
"profiles": [
{
"name": "analytics",
"kind": "trino",
"arguments": ["--password"]
"options": {
"server": "https://trino.example.com:8443",
"user": "alice",
"catalog": "hive",
"schema": "analytics",
"schema_patterns": {
"hive": ["analytics", "reporting"],
"iceberg": []
// add more catalogs as needed...// see Trino Multi-Catalog Schema Browser
},
}
}
]
}

Trino Multi-Catalog Schema Browser

Trino profiles still require catalog as the CLI's default catalog, but schema_patterns can browse schemas from multiple catalogs. Orbit retains each object's catalog for column inspection, copied names, and generated sample statements:

{
"catalog": "gridhive",
"schema_patterns": {
"catalog_1": ["data_v2"],
"catalog_2": ["aggr", "cleanroom", "report"],
"iceberg": ["cleanroom"],
"sqlserver_rep": ["dbo"]
}
}

An empty array, such as "catalog_1": [], includes every non-system schema from that catalog. Omit a catalog entirely to hide it.

Authentication

PostgreSQL profiles may include options.password. Orbit passes it only to psql as PGPASSWORD, never as a command-line argument. The profile file is owner-protected (0600), but a password remains sensitive; use your system's credential management or a ~/.pgpass file if you prefer not to store it in JSON.

Configure Trino authentication exactly as you do for the Trino CLI, including its --password flag, environment variables, tokens, keyrings, or credential providers it uses.

Orbit passes profile values to the CLI as literal arguments. It does not expand $VAR or ${VAR} inside JSON. Other Trino CLI authentication mechanisms, such as tokens or external credential providers, continue to work through their normal CLI configuration.

Note

Connection profiles can contain sensitive settings, including PostgreSQL passwords. Orbit requires the profile file to be mode 0600; do not copy it into a repository or share it.

Workspace Workflow

:OrbitWorkspace opens a dedicated Orbit tabpage with a profile/schema browser and a normal SQL editing window. Run it again to toggle that browser. :OrbitWorkspaceClose closes only that tabpage.

  1. Press <CR> on a profile to select it and bind it to the active query buffer.
  2. Optionally press l to load its schema for browsing and completion.
  3. Press n to open a new SQL buffer already bound to the selected profile.
  4. Execute a statement. Results appear in the reusable bottom result grid.

Set saved_query_dirs to add ordered, named recursive trees of .sql files to the sidebar:

saved_query_dirs= {
{ Work="~/queries/work" },
{ Personal="~/queries/personal" },
}

Each entry must contain one unique display name and directory. Orbit preserves the configured order, expands paths such as ~, and shows each location as a separate top-level tree collapsed by default. Select a profile, then press <CR> on a saved query to open it in the Workspace query window bound to that profile; loading the schema is not required. Press r on any saved-query directory to rescan only its top-level location.

From a workspace query buffer, / focuses the workspace filter. Elsewhere, / retains normal Neovim search behavior.

Commands

CommandDescription
:OrbitProfilesCreate, protect, and edit the profile file.
:OrbitProfileSearch profiles and bind one to the current query buffer.
:OrbitSelectProfileAlias for :OrbitProfile.
:OrbitExecuteExecute the single unambiguous statement in the current buffer.
:'<,'>OrbitExecuteExecute the selected line range.
:OrbitCancelCancel the statement running in the current buffer.
:OrbitDisconnectClose the connection for the current buffer's profile.
:OrbitWorkspaceOpen the workspace or toggle its profile/schema browser.
:OrbitWorkspaceCloseClose the Orbit workspace tabpage.

Whole-buffer execution rejects ambiguous multi-statement content. Select the exact statement in Visual mode, then run :OrbitExecute or <leader>E.

Keybindings

Configurable Mappings

Orbit installs the following defaults:

Mode and scopeMappingAction
Normal, global<leader>DOpen the workspace or toggle its profile/schema browser.
Normal, SQL buffer<leader>EExecute the buffer statement.
Visual, SQL buffer<leader>EExecute the visual selection.
Normal, SQL buffer<leader>PSelect a connection profile.
Normal, SQL buffer<leader>XCancel the running statement.

Configure action mappings through keymaps. execute, browse, cancel, and select_profile are buffer-local in SQL buffers; workspace is global. Set an action to false to disable its default mapping.

require("orbit").setup({
keymaps= {
execute="<leader>E",
workspace="<leader>D",
select_profile="<leader>P",
cancel="<leader>X",
},
})

Workspace Sidebar

KeyAction
lExpand the selected profile, schema, object group, table metadata folder, or object.
hCollapse the selected node.
<CR>Select and bind a profile to the current query buffer, or open a saved query bound to the selected profile.
nCreate a query buffer bound to the selected profile.
sOpen a bound sample statement for the selected table or view.
aSelect a connector-supported action for the selected table or view.
yCopy the qualified selected table or view name.
PPreview the selected saved query without opening or binding it.
/Filter profiles, schema objects, and saved queries.
rReload the profile file and refresh the selected profile schema, or rescan saved queries.
ZCollapse the open profile schema tree.
?Show help.
qClose the workspace.

Expanding a table reveals its available metadata folders. SQLite provides columns, primary keys, foreign keys, and indexes; each folder loads on demand. Views remain under the schema's views group and expose their columns.

Result Grid

KeyAction
h, j, k, lMove between cells.
<CR>Inspect the raw value in a floating window.
yCopy the raw selected value.
qClose the standalone grid, or return to the query editor in a workspace.

Workspace sample statements for PostgreSQL and SQLite base tables become editable when Orbit can load a primary key. Ad-hoc statements, views, Trino, and tables without a primary key remain read-only.

Key / commandAction
o, OInsert a local row below or above the current row.
i, <CR>Enter Insert mode in the focused cell; press Esc to keep the local edit.
ddMark the current row for local deletion.
V, j / k, dSelect complete rows and delete the selection.
uUndo the most recent local edit.
:wConfirm, transactionally save, and reload pending changes.
:wqSave successfully, then close the Result grid.
:q!Discard local changes and close.
:e!Discard local changes and reload the table.

Edits are never sent to the database until :w. A failed write leaves the local Result grid unchanged. Type NULL as the complete cell value to write a SQL NULL value.

Normal Neovim scrolling remains available, including <C-d>, <C-u>, zh, and zl.

Schema Object Actions

Press a on a table or view in the Workspace schema browser to select an action supplied by its connection profile kind. Actions that inspect metadata open in the Result grid; sample actions create a bound query buffer instead.

  • SQLite: sample statement, columns, primary keys, indexes, foreign keys, and object definition.
  • PostgreSQL: sample statement, columns, primary keys, indexes, foreign keys, and view definition.
  • Trino: sample statement and columns.

Available actions are intentionally connector-specific. Orbit does not present metadata actions that the selected CLI or database cannot support reliably.

Completion

Binding a connection profile attaches Orbit's native omnifunc to the query buffer. Use <C-x><C-o> in Insert mode for cached schema objects. Completion is clause-aware: it parses the statement around your cursor (not just the current line) with a small dependency-free SQL tokenizer, so suggestions depend on where you are:

  • Tables and views after any FROM-family clause (FROM, JOIN, UPDATE, INTO), and after schema./catalog.schema. qualifiers on connectors that support them (PostgreSQL, Trino).
  • Columns in the SELECT list, WHERE, ON, GROUP BY, ORDER BY, INSERT INTO t (...), and UPDATE t SET ....
  • Table aliases: SELECT u.| FROM users u resolves u to users's columns, including old-style comma joins (FROM a, b). With more than one table in scope, unqualified columns are offered from every table, each annotated with its source alias.
  • The alias/table scope is limited to the statement your cursor is in; other statements in the same buffer (separated by ;) never leak into it. CTEs and derived tables (FROM (SELECT ...) sub) are recognized so they don't break parsing, but don't offer column completion.

Selecting a profile preloads tables and views in the background; expanding it in the Workspace schema browser fills more of the cache. Completion never runs the CLI while you type. SQL keywords and functions, formatting, and highlighting remain the responsibility of your existing SQL tooling.

blink.cmp

Orbit also ships an optional blink.cmp source (orbit.blink) with the same clause-aware suggestions. blink.cmp has no API for a plugin to register itself as a source at runtime, so add it to your own blink.cmp config:

{
"saghen/blink.cmp",
opts= {
sources= {
default= { "lsp", "path", "snippets", "buffer", "orbit" },
providers= {
orbit= { name="orbit", module="orbit.blink" },
},
},
},
}

Set completion = false in Orbit's setup() to disable both the native omnifunc attachment and the blink source.

Execution And Results

Orbit runs statements asynchronously through the selected profile's CLI. For SQLite and PostgreSQL, schema work and statements share one retained connection and execute one at a time; failures notify you and open a diagnostic window, and the next request starts a new connection. Trino statements each run their own trino CLI invocation, still serialized per profile. One running statement is allowed per query buffer; :OrbitCancel terminates the current CLI invocation (and, for SQLite/PostgreSQL, the retained connection) and pending work fails rather than running against an uncertain session.

Potentially mutating statements require confirmation by default. A single SELECT, SHOW, DESCRIBE, EXPLAIN, USE, or VALUES statement runs without confirmation; everything else requires it. This is a convenience guardrail, not a security boundary.

Result grids are reused per tabpage. They show up to result_limit rows and truncate displayed cell text to max_cell_width characters while retaining the raw value for copy and inspection.

Configuration

require("orbit").setup({
completion=true,
confirm_mutations=true,
focus_results=false,
profile_path=vim.fn.expand("~/.local/share/orbit.nvim/profiles.json"),
result_limit=200,
result_height=15,
saved_query_dirs= {
{ Work="~/queries/work" },
{ Personal="~/queries/personal" },
},
max_cell_width=48,
workspace_sidebar_width=32,
workspace_result_ratio=0.30,
winbar=false,
icons= {
collapsed=">",
column="σ° ΅",
expanded="σ°˜–",
folder="󰉋",
index="",
key="",
profile="σ°†Ό",
query="󰆋",
result="󰎟",
saved_query="σ°†Ό",
table="σ°“«",
view="󰈈",
workspace="σ±“ž",
},
})
OptionDefaultDescription
completiontrueEnable clause-aware completion: both the native omnifunc attachment and the optional blink.cmp source's enabled().
confirm_mutationstrueAsk before statements that are not recognised as read-only. A profile can override this with options.confirm_mutations.
focus_resultsfalseFocus a completed standalone result grid instead of keeping focus in the query buffer.
profile_path~/.local/share/orbit.nvim/profiles.jsonLocation of the profile file.
result_limit200Maximum returned rows displayed in the result grid.
result_height15Height of a standalone result grid.
saved_query_dirs{}Ordered named directories of recursively discovered .sql files shown in the Workspace sidebar.
max_cell_width48Maximum displayed width of a result cell.
workspace_sidebar_width32Width of the workspace sidebar.
workspace_result_ratio0.30Fraction of editor height used by workspace results, with a six-line minimum.
winbarfalseShow Orbit status in SQL-window winbars.
keymapsSee aboveConfigurable action mappings.
iconsNerd Font glyphsOverride collapsed, expanded, folder, index, key, profile, query, result, saved_query, table, view, column, and workspace.

For a custom statusline, call require("orbit").status(). It reports the bound profile and shows elapsed time while a statement is running.

About

πŸš€ A database IDE for Neovim. Yes Another One...query, browse schemas, autocomplete tables and columns, and inspect results without leaving your editor.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages