agentleFS
postgres-aipostgres-ai/database-lab-engine/CLAUDE.md

database-lab-engine

CLAUDE.md2.8k starsChanged 4 months agoApache-2.0View on GitHub

We split this CLAUDE.md into the rules it gives an agent

60 rules. About 0 are common, 54 are distinctive, and 6 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈54

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 6

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  • could be automatic: a setting could enforce it
  1. Distinctive:

    Always run tests before pushing: If tests fail, do not push.

    line 27
  2. Very specific:

    Run unit tests: cd engine && make test

    line 32
  3. Very specific:

    Run integration tests: cd engine && make test-ci-integration

    line 33
  4. Very specific:

    Run a specific test: cd engine && GO111MODULE=on go test -v ./path/to/package -run TestName

    line 34
  5. Very specific:

    Run UI: cd ui && pnpm start:ce (Community Edition) or pnpm start:platform

    line 35
  6. Distinctive:

    Use present tense and imperative mood in commit messages

    line 39
  7. Distinctive:

    All Git commits must be signed

    line 41
  8. Distinctive:

    Use error handling with pkg/errors

    line 43
  9. Distinctive:

    Follow standard Go import ordering

    line 44
  10. Distinctive:

    Always run tests, linter and normalize comments BEFORE committing anything

    line 51
  11. Distinctive:

    Run formatting, code generation, linting and testing on completion

    line 52
  12. Distinctive:

    Never commit without running completion sequence

    line 53
  13. Distinctive:

    Run tests and linter after making significant changes to verify functionality

    line 54
  14. Distinctive:

    Do not add comments that describe changes, progress, or historical modifications

    line 57
  15. Distinctive:

    After important functionality added, update README.md accordingly

    line 59
  16. Distinctive:

    When merging master changes to an active branch, make sure both branches are pulled and up to date first

    line 60
  17. Distinctive:

    Don't leave commented out code in place

    line 61
  18. Distinctive:

    Avoid multi-level ifs, never use else if

    line 63
  19. Distinctive:

    Avoid else branches if possible

    line 65
  20. Distinctive:

    Write tests in compact form by fitting struct fields to a single line (up to 130 characters)

    line 66
  21. Distinctive:

    Before any significant refactoring, ensure all tests pass and consider creating a new branch

    line 67
  22. Distinctive:

    When refactoring, editing, or fixing failed tests:

    line 68
  23. Distinctive:

    Do not redesign fundamental parts of the code architecture

    line 69
  24. Distinctive:

    If unable to fix an issue with the current approach, report the problem and ask for guidance

    line 70
  25. Distinctive:

    Use descriptive error messages that help with debugging

    line 99
  26. Very specific:

    Use error wrapping: fmt.Errorf("failed to process request: %w", err)

    line 100
  27. Distinctive:

    Check errors immediately after function calls

    line 101
  28. Distinctive:

    Use descriptive camelCase names for variables and functions

    line 105
  29. Distinctive:

    Use constants for magic numbers and strings

    line 110
  30. Distinctive:

    Use meaningful names for constants and enums

    line 111
  31. Distinctive:

    Use descriptive parameter names that indicate their purpose

    line 115
  32. Distinctive:

    Consider using parameter structs for functions with many (4+) parameters

    line 116
  33. Distinctive:

    If function returns 3 or more results, consider wrapping in Result/Response struct

    line 117
  34. Distinctive:

    If function accepts 3 or more input parameters, consider wrapping in Request/Input struct (but never add context to struct)

    line 118
  35. Distinctive:

    All exported functions, types, and methods must have clear godoc comments

    line 121
  36. Distinctive:

    Document any non-obvious behavior or edge cases

    line 124
  37. Distinctive:

    All comments should be lowercase, except for godoc public functions and methods

    line 125
  38. Distinctive:

    Keep code modular with focused responsibilities

    line 129
  39. Distinctive:

    Use interfaces to define behavior and enable mocking for tests

    line 132
  40. Distinctive:

    Keep code minimal and avoid unnecessary complexity

    line 133
  41. Distinctive:

    Don't keep old functions for imaginary compatibility

    line 134
  42. Distinctive:

    Consider nested functions when they simplify complex functions

    line 137
  43. Distinctive:

    Keep cyclomatic complexity under 30

    line 140
  44. Distinctive:

    Don't break down functions too small as it can reduce readability

    line 143
  45. Distinctive:

    Keep lines under 130 characters when possible

    line 145
  46. Distinctive:

    Avoid if-else chains and nested conditionals:

    line 146
  47. Distinctive:

    Never use long if-else-if chains.

    line 147
  48. Distinctive:

    Prefer early returns to reduce nesting depth

    line 148
  49. Distinctive:

    Use context structs or functional options instead of multiple boolean flags

    line 150
  50. Very specific:

    Write thorough tests with descriptive names (e.g., TestRouter_HandlesMiddlewareCorrectly)

    line 153
  51. Distinctive:

    Prefer subtests or table-based tests, using Testify

    line 154
  52. Distinctive:

    Use table-driven tests for testing multiple cases with the same logic

    line 155
  53. Distinctive:

    Test both success and error scenarios

    line 156
  54. Distinctive:

    Keep tests compact but readable

    line 159
  55. Distinctive:

    If test has too many subtests, consider splitting it to multiple tests

    line 160
  56. Distinctive:

    Never disable tests without a good reason and approval

    line 161
  57. Distinctive:

    Don't create new test files if one already exists matching the source file name

    line 163
  58. Distinctive:

    Add new tests to existing test files following the same naming and structuring conventions

    line 164
  59. Distinctive:

    Don't add comments before subtests, t.Run("description") already communicates what test case is doing

    line 165
  60. Distinctive:

    Never use godoc-style comments for test functions

    line 166

≈ “Common” is an estimate: at least 1 in 5 of the 25,680 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
CLAUDE.md

CLAUDE.md

@AGENTS.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Architecture Overview

Core Components

  1. Backend code (engine/) 1.1. Entry Points (cmd/)
  2. Frontend code (ui/)

Notable patterns

  • Source-detection logic lives in engine/internal/retrieval/probe/. The Propose orchestrator returns a structured ProposedConfig consumed by both the /admin/probe-source HTTP handler and the dblab local-install CLI (engine/cmd/cli/commands/localinstall/). Extend probe rules there, not in tools/db/pg.go.
  • Config projection (engine/pkg/models/configuration.go + engine/pkg/util/projection/) walks only top-level struct fields with single flat proj:"..." paths — no recursion into nested structs. The RetrievalMode field on ConfigProjection carries no proj: tag because it's a synthetic field injected by projectedAdminConfig after StoreJSON; the request-side dispatcher reads it directly from the incoming JSON map. A projection field for a key that is not pre-seeded in the config scaffold (e.g. connectionString) needs the ,createKey tag — projection.Set silently skips a missing leaf without it.
  • Mode-aware config writes: applyProjectedAdminConfig dispatches on the synthetic retrievalMode, and guardModeFields enforces a per-mode allow-list of populated fields so logical-only fields cannot leak into a physical config (and vice-versa).
  • Source connection-string passthrough: when logicalDump.options.source.connectionString is set it wins over the discrete connection.* fields. logical/connstring.go (withDatabase, sourcePgxConfig) preserves every libpq option (sslmode, connect_timeout, …) end-to-end into pg_dump (-d <conninfo>) and the engine's own pgx connections to the source (getDBList, dbSourceActivity). The password is always injected separately — never embedded in the string. Restore paths target the local container and must never receive it.
  • Clone major upgrade (engine/internal/{provision,cloning,srv}/upgrade.go + scripts/pg_upgrade_clone.sh + Dockerfile.pg-upgrade): pg_upgrade --link converts a clone's data directory in place. Four invariants hold the design together:
    • FATAL is a data-destroying status. filterRunningClones (cloning/storage.go) drops any wrapper whose status is FATAL or whose container is not running, and cleanupInvalidClones then destroys its dataset. So a running clone must never be marked FATAL; failures that leave the clone up use StatusWarning. Anything that has to survive a restart must also be persisted with SaveClonesState() — UpdateCloneStatus only mutates memory.
    • Recovery is decided from the data directory, not from a breadcrumb — and only a positive marker proves completion. Every passive marker in the directory is already in place before the transfer begins: a target-major PG_VERSION in data_new is written by the script's initdb, and pg_upgrade renames global/pg_control away when linking starts, not when it finishes (see "Reverting to old cluster" in the pg_upgrade docs). So a run killed part-way through the transfer is indistinguishable from a finished one by those facts alone. The script therefore writes data_new/.dblab_upgrade_done once pg_upgrade has returned 0, and classifyOutcome promotes only on a completed swap or on that marker (ConversionDone); everything else with a disabled old cluster is a recoveryReprovision. Treating the pg_control rename as proof of completion would promote a partially linked cluster, report success, and then delete the old directory holding the only copy of whatever had not been linked yet. The marker is removed once the swap is promoted, so it can never vouch for a later upgrade. Exit codes are carried into the status message by describeExitCode and never classify anything. Base.RecoverInterruptedUpgrades runs from Run before filterRunningClones for the same reason as the first invariant, and a missing upgrade/state.json means there is nothing in flight (UpgradeUnchanged), never a failure.
    • The target major is the instance's, not the caller's. Dockerfile.pg-upgrade takes PG_MAJOR from its base image, so one configured provision.pgUpgradeImage means exactly one reachable target; there is nothing for an API field to choose. Provisioner.UpgradeTargetVersion derives it — probe.MajorFromImage off the tag, falling back to PG_MAJOR in the image config (docker.ImagePGMajor) for a tag outside the release grammar, cached under the image it came from so a Reload that repoints pgUpgradeImage cannot be answered from the old entry. Only released images carry a bare-major tag (CI publishes pg-upgrade:17-<branch>), so ResolveUpgradeTarget fetches the image in the background from main.go and on Reload; without it the feature would sit unavailable on every non-released instance. Server.cloneUpgradeStatus advertises the result as cloneUpgrade on /status so clients display the version instead of asking for one, and verifyUpgradeImageMajor re-reads the image before the clone goes down — a tag only claims a major while the image states one — which also refreshes the cache. An inspect error there fails the upgrade rather than passing the guard: docker.ImagePGMajor returns (0, nil) only for an image that genuinely declares no PG_MAJOR.
    • The engine owns every directory operation inside the clone directory. It belongs to the engine OS user while the upgrade container runs as the data-directory owner (resolved by stat'ing it, not assumed — the image entrypoint gosu-chowns PGDATA to uid 999 while zfs.go chowns the dataset to user.Current()). The container therefore cannot create data_new or rename anything; the engine pre-creates the empty target, chowns it plus the upgrade/ working area, and performs the swap itself.
  • Engine-side image resolution: probe/registry.go resolves a glibc-aware docker image by querying the live registries (Docker Hub for the generic image, GitLab for managed-provider SE images) with a per-repo TTL cache and a go:embed offline snapshot (images_fallback.json). Resolution never hard-fails or hangs: fresh cache → live fetch (bounded) → last good cache → embedded snapshot → provider default <repo>:<major>. Tag selection (imageselect.go) is pure and unit-tested; the Registry is built once on Server.

Testing Before Pushing

Always run tests before pushing. If tests fail, do not push. Fix the failing tests first. Only skip this if the user explicitly says to ignore test failures.

Build/Test/Lint Commands

  • Build all components: cd engine && make build
  • Lint code: cd engine && make run-lint
  • Run unit tests: cd engine && make test
  • Run integration tests: cd engine && make test-ci-integration
  • Run a specific test: cd engine && GO111MODULE=on go test -v ./path/to/package -run TestName
  • Run UI: cd ui && pnpm start:ce (Community Edition) or pnpm start:platform

Code Style Guidelines

  • Go code follows "Effective Go" and "Go Code Review Comments" guidelines
  • Use present tense and imperative mood in commit messages
  • Limit first commit line to 72 characters
  • All Git commits must be signed
  • Format Go code with cd engine && make fmt
  • Use error handling with pkg/errors
  • Follow standard Go import ordering
  • Group similar functions together
  • Error messages should be descriptive and actionable
  • UI uses pnpm for package management

Important Backend Workflow Notes

  • Always run tests, linter and normalize comments BEFORE committing anything
  • Run formatting, code generation, linting and testing on completion
  • Never commit without running completion sequence
  • Run tests and linter after making significant changes to verify functionality
  • IMPORTANT: Never put into commit message any mention of Claude or Claude Code
  • IMPORTANT: Never include "Test plan" sections in PR descriptions
  • Do not add comments that describe changes, progress, or historical modifications
  • Comments should only describe the current state and purpose of the code, not its history or evolution
  • After important functionality added, update README.md accordingly
  • When merging master changes to an active branch, make sure both branches are pulled and up to date first
  • Don't leave commented out code in place
  • Avoid multi-level nesting
  • Avoid multi-level ifs, never use else if
  • Never use goto
  • Avoid else branches if possible
  • Write tests in compact form by fitting struct fields to a single line (up to 130 characters)
  • Before any significant refactoring, ensure all tests pass and consider creating a new branch
  • When refactoring, editing, or fixing failed tests:
    • Do not redesign fundamental parts of the code architecture
    • If unable to fix an issue with the current approach, report the problem and ask for guidance
    • Focus on minimal changes to address the specific issue at hand
    • Preserve the existing patterns and conventions of the codebase

Backend Code Style Guidelines

Import Organization

  • Organize imports in the following order:
    1. Standard library packages first (e.g., "fmt", "context")
    2. A blank line separator
    3. Third-party packages
    4. A blank line separator
    5. Project imports (e.g., "gitlab.com/postgres-ai/database-lab/v3/pkg/*")
  • Example:
    import (
        "context"
        "fmt"
        "net/http"
    
        "github.com/docker/docker/api/types"
        "github.com/gorilla/mux"
    
        "gitlab.com/postgres-ai/database-lab/v3/pkg/util/branching"
    )

Error Handling

  • Return errors to the caller rather than using panics
  • Use descriptive error messages that help with debugging
  • Use error wrapping: fmt.Errorf("failed to process request: %w", err)
  • Check errors immediately after function calls
  • Return early when possible to avoid deep nesting

Variable Naming

  • Use descriptive camelCase names for variables and functions
  • Good: notFoundHandler, requestContext, userID
  • Bad: not_found_handler, x, temp1
  • Be consistent with abbreviations (e.g., httpClient not HTTPClient)
  • Local scope variables can be short (e.g., "lmt" instead of "orderLimit")
  • Use constants for magic numbers and strings
  • Use meaningful names for constants and enums

Function Parameters

  • Group related parameters together logically
  • Use descriptive parameter names that indicate their purpose
  • Consider using parameter structs for functions with many (4+) parameters
  • If function returns 3 or more results, consider wrapping in Result/Response struct
  • If function accepts 3 or more input parameters, consider wrapping in Request/Input struct (but never add context to struct)

Documentation

  • All exported functions, types, and methods must have clear godoc comments
  • Begin comments with the name of the element being documented
  • Include usage examples for complex functions
  • Document any non-obvious behavior or edge cases
  • All comments should be lowercase, except for godoc public functions and methods
  • IMPORTANT: all comments except godoc comments must be lowercase, test messages must be lowercase, log messages must be lowercase

Code Structure

  • Keep code modular with focused responsibilities
  • Limit file sizes to 300-500 lines when possible
  • Group related functionality in the same package
  • Use interfaces to define behavior and enable mocking for tests
  • Keep code minimal and avoid unnecessary complexity
  • Don't keep old functions for imaginary compatibility
  • Interfaces should be defined on the consumer side (idiomatic Go)
  • Aim to pass interfaces but return concrete types when possible
  • Consider nested functions when they simplify complex functions

Code Layout

  • Keep cyclomatic complexity under 30
  • Function size preferences:
    • Aim for functions around 50-60 lines when possible
    • Don't break down functions too small as it can reduce readability
    • Maintain focus on a single responsibility per function
  • Keep lines under 130 characters when possible
  • Avoid if-else chains and nested conditionals:
    • Never use long if-else-if chains; use switch statements instead
    • Prefer early returns to reduce nesting depth
    • Extract complex conditions into separate boolean functions or variables
    • Use context structs or functional options instead of multiple boolean flags

Testing

  • Write thorough tests with descriptive names (e.g., TestRouter_HandlesMiddlewareCorrectly)
  • Prefer subtests or table-based tests, using Testify
  • Use table-driven tests for testing multiple cases with the same logic
  • Test both success and error scenarios
  • Mock external dependencies to ensure unit tests are isolated and fast
  • Aim for at least 80% code coverage
  • Keep tests compact but readable
  • If test has too many subtests, consider splitting it to multiple tests
  • Never disable tests without a good reason and approval
  • Important: Never update code with special conditions to just pass tests
  • Don't create new test files if one already exists matching the source file name
  • Add new tests to existing test files following the same naming and structuring conventions
  • Don't add comments before subtests, t.Run("description") already communicates what test case is doing
  • Never use godoc-style comments for test functions

Download now (ZIP)

Trending

Quiet since February.thin dataabout the whole repository

Dec 2025: 0 mentionsJan 2026: 0 mentionsFeb 2026: 1 mentionMar 2026: 0 mentionsApr 2026: 0 mentionsMay 2026: 0 mentionsJun 2026: 0 mentionsJul 2026: 0 mentionsAug 2026: 0 mentionsSep 2026: 0 mentionsOct 2026: 0 mentionsNov 2026: 0 mentions
Dec 2025Jun 2026Nov 2026
Mentions a month of the postgres-ai/database-lab-engine repository that our weekly crawl found: only 5 in all, so this is a hint, not a trend. There is no adoption data for this file yet.
  • In this repositoryOne other file it gives its agents.

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.