Skip to main content

Project-Specific Rules

Make diffray even smarter by teaching it your team's standards.

Your Rules, Your Way

diffray comes with comprehensive default rules, but every team is different:

  • Your coding standards — enforce conventions specific to your team
  • Your libraries — ensure correct usage of internal APIs
  • Your domain — add checks that make sense for your business

How It Works

  1. Add a .diffray/rules/ folder to your repository
  2. Create YAML files with your custom rules
  3. diffray automatically picks them up on the next PR
your-repo/
└── .diffray/
└── rules/
└── team-standards.yaml

Example: Enforce Your Logger

rules:
- id: use_internal_logger
agent: quality
title: "Use internal logger"
description: "Use our logger instead of console for proper log levels"
importance: 7

match:
file_glob:
- "src/**/*.ts"
- "!src/**/*.test.ts"

checklist:
- "Find console.log/error/warn calls"
- "Suggest using logger from @/lib/logger"

examples:
bad: |
console.log('User logged in', userId);
good: |
logger.info('User logged in', { userId });

Example: Rule for Specific Path

Apply rules only to certain folders — like checking API endpoints only in your API directory:

rules:
- id: api_error_handling
agent: bugs
title: "API endpoints must handle errors"
description: "All API routes should have try-catch with proper error responses"
importance: 8

match:
file_glob:
- "src/api/**/*.ts" # Only API folder
- "src/routes/**/*.ts" # Or routes folder
- "!src/api/**/*.test.ts" # Exclude tests

checklist:
- "Check that async handlers have try-catch"
- "Verify error responses use standard format"

examples:
bad: |
app.get('/users', async (req, res) => {
const users = await db.getUsers();
res.json(users);
});
good: |
app.get('/users', async (req, res) => {
try {
const users = await db.getUsers();
res.json(users);
} catch (error) {
res.status(500).json({ error: 'Failed to fetch users' });
}
});

What You Can Customize

WhatHow
Add new rulesCreate rules for your specific patterns
Adjust severityMake certain checks more or less strict
Target specific foldersApply rules only where they matter
Disable default rulesUse config.yaml to exclude rules

Using Tags

Tags help categorize rules and can be used for filtering. Add one or more tags to your rules:

rules:
- id: use_internal_logger
agent: quality
title: "Use internal logger"
# ...
tags:
- logging
- typescript
- maintainability

Available Tags

CategoryTags
Coresecurity, performance, bugs, error-handling, maintainability, readability, quality, consistency
Code qualitystyle-conventions, type-safety, duplication, dead-code, code-quality, debugging, memory, memory-leak
Architecturearchitecture, api-design, api, api-contracts-versioning, separation-of-concerns, testability
Testing & docstesting, testing-quality, documentation, docstring, docs-adrs, e2e, mocha, chai, sinon
Observabilitylogging, observability, traceability
Compliancecompliance-gdpr, compliance-soc2-essentials, compliance-pci-dss, compliance-hipaa, compliance-lgpd, privacy-pii, secrets, secrets-credentials
Languagestypescript, javascript, python, go, java, kotlin, csharp, rust, ruby, php, dart, swift, scala, cpp, c, shell, graphql, protobuf, solidity, css
Frameworksreact, nextjs, vue, angular, svelte, nestjs, nodejs, django, fastapi, flask, spring, rails, aspnet, dotnet, wordpress
Stacksstack-nextjs, stack-nodejs, stack-php, stack-python, stack-react, stack-vue
Infrastructuredocker, kubernetes, ci-cd-build-hygiene, infra-as-code, infrastructure, monorepo-hygiene, container-docker-hygiene
Frontendfrontend, dom, a11y, accessibility, accessibility-a11y, i18n, internationalization-i18n, state-management, design-system, ui-robustness, ux, bundle-size, web-static-assets
Async & Concurrencyasync, concurrency, race-condition, resilience, resilience-retries-idempotency, idempotency
Data & APIscaching-strategy, migrations-backward-compat, dependency-supply-chain, financial, payments, inventory
Git & Deploymentgit, deployment, risk-management, build-tools
Miscellaneousowasp, prototype-pollution, organization, server-actions, server-components, vite

Assigning Rules to Agents

Each rule is processed by a specialized agent. Choose the one that fits:

  • security — vulnerabilities, auth, data exposure
  • performance — bottlenecks, efficiency
  • bugs — logic errors, runtime issues
  • quality — readability, best practices
  • architecture — design patterns, structure
  • consistency — code reuse, conventions
  • documentation — docs and comments
  • testing — test quality and coverage
  • general — cross-cutting concerns

Example: Feature Flags

If your team uses a specific feature flag library, create a rule to enforce proper usage patterns:

rules:
- id: feature_flag_gradual_rollout
agent: quality
title: "Feature flags should support gradual rollout"
description: "Risky changes should use percentage-based rollout via feature flags"
importance: 7

match:
file_glob:
- "src/**/*.ts"
- "src/**/*.js"
- "!src/**/*.test.ts"
content_regex:
- "featureFlags\\."
- "isFeatureEnabled"

checklist:
- "Check if feature flag supports percentage-based activation"
- "Verify user/company ID is passed for consistent rollout"
- "Ensure new risky features are behind feature flags"

examples:
bad: |
// No gradual rollout support
if (featureFlags.isEnabled('new_checkout')) {
useNewCheckout();
}

// Boolean only - can't do percentage rollout
const useNew = config.newCheckoutEnabled;
good: |
// Percentage-based rollout with user context
if (featureFlags.isEnabled('new_checkout', {
userId: user.id, // Consistent per-user experience
percent: 10, // Enable for 10% of users
allowlist: ['beta-testers'] // Always enable for beta group
})) {
useNewCheckout();
}

tags:
- quality
- architecture
- deployment
why_important: Gradual rollout reduces blast radius and enables quick rollback.

Example: Domain-Specific Validation

Enforce business rules specific to your domain:

rules:
- id: money_use_decimal
agent: bugs
title: "Use Decimal for monetary values"
description: "Never use float/number for money - use Decimal or BigInt cents"
importance: 9

match:
file_glob:
- "src/**/*.ts"
- "src/**/*.py"
content_regex:
- "(price|amount|total|cost|fee|balance)\\s*[=:]\\s*\\d+\\.\\d+"
- "(price|amount|total|cost|fee|balance)\\s*:\\s*(number|float)"

checklist:
- "Find monetary fields using float/number types"
- "Check calculations don't use floating point arithmetic"
- "Verify storage uses cents (integer) or Decimal type"

examples:
bad: |
// TypeScript - float precision issues
interface Order {
price: number; // 0.1 + 0.2 !== 0.3 in JS!
total: number;
}
const total = price * quantity; // Floating point errors

# Python - same problem
price: float = 19.99
total = price * quantity # Precision loss
good: |
// TypeScript - use cents (integer)
interface Order {
priceInCents: number; // Store as integer cents
totalInCents: number;
}
const totalCents = priceInCents * quantity;
const displayPrice = (totalCents / 100).toFixed(2);

// Or use a Decimal library
import Decimal from 'decimal.js';
const price = new Decimal('19.99');
const total = price.times(quantity);

# Python - use Decimal
from decimal import Decimal
price = Decimal('19.99')
total = price * quantity

tags:
- bugs
- fintech
- data-integrity
why_important: Floating point errors in money calculations cause real financial discrepancies.

Example: Internal API Usage

Ensure your internal libraries are used correctly:

rules:
- id: http_client_use_internal
agent: consistency
title: "Use internal HTTP client wrapper"
description: "Use our httpClient instead of raw fetch/axios for consistent error handling"
importance: 7

match:
file_glob:
- "src/**/*.ts"
- "!src/lib/http-client.ts" # Exclude the wrapper itself
- "!src/**/*.test.ts"
content_regex:
- "\\bfetch\\("
- "axios\\."
- "import.*from ['\"]axios['\"]"

checklist:
- "Find raw fetch() or axios calls"
- "Check if code should use httpClient from @/lib/http-client"
- "Verify error handling follows team standards"

examples:
bad: |
// Raw fetch - no centralized error handling
const response = await fetch('/api/users');
const data = await response.json();

// Direct axios - bypasses our interceptors
import axios from 'axios';
const { data } = await axios.get('/api/users');
good: |
// Use internal wrapper with built-in:
// - Auth token injection
// - Error normalization
// - Retry logic
// - Request logging
import { httpClient } from '@/lib/http-client';

const data = await httpClient.get('/api/users');

tags:
- consistency
- error-handling
- internal-api
why_important: Centralized HTTP client ensures consistent auth, logging, and error handling.

Tips for Great Rules

  1. Start simple — one or two rules, see how they work
  2. Be specific — target only relevant files
  3. Add examples — show what's wrong and how to fix it
  4. Test it — create a PR that should trigger your rule

See also:

  • Configuration — global settings, file filters, rule exclusions

Need help writing rules? Contact support and we'll help you set up rules for your team's needs.