Command-line mode
Run RED headless to query, script, and seed dev/staging databases.
RED runs headless from a terminal for the things you don't want a window for: running a query in a script, executing a migration, or seeding a dev/staging database from another connection. It's the same binary and the same backend as the app - a subcommand runs the command and exits; a bare launch opens the desktop app as usual.
New and evolving
CLI mode is a recent addition. The verbs below are stable in shape, but flags and output may still change before the first stable release.
Invocation
red <command> [args] # runs headless, then exits
red # no command → opens the desktop appBuilding from source? Pass args through Cargo:
cargo run -p red -- query mydb "SELECT 1"Referencing a connection
Every verb takes a connection as its first argument. It resolves, in order:
- A saved connection by name (the ones you manage in the app) - credentials are read from the OS keychain, exactly like the GUI.
- An inline DSN - handy in CI where nothing is saved:
red query "postgres://user:pass@host:5432/shop" "SELECT count(*) FROM orders"
red exec "sqlite:///abs/path/app.db" -f schema.sqlList what's saved with red connections (add --json for scripting).
Verbs
| Command | What it does |
|---|---|
red connections [list] [--json] | List saved connections |
red test <conn> | Check a connection can be reached |
red query <conn> [sql] | Run a query, stream rows to stdout |
red exec <conn> [sql] | Run statements / a script (writes, DDL) |
red copy <src> <table> --to <dst> | Copy one table into another |
red migrate <src> --to <dst> | Migrate whole tables into another connection |
Querying
query streams the result to stdout in the format you pick - table (default),
csv, tsv, or json:
red query mydb "SELECT id, name FROM users LIMIT 5"
red query mydb --format csv "SELECT * FROM users" > users.csv
red query mydb --format json "SELECT * FROM users" | jq '.[].name'SQL can come from an argument, a file with -f, or piped on stdin:
red query mydb -f report.sql
echo "SELECT now()" | red query mydb -f -Executing statements and scripts
exec runs writes and DDL - the primary way to seed a database. A
multi-statement script is split and run one statement at a time, each in its own
transaction:
red exec staging -f seed.sql
red exec staging "UPDATE feature_flags SET enabled = true"
cat schema.sql | red exec staging -f -Copying and migrating
The headline for populating dev/staging. Both open a source and a target connection (same engine or across engines) and stream rows through in bounded chunks - no intermediate dump file.
copy moves one table. Use --create to make the target table from the
source's columns if it doesn't exist, --as to rename it, and --mode to append
(default) or replace:
# create staging.users from prod and fill it
red copy prod users --to staging --create
# refresh an existing table (clear, then insert)
red copy prod users --to staging --mode replacemigrate moves many tables at once - create-fresh, foreign-key ordered,
skipping any table that already exists on the target. Without --tables it moves
the whole schema:
# migrate an entire database into staging
red migrate prod --to staging
# just a few tables
red migrate prod --to staging --tables users,orders,line_itemsPreview first with --dry-run
copy --dry-run prints the target, write mode, and the resolved column
mapping; migrate --dry-run prints which tables would be created vs skipped -
neither writes anything.
Scripting conventions
CLI mode is built to compose in pipelines and CI:
- Data goes to stdout, progress and summaries go to stderr - so
red query … | psql …stays clean. -q/--quietsilences progress and success lines (errors still print).- Exit codes let a script branch on the failure class:
| Code | Meaning |
|---|---|
0 | Success |
2 | Usage error (bad args, unknown connection, no SQL) |
3 | Connection failure (auth, unreachable host, untrusted SSH host) |
4 | Runtime failure (a query, exec, copy, or migrate error) |
Run red <command> --help for the full flag list of any verb.