- Stop telling me "You're right", it just shows how incompetent you are. Do it right on your first try, fact-check and review after changes. If you are not sure, ask for help.
- When you see changes made outside your knowledge, use the current version as your new starting point. Do not blindly overwrite those changes or you suck. Even if you have to update the code, always respect the pattern in the surrounding context!
This applies to all texts, including but not limited to UI, documentation, code comments.
- Use sentence case. Preserve original casing for brand names, e.g., Git, GitHub, Go, Git LFS, NGINX.
- End with a period for a full sentence.
- Never use em dashes (
—) or en dashes (–). Rewrite the sentence with a comma, period, colon, or parentheses instead. - Do not overuse semicolons. Two short sentences are almost always clearer than one sentence joined by a semicolon. Reserve the semicolon for the rare case where the two clauses are so tightly coupled that splitting them loses meaning, never as a default em-dash replacement or a way to chain related thoughts.
- Do not add comments that repeat what the code is doing, always prefer more descriptive names. Do add comments for intentions that aren't obvious via reading the code alone. This rule takes precedence over matching existing patterns.
- Use
github.com/cockroachdb/errorsfor error handling.- Always wrap errors with context using
errors.Wraporerrors.Wrapf. Do not return bare errors.
- Always wrap errors with context using
- Use
github.com/stretchr/testifyfor assertions in tests. Be mindful about the choice ofrequireandassert, the former should be used when the test cannot proceed meaningfully after a failed assertion. - Prefer grouping related cases as
t.Runsubtests under a single top-levelTestXxxfunction, instead of writing one top-levelTestXxx_Caseper case. Reserve separate top-level functions for unrelated subjects and complex subtest setup. - Always use backtick (raw string) literals for multi-line strings. Never use
"...\n" +concatenation. - When each is available, the first set of arguments should always be:
context.Context,*logx.Logger.- Logger scoping (
logger.Scoped(...)) is done at the call site, not inside the callee's constructor. The constructor stores the logger as-is. - Log scope and attribute names use camelCase while respecting Go idioms, e.g.,
"userID","messageLength".
- Logger scoping (
- The primary key must be
id BIGSERIALoruuid UUID(UUIDv7). - Always spell out the exact column name in GORM struct tags, e.g.,
gorm:"column:created_at". - For complex SQL queries (upserts with
ON CONFLICT, JSONB concatenation, multi-column updates with expressions, etc.), write raw SQL with GORM named args (@name+map[string]any). UseCAST(@name AS type)instead of@name::typefor type casts on named args. Reserve the GORM query builder for simple CRUD operations.
- Prefer
mooncommand over vanillagocommand when available. - Run
moon run :lintafter every time you finish changing code, and fix all linter errors. - Run
go mod tidyafter every time you changego.mod, do not manually editgo.sumfile.
- Use
ghCLI to access information on github.com that is not publicly available. For public information, directly fetch the webpage and extract content to save GitHub API usage.
- For multi-issue reviews (code review, security review, refactor lists), always present the findings as a numbered list first and walk through them with the user one by one. The user decides fix or skip per item before any edit.
- For non-trivial changes that touch multiple files, propose the approach (in a plan or in chat) and wait for approval before editing. Do not start edits while the user is still discussing the approach.
- Do not batch-fix multiple items just because the next one seems obvious. Triage strictly item by item.
- Never commit on the
mainbranch directly unless being explicitly asked to do so. A single ask only grants a single commit action on themainbranch. - Never amend commits unless being explicitly asked to do so.