Skip to main content
PostgresVFS connects to a Postgres database via a DSN and exposes its schemas and tables as a tree the agent can list, read, and grep. Install the extra:

Config

For DSN format and permissions, see Postgres Setup. To inspect data, run find /pg/ -name rows.jsonl, then head -n 3 on a returned path. Fields marked secret are redacted in snapshots.

VFS.md

The VFS.md an agent reads with Postgres mounted at /<path>.

Virtual Filesystem

/<path> layout

Supported Unix Commands for VFS

Unix commands work on each path as on a local filesystem, as far as the path supports them:

Limitations of Unix Commands for VFS

Where a path differs from a local filesystem:Run man <cmd> or <cmd> --help for one command’s usage.

Mount mode

read only. Postgres mounts are read-only at the VFS level.

Snapshot behavior

The DSN is redacted on snapshot. Hand the mount back at load (mounts=, or a config over the server and CLI).

File size and du

rows.jsonl is rendered on demand. stat -c %s and ls -l show - when its rendered byte length is unknown; physical table storage is never used as a file size. stat checks existence and type without fetching columns, row counts, or relation sizes. Planner counts cannot identify content changes, so they are not used as a content fingerprint. The metadata JSON files expose explicitly named row and storage estimates. Use wc -c rows.jsonl for the rendered byte count; reading the whole export is subject to the configured row and byte limits.

Integration

What PostgreSQL answers through its own API, so fewer files are read. Integration explains each command. For one plain text in a table’s or view’s rows.jsonl, grep and rg ask Postgres for the rows that hold it, with a LIKE over each column (ILIKE under -i), in the order a plain read returns them, and search those rows instead of the whole relation. A column is searched through its cast when a line spells it the same way: text, an integer, a boolean, a uuid, an enum, jsonb, char(n) for a text without a space, and an array of text, integers or uuids. A number, date or time column is left out when the text holds a character it never spells (ada in a float8). The file is read as usual when another column type is present (json, interval, bytea), when the text could lie inside one of those values, match a key, null or the JSON between values, or when more than max_read_rows rows match. Since only the matching rows are fetched, a relation too large to read can still be searched when the output shows no line numbers or context.