Local-first PostgreSQL CLI and TUI for dumping, restoring, and cloning databases.
Español
Choose your path:
| If you want to… | Start here |
|---|---|
| Clone your database first | Quick start: clone — install, add a .env, run dolly clone. |
| Work interactively | dolly tui — connect, inspect schemas, dump, and clone from a real terminal. |
| Script dump or restore | dolly dump, dolly restore, and dolly clone — use a DSN or saved connection. |
dolly tui has no flags, requires a TTY, and reads config.jsonc from the current directory.
Installers download the matching GitHub Release asset and verify it against that release's checksums.txt before installing it.
curl -fsSL https://raw.githubusercontent.com/VicenteOlmos/dolly/main/install.sh | shPin a release:
curl -fsSL https://raw.githubusercontent.com/VicenteOlmos/dolly/main/install.sh | DOLLY_VERSION=0.3.5 shDefault install path: /usr/local/bin. Set DOLLY_INSTALL_DIR to install elsewhere.
irm https://raw.githubusercontent.com/VicenteOlmos/dolly/main/install.ps1 | iexPin a release:
$env:DOLLY_VERSION="0.3.5"; irm https://raw.githubusercontent.com/VicenteOlmos/dolly/main/install.ps1 | iexDefault install path: %LOCALAPPDATA%\Programs\dolly\bin; the installer adds it to your user PATH.
| Topic | Detail |
|---|---|
| Latest release | Installers default to the latest GitHub Release. |
| Pin a version | Set DOLLY_VERSION (for example 0.3.5) in the install command above. |
| SemVer tags | Release tags follow vX.Y.Z. Only the latest release receives security fixes. |
| Immutable assets | Tags and release archives are never overwritten — use a new patch tag for fixes. |
| Checksums | Each release ships checksums.txt; installers verify archives before install. |
go install github.com/VicenteOlmos/dolly/cmd/dolly@latest
# or from a checkout:
go build -buildvcs=false -o ./bin/dolly ./cmd/dolly- Install Dolly using the Install steps above.
- In your project directory, create a
.envfile with a compatible connection. UseDB_URLor discreteDB_HOST,DB_PORT,DB_NAME,DB_USER, andDB_PASSWORDvariables:
DB_URL='postgres://user:pass@localhost:5432/mydb?sslmode=disable'
# or discrete vars:
# DB_HOST=localhost
# DB_PORT=5432
# DB_NAME=mydb
# DB_USER=user
# DB_PASSWORD=pass- Run:
dolly cloneDolly discovers .env in the current working directory when resolving the source database. On Unix, if the file has broad permissions (group/other readable), Dolly emits one warning and continues without changing bytes, mode, owner, or timestamps on that file.
For scripted clone with config defaults:
dolly clone -ffOptional: dolly config init writes config.jsonc for target URL, clone naming, strategies, and other defaults.
Owner-only permissions (for example chmod 600 .env) are recommended for secret files. Dolly does not require or modify permissions on external .env files it discovers.
Create optional local configuration, then choose the interactive or scriptable route.
dolly config init
dolly tuiFor dump and restore without cloning, pass a PostgreSQL DSN:
export DB='postgres://user:pass@localhost:5432/mydb?sslmode=disable'
dolly dump --dsn "$DB" --output ./dolly_dump
dolly dump --dsn "$DB" --schemas app,public --output ./dolly_dump
dolly dump list --output ./dolly_dump
dolly restore --dsn "$DB" --input ./dolly_dump/1 --on-conflict skipDolly does not inspect your database size or network conditions, and it does not auto-tune. Treat sizes and speeds as qualitative—hardware, schema shape, row width, and latency all affect outcomes.
Not sure what to pick? Run dolly tui for guided choices. On the CLI, omitting optimization flags keeps safe serial defaults (workers=1, transactional restore).
| Situation | Recommendation | Why | Tradeoff |
|---|---|---|---|
| Unsure / want the safest path | dolly dump --dsn "$DB" --output ./dolly_dump → dolly restore --dsn "$TARGET_DB" --input ./dolly_dump/1 |
One worker by default; restore stays transactional and atomic | Slower than parallel modes on large databases |
| Small database, straightforward copy | dolly dump --dsn "$DB" --output ./dolly_dump |
Full dump with minimal flags | Gets slower as data grows |
| Very large named tables where resumability matters more than speed | dolly dump ... --chunk-table public.large_table --workers 1 |
PK or eligible unique-key plans use resumable keyset chunks | Tables without a safe key use a warned, non-resumable normal stream |
| Large data, slow or unreliable link | dolly dump ... --slow-connection --workers 1 |
Safe per-table keys get checkpoints; no-safe-key tables still complete | Fallback tables are not resumable; mode is non-transactional and incompatible with subset and parallel dump |
| Large database, stable connection, maximum dump throughput | dolly dump ... --workers "$WORKERS" |
Shared consistent snapshot across parallel table workers | Tune empirically within 1–16; needs max_open_conns >= workers+1; excludes slow/chunk/subset/--no-transaction |
| Maximum restore throughput | ADVANCED — NON-ATOMIC dolly restore ... --workers "$WORKERS" --no-transaction --yes --ack-partial-state |
Parallel table restore after acknowledging partial-state risk | No atomic rollback; on-conflict must be error; cannot use --replace, --trust-schema-sql, skip, or upsert |
| Dev/test sample, not a full copy | dolly dump ... --percent "$PERCENT" --max-rows-per-table "$ROW_CAP" |
Recent-root selection plus FK closure | Not statistically representative; closure may exceed the target percent |
| Fastest clone on the same instance | dolly clone --strategy template |
Template database copy on one PostgreSQL server | Source must have no active connections; unsanitized |
| Large single-database cross-server copy | dolly clone --strategy logical-stream |
Logical stream for large remote copies | Unsanitized; not a physical cluster copy |
$WORKERS, $PERCENT, and $ROW_CAP are operator-chosen values—Dolly does not set them automatically.
See dolly dump --help, dolly restore --help, and dolly clone --help for flags. Copyable recipes remain in Common workflows and limits.
| If you need… | Use | Do not use when |
|---|---|---|
| An exact table subset | --include-table / --exclude-table (or selector files) |
You need FK-closure percent sampling (--percent / --seed-file) |
| Resumable export of large named tables | --chunk-table with workers=1 |
The table lacks a safe PK/unique key and you require resume, or you need parallel dump workers |
| A consistent parallel export | --workers N (shared snapshot) |
--no-transaction, chunk/slow modes, or subset policies |
| Faster acknowledged restore | --workers N with --no-transaction --yes --ack-partial-state |
You need atomic rollback, --replace, skip/upsert, or --trust-schema-sql |
| Atomic rollback on restore failure | Default serial restore (workers=1) |
You need FK-level concurrency |
Copyable recipes for each mode are in Common workflows and limits. Full flag catalogs: dolly dump --help, dolly restore --help, and config.example.jsonc.
| Command | Purpose |
|---|---|
dolly tui |
Interactive cockpit for connecting, dumping, and cloning. |
dolly dump |
Export data to numbered NDJSON dump directories. Schema scope: --schemas (comma-separated) overrides saved connection profile schemas, then dump.schemas in config, then public. Refuses when the effective schema scope has no tables. |
dolly dump --percent N |
Subset dump: recent roots plus FK closure; output can exceed N%. Empty schema scope fails closed; nonempty scope with no eligible percent roots reports a candidate-root diagnostic. |
dolly dump list |
List local dump history without a database connection. |
dolly restore |
Load a Dolly dump into PostgreSQL. Refuses zero-table dumps before any database mutation. |
dolly clone |
Clone with schema-replay, template, logical-stream, or physical-backup. |
dolly config |
Create or inspect config.jsonc with init and show. |
dolly update |
Install the latest stable GitHub release (--check verifies without replacing; Windows defers replacement to a hidden helper). |
dolly version |
Print build version. |
Run dolly <command> --help for command-specific flags.
TUI and CLI restore differ: the TUI restores from Dolly dump history. To restore an arbitrary directory, use dolly restore --input <dir>.
When pg_dump is on PATH, Dolly captures schema.sql and sanitizes it for cross-version restore compatibility. Restore never executes that SQL unless you explicitly pass --trust-schema-sql for reviewed artifacts.
Trusted schema replay runs outside the restore transaction, so acknowledge both conditions explicitly:
dolly restore --dsn "$DB" --input ./dolly_dump/1 --trust-schema-sql --no-transaction --yesSix copyable recipes below. Each uses the same scan pattern: Use when, Command, Result/artifacts, and Constraint/warning. See also the mode decision table, dolly dump --help, dolly restore --help, and config.example.jsonc.
Use when you need a narrow dump of specific tables by exact schema.table name.
Command
dolly dump --dsn "$DB" --output ./dolly_dump \
--include-table public.users --exclude-table public.audit_logResult/artifacts numbered {output}/{n}/ with NDJSON per table, metadata.json selection provenance (credential-free), and optional schema.sql when pg_dump is on PATH.
Constraint/warning includes narrow scope; excludes win over includes. Globs, CSV, and unqualified names are rejected. Unmatched includes fail before output; unmatched excludes become warnings in metadata. Subset modes (--percent, --seed-file) are incompatible on the same run. Shared-snapshot parallel dump (--workers N) can export included tables when chunk/slow/subset/--no-transaction are off.
Use when the same include/exclude list is reused across runs or is too long for repeated flags.
Command
dolly dump --dsn "$DB" --output ./dolly_dump \
--include-table-file tables.include.txt \
--exclude-table-file tables.exclude.txtResult/artifacts same numbered dump layout and metadata.json provenance as direct selectors.
Constraint/warning files are newline-delimited; # comments and blank lines are ignored. Same exact schema.table grammar, include-narrow/exclude-win precedence, and validation rules as direct flags. Config equivalents: dump.include_table_files / dump.exclude_table_files (CLI flags replace config when set).
Use when named tables are large or the connection is unstable and you need checkpointed, resumable streaming.
Command
dolly dump --dsn "$DB" --output ./dolly_dump \
--chunk-table public.orders --chunk-table public.eventsResult/artifacts numbered {output}/{n}/ with per-table NDJSON, metadata.json chunk provenance, transient checkpoint files under the run directory during export, and final metadata published only after completion.
Constraint/warning each requested table uses its primary key when present, otherwise an eligible simple or composite UNIQUE NOT NULL B-tree key. A table without a safe key completes through a qualified, non-resumable normal-stream fallback and creates no checkpoint. Unmatched chunk selectors fail before output. Resume requires the same source, selection, chunk policy, and strategy fingerprint; changed plans fail closed and preserve the interrupted candidate. Rejects workers > 1 and subset modes (--percent, --seed-file). --slow-connection applies the same per-table planning to every selected table.
Use when you need faster full or selected-table export with point-in-time consistency across tables.
Command
dolly dump --dsn "$DB" --output ./dolly_dump --workers 4Result/artifacts tables export concurrently from one read-only repeatable-read snapshot into numbered {output}/{n}/; metadata.json is written last on success only.
Constraint/warning --workers (or dump.workers, default 1, max 16) requires db.max_open_conns >= workers+1. Rejects --no-transaction, --slow-connection, chunk selectors, and subset modes. Unpublished run artifacts are cleaned on failure; coordinator monitors snapshot liveness during parallel export.
Use when you accept non-atomic, FK-level concurrency for faster restore into a trusted or disposable target.
Command
dolly restore --dsn "$DB" --input ./dolly_dump/1 \
--workers 4 --no-transaction --yes --ack-partial-stateResult/artifacts tables restore by FK dependency level with bounded workers; sequences synchronize after all table data commits. On full success, .dolly-restore-partial-state.json is removed from the input directory.
Constraint/warning non-atomic: each table commits independently; no global rollback. --workers (or restore.workers, default 1, max 16) requires --no-transaction, --yes, --ack-partial-state, conflict policy error (default), and a resolvable DSN. Rejects --replace, --trust-schema-sql, and skip/upsert. Manifest defaults to {input_dir}/.dolly-restore-partial-state.json (override with --partial-state-file or restore.partial_state_file); retained on failure for inspection. Acknowledgement is CLI-only and never stored in config. Not available from TUI history without these CLI flags.
Use when you need a documented path from selective dump through restore without mixing incompatible modes.
Command (exact selection + optional chunk, then default atomic restore)
dolly dump --dsn "$DB" --output ./dolly_dump \
--include-table public.users --include-table public.orders \
--chunk-table public.orders
dolly restore --dsn "$DB" --input ./dolly_dump/1Command (snapshot-parallel dump, then explicit parallel restore)
dolly dump --dsn "$DB" --output ./dolly_dump --workers 4
dolly restore --dsn "$DB" --input ./dolly_dump/1 \
--workers 4 --no-transaction --yes --ack-partial-stateResult/artifacts dump writes {output}/{n}/ with metadata.json, NDJSON, optional schema.sql, and checkpoint state only while chunk/slow export is in progress. Parallel restore may leave .dolly-restore-partial-state.json until full success.
Constraint/warning keep workers=1 for chunk/selective dumps; use default serial restore when atomic rollback matters. When includes narrow scope, each --chunk-table must name a table in the include set. Do not combine parallel dump with chunk/slow/subset/--no-transaction. Do not combine parallel restore with replace, trusted schema, or skip/upsert policies.
dolly dump --dsn "$DB" --output ./dolly_dump --percent 10 --max-rows-per-table 1000--percent conflicts with --seed-file and --slow-connection. FK closure can make a subset dump larger than the requested percentage.
Default restore runs in one transaction. For trusted empty targets or very large loads:
dolly restore --dsn "$DB" --input ./dolly_dump/1 --no-transaction --yesSerial --no-transaction mode can leave partial progress if it fails mid-way. Parallel restore (--workers > 1) always requires --ack-partial-state and writes a manifest until full success. Prefer the default when you need atomic rollback.
Default schema-replay clone recreates schema and object definitions (including trigger and materialized-view definitions), restores regular table data and sequence state, and excludes owners, ACLs, and cluster-global roles and tablespaces. Materialized-view contents are not cloned (definitions only). Cloned triggers may fire during restore.
| Strategy | When | Sanitization |
|---|---|---|
schema-replay |
Default cross-server or development clone | Supported |
template |
Same PostgreSQL instance; fastest | No |
logical-stream |
Large cross-server logical copy | No |
physical-backup |
Whole cluster directory copy | No |
physical-backup uses pg_basebackup, requires replication privileges, and copies the entire cluster data directory rather than one database. Read physical backup before using it.
Non-profile clone -ff keeps your dotenv or shell DB_URL as-is (query params such as sslmode stay intact; config may add only statement_timeout). When preflight cannot reach the source, the error includes a redacted connection detail before the generic network hint — passwords and full raw DSNs are not printed.
Treat Dolly like a database administration tool:
restore --replacetruncates target tables before insert.restore --no-transaction --yescan leave partial table state.- Sanitization is pattern-based and only applies to
dumpandschema-replay; it is not a compliance guarantee. template,logical-stream, andphysical-backupcopy unsanitized row data.
Before using production or production-like data, use a least-privilege role, keep DSNs and dumps out of Git, confirm destructive targets are disposable, validate sanitization manually, and rehearse in staging. See security and physical backup.
dolly config init writes config.jsonc. See config.example.jsonc for the complete template.
Saved connections are off by default. Enable them explicitly:
Then CLI commands can use --connection <name> instead of --dsn. Project-scoped stores are convenient but easier to commit by accident; encrypted stores need DOLLY_CONNECTIONS_KEY, and losing that key loses access to encrypted profiles.
dump, restore, clone, version, and update accept --json:
- Exit 0: success JSON on stdout.
- Exit 1:
{"ok":false,"command":"...","error":"..."}on stderr. clone --jsonrequires-fffor non-interactive use.dump list --jsonreturns an array of history records instead of the command envelope.
result=$(dolly dump --dsn "$DB" --output ./out --json 2>err.json) || { cat err.json; exit 1; }
echo "$result"Check for updates without replacing:
dolly update --check --jsonRequires Go 1.26.3+ (match go.mod) and PostgreSQL 16 client tools on PATH for schema capture and clone strategies.
Run a local PostgreSQL round trip from a source checkout:
docker compose up -d
export DOLLY_TEST_PG_DSN='postgres://dolly:dolly@127.0.0.1:5433/dolly?sslmode=disable'
go build -buildvcs=false -o ./bin/dolly ./cmd/dolly
./bin/dolly dump --dsn "$DOLLY_TEST_PG_DSN" --output ./dolly_dump
./bin/dolly restore --dsn "$DOLLY_TEST_PG_DSN" --input ./dolly_dump/1 --on-conflict skipgo test ./...
go vet ./...
make preflight
make test-integration # needs DOLLY_TEST_PG_DSNRelease notes: docs/release.md · CHANGELOG.md
Report security issues privately via GitHub private vulnerability reporting — see SECURITY.md.
{ "save_connections": true, "connections": { "scope": "xdg", // or "project" "encrypt": true // set DOLLY_CONNECTIONS_KEY (32-byte standard base64) } }