Overview

Persistent PostgreSQL client for AI agents — SQL-native JSONL in, JSONL out.

Supported platforms: macOS, Linux, Windows.

Install

brew install agentfirstkit/tap/afpsql   # macOS/Linux
scoop bucket add agentfirstkit https://github.com/agentfirstkit/scoop-bucket && scoop install afpsql  # Windows
cargo install agent-first-psql     # any platform

Optional local psql wrapper:

afpsql psql status
afpsql psql install
afpsql psql uninstall

By default, afpsql psql install writes the wrapper next to the afpsql executable, for example ~/.cargo/bin/psql after cargo install. Use --bin-dir to choose a different directory:

afpsql psql install --bin-dir ~/.local/bin
afpsql psql status --bin-dir ~/.local/bin

The wrapper is managed only when it contains the afpsql marker generated by afpsql psql install; existing system psql binaries are not overwritten or removed.

psql is optimized for humans in a terminal. Agents need stable machine-readable structures, connection reuse, and streaming for large result sets.

afpsql is a long-lived process with SQL-native protocol events:

Modes

Contract

afpsql has one Agent-First Data runtime protocol and two CLI entry styles:

  1. agent-first CLI mode (default)
  2. psql mode (CLI translation layer only)

psql mode scope:

Out of scope in psql mode:

Secure Parameters (Default)

JSON transport does not imply SQL safety. afpsql uses positional parameter binding:

{"code":"query","id":"q1","sql":"select * from users where id = $1 and status = $2","params":[123,"active"]}

Canonical protocol shape:

CLI binding syntax:

In psql mode, translation may also accept numeric -v entries and map them to agent-first params by position.

Not supported:

Connection Inputs

Canonical agent-first connection fields:

psql mode accepts legacy CLI connection flags and translates them to the same agent-first fields.

For CLI use, secrets can also be read from environment variables without putting their values in shell history:

afpsql --dsn-secret-env DATABASE_URL --sql "select 1"
afpsql --password-secret-env PGPASSWORD --host localhost --sql "select 1"

Environment fallback (lowest precedence) also reads standard PostgreSQL variables:

Unix socket example using system PGHOST and only passing dbname in the command:

export PGHOST=/var/run/postgresql
export PGUSER=roger
afpsql --dbname appdb --sql "select current_database()"

See docs for details:

License

MIT