Custom rules
Learn how to define custom rules
Custom rules allow you to enforce your organization’s specific best practices across all pull requests, ensuring consistency and compliance with your team’s established standards.
Defining a custom rule
To define a rule, navigate to the AI review page in cubic and click “Add rule”.
Each custom rule includes:
-
A Name
A concise title, like “Prevent N+1 Queries” or “Require Sentry Error Handling.” -
A Description
A clear, natural-language instruction the AI will use, such as “Flag code that may cause multiple database calls inside loops.”Be as clear and explicit as possible; the more specific you are, the better the results.
-
Optional Path Filters
Use Glob patterns to limit where the rule applies (or exclude certain paths). This is especially helpful for monorepos, where different directories often require different rules. For example:- Include:
backend/**
to apply the rule only to files under abackend
folder. - Exclude:
!tests/**
to ignore test files and focus on production code.
- Include:
Custom rules are defined at the repository level, and will be applied to all pull requests in the repository. This means that you can enforce different custom rules for each repository.
Common custom rule patterns
Custom rules help catch deviations that human reviewers might miss, ensuring consistent application of your team’s standards. When a violation of a rule is detected in a pull request, the AI will comment directly on the affected lines.
Code quality and performance
Code quality and performance
- Enforce rollback steps in database migrations: Each database migration file must include a “down” or “rollback” section that reverses the changes. This ensures all database changes can be safely undone if deployment issues occur. Migration files should clearly separate “up” and “down” migrations using appropriate method names or comments.
- Require alt text for all images: All
<img>
elements must include meaningful alt text that describes the image content or function. Decorative images should usealt=""
explicitly. This improves accessibility for screen readers and SEO. The alt text should be descriptive and concise, avoiding phrases like “image of” or “picture of.” - No direct
process.env
access: Direct access toprocess.env
is prohibited. Use the centralized Env utility from@/lib/env.ts
instead. This ensures type safety, runtime validation, and consistent access patterns for environment variables. The utility also provides proper error handling for missing or invalid environment variables. - Ensure i18n calls wrap all user-facing strings: All user-visible text must be wrapped in translation function calls (
t()
,useTranslation
, etc.). This includes button labels, headings, error messages, and placeholder text. Raw string literals in JSX or template strings should be replaced with translation keys. Exception: Technical identifiers and logging messages. - Ensure color palette consistency: All color values must use design system tokens from the theme configuration. Raw hex codes, RGB values, or named colors are not allowed. Use semantic color variables (e.g., primary, secondary, accent) or role-based tokens (e.g., background, text, border) from
@/styles/theme.ts
. This ensures consistent branding and supports dark mode. - Restrict inline styles: Inline style attributes are prohibited in favor of Tailwind classes or styled-components. This improves maintainability and ensures consistent styling patterns. Exception: Dynamic styles that cannot be handled by CSS variables or class names. Use
className
prop for styling and avoid thestyle
prop except for truly dynamic values. - Check missing or invalid Jest/Testing Library tests: New or modified components and utilities must include corresponding test files. Tests should use React Testing Library patterns, avoid implementation details, and include both happy and error paths. Each exported function or component needs at least basic render and interaction tests.
- Require proper logging: Production code must use the application logging utility instead of
console.*
methods. Errors must be properly caught and logged with appropriate severity levels and context. Error boundaries should log uncaught errors. Sensitive information must be redacted from logs using the sanitize utility. - Enforce accessible headings: Heading elements (h1-h6) must follow a logical hierarchy without skipping levels. Each page should have exactly one h1 element, with subsequent headings properly nested. This improves screen reader navigation and document structure. Heading text should be descriptive and meaningful.
- Detect duplicate or outdated feature flag usage: Feature flags must be centrally defined and consistently referenced. Flags marked as deprecated must not be used in new code. Multiple branches checking the same feature flag should be consolidated. Remove feature flag logic once features are fully launched or deprecated.
- Enforce ARIA attributes on interactive elements: Interactive elements must include appropriate ARIA attributes for accessibility. Buttons need
aria-label
oraria-labelledby
when text content is not descriptive. Custom controls require proper role and state attributes. Dialog components must manage focus and include proper modal attributes. - Ensure valid image format and responsive sizing: Images must use modern formats (WebP with fallbacks) and implement responsive sizing. The
next/image
component is required with properwidth
/height
props to prevent layout shift. Large images should use automatic optimization and lazy loading. Provide multiple sizes for responsive images usingsrcSet
. - Check for required tracking/analytics hooks: User interactions and key application events must include appropriate analytics tracking. Use the centralized analytics hooks for consistency. Track page views, feature usage, error states, and conversion events. Ensure proper data sanitization and respect user privacy settings.
Security and compliance
Security and compliance
- Flag security vulnerabilities: Scan for security flaws: hardcoded secrets, SQL injection,
XSS, weak auth, exposed data, poor crypto, unsafe deserialization, and more. Identify attack
vectors and security violations to maintain robust defenses. - Block insecure HTTP calls from
secure context: All network requests must use HTTPS (TLS) in production environments. This
includes API calls, asset loading, and third-party integrations. The rule checks for
http://
URLs in fetch calls, src attributes, and configuration files. Development localhost URLs are exempted from this check. - Validate 2FA for protected routes: Routes marked as requiring two-factor authentication must implement proper 2FA middleware checks. This includes verifying both primary authentication and valid 2FA status before allowing access. Protected routes should redirect unauthenticated or 2FA-pending users to appropriate setup flows. - No plain text passwords in logs: Logging statements must not contain password fields, authentication tokens, or other credentials. Use the sanitize utility to redact sensitive data before logging. This applies to error messages, debug logs, and analytics events. Check both direct logging calls and error serialization.
Architecture and design patterns
Architecture and design patterns
- Check system design and architectural patterns: Review code for architectural anti-patterns, SOLID principle violations, improper layering, circular dependencies, and missing abstractions. Ensure proper separation of concerns, appropriate design patterns usage, and maintainable module boundaries. Flag tightly coupled components, God objects, and violations of established architectural conventions. - Enforce command query separation in API handlers: API handlers must either perform reads (queries) or writes (commands), but not both. This improves code maintainability and makes side effects more predictable. GET handlers should only read data, while POST/PUT/DELETE handlers should focus on data modification. Each handler should have a single, clear responsibility.
Language-specific best practices
Language-specific best practices
JavaScript/TypeScript
- Use
const
/let
instead ofvar
for variable declarations. - Prefer
async
/await
over Promise chains for readability. - Use strict equality (
===
) instead of loose equality (==
). - Always define return types for functions.
- Use meaningful variable and function names.
- Avoid
any
type; use specific types instead. - Handle promise rejections explicitly.
Python
- Follow PEP 8 style guidelines for naming conventions.
- Use list comprehensions instead of loops where appropriate.
- Include type hints for all function parameters and return values.
- Use context managers for resource management.
- Prefer f-strings over string concatenation.
- Handle exceptions with specific exception types.
- Use dataclasses for simple data containers.
Go
- Follow idiomatic Go patterns and conventions.
- Handle errors explicitly; do not ignore them.
- Use meaningful variable names; avoid single-letter variables.
- Use interfaces for abstraction.
- Prefer composition over embedding.
- Use context for cancellation and timeouts.
- Initialize struct fields explicitly.
Java
- Use
Optional
instead of returningnull
for optional values. - Prefer composition over inheritance for code reuse.
- Close resources properly using try-with-resources.
- Use
StringBuilder
for string concatenation in loops. - Make fields private and use getters/setters.
- Use
final
keyword for immutable variables. - Handle checked exceptions appropriately.
Importing rules from Cursor
If your team uses Cursor rules, you can easily import these into cubic by clicking the Sync Cursor Rules button on the AI review page.
cubic will analyze your Cursor rule files, suggest suitable custom rules, and let you select which ones you’d like to enable.
Limitations
- Rule limit: Each repository can have a maximum of 5 custom rules. Consider combining related checks into single rules to stay within this limit.
- Single check per PR: cubic currently performs rule checks only once when the pull request is first opened. Subsequent commits won’t trigger additional checks yet.
- Potential false positives: Occasionally, the AI might incorrectly flag or overlook certain scenarios. Consider AI feedback as helpful guidance rather than definitive judgments.
Tips for effective custom rules
-
Combine related checks: There’s a limit of 5 rules per repository, but you can combine multiple related checks into a single rule if it makes sense. Grouping semantically similar things together usually works well and helps you stay within the limit.
-
Leverage path filters in monorepos: When working with monorepos, use Glob patterns to target specific files or folders. The “glob wizard” and “glob testing” tools in the advanced section are super handy for making sure your patterns do exactly what you expect.
-
Use the auto-suggestion feature: When creating a rule in the UI, look for the little wand icon that can help auto-word your rule if you’re stuck. This can provide a good starting point that you can then refine.
-
Complement existing tools: Custom rules should focus on checks that standard tools like ESLint or Prettier might miss, such as business logic validations or team-specific conventions.
Next steps
Overview: Understand how cubic reviews pull requests by default.