agentsclimarketplace

Coding style

Skill matejformanek/postgres-claude/.claude/skills/coding-style

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 coding-style

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

Format C code to upstream PostgreSQL house style for src/backend / src/include — covers hard tabs at width 4, BSD braces, postgres.h-first include order, C99 subset rules (no // comments, no VLA, no mid-block declarations), naming conventions (struct typedef + field naming, function names matching typedef names), function-header comment format, ~78-char line length, and pgindent expectations. Use whenever a PG patch edits, adds, or reviews .c / .h files under source/src/ or dev/src/, or when a reviewer flags pgindent churn on a posted patch. Skip for Linux-kernel style (CodingStyle), clang-format / rustfmt / prettier / black / shfmt configurations, non-PG C / C++ style (Google style, LLVM style, Mozilla style), Java checkstyle, JavaScript ESLint, EditorConfig tuning, and general "what's a good C style" advice.

SKILL.md

9.9 KB, as published. Nobody here has run it

PostgreSQL coding-style — operational rules

When you touch any .c or .h under source/src/, the file must end up looking like the surrounding code. Follow this checklist; full reasoning and citations live in knowledge/conventions/coding-style.md.

Hard rules (must not violate)

1. Indentation: hard tabs, width 4

  • Literal \t, not spaces. One tab per nesting level.
  • Verify your editor: .editorconfig covers it; if you write a file with spaces, pgindent will produce a noisy diff.

2. #include "postgres.h" is line 1 of every backend .c file

Order (each group separated by a blank line):

  1. #include "postgres.h" (backend) or "postgres_fe.h" (frontend) or "c.h" (shared) — before any system header
  2. <system headers> (<stdio.h>, <unistd.h>, …)
  3. "project headers" grouped, alphabetical-ish

Headers under src/include/ must compile standalone (make headerscheck) and as C++ (make cpluspluscheck).

3. C99 subset only — these are banned even though C99 has them

  • No // line comments (use /* … */)
  • No variable-length arrays
  • No declarations interleaved with statements — declare locals at the top of the block before any statement. This includes for (int i = 0; …) — declare i at the top of the enclosing block.
  • No universal character names (\uXXXX)
  • Newer features (_Static_assert, GCC builtins) require a fallback.

4. No raw malloc / free / strdup in the backend

Use palloc / pfree / repalloc / pstrdup / psprintf. Allocations live in CurrentMemoryContext. Frontend/common code uses pg_malloc etc. from src/common.

5. Errors via ereport, not fprintf(stderr, …)

ereport(ERROR,
        errcode(ERRCODE_DIVISION_BY_ZERO),
        errmsg("division by zero"));

Use elog(level, …) only for internal / "cannot happen" / debug messages (no SQLSTATE, no translation). ereport(ERROR, …) does not return — never write code after it. Memory and resource cleanup after ereport(ERROR, …) is also unnecessary — AbortTransaction() releases the per-query memory context, locks, buffers, and open file descriptors.

6. Assertions never have side effects

Assert(cond) compiles away in non-cassert builds. Move any side effect out of the macro. Prefer StaticAssertDecl/StaticAssertStmt for compile-time checks.

7. File header block is mandatory and copyrights are exact

Every .c and most .h start with this format-preserving block. Both copyright lines, verbatim:

/*-------------------------------------------------------------------------
 *
 * filename.c
 *      one-line description
 *
 * Portions Copyright (c) 1996-<year>, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *      src/path/to/filename.c
 *
 *-------------------------------------------------------------------------
 */

The leading /*------- makes pgindent leave it alone.

Formatting checklist (pgindent will fix these — do them anyway)

RuleDetail
Brace styleBSD/Allman — opening brace on its own line at same indent
Function definitionReturn type alone on a line; name(args) on the next; { in column 1
Pointer starBinds to the variable: char *p. Function return type: Foo * with one space
Single-statement ifNo braces; body on next line indented +1
elseOn its own line after the closing }
Line lengthTarget ~80 cols; pgindent uses -l79. Don't fracture translatable strings just to fit
Trailing whitespaceStripped everywhere except a few data files (see .editorconfig)
Final newlineRequired (except a few data files)

Comment style

Standard multi-line block:

/*
 * comment text begins here
 * and continues here
 */

Format-preserving block (pgindent won't reflow):

/*---------
 * keep these line breaks
 *---------
 */

Function header comments sit directly above the function, start with the function name, then describe what it does and any non-obvious preconditions. They are anchored in column 1 and not reflowed.

Naming

ThingConventionExamples
Types / typedefsPascalCase, no _t suffixHeapTuple, MemoryContext
Functions (verbs on a subsystem)lower_snake_caseheap_fetch_next_buffer, log_heap_update
Functions ("MethodOnType")PascalCaseMultiXactIdGetUpdateXid
Locals & struct fieldslower_snake_case, often with a 2-3 char subsystem prefix (rs_…)scan->rs_cbuf
Globalsmixed; match surrounding moduleerror_context_stack, Log_line_prefix
Macros & constantsALL_CAPS_SNAKE for action macros, PascalCase for values of Pascal-typed constantsCHECK_FOR_INTERRUPTS(), InvalidBlockNumber
SQLSTATE codesERRCODE_*ERRCODE_DIVISION_BY_ZERO

Two operational rules:

  1. If you add a new typedef, also add it to source/src/tools/pgindent/typedefs.list — otherwise pgindent mis-spaces uses of the new type.
  2. Don't give a function the same name as a typedef. pgindent will mangle both.

Error message style (when wrapping in errmsg/errdetail/errhint)

SlotFirst letterTerminal punctuationSentence shape
errmsg (primary)lower-casenonefragment, one line
errdetail, errhintCapital.complete sentences
errcontextlower-casenonefragment
  • Active voice. Past tense ("could not …") for recoverable; present tense ("cannot …") for permanent.
  • No contractions. Use "cannot", never "can't".
  • Avoid "unable", "illegal", "bad", "unknown" → prefer "cannot/could not", "invalid", "unrecognized".
  • Quote user-supplied identifiers, file names, GUC names with "%s".
  • %m expands to strerror(errno).
  • State the reason. could not open file "%s": %m — not open() failed.
  • Wrap user-visible literal strings in _("…") so xgettext extracts them. errmsg already does this internally; errmsg_internal does not.
  • For file/socket failures, prefer errcode_for_file_access() / errcode_for_socket_access() — they pick the right ERRCODE_* from errno so you don't have to.

PG_TRY / PG_CATCH rules

PG_TRY();
{
    /* code that might ereport(ERROR) */
}
PG_CATCH();
{
    /* release resources held across the TRY */
    PG_RE_THROW();
}
PG_END_TRY();
  • Don't use PG_TRY for ordinary control flow.
  • Always PG_RE_THROW() from CATCH unless you have a specific reason to swallow (e.g. a PL exception handler).
  • Don't return/goto/break/continue out of the TRY block.
  • Any resource (lock, buffer, file, palloc'd memory you can't let context cleanup handle) acquired inside the TRY must be released in the CATCH before re-throwing.

Before you commit

Format-check (pgindent / pgperltidy) and a scoped meson test run automatically: the PostToolUse hook (.claude/hooks/pg-format.sh) rewrites C/H/Perl files on edit, and the git pre-commit hook (.claude/hooks/pg-precommit.sh) re-verifies on commit and runs an R13-scoped suite list. If the hook isn't firing, run /pg-install-hooks (the marker is # pg-precommit-guard v1 in dev/.git/hooks/pre-commit). Manual headerscheck / cpluspluscheck is still the user's call for public-header changes.

If pgindent insists on changes outside your patch:

  1. Did you add a typedef? Put it in src/tools/pgindent/typedefs.list.
  2. Did you name a function the same as a typedef? Rename one.
  3. Mismatched braces inside an #if? Restructure.

Other committing-checklist items relevant to style:

  • *printf calls: check trailing newlines.
  • Catalog change? Bump CATALOG_VERSION_NO.
  • WAL/control change? Bump PG_CONTROL_VERSION etc.
  • Regression-test names: regress_* pattern.
  • EXPLAIN in tests: use COSTS OFF so output is portable.

When in doubt: imitate the neighbours

"Make the new code look like the existing code around it." — PG docs, Source Formatting

If two patterns exist in the tree (snake_case vs PascalCase for functions, parenthesized vs un-parenthesized ereport aux calls, etc.), match the file you are editing. Consistency within a file matters more than picking the globally "right" answer.

Cross-references

  • knowledge/conventions/coding-style.md — long-form rationale and citations.
  • .claude/skills/error-handling/SKILL.mdereport/elog rule (§5) deep-dive.
  • .claude/skills/memory-contexts/SKILL.mdpalloc vs malloc rule (§4) deep-dive.
  • .claude/skills/patch-submission/SKILL.md — pgindent + check-world before submission.
  • .claude/skills/commit-message-style/SKILL.md — upstream-style commit message for the diff that comes out of this skill.
  • .claude/skills/build-and-run/SKILL.md — running headerscheck / cpluspluscheck under the dev build.

Keep looking

Skills are one crate of 328,083. 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.