pgview docs

pgview

v0.4.1 Go 1.22+ MIT

pgview is a lightweight, keyboard-driven PostgreSQL browser for the terminal. Built in Go using the same TUI framework as k9s, it lets you connect to any PostgreSQL-compatible endpoint — direct host, pgBouncer, RDS Proxy, or SSH tunnel — and navigate tables, inspect schemas, filter rows, edit data, and run arbitrary SQL queries, all without leaving your terminal.

pgview demo — table list, data view, fuzzy search, schema browser, and export

Features

k9s-style TUI

Navigable table list, data view, schema browser, and SQL editor — same interaction model as the Kubernetes CLI.

Connect Anywhere

host:port, pgBouncer, RDS Proxy, SSH tunnel, or a full postgres:// DSN. PgBouncer simple-query protocol supported.

Smart Filter DSL

Press / to filter rows with col=val, col=%sub%, comparisons, or free text. Array and JSONB columns match element-wise.

SQL Editor

Full-screen editor with schema-aware Tab completion — type-matched operators, table names in FROM/JOIN, column names in SELECT/WHERE.

SQL Templates

Ctrl+T opens a side panel of pre-filled Query, Write, and DDL templates built from the current table's real column and PK names.

Row Viewer & Editor

Press f to open a full-screen two-column view of the selected row. Edit any field in-place and commit with Ctrl+S.

Mouse & Touchpad

Vertical scroll moves row selection. Horizontal two-finger swipe pans wide column sets. Works in all table views.

Query History

Ctrl+R in the SQL editor shows the last 50 queries, most-recent-first. Press Enter to reload any entry.

Fuzzy Table Search

Press / in the table list for a full-screen fuzzy finder across all schemas. Matched characters highlighted in blue; ranked by consecutive runs and word boundaries.

Export to CSV / JSON

Press E (Shift+E) in the data view to export the full result set (no page limit) to a file. Interactive format + path prompt; NULL → empty string in CSV, null in JSON.

Schema Browser

Press d from the table list or data view to open a 4-tab panel: Columns, Indexes, Constraints, and a reconstructed DDL view. Navigate with 14 or Tab.

Multi-Arch Releases

Pre-built binaries for linux/amd64, linux/arm64, darwin/amd64, and darwin/arm64 on every GitHub release.

Want to try it right now?

Follow the step-by-step guide to spin up a local Postgres instance with Docker, load seed data, download the binary, and walk through every feature — no existing database required.

Try pgview →

Installation

Prerequisites

Go 1.22 or later — go.dev/dl

Download a binary

Pre-built binaries are available on the Releases page for linux and macOS (amd64 and arm64).

# macOS arm64 example
curl -L https://github.com/sibasismukherjee/pgview/releases/latest/download/pgview-darwin-arm64 \
  -o /usr/local/bin/pgview
chmod +x /usr/local/bin/pgview

Build from source

git clone https://github.com/sibasismukherjee/pgview.git
cd pgview
make build        # produces ./pgview

Install to PATH

make install      # go install — places binary in $(go env GOPATH)/bin

Connecting

# Interactive prompts for all connection details
pgview

# Host and port with explicit credentials
pgview -url myproxy.internal:5432 -username myuser -dbname mydb

# Full DSN (password embedded in URL)
pgview -url "postgres://myuser:secret@localhost:5432/mydb?sslmode=disable"

# Disable SSL for local development
pgview -url localhost -username postgres -dbname mydb -sslmode disable
Passwords are never stored. If omitted from the DSN, pgview prompts for them securely with no terminal echo.

CLI Flags

FlagDescriptionDefault
-urlPostgreSQL connection URL — host, host:port, or postgres://…prompted
-usernameDatabase usernameprompted
-passwordDatabase password (prompted securely if omitted)prompted
-dbnameDatabase namepostgres
-sslmodedisable | allow | prefer | requireprefer
-versionPrint version and exit

Table List

The default view after connecting. Lists all tables and views in the database, grouped by schema.

 pgview              │  <↵> view  <d> schema  <i> stats              │  Tables
 admin@mydb · local  │  </> search  <r> refresh  <e> SQL  <q> quit  │  public
──────────────────────────────────────────────────────────────────────────────────────
  schema    table                   type
  public    orders                  BASE TABLE
  public    products                BASE TABLE
▶ public    customers               BASE TABLE
  reporting monthly_totals          VIEW
KeyAction
/ Move selection
EnterOpen data view for the selected table
dOpen schema browser (Columns, Indexes, Constraints, DDL)
iShow table stats (estimated row count, PK, index count)
/Fuzzy search across all schemas and tables
rRefresh the list
eOpen SQL editor
qQuit

Fuzzy Table Search

Press / from the table list to open a full-screen fuzzy finder that searches across all schemas simultaneously. Results update as you type.

 pgview              │  <↵> open  <Esc> cancel  │  <↑↓> navigate  │  type to filter all schemas
 admin@mydb · local  │
──────────────────────────────────────────────────────────────────────────────────────
 / ord
──────────────────────────────────────────────────────────────────────────────────────
   public.orders
   public.order_items
   reporting.daily_order_summary
KeyAction
Type charactersFilter all schemas and tables by fuzzy match (subsequence)
/ Navigate results
EnterOpen selected table's data view
EscClose and return to table list

Matched characters are highlighted in blue. Schema names shown in muted gray, table names in white. Results are ranked by match quality — consecutive character runs and word-boundary hits score higher than scattered matches.

Data View

Shows rows of the selected table, 200 per page. Type-aware cell colouring: numbers, booleans, UUIDs, timestamps, JSON, and NULL each have a distinct colour.

 pgview              │  <Esc> back  <g> top  <G> bottom  │  <n>/<p> page  │  </> filter  │  Data  public.customers
 admin@mydb · local  │  <d> schema  <f> row view/edit  <E> export  <i> stats  │  42 rows  ~1.2K est · PK: id
──────────────────────────────────────────────────────────────────────────────────────────────────────────────
  id    name              status    created_at           tags
▶ 1     Alice Johnson     active    2024-01-15 09:23:11  {platform,growth}
  3     Carol White       active    2024-03-19 11:02:44  {platform,api}
  7     Eve Martinez      active    2024-05-01 16:14:09  {growth}

 WHERE "status"::text ILIKE 'active'
KeyAction
/ Move row selection
n / pNext / previous page (200 rows per page)
g / GJump to top / bottom of current page
/Open filter prompt
fOpen row viewer / editor
dOpen schema browser for this table
EExport full result set to CSV or JSON (interactive format + path prompt)
iRefresh table stats
rRe-run current query
eOpen SQL editor (pre-filled with last query)
EscBack to table list (clears filter)

Filter DSL

Press / in the data view to open the filter prompt. Terms are whitespace-separated and AND-ed together.

InputBehaviour
col=valExact match — ILIKE 'val' for scalars, 'val' = ANY(col) for arrays
col=%val%Substring match — element-wise for arrays and JSONB
col!=valNegation
col>val / col>=valNumeric or date comparison
name="john doe"Quote values that contain spaces
freetextSearch across all columns with ILIKE '%freetext%'
Array columns (text[], int[], uuid[]) and JSONB columns are detected automatically from PostgreSQL OIDs and matched element-wise rather than casting the whole value to text.
# Show only active rows with a specific tag
/ status=active tags=platform

# Date range on a timestamp column
/ created_at>=2024-01-01 created_at<2025-01-01

# Free-text search across all columns
/ johnson

Export to CSV / JSON

Press E (Shift+E) from the data view to start an interactive two-step export flow. Works for both table browse and SQL query results.

StepPromptNotes
1export format:Type csv or json, press Enter
2export to:Pre-filled with ~/export_<table>_<timestamp>.<ext>; edit path, press Enter
The export re-runs the current query without LIMIT or OFFSET so all rows are written to the file, not just the visible page. Success or error is shown in the footer bar.

NULL values are written as an empty string in CSV and as null in JSON.

Row Viewer & Editor

Press f in the data view to open a full-screen two-column table showing every column of the selected row alongside its value.

 Row Viewer  <e>/<↵> edit  <Ctrl+S> save  <Esc> close  · public.customers · row 1
─────────────────────┬──────────────────────────────────────────────────────────
 Column              │ Value
─────────────────────┼──────────────────────────────────────────────────────────
 id                  │  1
 name                │  Alice Johnson
▶ status             │  active                              (edited)
 created_at          │  2024-01-15 09:23:11
 tags                │  {platform,growth}
─────────────────────┴──────────────────────────────────────────────────────────

 1 unsaved change(s) — Ctrl+S to save, Esc to discard

 edit status  ▏ inactive▌
KeyAction
/ Navigate fields
e / EnterEdit the selected field (input bar pre-filled with current value)
Ctrl+SSave — runs UPDATE … SET … WHERE pk = … and refreshes the data view
EscClose and return to data view

Modified fields are highlighted in teal with an (edited) marker. The footer shows a count of unsaved changes. Type NULL (any case) to set a field to SQL NULL.

The WHERE clause always uses the original primary-key value loaded from the database, so editing a PK column itself is safe — the correct row is still targeted.

Schema Browser

Press d from the table list or data view to open a four-tab panel for the selected table. Navigate tabs with 14 or Tab / Shift+Tab.

 pgview              │  <1> Columns  <2> Indexes  <3> Constraints  <4> DDL  │  Schema  public.customers
 admin@mydb · local  │  <Tab> next tab  │  <↵> view data  <e> SQL  <Esc> back  <q> quit
─────────────────────────────────────────────────────────────────────────────────────────
 [1] Columns   [2] Indexes   [3] Constraints   [4] DDL
──────────────────────────────────────────────────────────
  Column       Type                    Nullable   Default
  id           bigint                  NOT NULL
  name         character varying(120)  NOT NULL
▶ status       text                    NULL       'active'
  created_at   timestamp with tz       NOT NULL   now()
  tags         text[]                  NULL

The DDL tab (4) shows a reconstructed CREATE TABLE statement using accurate type names from pg_catalog.format_type, inline constraints, and standalone CREATE INDEX statements for non-primary indexes:

 [1] Columns   [2] Indexes   [3] Constraints   [4] DDL
──────────────────────────────────────────────────────────
 CREATE TABLE "public"."customers" (
   "id"          bigint  NOT NULL  DEFAULT nextval('customers_id_seq'),
   "name"        character varying(120)  NOT NULL,
   "status"      text  DEFAULT 'active',
   "created_at"  timestamp with time zone  NOT NULL  DEFAULT now(),
   "tags"        text[],
   CONSTRAINT "customers_pkey"  PRIMARY KEY  (id),
   CONSTRAINT "customers_status_check"  CHECK  (status = ANY (ARRAY['active','inactive']))
 );

 CREATE INDEX idx_customers_status ON public.customers USING btree (status);
KeyAction
1Columns tab — name, type, nullability, default
2Indexes tab — name, unique/primary flags, method, definition
3Constraints tab — name, type (PK / FK / UNIQUE / CHECK), definition
4DDL tab — reconstructed CREATE TABLE with constraints and indexes
Tab / Shift+TabCycle forward / backward through tabs
EnterView data rows for this table (Columns, Indexes, Constraints tabs)
eOpen SQL editor
EscBack to table list
qQuit

SQL Editor

Press e from any view to open a full-screen SQL editor. When opened from the data view it is pre-filled with the last executed query.

 pgview              │  <Ctrl+E> run  <Tab> complete  <Ctrl+L> clear  <Esc> cancel  │  SQL Editor
 admin@mydb · local  │  <Ctrl+R> history  <Ctrl+T> templates                              │
──────────────────────────────────────────────────────────────────────────────────────────
  SELECT *
  FROM "public"."customers"
  WHERE status = 'active'
  LIMIT 100▌

Schema-aware Tab completion

Completion is clause-sensitive. Pressing Tab prioritises suggestions based on context:

  1. Type-matched operator when the previous token is a known column in WHERE/ON/HAVING — LIKE/ILIKE for text, >=/<= for timestamps, IS TRUE/IS FALSE for booleans, = ANY( for arrays, ->/->> for JSON
  2. Table name in FROM/JOIN context
  3. Column name in SELECT/WHERE/ORDER BY context
  4. SQL keyword or table name as fallback
KeyAction
Ctrl+EExecute query; results replace the data view
TabContext-aware completion popup
Ctrl+TOpen templates panel
Ctrl+ROpen query history panel
Ctrl+LClear editor
EscCancel and return to previous view

Templates Panel

Ctrl+T opens a panel on the left side of the SQL editor. Templates are pre-filled with the current table's real column names, quoted identifiers, and primary-key column.

  Templates                  │
  ── Query ─────────────     │  SELECT *
   SELECT *                  │  FROM "public"."customers"
   SELECT cols               │  LIMIT 100▌
   SELECT WHERE              │
   COUNT                     │
  ── Write ─────────────     │
   INSERT                    │
   UPDATE                    │
   DELETE                    │
   UPSERT                    │
  ── DDL ───────────────     │
   ADD COLUMN                │
   DROP COLUMN               │
   CREATE INDEX              │
   ANALYZE                   │
   TRUNCATE                  │
CategoryTemplates
QuerySELECT *, SELECT cols, SELECT WHERE, COUNT
WriteINSERT, UPDATE, DELETE, UPSERT (ON CONFLICT)
DDLADD COLUMN, DROP COLUMN, CREATE INDEX, ANALYZE, TRUNCATE

Use / to navigate (category headers are skipped), Enter to load the template into the editor, Esc to return focus to the editor.

When opened from the table list with no active table, generic schema, table, and col1 placeholders are used.

Query History

Ctrl+R in the SQL editor opens a navigable history panel showing the last 50 queries, most-recent-first. Press Enter to load a query back into the editor, or Esc to close without loading.

Mouse & Touchpad

All table views (table list, data view, schema browser) support scroll gestures:

GestureAction
Mouse wheel up / two-finger swipe upMove row selection up
Mouse wheel down / two-finger swipe downMove row selection down
Two-finger swipe left / WheelLeftPan columns left (wide result sets)
Two-finger swipe right / WheelRightPan columns right

The SQL editor's text area handles its own scroll natively and is unaffected by the global capture.

Full Keyboard Reference

Table List

KeyAction
/ Move selection
EnterView data rows
dOpen schema browser
iTable stats (estimated rows, PK, index count)
/Fuzzy search across all schemas and tables
rRefresh list
eOpen SQL editor
qQuit

Fuzzy Search

KeyAction
Type charactersFilter all schemas and tables
/ Navigate results
EnterOpen selected table's data view
EscClose, return to table list

Data View

KeyAction
/ Move row selection
n / pNext / previous page (200 rows)
g / GTop / bottom of page
/Filter prompt
fRow viewer / editor
dOpen schema browser
EExport to CSV or JSON
iTable stats
rRe-run query
eSQL editor
EscBack to table list

Row Viewer / Editor

KeyAction
/ Navigate fields
e / EnterEdit selected field
Ctrl+SSave changes (UPDATE)
EscClose, return to data view

Schema Browser

KeyAction
1Columns tab
2Indexes tab
3Constraints tab
4DDL tab
Tab / Shift+TabCycle forward / backward through tabs
EnterView data rows
eSQL editor
EscBack to table list
qQuit

SQL Editor

KeyAction
Ctrl+EExecute query
TabSchema-aware completion
Ctrl+TTemplates panel
Ctrl+RQuery history
Ctrl+LClear editor
EscCancel, go back

Makefile Targets

TargetAction
make buildCompile binary to ./pgview
make installInstall to $(go env GOPATH)/bin
make runBuild and launch interactively
make testRun all unit tests with -race
make lintRun golangci-lint
make tidygo mod tidy
make cleanRemove build artefacts

Contributing

Contributions are welcome. The short version:

  1. Search or open an Issue first
  2. Fork → branch from main → PR
  3. Tests and lint must pass — CI runs automatically on every PR

See CONTRIBUTING.md for the full guide, CODE_OF_CONDUCT.md for community standards, and SECURITY.md for reporting vulnerabilities privately.

License

pgview is released under the MIT License. Use it freely in personal and commercial projects.