agentsclimarketplace

Gucs config

Skill matejformanek/postgres-claude/.claude/skills/gucs-config

Turn Claude Code into a long-term collaborator on PostgreSQL internals — cited knowledge corpus, agent skills, slash commands, and task-shaped scenarios for backend hacking.

Install
npx -y skills add matejformanek/postgres-claude --skill gucs-config

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Add or modify a custom GUC variable in a PostgreSQL backend patch or extension — covers DefineCustomBoolVariable / IntVariable / RealVariable / StringVariable / EnumVariable, picking the right GucContext (PGC_POSTMASTER / PGC_SIGHUP / PGC_SUSET / PGC_USERSET), MarkGUCPrefixReserved, the check/assign/show hook trio, GUC_LIST_INPUT / GUC_LIST_QUOTE / GUC_UNIT_MS / GUC_UNIT_KB / GUC_REPORT / GUC_EXPLAIN flags, and string-GUC guc_malloc rules. Use whenever a PG patch or extension calls DefineCustom*Variable, picks a GucContext, wires check/assign/show hooks, debugs a placeholder GUC, or marks a GUC reserved via MarkGUCPrefixReserved. Skip for DBA tuning of shared_buffers / max_connections / work_mem in production, dotenv / Viper / Dynaconf / Spring @Value configuration libraries, Kubernetes ConfigMap, Terraform variables, and non-PG application config systems.

SKILL.md

11.2 KB, ~2.7k tokens by cl100k_base, as published. Nobody here has run it

gucs-config — custom GUC variables

This is the procedural cookbook for adding custom GUC variables to a PostgreSQL backend patch or extension. For the conceptual model see knowledge/idioms/guc-variables.md.

This skill is one of three siblings that share the _PG_init / postmaster-lifecycle boundary:

  • gucs-config (this skill) — custom GUC variables.
  • bgworker-and-extensions — RegisterBackgroundWorker, shared-library hooks.
  • parallel-query — ParallelContext + parallel-safe markings.

1. Picking the right Define*Variable

Five typed entry points, all in utils/guc.h. [verified-by-code source/src/include/utils/guc.h:358-416]

TypeFunctionNotes
boolDefineCustomBoolVariable
intDefineCustomIntVariablewith minValue / maxValue
doubleDefineCustomRealVariablewith minValue / maxValue
stringDefineCustomStringVariablevalueAddr is char **, see §5
enumDefineCustomEnumVariabletakes a const struct config_enum_entry[]

All five take the same trailing trio of hooks: check_hook, assign_hook, show_hook (any can be NULL).

2. GucContext — when the value can change

[verified-by-code source/src/include/utils/guc.h:71-80]

GucContextWhen the user can change it
PGC_INTERNALNever — display-only (e.g. server_version).
PGC_POSTMASTEROnly at postmaster startup (postgresql.conf / cmd line).
PGC_SIGHUPPostmaster start OR config-reload (SIGHUP / pg_reload_conf()).
PGC_SU_BACKENDStart of backend, superusers can pass via startup packet.
PGC_BACKENDStart of backend (libpq PGOPTIONS), then fixed.
PGC_SUSETAny time by a superuser, including SET.
PGC_USERSETAny time by anyone.

Rule of thumb: pick the loosest context that's still safe. If changing the value mid-session would require restarting a worker or reallocating shared memory, use PGC_POSTMASTER. If it just changes a runtime threshold, use PGC_SIGHUP or PGC_SUSET.

3. Skeleton — _PG_init for an extension with GUCs

void
_PG_init(void)
{
    DefineCustomIntVariable("my_ext.naptime",
                            "Seconds between scans.",
                            NULL,           /* long_desc */
                            &my_naptime,    /* int *valueAddr */
                            10,             /* boot_val */
                            1, INT_MAX,     /* min, max */
                            PGC_SIGHUP,
                            GUC_UNIT_S,     /* flags — UNIT_S = seconds */
                            NULL, NULL, NULL); /* check/assign/show */

    DefineCustomStringVariable("my_ext.database",
                               "DB to connect to.",
                               NULL,
                               &my_database,
                               "postgres",
                               PGC_POSTMASTER,
                               0,
                               NULL, NULL, NULL);

    /* MUST be called AFTER all DefineCustom* calls. */
    MarkGUCPrefixReserved("my_ext");
}

[verified-by-code source/src/test/modules/worker_spi/worker_spi.c:303-360]

4. MarkGUCPrefixReserved

Call exactly once per extension, after every DefineCustom*Variable for your prefix. It does two things:

  1. Removes any placeholder GUCs (GUC_CUSTOM_PLACEHOLDER) under that prefix — these get created when a config file mentions a custom variable before the defining extension loads. Without removal, parallel-worker startup later trips over them.
  2. Adds the prefix to a list so future placeholders under it are refused — typos in postgresql.conf (my_ext.napitme) now produce a clear error instead of silently being accepted.

[verified-by-code source/src/backend/utils/misc/guc.c:5185-5228]

The old name EmitWarningsOnPlaceholders is still a #define alias — prefer the new name in new code. [verified-by-code source/src/include/utils/guc.h:421]

5. String GUCs and guc_malloc

For string GUCs, valueAddr is a char **. The pointed-to storage is owned by guc.c and must be allocated with guc_malloc / guc_strdupnever palloc. If a check_hook wants to replace the proposed value it must guc_malloc the new value and guc_free the old one. Use guc_realloc to grow an existing guc_malloc allocation (typical for a derived extra payload). All four functions live in source/src/include/utils/guc.h:473-476. [from-README source/src/backend/utils/misc/README:50-62]

6. The hook trio

check_hook(newval *, void **extra, GucSource source) → bool

Signature varies by GUC type — the first argument's exact pointer type matches the variable's storage:

GUC typecheck_hook first arg
boolbool *newval
intint *newval
realdouble *newval
stringchar **newval (so *newval is the proposed char *)
enumint *newval (enum encoded as int)

[from-README source/src/backend/utils/misc/README:25-30]

  • Validate the proposed value; return false on reject.
  • May modify *newval to canonicalize (round, lowercase, ...).
  • May allocate an extra struct with guc_malloc and return it through *extra to pass derived data to the assign hook.
  • For error detail: GUC_check_errdetail(...), GUC_check_errhint(...), GUC_check_errcode(...), GUC_check_errmsg(...) — never ereport(ERROR) directly except on OOM. GUC_check_errcode(sqlerrcode) overrides the default rejection SQLSTATE (ERRCODE_INVALID_PARAMETER_VALUE, 22023); only override when you have a more specific code.
  • May run outside any transaction (bootstrap, postmaster startup, config reload). Guard catalog lookups with IsTransactionState().
  • May also be called just to validate without assigning — must not have side effects.
  • For GUC_LIST_INPUT GUCs (see §7), parse *newval inside the check_hook with SplitIdentifierString(rawstring, ',', &elemlist) (identifier-style lists) or SplitGUCList(rawstring, ',', &elemlist) (general case). Both live in source/src/include/utils/varlena.h:33-37; they pstrdup elements and pfree/list_free is the caller's job. Don't roll your own splitter — these match how the parser handles search_path, including quoted elements.

[from-README source/src/backend/utils/misc/README:25-75]

assign_hook(newval, void *extra) → void

  • Cannot fail (no return). Do all fallible work in the check hook.
  • May be called during transaction rollback → no catalog lookups.

[from-README source/src/backend/utils/misc/README:78-109]

show_hook(void) → const char *

  • Customise what SHOW displays. Static buffer is fine; not reentrant.

[from-README source/src/backend/utils/misc/README:112-117]

7. Useful flags bits

[verified-by-code source/src/include/utils/guc.h:214-242]

FlagEffect
GUC_LIST_INPUTValue is a comma-separated list — needed to use lists at all.
GUC_LIST_QUOTEEach list element is double-quoted on serialization. Required for lists of identifiers (e.g. search_path).
GUC_UNIT_KB / _MB / _BYTE / _BLOCKSInt GUC understands '128MB'.
GUC_UNIT_MS / _S / _MINTime units.
GUC_NOT_IN_SAMPLEDon't include in generated postgresql.conf.sample.
GUC_SUPERUSER_ONLYHide value from non-superusers in pg_settings.
GUC_DISALLOW_IN_FILECannot appear in config file (set only at runtime).
GUC_DISALLOW_IN_AUTO_FILECannot be set by ALTER SYSTEM.
GUC_REPORTAuto-send ParameterStatus to client on change.
GUC_EXPLAINInclude in EXPLAIN (SETTINGS) output.
GUC_ALLOW_IN_PARALLELOK to set inside a parallel-mode block.

8. GUC state under workers (cross-cutting)

  • Parallel workers — GUC state is serialized by the leader and restored in each worker by ParallelWorkerMain before your code runs. Workers see exactly the leader's GUC values at launch time. If a PGC_USERSET GUC changes mid-flight, in-flight workers do not see the change. See parallel-query for the launch mechanics.

  • Background workers (non-parallel) — GUC state is whatever postgresql.conf says at start. To honour SIGHUP, install SignalHandlerForConfigReload and call ProcessConfigFile(PGC_SIGHUP) when ConfigReloadPending is set. See bgworker-and-extensions for the signal-handling skeleton.

9. Checklist

  • _PG_init defines every custom GUC.
  • MarkGUCPrefixReserved(prefix) is called after all definitions.
  • String storage uses guc_malloc / guc_strdup, never palloc.
  • check_hook is side-effect-free and uses GUC_check_errdetail (not ereport(ERROR)) for validation failures.
  • check_hook guards catalog lookups with IsTransactionState().
  • Right GucContext chosen (don't use PGC_USERSET if the change would require restarting workers).
  • Unit flag set on int GUCs that represent size or time.
  • List GUCs have GUC_LIST_INPUT, and GUC_LIST_QUOTE if elements are identifiers.

10. Useful greps

  • All custom GUC definitions: grep -RIn 'DefineCustom\(Bool\|Int\|Real\|String\|Enum\)Variable' source/src
  • All check / assign hooks in tree: grep -RIn 'check_hook\|assign_hook' source/src/include/utils/guc.h

Cross-references

  • .claude/skills/bgworker-and-extensions/SKILL.md_PG_init flow for the surrounding extension; SIGHUP signal handler for picking up config reloads.
  • .claude/skills/parallel-query/SKILL.md — how GUCs get restored in parallel workers; GUC_ALLOW_IN_PARALLEL flag.
  • .claude/skills/extension-development/SKILL.md_PG_init, .control file, shared_preload_libraries.
  • .claude/skills/coding-style/SKILL.md — backend C style for the hook functions.
  • .claude/skills/error-handling/SKILL.mdGUC_check_errdetail vs ereport(ERROR); OOM contract.
  • knowledge/idioms/guc-variables.md — conceptual model.
  • knowledge/files/src/include/utils/guc.h.md — per-file doc for the public API surface.
  • knowledge/files/src/backend/utils/misc/guc.c.md — per-file doc for the implementation.

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 326,970. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.