A PostgreSQL application-cloning CLI for local development and refresh workflows.
pgcopycat is a Go CLI that clones the application layer of a PostgreSQL database by orchestrating native PostgreSQL tools such as pg_dump, pg_restore, and psql. It is built for developer workflows where you want a usable local copy of an application database without attempting a full administrative cluster clone.
- Schemas
- Tables and columns
- Primary keys
- Foreign keys
- Constraints
- Indexes
- Sequences
- Views
- Functions and triggers present in the application dump
- Data, depending on the selected clone mode
- PostgreSQL roles and users
- Ownership restoration
- Grants and ACL management
- Cluster-wide administration
- Continuous replication
- Incremental synchronization
- Clone modes:
full,schema-only,data-only - Interactive mode when launched without arguments
- Non-interactive execution with flags
- Reusable YAML profiles
- Automatic profile discovery
- Early checks for required PostgreSQL client tools
- Pre-checks for connectivity, target safety, filters, and extensions
- Optional extension creation on the destination database
- Sequence resynchronization after data restore
- Text and JSON reporting
- Local profile saving before execution
- Go 1.25+
- PostgreSQL client tools available in
PATHpg_dumppg_restorepsql
Build a local binary in the current directory:
go build -o pgcopycat ./cmd/pgcopycat
./pgcopycatInstall it into your Go bin directory:
go install ./cmd/pgcopycatIf needed, add your Go bin directory to PATH:
export PATH="$HOME/go/bin:$PATH"On macOS, if PostgreSQL client tools are missing, pgcopycat can guide you toward installing them with Homebrew.
Run the interactive workflow:
./pgcopycatCreate an example config:
./pgcopycat initRun from a config file:
./pgcopycat run --config ./pgcopycat.ymlRun from a saved profile:
./pgcopycat run --profile local-refreshRun checks only:
./pgcopycat check --config ./pgcopycat.ymlpgcopycat
pgcopycat run --config ./pgcopycat.yml
pgcopycat run --profile local-refresh --yes
pgcopycat check --config ./pgcopycat.yml
pgcopycat profiles
pgcopycat init
pgcopycat version
The recommended example file is examples/pgcopycat.yml.
Main configuration sections:
source: source PostgreSQL connectiondestination: destination PostgreSQL connectionclone: clone mode, target strategy, sequence reset behaviorfilters: schema and table inclusion or exclusion rulesextensions:check,ensure, orignoreexecution:dry_run,verbose,yesreport: output format and optional report file
Important fields:
clone.mode:full,schema-only,data-onlyclone.target_mode:safe,drop-schemasclone.reset_sequences: resynchronize owned sequences after data restorefilters.exclude_tables: remove table structure and data from the dumpfilters.exclude_table_data: keep structure but skip data for selected tablesextensions.mode: verify only, auto-create, or ignorereport.format:textorjson
For local development, pgcopycat supports plain-text passwords directly in config files:
source:
user: postgres
password: postgresEnvironment-variable based passwords are still supported with password_env if you prefer them.
Local configuration files may contain plain-text passwords. The repository ships with a .gitignore that excludes:
pgcopycat.ymlpgcopycat.yaml.pgcopycat/*.yml.pgcopycat/*.yaml
Do not commit personal or environment-specific database credentials.
When started without arguments, pgcopycat follows this flow:
- Checks for
pg_dump,pg_restore, andpsqlbefore asking for database details - If tools are missing, shows an alert and proposes installation guidance
- Scans for saved local and global profiles
- Lets you select a profile or continue with manual configuration
- Prompts for source and destination connection details, with examples
- Asks whether exclusions should be configured before asking exclusion details
- Detects missing destination extensions and can propose auto-creation
- Offers to save a manual configuration before execution
- Shows a final summary and asks for confirmation
When pgcopycat starts without explicit --config or --profile, it scans:
./pgcopycat.yml./pgcopycat.yaml./.pgcopycat/*.yml./.pgcopycat/*.yaml~/.config/pgcopycat/profiles/*.yml~/.config/pgcopycat/profiles/*.yaml
If profiles are found and stdin is interactive, the CLI proposes launching one directly or continuing with manual configuration.
If you save a manual configuration, pgcopycat suggests a path such as:
./pgcopycat.yml./.pgcopycat/local-refresh.yml
Saved configs are discovered automatically on the next startup and can also be launched directly:
./pgcopycat run --config ./.pgcopycat/local-refresh.yml
./pgcopycat run --profile local-refreshsafetarget mode refuses to restore into non-empty target schemas- Source and destination identity are checked before execution
- Missing PostgreSQL client tools are detected before database questions
- Missing destination extensions are surfaced during pre-checks
- Confirmation is required before destructive operations unless
--yesis provided - Local config files are ignored by Git by default
Every run prints a final report that includes:
- Profile or config file used
- Source and destination summaries
- Clone mode and target mode
- Included and excluded schemas
- Excluded tables and excluded table data
- Extension verification or creation status
- Sequence reset status
- Step results
- Warnings, errors, duration, and final status
Optional file output can be enabled with report.output_file and report.format.
Run the test suite:
go test ./...The project currently uses:
cobrafor the CLIyaml.v3for configurationsurvey/v2for interactive promptspgx/v5for PostgreSQL access during checks and post-restore operations
Contributions are welcome. Start with CONTRIBUTING.md for development setup, pull request expectations, and review guidance.
For security-related issues, do not open a public issue first. Please read SECURITY.md.
This project is licensed under the Apache License 2.0. See LICENSE.
