Objects and the DDL snapshot
The Objects side tab (Ctrl+Shift+D, Cmd+Shift+D on macOS) shows the connected database as a tree. Behind the tree is a directory of DDL files, one per object, grouped per schema by object type and rendered from PostgreSQL's own decompilers: the DDL snapshot. The tree reads those files, and so do completion, hover, the psql commands and the generated scripts, which is why none of them hammer the catalog.
A dump you can trust
The snapshot is proven to re-execute. A test matrix boots one server per supported major, PostgreSQL 13 through 18, plus a TimescaleDB and a Citus server, and checks that every rendered file executes again on the server it came from, that a snapshot of the replayed database is identical byte for byte, that the dictionary matches the catalog and that two builds never differ.
The object families: tables, views, materialized views, sequences, indexes, constraints, triggers, policies, rules, types, domains, functions, procedures, aggregates, extended statistics, foreign tables, foreign servers and foreign data wrappers, event triggers, publications and extensions, plus roles, ownership and privileges (schema.includeRoles, schema.includeOwner, schema.includePrivileges, all on by default, like pg_dump). Dependencies come from pg_depend unioned with a textual scan of the DDL, so "depends on" and "used by" also see inside routine bodies.
Statistics
Every row carries what the database already knows: a row estimate, size with indexes and TOAST, scans, dead rows, last vacuum and analyze, a routine's calls. Folders sum them, the tree sorts by size, and a table that dominates the database is marked. The numbers come from one cheap statement per connection, on their own clock (stats.staleAfter, an hour by default), cached to disk and labelled with their age. stats.show turns them off; each connection's editor can override it.
The refresh model
Builds are incremental and fingerprinted: a refresh rebuilds only the schemas whose fingerprint moved, and the row menu refreshes one object, one family or one schema. Your own DDL is caught the moment it runs (schema.refreshOnChange). For a shared server where other people change the structure, schema.autoRefresh polls on an interval, from 15 seconds to 5 minutes, off by default. A snapshot older than schema.staleAfter (12 hours) is rechecked on the next open. System catalogs are rendered once per server release into a shared store. Each connection's Snapshot section can override any of this.
Session-only objects
Every tab is a dedicated backend and the object browser borrows it, so a CREATE TEMP TABLE reaches the tree as a TEMP TABLE row and completes its columns. Inside an open transaction, a table created after BEGIN shows on the "New in this session" shelf with a hollow amber dot until COMMIT settles it or ROLLBACK removes it. That read goes through your transaction behind a savepoint, so a refresh can never abort your work; schema.refreshInTx is the veto.
Reading the DDL
A click opens an object's DDL viewer with its statistics on top, a Browse Data button on a table and a Documentation button on a catalog or extension object. A folder opens as one folding document with a code lens per object. Hover on a row shows the object's comment, and a table's columns and a routine's parameters disclose under a chevron.
Because the snapshot is files, Search in Files (Ctrl+Shift+F) searches the DDL as a scope: where a column is used across every view, function and trigger is a local search with no query and no connection. Replace never writes into the snapshot.
Scripts from the row menu
The row menu writes the statements one writes about an object over and over. A table gets select, select with its foreign keys joined two levels out, count, the insert, update and delete matrix with every ON CONFLICT action and RETURNING variant (and MERGE where the server has it), create index, rename, analyze, vacuum, grant, revoke, alter, truncate and drop. A view gets its select, a materialized view its refresh, a function its call, a sequence its nextval, setval and restart, every droppable object a drop, every object its COMMENT ON. Script opens the text in a temporary tab on the object's connection; Copy Script puts it on the clipboard. Values a template cannot know are $1..$n, so Run asks for them.
Edit Comment opens one form with the object's comment and every column's, prefilled; Save writes one COMMENT ON per changed field and re-renders the object, so the tree, the hovers and completion carry the new text at once.
Filter, find, pins and hides
The Object filter window narrows a connection's tree per schema and object type, and unchecking a row hides it; the Object find window searches names, comments, columns and parameters. The row menu pins an object to the top and hides one at any ancestor level. A Frequent shelf ranks by frecency, big folders open capped at 200 rows with "Show N more", and the tree follows the editor's cursor (schema.followCursor). All of it is remembered per workspace and per connection.
plumesql dump-tree
The same renderer works from the command line:
sh
PGDATABASE=mydb plumesql dump-tree -out objectswrites every object of the database to objects/<schema>/<type>/<name>.sql, byte for byte as pg_restore prints it, ready for a repository or a diff.
TimescaleDB, Citus, PostGIS, pgvector
An extension that changes what a table is gets read the way the catalog is read. TimescaleDB hypertables lead with HYPERTABLE and continuous aggregates with CAGG; the hover says the time column, the chunk interval and whether compression is on, and the DDL file carries the create_hypertable call, compression settings and policies. Citus distributed tables lead with DISTRIBUTED and reference tables with REFERENCE; the file carries create_distributed_table with its co-location, or citus_schema_distribute for a distributed schema. @for hypertable, @for continuous aggregate, @for distributed table and @for reference table attach extensions to exactly those rows, and starter folders ship for TimescaleDB, Citus, pg_cron and pg_partman.
PostGIS geometries decode client side into sketches with their validity, and pgvector values into cards with a sparkline, in the grid (see Results). Every extension's own objects enter the dictionary for completion and hover but write no file: they replay inside their CREATE EXTENSION.