RED Docs

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.

Still evolving

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 app

Building 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:

  1. A saved connection by name (the ones you manage in the app) - credentials are read from the OS keychain, exactly like the GUI.
  2. 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.sql

List what's saved with red connections (add --json for scripting).

Verbs

CommandWhat 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
red mcp <conn>Serve RED's read-only tools to an MCP client over stdio
red reset [--yes]Remove all RED data: config, cached data, keychain secrets

-q / --quiet is global. Every verb takes --help.

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 -

Risky and destructive statements are confirmed on the terminal, the same way they are in the app. Pass --yes to skip the prompt in a script or CI run - query takes it too. See Safety and guards.

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, --target-schema to place 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 replace

migrate 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_items

Preview 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.

MCP server

red mcp <connection> is a headless stdio MCP server. Point Claude Code (or any MCP client) at it and the client gets RED's read-only database tools - schema, describe, profile, SELECT, explain - grounded in that connection, with no GUI and no ports:

red mcp prod-readonly

Writes are withheld and a tool-call budget bounds a runaway client, like the in-app path. It honours your [ai] policy: a connection whose assistant you disabled serves nothing, and the gate fails closed if the policy can't be read. See AI assistant.

Removing RED's data

red reset deletes RED's config and cached-data directories and every keychain secret - connection passwords, SSH secrets, AI keys - in one step. It shows what will be removed and prompts first; --yes skips the prompt for CI teardown. The binary itself is left alone.

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 / --quiet silences progress and success lines (errors still print).
  • Exit codes let a script branch on the failure class:
CodeMeaning
0Success
2Usage error (bad args, unknown connection, no SQL)
3Connection failure (auth, unreachable host, untrusted SSH host)
4Runtime failure (a query, exec, copy, or migrate error)

Run red <command> --help for the full flag list of any verb.

On this page