# postgres CLI reference

> Flags from --help, must-be-first dispatch options, -c/--NAME=VALUE GUC overrides, and exit paths for --version and --describe-config.

- Repository: malisper/pgrust
- GitHub: https://github.com/malisper/pgrust
- Human docs: https://grok-wiki.com/public/docs/malisper-pgrust-7e0c8e82bc21
- Complete Markdown: https://grok-wiki.com/public/docs/malisper-pgrust-7e0c8e82bc21/llms-full.txt

## Source Files

- `crates/backend/main/main_main/src/help.rs`
- `crates/backend/main/main_main/src/lib.rs`
- `crates/_support/seam/init/src/bin/postgres.rs`
- `crates/backend/tcop/postgres/src/guc.rs`
- `crates/backend/postmaster/postmaster/src/gucreads.rs`

---

---
title: "postgres CLI reference"
description: "Flags from --help, must-be-first dispatch options, -c/--NAME=VALUE GUC overrides, and exit paths for --version and --describe-config."
---

The single `postgres` binary is the C-ABI entry shell over `pg_main`. After seam registration and `TopMemoryContext` setup, it owns argv, dispatches by the first argument, and maps print-only paths (`--help`, `--version`, `--describe-config`) to stdout + `exit(0)`. Postmaster and backend switches share `process_postgres_switches`, which applies short flags and `-c` / `--NAME=VALUE` as GUC overrides under `PGC_POSTMASTER` / `PGC_S_ARGV`.

## Binary entry and outcomes

| Stage | Behavior |
| --- | --- |
| Argv | Native: `std::env::args()`. Wasm: host-provided argv (fallback `["postgres"]` if empty). |
| Init | Leak `TopMemoryContext`, call `init::init_all()`, then `pg_main(mcx, argv)`. |
| Success print | `MainOutcome::PrintAndExit(text)` → write stdout, `exit(0)`. |
| Initdb | `MainOutcome::Initdb` → `initdb_main`; `exit(0)` or `exit(1)`. Not built on wasm (`exit(1)`). |
| Dispatch | `MainOutcome::Dispatched` if a subprogram returned (logic error); shell still `exit(0)`. |
| Fatal startup | `Err` → `progname: {err}` on stderr, `exit(1)`. |

```text
argv[1] early scan
  --help | -?        → help text, exit 0
  --version | -V     → version banner, exit 0
  initdb | --initdb  → initdb driver (pgrust; not a DispatchOption)
  --describe-config  → skip root check
  -C <name> (first)  → skip root check
root check (unless skipped)
dispatch from "--*" first arg
  --check / --boot / --describe-config / --single / (default postmaster)
```

## Print-and-exit paths

These must appear as **argv[1]** (exact match). Later arguments are not scanned for them.

| Argument | Output | Exit |
| --- | --- | --- |
| `--help` or `-?` | Full help string from `help(progname)` | `0` |
| `--version` or `-V` | `postgres (PostgreSQL) 18.3\n` (`PG_BACKEND_VERSIONSTR`) | `0` |
| `--describe-config` | Tab-separated GUC dump from `GucInfoMain` | `0` |

### `--help` content (flags advertised)

**Options**

| Flag | Meaning |
| --- | --- |
| `-B NBUFFERS` | shared buffers |
| `-c NAME=VALUE` | set run-time parameter |
| `-C NAME` | print value of run-time parameter, then exit (advertised; see [Root check and `-C`](#root-check-and--c)) |
| `-d 1-5` | debugging level |
| `-D DATADIR` | database directory |
| `-e` | European date input (DMY) |
| `-F` | turn fsync off |
| `-h HOSTNAME` | listen host |
| `-i` | enable TCP/IP (deprecated) |
| `-k DIRECTORY` | Unix-domain socket location |
| `-l` | enable SSL |
| `-N MAX-CONNECT` | max connections |
| `-p PORT` | listen port |
| `-s` | show statistics after each query |
| `-S WORK-MEM` | work_mem (kB) |
| `-V, --version` | version, then exit |
| `--NAME=VALUE` | set run-time parameter |
| `--describe-config` | describe configuration parameters, then exit |
| `-?, --help` | help, then exit |

**Developer options:** `-f s|i|o|b|t|n|m|h`, `-O`, `-P`, `-t pa|pl|ex`, `-T`, `-W NUM`.

**Single-user mode:** `--single` (must be first), `DBNAME`, `-d 0-5`, `-E`, `-j`, `-r FILENAME`.

**Bootstrapping mode:** `--boot` / `--check` (must be first), `DBNAME` (mandatory for bootstrap), `-r FILENAME`.

Bug report address in help: `pgsql-bugs@lists.postgresql.org`. Home page line: `https://www.postgresql.org/`.

### `--describe-config` row format

Visible built-in GUCs only. Hidden when flags include `GUC_NO_SHOW_ALL`, `GUC_NOT_IN_SAMPLE`, or `GUC_DISALLOW_IN_FILE`. Rows sorted by name. One line per GUC:

```text
name \t context \t group \t TYPE \t reset \t min \t max \t short_desc \t long_desc
```

| Column | Notes |
| --- | --- |
| `TYPE` | `BOOLEAN`, `INTEGER`, `REAL`, `STRING`, `ENUM` |
| `reset` for BOOL/INT/REAL | Zero-initialized C `reset_val` parity: `FALSE` / `0` / `0` (not boot defaults) |
| `min` / `max` | From static metadata for INT/REAL; empty for BOOL/STRING/ENUM |
| STRING/ENUM “reset” | STRING uses `boot_val` (or empty); ENUM uses enum name for `boot_val` |

Root may run `--describe-config` (read-only path).

## Must-be-first dispatch options

After the early scan and optional root check, if `argv[1]` starts with `--`, the name after the prefix is passed to `parse_dispatch_option`. Unknown names fall through to postmaster.

| First argument | `DispatchOption` | Target |
| --- | --- | --- |
| *(none / not `--*` / unmatched)* | `DISPATCH_POSTMASTER` | `PostmasterMain` |
| `--check` | `DISPATCH_CHECK` | `BootstrapModeMain(..., check_only=true)` |
| `--boot` | `DISPATCH_BOOT` | `BootstrapModeMain(..., check_only=false)` |
| `--describe-config` | `DISPATCH_DESCRIBE_CONFIG` | `GucInfoMain` → print and exit |
| `--single` | `DISPATCH_SINGLE` | single-user backend (`get_user_name_or_exit` + `postgres_single_user_main`) |
| `--forkchild…` | never matched | Non-`EXEC_BACKEND` builds skip `forkchild`; treated as postmaster |

<Warning>
Dispatch long options must be **argv[1]**. If they appear later (for example after `-D`), switch parsers reject them with `--{name} must be first argument` (`ERRCODE_SYNTAX_ERROR`).
</Warning>

### pgrust-only early entry (not a `DispatchOption`)

| First argument | Behavior |
| --- | --- |
| `initdb` or `--initdb` | `MainOutcome::Initdb` → in-process initdb driver; re-execs this binary for `--boot` / `--single` phases |

Full initdb argv is documented separately; this page only records the dispatch hook.

## Root check and `-C`

Unless skipped, `check_root` fails when:

- effective uid is `0` → FATAL: `"root" execution of the PostgreSQL server is not permitted...`
- real uid ≠ effective uid → FATAL: `{progname}: real and effective user IDs must match`

**Root check skipped when argv[1] is:**

- `--describe-config`, or
- `-C` with a following argument (`argv.len() > 2`)

`-C` is listed in `--help` as “print value of run-time parameter, then exit”. In `process_postgres_switches`, short option `C` is currently a no-op (“ignored for consistency with the postmaster”). The early root-check bypass remains for pg_ctl-style privileged probes; do not assume a stock Postgres-style print-and-exit until that path is fully wired in postmaster option handling.

## GUC overrides: `-c` and `--NAME=VALUE`

Postmaster and backend share `process_postgres_switches` (getopt optstring  
`B:bC:c:D:d:EeFf:h:ijk:lN:nOPp:r:S:sTt:v:W:-:`).

When context is `PGC_POSTMASTER` (secure):

- Source is `PGC_S_ARGV`
- A leading `--single` at `argv[1]` is dropped before getopt (postmaster path does not use this; single-user does)

### Long-option parsing (`ParseLongOption`)

| Input form | Result |
| --- | --- |
| `name=value` | name + value; `-` in name becomes `_` |
| `name` only | name only; value missing → error for `-c` / `--` GUC form |

Examples (equivalent):

```bash
postgres -D /data -c listen_addresses= -c io_method=sync
postgres -D /data --listen_addresses= --io_method=sync
postgres -D /data -c max_stack_depth=60000
```

Missing value errors:

- `--{optarg} requires a value`
- `-c {optarg} requires a value`

### Short flags → GUCs (secure / postmaster-relevant)

| Flag | GUC / effect |
| --- | --- |
| `-B` | `shared_buffers` |
| `-b` | binary upgrade (`IsBinaryUpgrade=true`) when secure |
| `-c` / `--` | `set_config_option(name, value, …)` |
| `-D` | data directory (`userDoption` / postmaster re-scan of argv) |
| `-d` | `set_debug_options`: `log_min_messages=debugN` or `notice`; levels ≥1 also set `log_connections`/`log_disconnections` under postmaster; ≥2 `log_statement=all`; ≥3–5 parse/plan/rewrite debug prints |
| `-e` | `datestyle=euro` |
| `-E` | echo queries (secure) |
| `-F` | `fsync=false` |
| `-f X` | disable plan type (`s/i/o/b/t/n/m/h` → `enable_seqscan` … `enable_hashjoin` = false) |
| `-h` | `listen_addresses` |
| `-i` | `listen_addresses=*` |
| `-j` | semi/newline delimiter mode (secure) |
| `-k` | `unix_socket_directories` |
| `-l` | `ssl=true` |
| `-N` | `max_connections` |
| `-O` | `allow_system_table_mods=true` |
| `-P` | `ignore_system_indexes=true` |
| `-p` | `port` |
| `-r` | redirect stdout/stderr path (secure) |
| `-S` | `work_mem` |
| `-s` | `log_statement_stats=true` |
| `-t pa\|pl\|ex` | `log_parser_stats` / `log_planner_stats` / `log_executor_stats` |
| `-v` | standalone `FrontendProtocol` override (secure) |
| `-W` | `post_auth_delay` |
| `-n`, `-T`, `-C` | ignored in this switch table (postmaster consistency) |

### pgrust extension flag

| Flag | Meaning |
| --- | --- |
| `--regress-output` | Valueless; enables psql `-a -q`-compatible single-user output for regression diffs. Not a GUC. |

### Invalid argument FATAL

If getopt fails or leftover non-option tokens remain (except the optional database name for standalone):

- Under postmaster: `invalid command-line argument for server process: {bad}`
- Standalone: `{progname}: invalid command-line argument: {bad}`
- Hint: `Try "{progname}" --help" for more information.`

## Postmaster argv after dispatch

Default path calls `PostmasterMain`, which:

1. `InitializeGUCOptions`
2. `process_postgres_switches(argv, PGC_POSTMASTER)`
3. Re-reads `-D` / `-Ddir` from argv for `SelectConfigFiles`
4. Continues control-file checks, listen sockets from `listen_addresses` / `unix_socket_directories` / `port` / `max_connections` (via postmaster GUC readers)

Example (from project README shape):

```bash
RUST_MIN_STACK=33554432 target/release/postgres \
  -D /tmp/pgrust-data \
  -F \
  -c listen_addresses= \
  -k /tmp \
  -p 5432 \
  -c io_method=sync \
  -c max_stack_depth=60000
```

Required runtime GUCs and stack limits are covered on the configuration and run-server pages; the CLI only delivers them as `-c` / `--` overrides or config files under `-D`.

## Bootstrap / check switch surface

`--boot` / `--check` use a smaller getopt set (`B:c:d:D:Fkr:X:-:` plus long options). Same rules: misplaced dispatch long options error with `--{name} must be first argument`; `-c` / `--NAME=VALUE` require values.

## Exit code summary

| Path | Code |
| --- | --- |
| `--help`, `--version`, `--describe-config` | `0` |
| initdb success | `0` |
| initdb error / wasm initdb | `1` |
| Startup `PgError` from `pg_main` | `1` |
| `SelectConfigFiles` failure in postmaster | `ExitPostmaster(2)` |
| Other postmaster shutdowns | `ExitPostmaster(0|1)` per state machine |

## Verification signals

```bash
# Help and version (no data dir)
./target/release/postgres --help | head -5
# expected: "... is the PostgreSQL server."

./target/release/postgres -V
# expected: postgres (PostgreSQL) 18.3

./target/release/postgres --describe-config | head -3
# expected: tab-separated GUC rows (name, context, group, TYPE, ...)

# Misplaced must-be-first option (after other args) → syntax error when switches run
# Root as euid 0 without --describe-config/-C → FATAL root refusal on stderr, exit 1
```

## Related pages

<CardGroup>
  <Card title="Process modes and dispatch" href="/process-modes">
    How postmaster, --single, --boot, --check, --describe-config, and initdb share one binary.
  </Card>
  <Card title="initdb options reference" href="/initdb-reference">
    Supported `postgres --initdb` argv, space-separated parsing, and unsupported flags.
  </Card>
  <Card title="Configuration reference" href="/configuration-reference">
    `io_method`, stack settings, listen_addresses, and build-time `PGRUST_*` path vars.
  </Card>
  <Card title="Run the server" href="/run-server">
    Start postmaster with `-D`, sockets, required overrides, and readiness checks.
  </Card>
  <Card title="Troubleshooting" href="/troubleshooting">
    Root execution refused, wrong share path, stack overflows, and initdb option gaps.
  </Card>
</CardGroup>
