
pgman
io.github.tombaldwin/pgman
PostgreSQL for coding agents: schema, read-only queries, EXPLAIN, masked dumps, confirmed writes.
Documentation
pgman
A k9s-style terminal UI for PostgreSQL 10 and newer, wherever it runs:
every database in every environment on one screen, guarded queries,
safe migrations, masked copies of production, and logs turned back into
runnable SQL (Postgres server logs, Hibernate logs and pasted JDBC,
offline, with N+1 detection). Teams on AWS or the JVM get extras: RDS
and Aurora discovery, Secrets Manager, bastions, and connections from
Spring and IntelliJ. Sibling project to
ebman.
⚠️ Beta
pgman is beta — expect rough edges and breaking changes. It defaults to read-only connections and routes every write through per-statement safety guards, but don't point it at a production database without reviewing your
safety.tomlfirst. Bug reports and feedback very welcome — open an issue.Install:
brew install tombaldwin/tap/pgmanorcargo install pgman --locked(more) · try it with no database:pgman --demo.

Captured from
pgman --demo, the synthetic-data mode baked into the binary (no database needed). Regenerate after a code change withvhs demo.tape.
At a glance:
- Every environment on one screen —
Elists each environment's databases (dev, staging, prod…) with replicas under their primary, from RDS, docker or hand-listed connections, without connecting.Enterconnects (replicas read-only, the password read from AWS Secrets Manager at that moment, through the bastion when there is one); opt-in probes add versions, migration level, pending patches, lag, sessions and size;pgman env discoverproposes the whole file from an AWS account. Seedocs/environments.md. - Applying patches —
Pplans an environment's pending patches read-only, checks each against your guard rails, and after you confirm runs each in its own transaction; a dry run or a throwaway copy rehearses it first;pgman applydoes the same from the command line, andpgman runruns a script that manages its own transactions (docs/run.md).lshows the RDS server's recent errors. - Dump and restore —
pgman dump staging/ledgerruns your ownpg_dumpthrough pgman's connection (from the replica, the password read at that moment, through the bastion; nothing secret on a command line or on disk), andpgman restoreputs it into a local database, never a protected one. Production is dumped masked — emails, names, phones and free text replaced as they are read, joins intact — and every copy is tracked until it is deleted (pgman copies). Seedocs/dump-restore.md. - For your coding agent —
pgman mcp servegives Claude Code (or any MCP client) read-only tools for queries, lock pre-flights, pending patches, schema lint and environments, plusapply_patches,dumpandrestore, each confirmed by you. Seedocs/mcp.md. - Connect fast — auto-discovers datasources from Spring
application*.yml/.properties, IntelliJ.idea/dataSources.xml, and a committed.pgman/pgman.toml. - Logs / pasted code → runnable SQL — Hibernate logs, Postgres/RDS server logs, and pasted JDBC, with N+1 detection — see "Logs and pasted code → runnable SQL" below.
- Safe by default — read-only connections,
statement_timeout, and per-database guard rails on every statement. - Edit and page results —
uon a result cell edits it in place: a one-rowUPDATEby primary key, shown in the same safety confirm as any statement you run.Mfetches the next 1000 rows of aSELECTthrough a server-side cursor. - Editor — syntax highlighting, completion, formatting, history, saved
queries (
:paramprompts, rename, search), DBUnit fixture apply + capture. - DBA panels — schema browser, EXPLAIN tree, slow queries, active sessions/locks, schema-lint wizard with a config advisor (RDS / Aurora parameter names), result diff.
- JDBC tap — live app-side queries from any JVM over OpenTelemetry, with hotspots and live N+1 detection. A dedicated Java library adding per-caller, per-pool and per-transaction views is planned.
- Screenshots —
--demoruns the whole tool against a synthetic billing database, and--redactblocks out hosts, accounts and server names on a real one.
Logs and pasted code → runnable SQL
Point it at a Postgres database, then turn logs and pasted code into runnable SQL:
- Hibernate logs → runnable SQL. Reconstruct executable statements from
org.hibernate.SQLlines plus the separately-logged bind parameters. Needs bind-parameter trace logging turned on (org.hibernate.orm.jdbc.bindatTRACEon Hibernate 6,org.hibernate.type.descriptor.sql.BasicBinderatTRACEon Hibernate 5) — without it you still get the statement, just with?placeholders instead of substituted values. - Postgres / RDS server logs → runnable SQL. Reconstruct from
log_statementoutput plusDETAIL: parameters: $1 = …lines (the more reliable source — it needs no application redeploy). - Pasted JDBC → runnable SQL. No log needed — a
?-placeholder statement plus a typed parameter list (TYPE:valueper line) reconstructs the same way. - N+1 detection. Cluster reconstructed queries by shape to surface loop-driven selects.
Three ways in: paste a log into the editor, press ctrl-l (or F8), pick a
query — Enter loads it terminated with ;, and a second Enter runs it; skip
the paste and launch straight into the reconstructed queries with
pgman --log app.log; or, with no log at all, paste a ?-placeholder
statement plus its typed parameter list. Walkthrough:
docs/logs-to-sql.md.
Run it inside a Spring project and it picks up spring.datasource.* to connect.
Project config (commit this)
Drop a .pgman/pgman.toml at the root of your repo. pgman walks up from the
current directory to find it, so launching pgman from any subdirectory of
the project works.
# .pgman/pgman.toml — commit this. No passwords here.
# Passwords come from the variable a connection's password_env names.
# PGPASSWORD is only used with --dsn, never for a discovered connection.
[[connections]]
name = "local"
url = "postgres://postgres@localhost:5432/myapp"
[[connections]]
name = "staging"
url = "postgres://stg-db.internal:5432/myapp"
user = "app"
password_env = "STAGING_DB_PASSWORD" # env var holding the password
# Per-database safety overrides. These can only TIGHTEN your personal
# `~/.config/pgman/safety.toml` — a committed file can't relax your guard
# rails. Commit just `[safety.databases.production]` and your own defaults
# still apply everywhere else.
[safety.databases.production]
read_only = true
statement_timeout_ms = 5000
Project connections show up in the startup picker alongside any IntelliJ
data sources found in .idea/dataSources.xml. Nothing in that picker
connects until you choose it — see Safety.
Safety
pgman connects to production databases. It opens read-only by default, enforces
a statement_timeout, classifies every statement, and applies per-database
guard rails — e.g. block DROP, confirm TRUNCATE /
unqualified DELETE, and wrap DML in a transaction you can roll back. (This is
a guard rail, not a replacement for least-privilege database roles — scope the
role you connect with.)
Three things worth knowing:
- Running pgman inside a checkout you did not write is a trust decision.
pgman discovers connections from files in the working tree, so nothing it
finds there connects without a keypress,
PGPASSWORDis only used with--dsn, and a project's[safety]block can only tighten your own guard rails — never relax them. Full trust model in docs/safety-and-privacy.md. - TLS:
sslmode=require/preferencrypt the connection but do not verify the server certificate (matching libpq). Usesslmode=verify-fullon untrusted networks.sslmode=verify-cachecks the chain but not the hostname, as libpq does. - JDBC tap: the
--tap-listen/--tap-otlp/--tap-udplisteners are unauthenticated and bind to127.0.0.1by default. Only bind a non-loopback address on a trusted/firewalled network. See docs/tap.md.
Install
Homebrew (macOS / Linux):
brew install tombaldwin/tap/pgman
On Homebrew 6 or newer, run brew trust tombaldwin/tap first: Homebrew
only loads formulae from taps you have trusted.
It brings libpq, whose pg_dump and pg_restore pgman dump and
pgman restore run.
Cargo:
cargo install pgman --locked
pgman dump and pgman restore also need PostgreSQL's client tools:
brew install libpq on macOS, apt install postgresql-client on
Debian/Ubuntu.
Pre-built binary: download the tarball for your platform (Linux and
macOS, x86_64 and arm64) from the
releases page, check
the *.sha256 next to it, extract, and put pgman on your PATH. Each
tarball also carries a build-provenance attestation:
gh attestation verify pgman-*.tar.gz --repo tombaldwin/pgman.
Then try it with no database: pgman --demo.
To hack on it, install from a checkout:
cargo install --path . --locked
The binary lands at ~/.cargo/bin/pgman, which is on $PATH if your shell
sources ~/.cargo/env (rustup does this for you).
Upgrade
pgman --upgrade
Works in place for a checkout (git pull + cargo install --path .), a
crates.io cargo install install, and a Homebrew install. An install made
with cargo install --git … isn't one of these: re-run that
cargo install --git command to upgrade it. A standalone binary (a downloaded release tarball) has no
in-place upgrade — --upgrade prints the
releases page instead.
pgman also checks crates.io for a newer release at most once every six hours
and shows a header badge when one exists. Turn that off with
--no-update-check (or PGMAN_NO_UPDATE_CHECK); it never blocks startup and
degrades silently if there's no network.
Testing
cargo fmt --all && cargo clippy --all-targets -- -D warnings && cargo test
See docs/development.md for the integration suite,
coverage, fuzzing, and what CI runs on every push.
Docs
docs/keys.md— every keybinding, by mode.docs/commands.md— command reference.docs/configuration.md— config file locations and options.docs/environments.md— the environments view,environments.tomlandpgman env discover.docs/run.md—pgman run, scripts with their own transactions and\c.docs/dump-restore.md—pgman dumpandpgman restore.docs/mcp.md—pgman mcp serve, the MCP server for coding agents.- MCP Registry name:
mcp-name: io.github.tombaldwin/pgman docs/safety-and-privacy.md— safety guard rails, what's stored locally.docs/privacy.md— what pgman does with copies of personal data, for a client's DPO.docs/logs-to-sql.md— the logs → runnable SQL walkthrough.docs/tap.md— the JDBC tap: OpenTelemetry, TCP and UDP ingest, the event format, limits, record and replay.docs/development.md— build / test / clippy + distribution notes.ARCHITECTURE.md— module map and the invariants the compiler doesn't enforce.
Status
Beta. See BACKLOG.md for what's next.
License
Dual-licensed under either of
- MIT license (LICENSE-MIT)
- Apache License, Version 2.0 (LICENSE-APACHE)
at your option. Unless you explicitly state otherwise, any contribution you submit for inclusion shall be dual-licensed as above, without additional terms.
Built by Polymorphism Ltd. pgman is one of the tools we build for ourselves and our clients — if you want this kind of internal developer tooling for your team, get in touch.
pgmancargo install pgmanRelated Servers
io.github.tombaldwin/candor
Per-function effect analysis for agents: blast radius, what reaches the network, gate verdicts.
io.github.tombaldwin/ebman
MCP server for AWS Elastic Beanstalk: read the fleet; --allow-writes adds two-phase writes.
io.github.tombaldwin/nattermatic
AI agents on different Claude accounts and machines message each other. Wakes idle sessions.